summaryrefslogtreecommitdiffstats
path: root/arch/alpha
diff options
context:
space:
mode:
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/Makefile59
-rw-r--r--arch/alpha/config.in99
-rw-r--r--arch/alpha/defconfig110
-rw-r--r--arch/alpha/kernel/Makefile89
-rw-r--r--arch/alpha/kernel/alpha_ksyms.c12
-rw-r--r--arch/alpha/kernel/bios32.c2191
-rw-r--r--arch/alpha/kernel/bios32.h155
-rw-r--r--arch/alpha/kernel/core_apecs.c (renamed from arch/alpha/kernel/apecs.c)400
-rw-r--r--arch/alpha/kernel/core_cia.c (renamed from arch/alpha/kernel/cia.c)492
-rw-r--r--arch/alpha/kernel/core_lca.c (renamed from arch/alpha/kernel/lca.c)270
-rw-r--r--arch/alpha/kernel/core_mcpcia.c970
-rw-r--r--arch/alpha/kernel/core_pyxis.c634
-rw-r--r--arch/alpha/kernel/core_t2.c (renamed from arch/alpha/kernel/t2.c)376
-rw-r--r--arch/alpha/kernel/core_tsunami.c446
-rw-r--r--arch/alpha/kernel/entry.S35
-rw-r--r--arch/alpha/kernel/es1888.c47
-rw-r--r--arch/alpha/kernel/fpreg.c92
-rw-r--r--arch/alpha/kernel/head.S12
-rw-r--r--arch/alpha/kernel/irq.c1651
-rw-r--r--arch/alpha/kernel/irq.h27
-rw-r--r--arch/alpha/kernel/machvec.h137
-rw-r--r--arch/alpha/kernel/mcpcia.c977
-rw-r--r--arch/alpha/kernel/osf_sys.c204
-rw-r--r--arch/alpha/kernel/process.c188
-rw-r--r--arch/alpha/kernel/proto.h131
-rw-r--r--arch/alpha/kernel/ptrace.c264
-rw-r--r--arch/alpha/kernel/pyxis.c663
-rw-r--r--arch/alpha/kernel/setup.c763
-rw-r--r--arch/alpha/kernel/signal.c288
-rw-r--r--arch/alpha/kernel/smc37c669.c3
-rw-r--r--arch/alpha/kernel/smp.c38
-rw-r--r--arch/alpha/kernel/sys_alcor.c263
-rw-r--r--arch/alpha/kernel/sys_cabriolet.c395
-rw-r--r--arch/alpha/kernel/sys_dp264.c231
-rw-r--r--arch/alpha/kernel/sys_eb64p.c206
-rw-r--r--arch/alpha/kernel/sys_jensen.c146
-rw-r--r--arch/alpha/kernel/sys_miata.c307
-rw-r--r--arch/alpha/kernel/sys_mikasa.c297
-rw-r--r--arch/alpha/kernel/sys_noritake.c301
-rw-r--r--arch/alpha/kernel/sys_rawhide.c195
-rw-r--r--arch/alpha/kernel/sys_ruffian.c267
-rw-r--r--arch/alpha/kernel/sys_sable.c297
-rw-r--r--arch/alpha/kernel/sys_sio.c470
-rw-r--r--arch/alpha/kernel/sys_sx164.c217
-rw-r--r--arch/alpha/kernel/sys_takara.c165
-rw-r--r--arch/alpha/kernel/time.c2
-rw-r--r--arch/alpha/kernel/traps.c79
-rw-r--r--arch/alpha/kernel/tsunami.c503
-rw-r--r--arch/alpha/lib/Makefile2
-rw-r--r--arch/alpha/lib/io.c170
-rw-r--r--arch/alpha/lib/memset.S25
-rw-r--r--arch/alpha/lib/strcasecmp.c26
-rw-r--r--arch/alpha/lib/strlen_user.S2
-rw-r--r--arch/alpha/math-emu/fp-emul.c31
-rw-r--r--arch/alpha/mm/fault.c61
-rw-r--r--arch/alpha/mm/init.c160
56 files changed, 9550 insertions, 7091 deletions
diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile
index ff6e422df..d497ec3c8 100644
--- a/arch/alpha/Makefile
+++ b/arch/alpha/Makefile
@@ -10,36 +10,41 @@
NM := nm -B
-#LINKFLAGS = -static -T arch/alpha/vmlinux.lds
-#CFLAGS := $(CFLAGS) -pipe -mno-fp-regs -ffixed-8
+LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N
+CFLAGS := $(CFLAGS) -pipe -mno-fp-regs -ffixed-8
-ifdef CONFIG_CROSSCOMPILE
-# enable this for linking under OSF/1:
-LINKFLAGS = -non_shared -T 0xfffffc0000310000 -N
-else
- elf=$(shell if $(LD) --help | grep elf64alpha >/dev/null; then echo yes; fi)
- ifeq ($(elf),yes)
-# LINKFLAGS = -static -Ttext 0xfffffc0000310000 -N
-LINKFLAGS = -static -T arch/alpha/vmlinux.lds
- else
- LINKFLAGS = -static -T arch/alpha/vmlinux.lds -N
- endif
-# GNU gcc/cc1/as can use pipes instead of temporary files
-CFLAGS := $(CFLAGS) -pipe
-endif
+# Determine if we can use the BWX instructions with GAS.
+old_gas := $(shell if $(AS) --version 2>&1 | grep 'version 2.7' > /dev/null; then echo y; else echo n; fi)
-CFLAGS := $(CFLAGS) -mno-fp-regs -ffixed-8 -Wno-uninitialized
+# Determine if GCC understands the -mcpu= option.
+have_mcpu := $(shell if $(CC) -mcpu=ev5 -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo y; else echo n; fi)
+
+# If GENERIC, make sure to turn off any instruction set extensions that
+# the host compiler might have on by default. Given that EV4 and EV5
+# have the same instruction set, prefer EV5 because an EV5 schedule is
+# more likely to keep an EV4 processor busy than vice-versa.
+ifeq ($(CONFIG_ALPHA_GENERIC)$(have_mcpu),yy)
+ CFLAGS := $(CFLAGS) -mcpu=ev5
+endif
-# determine if we can use the BWX instructions with GAS
-$(shell rm -f ./GAS_VER)
-$(shell $(AS) --version >& ./GAS_VER)
-OLD_GAS := $(shell if cat ./GAS_VER | grep 'version 2.7' > /dev/null; then echo yes; else echo no; fi)
-$(shell rm -f ./GAS_VER)
+# If EV6, turn on the proper optimizations.
+ifeq ($(CONFIG_ALPHA_EV6)$(have_mcpu),yy)
+ CFLAGS := $(CFLAGS) -mcpu=ev6
+endif
-ifneq ($(OLD_GAS),yes)
-# if PYXIS, then enable use of BWIO space
+# For TSUNAMI, we must have the assembler not emulate our instructions.
+# BWX is most important, but we don't really want any emulation ever.
+ifeq ($(old_gas),y)
+ ifneq ($(CONFIG_ALPHA_GENERIC)$(CONFIG_ALPHA_TSUNAMI),)
+ # How do we do #error in make?
+ CFLAGS := --error-please-upgrade-your-assembler
+ endif
+else
+ ifeq ($(CONFIG_ALPHA_GENERIC),y)
+ CFLAGS := $(CFLAGS) -Wa,-mev6
+ endif
ifeq ($(CONFIG_ALPHA_PYXIS),y)
- CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED
+ CFLAGS := $(CFLAGS) -Wa,-m21164a -DBWIO_ENABLED
endif
endif
@@ -61,7 +66,7 @@ rawboot:
@$(MAKEBOOT) rawboot
#
-# my boot writes directly to a specific disk partition, I doubt most
+# My boot writes directly to a specific disk partition, I doubt most
# people will want to do that without changes..
#
msb my-special-boot:
@@ -76,6 +81,8 @@ srmboot:
archclean:
@$(MAKEBOOT) clean
+archmrproper:
+
archdep:
@$(MAKEBOOT) dep
diff --git a/arch/alpha/config.in b/arch/alpha/config.in
index fc2546218..9d0f5769e 100644
--- a/arch/alpha/config.in
+++ b/arch/alpha/config.in
@@ -4,15 +4,6 @@
#
mainmenu_name "Kernel configuration of Linux for Alpha machines"
-# clear all implied options (don't want default values for those):
-unset CONFIG_CROSSCOMPILE CONFIG_NATIVE
-unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6
-unset CONFIG_PCI CONFIG_ALPHA_EISA
-unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA
-unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS
-unset CONFIG_ALPHA_TSUNAMI CONFIG_ALPHA_MCPCIA
-unset CONFIG_ALPHA_NEED_ROUNDING_EMULATION
-
mainmenu_option next_comment
comment 'Code maturity level options'
bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
@@ -31,6 +22,8 @@ endmenu
mainmenu_option next_comment
comment 'General setup'
+unset CONFIG_CROSSCOMPILE CONFIG_NATIVE
+
if [ "`uname`" != "Linux" ]; then
define_bool CONFIG_CROSSCOMPILE y
else
@@ -38,31 +31,44 @@ else
fi
choice 'Alpha system type' \
- "Avanti CONFIG_ALPHA_AVANTI \
- Alpha-XL CONFIG_ALPHA_XL \
- Alpha-XLT CONFIG_ALPHA_XLT \
- Cabriolet CONFIG_ALPHA_CABRIOLET \
- EB66 CONFIG_ALPHA_EB66 \
- EB66+ CONFIG_ALPHA_EB66P \
- EB64+ CONFIG_ALPHA_EB64P \
- EB164 CONFIG_ALPHA_EB164 \
- PC164 CONFIG_ALPHA_PC164 \
- LX164 CONFIG_ALPHA_LX164 \
- SX164 CONFIG_ALPHA_SX164 \
- DP264 CONFIG_ALPHA_DP264 \
- Jensen CONFIG_ALPHA_JENSEN \
- Noname CONFIG_ALPHA_NONAME \
- Takara CONFIG_ALPHA_TAKARA \
- Mikasa CONFIG_ALPHA_MIKASA \
- Noritake CONFIG_ALPHA_NORITAKE \
- Alcor CONFIG_ALPHA_ALCOR \
- Miata CONFIG_ALPHA_MIATA \
- Sable CONFIG_ALPHA_SABLE \
- Rawhide CONFIG_ALPHA_RAWHIDE \
- AlphaBook1 CONFIG_ALPHA_BOOK1 \
- Ruffian CONFIG_ALPHA_RUFFIAN \
- Platform2000 CONFIG_ALPHA_P2K" Cabriolet
+ "Generic CONFIG_ALPHA_GENERIC \
+ Alcor/Alpha-XLT CONFIG_ALPHA_ALCOR \
+ Alpha-XL CONFIG_ALPHA_XL \
+ AlphaBook1 CONFIG_ALPHA_BOOK1 \
+ Avanti CONFIG_ALPHA_AVANTI \
+ Cabriolet CONFIG_ALPHA_CABRIOLET \
+ DP264 CONFIG_ALPHA_DP264 \
+ EB164 CONFIG_ALPHA_EB164 \
+ EB64+ CONFIG_ALPHA_EB64P \
+ EB66 CONFIG_ALPHA_EB66 \
+ EB66+ CONFIG_ALPHA_EB66P \
+ Jensen CONFIG_ALPHA_JENSEN \
+ LX164 CONFIG_ALPHA_LX164 \
+ Miata CONFIG_ALPHA_MIATA \
+ Mikasa CONFIG_ALPHA_MIKASA \
+ Noname CONFIG_ALPHA_NONAME \
+ Noritake CONFIG_ALPHA_NORITAKE \
+ PC164 CONFIG_ALPHA_PC164 \
+ Platform2000 CONFIG_ALPHA_P2K \
+ Rawhide CONFIG_ALPHA_RAWHIDE \
+ Ruffian CONFIG_ALPHA_RUFFIAN \
+ SX164 CONFIG_ALPHA_SX164 \
+ Sable CONFIG_ALPHA_SABLE \
+ Takara CONFIG_ALPHA_TAKARA" Generic
+# clear all implied options (don't want default values for those):
+unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6
+unset CONFIG_PCI CONFIG_ALPHA_EISA
+unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA
+unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS
+unset CONFIG_ALPHA_TSUNAMI CONFIG_ALPHA_MCPCIA
+unset CONFIG_ALPHA_NEED_ROUNDING_EMULATION
+
+if [ "$CONFIG_ALPHA_GENERIC" = "y" ]
+then
+ define_bool CONFIG_PCI y
+ define_bool CONFIG_ALPHA_NEED_ROUNDING_EMULATION y
+fi
if [ "$CONFIG_ALPHA_BOOK1" = "y" ]
then
define_bool CONFIG_ALPHA_NONAME y
@@ -172,10 +178,6 @@ fi
#bool 'Echo console messages on /dev/ttyS0 (COM1)' CONFIG_SERIAL_ECHO
if [ "$CONFIG_PCI" = "y" ]; then
- bool 'TGA Console Support' CONFIG_TGA_CONSOLE
-# if [ "$CONFIG_TGA_CONSOLE" = "y" ]; then
-# bool 'VGA Console Support' CONFIG_VGA_CONSOLE
-# fi
bool 'PCI quirks' CONFIG_PCI_QUIRKS
if [ "$CONFIG_PCI_QUIRKS" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
bool 'PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
@@ -184,6 +186,7 @@ if [ "$CONFIG_PCI" = "y" ]; then
fi
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 a.out (ECOFF) binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
@@ -250,11 +253,23 @@ if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
fi
endmenu
+source drivers/char/Config.in
+
source fs/Config.in
source fs/nls/Config.in
-source drivers/char/Config.in
+if [ "$CONFIG_VT" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'Console drivers'
+ bool 'VGA text console' CONFIG_VGA_CONSOLE
+ bool 'Support for frame buffer devices' CONFIG_FB
+ if [ "$CONFIG_FB" = "y" ]; then
+ define_bool CONFIG_PCI_CONSOLE y
+ fi
+ source drivers/video/Config.in
+ endmenu
+fi
mainmenu_option next_comment
comment 'Sound'
@@ -269,10 +284,6 @@ mainmenu_option next_comment
comment 'Kernel hacking'
#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
-bool 'Kernel profiling support' CONFIG_PROFILE
-if [ "$CONFIG_PROFILE" = "y" ]; then
- int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
-fi
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'Kernel FP software completion' CONFIG_MATHEMU
else
@@ -281,7 +292,3 @@ fi
bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
endmenu
-
-if [ "$CONFIG_TGA_CONSOLE" = "n" ]; then
- define_bool CONFIG_VGA_CONSOLE y
-fi
diff --git a/arch/alpha/defconfig b/arch/alpha/defconfig
index 7d78e4b97..64a051c16 100644
--- a/arch/alpha/defconfig
+++ b/arch/alpha/defconfig
@@ -18,39 +18,37 @@ CONFIG_MODULES=y
# General setup
#
CONFIG_NATIVE=y
-# CONFIG_ALPHA_AVANTI is not set
+CONFIG_ALPHA_GENERIC=y
+# CONFIG_ALPHA_ALCOR is not set
# CONFIG_ALPHA_XL is not set
-# CONFIG_ALPHA_XLT is not set
+# CONFIG_ALPHA_BOOK1 is not set
+# CONFIG_ALPHA_AVANTI is not set
# CONFIG_ALPHA_CABRIOLET is not set
+# CONFIG_ALPHA_DP264 is not set
+# CONFIG_ALPHA_EB164 is not set
+# CONFIG_ALPHA_EB64P is not set
# CONFIG_ALPHA_EB66 is not set
# CONFIG_ALPHA_EB66P is not set
-# CONFIG_ALPHA_EB64P is not set
-# CONFIG_ALPHA_EB164 is not set
-# CONFIG_ALPHA_PC164 is not set
-# CONFIG_ALPHA_LX164 is not set
-# CONFIG_ALPHA_SX164 is not set
-# CONFIG_ALPHA_DP264 is not set
# CONFIG_ALPHA_JENSEN is not set
-# CONFIG_ALPHA_NONAME is not set
-# CONFIG_ALPHA_TAKARA is not set
+# CONFIG_ALPHA_LX164 is not set
+# CONFIG_ALPHA_MIATA is not set
# CONFIG_ALPHA_MIKASA is not set
+# CONFIG_ALPHA_NONAME is not set
# CONFIG_ALPHA_NORITAKE is not set
-CONFIG_ALPHA_ALCOR=y
-# CONFIG_ALPHA_MIATA is not set
-# CONFIG_ALPHA_SABLE is not set
+# CONFIG_ALPHA_PC164 is not set
+# CONFIG_ALPHA_P2K is not set
# CONFIG_ALPHA_RAWHIDE is not set
-# CONFIG_ALPHA_BOOK1 is not set
# CONFIG_ALPHA_RUFFIAN is not set
-# CONFIG_ALPHA_P2K is not set
+# CONFIG_ALPHA_SX164 is not set
+# CONFIG_ALPHA_SABLE is not set
+# CONFIG_ALPHA_TAKARA is not set
CONFIG_PCI=y
-CONFIG_ALPHA_EV5=y
-CONFIG_ALPHA_CIA=y
-CONFIG_ALPHA_SRM=y
-CONFIG_ALPHA_EISA=y
-CONFIG_TGA_CONSOLE=y
+CONFIG_ALPHA_NEED_ROUNDING_EMULATION=y
+# CONFIG_PCI_QUIRKS is not set
CONFIG_PCI_OLD_PROC=y
CONFIG_NET=y
CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
CONFIG_SYSCTL=y
CONFIG_BINFMT_AOUT=y
CONFIG_BINFMT_ELF=y
@@ -64,7 +62,7 @@ CONFIG_BINFMT_EM86=y
# CONFIG_PNP is not set
#
-# Floppy, IDE, and other block devices
+# Block devices
#
CONFIG_BLK_DEV_FD=y
# CONFIG_BLK_DEV_IDE is not set
@@ -78,6 +76,7 @@ CONFIG_BLK_DEV_FD=y
# Additional Block Devices
#
# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_MD is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_BLK_DEV_XD is not set
@@ -98,8 +97,6 @@ CONFIG_INET=y
# CONFIG_IP_MULTICAST is not set
# CONFIG_IP_ADVANCED_ROUTER is not set
# CONFIG_IP_PNP is not set
-# CONFIG_IP_ACCT is not set
-# CONFIG_IP_MASQUERADE is not set
# CONFIG_IP_ROUTER is not set
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
@@ -195,6 +192,8 @@ CONFIG_DE4X5=y
# CONFIG_DEC_ELCP is not set
# CONFIG_DGRS is not set
# CONFIG_EEXPRESS_PRO100 is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_TLAN is not set
# CONFIG_NET_POCKET is not set
# CONFIG_FDDI is not set
# CONFIG_DLCI is not set
@@ -222,6 +221,38 @@ CONFIG_DE4X5=y
# CONFIG_CD_NO_IDESCSI is not set
#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_MOUSE=y
+# CONFIG_ATIXL_BUSMOUSE is not set
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MS_BUSMOUSE is not set
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+# CONFIG_UMISC is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_APM is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_NVRAM is not set
+# CONFIG_JOYSTICK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+
+#
# Filesystems
#
# CONFIG_QUOTA is not set
@@ -248,39 +279,15 @@ CONFIG_LOCKD=y
# CONFIG_ROMFS_FS is not set
# CONFIG_AUTOFS_FS is not set
# CONFIG_UFS_FS is not set
+CONFIG_DEVPTS_FS=y
# CONFIG_MAC_PARTITION is not set
# CONFIG_NLS is not set
#
-# Character devices
+# Console drivers
#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_SERIAL=y
-# CONFIG_SERIAL_CONSOLE is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-CONFIG_MOUSE=y
-# CONFIG_ATIXL_BUSMOUSE is not set
-# CONFIG_BUSMOUSE is not set
-# CONFIG_MS_BUSMOUSE is not set
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-# CONFIG_UMISC is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_APM is not set
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_NVRAM is not set
-# CONFIG_JOYSTICK is not set
-# CONFIG_MISC_RADIO is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
+CONFIG_VGA_CONSOLE=y
+# CONFIG_FB is not set
#
# Sound
@@ -290,6 +297,5 @@ CONFIG_PSMOUSE=y
#
# Kernel hacking
#
-# CONFIG_PROFILE is not set
CONFIG_MATHEMU=y
# CONFIG_MAGIC_SYSRQ is not set
diff --git a/arch/alpha/kernel/Makefile b/arch/alpha/kernel/Makefile
index 8d09ea8c4..fcbb37615 100644
--- a/arch/alpha/kernel/Makefile
+++ b/arch/alpha/kernel/Makefile
@@ -20,34 +20,96 @@ O_OBJS := entry.o traps.o process.o osf_sys.o irq.o signal.o setup.o \
OX_OBJS := alpha_ksyms.o
+ifdef CONFIG_ALPHA_GENERIC
+
+O_OBJS += core_apecs.o core_cia.o core_lca.o core_mcpcia.o core_pyxis.o \
+ core_t2.o core_tsunami.o \
+ sys_alcor.o sys_cabriolet.o sys_dp264.o sys_eb64p.o \
+ sys_jensen.o sys_miata.o sys_mikasa.o sys_noritake.o \
+ sys_rawhide.o sys_ruffian.o sys_sable.o sys_sio.o \
+ sys_sx164.o sys_takara.o \
+ es1888.o smc37c669.o smc37c93x.o
+else
+
+# Core logic support
ifdef CONFIG_ALPHA_APECS
-O_OBJS += apecs.o
+O_OBJS += core_apecs.o
endif
ifdef CONFIG_ALPHA_CIA
-O_OBJS += cia.o
+O_OBJS += core_cia.o
endif
ifdef CONFIG_ALPHA_LCA
-O_OBJS += lca.o
+O_OBJS += core_lca.o
+endif
+ifdef CONFIG_ALPHA_MCPCIA
+O_OBJS += core_mcpcia.o
endif
ifdef CONFIG_ALPHA_PYXIS
-O_OBJS += pyxis.o
+O_OBJS += core_pyxis.o
endif
ifdef CONFIG_ALPHA_T2
-O_OBJS += t2.o
+O_OBJS += core_t2.o
endif
ifdef CONFIG_ALPHA_TSUNAMI
-O_OBJS += tsunami.o
+O_OBJS += core_tsunami.o
endif
-ifdef CONFIG_ALPHA_MCPCIA
-O_OBJS += mcpcia.o
+
+# Board support
+ifneq ($(CONFIG_ALPHA_ALCOR)$(CONFIG_ALPHA_XLT),)
+O_OBJS += sys_alcor.o
+endif
+ifneq ($(CONFIG_ALPHA_CABRIOLET)$(CONFIG_ALPHA_EB164)$(CONFIG_ALPHA_EB66P)$(CONFIG_ALPHA_LX164)$(CONFIG_ALPHA_PC164),)
+O_OBJS += sys_cabriolet.o
+endif
+ifdef CONFIG_ALPHA_DP264
+O_OBJS += sys_dp264.o
+endif
+ifneq ($(CONFIG_ALPHA_EB64P)$(CONFIG_ALPHA_EB66),)
+O_OBJS += sys_eb64p.o
+endif
+ifdef CONFIG_ALPHA_JENSEN
+O_OBJS += sys_jensen.o
+endif
+ifdef CONFIG_ALPHA_MIATA
+O_OBJS += sys_miata.o
+endif
+ifdef CONFIG_ALPHA_MIKASA
+O_OBJS += sys_mikasa.o
+endif
+ifdef CONFIG_ALPHA_NORITAKE
+O_OBJS += sys_noritake.o
+endif
+ifdef CONFIG_ALPHA_RAWHIDE
+O_OBJS += sys_rawhide.o
+endif
+ifdef CONFIG_ALPHA_RUFFIAN
+O_OBJS += sys_ruffian.o
+endif
+ifdef CONFIG_ALPHA_SABLE
+O_OBJS += sys_sable.o
+endif
+ifneq ($(CONFIG_ALPHA_BOOK1)$(CONFIG_ALPHA_AVANTI)$(CONFIG_ALPHA_NONAME)$(CONFIG_ALPHA_P2K)$(CONFIG_ALPHA_XL),)
+O_OBJS += sys_sio.o
+endif
+ifdef CONFIG_ALPHA_SX164
+O_OBJS += sys_sx164.o
+endif
+ifdef CONFIG_ALPHA_TAKARA
+O_OBJS += sys_takara.o
endif
-ifneq ($(CONFIG_ALPHA_PC164)$(CONFIG_ALPHA_LX164),nn)
-O_OBJS += smc37c93x.o
+# Device support
+ifdef CONFIG_ALPHA_MIATA
+O_OBJS += es1888.o
endif
-ifneq ($(CONFIG_ALPHA_SX164)$(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),nnn)
+ifneq ($(CONFIG_ALPHA_SX164)$(CONFIG_ALPHA_MIATA)$(CONFIG_ALPHA_DP264),)
O_OBJS += smc37c669.o
endif
+ifneq ($(CONFIG_ALPHA_PC164)$(CONFIG_ALPHA_LX164),)
+O_OBJS += smc37c93x.o
+endif
+
+endif # GENERIC
ifdef SMP
O_OBJS += smp.o
@@ -55,9 +117,4 @@ endif
all: kernel.o head.o
-head.o: head.s
-
-head.s: head.S $(TOPDIR)/include/asm-alpha/system.h
- $(CPP) -traditional $(AFLAGS) -o $*.s $<
-
include $(TOPDIR)/Rules.make
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c
index c220ccdc6..a7047dd1f 100644
--- a/arch/alpha/kernel/alpha_ksyms.c
+++ b/arch/alpha/kernel/alpha_ksyms.c
@@ -14,6 +14,7 @@
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/pci.h>
+#include <linux/tty.h>
#include <asm/io.h>
#include <asm/hwrpb.h>
@@ -23,6 +24,8 @@
#include <linux/interrupt.h>
#include <asm/softirq.h>
#include <asm/fpu.h>
+#include <asm/irq.h>
+#include <asm/machvec.h>
#define __KERNEL_SYSCALLS__
#include <asm/unistd.h>
@@ -41,8 +44,12 @@ extern void __remlu (void);
extern void __divqu (void);
extern void __remqu (void);
+EXPORT_SYMBOL(alpha_mv);
EXPORT_SYMBOL(local_bh_count);
EXPORT_SYMBOL(local_irq_count);
+EXPORT_SYMBOL(enable_irq);
+EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(screen_info);
/* platform dependent support */
EXPORT_SYMBOL(_inb);
@@ -59,7 +66,7 @@ EXPORT_SYMBOL(_writew);
EXPORT_SYMBOL(_writel);
EXPORT_SYMBOL(_memcpy_fromio);
EXPORT_SYMBOL(_memcpy_toio);
-EXPORT_SYMBOL(_memset_io);
+EXPORT_SYMBOL(_memset_c_io);
EXPORT_SYMBOL(insb);
EXPORT_SYMBOL(insw);
EXPORT_SYMBOL(insl);
@@ -82,6 +89,7 @@ EXPORT_SYMBOL(memcmp);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(__memcpy);
EXPORT_SYMBOL(__memset);
+EXPORT_SYMBOL(__memsetw);
EXPORT_SYMBOL(__constant_c_memset);
EXPORT_SYMBOL(dump_thread);
@@ -115,7 +123,9 @@ EXPORT_SYMBOL(csum_ipv6_magic);
#ifdef CONFIG_MATHEMU_MODULE
extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long);
+extern long (*alpha_fp_emul) (unsigned long pc);
EXPORT_SYMBOL(alpha_fp_emul_imprecise);
+EXPORT_SYMBOL(alpha_fp_emul);
#endif
/*
diff --git a/arch/alpha/kernel/bios32.c b/arch/alpha/kernel/bios32.c
index 64c7442b6..633273954 100644
--- a/arch/alpha/kernel/bios32.c
+++ b/arch/alpha/kernel/bios32.c
@@ -29,9 +29,17 @@
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <asm/pci.h>
#include <asm/dma.h>
-#if 0
+#include "proto.h"
+#include "bios32.h"
+
+#define DEBUG_DEVS 0
+
+#if DEBUG_DEVS
# define DBG_DEVS(args) printk args
#else
# define DBG_DEVS(args)
@@ -39,174 +47,290 @@
#ifndef CONFIG_PCI
-int pcibios_present(void)
+asmlinkage int sys_pciconfig_read() { return -ENOSYS; }
+asmlinkage int sys_pciconfig_write() { return -ENOSYS; }
+void reset_for_srm(void) { }
+
+#else /* CONFIG_PCI */
+
+#include <linux/malloc.h>
+#include <linux/mm.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+
+/*
+ * PCI public interfaces.
+ */
+
+#define MAJOR_REV 0
+#define MINOR_REV 4 /* minor revision 4, add multi-PCI handling */
+
+
+int
+pcibios_present(void)
{
- return 0;
+ return alpha_mv.pci_read_config_byte != NULL;
}
-asmlinkage int sys_pciconfig_read()
+void __init
+pcibios_init(void)
{
- return -ENOSYS;
+ printk("Alpha PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
+ if (alpha_use_srm_setup)
+ printk(" NOT modifying existing (SRM) PCI configuration\n");
+
+ /* FIXME: Scan for multiple PCI busses here. */
}
-asmlinkage int sys_pciconfig_write()
+char * __init
+pcibios_setup(char *str)
{
- return -ENOSYS;
+ return str;
}
-#else /* CONFIG_PCI */
+void __init
+pcibios_fixup(void)
+{
+ alpha_mv.pci_fixup();
+}
-#include <linux/pci.h>
-#include <linux/malloc.h>
-#include <linux/mm.h>
+void __init
+pcibios_fixup_bus(struct pci_bus *bus)
+{
+}
-#include <asm/hwrpb.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/segment.h>
-#include <asm/system.h>
+int
+pcibios_read_config_byte (u8 bus, u8 dev, u8 where, u8 *value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_read_config_byte)
+ r = alpha_mv.pci_read_config_byte(bus, dev, where, value);
+ return r;
+}
+int
+pcibios_read_config_word (u8 bus, u8 dev, u8 where, u16 *value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_read_config_word)
+ r = alpha_mv.pci_read_config_word(bus, dev, where, value);
+ return r;
+}
-#define KB 1024
-#define MB (1024*KB)
-#define GB (1024*MB)
+int
+pcibios_read_config_dword (u8 bus, u8 dev, u8 where, u32 *value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_read_config_dword)
+ r = alpha_mv.pci_read_config_dword(bus, dev, where, value);
+ return r;
+}
-#define MAJOR_REV 0
+int
+pcibios_write_config_byte (u8 bus, u8 dev, u8 where, u8 value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_write_config_byte)
+ r = alpha_mv.pci_write_config_byte(bus, dev, where, value);
+ return r;
+}
-/* minor revision 4, add multi-PCI handling */
-#define MINOR_REV 4
+int
+pcibios_write_config_word (u8 bus, u8 dev, u8 where, u16 value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_write_config_word)
+ r = alpha_mv.pci_write_config_word(bus, dev, where, value);
+ return r;
+}
-/*
- * Align VAL to ALIGN, which must be a power of two.
- */
-#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
+int
+pcibios_write_config_dword (u8 bus, u8 dev, u8 where, u32 value)
+{
+ int r = PCIBIOS_FUNC_NOT_SUPPORTED;
+ if (alpha_mv.pci_write_config_dword)
+ r = alpha_mv.pci_write_config_dword(bus, dev, where, value);
+ return r;
+}
+asmlinkage int
+sys_pciconfig_read(unsigned long bus, unsigned long dfn,
+ unsigned long off, unsigned long len,
+ unsigned char *buf)
+{
+ unsigned char ubyte;
+ unsigned short ushort;
+ unsigned int uint;
+ long err = 0;
-#if defined(CONFIG_ALPHA_MCPCIA) || defined(CONFIG_ALPHA_TSUNAMI)
-/* multiple PCI bus machines */
-/* make handle from bus number */
-extern struct linux_hose_info *bus2hose[256];
-#define HANDLE(b) (((unsigned long)(bus2hose[(b)]->pci_hose_index)&3)<<32)
-#define DEV_IS_ON_PRIMARY(dev) \
- (bus2hose[(dev)->bus->number]->pci_first_busno == (dev)->bus->number)
-#else /* MCPCIA || TSUNAMI */
-#define HANDLE(b) (0)
-#define DEV_IS_ON_PRIMARY(dev) ((dev)->bus->number == 0)
-#endif /* MCPCIA || TSUNAMI */
-/*
- * PCI_MODIFY
- *
- * Temporary internal macro. If this 0, then do not write to any of
- * the PCI registers, merely read them (i.e., use configuration as
- * determined by SRM). The SRM seem do be doing a less than perfect
- * job in configuring PCI devices, so for now we do it ourselves.
- * Reconfiguring PCI devices breaks console (RPB) callbacks, but
- * those don't work properly with 64 bit addresses anyways.
- *
- * The accepted convention seems to be that the console (POST
- * software) should fully configure boot devices and configure the
- * interrupt routing of *all* devices. In particular, the base
- * addresses of non-boot devices need not be initialized. For
- * example, on the AXPpci33 board, the base address a #9 GXE PCI
- * graphics card reads as zero (this may, however, be due to a bug in
- * the graphics card---there have been some rumor that the #9 BIOS
- * incorrectly resets that address to 0...).
- */
-#ifdef CONFIG_ALPHA_SRM_SETUP
-#define PCI_MODIFY 0
-static struct pci_dev *irq_dev_to_reset[16];
-static unsigned char irq_to_reset[16];
-static int irq_reset_count = 0;
-static struct pci_dev *io_dev_to_reset[16];
-static unsigned char io_reg_to_reset[16];
-static unsigned int io_to_reset[16];
-static int io_reset_count = 0;
-#else /* SRM_SETUP */
-#define PCI_MODIFY 1
-#endif /* SRM_SETUP */
-
-extern struct hwrpb_struct *hwrpb;
-
-/* Forward declarations for some extra fixup routines for specific hardware. */
-#if defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164)
-extern int SMC93x_Init(void);
-#endif
-extern int SMC669_Init(void);
-#ifdef CONFIG_ALPHA_MIATA
-static int es1888_init(void);
-#endif
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (!pcibios_present())
+ return -ENOSYS;
+
+ lock_kernel();
+ switch (len) {
+ case 1:
+ err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
+ if (err != PCIBIOS_SUCCESSFUL)
+ ubyte = 0xff;
+ put_user(ubyte, buf);
+ break;
+ case 2:
+ err = pcibios_read_config_word(bus, dfn, off, &ushort);
+ if (err != PCIBIOS_SUCCESSFUL)
+ ushort = 0xffff;
+ put_user(ushort, (unsigned short *)buf);
+ break;
+ case 4:
+ err = pcibios_read_config_dword(bus, dfn, off, &uint);
+ if (err != PCIBIOS_SUCCESSFUL)
+ uint = 0xffffffff;
+ put_user(uint, (unsigned int *)buf);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ unlock_kernel();
+ return err;
+}
-#if PCI_MODIFY
+asmlinkage int
+sys_pciconfig_write(unsigned long bus, unsigned long dfn,
+ unsigned long off, unsigned long len,
+ unsigned char *buf)
+{
+ unsigned char ubyte;
+ unsigned short ushort;
+ unsigned int uint;
+ long err = 0;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (!pcibios_present())
+ return -ENOSYS;
+
+ lock_kernel();
+ switch (len) {
+ case 1:
+ err = get_user(ubyte, buf);
+ if (err)
+ break;
+ err = pcibios_write_config_byte(bus, dfn, off, ubyte);
+ if (err != PCIBIOS_SUCCESSFUL) {
+ err = -EFAULT;
+ }
+ break;
+ case 2:
+ err = get_user(ushort, (unsigned short *)buf);
+ if (err)
+ break;
+ err = pcibios_write_config_word(bus, dfn, off, ushort);
+ if (err != PCIBIOS_SUCCESSFUL) {
+ err = -EFAULT;
+ }
+ break;
+ case 4:
+ err = get_user(uint, (unsigned int *)buf);
+ if (err)
+ break;
+ err = pcibios_write_config_dword(bus, dfn, off, uint);
+ if (err != PCIBIOS_SUCCESSFUL) {
+ err = -EFAULT;
+ }
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ unlock_kernel();
+ return err;
+}
-/*
- * NOTE: we can't just blindly use 64K for machines with EISA busses; they
- * may also have PCI-PCI bridges present, and then we'd configure the bridge
- * incorrectly.
- *
- * Also, we start at 0x8000 or 0x9000, in hopes to get all devices'
- * IO space areas allocated *before* 0xC000; this is because certain
- * BIOSes (Millennium for one) use PCI Config space "mechanism #2"
- * accesses to probe the bus. If a device's registers appear at 0xC000,
- * it may see an INx/OUTx at that address during BIOS emulation of the
- * VGA BIOS, and some cards, notably Adaptec 2940UW, take mortal offense.
- *
- * Note that we may need this stuff for SRM_SETUP also, since certain
- * SRM consoles screw up and allocate I/O space addresses > 64K behind
- * PCI-to_PCI bridges, which can't pass I/O addresses larger than 64K, AFAIK.
- */
-#if defined(CONFIG_ALPHA_EISA)
-#define DEFAULT_IO_BASE 0x9000 /* start above 8th slot */
-#else
-#define DEFAULT_IO_BASE 0x8000 /* start at 8th slot */
-#endif
-static unsigned int io_base;
-#if defined(CONFIG_ALPHA_XL)
/*
- * An XL is AVANTI (APECS) family, *but* it has only 27 bits of ISA address
- * that get passed through the PCI<->ISA bridge chip. Although this causes
- * us to set the PCI->Mem window bases lower than normal, we still allocate
- * PCI bus devices' memory addresses *below* the low DMA mapping window,
- * and hope they fit below 64Mb (to avoid conflicts), and so that they can
- * be accessed via SPARSE space.
- *
- * We accept the risk that a broken Myrinet card will be put into a true XL
- * and thus can more easily run into the problem described below.
+ * Gory details start here...
*/
-#define DEFAULT_MEM_BASE (16*MB + 2*MB) /* 16M to 64M-1 is avail */
-#elif defined(CONFIG_ALPHA_LCA) || defined(CONFIG_ALPHA_APECS)
+struct linux_hose_info *bus2hose[256];
+
/*
- * We try to make this address *always* have more than 1 bit set.
- * this is so that devices like the broken Myrinet card will always have
- * a PCI memory address that will never match a IDSEL address in
- * PCI Config space, which can cause problems with early rev cards.
- *
- * However, APECS and LCA have only 34 bits for physical addresses, thus
- * limiting PCI bus memory addresses for SPARSE access to be less than 128Mb.
+ * Align VAL to ALIGN, which must be a power of two.
*/
-#define DEFAULT_MEM_BASE (64*MB + 2*MB)
+#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
-#else
-/*
- * We try to make this address *always* have more than 1 bit set.
- * this is so that devices like the broken Myrinet card will always have
- * a PCI memory address that will never match a IDSEL address in
- * PCI Config space, which can cause problems with early rev cards.
- *
- * Because CIA and PYXIS and T2 have more bits for physical addresses,
- * they support an expanded range of SPARSE memory addresses.
+
+/*
+ * The following structure records initial configuration of devices
+ * so that we can reset them on shutdown and so enable clean reboots
+ * on SRM. It is more trouble than it iw worth to conditionalize this.
*/
-#define DEFAULT_MEM_BASE (128*MB + 16*MB)
+static struct {
+ struct reset_irq {
+ struct pci_dev *dev;
+ u8 irq;
+ } irq[16];
+ int irq_count;
+
+ struct reset_io {
+ struct pci_dev *dev;
+ u8 reg;
+ u32 io;
+ } io[16];
+ int io_count;
+} srm_resets;
+
+/* Apply the collected reset modifications. */
+
+void
+reset_for_srm(void)
+{
+ struct pci_dev *dev;
+ int i;
+
+ /* Reset any IRQs that we changed. */
+ for (i = 0; i < srm_resets.irq_count; i++) {
+ dev = srm_resets.irq[i].dev;
+
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_LINE,
+ srm_resets.irq[i].irq);
+#if 1
+ printk("reset_for_srm: bus %d slot 0x%x "
+ "SRM IRQ 0x%x changed back from 0x%x\n",
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ srm_resets.irq[i].irq, dev->irq);
#endif
-static unsigned int mem_base;
+ }
+
+ /* Reset any IO addresses that we changed. */
+ for (i = 0; i < srm_resets.io_count; i++) {
+ dev = srm_resets.io[i].dev;
+
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ srm_resets.io[i].reg,
+ srm_resets.io[i].io);
+#if 1
+ printk("reset_for_srm: bus %d slot 0x%x "
+ "SRM IO restored to 0x%x\n",
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ srm_resets.io[i].io);
+#endif
+ }
+}
+
/*
* Disable PCI device DEV so that it does not respond to I/O or memory
* accesses.
*/
-static void disable_dev(struct pci_dev *dev)
+static void __init
+disable_dev(struct pci_dev *dev)
{
struct pci_bus *bus;
unsigned short cmd;
@@ -217,12 +341,20 @@ static void disable_dev(struct pci_dev *dev)
*/
if (dev->vendor == PCI_VENDOR_ID_INTEL &&
dev->device == PCI_DEVICE_ID_INTEL_82375) {
+ dev->class = PCI_CLASS_BRIDGE_EISA;
DBG_DEVS(("disable_dev: ignoring PCEB...\n"));
return;
}
+ if (dev->vendor == PCI_VENDOR_ID_INTEL &&
+ dev->device == PCI_DEVICE_ID_INTEL_82378) {
+ dev->class = PCI_CLASS_BRIDGE_ISA;
+ DBG_DEVS(("disable_dev: ignoring SIO...\n"));
+ return;
+ }
+
/*
- * we don't have code that will init the CYPRESS bridge correctly
+ * 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... :-\
*/
@@ -232,6 +364,19 @@ static void disable_dev(struct pci_dev *dev)
return;
}
+#if DEBUG_DEVS && 0
+ /* Worse HACK: Don't disable the video card, so I can see where
+ it is *really* falling over. */
+ if (dev->class >> 16 == PCI_BASE_CLASS_DISPLAY) {
+ DBG_DEVS(("disable_dev: ignoring video card %04x:%04x\n",
+ dev->vendor, dev->device));
+ return;
+ }
+#endif
+
+ DBG_DEVS(("disable_dev: disabling %04x:%04x\n",
+ dev->vendor, dev->device));
+
bus = dev->bus;
pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
@@ -246,7 +391,11 @@ static void disable_dev(struct pci_dev *dev)
*/
#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2))
-static void layout_dev(struct pci_dev *dev)
+static unsigned int io_base;
+static unsigned int mem_base;
+
+static void __init
+layout_dev(struct pci_dev *dev)
{
struct pci_bus *bus;
unsigned short cmd;
@@ -260,12 +409,20 @@ static void layout_dev(struct pci_dev *dev)
*/
if (dev->vendor == PCI_VENDOR_ID_INTEL &&
dev->device == PCI_DEVICE_ID_INTEL_82375) {
+ dev->class = PCI_CLASS_BRIDGE_EISA;
DBG_DEVS(("layout_dev: ignoring PCEB...\n"));
return;
}
+ if (dev->vendor == PCI_VENDOR_ID_INTEL &&
+ dev->device == PCI_DEVICE_ID_INTEL_82378) {
+ dev->class = PCI_CLASS_BRIDGE_ISA;
+ DBG_DEVS(("layout_dev: ignoring SIO...\n"));
+ return;
+ }
+
/*
- * we don't have code that will init the CYPRESS bridge correctly
+ * 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... :-\
*/
@@ -324,7 +481,7 @@ static void layout_dev(struct pci_dev *dev)
pcibios_write_config_dword(bus->number, dev->devfn,
off, base | 0x1);
- handle = HANDLE(bus->number) | base | 1;
+ handle = PCI_HANDLE(bus->number) | base | 1;
dev->base_address[idx] = handle;
DBG_DEVS(("layout_dev: dev 0x%x IO @ 0x%lx (0x%x)\n",
@@ -375,7 +532,7 @@ static void layout_dev(struct pci_dev *dev)
*
* In sparse memory address space, the first
* octant (16MB) of every 128MB segment is
- * aliased to the the very first 16MB of the
+ * aliased to the very first 16 MB of the
* address space (i.e., it aliases the ISA
* memory address space). Thus, we try to
* avoid allocating PCI devices in that range.
@@ -409,7 +566,7 @@ static void layout_dev(struct pci_dev *dev)
mem_base = base + size;
pcibios_write_config_dword(bus->number, dev->devfn,
off, base);
- handle = HANDLE(bus->number) | base;
+ handle = PCI_HANDLE(bus->number) | base;
dev->base_address[idx] = handle;
DBG_DEVS(("layout_dev: dev 0x%x MEM @ 0x%lx (0x%x)\n",
dev->device, handle, size));
@@ -440,8 +597,8 @@ static void layout_dev(struct pci_dev *dev)
dev->device, dev->class, cmd|PCI_COMMAND_MASTER));
}
-
-static int layout_bus(struct pci_bus *bus)
+static int __init
+layout_bus(struct pci_bus *bus)
{
unsigned int l, tio, bio, tmem, bmem;
struct pci_bus *child;
@@ -552,24 +709,44 @@ static int layout_bus(struct pci_bus *bus)
return found_vga;
}
-#endif /* !PCI_MODIFY */
-
-
-int pcibios_present(void)
+void __init
+layout_all_busses(unsigned long default_io_base,
+ unsigned long default_mem_base)
{
- return 1;
-}
+ struct pci_bus *cur;
+#if defined(CONFIG_ALPHA_GENERIC)
+ static struct linux_hose_info dummy_hose;
+ int i;
-void __init
-pcibios_init(void)
-{
- printk("Alpha PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
-#if !PCI_MODIFY
- printk("...NOT modifying existing (SRM) PCI configuration\n");
+ /*
+ * HACK: Emulate a multi-bus machine to a limited extent
+ * by initializing bus2hose to point to something that
+ * has pci_hose_index & pci_first_busno zero.
+ */
+ for (i = 0; i <= 0xff; i++)
+ bus2hose[i] = &dummy_hose;
#endif
+
+ /*
+ * Scan the tree, allocating PCI memory and I/O space.
+ */
+ /*
+ * Sigh; check_region() will need changing to accept a PCI_HANDLE,
+ * if we allocate I/O space addresses on a per-bus basis.
+ * For now, make the I/O bases unique across all busses, so
+ * that check_region() will not get confused... ;-}
+ */
+ io_base = default_io_base;
+ for (cur = &pci_root; cur; cur = cur->next) {
+ mem_base = default_mem_base;
+ DBG_DEVS(("layout_all_busses: calling layout_bus()\n"));
+ layout_bus(cur);
+ }
+ DBG_DEVS(("layout_all_busses: done.\n"));
}
+
/*
* The SRM console *disables* the IDE interface, this code ensures it's
* enabled.
@@ -584,7 +761,9 @@ pcibios_init(void)
* written twice (I believe this is a safety feature to prevent
* accidental modification---fun, isn't it?).
*/
-static inline void enable_ide(long ide_base)
+
+void __init
+enable_ide(long ide_base)
{
int data;
@@ -595,68 +774,29 @@ static inline void enable_ide(long ide_base)
outb(data | 0x40, ide_base+1); /* turn on IDE, really! */
}
-/*
- * A small note about bridges and interrupts. The DECchip 21050 (and later)
- * adheres to the PCI-PCI bridge specification. This says that the
- * interrupts on the other side of a bridge are swizzled in the following
- * manner:
- *
- * Dev Interrupt Interrupt
- * Pin on Pin on
- * Device Connector
- *
- * 4 A A
- * B B
- * C C
- * D D
- *
- * 5 A B
- * B C
- * C D
- * D A
- *
- * 6 A C
- * B D
- * C A
- * D B
- *
- * 7 A D
- * B A
- * C B
- * D C
- *
- * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
- * Thus, each swizzle is ((pin-1) + (device#-4)) % 4
- *
- * The following code is somewhat simplistic as it assumes only one bridge.
- * I will fix it later (david.rusling@reo.mts.dec.com).
- */
-static inline unsigned char
-bridge_swizzle(unsigned char pin, unsigned int slot)
-{
- /* swizzle */
- return (((pin-1) + slot) % 4) + 1;
-}
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-/* look for mis-configured devices' I/O space addresses behind bridges */
-static void check_behind_io(struct pci_dev *dev)
+/* Look for mis-configured devices' I/O space addresses behind bridges. */
+static void
+check_behind_io(struct pci_dev *dev)
{
struct pci_bus *bus = dev->bus;
unsigned int reg, orig_base, new_base, found_one = 0;
+ struct reset_io *ior;
for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
- /* read the current setting, check for I/O space and >= 64K */
- pcibios_read_config_dword(bus->number, dev->devfn, reg, &orig_base);
+ /* Read the current setting, check for I/O space and >= 64K */
+ pcibios_read_config_dword(bus->number, dev->devfn,
+ reg, &orig_base);
+
if (!orig_base || !(orig_base & PCI_BASE_ADDRESS_SPACE_IO))
continue; /* unused or non-IO */
+
if (orig_base < 64*1024) {
#if 1
printk("check_behind_io: ALREADY OK! bus %d slot %d base 0x%x\n",
bus->number, PCI_SLOT(dev->devfn), orig_base);
#endif
if (orig_base & ~1)
- continue; /* OK! */
+ continue; /* OK! */
orig_base = 0x12001; /* HACK! FIXME!! */
}
@@ -671,1160 +811,148 @@ printk("check_behind_io: ALERT! bus %d slot %d old 0x%x new 0x%x\n",
pcibios_write_config_dword(bus->number, dev->devfn,
reg, new_base);
- io_dev_to_reset[io_reset_count] = dev;
- io_reg_to_reset[io_reset_count] = reg;
- io_to_reset[io_reset_count] = orig_base;
- io_reset_count++;
+ ior = &srm_resets.io[srm_resets.io_count++];
+ ior->dev = dev;
+ ior->reg = reg;
+ ior->io = orig_base;
found_one++;
- } /* end for-loop */
+ }
- /* if any were modified, gotta hack the bridge IO limits too... */
+ /* If any were modified, gotta hack the bridge IO limits too. */
if (found_one) {
- if (bus->self) {
- struct pci_dev *bridge = bus->self;
- unsigned int l;
- /*
- * Set up the top and bottom of the PCI I/O segment
- * for this bus.
- */
- pcibios_read_config_dword(bridge->bus->number,
- bridge->devfn, 0x1c, &l);
+ if (bus->self) {
+ struct pci_dev *bridge = bus->self;
+ unsigned int l;
+ /*
+ * Set up the top and bottom of the PCI I/O segment
+ * for this bus.
+ */
+ pcibios_read_config_dword(bridge->bus->number,
+ bridge->devfn, 0x1c, &l);
#if 1
printk("check_behind_io: ALERT! bus %d slot %d oldLIM 0x%x\n",
bus->number, PCI_SLOT(bridge->devfn), l);
#endif
- l = (l & 0xffff0000U) | 0xf080U; /* give it ALL */
- pcibios_write_config_dword(bridge->bus->number,
- bridge->devfn, 0x1c, l);
- pcibios_write_config_dword(bridge->bus->number,
- bridge->devfn,
- 0x3c, 0x00040000);
- pcibios_write_config_dword(bridge->bus->number,
- bridge->devfn,
- 0x4, 0xffff0007);
- } else
- printk("check_behind_io: WARNING! bus->self NULL\n");
+ l = (l & 0xffff0000U) | 0xf080U; /* give it ALL */
+ pcibios_write_config_dword(bridge->bus->number,
+ bridge->devfn, 0x1c, l);
+ pcibios_write_config_dword(bridge->bus->number,
+ bridge->devfn,
+ 0x3c, 0x00040000);
+ pcibios_write_config_dword(bridge->bus->number,
+ bridge->devfn,
+ 0x4, 0xffff0007);
+ } else
+ printk("check_behind_io: WARNING! bus->self NULL\n");
}
}
-#endif /* CONFIG_ALPHA_SRM_SETUP */
+
/*
- * Most evaluation boards share most of the fixup code, which is isolated
- * here. This function is declared "inline" as only one platform will ever
- * be selected in any given kernel. If that platform doesn't need this code,
- * we don't want it around as dead code.
+ * Most boards share most of the fixup code, which is isolated here.
*/
-static inline void
-common_fixup(long min_idsel, long max_idsel, long irqs_per_slot,
- char irq_tab[max_idsel - min_idsel + 1][irqs_per_slot],
- long ide_base)
+
+void __init
+common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin),
+ int (*swizzle)(struct pci_dev *dev, int *pin))
{
- struct pci_dev *dev, *curr;
- unsigned char pin;
- unsigned char slot;
+ struct pci_dev *dev;
+ u8 pin, slot, irq_orig;
+ int irq;
/*
- * Go through all devices, fixing up irqs as we see fit:
+ * Go through all devices, fixing up irqs as we see fit.
*/
for (dev = pci_devices; dev; dev = dev->next) {
- if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE ||
- dev->class >> 8 == PCI_CLASS_BRIDGE_PCMCIA) {
- /*
- * HACK: the PCI-to-EISA bridge appears not to identify
- * itself as a bridge... :-(
- */
- if (dev->vendor == PCI_VENDOR_ID_INTEL &&
- dev->device == PCI_DEVICE_ID_INTEL_82375) {
- DBG_DEVS(("common_fixup: ignoring PCEB...\n"));
- continue;
- }
-
- /*
- * This device is not on the primary bus, we need
- * to figure out which interrupt pin it will come
- * in on. We know which slot it will come in on
- * 'cos that slot is where the bridge is. Each
- * time the interrupt line passes through a PCI-PCI
- * bridge we must apply the swizzle function (see
- * the inline static routine above).
- */
- dev->irq = 0;
- if (!DEV_IS_ON_PRIMARY(dev)) {
- /* read the pin and do the PCI-PCI bridge
- interrupt pin swizzle */
- pcibios_read_config_byte(dev->bus->number,
- dev->devfn,
- PCI_INTERRUPT_PIN,
- &pin);
- /* cope with 0 and illegal */
- if (pin == 0 || pin > 4)
- pin = 1;
- /* follow the chain of bridges, swizzling
- as we go */
- curr = dev;
-#if defined(CONFIG_ALPHA_MIATA)
- /* check first for the built-in bridge */
- if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
- (PCI_SLOT(dev->bus->self->devfn) == 20)) {
- slot = PCI_SLOT(dev->devfn) + 5;
- DBG_DEVS(("MIATA: bus 1 slot %d pin %d"
- " irq %d min_idsel %d\n",
- PCI_SLOT(dev->devfn), pin,
- irq_tab[slot - min_idsel][pin],
- min_idsel));
- }
- else /* must be a card-based bridge */
- {
- do {
- if ((PCI_SLOT(curr->bus->self->devfn) == 8) ||
- (PCI_SLOT(curr->bus->self->devfn) == 20))
- {
- slot = PCI_SLOT(curr->devfn) + 5;
- break;
- }
- /* swizzle */
- pin = bridge_swizzle(
- pin, PCI_SLOT(curr->devfn)) ;
- /* move up the chain of bridges */
- curr = curr->bus->self ;
- /* slot of the next bridge. */
- slot = PCI_SLOT(curr->devfn);
- } while (curr->bus->self) ;
- }
-#elif defined(CONFIG_ALPHA_NORITAKE)
- /* check first for the built-in bridge */
- if (PCI_SLOT(dev->bus->self->devfn) == 8) {
- slot = PCI_SLOT(dev->devfn) + 15; /* WAG! */
- DBG_DEVS(("NORITAKE: bus 1 slot %d pin %d"
- "irq %d min_idsel %ld\n",
- PCI_SLOT(dev->devfn), pin,
- irq_tab[slot - min_idsel][pin],
- min_idsel));
- }
- else /* must be a card-based bridge */
- {
- do {
- if (PCI_SLOT(curr->bus->self->devfn) == 8) {
- slot = PCI_SLOT(curr->devfn) + 15;
- break;
- }
- /* swizzle */
- pin = bridge_swizzle(
- pin, PCI_SLOT(curr->devfn)) ;
- /* move up the chain of bridges */
- curr = curr->bus->self ;
- /* slot of the next bridge. */
- slot = PCI_SLOT(curr->devfn);
- } while (curr->bus->self) ;
- }
-#else /* everyone but MIATA and NORITAKE */
- DBG_DEVS(("common_fixup: bus %d slot %d pin %d "
- "irq %d min_idsel %ld\n",
- curr->bus->number,
- PCI_SLOT(dev->devfn), pin,
- irq_tab[slot - min_idsel][pin],
- min_idsel));
- do {
- /* swizzle */
- pin =
- bridge_swizzle(pin, PCI_SLOT(curr->devfn));
- /* move up the chain of bridges */
- curr = curr->bus->self;
- } while (curr->bus->self);
- /* The slot is the slot of the last bridge. */
- slot = PCI_SLOT(curr->devfn);
-#endif
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /*
- * must make sure that SRM didn't screw up
- * and allocate an address > 64K for I/O
- * space behind a PCI-PCI bridge
- */
- check_behind_io(dev);
-#endif /* CONFIG_ALPHA_SRM_SETUP */
- } else { /* just a device on a primary bus */
- /* work out the slot */
- slot = PCI_SLOT(dev->devfn);
- /* read the pin */
- pcibios_read_config_byte(dev->bus->number,
- dev->devfn,
- PCI_INTERRUPT_PIN,
- &pin);
- DBG_DEVS(("common_fixup: bus %d slot %d"
- " pin %d irq %d min_idsel %ld\n",
- dev->bus->number, slot, pin,
- irq_tab[slot - min_idsel][pin],
- min_idsel));
- /* cope with 0 and illegal */
- if (pin == 0 || pin > 4)
- pin = 1;
- }
- if (irq_tab[slot - min_idsel][pin] != -1)
- dev->irq = irq_tab[slot - min_idsel][pin];
-#ifdef CONFIG_ALPHA_RAWHIDE
- dev->irq +=
- 24 * bus2hose[dev->bus->number]->pci_hose_index;
-#endif /* RAWHIDE */
-#ifdef CONFIG_ALPHA_SRM
- {
- unsigned char irq_orig;
- /* read the original SRM-set IRQ and tell */
- pcibios_read_config_byte(dev->bus->number,
- dev->devfn,
- PCI_INTERRUPT_LINE,
- &irq_orig);
- if (irq_orig != dev->irq) {
- DBG_DEVS(("common_fixup: bus %d slot 0x%x "
- "SRM IRQ 0x%x changed to 0x%x\n",
- dev->bus->number,PCI_SLOT(dev->devfn),
- irq_orig, dev->irq));
-#ifdef CONFIG_ALPHA_SRM_SETUP
- irq_dev_to_reset[irq_reset_count] = dev;
- irq_to_reset[irq_reset_count] = irq_orig;
- irq_reset_count++;
-#endif /* CONFIG_ALPHA_SRM_SETUP */
- }
- }
-#endif /* SRM */
-
- /* always tell the device, so the driver knows what is
- * the real IRQ to use; the device does not use it.
- */
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_LINE, dev->irq);
-
- DBG_DEVS(("common_fixup: bus %d slot 0x%x"
- " VID 0x%x DID 0x%x\n"
- " int_slot 0x%x pin 0x%x"
- " pirq 0x%x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- dev->vendor, dev->device,
- slot, pin, dev->irq));
-
- /*
- * if it's a VGA, enable its BIOS ROM at C0000
- */
- if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
- /* but if its a Cirrus 543x/544x DISABLE it, */
- /* since enabling ROM disables the memory... */
- if ((dev->vendor == PCI_VENDOR_ID_CIRRUS) &&
- (dev->device >= 0x00a0) &&
- (dev->device <= 0x00ac)) {
- pcibios_write_config_dword(
- dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x00000000);
- } else {
- pcibios_write_config_dword(
- dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
- }
- }
- /*
- * if it's a SCSI, disable its BIOS ROM
- */
- if ((dev->class >> 8) == PCI_CLASS_STORAGE_SCSI) {
- pcibios_write_config_dword(dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x0000000);
- }
- }
- }
- if (ide_base) {
- enable_ide(ide_base);
- }
-}
-
-/*
- * The EB66+ is very similar to the EB66 except that it does not have
- * the on-board NCR and Tulip chips. In the code below, I have used
- * slot number to refer to the id select line and *not* the slot
- * number used in the EB66+ documentation. However, in the table,
- * I've given the slot number, the id select line and the Jxx number
- * that's printed on the board. The interrupt pins from the PCI slots
- * are wired into 3 interrupt summary registers at 0x804, 0x805 and
- * 0x806 ISA.
- *
- * In the table, -1 means don't assign an IRQ number. This is usually
- * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
- */
-static inline void eb66p_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- {16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J25 */
- {16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J26 */
- { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
- {16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 9, slot 2, J27 */
- {16+3, 16+3, 16+8, 16+12, 16+6} /* IdSel 10, slot 3, J28 */
- };
- common_fixup(6, 10, 5, irq_tab, 0x398);
-}
-
-
-/*
- * The PC164 and LX164 have 19 PCI interrupts, four from each of the four
- * PCI slots, the SIO, PCI/IDE, and USB.
- *
- * Each of the interrupts can be individually masked. This is
- * accomplished by setting the appropriate bit in the mask register.
- * A bit is set by writing a "1" to the desired position in the mask
- * register and cleared by writing a "0". There are 3 mask registers
- * located at ISA address 804h, 805h and 806h.
- *
- * An I/O read at ISA address 804h, 805h, 806h will return the
- * state of the 11 PCI interrupts and not the state of the MASKED
- * interrupts.
- *
- * Note: A write to I/O 804h, 805h, and 806h the mask register will be
- * updated.
- *
- *
- * ISA DATA<7:0>
- * ISA +--------------------------------------------------------------+
- * ADDRESS | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
- * +==============================================================+
- * 0x804 | INTB0 | USB | IDE | SIO | INTA3 |INTA2 | INTA1 | INTA0 |
- * +--------------------------------------------------------------+
- * 0x805 | INTD0 | INTC3 | INTC2 | INTC1 | INTC0 |INTB3 | INTB2 | INTB1 |
- * +--------------------------------------------------------------+
- * 0x806 | Rsrv | Rsrv | Rsrv | Rsrv | Rsrv |INTD3 | INTD2 | INTD1 |
- * +--------------------------------------------------------------+
- * * Rsrv = reserved bits
- * Note: The mask register is write-only.
- *
- * IdSel
- * 5 32 bit PCI option slot 2
- * 6 64 bit PCI option slot 0
- * 7 64 bit PCI option slot 1
- * 8 Saturn I/O
- * 9 32 bit PCI option slot 3
- * 10 USB
- * 11 IDE
- *
- */
-
-#if defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164)
-static inline void alphapc164_fixup(void)
-{
- static char irq_tab[7][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 16+2, 16+2, 16+9, 16+13, 16+17}, /* IdSel 5, slot 2, J20 */
- { 16+0, 16+0, 16+7, 16+11, 16+15}, /* IdSel 6, slot 0, J29 */
- { 16+1, 16+1, 16+8, 16+12, 16+16}, /* IdSel 7, slot 1, J26 */
- { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
- { 16+3, 16+3, 16+10, 16+14, 16+18}, /* IdSel 9, slot 3, J19 */
- { 16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 10, USB */
- { 16+5, 16+5, 16+5, 16+5, 16+5} /* IdSel 11, IDE */
- };
-
- common_fixup(5, 11, 5, irq_tab, 0);
- SMC93x_Init();
-}
-#endif
-
-/*
- * The AlphaPC64 is very similar to the EB66+ except that its slots
- * are numbered differently. In the code below, I have used slot
- * number to refer to the id select line and *not* the slot number
- * used in the AlphaPC64 documentation. However, in the table, I've
- * given the slot number, the id select line and the Jxx number that's
- * printed on the board. The interrupt pins from the PCI slots are
- * wired into 3 interrupt summary registers at 0x804, 0x805 and 0x806
- * ISA.
- *
- * In the table, -1 means don't assign an IRQ number. This is usually
- * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
- */
-static inline void cabriolet_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5, slot 2, J21 */
- { 16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J19 */
- { 16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J20 */
- { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
- { 16+3, 16+3, 16+8, 16+12, 16+16} /* IdSel 9, slot 3, J22 */
- };
-
- common_fixup(5, 9, 5, irq_tab, 0x398);
-}
-
-
-/*
- * Fixup configuration for EB66/EB64+ boards.
- *
- * Both these boards use the same interrupt summary scheme. There are
- * two 8 bit external summary registers as follows:
- *
- * Summary @ 0x26:
- * Bit Meaning
- * 0 Interrupt Line A from slot 0
- * 1 Interrupt Line A from slot 1
- * 2 Interrupt Line B from slot 0
- * 3 Interrupt Line B from slot 1
- * 4 Interrupt Line C from slot 0
- * 5 Interrupt line from the two ISA PICs
- * 6 Tulip (slot
- * 7 NCR SCSI
- *
- * Summary @ 0x27
- * Bit Meaning
- * 0 Interrupt Line C from slot 1
- * 1 Interrupt Line D from slot 0
- * 2 Interrupt Line D from slot 1
- * 3 RAZ
- * 4 RAZ
- * 5 RAZ
- * 6 RAZ
- * 7 RAZ
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 5 NCR SCSI controller
- * 6 PCI on board slot 0
- * 7 PCI on board slot 1
- * 8 Intel SIO PCI-ISA bridge chip
- * 9 Tulip - DECchip 21040 ethernet controller
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-static inline void eb66_and_eb64p_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- {16+7, 16+7, 16+7, 16+7, 16+7}, /* IdSel 5, slot ?, ?? */
- {16+0, 16+0, 16+2, 16+4, 16+9}, /* IdSel 6, slot ?, ?? */
- {16+1, 16+1, 16+3, 16+8, 16+10}, /* IdSel 7, slot ?, ?? */
- { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
- {16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 9, TULIP */
- };
- common_fixup(5, 9, 5, irq_tab, 0);
-}
-
-
-/*
- * Fixup configuration for MIKASA (AlphaServer 1000)
- *
- * Summary @ 0x536:
- * Bit Meaning
- * 0 Interrupt Line A from slot 0
- * 1 Interrupt Line B from slot 0
- * 2 Interrupt Line C from slot 0
- * 3 Interrupt Line D from slot 0
- * 4 Interrupt Line A from slot 1
- * 5 Interrupt line B from slot 1
- * 6 Interrupt Line C from slot 1
- * 7 Interrupt Line D from slot 1
- * 8 Interrupt Line A from slot 2
- * 9 Interrupt Line B from slot 2
- *10 Interrupt Line C from slot 2
- *11 Interrupt Line D from slot 2
- *12 NCR 810 SCSI
- *13 Power Supply Fail
- *14 Temperature Warn
- *15 Reserved
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 6 NCR SCSI controller
- * 7 Intel PCI-EISA bridge chip
- * 11 PCI on board slot 0
- * 12 PCI on board slot 1
- * 13 PCI on board slot 2
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-static inline void mikasa_fixup(void)
-{
- static char irq_tab[8][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- {16+12, 16+12, 16+12, 16+12, 16+12}, /* IdSel 17, SCSI */
- { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
- { -1, -1, -1, -1, -1}, /* IdSel 19, ???? */
- { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */
- { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */
- { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 0 */
- { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */
- { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 24, slot 2 */
- };
- common_fixup(6, 13, 5, irq_tab, 0);
-}
-
-/*
- * Fixup configuration for NORITAKE (AlphaServer 1000A)
- *
- * This is also used for CORELLE (AlphaServer 800)
- * and ALCOR Primo (AlphaStation 600A).
- *
- * Summary @ 0x542, summary register #1:
- * Bit Meaning
- * 0 All valid ints from summary regs 2 & 3
- * 1 QLOGIC ISP1020A SCSI
- * 2 Interrupt Line A from slot 0
- * 3 Interrupt Line B from slot 0
- * 4 Interrupt Line A from slot 1
- * 5 Interrupt line B from slot 1
- * 6 Interrupt Line A from slot 2
- * 7 Interrupt Line B from slot 2
- * 8 Interrupt Line A from slot 3
- * 9 Interrupt Line B from slot 3
- *10 Interrupt Line A from slot 4
- *11 Interrupt Line B from slot 4
- *12 Interrupt Line A from slot 5
- *13 Interrupt Line B from slot 5
- *14 Interrupt Line A from slot 6
- *15 Interrupt Line B from slot 6
- *
- * Summary @ 0x544, summary register #2:
- * Bit Meaning
- * 0 OR of all unmasked ints in SR #2
- * 1 OR of secondary bus ints
- * 2 Interrupt Line C from slot 0
- * 3 Interrupt Line D from slot 0
- * 4 Interrupt Line C from slot 1
- * 5 Interrupt line D from slot 1
- * 6 Interrupt Line C from slot 2
- * 7 Interrupt Line D from slot 2
- * 8 Interrupt Line C from slot 3
- * 9 Interrupt Line D from slot 3
- *10 Interrupt Line C from slot 4
- *11 Interrupt Line D from slot 4
- *12 Interrupt Line C from slot 5
- *13 Interrupt Line D from slot 5
- *14 Interrupt Line C from slot 6
- *15 Interrupt Line D from slot 6
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 7 Intel PCI-EISA bridge chip
- * 8 DEC PCI-PCI bridge chip
- * 11 PCI on board slot 0
- * 12 PCI on board slot 1
- * 13 PCI on board slot 2
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-static inline void noritake_fixup(void)
-{
- static char irq_tab[15][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- /* note: IDSELs 16, 17, and 25 are CORELLE only */
- { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
- { -1, -1, -1, -1, -1}, /* IdSel 17, S3 Trio64 */
- { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
- { -1, -1, -1, -1, -1}, /* IdSel 19, PPB */
- { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */
- { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */
- { 16+2, 16+2, 16+3, 32+2, 32+3}, /* IdSel 22, slot 0 */
- { 16+4, 16+4, 16+5, 32+4, 32+5}, /* IdSel 23, slot 1 */
- { 16+6, 16+6, 16+7, 32+6, 32+7}, /* IdSel 24, slot 2 */
- { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 25, slot 3 */
- /* the following 5 are actually on PCI bus 1, which is */
- /* across the built-in bridge of the NORITAKE only */
- { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
- { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 17, slot 3 */
- {16+10, 16+10, 16+11, 32+10, 32+11}, /* IdSel 18, slot 4 */
- {16+12, 16+12, 16+13, 32+12, 32+13}, /* IdSel 19, slot 5 */
- {16+14, 16+14, 16+15, 32+14, 32+15}, /* IdSel 20, slot 6 */
- };
- common_fixup(5, 19, 5, irq_tab, 0);
-}
-
-/*
- * Fixup configuration for ALCOR and XLT (XL-300/366/433)
- *
- * Summary @ GRU_INT_REQ:
- * Bit Meaning
- * 0 Interrupt Line A from slot 2
- * 1 Interrupt Line B from slot 2
- * 2 Interrupt Line C from slot 2
- * 3 Interrupt Line D from slot 2
- * 4 Interrupt Line A from slot 1
- * 5 Interrupt line B from slot 1
- * 6 Interrupt Line C from slot 1
- * 7 Interrupt Line D from slot 1
- * 8 Interrupt Line A from slot 0
- * 9 Interrupt Line B from slot 0
- *10 Interrupt Line C from slot 0
- *11 Interrupt Line D from slot 0
- *12 Interrupt Line A from slot 4
- *13 Interrupt Line B from slot 4
- *14 Interrupt Line C from slot 4
- *15 Interrupt Line D from slot 4
- *16 Interrupt Line D from slot 3
- *17 Interrupt Line D from slot 3
- *18 Interrupt Line D from slot 3
- *19 Interrupt Line D from slot 3
- *20-30 Reserved
- *31 EISA interrupt
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 6 built-in TULIP (XLT only)
- * 7 PCI on board slot 0
- * 8 PCI on board slot 3
- * 9 PCI on board slot 4
- * 10 PCEB (PCI-EISA bridge)
- * 11 PCI on board slot 2
- * 12 PCI on board slot 1
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-static inline void alcor_fixup(void)
-{
- static char irq_tab[7][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- /* note: IDSEL 17 is XLT only */
- {16+13, 16+13, 16+13, 16+13, 16+13}, /* IdSel 17, TULIP */
- { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 18, slot 0 */
- {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 19, slot 3 */
- {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 20, slot 4 */
- { -1, -1, -1, -1, -1}, /* IdSel 21, PCEB */
- { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 2 */
- { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */
- };
- common_fixup(6, 12, 5, irq_tab, 0);
-}
-
-/*
- * Fixup configuration for ALPHA SABLE (2100) - 2100A is different ??
- *
- * Summary Registers (536/53a/53c):
- * Bit Meaning
- *-----------------
- * 0 PCI slot 0
- * 1 NCR810 (builtin)
- * 2 TULIP (builtin)
- * 3 mouse
- * 4 PCI slot 1
- * 5 PCI slot 2
- * 6 keyboard
- * 7 floppy
- * 8 COM2
- * 9 parallel port
- *10 EISA irq 3
- *11 EISA irq 4
- *12 EISA irq 5
- *13 EISA irq 6
- *14 EISA irq 7
- *15 COM1
- *16 EISA irq 9
- *17 EISA irq 10
- *18 EISA irq 11
- *19 EISA irq 12
- *20 EISA irq 13
- *21 EISA irq 14
- *22 NC
- *23 IIC
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 0 TULIP
- * 1 SCSI
- * 2 PCI-EISA bridge
- * 3 none
- * 4 none
- * 5 none
- * 6 PCI on board slot 0
- * 7 PCI on board slot 1
- * 8 PCI on board slot 2
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-/*
- * NOTE: the IRQ assignments below are arbitrary, but need to be consistent
- * with the values in the sable_irq_to_mask[] and sable_mask_to_irq[] tables
- * in irq.c
- */
-static inline void sable_fixup(void)
-{
- static char irq_tab[9][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */
- { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */
- { -1, -1, -1, -1, -1}, /* IdSel 2, SIO */
- { -1, -1, -1, -1, -1}, /* IdSel 3, none */
- { -1, -1, -1, -1, -1}, /* IdSel 4, none */
- { -1, -1, -1, -1, -1}, /* IdSel 5, none */
- { 32+2, 32+2, 32+2, 32+2, 32+2}, /* IdSel 6, slot 0 */
- { 32+3, 32+3, 32+3, 32+3, 32+3}, /* IdSel 7, slot 1 */
- { 32+4, 32+4, 32+4, 32+4, 32+4}, /* IdSel 8, slot 2 */
- };
- common_fixup(0, 8, 5, irq_tab, 0);
-}
-
-/*
- * Fixup configuration for MIATA (EV56+PYXIS)
- *
- * Summary @ PYXIS_INT_REQ:
- * Bit Meaning
- * 0 Fan Fault
- * 1 NMI
- * 2 Halt/Reset switch
- * 3 none
- * 4 CID0 (Riser ID)
- * 5 CID1 (Riser ID)
- * 6 Interval timer
- * 7 PCI-ISA Bridge
- * 8 Ethernet
- * 9 EIDE (deprecated, ISA 14/15 used)
- *10 none
- *11 USB
- *12 Interrupt Line A from slot 4
- *13 Interrupt Line B from slot 4
- *14 Interrupt Line C from slot 4
- *15 Interrupt Line D from slot 4
- *16 Interrupt Line A from slot 5
- *17 Interrupt line B from slot 5
- *18 Interrupt Line C from slot 5
- *19 Interrupt Line D from slot 5
- *20 Interrupt Line A from slot 1
- *21 Interrupt Line B from slot 1
- *22 Interrupt Line C from slot 1
- *23 Interrupt Line D from slot 1
- *24 Interrupt Line A from slot 2
- *25 Interrupt Line B from slot 2
- *26 Interrupt Line C from slot 2
- *27 Interrupt Line D from slot 2
- *27 Interrupt Line A from slot 3
- *29 Interrupt Line B from slot 3
- *30 Interrupt Line C from slot 3
- *31 Interrupt Line D from slot 3
- *
- * The device to slot mapping looks like:
- *
- * Slot Device
- * 3 DC21142 Ethernet
- * 4 EIDE CMD646
- * 5 none
- * 6 USB
- * 7 PCI-ISA bridge
- * 8 PCI-PCI Bridge (SBU Riser)
- * 9 none
- * 10 none
- * 11 PCI on board slot 4 (SBU Riser)
- * 12 PCI on board slot 5 (SBU Riser)
- *
- * These are behind the bridge, so I'm not sure what to do...
- *
- * 13 PCI on board slot 1 (SBU Riser)
- * 14 PCI on board slot 2 (SBU Riser)
- * 15 PCI on board slot 3 (SBU Riser)
- *
- *
- * This two layered interrupt approach means that we allocate IRQ 16 and
- * above for PCI interrupts. The IRQ relates to which bit the interrupt
- * comes in on. This makes interrupt processing much easier.
- */
-
-#ifdef CONFIG_ALPHA_MIATA
-static inline void miata_fixup(void)
-{
- static char irq_tab[18][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- {16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8}, /* IdSel 14, DC21142 */
- { -1, -1, -1, -1, -1}, /* IdSel 15, EIDE */
- { -1, -1, -1, -1, -1}, /* IdSel 16, none */
- { -1, -1, -1, -1, -1}, /* IdSel 17, none */
-/* {16+11, 16+11, 16+11, 16+11, 16+11},*//* IdSel 17, USB ?? */
- { -1, -1, -1, -1, -1}, /* IdSel 18, PCI-ISA */
- { -1, -1, -1, -1, -1}, /* IdSel 19, PCI-PCI */
- { -1, -1, -1, -1, -1}, /* IdSel 20, none */
- { -1, -1, -1, -1, -1}, /* IdSel 21, none */
- {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 22, slot 4 */
- {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 23, slot 5 */
- /* The following are actually on bus 1, which is */
- /* across the builtin PCI-PCI bridge */
- {16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 24, slot 1 */
- {16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 25, slot 2 */
- {16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 26, slot 3 */
- { -1, -1, -1, -1, -1}, /* IdSel 27, none */
- { -1, -1, -1, -1, -1}, /* IdSel 28, none */
- { -1, -1, -1, -1, -1}, /* IdSel 29, none */
- { -1, -1, -1, -1, -1}, /* IdSel 30, none */
- { -1, -1, -1, -1, -1}, /* IdSel 31, PCI-PCI */
- };
- common_fixup(3, 20, 5, irq_tab, 0);
- SMC669_Init(); /* it might be a GL (fails harmlessly if not) */
- es1888_init();
-}
-#endif
-
-/*
- * Fixup configuration for SX164 (PCA56+PYXIS)
- *
- * Summary @ PYXIS_INT_REQ:
- * Bit Meaning
- * 0 RSVD
- * 1 NMI
- * 2 Halt/Reset switch
- * 3 MBZ
- * 4 RAZ
- * 5 RAZ
- * 6 Interval timer (RTC)
- * 7 PCI-ISA Bridge
- * 8 Interrupt Line A from slot 3
- * 9 Interrupt Line A from slot 2
- *10 Interrupt Line A from slot 1
- *11 Interrupt Line A from slot 0
- *12 Interrupt Line B from slot 3
- *13 Interrupt Line B from slot 2
- *14 Interrupt Line B from slot 1
- *15 Interrupt line B from slot 0
- *16 Interrupt Line C from slot 3
- *17 Interrupt Line C from slot 2
- *18 Interrupt Line C from slot 1
- *19 Interrupt Line C from slot 0
- *20 Interrupt Line D from slot 3
- *21 Interrupt Line D from slot 2
- *22 Interrupt Line D from slot 1
- *23 Interrupt Line D from slot 0
- *
- * IdSel
- * 5 32 bit PCI option slot 2
- * 6 64 bit PCI option slot 0
- * 7 64 bit PCI option slot 1
- * 8 Cypress I/O
- * 9 32 bit PCI option slot 3
- *
- */
+ if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
+ (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
+ continue;
-static inline void sx164_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 16+ 9, 16+ 9, 16+13, 16+17, 16+21}, /* IdSel 5 slot 2 J17 */
- { 16+11, 16+11, 16+15, 16+19, 16+23}, /* IdSel 6 slot 0 J19 */
- { 16+10, 16+10, 16+14, 16+18, 16+22}, /* IdSel 7 slot 1 J18 */
- { -1, -1, -1, -1, -1}, /* IdSel 8 SIO */
- { 16+ 8, 16+ 8, 16+12, 16+16, 16+20} /* IdSel 9 slot 3 J15 */
- };
- common_fixup(5, 9, 5, irq_tab, 0);
- SMC669_Init();
-}
+ /*
+ * This device is not on the primary bus, we need
+ * to figure out which interrupt pin it will come
+ * in on. We know which slot it will come in on
+ * 'cos that slot is where the bridge is. Each
+ * time the interrupt line passes through a PCI-PCI
+ * bridge we must apply the swizzle function (see
+ * the inline static routine above).
+ */
+ dev->irq = 0;
-/*
- * Fixup configuration for DP264 (EV6+TSUNAMI)
- *
- * Summary @ TSUNAMI_CSR_DIM0:
- * Bit Meaning
- * 0-17 Unused
- *18 Interrupt SCSI B (Adaptec 7895 builtin)
- *19 Interrupt SCSI A (Adaptec 7895 builtin)
- *20 Interrupt Line D from slot 2 PCI0
- *21 Interrupt Line C from slot 2 PCI0
- *22 Interrupt Line B from slot 2 PCI0
- *23 Interrupt Line A from slot 2 PCI0
- *24 Interrupt Line D from slot 1 PCI0
- *25 Interrupt Line C from slot 1 PCI0
- *26 Interrupt Line B from slot 1 PCI0
- *27 Interrupt Line A from slot 1 PCI0
- *28 Interrupt Line D from slot 0 PCI0
- *29 Interrupt Line C from slot 0 PCI0
- *30 Interrupt Line B from slot 0 PCI0
- *31 Interrupt Line A from slot 0 PCI0
- *
- *32 Interrupt Line D from slot 3 PCI1
- *33 Interrupt Line C from slot 3 PCI1
- *34 Interrupt Line B from slot 3 PCI1
- *35 Interrupt Line A from slot 3 PCI1
- *36 Interrupt Line D from slot 2 PCI1
- *37 Interrupt Line C from slot 2 PCI1
- *38 Interrupt Line B from slot 2 PCI1
- *39 Interrupt Line A from slot 2 PCI1
- *40 Interrupt Line D from slot 1 PCI1
- *41 Interrupt Line C from slot 1 PCI1
- *42 Interrupt Line B from slot 1 PCI1
- *43 Interrupt Line A from slot 1 PCI1
- *44 Interrupt Line D from slot 0 PCI1
- *45 Interrupt Line C from slot 0 PCI1
- *46 Interrupt Line B from slot 0 PCI1
- *47 Interrupt Line A from slot 0 PCI1
- *48-52 Unused
- *53 PCI0 NMI (from Cypress)
- *54 PCI0 SMI INT (from Cypress)
- *55 PCI0 ISA Interrupt (from Cypress)
- *56-60 Unused
- *61 PCI1 Bus Error
- *62 PCI0 Bus Error
- *63 Reserved
- *
- * IdSel
- * 5 Cypress Bridge I/O
- * 6 SCSI Adaptec builtin
- * 7 64 bit PCI option slot 0
- * 8 64 bit PCI option slot 1
- * 9 64 bit PCI option slot 2
- *
- */
+ pcibios_read_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_PIN, &pin);
+ /* Cope with 0 and illegal. */
+ if (pin == 0 || pin > 4)
+ pin = 1;
-static inline void dp264_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { -1, -1, -1, -1, -1}, /* IdSel 5 ISA Bridge */
- { 16+ 2, 16+ 2, 16+ 2, 16+ 2, 16+ 2}, /* IdSel 6 SCSI builtin */
- { 16+15, 16+15, 16+14, 16+13, 16+12}, /* IdSel 7 slot 0 */
- { 16+11, 16+11, 16+10, 16+ 9, 16+ 8}, /* IdSel 8 slot 1 */
- { 16+ 7, 16+ 7, 16+ 6, 16+ 5, 16+ 4} /* IdSel 9 slot 2 */
- };
- common_fixup(5, 9, 5, irq_tab, 0);
- SMC669_Init();
-}
+ if (!DEV_IS_ON_PRIMARY(dev)) {
+ /* Follow the chain of bridges, swizzling as we go. */
-/*
- * Fixup configuration for RAWHIDE
- *
- * Summary @ MCPCIA_PCI0_INT_REQ:
- * Bit Meaning
- *0 Interrupt Line A from slot 2 PCI0
- *1 Interrupt Line B from slot 2 PCI0
- *2 Interrupt Line C from slot 2 PCI0
- *3 Interrupt Line D from slot 2 PCI0
- *4 Interrupt Line A from slot 3 PCI0
- *5 Interrupt Line B from slot 3 PCI0
- *6 Interrupt Line C from slot 3 PCI0
- *7 Interrupt Line D from slot 3 PCI0
- *8 Interrupt Line A from slot 4 PCI0
- *9 Interrupt Line B from slot 4 PCI0
- *10 Interrupt Line C from slot 4 PCI0
- *11 Interrupt Line D from slot 4 PCI0
- *12 Interrupt Line A from slot 5 PCI0
- *13 Interrupt Line B from slot 5 PCI0
- *14 Interrupt Line C from slot 5 PCI0
- *15 Interrupt Line D from slot 5 PCI0
- *16 EISA interrupt (PCI 0) or SCSI interrupt (PCI 1)
- *17-23 NA
- *
- * IdSel
- * 1 EISA bridge (PCI bus 0 only)
- * 2 PCI option slot 2
- * 3 PCI option slot 3
- * 4 PCI option slot 4
- * 5 PCI option slot 5
- *
- */
+ int spill = pin;
+ slot = (*swizzle)(dev, &spill);
+ pin = spill;
-static inline void rawhide_fixup(void)
-{
- static char irq_tab[5][5] __initlocaldata = {
- /*INT INTA INTB INTC INTD */
- { 16+16, 16+16, 16+16, 16+16, 16+16}, /* IdSel 1 SCSI PCI 1 only */
- { 16+ 0, 16+ 0, 16+ 1, 16+ 2, 16+ 3}, /* IdSel 2 slot 2 */
- { 16+ 4, 16+ 4, 16+ 5, 16+ 6, 16+ 7}, /* IdSel 3 slot 3 */
- { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11}, /* IdSel 4 slot 4 */
- { 16+12, 16+12, 16+13, 16+14, 16+15} /* IdSel 5 slot 5 */
- };
- common_fixup(1, 5, 5, irq_tab, 0);
-}
+ /* Must make sure that SRM didn't screw up
+ and allocate an address > 64K for I/O
+ space behind a PCI-PCI bridge. */
+ if (alpha_use_srm_setup)
+ check_behind_io(dev);
+ } else {
+ /* Just a device on a primary bus. */
+ slot = PCI_SLOT(dev->devfn);
+ }
-/*
- * The Takara has PCI devices 1, 2, and 3 configured to slots 20,
- * 19, and 18 respectively, in the default configuration. They can
- * also be jumpered to slots 8, 7, and 6 respectively, which is fun
- * because the SIO ISA bridge can also be slot 7. However, the SIO
- * doesn't explicitly generate PCI-type interrupts, so we can
- * assign it whatever the hell IRQ we like and it doesn't matter.
- */
-static inline void takara_fixup(void)
-{
- static char irq_tab[15][5] __initlocaldata = {
- { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */
- { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */
- { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */
- { -1, -1, -1, -1, -1}, /* slot 9 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 10 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 11 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 12 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 13 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 14 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 15 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 16 == nothing */
- { -1, -1, -1, -1, -1}, /* slot 17 == nothing */
- { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 18 == device 3 */
- { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 19 == device 2 */
- { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 20 == device 1 */
- };
- common_fixup(6, 20, 5, irq_tab, 0x26e);
-}
+ irq = (*map_irq)(dev, slot, pin);
-/*
- * Fixup configuration for all boards that route the PCI interrupts
- * through the SIO PCI/ISA bridge. This includes Noname (AXPpci33),
- * Avanti (AlphaStation) and Kenetics's Platform 2000.
- */
-static inline void sio_fixup(void)
-{
- struct pci_dev *dev;
- /*
- * The Noname board has 5 PCI slots with each of the 4
- * interrupt pins routed to different pins on the PCI/ISA
- * bridge (PIRQ0-PIRQ3). The table below is based on
- * information available at:
- *
- * http://ftp.digital.com/pub/DEC/axppci/ref_interrupts.txt
- *
- * I have no information on the Avanti interrupt routing, but
- * the routing seems to be identical to the Noname except
- * that the Avanti has an additional slot whose routing I'm
- * unsure of.
- *
- * pirq_tab[0] is a fake entry to deal with old PCI boards
- * that have the interrupt pin number hardwired to 0 (meaning
- * that they use the default INTA line, if they are interrupt
- * driven at all).
- */
- static const char pirq_tab[][5] __initlocaldata = {
- /*INT A B C D */
-#ifdef CONFIG_ALPHA_P2K
- { 0, 0, -1, -1, -1}, /* idsel 6 (53c810) */
- {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */
- { 1, 1, 2, 3, 0}, /* idsel 8 (slot A) */
- { 2, 2, 3, 0, 1}, /* idsel 9 (slot B) */
- {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
- {-1, -1, -1, -1, -1}, /* idsel 11 (unused) */
- { 3, 3, -1, -1, -1}, /* idsel 12 (CMD0646) */
-#else
- { 3, 3, 3, 3, 3}, /* idsel 6 (53c810) */
- {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */
- { 2, 2, -1, -1, -1}, /* idsel 8 (Noname hack: slot closest to ISA) */
- {-1, -1, -1, -1, -1}, /* idsel 9 (unused) */
- {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
- { 0, 0, 2, 1, 0}, /* idsel 11 KN25_PCI_SLOT0 */
- { 1, 1, 0, 2, 1}, /* idsel 12 KN25_PCI_SLOT1 */
- { 2, 2, 1, 0, 2}, /* idsel 13 KN25_PCI_SLOT2 */
- { 0, 0, 0, 0, 0}, /* idsel 14 AS255 TULIP */
-#endif
- };
- const size_t pirq_tab_len = sizeof(pirq_tab)/sizeof(pirq_tab[0]);
+ DBG_DEVS(("common_pci_fixup: bus %d slot %d "
+ "pin %d irq %d\n",
+ dev->bus->number, slot, pin, irq));
- /*
- * route_tab selects irq routing in PCI/ISA bridge so that:
- * PIRQ0 -> irq 15
- * PIRQ1 -> irq 9
- * PIRQ2 -> irq 10
- * PIRQ3 -> irq 11
- *
- * This probably ought to be configurable via MILO. For
- * example, sound boards seem to like using IRQ 9.
- */
+ if (irq != -1)
+ dev->irq = irq;
-#if defined(CONFIG_ALPHA_BOOK1)
- /* for the AlphaBook1, NCR810 SCSI is 14, PCMCIA controller is 15 */
- const unsigned int new_route_tab = 0x0e0f0a0a;
+ if (alpha_using_srm) {
+ /* Read the original SRM-set IRQ and tell. */
+ pcibios_read_config_byte(dev->bus->number,
+ dev->devfn,
+ PCI_INTERRUPT_LINE,
+ &irq_orig);
-#elif defined(CONFIG_ALPHA_NONAME)
- /*
- * For UDB, the only available PCI slot must not map to IRQ 9,
- * since that's the builtin MSS sound chip. That PCI slot
- * will map to PIRQ1 (for INTA at least), so we give it IRQ 15
- * instead.
- *
- * Unfortunately we have to do this for NONAME as well, since
- * they are co-indicated when the platform type "Noname" is
- * selected... :-(
- */
- const unsigned int new_route_tab = 0x0b0a0f09;
-#else
- const unsigned int new_route_tab = 0x0b0a090f;
-#endif
- unsigned int route_tab, old_route_tab;
- unsigned int level_bits, old_level_bits;
- unsigned char pin, slot;
- int pirq;
-
- pcibios_read_config_dword(0, PCI_DEVFN(7, 0), 0x60, &old_route_tab);
- DBG_DEVS(("sio_fixup: old pirq route table: 0x%08x\n",
- old_route_tab));
-#if PCI_MODIFY
- route_tab = new_route_tab;
- pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60, route_tab);
-#else
- route_tab = old_route_tab;
-#endif
+ if (irq_orig != dev->irq) {
+ struct reset_irq *r;
- /*
- * Go through all devices, fixing up irqs as we see fit:
- */
- level_bits = 0;
- for (dev = pci_devices; dev; dev = dev->next) {
- if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
- (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
- continue;
+ DBG_DEVS(("common_pci_fixup: bus %d "
+ "slot 0x%x SRM IRQ 0x%x "
+ "changed to 0x%x\n",
+ dev->bus->number,
+ PCI_SLOT(dev->devfn),
+ irq_orig, dev->irq));
- dev->irq = 0;
- if (dev->bus->number != 0) {
- struct pci_dev *curr = dev;
- /*
- * read the pin and do the PCI-PCI bridge
- * interrupt pin swizzle
- */
- pcibios_read_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_PIN, &pin);
- /* cope with 0 */
- if (pin == 0)
- pin = 1;
- /* follow the chain of bridges, swizzling as we go */
- do {
- /* swizzle */
- pin = bridge_swizzle(pin, PCI_SLOT(curr->devfn));
- /* move up the chain of bridges */
- curr = curr->bus->self;
- } while (curr->bus->self);
- /* The slot is the slot of the last bridge. */
- slot = PCI_SLOT(curr->devfn);
- } else {
- /* work out the slot */
- slot = PCI_SLOT(dev->devfn);
- /* read the pin */
- pcibios_read_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_PIN, &pin);
+ r = &srm_resets.irq[srm_resets.irq_count++];
+ r->dev = dev;
+ r->irq = irq_orig;
+ }
}
- if (slot < 6 || slot >= 6 + pirq_tab_len) {
- printk("bios32.sio_fixup: "
- "weird, found device %04x:%04x in"
- " non-existent slot %d!!\n",
- dev->vendor, dev->device, slot);
- continue;
- }
- pirq = pirq_tab[slot - 6][pin];
+ /* Always tell the device, so the driver knows what is
+ the real IRQ to use; the device does not use it. */
+ pcibios_write_config_byte(dev->bus->number, dev->devfn,
+ PCI_INTERRUPT_LINE, dev->irq);
+
+ DBG_DEVS(("common_pci_fixup: bus %d slot 0x%x"
+ " VID 0x%x DID 0x%x\n"
+ " int_slot 0x%x pin 0x%x"
+ " pirq 0x%x\n",
+ dev->bus->number, PCI_SLOT(dev->devfn),
+ dev->vendor, dev->device,
+ slot, pin, dev->irq));
- DBG_DEVS(("sio_fixup: bus %d slot 0x%x VID 0x%x DID 0x%x\n"
- " int_slot 0x%x pin 0x%x pirq 0x%x\n",
- dev->bus->number, PCI_SLOT(dev->devfn), dev->vendor,
- dev->device, slot, pin, pirq));
/*
- * if it's a VGA, enable its BIOS ROM at C0000
+ * If it's a VGA, enable its BIOS ROM at C0000.
*/
if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
- /* but if its a Cirrus 543x/544x DISABLE it, */
- /* since enabling ROM disables the memory... */
+ /* But if its a Cirrus 543x/544x DISABLE it,
+ since enabling ROM disables the memory... */
if ((dev->vendor == PCI_VENDOR_ID_CIRRUS) &&
(dev->device >= 0x00a0) &&
(dev->device <= 0x00ac)) {
@@ -1836,408 +964,37 @@ static inline void sio_fixup(void)
} else {
pcibios_write_config_dword(
dev->bus->number,
- dev->devfn,
- PCI_ROM_ADDRESS,
- 0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
- }
- }
- if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
- continue; /* for now, displays get no IRQ */
- }
-
- if (pirq < 0) {
- DBG_DEVS(("bios32.sio_fixup: "
- "weird, device %04x:%04x coming in on"
- " slot %d has no irq line!!\n",
- dev->vendor, dev->device, slot));
- continue;
- }
-
- dev->irq = (route_tab >> (8 * pirq)) & 0xff;
-
-#ifndef CONFIG_ALPHA_BOOK1
- /* do not set *ANY* level triggers for AlphaBook1 */
- /* must set the PCI IRQs to level triggered */
- level_bits |= (1 << dev->irq);
-#endif /* !CONFIG_ALPHA_BOOK1 */
-
-#if PCI_MODIFY
- /* tell the device: */
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_LINE, dev->irq);
-#endif
-
-#ifdef CONFIG_ALPHA_BOOK1
- /*
- * On the AlphaBook1, the PCMCIA chip (Cirrus 6729)
- * is sensitive to PCI bus bursts, so we must DISABLE
- * burst mode for the NCR 8xx SCSI... :-(
- *
- * Note that the NCR810 SCSI driver must preserve the
- * setting of the bit in order for this to work. At the
- * moment (2.0.29), ncr53c8xx.c does NOT do this, but
- * 53c7,8xx.c DOES.
- */
- if (dev->vendor == PCI_VENDOR_ID_NCR &&
- (dev->device == PCI_DEVICE_ID_NCR_53C810 ||
- dev->device == PCI_DEVICE_ID_NCR_53C815 ||
- dev->device == PCI_DEVICE_ID_NCR_53C820 ||
- dev->device == PCI_DEVICE_ID_NCR_53C825)) {
- unsigned int io_port;
- unsigned char ctest4;
-
- pcibios_read_config_dword(dev->bus->number,
- dev->devfn,
- PCI_BASE_ADDRESS_0,
- &io_port);
- io_port &= PCI_BASE_ADDRESS_IO_MASK;
- ctest4 = inb(io_port+0x21);
- if (!(ctest4 & 0x80)) {
- printk("AlphaBook1 NCR init: setting"
- " burst disable\n");
- outb(ctest4 | 0x80, io_port+0x21);
+ dev->devfn,
+ PCI_ROM_ADDRESS,
+ 0x000c0000 | PCI_ROM_ADDRESS_ENABLE);
}
- }
-#endif /* CONFIG_ALPHA_BOOK1 */
- } /* end for-devs */
-
- /*
- * Now, make all PCI interrupts level sensitive. Notice:
- * these registers must be accessed byte-wise. inw()/outw()
- * don't work.
- *
- * Make sure to turn off any level bits set for IRQs 9,10,11,15,
- * so that the only bits getting set are for devices actually found.
- * Note that we do preserve the remainder of the bits, which we hope
- * will be set correctly by ARC/SRM.
- *
- * Note: we at least preserve any level-set bits on AlphaBook1
- */
- old_level_bits = inb(0x4d0) | (inb(0x4d1) << 8);
- DBG_DEVS(("sio_fixup: old irq level bits: 0x%04x\n",
- old_level_bits));
- level_bits |= (old_level_bits & 0x71ff);
- DBG_DEVS(("sio_fixup: new irq level bits: 0x%04x\n",
- level_bits));
- outb((level_bits >> 0) & 0xff, 0x4d0);
- outb((level_bits >> 8) & 0xff, 0x4d1);
-
-#ifdef CONFIG_ALPHA_BOOK1
- {
- unsigned char orig, config;
- /* On the AlphaBook1, make sure that register PR1
- indicates 1Mb mem */
- outb(0x0f, 0x3ce); orig = inb(0x3cf); /* read PR5 */
- outb(0x0f, 0x3ce); outb(0x05, 0x3cf); /* unlock PR0-4 */
- outb(0x0b, 0x3ce); config = inb(0x3cf); /* read PR1 */
- if ((config & 0xc0) != 0xc0) {
- printk("AlphaBook1 VGA init: setting 1Mb memory\n");
- config |= 0xc0;
- outb(0x0b, 0x3ce); outb(config, 0x3cf); /* write PR1 */
}
- outb(0x0f, 0x3ce); outb(orig, 0x3cf); /* (re)lock PR0-4 */
- }
-#endif /* CONFIG_ALPHA_BOOK1 */
-
-#ifndef CONFIG_ALPHA_BOOK1
- /* Do not do IDE init for AlphaBook1 */
- enable_ide(0x26e);
-#endif
-}
-
-
-#ifdef CONFIG_TGA_CONSOLE
-extern void tga_console_init(void);
-#endif /* CONFIG_TGA_CONSOLE */
-
-void __init
-pcibios_fixup(void)
-{
- struct pci_bus *cur;
-
-#ifdef CONFIG_ALPHA_MCPCIA
- /* must do massive setup for multiple PCI busses here... */
- DBG_DEVS(("pcibios_fixup: calling mcpcia_fixup()...\n"));
- mcpcia_fixup();
-#endif /* MCPCIA */
-
-#ifdef CONFIG_ALPHA_TSUNAMI
- /* must do massive setup for multiple PCI busses here... */
- /* tsunami_fixup(); */
-#endif /* TSUNAMI */
-
-#if PCI_MODIFY && !defined(CONFIG_ALPHA_RUFFIAN)
- /*
- * Scan the tree, allocating PCI memory and I/O space.
- */
- /*
- * Sigh; check_region() will need changing to accept a HANDLE,
- * if we allocate I/O space addresses on a per-bus basis.
- * For now, make the I/O bases unique across all busses, so
- * that check_region() will not get confused... ;-}
- */
- io_base = DEFAULT_IO_BASE;
- for (cur = &pci_root; cur; cur = cur->next) {
- mem_base = DEFAULT_MEM_BASE;
- DBG_DEVS(("pcibios_fixup: calling layout_bus()\n"));
- layout_bus(cur);
- }
-#endif
-
- /*
- * Now is the time to do all those dirty little deeds...
- */
-#if defined(CONFIG_ALPHA_NONAME) || defined(CONFIG_ALPHA_AVANTI) || \
- defined(CONFIG_ALPHA_P2K)
- sio_fixup();
-#elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB164)
- cabriolet_fixup();
-#elif defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164)
- alphapc164_fixup();
-#elif defined(CONFIG_ALPHA_EB66P)
- eb66p_fixup();
-#elif defined(CONFIG_ALPHA_EB66)
- eb66_and_eb64p_fixup();
-#elif defined(CONFIG_ALPHA_EB64P)
- eb66_and_eb64p_fixup();
-#elif defined(CONFIG_ALPHA_MIKASA)
- mikasa_fixup();
-#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
- alcor_fixup();
-#elif defined(CONFIG_ALPHA_SABLE)
- sable_fixup();
-#elif defined(CONFIG_ALPHA_MIATA)
- miata_fixup();
-#elif defined(CONFIG_ALPHA_NORITAKE)
- noritake_fixup();
-#elif defined(CONFIG_ALPHA_SX164)
- sx164_fixup();
-#elif defined(CONFIG_ALPHA_DP264)
- dp264_fixup();
-#elif defined(CONFIG_ALPHA_RAWHIDE)
- rawhide_fixup();
-#elif defined(CONFIG_ALPHA_TAKARA)
- takara_fixup();
-#elif defined(CONFIG_ALPHA_RUFFIAN)
- /* no fixup needed */
-#else
-# error "You must tell me what kind of platform you want."
-#endif
-
-#ifndef CONFIG_ABSTRACT_CONSOLE
-#ifdef CONFIG_TGA_CONSOLE
- tga_console_init();
-#endif
-#endif
-}
-
-
-asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- unsigned char *buf)
-{
- unsigned char ubyte;
- unsigned short ushort;
- unsigned int uint;
- long err = 0;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- lock_kernel();
- switch (len) {
- case 1:
- err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
- if (err != PCIBIOS_SUCCESSFUL)
- ubyte = 0xff;
- put_user(ubyte, buf);
- break;
- case 2:
- err = pcibios_read_config_word(bus, dfn, off, &ushort);
- if (err != PCIBIOS_SUCCESSFUL)
- ushort = 0xffff;
- put_user(ushort, (unsigned short *)buf);
- break;
- case 4:
- err = pcibios_read_config_dword(bus, dfn, off, &uint);
- if (err != PCIBIOS_SUCCESSFUL)
- uint = 0xffffffff;
- put_user(uint, (unsigned int *)buf);
- break;
- default:
- err = -EINVAL;
- break;
- }
- unlock_kernel();
- return err;
-}
-
-
-asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn,
- unsigned long off, unsigned long len,
- unsigned char *buf)
-{
- unsigned char ubyte;
- unsigned short ushort;
- unsigned int uint;
- long err = 0;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- lock_kernel();
- switch (len) {
- case 1:
- err = get_user(ubyte, buf);
- if (err)
- break;
- err = pcibios_write_config_byte(bus, dfn, off, ubyte);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
- }
- break;
- case 2:
- err = get_user(ushort, (unsigned short *)buf);
- if (err)
- break;
- err = pcibios_write_config_word(bus, dfn, off, ushort);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
- }
- break;
- case 4:
- err = get_user(uint, (unsigned int *)buf);
- if (err)
- break;
- err = pcibios_write_config_dword(bus, dfn, off, uint);
- if (err != PCIBIOS_SUCCESSFUL) {
- err = -EFAULT;
+ /*
+ * If it's a SCSI, disable its BIOS ROM.
+ */
+ if ((dev->class >> 8) == PCI_CLASS_STORAGE_SCSI) {
+ pcibios_write_config_dword(dev->bus->number,
+ dev->devfn,
+ PCI_ROM_ADDRESS,
+ 0x0000000);
}
- break;
- default:
- err = -EINVAL;
- break;
}
- unlock_kernel();
- return err;
}
-#if (defined(CONFIG_ALPHA_PC164) || \
- defined(CONFIG_ALPHA_LX164) || \
- defined(CONFIG_ALPHA_SX164) || \
- defined(CONFIG_ALPHA_EB164) || \
- defined(CONFIG_ALPHA_EB66P) || \
- defined(CONFIG_ALPHA_CABRIOLET)) && defined(CONFIG_ALPHA_SRM)
+/* Most Alphas have straight-forward swizzling needs. */
-/*
- on the above machines, under SRM console, we must use the CSERVE PALcode
- routine to manage the interrupt mask for us, otherwise, the kernel/HW get
- out of sync with what the PALcode thinks it needs to deliver/ignore
- */
-void
-cserve_update_hw(unsigned long irq, unsigned long mask)
+int __init
+common_swizzle(struct pci_dev *dev, int *pinp)
{
- extern void cserve_ena(unsigned long);
- extern void cserve_dis(unsigned long);
-
- if (mask & (1UL << irq))
- /* disable */
- cserve_dis(irq - 16);
- else
- /* enable */
- cserve_ena(irq - 16);
- return;
-}
-#endif /* (PC164 || LX164 || SX164 || EB164 || CABRIO) && SRM */
+ int pin = *pinp;
+ do {
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ } while (dev->bus->self);
+ *pinp = pin;
-#ifdef CONFIG_ALPHA_MIATA
-/*
- * Init the built-in ES1888 sound chip (SB16 compatible)
- */
-static int __init
-es1888_init(void)
-{
- /* Sequence of IO reads to init the audio controller */
- inb(0x0229);
- inb(0x0229);
- inb(0x0229);
- inb(0x022b);
- inb(0x0229);
- inb(0x022b);
- inb(0x0229);
- inb(0x0229);
- inb(0x022b);
- inb(0x0229);
- inb(0x0220); /* This sets the base address to 0x220 */
-
- /* Sequence to set DMA channels */
- outb(0x01, 0x0226); /* reset */
- inb(0x0226); /* pause */
- outb(0x00, 0x0226); /* release reset */
- while (!(inb(0x022e) & 0x80)) /* wait for bit 7 to assert*/
- continue;
- inb(0x022a); /* pause */
- outb(0xc6, 0x022c); /* enable extended mode */
- while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
- continue;
- outb(0xb1, 0x022c); /* setup for write to Interrupt CR */
- while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
- continue;
- outb(0x14, 0x022c); /* set IRQ 5 */
- while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
- continue;
- outb(0xb2, 0x022c); /* setup for write to DMA CR */
- while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
- continue;
- outb(0x18, 0x022c); /* set DMA channel 1 */
-
- return 0;
+ /* The slot is the slot of the last bridge. */
+ return PCI_SLOT(dev->devfn);
}
-#endif /* CONFIG_ALPHA_MIATA */
-
-__initfunc(char *pcibios_setup(char *str))
-{
- return str;
-}
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-void reset_for_srm(void)
-{
- extern void scrreset(void);
- struct pci_dev *dev;
- int i;
-
- /* reset any IRQs that we changed */
- for (i = 0; i < irq_reset_count; i++) {
- dev = irq_dev_to_reset[i];
-
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- PCI_INTERRUPT_LINE, irq_to_reset[i]);
-#if 1
- printk("reset_for_srm: bus %d slot 0x%x "
- "SRM IRQ 0x%x changed back from 0x%x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- irq_to_reset[i], dev->irq);
-#endif
- }
-
- /* reset any IO addresses that we changed */
- for (i = 0; i < io_reset_count; i++) {
- dev = io_dev_to_reset[i];
-
- pcibios_write_config_byte(dev->bus->number, dev->devfn,
- io_reg_to_reset[i], io_to_reset[i]);
-#if 1
- printk("reset_for_srm: bus %d slot 0x%x "
- "SRM IO restored to 0x%x\n",
- dev->bus->number, PCI_SLOT(dev->devfn),
- io_to_reset[i]);
-#endif
-}
-
- /* reset the visible screen to the top of display memory */
- scrreset();
-}
-#endif /* CONFIG_ALPHA_SRM_SETUP */
-
#endif /* CONFIG_PCI */
diff --git a/arch/alpha/kernel/bios32.h b/arch/alpha/kernel/bios32.h
new file mode 100644
index 000000000..9a3184fe5
--- /dev/null
+++ b/arch/alpha/kernel/bios32.h
@@ -0,0 +1,155 @@
+/*
+ * linux/arch/alpha/kernel/bios32.h
+ *
+ * This file contains declarations and inline functions for interfacing
+ * with the PCI initialization routines in bios32.c.
+ */
+
+
+#define KB 1024
+#define MB (1024*KB)
+#define GB (1024*MB)
+
+/*
+ * We can't just blindly use 64K for machines with EISA busses; they
+ * may also have PCI-PCI bridges present, and then we'd configure the
+ * bridge incorrectly.
+ *
+ * Also, we start at 0x8000 or 0x9000, in hopes to get all devices'
+ * IO space areas allocated *before* 0xC000; this is because certain
+ * BIOSes (Millennium for one) use PCI Config space "mechanism #2"
+ * accesses to probe the bus. If a device's registers appear at 0xC000,
+ * it may see an INx/OUTx at that address during BIOS emulation of the
+ * VGA BIOS, and some cards, notably Adaptec 2940UW, take mortal offense.
+ *
+ * Note that we may need this stuff for SRM_SETUP also, since certain
+ * SRM consoles screw up and allocate I/O space addresses > 64K behind
+ * PCI-to_PCI bridges, which can't pass I/O addresses larger than 64K,
+ * AFAIK.
+ */
+
+#define EISA_DEFAULT_IO_BASE 0x9000 /* start above 8th slot */
+#define DEFAULT_IO_BASE 0x8000 /* start at 8th slot */
+
+/*
+ * An XL is AVANTI (APECS) family, *but* it has only 27 bits of ISA address
+ * that get passed through the PCI<->ISA bridge chip. Although this causes
+ * us to set the PCI->Mem window bases lower than normal, we still allocate
+ * PCI bus devices' memory addresses *below* the low DMA mapping window,
+ * and hope they fit below 64Mb (to avoid conflicts), and so that they can
+ * be accessed via SPARSE space.
+ *
+ * We accept the risk that a broken Myrinet card will be put into a true XL
+ * and thus can more easily run into the problem described below.
+ */
+#define XL_DEFAULT_MEM_BASE (16*MB + 2*MB) /* 16M to 64M-1 is avail */
+
+/*
+ * We try to make this address *always* have more than 1 bit set.
+ * this is so that devices like the broken Myrinet card will always have
+ * a PCI memory address that will never match a IDSEL address in
+ * PCI Config space, which can cause problems with early rev cards.
+ *
+ * However, APECS and LCA have only 34 bits for physical addresses, thus
+ * limiting PCI bus memory addresses for SPARSE access to be less than 128Mb.
+ */
+#define APECS_AND_LCA_DEFAULT_MEM_BASE (64*MB + 2*MB)
+
+/*
+ * We try to make this address *always* have more than 1 bit set.
+ * this is so that devices like the broken Myrinet card will always have
+ * a PCI memory address that will never match a IDSEL address in
+ * PCI Config space, which can cause problems with early rev cards.
+ *
+ * Because CIA and PYXIS and T2 have more bits for physical addresses,
+ * they support an expanded range of SPARSE memory addresses.
+ */
+#define DEFAULT_MEM_BASE (128*MB + 16*MB)
+
+
+/*
+ * PCI_MODIFY
+ *
+ * If this 0, then do not write to any of the PCI registers, merely
+ * read them (i.e., use configuration as determined by SRM). The SRM
+ * seem do be doing a less than perfect job in configuring PCI
+ * devices, so for now we do it ourselves. Reconfiguring PCI devices
+ * breaks console (RPB) callbacks, but those don't work properly with
+ * 64 bit addresses anyways.
+ *
+ * The accepted convention seems to be that the console (POST
+ * software) should fully configure boot devices and configure the
+ * interrupt routing of *all* devices. In particular, the base
+ * addresses of non-boot devices need not be initialized. For
+ * example, on the AXPpci33 board, the base address a #9 GXE PCI
+ * graphics card reads as zero (this may, however, be due to a bug in
+ * the graphics card---there have been some rumor that the #9 BIOS
+ * incorrectly resets that address to 0...).
+ */
+
+#define PCI_MODIFY (!alpha_use_srm_setup)
+
+
+/*
+ * A small note about bridges and interrupts. The DECchip 21050 (and
+ * later) adheres to the PCI-PCI bridge specification. This says that
+ * the interrupts on the other side of a bridge are swizzled in the
+ * following manner:
+ *
+ * Dev Interrupt Interrupt
+ * Pin on Pin on
+ * Device Connector
+ *
+ * 4 A A
+ * B B
+ * C C
+ * D D
+ *
+ * 5 A B
+ * B C
+ * C D
+ * D A
+ *
+ * 6 A C
+ * B D
+ * C A
+ * D B
+ *
+ * 7 A D
+ * B A
+ * C B
+ * D C
+ *
+ * Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
+ * Thus, each swizzle is ((pin-1) + (device#-4)) % 4
+ *
+ * The following code swizzles for exactly one bridge. The routine
+ * common_swizzle below handles multiple bridges. But there are a
+ * couple boards that do strange things, so we define this here.
+ */
+
+static inline unsigned char
+bridge_swizzle(unsigned char pin, unsigned int slot)
+{
+ return (((pin-1) + slot) % 4) + 1;
+}
+
+extern void layout_all_busses(unsigned long io_base, unsigned long mem_base);
+extern void enable_ide(long ide_base);
+
+struct pci_dev;
+
+extern void
+common_pci_fixup(int (*map_irq)(struct pci_dev *dev, int slot, int pin),
+ int (*swizzle)(struct pci_dev *dev, int *pin));
+
+extern int common_swizzle(struct pci_dev *dev, int *pinp);
+
+/* The following macro is used to implement the table-based irq mapping
+ function for all single-bus Alphas. */
+
+#define COMMON_TABLE_LOOKUP \
+({ long _ctl_ = -1; \
+ if (slot >= min_idsel && slot <= max_idsel && pin < irqs_per_slot) \
+ _ctl_ = irq_tab[slot - min_idsel][pin]; \
+ _ctl_; })
diff --git a/arch/alpha/kernel/apecs.c b/arch/alpha/kernel/core_apecs.c
index 2bbdf0062..d2633bef1 100644
--- a/arch/alpha/kernel/apecs.c
+++ b/arch/alpha/kernel/core_apecs.c
@@ -1,5 +1,7 @@
/*
- * Code common to all APECS chips.
+ * linux/arch/alpha/kernel/core_apecs.c
+ *
+ * Code common to all APECS core logic chips.
*
* Rewritten for Apecs from the lca.c from:
*
@@ -11,21 +13,24 @@
#include <linux/config.h>
#include <linux/types.h>
#include <linux/pci.h>
+#include <linux/init.h>
#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/hwrpb.h>
#include <asm/ptrace.h>
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_apecs.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+
/*
* NOTE: Herein lie back-to-back mb instructions. They are magic.
* One plausible explanation is that the i/o controller does not properly
* handle the system transaction. Another involves timing. Ho hum.
*/
-extern struct hwrpb_struct *hwrpb;
-extern asmlinkage void wrmces(unsigned long mces);
-
/*
* BIOS32-style PCI interface:
*/
@@ -38,14 +43,10 @@ extern asmlinkage void wrmces(unsigned long mces);
#define vuip volatile unsigned int *
-static volatile unsigned int apecs_mcheck_expected = 0;
-static volatile unsigned int apecs_mcheck_taken = 0;
+volatile unsigned int apecs_mcheck_expected = 0;
+volatile unsigned int apecs_mcheck_taken = 0;
static unsigned int apecs_jd, apecs_jd1, apecs_jd2;
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int APECS_DMA_WIN_BASE = APECS_DMA_WIN_BASE_DEFAULT;
-unsigned int APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT;
-#endif /* SRM_SETUP */
/*
* Given a bus, device, and function number, compute resulting
@@ -82,15 +83,16 @@ unsigned int APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT;
*
* Notes:
* The function number selects which function of a multi-function device
- * (e.g., scsi and ethernet).
+ * (e.g., SCSI and Ethernet).
*
* The register selects a DWORD (32 bit) register offset. Hence it
* doesn't get shifted by 2 bits as we want to "drop" the bottom two
* bits.
*/
-static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned long *pci_addr,
- unsigned char *type1)
+
+static int
+mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+ unsigned char *type1)
{
unsigned long addr;
@@ -121,40 +123,25 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
return 0;
}
-
-static unsigned int conf_read(unsigned long addr, unsigned char type1)
+static unsigned int
+conf_read(unsigned long addr, unsigned char type1)
{
unsigned long flags;
unsigned int stat0, value;
- unsigned int haxr2 = 0; /* to keep gcc quiet */
-
-#ifdef CONFIG_ALPHA_SRM
- /* some SRMs step on these registers during a machine check: */
- register long s0 asm ("9");
- register long s1 asm ("10");
- register long s2 asm ("11");
- register long s3 asm ("12");
- register long s4 asm ("13");
- register long s5 asm ("14");
- asm volatile ("# %0" : "r="(s0));
- asm volatile ("# %0" : "r="(s1));
- asm volatile ("# %0" : "r="(s2));
- asm volatile ("# %0" : "r="(s3));
- asm volatile ("# %0" : "r="(s4));
- asm volatile ("# %0" : "r="(s5));
-#endif
+ unsigned int haxr2 = 0;
save_flags(flags); /* avoid getting hit by machine check */
cli();
DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
- /* reset status register to avoid losing errors: */
+ /* Reset status register to avoid losing errors. */
stat0 = *(vuip)APECS_IOC_DCSR;
*(vuip)APECS_IOC_DCSR = stat0;
mb();
DBG(("conf_read: APECS DCSR was 0x%x\n", stat0));
- /* if Type1 access, must set HAE #2 */
+
+ /* If Type1 access, must set HAE #2. */
if (type1) {
haxr2 = *(vuip)APECS_IOC_HAXR2;
mb();
@@ -166,10 +153,13 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
apecs_mcheck_expected = 1;
apecs_mcheck_taken = 0;
mb();
- /* access configuration space: */
- value = *(vuip)addr;
- mb();
- mb(); /* magic */
+
+ /* Access configuration space. */
+
+ /* Some SRMs step on these registers during a machine check. */
+ asm volatile("ldl %0,%1; mb; mb" : "=r"(value) : "m"(*(vuip)addr)
+ : "$9", "$10", "$11", "$12", "$13", "$14", "memory");
+
if (apecs_mcheck_taken) {
apecs_mcheck_taken = 0;
value = 0xffffffffU;
@@ -187,16 +177,18 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
*/
draina();
- /* now look for any errors */
+ /* Now look for any errors. */
stat0 = *(vuip)APECS_IOC_DCSR;
DBG(("conf_read: APECS DCSR after read 0x%x\n", stat0));
- if (stat0 & 0xffe0U) { /* is any error bit set? */
- /* if not NDEV, print status */
+
+ /* Is any error bit set? */
+ if (stat0 & 0xffe0U) {
+ /* If not NDEV, print status. */
if (!(stat0 & 0x0800)) {
printk("apecs.c:conf_read: got stat0=%x\n", stat0);
}
- /* reset error status: */
+ /* Reset error status. */
*(vuip)APECS_IOC_DCSR = stat0;
mb();
wrmces(0x7); /* reset machine check */
@@ -204,40 +196,32 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
}
#endif
- /* if Type1 access, must reset HAE #2 so normal IO space ops work */
+ /* If Type1 access, must reset HAE #2 so normal IO space ops work. */
if (type1) {
*(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
mb();
}
restore_flags(flags);
-#ifdef CONFIG_ALPHA_SRM
- /* some SRMs step on these registers during a machine check: */
- asm volatile ("# %0" :: "r"(s0));
- asm volatile ("# %0" :: "r"(s1));
- asm volatile ("# %0" :: "r"(s2));
- asm volatile ("# %0" :: "r"(s3));
- asm volatile ("# %0" :: "r"(s4));
- asm volatile ("# %0" :: "r"(s5));
-#endif
+
return value;
}
-
-static void conf_write(unsigned long addr, unsigned int value, unsigned char type1)
+static void
+conf_write(unsigned long addr, unsigned int value, unsigned char type1)
{
unsigned long flags;
unsigned int stat0;
- unsigned int haxr2 = 0; /* to keep gcc quiet */
+ unsigned int haxr2 = 0;
save_flags(flags); /* avoid getting hit by machine check */
cli();
- /* reset status register to avoid losing errors: */
+ /* Reset status register to avoid losing errors. */
stat0 = *(vuip)APECS_IOC_DCSR;
*(vuip)APECS_IOC_DCSR = stat0;
mb();
- /* if Type1 access, must set HAE #2 */
+ /* If Type1 access, must set HAE #2. */
if (type1) {
haxr2 = *(vuip)APECS_IOC_HAXR2;
mb();
@@ -247,7 +231,8 @@ static void conf_write(unsigned long addr, unsigned int value, unsigned char typ
draina();
apecs_mcheck_expected = 1;
mb();
- /* access configuration space: */
+
+ /* Access configuration space. */
*(vuip)addr = value;
mb();
mb(); /* magic */
@@ -263,22 +248,24 @@ static void conf_write(unsigned long addr, unsigned int value, unsigned char typ
*/
draina();
- /* now look for any errors */
+ /* Now look for any errors. */
stat0 = *(vuip)APECS_IOC_DCSR;
- if (stat0 & 0xffe0U) { /* is any error bit set? */
- /* if not NDEV, print status */
+
+ /* Is any error bit set? */
+ if (stat0 & 0xffe0U) {
+ /* If not NDEV, print status. */
if (!(stat0 & 0x0800)) {
printk("apecs.c:conf_write: got stat0=%x\n", stat0);
}
- /* reset error status: */
+ /* Reset error status. */
*(vuip)APECS_IOC_DCSR = stat0;
mb();
wrmces(0x7); /* reset machine check */
}
#endif
- /* if Type1 access, must reset HAE #2 so normal IO space ops work */
+ /* If Type1 access, must reset HAE #2 so normal IO space ops work. */
if (type1) {
*(vuip)APECS_IOC_HAXR2 = haxr2 & ~1;
mb();
@@ -286,9 +273,8 @@ static void conf_write(unsigned long addr, unsigned int value, unsigned char typ
restore_flags(flags);
}
-
-int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
+int
+apecs_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value)
{
unsigned long addr = APECS_CONF;
unsigned long pci_addr;
@@ -296,9 +282,8 @@ int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
*value = 0xff;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
addr |= (pci_addr << 5) + 0x00;
@@ -307,9 +292,8 @@ int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short *value)
+int
+apecs_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value)
{
unsigned long addr = APECS_CONF;
unsigned long pci_addr;
@@ -317,13 +301,10 @@ int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
*value = 0xffff;
- if (where & 0x1) {
+ if (where & 0x1)
return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
addr |= (pci_addr << 5) + 0x08;
@@ -331,195 +312,138 @@ int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int *value)
+int
+apecs_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value)
{
unsigned long addr = APECS_CONF;
unsigned long pci_addr;
unsigned char type1;
*value = 0xffffffff;
- if (where & 0x3) {
+ if (where & 0x3)
return PCIBIOS_BAD_REGISTER_NUMBER;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
addr |= (pci_addr << 5) + 0x18;
*value = conf_read(addr, type1);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char value)
+int
+apecs_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value)
{
unsigned long addr = APECS_CONF;
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x00;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short value)
+int
+apecs_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value)
{
unsigned long addr = APECS_CONF;
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x08;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int value)
+int
+apecs_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value)
{
unsigned long addr = APECS_CONF;
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x18;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-
-unsigned long apecs_init(unsigned long mem_start, unsigned long mem_end)
+void __init
+apecs_init_arch(unsigned long *mem_start, unsigned long *mem_end)
{
-
-#ifdef CONFIG_ALPHA_XL
- /*
- * Set up the PCI->physical memory translation windows.
- * For the XL we *must* use both windows, in order to
- * maximize the amount of physical memory that can be used
- * to DMA from the ISA bus, and still allow PCI bus devices
- * access to all of host memory.
- *
- * see <asm/apecs.h> for window bases and sizes.
- *
- * this restriction due to the true XL motherboards' 82379AB SIO
- * PCI<->ISA bridge chip which passes only 27 bits of address...
- */
-
- *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_XL_DMA_WIN1_BASE & 0xfff00000U);
- *(vuip)APECS_IOC_PM1R = (APECS_XL_DMA_WIN1_SIZE - 1) & 0xfff00000U;
- *(vuip)APECS_IOC_TB1R = 0;
-
- *(vuip)APECS_IOC_PB2R = 1U<<19 | (APECS_XL_DMA_WIN2_BASE & 0xfff00000U);
- *(vuip)APECS_IOC_PM2R = (APECS_XL_DMA_WIN2_SIZE - 1) & 0xfff00000U;
- *(vuip)APECS_IOC_TB2R = 0;
-
-#else /* CONFIG_ALPHA_XL */
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 1 for enabled and mapped to 0 */
- if ((*(vuip)APECS_IOC_PB1R & (1U<<19)) && (*(vuip)APECS_IOC_TB1R == 0))
+ switch (alpha_use_srm_setup)
{
- APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB1R & 0xfff00000U;
- APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM1R & 0xfff00000U;
- APECS_DMA_WIN_SIZE += 0x00100000U;
-#if 0
- printk("apecs_init: using Window 1 settings\n");
- printk("apecs_init: PB1R 0x%x PM1R 0x%x TB1R 0x%x\n",
- *(vuip)APECS_IOC_PB1R,
- *(vuip)APECS_IOC_PM1R,
- *(vuip)APECS_IOC_TB1R);
-#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if ((*(vuip)APECS_IOC_PB2R & (1U<<19)) && (*(vuip)APECS_IOC_TB2R == 0))
- {
- APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB2R & 0xfff00000U;
- APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM2R & 0xfff00000U;
- APECS_DMA_WIN_SIZE += 0x00100000U;
-#if 0
- printk("apecs_init: using Window 2 settings\n");
- printk("apecs_init: PB2R 0x%x PM2R 0x%x TB2R 0x%x\n",
- *(vuip)APECS_IOC_PB2R,
- *(vuip)APECS_IOC_PM2R,
- *(vuip)APECS_IOC_TB2R);
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 1 for enabled and mapped to 0. */
+ if ((*(vuip)APECS_IOC_PB1R & (1U<<19))
+ && (*(vuip)APECS_IOC_TB1R == 0)) {
+ APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB1R & 0xfff00000U;
+ APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM1R & 0xfff00000U;
+ APECS_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("apecs_init: using Window 1 settings\n");
+ printk("apecs_init: PB1R 0x%x PM1R 0x%x TB1R 0x%x\n",
+ *(vuip)APECS_IOC_PB1R,
+ *(vuip)APECS_IOC_PM1R,
+ *(vuip)APECS_IOC_TB1R);
#endif
- }
- else /* we must use our defaults... */
-#endif /* SRM_SETUP */
- {
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, window 2 is disabled. In the future, we may
- * want to use it to do scatter/gather DMA. Window 1
- * goes at 1 GB and is 1 GB large.
- */
- *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */
+ break;
+ }
- *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_DMA_WIN_BASE & 0xfff00000U);
- *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE - 1) & 0xfff00000U;
- *(vuip)APECS_IOC_TB1R = 0;
+ /* Check window 2 for enabled and mapped to 0. */
+ if ((*(vuip)APECS_IOC_PB2R & (1U<<19))
+ && (*(vuip)APECS_IOC_TB2R == 0)) {
+ APECS_DMA_WIN_BASE = *(vuip)APECS_IOC_PB2R & 0xfff00000U;
+ APECS_DMA_WIN_SIZE = *(vuip)APECS_IOC_PM2R & 0xfff00000U;
+ APECS_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("apecs_init: using Window 2 settings\n");
+ printk("apecs_init: PB2R 0x%x PM2R 0x%x TB2R 0x%x\n",
+ *(vuip)APECS_IOC_PB2R,
+ *(vuip)APECS_IOC_PM2R,
+ *(vuip)APECS_IOC_TB2R);
+#endif
+ break;
+ }
+
+ /* Otherwise, we must use our defaults. */
+ APECS_DMA_WIN_BASE = APECS_DMA_WIN_BASE_DEFAULT;
+ APECS_DMA_WIN_SIZE = APECS_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, window 2 is disabled. In the future, we may
+ * want to use it to do scatter/gather DMA. Window 1
+ * goes at 1 GB and is 1 GB large.
+ */
+ *(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */
+
+ *(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
+ *(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
+ *(vuip)APECS_IOC_TB1R = 0;
+ break;
}
-#endif /* CONFIG_ALPHA_XL */
-#ifdef CONFIG_ALPHA_CABRIOLET
-#ifdef NO_LONGER_NEEDED_I_HOPE
/*
- * JAE: HACK!!! for now, hardwire if configured...
- * davidm: Older miniloader versions don't set the clock frequency
- * right, so hardcode it for now.
+ * Finally, clear the HAXR2 register, which gets used
+ * for PCI Config Space accesses. That is the way
+ * we want to use it, and we do not want to depend on
+ * what ARC or SRM might have left behind...
*/
- if (hwrpb->sys_type == ST_DEC_EB64P) {
- hwrpb->sys_type = ST_DEC_EBPC64;
- }
- if (hwrpb->cycle_freq == 0) {
- hwrpb->cycle_freq = 275000000;
- }
-
- /* update checksum: */
- {
- unsigned long *l, sum;
-
- sum = 0;
- for (l = (unsigned long *) hwrpb;
- l < (unsigned long *) &hwrpb->chksum;
- ++l)
- sum += *l;
- hwrpb->chksum = sum;
- }
-#endif /* NO_LONGER_NEEDED_I_HOPE */
-#endif /* CONFIG_ALPHA_CABRIOLET */
-
- /*
- * Finally, clear the HAXR2 register, which gets used
- * for PCI Config Space accesses. That is the way
- * we want to use it, and we do not want to depend on
- * what ARC or SRM might have left behind...
- */
- {
-#if 0
- unsigned int haxr2 = *(vuip)APECS_IOC_HAXR2; mb();
- if (haxr2) printk("apecs_init: HAXR2 was 0x%x\n", haxr2);
-#endif
- *(vuip)APECS_IOC_HAXR2 = 0; mb();
- }
-
-
- return mem_start;
+ *(vuip)APECS_IOC_HAXR2 = 0; mb();
}
-int apecs_pci_clr_err(void)
+int
+apecs_pci_clr_err(void)
{
apecs_jd = *(vuip)APECS_IOC_DCSR;
if (apecs_jd & 0xffe0L) {
@@ -534,21 +458,24 @@ int apecs_pci_clr_err(void)
return 0;
}
-void apecs_machine_check(unsigned long vector, unsigned long la_ptr,
- struct pt_regs * regs)
+void
+apecs_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
{
struct el_common *mchk_header;
- struct el_procdata *mchk_procdata;
+ struct el_apecs_procdata *mchk_procdata;
struct el_apecs_sysdata_mcheck *mchk_sysdata;
unsigned long *ptr;
int i;
-
mchk_header = (struct el_common *)la_ptr;
- mchk_procdata = (struct el_procdata *)
- (la_ptr + mchk_header->proc_offset - sizeof(mchk_procdata->paltemp));
- mchk_sysdata =
- (struct el_apecs_sysdata_mcheck *)(la_ptr + mchk_header->sys_offset);
+
+ mchk_procdata = (struct el_apecs_procdata *)
+ (la_ptr + mchk_header->proc_offset
+ - sizeof(mchk_procdata->paltemp));
+
+ mchk_sysdata = (struct el_apecs_sysdata_mcheck *)
+ (la_ptr + mchk_header->sys_offset);
#ifdef DEBUG
printk("apecs_machine_check: vector=0x%lx la_ptr=0x%lx\n",
@@ -563,23 +490,15 @@ void apecs_machine_check(unsigned long vector, unsigned long la_ptr,
for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
}
-#endif /* DEBUG */
+#endif
/*
* Check if machine check is due to a badaddr() and if so,
* ignore the machine check.
*/
-#ifdef CONFIG_ALPHA_MIKASA
-#define MCHK_NO_DEVSEL 0x205L
-#define MCHK_NO_TABT 0x204L
- if (apecs_mcheck_expected &&
- (((unsigned int)mchk_header->code == MCHK_NO_DEVSEL) ||
- ((unsigned int)mchk_header->code == MCHK_NO_TABT))
- )
- {
-#else
- if (apecs_mcheck_expected && (mchk_sysdata->epic_dcsr && 0x0c00UL)) {
-#endif
+
+ if (apecs_mcheck_expected
+ && (mchk_sysdata->epic_dcsr & 0x0c00UL)) {
apecs_mcheck_expected = 0;
apecs_mcheck_taken = 1;
mb();
@@ -591,7 +510,8 @@ void apecs_machine_check(unsigned long vector, unsigned long la_ptr,
DBG(("apecs_machine_check: EXPECTED\n"));
}
else if (vector == 0x620 || vector == 0x630) {
- wrmces(0x1f); /* disable correctable from now on */
+ /* Disable correctable from now on. */
+ wrmces(0x1f);
mb();
draina();
printk("apecs_machine_check: HW correctable (0x%lx)\n",
@@ -611,8 +531,8 @@ void apecs_machine_check(unsigned long vector, unsigned long la_ptr,
ptr = (unsigned long *)la_ptr;
for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(KERN_CRIT " +%lx %lx %lx\n",
- i*sizeof(long), ptr[i], ptr[i+1]);
+ printk(KERN_CRIT " +%lx %lx %lx\n",
+ i*sizeof(long), ptr[i], ptr[i+1]);
}
#if 0
/* doesn't work with MILO */
diff --git a/arch/alpha/kernel/cia.c b/arch/alpha/kernel/core_cia.c
index 57fae7d87..9f290bf80 100644
--- a/arch/alpha/kernel/cia.c
+++ b/arch/alpha/kernel/core_cia.c
@@ -1,5 +1,7 @@
/*
- * Code common to all CIA chips.
+ * linux/arch/alpha/kernel/core_cia.c
+ *
+ * Code common to all CIA core logic chips.
*
* Written by David A Rusling (david.rusling@reo.mts.dec.com).
* December 1995.
@@ -10,12 +12,17 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/sched.h>
+#include <linux/init.h>
#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/hwrpb.h>
#include <asm/ptrace.h>
-#include <asm/mmu_context.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_cia.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
/*
* NOTE: Herein lie back-to-back mb instructions. They are magic.
@@ -23,7 +30,6 @@
* handle the system transaction. Another involves timing. Ho hum.
*/
-extern struct hwrpb_struct *hwrpb;
extern asmlinkage void wrmces(unsigned long mces);
/*
@@ -42,16 +48,16 @@ extern asmlinkage void wrmces(unsigned long mces);
* BIOS32-style PCI interface:
*/
-/* #define DEBUG_MCHECK */
-/* #define DEBUG_CONFIG */
+#define DEBUG_MCHECK 0
+#define DEBUG_CONFIG 0
/* #define DEBUG_DUMP_REGS */
-#ifdef DEBUG_MCHECK
+#if DEBUG_MCHECK
# define DBGM(args) printk args
#else
# define DBGM(args)
#endif
-#ifdef DEBUG_CONFIG
+#if DEBUG_CONFIG
# define DBGC(args) printk args
#else
# define DBGC(args)
@@ -63,11 +69,6 @@ static volatile unsigned int CIA_mcheck_expected = 0;
static volatile unsigned int CIA_mcheck_taken = 0;
static unsigned int CIA_jd;
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int CIA_DMA_WIN_BASE = CIA_DMA_WIN_BASE_DEFAULT;
-unsigned int CIA_DMA_WIN_SIZE = CIA_DMA_WIN_SIZE_DEFAULT;
-unsigned long cia_sm_base_r1, cia_sm_base_r2, cia_sm_base_r3;
-#endif /* SRM_SETUP */
/*
* Given a bus, device, and function number, compute resulting
@@ -104,15 +105,16 @@ unsigned long cia_sm_base_r1, cia_sm_base_r2, cia_sm_base_r3;
*
* Notes:
* The function number selects which function of a multi-function device
- * (e.g., scsi and ethernet).
+ * (e.g., SCSI and Ethernet).
*
* The register selects a DWORD (32 bit) register offset. Hence it
* doesn't get shifted by 2 bits as we want to "drop" the bottom two
* bits.
*/
-static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned long *pci_addr,
- unsigned char *type1)
+
+static int
+mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+ unsigned char *type1)
{
unsigned long addr;
@@ -123,7 +125,7 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
if (bus == 0) {
int device = device_fn >> 3;
- /* type 0 configuration cycle: */
+ /* Type 0 configuration cycle. */
if (device > 20) {
DBGC(("mk_conf_addr: device (%d) > 20, returning -1\n",
@@ -134,7 +136,7 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
*type1 = 0;
addr = (device_fn << 8) | (where);
} else {
- /* type 1 configuration cycle: */
+ /* Type 1 configuration cycle. */
*type1 = 1;
addr = (bus << 16) | (device_fn << 8) | (where);
}
@@ -143,12 +145,12 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
return 0;
}
-
-static unsigned int conf_read(unsigned long addr, unsigned char type1)
+static unsigned int
+conf_read(unsigned long addr, unsigned char type1)
{
unsigned long flags;
unsigned int stat0, value;
- unsigned int cia_cfg = 0; /* to keep gcc quiet */
+ unsigned int cia_cfg = 0;
value = 0xffffffffU;
mb();
@@ -158,12 +160,13 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
DBGC(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
- /* reset status register to avoid losing errors: */
+ /* Reset status register to avoid losing errors. */
stat0 = *(vuip)CIA_IOC_CIA_ERR;
*(vuip)CIA_IOC_CIA_ERR = stat0;
mb();
DBGC(("conf_read: CIA ERR was 0x%x\n", stat0));
- /* if Type1 access, must set CIA CFG */
+
+ /* If Type1 access, must set CIA CFG. */
if (type1) {
cia_cfg = *(vuip)CIA_IOC_CFG;
*(vuip)CIA_IOC_CFG = cia_cfg | 1;
@@ -176,7 +179,8 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
CIA_mcheck_expected = 1;
CIA_mcheck_taken = 0;
mb();
- /* access configuration space: */
+
+ /* Access configuration space. */
value = *(vuip)addr;
mb();
mb(); /* magic */
@@ -189,17 +193,17 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
mb();
#if 0
- /*
- this code might be necessary if machine checks aren't taken,
- but I can't get it to work on CIA-2, so its disabled.
- */
+ /* This code might be necessary if machine checks aren't taken,
+ but I can't get it to work on CIA-2, so its disabled. */
draina();
- /* now look for any errors */
+ /* Now look for any errors. */
stat0 = *(vuip)CIA_IOC_CIA_ERR;
DBGC(("conf_read: CIA ERR after read 0x%x\n", stat0));
- if (stat0 & 0x8FEF0FFFU) { /* is any error bit set? */
- /* if not MAS_ABT, print status */
+
+ /* Is any error bit set? */
+ if (stat0 & 0x8FEF0FFFU) {
+ /* If not MAS_ABT, print status. */
if (!(stat0 & 0x0080)) {
printk("CIA.c:conf_read: got stat0=%x\n", stat0);
}
@@ -212,7 +216,7 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
}
#endif
- /* if Type1 access, must reset IOC CFG so normal IO space ops work */
+ /* If Type1 access, must reset IOC CFG so normal IO space ops work. */
if (type1) {
*(vuip)CIA_IOC_CFG = cia_cfg & ~1;
mb();
@@ -224,23 +228,23 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
return value;
}
-
-static void conf_write(unsigned long addr, unsigned int value,
- unsigned char type1)
+static void
+conf_write(unsigned long addr, unsigned int value, unsigned char type1)
{
unsigned long flags;
unsigned int stat0;
- unsigned int cia_cfg = 0; /* to keep gcc quiet */
+ unsigned int cia_cfg = 0;
save_flags(flags); /* avoid getting hit by machine check */
cli();
- /* reset status register to avoid losing errors: */
+ /* Reset status register to avoid losing errors. */
stat0 = *(vuip)CIA_IOC_CIA_ERR;
*(vuip)CIA_IOC_CIA_ERR = stat0;
mb();
DBGC(("conf_write: CIA ERR was 0x%x\n", stat0));
- /* if Type1 access, must set CIA CFG */
+
+ /* If Type1 access, must set CIA CFG. */
if (type1) {
cia_cfg = *(vuip)CIA_IOC_CFG;
*(vuip)CIA_IOC_CFG = cia_cfg | 1;
@@ -251,7 +255,8 @@ static void conf_write(unsigned long addr, unsigned int value,
draina();
CIA_mcheck_expected = 1;
mb();
- /* access configuration space: */
+
+ /* Access configuration space. */
*(vuip)addr = value;
mb();
mb(); /* magic */
@@ -260,22 +265,22 @@ static void conf_write(unsigned long addr, unsigned int value,
mb();
#if 0
- /*
- * This code might be necessary if machine checks aren't taken,
- * but I can't get it to work on CIA-2, so its disabled.
- */
+ /* This code might be necessary if machine checks aren't taken,
+ but I can't get it to work on CIA-2, so its disabled. */
draina();
/* Now look for any errors */
stat0 = *(vuip)CIA_IOC_CIA_ERR;
DBGC(("conf_write: CIA ERR after write 0x%x\n", stat0));
- if (stat0 & 0x8FEF0FFFU) { /* is any error bit set? */
+
+ /* Is any error bit set? */
+ if (stat0 & 0x8FEF0FFFU) {
/* If not MAS_ABT, print status */
if (!(stat0 & 0x0080)) {
printk("CIA.c:conf_read: got stat0=%x\n", stat0);
}
- /* reset error status: */
+ /* Reset error status. */
*(vuip)CIA_IOC_CIA_ERR = stat0;
mb();
wrmces(0x7); /* reset machine check */
@@ -283,7 +288,7 @@ static void conf_write(unsigned long addr, unsigned int value,
}
#endif
- /* if Type1 access, must reset IOC CFG so normal IO space ops work */
+ /* If Type1 access, must reset IOC CFG so normal IO space ops work. */
if (type1) {
*(vuip)CIA_IOC_CFG = cia_cfg & ~1;
mb();
@@ -293,9 +298,8 @@ static void conf_write(unsigned long addr, unsigned int value,
restore_flags(flags);
}
-
-int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
+int
+cia_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value)
{
unsigned long addr = CIA_CONF;
unsigned long pci_addr;
@@ -303,20 +307,16 @@ int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
*value = 0xff;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
addr |= (pci_addr << 5) + 0x00;
-
*value = conf_read(addr, type1) >> ((where & 3) * 8);
-
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short *value)
+int
+cia_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value)
{
unsigned long addr = CIA_CONF;
unsigned long pci_addr;
@@ -324,91 +324,85 @@ int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
*value = 0xffff;
- if (where & 0x1) {
+ if (where & 0x1)
return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
addr |= (pci_addr << 5) + 0x08;
-
*value = conf_read(addr, type1) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int *value)
+int
+cia_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value)
{
unsigned long addr = CIA_CONF;
unsigned long pci_addr;
unsigned char type1;
*value = 0xffffffff;
- if (where & 0x3) {
+ if (where & 0x3)
return PCIBIOS_BAD_REGISTER_NUMBER;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
addr |= (pci_addr << 5) + 0x18;
*value = conf_read(addr, type1);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char value)
+int
+cia_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value)
{
unsigned long addr = CIA_CONF;
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x00;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short value)
+int
+cia_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value)
{
unsigned long addr = CIA_CONF;
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x08;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int value)
+int
+cia_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value)
{
unsigned long addr = CIA_CONF;
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x18;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-
-unsigned long cia_init(unsigned long mem_start, unsigned long mem_end)
+void __init
+cia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
{
unsigned int cia_tmp;
@@ -416,49 +410,49 @@ unsigned long cia_init(unsigned long mem_start, unsigned long mem_end)
{
unsigned int temp;
temp = *(vuip)CIA_IOC_CIA_REV; mb();
- printk("CIA_init: CIA_REV was 0x%x\n", temp);
+ printk("cia_init: CIA_REV was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_PCI_LAT; mb();
- printk("CIA_init: CIA_PCI_LAT was 0x%x\n", temp);
+ printk("cia_init: CIA_PCI_LAT was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
- printk("CIA_init: CIA_CTRL was 0x%x\n", temp);
+ printk("cia_init: CIA_CTRL was 0x%x\n", temp);
temp = *(vuip)0xfffffc8740000140UL; mb();
- printk("CIA_init: CIA_CTRL1 was 0x%x\n", temp);
+ printk("cia_init: CIA_CTRL1 was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_HAE_MEM; mb();
- printk("CIA_init: CIA_HAE_MEM was 0x%x\n", temp);
+ printk("cia_init: CIA_HAE_MEM was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_HAE_IO; mb();
- printk("CIA_init: CIA_HAE_IO was 0x%x\n", temp);
+ printk("cia_init: CIA_HAE_IO was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_CFG; mb();
- printk("CIA_init: CIA_CFG was 0x%x\n", temp);
+ printk("cia_init: CIA_CFG was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_CACK_EN; mb();
- printk("CIA_init: CIA_CACK_EN was 0x%x\n", temp);
+ printk("cia_init: CIA_CACK_EN was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_CFG; mb();
- printk("CIA_init: CIA_CFG was 0x%x\n", temp);
+ printk("cia_init: CIA_CFG was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_CIA_DIAG; mb();
- printk("CIA_init: CIA_DIAG was 0x%x\n", temp);
+ printk("cia_init: CIA_DIAG was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_DIAG_CHECK; mb();
- printk("CIA_init: CIA_DIAG_CHECK was 0x%x\n", temp);
+ printk("cia_init: CIA_DIAG_CHECK was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_PERF_MONITOR; mb();
- printk("CIA_init: CIA_PERF_MONITOR was 0x%x\n", temp);
+ printk("cia_init: CIA_PERF_MONITOR was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_PERF_CONTROL; mb();
- printk("CIA_init: CIA_PERF_CONTROL was 0x%x\n", temp);
+ printk("cia_init: CIA_PERF_CONTROL was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_CIA_ERR; mb();
- printk("CIA_init: CIA_ERR was 0x%x\n", temp);
+ printk("cia_init: CIA_ERR was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_CIA_STAT; mb();
- printk("CIA_init: CIA_STAT was 0x%x\n", temp);
+ printk("cia_init: CIA_STAT was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_MCR; mb();
- printk("CIA_init: CIA_MCR was 0x%x\n", temp);
+ printk("cia_init: CIA_MCR was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_CIA_CTRL; mb();
- printk("CIA_init: CIA_CTRL was 0x%x\n", temp);
+ printk("cia_init: CIA_CTRL was 0x%x\n", temp);
temp = *(vuip)CIA_IOC_ERR_MASK; mb();
- printk("CIA_init: CIA_ERR_MASK was 0x%x\n", temp);
+ printk("cia_init: CIA_ERR_MASK was 0x%x\n", temp);
temp = *((vuip)CIA_IOC_PCI_W0_BASE); mb();
- printk("CIA_init: W0_BASE was 0x%x\n", temp);
+ printk("cia_init: W0_BASE was 0x%x\n", temp);
temp = *((vuip)CIA_IOC_PCI_W1_BASE); mb();
- printk("CIA_init: W1_BASE was 0x%x\n", temp);
+ printk("cia_init: W1_BASE was 0x%x\n", temp);
temp = *((vuip)CIA_IOC_PCI_W2_BASE); mb();
- printk("CIA_init: W2_BASE was 0x%x\n", temp);
+ printk("cia_init: W2_BASE was 0x%x\n", temp);
temp = *((vuip)CIA_IOC_PCI_W3_BASE); mb();
- printk("CIA_init: W3_BASE was 0x%x\n", temp);
+ printk("cia_init: W3_BASE was 0x%x\n", temp);
}
#endif /* DEBUG_DUMP_REGS */
@@ -471,152 +465,147 @@ unsigned long cia_init(unsigned long mem_start, unsigned long mem_end)
mb();
cia_tmp = *(vuip)CIA_IOC_CIA_CTRL;
- cia_tmp |= 0x400; /* turn on FILL_ERR to get mchecks */
+ cia_tmp |= 0x400; /* turn on FILL_ERR to get mchecks */
*(vuip)CIA_IOC_CIA_CTRL = cia_tmp;
mb();
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 0 for enabled and mapped to 0 */
- if (((*(vuip)CIA_IOC_PCI_W0_BASE & 3) == 1) &&
- (*(vuip)CIA_IOC_PCI_T0_BASE == 0))
+ switch (alpha_use_srm_setup)
{
- CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W0_BASE & 0xfff00000U;
- CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W0_MASK & 0xfff00000U;
- CIA_DMA_WIN_SIZE += 0x00100000U;
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 0 for enabled and mapped to 0 */
+ if (((*(vuip)CIA_IOC_PCI_W0_BASE & 3) == 1)
+ && (*(vuip)CIA_IOC_PCI_T0_BASE == 0)) {
+ CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W0_BASE & 0xfff00000U;
+ CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W0_MASK & 0xfff00000U;
+ CIA_DMA_WIN_SIZE += 0x00100000U;
#if 1
- printk("cia_init: using Window 0 settings\n");
- printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)CIA_IOC_PCI_W0_BASE,
- *(vuip)CIA_IOC_PCI_W0_MASK,
- *(vuip)CIA_IOC_PCI_T0_BASE);
+ printk("cia_init: using Window 0 settings\n");
+ printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)CIA_IOC_PCI_W0_BASE,
+ *(vuip)CIA_IOC_PCI_W0_MASK,
+ *(vuip)CIA_IOC_PCI_T0_BASE);
#endif
- }
- else /* check window 1 for enabled and mapped to 0 */
- if (((*(vuip)CIA_IOC_PCI_W1_BASE & 3) == 1) &&
- (*(vuip)CIA_IOC_PCI_T1_BASE == 0))
- {
- CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W1_BASE & 0xfff00000U;
- CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W1_MASK & 0xfff00000U;
- CIA_DMA_WIN_SIZE += 0x00100000U;
+ break;
+ }
+
+ /* Check window 1 for enabled and mapped to 0. */
+ if (((*(vuip)CIA_IOC_PCI_W1_BASE & 3) == 1)
+ && (*(vuip)CIA_IOC_PCI_T1_BASE == 0)) {
+ CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W1_BASE & 0xfff00000U;
+ CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W1_MASK & 0xfff00000U;
+ CIA_DMA_WIN_SIZE += 0x00100000U;
#if 1
- printk("cia_init: using Window 1 settings\n");
- printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)CIA_IOC_PCI_W1_BASE,
- *(vuip)CIA_IOC_PCI_W1_MASK,
- *(vuip)CIA_IOC_PCI_T1_BASE);
+ printk("cia_init: using Window 1 settings\n");
+ printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)CIA_IOC_PCI_W1_BASE,
+ *(vuip)CIA_IOC_PCI_W1_MASK,
+ *(vuip)CIA_IOC_PCI_T1_BASE);
#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if (((*(vuip)CIA_IOC_PCI_W2_BASE & 3) == 1) &&
- (*(vuip)CIA_IOC_PCI_T2_BASE == 0))
- {
- CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W2_BASE & 0xfff00000U;
- CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W2_MASK & 0xfff00000U;
- CIA_DMA_WIN_SIZE += 0x00100000U;
+ break;
+ }
+
+ /* Check window 2 for enabled and mapped to 0. */
+ if (((*(vuip)CIA_IOC_PCI_W2_BASE & 3) == 1)
+ && (*(vuip)CIA_IOC_PCI_T2_BASE == 0)) {
+ CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W2_BASE & 0xfff00000U;
+ CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W2_MASK & 0xfff00000U;
+ CIA_DMA_WIN_SIZE += 0x00100000U;
#if 1
- printk("cia_init: using Window 2 settings\n");
- printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)CIA_IOC_PCI_W2_BASE,
- *(vuip)CIA_IOC_PCI_W2_MASK,
- *(vuip)CIA_IOC_PCI_T2_BASE);
+ printk("cia_init: using Window 2 settings\n");
+ printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)CIA_IOC_PCI_W2_BASE,
+ *(vuip)CIA_IOC_PCI_W2_MASK,
+ *(vuip)CIA_IOC_PCI_T2_BASE);
#endif
- }
- else /* check window 3 for enabled and mapped to 0 */
- if (((*(vuip)CIA_IOC_PCI_W3_BASE & 3) == 1) &&
- (*(vuip)CIA_IOC_PCI_T3_BASE == 0))
- {
- CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W3_BASE & 0xfff00000U;
- CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W3_MASK & 0xfff00000U;
- CIA_DMA_WIN_SIZE += 0x00100000U;
+ break;
+ }
+
+ /* Check window 3 for enabled and mapped to 0. */
+ if (((*(vuip)CIA_IOC_PCI_W3_BASE & 3) == 1)
+ && (*(vuip)CIA_IOC_PCI_T3_BASE == 0)) {
+ CIA_DMA_WIN_BASE = *(vuip)CIA_IOC_PCI_W3_BASE & 0xfff00000U;
+ CIA_DMA_WIN_SIZE = *(vuip)CIA_IOC_PCI_W3_MASK & 0xfff00000U;
+ CIA_DMA_WIN_SIZE += 0x00100000U;
#if 1
- printk("cia_init: using Window 3 settings\n");
- printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)CIA_IOC_PCI_W3_BASE,
- *(vuip)CIA_IOC_PCI_W3_MASK,
- *(vuip)CIA_IOC_PCI_T3_BASE);
+ printk("cia_init: using Window 3 settings\n");
+ printk("cia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)CIA_IOC_PCI_W3_BASE,
+ *(vuip)CIA_IOC_PCI_W3_MASK,
+ *(vuip)CIA_IOC_PCI_T3_BASE);
#endif
- }
- else /* we must use our defaults which were pre-initialized... */
-#endif /* SRM_SETUP */
- {
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, windows 1,2 and 3 are disabled. In the future, we may
- * want to use them to do scatter/gather DMA. Window 0
- * goes at 1 GB and is 1 GB large.
- */
-
- *(vuip)CIA_IOC_PCI_W0_BASE = 1U | (CIA_DMA_WIN_BASE & 0xfff00000U);
- *(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN_SIZE - 1) & 0xfff00000U;
- *(vuip)CIA_IOC_PCI_T0_BASE = 0;
-
- *(vuip)CIA_IOC_PCI_W1_BASE = 0x0;
- *(vuip)CIA_IOC_PCI_W2_BASE = 0x0;
- *(vuip)CIA_IOC_PCI_W3_BASE = 0x0;
- }
+ break;
+ }
- /*
- * check ASN in HWRPB for validity, report if bad
- */
- if (hwrpb->max_asn != MAX_ASN) {
- printk("CIA_init: max ASN from HWRPB is bad (0x%lx)\n",
- hwrpb->max_asn);
- hwrpb->max_asn = MAX_ASN;
+ /* Otherwise, we must use our defaults. */
+ CIA_DMA_WIN_BASE = CIA_DMA_WIN_BASE_DEFAULT;
+ CIA_DMA_WIN_SIZE = CIA_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, windows 1,2 and 3 are disabled. In the future,
+ * we may want to use them to do scatter/gather DMA.
+ *
+ * Window 0 goes at 1 GB and is 1 GB large.
+ */
+
+ *(vuip)CIA_IOC_PCI_W0_BASE = 1U | (CIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
+ *(vuip)CIA_IOC_PCI_W0_MASK = (CIA_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
+ *(vuip)CIA_IOC_PCI_T0_BASE = 0;
+
+ *(vuip)CIA_IOC_PCI_W1_BASE = 0x0;
+ *(vuip)CIA_IOC_PCI_W2_BASE = 0x0;
+ *(vuip)CIA_IOC_PCI_W3_BASE = 0x0;
+ break;
}
/*
* Next, clear the CIA_CFG register, which gets used
- * for PCI Config Space accesses. That is the way
- * we want to use it, and we do not want to depend on
- * what ARC or SRM might have left behind...
+ * for PCI Config Space accesses. That is the way
+ * we want to use it, and we do not want to depend on
+ * what ARC or SRM might have left behind...
*/
- {
- unsigned int cia_cfg = *((vuip)CIA_IOC_CFG); mb();
- if (cia_cfg) {
- printk("CIA_init: CFG was 0x%x\n", cia_cfg);
- *((vuip)CIA_IOC_CFG) = 0; mb();
- }
- }
+ *((vuip)CIA_IOC_CFG) = 0; mb();
- {
- unsigned int cia_hae_mem = *((vuip)CIA_IOC_HAE_MEM);
- unsigned int cia_hae_io = *((vuip)CIA_IOC_HAE_IO);
-#if 0
- printk("CIA_init: HAE_MEM was 0x%x\n", cia_hae_mem);
- printk("CIA_init: HAE_IO was 0x%x\n", cia_hae_io);
-#endif
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /*
- sigh... For the SRM setup, unless we know apriori what the HAE
- contents will be, we need to setup the arbitrary region bases
- so we can test against the range of addresses and tailor the
- region chosen for the SPARSE memory access.
-
- see include/asm-alpha/cia.h for the SPARSE mem read/write
- */
- cia_sm_base_r1 = (cia_hae_mem ) & 0xe0000000UL; /* region 1 */
- cia_sm_base_r2 = (cia_hae_mem << 16) & 0xf8000000UL; /* region 2 */
- cia_sm_base_r3 = (cia_hae_mem << 24) & 0xfc000000UL; /* region 3 */
-
- /*
- Set the HAE cache, so that setup_arch() code
- will use the SRM setting always. Our readb/writeb
- code in cia.h expects never to have to change
- the contents of the HAE.
- */
- hae.cache = cia_hae_mem;
-#else /* SRM_SETUP */
- *((vuip)CIA_IOC_HAE_MEM) = 0; mb();
- cia_hae_mem = *((vuip)CIA_IOC_HAE_MEM);
- *((vuip)CIA_IOC_HAE_IO) = 0; mb();
- cia_hae_io = *((vuip)CIA_IOC_HAE_IO);
-#endif /* SRM_SETUP */
+
+ /*
+ * Sigh... For the SRM setup, unless we know apriori what the HAE
+ * contents will be, we need to setup the arbitrary region bases
+ * so we can test against the range of addresses and tailor the
+ * region chosen for the SPARSE memory access.
+ *
+ * See include/asm-alpha/cia.h for the SPARSE mem read/write.
+ */
+ if (alpha_use_srm_setup) {
+ unsigned int cia_hae_mem = *((vuip)CIA_IOC_HAE_MEM);
+
+ alpha_mv.sm_base_r1 = (cia_hae_mem ) & 0xe0000000UL;
+ alpha_mv.sm_base_r2 = (cia_hae_mem << 16) & 0xf8000000UL;
+ alpha_mv.sm_base_r3 = (cia_hae_mem << 24) & 0xfc000000UL;
+
+ /*
+ * Set the HAE cache, so that setup_arch() code
+ * will use the SRM setting always. Our readb/writeb
+ * code in cia.h expects never to have to change
+ * the contents of the HAE.
+ */
+ alpha_mv.hae_cache = cia_hae_mem;
+
+ alpha_mv.mv_readb = cia_srm_readb;
+ alpha_mv.mv_readw = cia_srm_readw;
+ alpha_mv.mv_writeb = cia_srm_writeb;
+ alpha_mv.mv_writew = cia_srm_writew;
+ } else {
+ *((vuip)CIA_IOC_HAE_MEM) = 0; mb();
+ *((vuip)CIA_IOC_HAE_MEM); /* read it back. */
+ *((vuip)CIA_IOC_HAE_IO) = 0; mb();
+ *((vuip)CIA_IOC_HAE_IO); /* read it back. */
}
-
- return mem_start;
}
-int cia_pci_clr_err(void)
+static int
+cia_pci_clr_err(void)
{
CIA_jd = *(vuip)CIA_IOC_CIA_ERR;
DBGM(("CIA_pci_clr_err: CIA ERR after read 0x%x\n", CIA_jd));
@@ -625,11 +614,12 @@ int cia_pci_clr_err(void)
return 0;
}
-void cia_machine_check(unsigned long vector, unsigned long la_ptr,
- struct pt_regs * regs)
+void
+cia_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
{
struct el_common *mchk_header;
- struct el_procdata *mchk_procdata;
+ struct el_CIA_procdata *mchk_procdata;
struct el_CIA_sysdata_mcheck *mchk_sysdata;
unsigned long * ptr;
const char * reason;
@@ -637,8 +627,10 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr,
long i;
mchk_header = (struct el_common *)la_ptr;
- mchk_procdata = (struct el_procdata *)
+
+ mchk_procdata = (struct el_CIA_procdata *)
(la_ptr + mchk_header->proc_offset);
+
mchk_sysdata = (struct el_CIA_sysdata_mcheck *)
(la_ptr + mchk_header->sys_offset);
@@ -651,7 +643,7 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr,
CIA_mcheck_expected, mchk_sysdata->epic_dcsr,
mchk_sysdata->epic_pear));
-#ifdef DEBUG_MCHECK
+#if DEBUG_MCHECK
{
unsigned long *ptr;
int i;
@@ -686,7 +678,7 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr,
switch ((unsigned int) mchk_header->code) {
case MCHK_K_TPERR: reason = "tag parity error"; break;
case MCHK_K_TCPERR: reason = "tag control parity error"; break;
- case MCHK_K_HERR: reason = "generic hard error"; break;
+ case MCHK_K_HERR: reason = "generic hard error"; break;
case MCHK_K_ECC_C: reason = "correctable ECC error"; break;
case MCHK_K_ECC_NC: reason = "uncorrectable ECC error"; break;
case MCHK_K_OS_BUGCHECK: reason = "OS-specific PAL bugcheck"; break;
@@ -694,7 +686,7 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr,
case 0x96: reason = "i-cache read retryable error"; break;
case 0x98: reason = "processor detected hard error"; break;
- /* system specific (these are for Alcor, at least): */
+ /* System specific (these are for Alcor, at least): */
case 0x203: reason = "system detected uncorrectable ECC error"; break;
case 0x205: reason = "parity error detected by CIA"; break;
case 0x207: reason = "non-existent memory error"; break;
@@ -720,16 +712,16 @@ void cia_machine_check(unsigned long vector, unsigned long la_ptr,
wrmces(rdmces()); /* reset machine check pending flag */
mb();
- printk(KERN_CRIT " CIA machine check: %s%s\n",
+ printk(KERN_CRIT "CIA machine check: %s%s\n",
reason, mchk_header->retry ? " (retryable)" : "");
printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx pc=0x%lx\n",
vector, la_ptr, regs->pc);
- /* dump the the logout area to give all info: */
+ /* Dump the logout area to give all info. */
ptr = (unsigned long *)la_ptr;
for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(KERN_CRIT " +%8lx %016lx %016lx\n",
+ printk(KERN_CRIT " +%8lx %016lx %016lx\n",
i*sizeof(long), ptr[i], ptr[i+1]);
}
}
diff --git a/arch/alpha/kernel/lca.c b/arch/alpha/kernel/core_lca.c
index a0b8aea8d..fe1e77952 100644
--- a/arch/alpha/kernel/lca.c
+++ b/arch/alpha/kernel/core_lca.c
@@ -1,5 +1,7 @@
/*
- * Code common to all LCA chips.
+ * linux/arch/alpha/kernel/core_lca.c
+ *
+ * Code common to all LCA core logic chips.
*
* Written by David Mosberger (davidm@cs.arizona.edu) with some code
* taken from Dave Rusling's (david.rusling@reo.mts.dec.com) 32-bit
@@ -9,18 +11,24 @@
#include <linux/config.h>
#include <linux/types.h>
#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/tty.h>
#include <asm/ptrace.h>
#include <asm/system.h>
+#include <asm/smp.h>
+
+#define __EXTERN_INLINE inline
#include <asm/io.h>
+#include <asm/core_lca.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
/*
* BIOS32-style PCI interface:
*/
-#define vulp volatile unsigned long *
-#define vuip volatile unsigned int *
-
/*
* Machine check reasons. Defined according to PALcode sources
* (osf.h and platform.h).
@@ -37,6 +45,7 @@
#define MCHK_K_DCPERR 0x0092
#define MCHK_K_ICPERR 0x0094
+
/*
* Platform-specific machine-check reasons:
*/
@@ -44,10 +53,6 @@
#define MCHK_K_SIO_IOCHK 0x206 /* all platforms so far */
#define MCHK_K_DCSR 0x208 /* all but Noname */
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int LCA_DMA_WIN_BASE = LCA_DMA_WIN_BASE_DEFAULT;
-unsigned int LCA_DMA_WIN_SIZE = LCA_DMA_WIN_SIZE_DEFAULT;
-#endif /* SRM_SETUP */
/*
* Given a bus, device, and function number, compute resulting
@@ -84,14 +89,15 @@ unsigned int LCA_DMA_WIN_SIZE = LCA_DMA_WIN_SIZE_DEFAULT;
*
* Notes:
* The function number selects which function of a multi-function device
- * (e.g., scsi and ethernet).
+ * (e.g., SCSI and Ethernet).
*
* The register selects a DWORD (32 bit) register offset. Hence it
* doesn't get shifted by 2 bits as we want to "drop" the bottom two
* bits.
*/
-static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned long *pci_addr)
+
+static int
+mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr)
{
unsigned long addr;
@@ -99,7 +105,7 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
int device = device_fn >> 3;
int func = device_fn & 0x7;
- /* type 0 configuration cycle: */
+ /* Type 0 configuration cycle. */
if (device > 12) {
return -1;
@@ -108,7 +114,7 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
*(vulp)LCA_IOC_CONF = 0;
addr = (1 << (11 + device)) | (func << 8) | where;
} else {
- /* type 1 configuration cycle: */
+ /* Type 1 configuration cycle. */
*(vulp)LCA_IOC_CONF = 1;
addr = (bus << 16) | (device_fn << 8) | where;
}
@@ -116,8 +122,8 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
return 0;
}
-
-static unsigned int conf_read(unsigned long addr)
+static unsigned int
+conf_read(unsigned long addr)
{
unsigned long flags, code, stat0;
unsigned int value;
@@ -125,13 +131,12 @@ static unsigned int conf_read(unsigned long addr)
save_flags(flags);
cli();
- /* reset status register to avoid loosing errors: */
+ /* Reset status register to avoid loosing errors. */
stat0 = *(vulp)LCA_IOC_STAT0;
*(vulp)LCA_IOC_STAT0 = stat0;
mb();
- /* access configuration space: */
-
+ /* Access configuration space. */
value = *(vuip)addr;
draina();
@@ -143,10 +148,12 @@ static unsigned int conf_read(unsigned long addr)
printk("lca.c:conf_read: got stat0=%lx\n", stat0);
}
- /* reset error status: */
+ /* Reset error status. */
*(vulp)LCA_IOC_STAT0 = stat0;
mb();
- wrmces(0x7); /* reset machine check */
+
+ /* Reset machine check. */
+ wrmces(0x7);
value = 0xffffffff;
}
@@ -154,21 +161,20 @@ static unsigned int conf_read(unsigned long addr)
return value;
}
-
-static void conf_write(unsigned long addr, unsigned int value)
+static void
+conf_write(unsigned long addr, unsigned int value)
{
unsigned long flags, code, stat0;
save_flags(flags); /* avoid getting hit by machine check */
cli();
- /* reset status register to avoid loosing errors: */
+ /* Reset status register to avoid loosing errors. */
stat0 = *(vulp)LCA_IOC_STAT0;
*(vulp)LCA_IOC_STAT0 = stat0;
mb();
- /* access configuration space: */
-
+ /* Access configuration space. */
*(vuip)addr = value;
draina();
@@ -180,163 +186,170 @@ static void conf_write(unsigned long addr, unsigned int value)
printk("lca.c:conf_write: got stat0=%lx\n", stat0);
}
- /* reset error status: */
+ /* Reset error status. */
*(vulp)LCA_IOC_STAT0 = stat0;
mb();
- wrmces(0x7); /* reset machine check */
+
+ /* Reset machine check. */
+ wrmces(0x7);
}
restore_flags(flags);
}
-
-int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
+int
+lca_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value)
{
unsigned long addr = LCA_CONF;
unsigned long pci_addr;
*value = 0xff;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x00;
*value = conf_read(addr) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short *value)
+int
+lca_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value)
{
unsigned long addr = LCA_CONF;
unsigned long pci_addr;
*value = 0xffff;
- if (where & 0x1) {
+ if (where & 0x1)
return PCIBIOS_BAD_REGISTER_NUMBER;
- }
- if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x08;
*value = conf_read(addr) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int *value)
+int
+lca_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value)
{
unsigned long addr = LCA_CONF;
unsigned long pci_addr;
*value = 0xffffffff;
- if (where & 0x3) {
+ if (where & 0x3)
return PCIBIOS_BAD_REGISTER_NUMBER;
- }
- if (mk_conf_addr(bus, device_fn, where, &pci_addr)) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x18;
*value = conf_read(addr);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char value)
+int
+lca_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value)
{
unsigned long addr = LCA_CONF;
unsigned long pci_addr;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x00;
conf_write(addr, value << ((where & 3) * 8));
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short value)
+int
+lca_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value)
{
unsigned long addr = LCA_CONF;
unsigned long pci_addr;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x08;
conf_write(addr, value << ((where & 3) * 8));
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int value)
+int
+lca_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value)
{
unsigned long addr = LCA_CONF;
unsigned long pci_addr;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x18;
conf_write(addr, value << ((where & 3) * 8));
return PCIBIOS_SUCCESSFUL;
}
-
-unsigned long lca_init(unsigned long mem_start, unsigned long mem_end)
+void __init
+lca_init_arch(unsigned long *mem_start, unsigned long *mem_end)
{
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 0 for enabled and mapped to 0 */
- if ((*(vulp)LCA_IOC_W_BASE0 & (1UL<<33)) &&
- (*(vulp)LCA_IOC_T_BASE0 == 0))
+ switch (alpha_use_srm_setup)
{
- LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE0 & 0xffffffffUL;
- LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK0 & 0xffffffffUL;
- LCA_DMA_WIN_SIZE += 1;
-#if 1
- printk("lca_init: using Window 0 settings\n");
- printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
- *(vulp)LCA_IOC_W_BASE0,
- *(vulp)LCA_IOC_W_MASK0,
- *(vulp)LCA_IOC_T_BASE0);
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 0 for enabled and mapped to 0. */
+ if ((*(vulp)LCA_IOC_W_BASE0 & (1UL<<33))
+ && (*(vulp)LCA_IOC_T_BASE0 == 0)) {
+ LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE0 & 0xffffffffUL;
+ LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK0 & 0xffffffffUL;
+ LCA_DMA_WIN_SIZE += 1;
+#if 0
+ printk("lca_init: using Window 0 settings\n");
+ printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)LCA_IOC_W_BASE0,
+ *(vulp)LCA_IOC_W_MASK0,
+ *(vulp)LCA_IOC_T_BASE0);
#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if ((*(vulp)LCA_IOC_W_BASE1 & (1UL<<33)) &&
- (*(vulp)LCA_IOC_T_BASE1 == 0))
- {
- LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE1 & 0xffffffffUL;
- LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK1 & 0xffffffffUL;
- LCA_DMA_WIN_SIZE += 1;
+ break;
+ }
+
+ /* Check window 2 for enabled and mapped to 0. */
+ if ((*(vulp)LCA_IOC_W_BASE1 & (1UL<<33))
+ && (*(vulp)LCA_IOC_T_BASE1 == 0)) {
+ LCA_DMA_WIN_BASE = *(vulp)LCA_IOC_W_BASE1 & 0xffffffffUL;
+ LCA_DMA_WIN_SIZE = *(vulp)LCA_IOC_W_MASK1 & 0xffffffffUL;
+ LCA_DMA_WIN_SIZE += 1;
#if 1
- printk("lca_init: using Window 1 settings\n");
- printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
- *(vulp)LCA_IOC_W_BASE1,
- *(vulp)LCA_IOC_W_MASK1,
- *(vulp)LCA_IOC_T_BASE1);
+ printk("lca_init: using Window 1 settings\n");
+ printk("lca_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)LCA_IOC_W_BASE1,
+ *(vulp)LCA_IOC_W_MASK1,
+ *(vulp)LCA_IOC_T_BASE1);
#endif
- }
- else /* we must use our defaults... */
-#endif /* SRM_SETUP */
- {
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, window 1 is disabled. In the future, we may
- * want to use it to do scatter/gather DMA. Window 0
- * goes at 1 GB and is 1 GB large.
- */
- *(vulp)LCA_IOC_W_BASE1 = 0UL<<33;
+ break;
+ }
- *(vulp)LCA_IOC_W_BASE0 = 1UL<<33 | LCA_DMA_WIN_BASE;
- *(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE - 1;
- *(vulp)LCA_IOC_T_BASE0 = 0;
+ /* Otherwise, we must use our defaults. */
+ LCA_DMA_WIN_BASE = LCA_DMA_WIN_BASE_DEFAULT;
+ LCA_DMA_WIN_SIZE = LCA_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, window 1 is disabled. In the future, we may
+ * want to use it to do scatter/gather DMA.
+ *
+ * Window 0 goes at 1 GB and is 1 GB large.
+ */
+ *(vulp)LCA_IOC_W_BASE1 = 0UL<<33;
+
+ *(vulp)LCA_IOC_W_BASE0 = 1UL<<33 | LCA_DMA_WIN_BASE_DEFAULT;
+ *(vulp)LCA_IOC_W_MASK0 = LCA_DMA_WIN_SIZE_DEFAULT - 1;
+ *(vulp)LCA_IOC_T_BASE0 = 0;
+ break;
}
/*
@@ -345,10 +358,8 @@ unsigned long lca_init(unsigned long mem_start, unsigned long mem_end)
* data parity errors.
*/
*(vulp)LCA_IOC_PAR_DIS = 1UL<<5;
- return mem_start;
}
-
/*
* Constants used during machine-check handling. I suppose these
* could be moved into lca.h but I don't see much reason why anybody
@@ -373,12 +384,12 @@ unsigned long lca_init(unsigned long mem_start, unsigned long mem_end)
#define IOC_LOST ( 1<<5)
#define IOC_P_NBR ((__u32) ~((1<<13) - 1))
-
-void mem_error (unsigned long esr, unsigned long ear)
+static void
+mem_error (unsigned long esr, unsigned long ear)
{
printk(" %s %s error to %s occurred at address %x\n",
- *((esr & ESR_CEE) ? "Correctable" :
- (esr & ESR_UEE) ? "Uncorrectable" : "A"),
+ ((esr & ESR_CEE) ? "Correctable" :
+ (esr & ESR_UEE) ? "Uncorrectable" : "A"),
(esr & ESR_WRE) ? "write" : "read",
(esr & ESR_SOR) ? "memory" : "b-cache",
(unsigned) (ear & 0x1ffffff8));
@@ -396,8 +407,8 @@ void mem_error (unsigned long esr, unsigned long ear)
}
}
-
-void ioc_error (__u32 stat0, __u32 stat1)
+static void
+ioc_error (__u32 stat0, __u32 stat1)
{
static const char * const pci_cmd[] = {
"Interrupt Acknowledge", "Special", "I/O Read", "I/O Write",
@@ -427,9 +438,9 @@ void ioc_error (__u32 stat0, __u32 stat1)
}
}
-
-void lca_machine_check (unsigned long vector, unsigned long la,
- struct pt_regs *regs)
+void
+lca_machine_check (unsigned long vector, unsigned long la,
+ struct pt_regs *regs)
{
unsigned long * ptr;
const char * reason;
@@ -440,6 +451,7 @@ void lca_machine_check (unsigned long vector, unsigned long la,
printk(KERN_CRIT "lca: machine check (la=0x%lx,pc=0x%lx)\n",
la, regs->pc);
el.c = (struct el_common *) la;
+
/*
* The first quadword after the common header always seems to
* be the machine check reason---don't know why this isn't
@@ -504,7 +516,7 @@ void lca_machine_check (unsigned long vector, unsigned long la,
printk(KERN_CRIT " Unknown errorlog size %d\n", el.c->size);
}
- /* dump the the logout area to give all info: */
+ /* Dump the logout area to give all info. */
ptr = (unsigned long *) la;
for (i = 0; i < el.c->size / sizeof(long); i += 2) {
@@ -523,11 +535,11 @@ lca_clock_print(void)
{
long pmr_reg;
- pmr_reg = READ_PMR;
+ pmr_reg = LCA_READ_PMR;
printk("Status of clock control:\n");
- printk("\tPrimary clock divisor\t0x%x\n", GET_PRIMARY(pmr_reg));
- printk("\tOverride clock divisor\t0x%x\n", GET_OVERRIDE(pmr_reg));
+ printk("\tPrimary clock divisor\t0x%lx\n", LCA_GET_PRIMARY(pmr_reg));
+ printk("\tOverride clock divisor\t0x%lx\n", LCA_GET_OVERRIDE(pmr_reg));
printk("\tInterrupt override is %s\n",
(pmr_reg & LCA_PMR_INTO) ? "on" : "off");
printk("\tDMA override is %s\n",
@@ -540,8 +552,8 @@ lca_get_clock(void)
{
long pmr_reg;
- pmr_reg = READ_PMR;
- return(GET_PRIMARY(pmr_reg));
+ pmr_reg = LCA_READ_PMR;
+ return(LCA_GET_PRIMARY(pmr_reg));
}
@@ -550,9 +562,9 @@ lca_clock_fiddle(int divisor)
{
long pmr_reg;
- pmr_reg = READ_PMR;
- SET_PRIMARY_CLOCK(pmr_reg, divisor);
+ pmr_reg = LCA_READ_PMR;
+ LCA_SET_PRIMARY_CLOCK(pmr_reg, divisor);
/* lca_norm_clock = divisor; */
- WRITE_PMR(pmr_reg);
+ LCA_WRITE_PMR(pmr_reg);
mb();
}
diff --git a/arch/alpha/kernel/core_mcpcia.c b/arch/alpha/kernel/core_mcpcia.c
new file mode 100644
index 000000000..0e101eba8
--- /dev/null
+++ b/arch/alpha/kernel/core_mcpcia.c
@@ -0,0 +1,970 @@
+/*
+ * linux/arch/alpha/kernel/core_mcpcia.c
+ *
+ * Code common to all MCbus-PCI Adaptor core logic chipsets
+ *
+ * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/pci.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_mcpcia.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+
+/*
+ * NOTE: Herein lie back-to-back mb instructions. They are magic.
+ * One plausible explanation is that the i/o controller does not properly
+ * handle the system transaction. Another involves timing. Ho hum.
+ */
+
+extern asmlinkage void wrmces(unsigned long mces);
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#undef DEBUG_CFG
+
+#ifdef DEBUG_CFG
+# define DBG_CFG(args) printk args
+#else
+# define DBG_CFG(args)
+#endif
+
+#undef DEBUG_PCI
+
+#ifdef DEBUG_PCI
+# define DBG_PCI(args) printk args
+#else
+# define DBG_PCI(args)
+#endif
+
+#define DEBUG_MCHECK
+
+#ifdef DEBUG_MCHECK
+# define DBG_MCK(args) printk args
+# define DEBUG_MCHECK_DUMP
+#else
+# define DBG_MCK(args)
+#endif
+
+#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
+
+static volatile unsigned int MCPCIA_mcheck_expected[NR_CPUS];
+static volatile unsigned int MCPCIA_mcheck_taken[NR_CPUS];
+static unsigned int MCPCIA_jd[NR_CPUS];
+
+#define MCPCIA_MAX_HOSES 2
+static int mcpcia_num_hoses = 0;
+
+static int pci_probe_enabled = 0; /* disable to start */
+
+static struct linux_hose_info *mcpcia_root = NULL, *mcpcia_last_hose;
+
+static inline unsigned long long_align(unsigned long addr)
+{
+ return ((addr + (sizeof(unsigned long) - 1)) &
+ ~(sizeof(unsigned long) - 1));
+}
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address and setup the MCPCIA_HAXR2 register
+ * accordingly. It is therefore not safe to have concurrent
+ * invocations to configuration space access routines, but there
+ * really shouldn't be any need for this.
+ *
+ * Type 0:
+ *
+ * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 31:11 Device select bit.
+ * 10:8 Function number
+ * 7:2 Register number
+ *
+ * Type 1:
+ *
+ * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 31:24 reserved
+ * 23:16 bus number (8 bits = 128 possible buses)
+ * 15:11 Device number (5 bits)
+ * 10:8 function number
+ * 7:2 register number
+ *
+ * Notes:
+ * The function number selects which function of a multi-function device
+ * (e.g., SCSI and Ethernet).
+ *
+ * The register selects a DWORD (32 bit) register offset. Hence it
+ * doesn't get shifted by 2 bits as we want to "drop" the bottom two
+ * bits.
+ */
+
+static unsigned int
+conf_read(unsigned long addr, unsigned char type1,
+ struct linux_hose_info *hose)
+{
+ unsigned long flags;
+ unsigned long hoseno = hose->pci_hose_index;
+ unsigned int stat0, value, temp, cpu;
+
+ cpu = smp_processor_id();
+
+ save_and_cli(flags);
+
+ DBG_CFG(("conf_read(addr=0x%lx, type1=%d, hose=%d)\n",
+ addr, type1, hoseno));
+
+ /* Reset status register to avoid losing errors. */
+ stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno);
+ *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb();
+ temp = *(vuip)MCPCIA_CAP_ERR(hoseno);
+ DBG_CFG(("conf_read: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0));
+
+ mb();
+ draina();
+ MCPCIA_mcheck_expected[cpu] = 1;
+ MCPCIA_mcheck_taken[cpu] = 0;
+ mb();
+
+ /* Access configuration space. */
+ value = *((vuip)addr);
+ mb();
+ mb(); /* magic */
+
+ if (MCPCIA_mcheck_taken[cpu]) {
+ MCPCIA_mcheck_taken[cpu] = 0;
+ value = 0xffffffffU;
+ mb();
+ }
+ MCPCIA_mcheck_expected[cpu] = 0;
+ mb();
+
+ DBG_CFG(("conf_read(): finished\n"));
+
+ restore_flags(flags);
+ return value;
+}
+
+static void
+conf_write(unsigned long addr, unsigned int value, unsigned char type1,
+ struct linux_hose_info *hose)
+{
+ unsigned long flags;
+ unsigned long hoseno = hose->pci_hose_index;
+ unsigned int stat0, temp, cpu;
+
+ cpu = smp_processor_id();
+
+ save_and_cli(flags); /* avoid getting hit by machine check */
+
+ /* Reset status register to avoid losing errors. */
+ stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno);
+ *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb();
+ temp = *(vuip)MCPCIA_CAP_ERR(hoseno);
+ DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0));
+
+ draina();
+ MCPCIA_mcheck_expected[cpu] = 1;
+ mb();
+
+ /* Access configuration space. */
+ *((vuip)addr) = value;
+ mb();
+ mb(); /* magic */
+ temp = *(vuip)MCPCIA_CAP_ERR(hoseno); /* read to force the write */
+ MCPCIA_mcheck_expected[cpu] = 0;
+ mb();
+
+ DBG_CFG(("conf_write(): finished\n"));
+ restore_flags(flags);
+}
+
+static int
+mk_conf_addr(struct linux_hose_info *hose,
+ u8 bus, u8 device_fn, u8 where,
+ unsigned long *pci_addr, unsigned char *type1)
+{
+ unsigned long addr;
+
+ if (!pci_probe_enabled) /* if doing standard pci_init(), ignore */
+ return -1;
+
+ DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
+ " pci_addr=0x%p, type1=0x%p)\n",
+ bus, device_fn, where, pci_addr, type1));
+
+ /* Type 1 configuration cycle for *ALL* busses. */
+ *type1 = 1;
+
+ if (hose->pci_first_busno == bus)
+ bus = 0;
+ addr = (bus << 16) | (device_fn << 8) | (where);
+ addr <<= 5; /* swizzle for SPARSE */
+ addr |= hose->pci_config_space;
+
+ *pci_addr = addr;
+ DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+ return 0;
+}
+
+/* FIXME: At some point we should update these routines to use the new
+ PCI interface, which can jump through these hoops for us. */
+
+static inline int
+hose_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value,
+ struct linux_hose_info *hose)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ *value = 0xff;
+
+ if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= 0x00;
+ *value = conf_read(addr, type1, hose) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int
+hose_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value,
+ struct linux_hose_info *hose)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ *value = 0xffff;
+
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= 0x08;
+ *value = conf_read(addr, type1, hose) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int
+hose_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value,
+ struct linux_hose_info *hose)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ *value = 0xffffffff;
+
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= 0x18;
+ *value = conf_read(addr, type1, hose);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int
+hose_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value,
+ struct linux_hose_info *hose)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= 0x00;
+ conf_write(addr, value << ((where & 3) * 8), type1, hose);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int
+hose_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value,
+ struct linux_hose_info *hose)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= 0x08;
+ conf_write(addr, value << ((where & 3) * 8), type1, hose);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int
+hose_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value,
+ struct linux_hose_info *hose)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= 0x18;
+ conf_write(addr, value << ((where & 3) * 8), type1, hose);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+mcpcia_pcibios_read_config_byte (u8 bus, u8 devfn, u8 where, u8 *value)
+{
+ return hose_read_config_byte(bus, devfn, where, value, bus2hose[bus]);
+}
+
+int
+mcpcia_pcibios_read_config_word (u8 bus, u8 devfn, u8 where, u16 *value)
+{
+ return hose_read_config_word(bus, devfn, where, value, bus2hose[bus]);
+}
+
+int
+mcpcia_pcibios_read_config_dword (u8 bus, u8 devfn, u8 where, u32 *value)
+{
+ return hose_read_config_dword(bus, devfn, where, value, bus2hose[bus]);
+}
+
+int
+mcpcia_pcibios_write_config_byte (u8 bus, u8 devfn, u8 where, u8 value)
+{
+ return hose_write_config_byte(bus, devfn, where, value, bus2hose[bus]);
+}
+
+int
+mcpcia_pcibios_write_config_word (u8 bus, u8 devfn, u8 where, u16 value)
+{
+ return hose_write_config_word(bus, devfn, where, value, bus2hose[bus]);
+}
+
+int
+mcpcia_pcibios_write_config_dword (u8 bus, u8 devfn, u8 where, u32 val)
+{
+ return hose_write_config_dword(bus, devfn, where, val, bus2hose[bus]);
+}
+
+void __init
+mcpcia_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ struct linux_hose_info *hose;
+ unsigned int mcpcia_err;
+ unsigned int pci_rev;
+ int h;
+
+ *mem_start = long_align(*mem_start);
+
+ for (h = 0; h < NR_CPUS; h++) {
+ MCPCIA_mcheck_expected[h] = 0;
+ MCPCIA_mcheck_taken[h] = 0;
+ }
+
+ /* First, find how many hoses we have. */
+ for (h = 0; h < MCPCIA_MAX_HOSES; h++) {
+ pci_rev = *(vuip)MCPCIA_REV(h);
+#if 0
+ printk("mcpcia_init: got 0x%x for PCI_REV for hose %d\n",
+ pci_rev, h);
+#endif
+ if ((pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST) {
+ mcpcia_num_hoses++;
+
+ hose = (struct linux_hose_info *)*mem_start;
+ *mem_start = long_align(*mem_start + sizeof(*hose));
+
+ memset(hose, 0, sizeof(*hose));
+
+ if (mcpcia_root)
+ mcpcia_last_hose->next = hose;
+ else
+ mcpcia_root = hose;
+ mcpcia_last_hose = hose;
+
+ hose->pci_io_space = MCPCIA_IO(h);
+ hose->pci_mem_space = MCPCIA_DENSE(h);
+ hose->pci_config_space = MCPCIA_CONF(h);
+ hose->pci_sparse_space = MCPCIA_SPARSE(h);
+ hose->pci_hose_index = h;
+ hose->pci_first_busno = 255;
+ hose->pci_last_busno = 0;
+ }
+ }
+
+#if 1
+ printk("mcpcia_init: found %d hoses\n", mcpcia_num_hoses);
+#endif
+
+ /* Now do init for each hose. */
+ for (hose = mcpcia_root; hose; hose = hose->next) {
+ h = hose->pci_hose_index;
+#if 0
+ printk("mcpcia_init: -------- hose %d --------\n",h);
+ printk("MCPCIA_REV 0x%x\n", *(vuip)MCPCIA_REV(h));
+ printk("MCPCIA_WHOAMI 0x%x\n", *(vuip)MCPCIA_WHOAMI(h));
+ printk("MCPCIA_HAE_MEM 0x%x\n", *(vuip)MCPCIA_HAE_MEM(h));
+ printk("MCPCIA_HAE_IO 0x%x\n", *(vuip)MCPCIA_HAE_IO(h));
+ printk("MCPCIA_HAE_DENSE 0x%x\n", *(vuip)MCPCIA_HAE_DENSE(h));
+ printk("MCPCIA_INT_CTL 0x%x\n", *(vuip)MCPCIA_INT_CTL(h));
+ printk("MCPCIA_INT_REQ 0x%x\n", *(vuip)MCPCIA_INT_REQ(h));
+ printk("MCPCIA_INT_TARG 0x%x\n", *(vuip)MCPCIA_INT_TARG(h));
+ printk("MCPCIA_INT_ADR 0x%x\n", *(vuip)MCPCIA_INT_ADR(h));
+ printk("MCPCIA_INT_ADR_EXT 0x%x\n", *(vuip)MCPCIA_INT_ADR_EXT(h));
+ printk("MCPCIA_INT_MASK0 0x%x\n", *(vuip)MCPCIA_INT_MASK0(h));
+ printk("MCPCIA_INT_MASK1 0x%x\n", *(vuip)MCPCIA_INT_MASK1(h));
+ printk("MCPCIA_HBASE 0x%x\n", *(vuip)MCPCIA_HBASE(h));
+#endif
+
+ /*
+ * Set up error reporting. Make sure CPU_PE is OFF in the mask.
+ */
+#if 0
+ mcpcia_err = *(vuip)MCPCIA_ERR_MASK(h);
+ mcpcia_err &= ~4;
+ *(vuip)MCPCIA_ERR_MASK(h) = mcpcia_err;
+ mb();
+ mcpcia_err = *(vuip)MCPCIA_ERR_MASK;
+#endif
+
+ mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
+ mcpcia_err |= 0x0006; /* master/target abort */
+ *(vuip)MCPCIA_CAP_ERR(h) = mcpcia_err;
+ mb() ;
+ mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
+
+ switch (alpha_use_srm_setup)
+ {
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 0 for enabled and mapped to 0. */
+ if (((*(vuip)MCPCIA_W0_BASE(h) & 3) == 1)
+ && (*(vuip)MCPCIA_T0_BASE(h) == 0)
+ && ((*(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
+ MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W0_BASE(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("mcpcia_init: using Window 0 settings\n");
+ printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)MCPCIA_W0_BASE(h),
+ *(vuip)MCPCIA_W0_MASK(h),
+ *(vuip)MCPCIA_T0_BASE(h));
+#endif
+ break;
+ }
+
+ /* Check window 1 for enabled and mapped to 0. */
+ if (((*(vuip)MCPCIA_W1_BASE(h) & 3) == 1)
+ && (*(vuip)MCPCIA_T1_BASE(h) == 0)
+ && ((*(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
+ MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W1_BASE(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("mcpcia_init: using Window 1 settings\n");
+ printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)MCPCIA_W1_BASE(h),
+ *(vuip)MCPCIA_W1_MASK(h),
+ *(vuip)MCPCIA_T1_BASE(h));
+#endif
+ break;
+ }
+
+ /* Check window 2 for enabled and mapped to 0. */
+ if (((*(vuip)MCPCIA_W2_BASE(h) & 3) == 1)
+ && (*(vuip)MCPCIA_T2_BASE(h) == 0)
+ && ((*(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
+ MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W2_BASE(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("mcpcia_init: using Window 2 settings\n");
+ printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)MCPCIA_W2_BASE(h),
+ *(vuip)MCPCIA_W2_MASK(h),
+ *(vuip)MCPCIA_T2_BASE(h));
+#endif
+ break;
+ }
+
+ /* Check window 3 for enabled and mapped to 0. */
+ if (((*(vuip)MCPCIA_W3_BASE(h) & 3) == 1)
+ && (*(vuip)MCPCIA_T3_BASE(h) == 0)
+ && ((*(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U) > 0x0ff00000U)) {
+ MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W3_BASE(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U;
+ MCPCIA_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("mcpcia_init: using Window 3 settings\n");
+ printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)MCPCIA_W3_BASE(h),
+ *(vuip)MCPCIA_W3_MASK(h),
+ *(vuip)MCPCIA_T3_BASE(h));
+#endif
+ break;
+ }
+
+ /* Otherwise, we must use our defaults. */
+ MCPCIA_DMA_WIN_BASE = MCPCIA_DMA_WIN_BASE_DEFAULT;
+ MCPCIA_DMA_WIN_SIZE = MCPCIA_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, windows 1,2 and 3 are disabled. In the
+ * future, we may want to use them to do scatter/
+ * gather DMA.
+ *
+ * Window 0 goes at 1 GB and is 1 GB large.
+ */
+
+ *(vuip)MCPCIA_W0_BASE(h) = 1U | (MCPCIA_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
+ *(vuip)MCPCIA_W0_MASK(h) = (MCPCIA_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
+ *(vuip)MCPCIA_T0_BASE(h) = 0;
+
+ *(vuip)MCPCIA_W1_BASE(h) = 0x0 ;
+ *(vuip)MCPCIA_W2_BASE(h) = 0x0 ;
+ *(vuip)MCPCIA_W3_BASE(h) = 0x0 ;
+
+ *(vuip)MCPCIA_HBASE(h) = 0x0 ;
+ mb();
+ break;
+ }
+#if 0
+ {
+ unsigned int mcpcia_int_ctl = *((vuip)MCPCIA_INT_CTL(h));
+ printk("mcpcia_init: INT_CTL was 0x%x\n", mcpcia_int_ctl);
+ *(vuip)MCPCIA_INT_CTL(h) = 1U; mb();
+ mcpcia_int_ctl = *(vuip)MCPCIA_INT_CTL(h);
+ }
+#endif
+
+ /*
+ * Sigh... For the SRM setup, unless we know apriori what the HAE
+ * contents will be, we need to setup the arbitrary region bases
+ * so we can test against the range of addresses and tailor the
+ * region chosen for the SPARSE memory access.
+ *
+ * See include/asm-alpha/mcpcia.h for the SPARSE mem read/write.
+ */
+ if (alpha_use_srm_setup) {
+ unsigned int mcpcia_hae_mem = *(vuip)MCPCIA_HAE_MEM(h);
+
+ alpha_mv.sm_base_r1 = (mcpcia_hae_mem ) & 0xe0000000UL;
+ alpha_mv.sm_base_r2 = (mcpcia_hae_mem << 16) & 0xf8000000UL;
+ alpha_mv.sm_base_r3 = (mcpcia_hae_mem << 24) & 0xfc000000UL;
+
+ /*
+ * Set the HAE cache, so that setup_arch() code
+ * will use the SRM setting always. Our readb/writeb
+ * code in mcpcia.h expects never to have to change
+ * the contents of the HAE.
+ */
+ alpha_mv.hae_cache = mcpcia_hae_mem;
+
+ alpha_mv.mv_readb = mcpcia_srm_readb;
+ alpha_mv.mv_readw = mcpcia_srm_readw;
+ alpha_mv.mv_writeb = mcpcia_srm_writeb;
+ alpha_mv.mv_writew = mcpcia_srm_writew;
+ } else {
+ *(vuip)MCPCIA_HAE_MEM(h) = 0U; mb();
+ *(vuip)MCPCIA_HAE_MEM(h); /* read it back. */
+ *(vuip)MCPCIA_HAE_IO(h) = 0; mb();
+ *(vuip)MCPCIA_HAE_IO(h); /* read it back. */
+ }
+ }
+}
+
+static int
+mcpcia_pci_clr_err(int h)
+{
+ unsigned int cpu = smp_processor_id();
+
+ MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h);
+#if 0
+ DBG_MCK(("MCPCIA_pci_clr_err: MCPCIA CAP_ERR(%d) after read 0x%x\n",
+ h, MCPCIA_jd[cpu]));
+#endif
+ *(vuip)MCPCIA_CAP_ERR(h) = 0xffffffff; mb(); /* clear them all */
+ MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h);
+ return 0;
+}
+
+static void
+mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout)
+{
+ struct el_common_EV5_uncorrectable_mcheck *frame;
+ int i;
+
+ frame = &logout->procdata;
+
+ /* Print PAL fields */
+ for (i = 0; i < 24; i += 2) {
+ printk("\tpal temp[%d-%d]\t\t= %16lx %16lx\n\r",
+ i, i+1, frame->paltemp[i], frame->paltemp[i+1]);
+ }
+ for (i = 0; i < 8; i += 2) {
+ printk("\tshadow[%d-%d]\t\t= %16lx %16lx\n\r",
+ i, i+1, frame->shadow[i],
+ frame->shadow[i+1]);
+ }
+ printk("\tAddr of excepting instruction\t= %16lx\n\r",
+ frame->exc_addr);
+ printk("\tSummary of arithmetic traps\t= %16lx\n\r",
+ frame->exc_sum);
+ printk("\tException mask\t\t\t= %16lx\n\r",
+ frame->exc_mask);
+ printk("\tBase address for PALcode\t= %16lx\n\r",
+ frame->pal_base);
+ printk("\tInterrupt Status Reg\t\t= %16lx\n\r",
+ frame->isr);
+ printk("\tCURRENT SETUP OF EV5 IBOX\t= %16lx\n\r",
+ frame->icsr);
+ printk("\tI-CACHE Reg %s parity error\t= %16lx\n\r",
+ (frame->ic_perr_stat & 0x800L) ?
+ "Data" : "Tag",
+ frame->ic_perr_stat);
+ printk("\tD-CACHE error Reg\t\t= %16lx\n\r",
+ frame->dc_perr_stat);
+ if (frame->dc_perr_stat & 0x2) {
+ switch (frame->dc_perr_stat & 0x03c) {
+ case 8:
+ printk("\t\tData error in bank 1\n\r");
+ break;
+ case 4:
+ printk("\t\tData error in bank 0\n\r");
+ break;
+ case 20:
+ printk("\t\tTag error in bank 1\n\r");
+ break;
+ case 10:
+ printk("\t\tTag error in bank 0\n\r");
+ break;
+ }
+ }
+ printk("\tEffective VA\t\t\t= %16lx\n\r",
+ frame->va);
+ printk("\tReason for D-stream\t\t= %16lx\n\r",
+ frame->mm_stat);
+ printk("\tEV5 SCache address\t\t= %16lx\n\r",
+ frame->sc_addr);
+ printk("\tEV5 SCache TAG/Data parity\t= %16lx\n\r",
+ frame->sc_stat);
+ printk("\tEV5 BC_TAG_ADDR\t\t\t= %16lx\n\r",
+ frame->bc_tag_addr);
+ printk("\tEV5 EI_ADDR: Phys addr of Xfer\t= %16lx\n\r",
+ frame->ei_addr);
+ printk("\tFill Syndrome\t\t\t= %16lx\n\r",
+ frame->fill_syndrome);
+ printk("\tEI_STAT reg\t\t\t= %16lx\n\r",
+ frame->ei_stat);
+ printk("\tLD_LOCK\t\t\t\t= %16lx\n\r",
+ frame->ld_lock);
+}
+
+void
+mcpcia_machine_check(unsigned long type, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+#if 0
+ printk("mcpcia machine check ignored\n") ;
+#else
+ struct el_common *mchk_header;
+ struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout;
+ unsigned int cpu = smp_processor_id();
+ int h = 0;
+
+ mchk_header = (struct el_common *)la_ptr;
+ mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr;
+
+#if 0
+ DBG_MCK(("mcpcia_machine_check: type=0x%lx la_ptr=0x%lx\n",
+ type, la_ptr));
+ DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+ regs->pc, mchk_header->size, mchk_header->proc_offset,
+ mchk_header->sys_offset));
+#endif
+ /*
+ * Check if machine check is due to a badaddr() and if so,
+ * ignore the machine check.
+ */
+ mb();
+ mb(); /* magic */
+ if (MCPCIA_mcheck_expected[cpu]) {
+#if 0
+ DBG_MCK(("MCPCIA machine check expected\n"));
+#endif
+ MCPCIA_mcheck_expected[cpu] = 0;
+ MCPCIA_mcheck_taken[cpu] = 1;
+ mb();
+ mb(); /* magic */
+ draina();
+ mcpcia_pci_clr_err(h);
+ wrmces(0x7);
+ mb();
+ }
+#if 1
+ else {
+ printk("MCPCIA machine check NOT expected on CPU %d\n", cpu);
+ DBG_MCK(("mcpcia_machine_check: type=0x%lx pc=0x%lx"
+ " code=0x%lx\n",
+ type, regs->pc, mchk_header->code));
+
+ MCPCIA_mcheck_expected[cpu] = 0;
+ MCPCIA_mcheck_taken[cpu] = 1;
+ mb();
+ mb(); /* magic */
+ draina();
+ mcpcia_pci_clr_err(h);
+ wrmces(0x7);
+ mb();
+#ifdef DEBUG_MCHECK_DUMP
+ if (type == 0x620)
+ printk("MCPCIA machine check: system CORRECTABLE!\n");
+ else if (type == 0x630)
+ printk("MCPCIA machine check: processor CORRECTABLE!\n");
+ else
+ mcpcia_print_uncorrectable(mchk_logout);
+#endif /* DEBUG_MCHECK_DUMP */
+ }
+#endif
+#endif
+}
+
+/*==========================================================================*/
+
+#define PRIMARY(b) ((b)&0xff)
+#define SECONDARY(b) (((b)>>8)&0xff)
+#define SUBORDINATE(b) (((b)>>16)&0xff)
+
+static int __init
+hose_scan_bridges(struct linux_hose_info *hose, unsigned char bus)
+{
+ unsigned int devfn, l, class;
+ unsigned char hdr_type = 0;
+ unsigned int found = 0;
+
+ for (devfn = 0; devfn < 0xff; ++devfn) {
+ if (PCI_FUNC(devfn) == 0) {
+ hose_read_config_byte(bus, devfn, PCI_HEADER_TYPE,
+ &hdr_type, hose);
+ } else if (!(hdr_type & 0x80)) {
+ /* not a multi-function device */
+ continue;
+ }
+
+ /* Check if there is anything here. */
+ hose_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l, hose);
+ if (l == 0xffffffff || l == 0x00000000) {
+ hdr_type = 0;
+ continue;
+ }
+
+ /* See if this is a bridge device. */
+ hose_read_config_dword(bus, devfn, PCI_CLASS_REVISION,
+ &class, hose);
+
+ if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
+ unsigned int busses;
+
+ found++;
+
+ hose_read_config_dword(bus, devfn, PCI_PRIMARY_BUS,
+ &busses, hose);
+
+ DBG_PCI(("hose_scan_bridges: hose %d bus %d "
+ "slot %d busses 0x%x\n",
+ hose->pci_hose_index, bus, PCI_SLOT(devfn),
+ busses));
+
+ /*
+ * Do something with first_busno and last_busno
+ */
+ if (hose->pci_first_busno > PRIMARY(busses)) {
+ hose->pci_first_busno = PRIMARY(busses);
+ DBG_PCI(("hose_scan_bridges: hose %d bus %d "
+ "slot %d change first to %d\n",
+ hose->pci_hose_index, bus,
+ PCI_SLOT(devfn), PRIMARY(busses)));
+ }
+ if (hose->pci_last_busno < SUBORDINATE(busses)) {
+ hose->pci_last_busno = SUBORDINATE(busses);
+ DBG_PCI(("hose_scan_bridges: hose %d bus %d "
+ "slot %d change last to %d\n",
+ hose->pci_hose_index, bus,
+ PCI_SLOT(devfn),
+ SUBORDINATE(busses)));
+ }
+ /*
+ * Now scan everything underneath the bridge.
+ */
+ hose_scan_bridges(hose, SECONDARY(busses));
+ }
+ }
+ return found;
+}
+
+static void __init
+hose_reconfigure_bridges(struct linux_hose_info *hose, unsigned char bus)
+{
+ unsigned int devfn, l, class;
+ unsigned char hdr_type = 0;
+
+ for (devfn = 0; devfn < 0xff; ++devfn) {
+ if (PCI_FUNC(devfn) == 0) {
+ hose_read_config_byte(bus, devfn, PCI_HEADER_TYPE,
+ &hdr_type, hose);
+ } else if (!(hdr_type & 0x80)) {
+ /* not a multi-function device */
+ continue;
+ }
+
+ /* Check if there is anything here. */
+ hose_read_config_dword(bus, devfn, PCI_VENDOR_ID, &l, hose);
+ if (l == 0xffffffff || l == 0x00000000) {
+ hdr_type = 0;
+ continue;
+ }
+
+ /* See if this is a bridge device. */
+ hose_read_config_dword(bus, devfn, PCI_CLASS_REVISION,
+ &class, hose);
+
+ if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
+ unsigned int busses;
+
+ hose_read_config_dword(bus, devfn, PCI_PRIMARY_BUS,
+ &busses, hose);
+
+ /*
+ * First reconfigure everything underneath the bridge.
+ */
+ hose_reconfigure_bridges(hose, (busses >> 8) & 0xff);
+
+ /*
+ * Unconfigure this bridges bus numbers,
+ * pci_scan_bus() will fix this up properly.
+ */
+ busses &= 0xff000000;
+ hose_write_config_dword(bus, devfn, PCI_PRIMARY_BUS,
+ busses, hose);
+ }
+ }
+}
+
+static void __init
+mcpcia_fixup_busno(struct linux_hose_info *hose, unsigned char bus)
+{
+ unsigned int nbus;
+
+ /*
+ * First, scan for all bridge devices underneath this hose,
+ * to determine the first and last busnos.
+ */
+ if (!hose_scan_bridges(hose, 0)) {
+ /* none found, exit */
+ hose->pci_first_busno = bus;
+ hose->pci_last_busno = bus;
+ } else {
+ /*
+ * Reconfigure all bridge devices underneath this hose.
+ */
+ hose_reconfigure_bridges(hose, hose->pci_first_busno);
+ }
+
+ /*
+ * Now reconfigure the hose to it's new bus number and set up
+ * our bus2hose mapping for this hose.
+ */
+ nbus = hose->pci_last_busno - hose->pci_first_busno;
+
+ hose->pci_first_busno = bus;
+
+ DBG_PCI(("mcpcia_fixup_busno: hose %d startbus %d nbus %d\n",
+ hose->pci_hose_index, bus, nbus));
+
+ do {
+ bus2hose[bus++] = hose;
+ } while (nbus-- > 0);
+}
+
+static void __init
+mcpcia_probe(struct linux_hose_info *hose)
+{
+ static struct pci_bus *pchain = NULL;
+ struct pci_bus *pbus = &hose->pci_bus;
+ static unsigned char busno = 0;
+
+ /*
+ * Hoses include child PCI bridges in bus-range property,
+ * but we don't scan each of those ourselves, Linux generic PCI
+ * probing code will find child bridges and link them into this
+ * hose's root PCI device hierarchy.
+ */
+
+ pbus->number = pbus->secondary = busno;
+ pbus->sysdata = hose;
+
+ mcpcia_fixup_busno(hose, busno);
+
+ pbus->subordinate = pci_scan_bus(pbus); /* the original! */
+
+ /*
+ * Set the maximum subordinate bus of this hose.
+ */
+ hose->pci_last_busno = pbus->subordinate;
+#if 0
+ hose_write_config_byte(busno, 0, 0x41, hose->pci_last_busno, hose);
+#endif
+ busno = pbus->subordinate + 1;
+
+ /*
+ * Fixup the chain of primary PCI busses.
+ */
+ if (pchain) {
+ pchain->next = &hose->pci_bus;
+ pchain = pchain->next;
+ } else {
+ pchain = &pci_root;
+ memcpy(pchain, &hose->pci_bus, sizeof(pci_root));
+ }
+}
+
+void __init
+mcpcia_pci_fixup(void)
+{
+ struct linux_hose_info *hose;
+
+ /* Turn on Config space access finally! */
+ pci_probe_enabled = 1;
+
+ /* For each hose, probe and setup the devices on the hose. */
+ for (hose = mcpcia_root; hose; hose = hose->next)
+ mcpcia_probe(hose);
+}
diff --git a/arch/alpha/kernel/core_pyxis.c b/arch/alpha/kernel/core_pyxis.c
new file mode 100644
index 000000000..ab49de096
--- /dev/null
+++ b/arch/alpha/kernel/core_pyxis.c
@@ -0,0 +1,634 @@
+/*
+ * linux/arch/alpha/kernel/core_pyxis.c
+ *
+ * Code common to all PYXIS core logic chips.
+ *
+ * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
+ *
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_pyxis.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+
+/* NOTE: Herein are back-to-back mb instructions. They are magic.
+ One plausible explanation is that the I/O controller does not properly
+ handle the system transaction. Another involves timing. Ho hum. */
+
+extern asmlinkage void wrmces(unsigned long mces);
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#ifdef DEBUG
+# define DBG(args) printk args
+#else
+# define DBG(args)
+#endif
+
+#define DEBUG_MCHECK
+#ifdef DEBUG_MCHECK
+# define DBG_MCK(args) printk args
+#define DEBUG_MCHECK_DUMP
+#else
+# define DBG_MCK(args)
+#endif
+
+
+static volatile unsigned int PYXIS_mcheck_expected = 0;
+static volatile unsigned int PYXIS_mcheck_taken = 0;
+static unsigned int PYXIS_jd;
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address and setup the PYXIS_HAXR2 register
+ * accordingly. It is therefore not safe to have concurrent
+ * invocations to configuration space access routines, but there
+ * really shouldn't be any need for this.
+ *
+ * Type 0:
+ *
+ * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 31:11 Device select bit.
+ * 10:8 Function number
+ * 7:2 Register number
+ *
+ * Type 1:
+ *
+ * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 31:24 reserved
+ * 23:16 bus number (8 bits = 128 possible buses)
+ * 15:11 Device number (5 bits)
+ * 10:8 function number
+ * 7:2 register number
+ *
+ * Notes:
+ * The function number selects which function of a multi-function device
+ * (e.g., SCSI and Ethernet).
+ *
+ * The register selects a DWORD (32 bit) register offset. Hence it
+ * doesn't get shifted by 2 bits as we want to "drop" the bottom two
+ * bits.
+ */
+
+static int
+mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+ unsigned char *type1)
+{
+ unsigned long addr;
+
+ DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
+ " pci_addr=0x%p, type1=0x%p)\n",
+ bus, device_fn, where, pci_addr, type1));
+
+ if (bus == 0) {
+ int device;
+
+ device = device_fn >> 3;
+ /* Type 0 configuration cycle. */
+#if NOT_NOW
+ if (device > 20) {
+ DBG(("mk_conf_addr: device (%d) > 20, returning -1\n",
+ device));
+ return -1;
+ }
+#endif
+ *type1 = 0;
+ addr = (device_fn << 8) | (where);
+ } else {
+ /* Type 1 configuration cycle. */
+ *type1 = 1;
+ addr = (bus << 16) | (device_fn << 8) | (where);
+ }
+ *pci_addr = addr;
+ DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+ return 0;
+}
+
+static unsigned int
+conf_read(unsigned long addr, unsigned char type1)
+{
+ unsigned long flags;
+ unsigned int stat0, value, temp;
+ unsigned int pyxis_cfg = 0;
+
+ save_and_cli(flags); /* avoid getting hit by machine check */
+
+ DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
+
+ /* Reset status register to avoid losing errors. */
+ stat0 = *(vuip)PYXIS_ERR;
+ *(vuip)PYXIS_ERR = stat0; mb();
+ temp = *(vuip)PYXIS_ERR; /* re-read to force write */
+ DBG(("conf_read: PYXIS ERR was 0x%x\n", stat0));
+
+ /* If Type1 access, must set PYXIS CFG. */
+ if (type1) {
+ pyxis_cfg = *(vuip)PYXIS_CFG;
+ *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb();
+ temp = *(vuip)PYXIS_CFG; /* re-read to force write */
+ DBG(("conf_read: TYPE1 access\n"));
+ }
+
+ mb();
+ draina();
+ PYXIS_mcheck_expected = 1;
+ PYXIS_mcheck_taken = 0;
+ mb();
+
+ /* Access configuration space. */
+ value = *(vuip)addr;
+ mb();
+ mb(); /* magic */
+
+ if (PYXIS_mcheck_taken) {
+ PYXIS_mcheck_taken = 0;
+ value = 0xffffffffU;
+ mb();
+ }
+ PYXIS_mcheck_expected = 0;
+ mb();
+
+ /* If Type1 access, must reset IOC CFG so normal IO space ops work. */
+ if (type1) {
+ *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb();
+ temp = *(vuip)PYXIS_CFG; /* re-read to force write */
+ }
+
+ DBG(("conf_read(): finished\n"));
+
+ restore_flags(flags);
+ return value;
+}
+
+static void
+conf_write(unsigned long addr, unsigned int value, unsigned char type1)
+{
+ unsigned long flags;
+ unsigned int stat0, temp;
+ unsigned int pyxis_cfg = 0;
+
+ save_and_cli(flags); /* avoid getting hit by machine check */
+
+ /* Reset status register to avoid losing errors. */
+ stat0 = *(vuip)PYXIS_ERR;
+ *(vuip)PYXIS_ERR = stat0; mb();
+ temp = *(vuip)PYXIS_ERR; /* re-read to force write */
+ DBG(("conf_write: PYXIS ERR was 0x%x\n", stat0));
+
+ /* If Type1 access, must set PYXIS CFG. */
+ if (type1) {
+ pyxis_cfg = *(vuip)PYXIS_CFG;
+ *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb();
+ temp = *(vuip)PYXIS_CFG; /* re-read to force write */
+ DBG(("conf_read: TYPE1 access\n"));
+ }
+
+ draina();
+ PYXIS_mcheck_expected = 1;
+ mb();
+
+ /* Access configuration space. */
+ *(vuip)addr = value;
+ mb();
+ mb(); /* magic */
+ temp = *(vuip)PYXIS_ERR; /* do a PYXIS read to force the write */
+ PYXIS_mcheck_expected = 0;
+ mb();
+
+ /* If Type1 access, must reset IOC CFG so normal IO space ops work. */
+ if (type1) {
+ *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb();
+ temp = *(vuip)PYXIS_CFG; /* re-read to force write */
+ }
+
+ DBG(("conf_write(): finished\n"));
+ restore_flags(flags);
+}
+
+int
+pyxis_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value)
+{
+ unsigned long addr = PYXIS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ *value = 0xff;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x00;
+ *value = conf_read(addr, type1) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+pyxis_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value)
+{
+ unsigned long addr = PYXIS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ *value = 0xffff;
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x08;
+ *value = conf_read(addr, type1) >> ((where & 3) * 8);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+pyxis_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value)
+{
+ unsigned long addr = PYXIS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ *value = 0xffffffff;
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x18;
+ *value = conf_read(addr, type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+pyxis_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value)
+{
+ unsigned long addr = PYXIS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x00;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+pyxis_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value)
+{
+ unsigned long addr = PYXIS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x08;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+pyxis_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value)
+{
+ unsigned long addr = PYXIS_CONF;
+ unsigned long pci_addr;
+ unsigned char type1;
+
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ addr |= (pci_addr << 5) + 0x18;
+ conf_write(addr, value << ((where & 3) * 8), type1);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+void __init
+pyxis_enable_errors (void)
+{
+ unsigned int pyxis_err;
+
+#if 0
+ printk("pyxis_init: PYXIS_ERR_MASK 0x%x\n", *(vuip)PYXIS_ERR_MASK);
+ printk("pyxis_init: PYXIS_ERR 0x%x\n", *(vuip)PYXIS_ERR);
+ printk("pyxis_init: PYXIS_INT_REQ 0x%lx\n", *(vulp)PYXIS_INT_REQ);
+ printk("pyxis_init: PYXIS_INT_MASK 0x%lx\n", *(vulp)PYXIS_INT_MASK);
+ printk("pyxis_init: PYXIS_INT_ROUTE 0x%lx\n", *(vulp)PYXIS_INT_ROUTE);
+ printk("pyxis_init: PYXIS_INT_HILO 0x%lx\n", *(vulp)PYXIS_INT_HILO);
+ printk("pyxis_init: PYXIS_INT_CNFG 0x%x\n", *(vuip)PYXIS_INT_CNFG);
+ printk("pyxis_init: PYXIS_RT_COUNT 0x%lx\n", *(vulp)PYXIS_RT_COUNT);
+#endif
+
+ /*
+ * Set up error reporting. Make sure CPU_PE is OFF in the mask.
+ */
+ pyxis_err = *(vuip)PYXIS_ERR_MASK;
+ pyxis_err &= ~4;
+ *(vuip)PYXIS_ERR_MASK = pyxis_err; mb();
+ pyxis_err = *(vuip)PYXIS_ERR_MASK; /* re-read to force write */
+
+ pyxis_err = *(vuip)PYXIS_ERR ;
+ pyxis_err |= 0x180; /* master/target abort */
+ *(vuip)PYXIS_ERR = pyxis_err; mb();
+ pyxis_err = *(vuip)PYXIS_ERR; /* re-read to force write */
+}
+
+int __init
+pyxis_srm_window_setup (void)
+{
+ switch (alpha_use_srm_setup)
+ {
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 0 for enabled and mapped to 0. */
+ if (((*(vuip)PYXIS_W0_BASE & 3) == 1)
+ && (*(vuip)PYXIS_T0_BASE == 0)
+ && ((*(vuip)PYXIS_W0_MASK & 0xfff00000U) > 0x0ff00000U)) {
+ PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W0_BASE & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W0_MASK & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("pyxis_init: using Window 0 settings\n");
+ printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)PYXIS_W0_BASE,
+ *(vuip)PYXIS_W0_MASK,
+ *(vuip)PYXIS_T0_BASE);
+#endif
+ break;
+ }
+
+ /* Check window 1 for enabled and mapped to 0. */
+ if (((*(vuip)PYXIS_W1_BASE & 3) == 1)
+ && (*(vuip)PYXIS_T1_BASE == 0)
+ && ((*(vuip)PYXIS_W1_MASK & 0xfff00000U) > 0x0ff00000U)) {
+ PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W1_BASE & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W1_MASK & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("pyxis_init: using Window 1 settings\n");
+ printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)PYXIS_W1_BASE,
+ *(vuip)PYXIS_W1_MASK,
+ *(vuip)PYXIS_T1_BASE);
+#endif
+ break;
+ }
+
+ /* Check window 2 for enabled and mapped to 0. */
+ if (((*(vuip)PYXIS_W2_BASE & 3) == 1)
+ && (*(vuip)PYXIS_T2_BASE == 0)
+ && ((*(vuip)PYXIS_W2_MASK & 0xfff00000U) > 0x0ff00000U)) {
+ PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W2_BASE & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W2_MASK & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("pyxis_init: using Window 2 settings\n");
+ printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)PYXIS_W2_BASE,
+ *(vuip)PYXIS_W2_MASK,
+ *(vuip)PYXIS_T2_BASE);
+#endif
+ break;
+ }
+
+ /* Check window 3 for enabled and mapped to 0. */
+ if (((*(vuip)PYXIS_W3_BASE & 3) == 1)
+ && (*(vuip)PYXIS_T3_BASE == 0)
+ && ((*(vuip)PYXIS_W3_MASK & 0xfff00000U) > 0x0ff00000U)) {
+ PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W3_BASE & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W3_MASK & 0xfff00000U;
+ PYXIS_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("pyxis_init: using Window 3 settings\n");
+ printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
+ *(vuip)PYXIS_W3_BASE,
+ *(vuip)PYXIS_W3_MASK,
+ *(vuip)PYXIS_T3_BASE);
+#endif
+ break;
+ }
+
+ /* Otherwise, we must use our defaults. */
+ PYXIS_DMA_WIN_BASE = PYXIS_DMA_WIN_BASE_DEFAULT;
+ PYXIS_DMA_WIN_SIZE = PYXIS_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ return 0;
+ }
+ return 1;
+}
+
+void __init
+pyxis_native_window_setup(void)
+{
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, windows 1,2 and 3 are disabled. In the future, we may
+ * want to use them to do scatter/gather DMA.
+ *
+ * Window 0 goes at 1 GB and is 1 GB large.
+ */
+
+ *(vuip)PYXIS_W0_BASE = 1U | (PYXIS_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
+ *(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000U;
+ *(vuip)PYXIS_T0_BASE = 0;
+
+ *(vuip)PYXIS_W1_BASE = 0x0 ;
+ *(vuip)PYXIS_W2_BASE = 0x0 ;
+ *(vuip)PYXIS_W3_BASE = 0x0 ;
+ mb();
+}
+
+void __init
+pyxis_finish_init_arch(void)
+{
+ /*
+ * Next, clear the PYXIS_CFG register, which gets used
+ * for PCI Config Space accesses. That is the way
+ * we want to use it, and we do not want to depend on
+ * what ARC or SRM might have left behind...
+ */
+ {
+ unsigned int pyxis_cfg, temp;
+ pyxis_cfg = *(vuip)PYXIS_CFG; mb();
+ if (pyxis_cfg != 0) {
+#if 1
+ printk("PYXIS_init: CFG was 0x%x\n", pyxis_cfg);
+#endif
+ *(vuip)PYXIS_CFG = 0; mb();
+ temp = *(vuip)PYXIS_CFG; /* re-read to force write */
+ }
+ }
+
+ /*
+ * Sigh... For the SRM setup, unless we know apriori what the HAE
+ * contents will be, we need to setup the arbitrary region bases
+ * so we can test against the range of addresses and tailor the
+ * region chosen for the SPARSE memory access.
+ *
+ * See include/asm-alpha/pyxis.h for the SPARSE mem read/write.
+ */
+ if (alpha_use_srm_setup) {
+ unsigned int pyxis_hae_mem = *(vuip)PYXIS_HAE_MEM;
+
+ alpha_mv.sm_base_r1 = (pyxis_hae_mem ) & 0xe0000000UL;
+ alpha_mv.sm_base_r2 = (pyxis_hae_mem << 16) & 0xf8000000UL;
+ alpha_mv.sm_base_r3 = (pyxis_hae_mem << 24) & 0xfc000000UL;
+
+ /*
+ * Set the HAE cache, so that setup_arch() code
+ * will use the SRM setting always. Our readb/writeb
+ * code in pyxis.h expects never to have to change
+ * the contents of the HAE.
+ */
+ alpha_mv.hae_cache = pyxis_hae_mem;
+
+#ifndef CONFIG_ALPHA_GENERIC
+ /* In a generic kernel, we can always use BWIO. */
+ alpha_mv.mv_readb = pyxis_srm_readb;
+ alpha_mv.mv_readw = pyxis_srm_readw;
+ alpha_mv.mv_writeb = pyxis_srm_writeb;
+ alpha_mv.mv_writew = pyxis_srm_writew;
+#endif
+ } else {
+ *(vuip)PYXIS_HAE_MEM = 0U; mb();
+ *(vuip)PYXIS_HAE_MEM; /* re-read to force write */
+ *(vuip)PYXIS_HAE_IO = 0; mb();
+ *(vuip)PYXIS_HAE_IO; /* re-read to force write */
+ }
+
+ /*
+ * Finally, check that the PYXIS_CTRL1 has IOA_BEN set for
+ * enabling byte/word PCI bus space(s) access.
+ */
+ {
+ unsigned int ctrl1;
+ ctrl1 = *(vuip) PYXIS_CTRL1;
+ if (!(ctrl1 & 1)) {
+#if 1
+ printk("PYXIS_init: enabling byte/word PCI space\n");
+#endif
+ *(vuip) PYXIS_CTRL1 = ctrl1 | 1; mb();
+ ctrl1 = *(vuip)PYXIS_CTRL1; /* re-read */
+ }
+ }
+}
+
+void __init
+pyxis_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ pyxis_enable_errors();
+ if (!pyxis_srm_window_setup())
+ pyxis_native_window_setup();
+ pyxis_finish_init_arch();
+}
+
+static int
+pyxis_pci_clr_err(void)
+{
+ PYXIS_jd = *(vuip)PYXIS_ERR;
+ DBG(("PYXIS_pci_clr_err: PYXIS ERR after read 0x%x\n", PYXIS_jd));
+ *(vuip)PYXIS_ERR = 0x0180; mb();
+ PYXIS_jd = *(vuip)PYXIS_ERR; /* re-read to force write */
+ return 0;
+}
+
+void
+pyxis_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+ struct el_common *mchk_header;
+ struct el_PYXIS_sysdata_mcheck *mchk_sysdata;
+
+ mchk_header = (struct el_common *)la_ptr;
+
+ mchk_sysdata = (struct el_PYXIS_sysdata_mcheck *)
+ (la_ptr + mchk_header->sys_offset);
+
+#if 0
+ DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr));
+ DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+ regs->pc, mchk_header->size, mchk_header->proc_offset,
+ mchk_header->sys_offset));
+ DBG_MCK(("pyxis_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
+ PYXIS_mcheck_expected, mchk_sysdata->epic_dcsr,
+ mchk_sysdata->epic_pear));
+#endif
+#ifdef DEBUG_MCHECK_DUMP
+ {
+ unsigned long *ptr;
+ int i;
+
+ ptr = (unsigned long *)la_ptr;
+ for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+ printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
+ }
+ }
+#endif /* DEBUG_MCHECK_DUMP */
+
+ /*
+ * Check if machine check is due to a badaddr() and if so,
+ * ignore the machine check.
+ */
+ mb();
+ mb(); /* magic */
+ if (PYXIS_mcheck_expected) {
+ DBG(("PYXIS machine check expected\n"));
+ PYXIS_mcheck_expected = 0;
+ PYXIS_mcheck_taken = 1;
+ mb();
+ mb(); /* magic */
+ draina();
+ pyxis_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ }
+#if 1
+ else {
+ printk("PYXIS machine check NOT expected\n") ;
+ DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr));
+ DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x"
+ " sysoffset 0x%x\n",
+ regs->pc, mchk_header->size, mchk_header->proc_offset,
+ mchk_header->sys_offset));
+ PYXIS_mcheck_expected = 0;
+ PYXIS_mcheck_taken = 1;
+ mb();
+ mb(); /* magic */
+ draina();
+ pyxis_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ }
+#endif
+}
diff --git a/arch/alpha/kernel/t2.c b/arch/alpha/kernel/core_t2.c
index 69ca71404..13adb7bdf 100644
--- a/arch/alpha/kernel/t2.c
+++ b/arch/alpha/kernel/core_t2.c
@@ -1,5 +1,7 @@
/*
- * Code common to all T2 chips.
+ * linux/arch/alpha/kernel/core_t2.c
+ *
+ * Code common to all T2 core logic chips.
*
* Written by Jay A Estabrook (jestabro@amt.tay1.dec.com).
* December 1996.
@@ -7,17 +9,22 @@
* based on CIA code by David A Rusling (david.rusling@reo.mts.dec.com)
*
*/
-#include <linux/kernel.h>
#include <linux/config.h>
+#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/sched.h>
+#include <linux/init.h>
+#include <asm/ptrace.h>
#include <asm/system.h>
+
+#define __EXTERN_INLINE
#include <asm/io.h>
-#include <asm/hwrpb.h>
-#include <asm/ptrace.h>
-#include <asm/mmu_context.h>
+#include <asm/core_t2.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
/*
* NOTE: Herein lie back-to-back mb instructions. They are magic.
@@ -25,9 +32,6 @@
* handle the system transaction. Another involves timing. Ho hum.
*/
-extern struct hwrpb_struct *hwrpb;
-extern asmlinkage void wrmces(unsigned long mces);
-
/*
* Machine check reasons. Defined according to PALcode sources
* (osf.h and platform.h).
@@ -56,17 +60,9 @@ extern asmlinkage void wrmces(unsigned long mces);
# define DBGMC(args)
#endif
-#define vulp volatile unsigned long *
-#define vuip volatile unsigned int *
-
static volatile unsigned int T2_mcheck_expected[NR_CPUS];
static volatile unsigned int T2_mcheck_taken[NR_CPUS];
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int T2_DMA_WIN_BASE = T2_DMA_WIN_BASE_DEFAULT;
-unsigned int T2_DMA_WIN_SIZE = T2_DMA_WIN_SIZE_DEFAULT;
-unsigned long t2_sm_base;
-#endif /* SRM_SETUP */
/*
* Given a bus, device, and function number, compute resulting
@@ -103,15 +99,16 @@ unsigned long t2_sm_base;
*
* Notes:
* The function number selects which function of a multi-function device
- * (e.g., scsi and ethernet).
+ * (e.g., SCSI and Ethernet).
*
* The register selects a DWORD (32 bit) register offset. Hence it
* doesn't get shifted by 2 bits as we want to "drop" the bottom two
* bits.
*/
-static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned long *pci_addr,
- unsigned char *type1)
+
+static int
+mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+ unsigned char *type1)
{
unsigned long addr;
@@ -122,7 +119,7 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
if (bus == 0) {
int device = device_fn >> 3;
- /* type 0 configuration cycle: */
+ /* Type 0 configuration cycle. */
if (device > 8) {
DBG(("mk_conf_addr: device (%d)>20, returning -1\n",
@@ -133,7 +130,7 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
*type1 = 0;
addr = (0x0800L << device) | ((device_fn & 7) << 8) | (where);
} else {
- /* type 1 configuration cycle: */
+ /* Type 1 configuration cycle. */
*type1 = 1;
addr = (bus << 16) | (device_fn << 8) | (where);
}
@@ -142,12 +139,12 @@ static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
return 0;
}
-
-static unsigned int conf_read(unsigned long addr, unsigned char type1)
+static unsigned int
+conf_read(unsigned long addr, unsigned char type1)
{
unsigned long flags;
unsigned int stat0, value, cpu;
- unsigned long t2_cfg = 0; /* to keep gcc quiet */
+ unsigned long t2_cfg = 0;
cpu = smp_processor_id();
@@ -157,13 +154,14 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
#if 0
- /* reset status register to avoid losing errors: */
+ /* Reset status register to avoid losing errors. */
stat0 = *(vulp)T2_IOCSR;
*(vulp)T2_IOCSR = stat0;
mb();
DBG(("conf_read: T2 IOCSR was 0x%x\n", stat0));
#endif
- /* if Type1 access, must set T2 CFG */
+
+ /* If Type1 access, must set T2 CFG. */
if (type1) {
t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL;
*(vulp)T2_HAE_3 = 0x40000000UL | t2_cfg;
@@ -176,10 +174,12 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
T2_mcheck_expected[cpu] = 1;
T2_mcheck_taken[cpu] = 0;
mb();
- /* access configuration space: */
+
+ /* Access configuration space. */
value = *(vuip)addr;
mb();
mb(); /* magic */
+
if (T2_mcheck_taken[cpu]) {
T2_mcheck_taken[cpu] = 0;
value = 0xffffffffU;
@@ -188,7 +188,7 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
T2_mcheck_expected[cpu] = 0;
mb();
- /* if Type1 access, must reset T2 CFG so normal IO space ops work */
+ /* If Type1 access, must reset T2 CFG so normal IO space ops work. */
if (type1) {
*(vulp)T2_HAE_3 = t2_cfg;
mb();
@@ -199,13 +199,12 @@ static unsigned int conf_read(unsigned long addr, unsigned char type1)
return value;
}
-
-static void conf_write(unsigned long addr, unsigned int value,
- unsigned char type1)
+static void
+conf_write(unsigned long addr, unsigned int value, unsigned char type1)
{
unsigned long flags;
unsigned int stat0, cpu;
- unsigned long t2_cfg = 0; /* to keep gcc quiet */
+ unsigned long t2_cfg = 0;
cpu = smp_processor_id();
@@ -213,13 +212,14 @@ static void conf_write(unsigned long addr, unsigned int value,
cli();
#if 0
- /* reset status register to avoid losing errors: */
+ /* Reset status register to avoid losing errors. */
stat0 = *(vulp)T2_IOCSR;
*(vulp)T2_IOCSR = stat0;
mb();
DBG(("conf_write: T2 ERR was 0x%x\n", stat0));
#endif
- /* if Type1 access, must set T2 CFG */
+
+ /* If Type1 access, must set T2 CFG. */
if (type1) {
t2_cfg = *(vulp)T2_HAE_3 & ~0xc0000000UL;
*(vulp)T2_HAE_3 = t2_cfg | 0x40000000UL;
@@ -231,14 +231,16 @@ static void conf_write(unsigned long addr, unsigned int value,
T2_mcheck_expected[cpu] = 1;
mb();
- /* access configuration space: */
+
+ /* Access configuration space. */
*(vuip)addr = value;
mb();
mb(); /* magic */
+
T2_mcheck_expected[cpu] = 0;
mb();
- /* if Type1 access, must reset T2 CFG so normal IO space ops work */
+ /* If Type1 access, must reset T2 CFG so normal IO space ops work. */
if (type1) {
*(vulp)T2_HAE_3 = t2_cfg;
mb();
@@ -248,121 +250,109 @@ static void conf_write(unsigned long addr, unsigned int value,
}
-int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
+int
+t2_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value)
{
unsigned long addr = T2_CONF;
unsigned long pci_addr;
unsigned char type1;
*value = 0xff;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
addr |= (pci_addr << 5) + 0x00;
-
*value = conf_read(addr, type1) >> ((where & 3) * 8);
-
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short *value)
+int
+t2_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value)
{
unsigned long addr = T2_CONF;
unsigned long pci_addr;
unsigned char type1;
*value = 0xffff;
-
- if (where & 0x1) {
+ if (where & 0x1)
return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
addr |= (pci_addr << 5) + 0x08;
-
*value = conf_read(addr, type1) >> ((where & 3) * 8);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int *value)
+int
+t2_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value)
{
unsigned long addr = T2_CONF;
unsigned long pci_addr;
unsigned char type1;
*value = 0xffffffff;
- if (where & 0x3) {
+ if (where & 0x3)
return PCIBIOS_BAD_REGISTER_NUMBER;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
addr |= (pci_addr << 5) + 0x18;
*value = conf_read(addr, type1);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char value)
+int
+t2_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value)
{
unsigned long addr = T2_CONF;
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x00;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short value)
+int
+t2_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value)
{
unsigned long addr = T2_CONF;
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x08;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-
-int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int value)
+int
+t2_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value)
{
unsigned long addr = T2_CONF;
unsigned long pci_addr;
unsigned char type1;
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
addr |= (pci_addr << 5) + 0x18;
conf_write(addr, value << ((where & 3) * 8), type1);
return PCIBIOS_SUCCESSFUL;
}
-
-unsigned long t2_init(unsigned long mem_start, unsigned long mem_end)
+void __init
+t2_init_arch(unsigned long *mem_start, unsigned long *mem_end)
{
unsigned long t2_err;
unsigned int i;
@@ -394,138 +384,129 @@ unsigned long t2_init(unsigned long mem_start, unsigned long mem_end)
*(vulp)T2_TBASE2);
#endif
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 1 for enabled and mapped to 0 */
- if (((*(vulp)T2_WBASE1 & (3UL<<18)) == (2UL<<18)) &&
- (*(vulp)T2_TBASE1 == 0))
+ switch (alpha_use_srm_setup)
{
- T2_DMA_WIN_BASE = *(vulp)T2_WBASE1 & 0xfff00000UL;
- T2_DMA_WIN_SIZE = *(vulp)T2_WMASK1 & 0xfff00000UL;
- T2_DMA_WIN_SIZE += 0x00100000UL;
-/* DISABLE window 2!! ?? */
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 1 for enabled and mapped to 0. */
+ if (((*(vulp)T2_WBASE1 & (3UL<<18)) == (2UL<<18))
+ && (*(vulp)T2_TBASE1 == 0)) {
+ T2_DMA_WIN_BASE = *(vulp)T2_WBASE1 & 0xfff00000UL;
+ T2_DMA_WIN_SIZE = *(vulp)T2_WMASK1 & 0xfff00000UL;
+ T2_DMA_WIN_SIZE += 0x00100000UL;
+ /* DISABLE window 2!! ?? */
#if 1
- printk("t2_init: using Window 1 settings\n");
- printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
- *(vulp)T2_WBASE1,
- *(vulp)T2_WMASK1,
- *(vulp)T2_TBASE1);
+ printk("t2_init: using Window 1 settings\n");
+ printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)T2_WBASE1,
+ *(vulp)T2_WMASK1,
+ *(vulp)T2_TBASE1);
#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if (((*(vulp)T2_WBASE2 & (3UL<<18)) == (2UL<<18)) &&
- (*(vulp)T2_TBASE2 == 0))
- {
- T2_DMA_WIN_BASE = *(vulp)T2_WBASE2 & 0xfff00000UL;
- T2_DMA_WIN_SIZE = *(vulp)T2_WMASK2 & 0xfff00000UL;
- T2_DMA_WIN_SIZE += 0x00100000UL;
-/* DISABLE window 1!! ?? */
+ break;
+ }
+
+ /* Check window 2 for enabled and mapped to 0. */
+ if (((*(vulp)T2_WBASE2 & (3UL<<18)) == (2UL<<18))
+ && (*(vulp)T2_TBASE2 == 0)) {
+ T2_DMA_WIN_BASE = *(vulp)T2_WBASE2 & 0xfff00000UL;
+ T2_DMA_WIN_SIZE = *(vulp)T2_WMASK2 & 0xfff00000UL;
+ T2_DMA_WIN_SIZE += 0x00100000UL;
+ /* DISABLE window 1!! ?? */
#if 1
- printk("t2_init: using Window 2 settings\n");
- printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
- *(vulp)T2_WBASE2,
- *(vulp)T2_WMASK2,
- *(vulp)T2_TBASE2);
+ printk("t2_init: using Window 2 settings\n");
+ printk("t2_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)T2_WBASE2,
+ *(vulp)T2_WMASK2,
+ *(vulp)T2_TBASE2);
#endif
- }
- else /* we must use our defaults... */
-#endif /* SRM_SETUP */
- {
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, window 2 is disabled. In the future, we may
- * want to use it to do scatter/gather DMA. Window 1
- * goes at 1 GB and is 1 GB large.
- */
-
- /* WARNING!! must correspond to the DMA_WIN params!!! */
- *(vulp)T2_WBASE1 = 0x400807ffU;
- *(vulp)T2_WMASK1 = 0x3ff00000U;
- *(vulp)T2_TBASE1 = 0;
-
- *(vulp)T2_WBASE2 = 0x0;
- *(vulp)T2_HBASE = 0x0;
- }
+ break;
+ }
- /*
- * check ASN in HWRPB for validity, report if bad
- */
- if (hwrpb->max_asn != MAX_ASN) {
- printk("T2_init: max ASN from HWRPB is bad (0x%lx)\n",
- hwrpb->max_asn);
- hwrpb->max_asn = MAX_ASN;
+ /* Otherwise, we must use our defaults. */
+ T2_DMA_WIN_BASE = T2_DMA_WIN_BASE_DEFAULT;
+ T2_DMA_WIN_SIZE = T2_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, window 2 is disabled. In the future, we may
+ * want to use it to do scatter/gather DMA.
+ *
+ * Window 1 goes at 1 GB and is 1 GB large.
+ */
+
+ /* WARNING!! must correspond to the DMA_WIN params!!! */
+ *(vulp)T2_WBASE1 = 0x400807ffU;
+ *(vulp)T2_WMASK1 = 0x3ff00000U;
+ *(vulp)T2_TBASE1 = 0;
+
+ *(vulp)T2_WBASE2 = 0x0;
+ *(vulp)T2_HBASE = 0x0;
+ break;
}
/*
- * Finally, clear the T2_HAE_3 register, which gets used
- * for PCI Config Space accesses. That is the way
- * we want to use it, and we do not want to depend on
- * what ARC or SRM might have left behind...
+ * Sigh... For the SRM setup, unless we know apriori what the HAE
+ * contents will be, we need to setup the arbitrary region bases
+ * so we can test against the range of addresses and tailor the
+ * region chosen for the SPARSE memory access.
+ *
+ * See include/asm-alpha/t2.h for the SPARSE mem read/write.
*/
- {
- unsigned long t2_hae_1 = *(vulp)T2_HAE_1;
- unsigned long t2_hae_2 = *(vulp)T2_HAE_2;
- unsigned long t2_hae_3 = *(vulp)T2_HAE_3;
- unsigned long t2_hae_4 = *(vulp)T2_HAE_4;
-#if 1
- printk("T2_init: HAE1 was 0x%lx\n", t2_hae_1);
- printk("T2_init: HAE2 was 0x%lx\n", t2_hae_2);
- printk("T2_init: HAE3 was 0x%lx\n", t2_hae_3);
- printk("T2_init: HAE4 was 0x%lx\n", t2_hae_4);
-#endif
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /*
- * sigh... For the SRM setup, unless we know apriori what the HAE
- * contents will be, we need to setup the arbitrary region bases
- * so we can test against the range of addresses and tailor the
- * region chosen for the SPARSE memory access.
- *
- * see include/asm-alpha/t2.h for the SPARSE mem read/write
- */
- t2_sm_base = (t2_hae_1 << 27) & 0xf8000000UL;
- /*
- Set the HAE cache, so that setup_arch() code
- will use the SRM setting always. Our readb/writeb
- code in .h expects never to have to change
- the contents of the HAE.
- */
- hae.cache = t2_hae_1;
-#else /* SRM_SETUP */
- *(vulp)T2_HAE_1 = 0; mb();
- *(vulp)T2_HAE_2 = 0; mb();
- *(vulp)T2_HAE_3 = 0; mb();
+ if (alpha_use_srm_setup) {
+ unsigned long t2_hae_1 = *(vulp)T2_HAE_1;
+
+ alpha_mv.sm_base_r1 = (t2_hae_1 << 27) & 0xf8000000UL;
+
+ /*
+ * Set the HAE cache, so that setup_arch() code
+ * will use the SRM setting always. Our readb/writeb
+ * code in .h expects never to have to change
+ * the contents of the HAE.
+ */
+ alpha_mv.hae_cache = t2_hae_1;
+
+ alpha_mv.mv_readb = t2_srm_readb;
+ alpha_mv.mv_readw = t2_srm_readw;
+ alpha_mv.mv_writeb = t2_srm_writeb;
+ alpha_mv.mv_writew = t2_srm_writew;
+ } else {
+ *(vulp)T2_HAE_1 = 0; mb();
+ *(vulp)T2_HAE_2 = 0; mb();
+ *(vulp)T2_HAE_3 = 0; mb();
#if 0
- *(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */
+ *(vulp)T2_HAE_4 = 0; mb(); /* do not touch this */
#endif
-#endif /* SRM_SETUP */
}
-
- return mem_start;
}
#define SIC_SEIC (1UL << 33) /* System Event Clear */
-static struct sable_cpu_csr *sable_cpu_regs[4] = {
- (struct sable_cpu_csr *)CPU0_BASE,
- (struct sable_cpu_csr *)CPU1_BASE,
- (struct sable_cpu_csr *)CPU2_BASE,
- (struct sable_cpu_csr *)CPU3_BASE,
-};
-
-int t2_clear_errors(void)
+static int
+t2_clear_errors(void)
{
unsigned int cpu = smp_processor_id();
+ static struct sable_cpu_csr *cpu_regs = NULL;
+
+ switch (cpu)
+ {
+ case 0: cpu_regs = (struct sable_cpu_csr *)T2_CPU0_BASE; break;
+ case 1: cpu_regs = (struct sable_cpu_csr *)T2_CPU1_BASE; break;
+ case 2: cpu_regs = (struct sable_cpu_csr *)T2_CPU2_BASE; break;
+ case 3: cpu_regs = (struct sable_cpu_csr *)T2_CPU3_BASE; break;
+ }
DBGMC(("???????? t2_clear_errors\n"));
- sable_cpu_regs[cpu]->sic &= ~SIC_SEIC;
+ cpu_regs->sic &= ~SIC_SEIC;
/*
- * clear cpu errors
+ * clear CPU errors
*/
- sable_cpu_regs[cpu]->bcce |= sable_cpu_regs[cpu]->bcce;
- sable_cpu_regs[cpu]->cbe |= sable_cpu_regs[cpu]->cbe;
- sable_cpu_regs[cpu]->bcue |= sable_cpu_regs[cpu]->bcue;
- sable_cpu_regs[cpu]->dter |= sable_cpu_regs[cpu]->dter;
+ cpu_regs->bcce |= cpu_regs->bcce;
+ cpu_regs->cbe |= cpu_regs->cbe;
+ cpu_regs->bcue |= cpu_regs->bcue;
+ cpu_regs->dter |= cpu_regs->dter;
*(vulp)T2_CERR1 |= *(vulp)T2_CERR1;
*(vulp)T2_PERR1 |= *(vulp)T2_PERR1;
@@ -535,8 +516,9 @@ int t2_clear_errors(void)
return 0;
}
-void t2_machine_check(unsigned long vector, unsigned long la_ptr,
- struct pt_regs * regs)
+void
+t2_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
{
struct el_t2_logout_header *mchk_header;
struct el_t2_procdata_mcheck *mchk_procdata;
@@ -556,9 +538,9 @@ void t2_machine_check(unsigned long vector, unsigned long la_ptr,
mchk_header->elfl_sysoffset, mchk_header->elfl_procoffset));
mchk_sysdata = (struct el_t2_sysdata_mcheck *)
- (la_ptr + mchk_header->elfl_sysoffset);
+ (la_ptr + mchk_header->elfl_sysoffset);
mchk_procdata = (struct el_t2_procdata_mcheck *)
- (la_ptr + mchk_header->elfl_procoffset - sizeof(unsigned long)*32);
+ (la_ptr + mchk_header->elfl_procoffset - sizeof(unsigned long)*32);
DBGMC((" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
regs->pc, mchk_header->elfl_size, mchk_header->elfl_procoffset,
@@ -607,7 +589,7 @@ void t2_machine_check(unsigned long vector, unsigned long la_ptr,
case 0x96: reason = "i-cache read retryable error"; break;
case 0x98: reason = "processor detected hard error"; break;
- /* System specific (these are for Alcor, at least): */
+ /* System specific (these are for Alcor, at least): */
case 0x203: reason = "system detected uncorrectable ECC error"; break;
case 0x205: reason = "parity error detected by T2"; break;
case 0x207: reason = "non-existent memory error"; break;
@@ -636,7 +618,7 @@ void t2_machine_check(unsigned long vector, unsigned long la_ptr,
printk(KERN_CRIT " T2 machine check: %s%s\n",
reason, mchk_header->elfl_retry ? " (retryable)" : "");
- /* dump the the logout area to give all info: */
+ /* Dump the logout area to give all info. */
ptr = (unsigned long *)la_ptr;
for (i = 0; i < mchk_header->elfl_size / sizeof(long); i += 2) {
diff --git a/arch/alpha/kernel/core_tsunami.c b/arch/alpha/kernel/core_tsunami.c
new file mode 100644
index 000000000..382a97647
--- /dev/null
+++ b/arch/alpha/kernel/core_tsunami.c
@@ -0,0 +1,446 @@
+/*
+ * linux/arch/alpha/kernel/core_tsunami.c
+ *
+ * Code common to all TSUNAMI core logic chips.
+ *
+ * Based on code written by David A. Rusling (david.rusling@reo.mts.dec.com).
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/core_tsunami.h>
+#undef __EXTERN_INLINE
+
+#include "proto.h"
+
+/*
+ * NOTE: Herein lie back-to-back mb instructions. They are magic.
+ * One plausible explanation is that the I/O controller does not properly
+ * handle the system transaction. Another involves timing. Ho hum.
+ */
+
+/*
+ * BIOS32-style PCI interface:
+ */
+
+#ifdef DEBUG
+# define DBG(args) printk args
+#else
+# define DBG(args)
+#endif
+
+#define DEBUG_MCHECK
+#ifdef DEBUG_MCHECK
+# define DBG_MCK(args) printk args
+#define DEBUG_MCHECK_DUMP
+#else
+# define DBG_MCK(args)
+#endif
+
+static volatile unsigned int TSUNAMI_mcheck_expected[NR_CPUS];
+static volatile unsigned int TSUNAMI_mcheck_taken[NR_CPUS];
+static unsigned int TSUNAMI_jd[NR_CPUS];
+
+
+/*
+ * Given a bus, device, and function number, compute resulting
+ * configuration space address
+ * accordingly. It is therefore not safe to have concurrent
+ * invocations to configuration space access routines, but there
+ * really shouldn't be any need for this.
+ *
+ * Note that all config space accesses use Type 1 address format.
+ *
+ * Note also that type 1 is determined by non-zero bus number.
+ *
+ * Type 1:
+ *
+ * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
+ * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * 31:24 reserved
+ * 23:16 bus number (8 bits = 128 possible buses)
+ * 15:11 Device number (5 bits)
+ * 10:8 function number
+ * 7:2 register number
+ *
+ * Notes:
+ * The function number selects which function of a multi-function device
+ * (e.g., SCSI and Ethernet).
+ *
+ * The register selects a DWORD (32 bit) register offset. Hence it
+ * doesn't get shifted by 2 bits as we want to "drop" the bottom two
+ * bits.
+ */
+
+static int
+mk_conf_addr(u8 bus, u8 device_fn, u8 where, unsigned long *pci_addr,
+ unsigned char *type1)
+{
+ unsigned long addr;
+
+ DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, "
+ "pci_addr=0x%p, type1=0x%p)\n",
+ bus, device_fn, where, pci_addr, type1));
+
+ if (bus == 0) {
+ *type1 = 0;
+ } else {
+ /* Type 1 configuration cycle. */
+ *type1 = 1;
+ }
+ addr = (bus << 16) | (device_fn << 8) | (where);
+ *pci_addr = addr;
+ DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
+ return 0;
+}
+
+int
+tsunami_pcibios_read_config_byte (u8 bus, u8 device_fn, u8 where, u8 *value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ *value = 0xff;
+ if (mk_conf_addr(bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *value = __kernel_ldbu(*(vucp)(addr+TSUNAMI_PCI0_CONF));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+tsunami_pcibios_read_config_word (u8 bus, u8 device_fn, u8 where, u16 *value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ *value = 0xffff;
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *value = __kernel_ldwu(*(vusp)(addr+TSUNAMI_PCI0_CONF));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+tsunami_pcibios_read_config_dword (u8 bus, u8 device_fn, u8 where, u32 *value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ *value = 0xffffffff;
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *value = *(vuip)(addr+TSUNAMI_PCI0_CONF);
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+tsunami_pcibios_write_config_byte (u8 bus, u8 device_fn, u8 where, u8 value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (mk_conf_addr(bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ __kernel_stb(value, *(vucp)(addr+TSUNAMI_PCI0_CONF));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+tsunami_pcibios_write_config_word (u8 bus, u8 device_fn, u8 where, u16 value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (where & 0x1)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ __kernel_stw(value, *(vusp)(addr+TSUNAMI_PCI0_CONF));
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int
+tsunami_pcibios_write_config_dword (u8 bus, u8 device_fn, u8 where, u32 value)
+{
+ unsigned long addr;
+ unsigned char type1;
+
+ if (where & 0x3)
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+ if (mk_conf_addr(bus, device_fn, where, &addr, &type1))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ *(vuip)(addr+TSUNAMI_PCI0_CONF) = value;
+ return PCIBIOS_SUCCESSFUL;
+}
+
+void __init
+tsunami_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ unsigned long tsunami_err;
+ unsigned int i;
+
+#if 0
+ printk("tsunami_init: CChip registers:\n");
+ printk("CSR_CSC 0x%lx\n", *(vulp)TSUNAMI_CSR_CSC);
+ printk("CSR_MTR 0x%lx\n", *(vulp)TSUNAMI_CSR_MTR);
+ printk("CSR_MISC 0x%lx\n", *(vulp)TSUNAMI_CSR_MISC);
+ printk("CSR_DIM0 0x%lx\n", *(vulp)TSUNAMI_CSR_DIM0);
+ printk("CSR_DIM1 0x%lx\n", *(vulp)TSUNAMI_CSR_DIM1);
+ printk("CSR_DIR0 0x%lx\n", *(vulp)TSUNAMI_CSR_DIR0);
+ printk("CSR_DIR1 0x%lx\n", *(vulp)TSUNAMI_CSR_DIR1);
+ printk("CSR_DRIR 0x%lx\n", *(vulp)TSUNAMI_CSR_DRIR);
+
+ printk("tsunami_init: DChip registers:\n");
+ printk("CSR_DSC 0x%lx\n", *(vulp)TSUNAMI_CSR_DSC);
+ printk("CSR_STR 0x%lx\n", *(vulp)TSUNAMI_CSR_STR);
+ printk("CSR_DREV 0x%lx\n", *(vulp)TSUNAMI_CSR_DREV);
+
+ printk("tsunami_init: PChip registers:\n");
+ printk("PCHIP0_WSBA0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA0);
+ printk("PCHIP0_WSBA1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA1);
+ printk("PCHIP0_WSBA2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA2);
+ printk("PCHIP0_WSBA3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA3);
+ printk("PCHIP0_WSM0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM0);
+ printk("PCHIP0_WSM1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM1);
+ printk("PCHIP0_WSM2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM2);
+ printk("PCHIP0_WSM3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM3);
+ printk("PCHIP0_TBA0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA0);
+ printk("PCHIP0_TBA1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA1);
+ printk("PCHIP0_TBA2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA2);
+ printk("PCHIP0_TBA3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA3);
+ printk("PCHIP0_PCTL 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PCTL);
+ printk("PCHIP0_PLAT 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PLAT);
+ printk("PCHIP0_PERROR 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PERROR);
+ printk("PCHIP0_PERRMASK 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PERRMASK);
+#endif
+
+ for (i = 0; i < NR_CPUS; i++) {
+ TSUNAMI_mcheck_expected[i] = 0;
+ TSUNAMI_mcheck_taken[i] = 0;
+ }
+
+#ifdef NOT_YET
+ /*
+ * Set up error reporting. Make sure CPU_PE is OFF in the mask.
+ */
+ tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERRMASK;
+ tsunami_err &= ~20;
+ *(vulp)TSUNAMI_PCHIP0_PERRMASK = tsunami_err;
+ mb();
+ tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERRMASK;
+
+ tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERROR ;
+ tsunami_err |= 0x40; /* master/target abort */
+ *(vulp)TSUNAMI_PCHIP0_PERROR = tsunami_err ;
+ mb() ;
+ tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERROR ;
+#endif /* NOT_YET */
+
+ switch (alpha_use_srm_setup)
+ {
+ default:
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM_SETUP)
+ /* Check window 0 for enabled and mapped to 0. */
+ if (((*(vulp)TSUNAMI_PCHIP0_WSBA0 & 3) == 1)
+ && (*(vulp)TSUNAMI_PCHIP0_TBA0 == 0)
+ && ((*(vulp)TSUNAMI_PCHIP0_WSM0 & 0xfff00000U) > 0x0ff00000U)) {
+ TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA0 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM0 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("tsunami_init: using Window 0 settings\n");
+ printk("tsunami_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)TSUNAMI_PCHIP0_WSBA0,
+ *(vulp)TSUNAMI_PCHIP0_WSM0,
+ *(vulp)TSUNAMI_PCHIP0_TBA0);
+#endif
+ break;
+ }
+
+ /* Check window 1 for enabled and mapped to 0. */
+ if (((*(vulp)TSUNAMI_PCHIP0_WSBA1 & 3) == 1)
+ && (*(vulp)TSUNAMI_PCHIP0_TBA1 == 0)
+ && ((*(vulp)TSUNAMI_PCHIP0_WSM1 & 0xfff00000U) > 0x0ff00000U)) {
+ TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA1 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM1 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("tsunami_init: using Window 1 settings\n");
+ printk("tsunami_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)TSUNAMI_PCHIP0_WSBA1,
+ *(vulp)TSUNAMI_PCHIP0_WSM1,
+ *(vulp)TSUNAMI_PCHIP0_TBA1);
+#endif
+ break;
+ }
+
+ /* Check window 2 for enabled and mapped to 0. */
+ if (((*(vulp)TSUNAMI_PCHIP0_WSBA2 & 3) == 1)
+ && (*(vulp)TSUNAMI_PCHIP0_TBA2 == 0)
+ && ((*(vulp)TSUNAMI_PCHIP0_WSM2 & 0xfff00000U) > 0x0ff00000U)) {
+ TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA2 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM2 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("tsunami_init: using Window 2 settings\n");
+ printk("tsunami_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)TSUNAMI_PCHIP0_WSBA2,
+ *(vulp)TSUNAMI_PCHIP0_WSM2,
+ *(vulp)TSUNAMI_PCHIP0_TBA2);
+#endif
+ break;
+ }
+
+ /* Check window 3 for enabled and mapped to 0. */
+ if (((*(vulp)TSUNAMI_PCHIP0_WSBA3 & 3) == 1)
+ && (*(vulp)TSUNAMI_PCHIP0_TBA3 == 0)
+ && ((*(vulp)TSUNAMI_PCHIP0_WSM3 & 0xfff00000U) > 0x0ff00000U)) {
+ TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA3 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM3 & 0xfff00000U;
+ TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
+#if 1
+ printk("tsunami_init: using Window 3 settings\n");
+ printk("tsunami_init: BASE 0x%lx MASK 0x%lx TRANS 0x%lx\n",
+ *(vulp)TSUNAMI_PCHIP0_WSBA3,
+ *(vulp)TSUNAMI_PCHIP0_WSM3,
+ *(vulp)TSUNAMI_PCHIP0_TBA3);
+#endif
+ break;
+ }
+
+ /* Otherwise, we must use our defaults. */
+ TSUNAMI_DMA_WIN_BASE = TSUNAMI_DMA_WIN_BASE_DEFAULT;
+ TSUNAMI_DMA_WIN_SIZE = TSUNAMI_DMA_WIN_SIZE_DEFAULT;
+#endif
+ case 0:
+ /*
+ * Set up the PCI->physical memory translation windows.
+ * For now, windows 1,2 and 3 are disabled. In the future,
+ * we may want to use them to do scatter/gather DMA.
+ *
+ * Window 0 goes at 1 GB and is 1 GB large.
+ */
+
+ *(vulp)TSUNAMI_PCHIP0_WSBA0
+ = 1L | (TSUNAMI_DMA_WIN_BASE_DEFAULT & 0xfff00000U);
+ *(vulp)TSUNAMI_PCHIP0_WSM0
+ = (TSUNAMI_DMA_WIN_SIZE_DEFAULT - 1) & 0xfff00000UL;
+ *(vulp)TSUNAMI_PCHIP0_TBA0 = 0UL;
+
+ *(vulp)TSUNAMI_PCHIP0_WSBA1 = 0UL;
+ *(vulp)TSUNAMI_PCHIP0_WSBA2 = 0UL;
+ *(vulp)TSUNAMI_PCHIP0_WSBA3 = 0UL;
+ mb();
+ }
+}
+
+static int
+tsunami_pci_clr_err(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ TSUNAMI_jd[cpu] = *((vulp)TSUNAMI_PCHIP0_PERROR);
+ DBG(("TSUNAMI_pci_clr_err: PERROR after read 0x%x\n",TSUNAMI_jd[cpu]));
+ *((vulp)TSUNAMI_PCHIP0_PERROR) = 0x040; mb();
+ TSUNAMI_jd[cpu] = *((vulp)TSUNAMI_PCHIP0_PERROR);
+ return 0;
+}
+
+void
+tsunami_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+#if 1
+ printk("TSUNAMI machine check ignored\n") ;
+#else
+ struct el_common *mchk_header;
+ struct el_TSUNAMI_sysdata_mcheck *mchk_sysdata;
+ unsigned int cpu = smp_processor_id();
+
+ mchk_header = (struct el_common *)la_ptr;
+
+ mchk_sysdata = (struct el_TSUNAMI_sysdata_mcheck *)
+ (la_ptr + mchk_header->sys_offset);
+
+#if 0
+ DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr));
+ DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+ regs->pc, mchk_header->size, mchk_header->proc_offset,
+ mchk_header->sys_offset));
+ DBG_MCK(("tsunami_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
+ TSUNAMI_mcheck_expected[cpu], mchk_sysdata->epic_dcsr,
+ mchk_sysdata->epic_pear));
+#endif
+#ifdef DEBUG_MCHECK_DUMP
+ {
+ unsigned long *ptr;
+ int i;
+
+ ptr = (unsigned long *)la_ptr;
+ for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+ printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
+ }
+ }
+#endif /* DEBUG_MCHECK_DUMP */
+ /*
+ * Check if machine check is due to a badaddr() and if so,
+ * ignore the machine check.
+ */
+ mb();
+ mb(); /* magic */
+ if (TSUNAMI_mcheck_expected[cpu]) {
+ DBG(("TSUNAMI machine check expected\n"));
+ TSUNAMI_mcheck_expected[cpu] = 0;
+ TSUNAMI_mcheck_taken[cpu] = 1;
+ mb();
+ mb(); /* magic */
+ draina();
+ tsunami_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ }
+#if 1
+ else {
+ printk("TSUNAMI machine check NOT expected\n") ;
+ DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr));
+ DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+ regs->pc, mchk_header->size, mchk_header->proc_offset,
+ mchk_header->sys_offset));
+ TSUNAMI_mcheck_expected[cpu] = 0;
+ TSUNAMI_mcheck_taken[cpu] = 1;
+ mb();
+ mb(); /* magic */
+ draina();
+ tsunami_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ }
+#endif
+#endif
+}
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index 0bbc71926..79b0d818c 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -15,7 +15,7 @@
#define osf_vfork sys_fork
/*
- * These offsets must match with "struct hae" in io.h:
+ * These offsets must match with alpha_mv in <asm/machvec.h>.
*/
#define HAE_CACHE 0
#define HAE_REG 8
@@ -30,10 +30,12 @@
/*
* task structure offsets
*/
-#define TASK_STATE 0
-#define TASK_FLAGS 8
-#define TASK_SIGPENDING 16
-#define TASK_SIZE 24
+#define TASK_STATE 0
+#define TASK_FLAGS 8
+#define TASK_SIGPENDING 16
+#define TASK_ADDR_LIMIT 24
+#define TASK_EXEC_DOMAIN 32
+#define TASK_NEED_RESCHED 40
/*
* task flags (must match include/linux/sched.h):
@@ -107,7 +109,7 @@
stq $3,24($30); \
stq $4,32($30); \
stq $28,144($30); \
- lda $2,hae; \
+ lda $2,alpha_mv; \
stq $5,40($30); \
stq $6,48($30); \
stq $7,56($30); \
@@ -128,7 +130,7 @@
stq $18,176($30)
#define RESTORE_ALL \
- lda $19,hae; \
+ lda $19,alpha_mv; \
ldq $0,0($30); \
ldq $1,8($30); \
ldq $2,16($30); \
@@ -264,7 +266,7 @@ kernel_clone:
stq $18,40($30)
bis $31,2,$0 /* Register v0: syscall nr for fork() */
SAVE_ALL
- jsr $26,sys_clone
+ bsr $26,sys_clone
stq $0,0($30)
br $31,ret_from_sys_call
.end kernel_clone
@@ -559,6 +561,7 @@ sys_clone:
.globl alpha_switch_to
.ent alpha_switch_to
alpha_switch_to:
+ .prologue 0
bsr $1,do_switch_stack
call_pal PAL_swpctx
lda $16,-2($31)
@@ -615,8 +618,7 @@ ret_from_handle_bh:
and $0,8,$0
beq $0,restore_all
ret_from_reschedule:
- lda $0,need_resched
- ldl $2,0($0)
+ ldq $2,TASK_NEED_RESCHED($8)
lda $4,init_task_union
bne $2,reschedule
xor $4,$8,$4
@@ -923,7 +925,7 @@ sys_call_table:
.quad alpha_ni_syscall
.quad alpha_ni_syscall /* 110 */
.quad sys_sigsuspend
- .quad sys_ni_syscall
+ .quad osf_sigstack
.quad sys_recvmsg
.quad sys_sendmsg
.quad alpha_ni_syscall /* 115 */
@@ -1046,7 +1048,7 @@ sys_call_table:
.quad alpha_ni_syscall
.quad sys_getpgid
.quad sys_getsid
- .quad alpha_ni_syscall /* 235 */
+ .quad sys_sigaltstack /* 235 */
.quad alpha_ni_syscall
.quad alpha_ni_syscall
.quad alpha_ni_syscall
@@ -1133,7 +1135,7 @@ sys_call_table:
.quad sys_sysinfo
.quad sys_sysctl
.quad sys_idle /* 320 */
- .quad sys_umount
+ .quad sys_oldumount
.quad sys_swapon
.quad sys_times
.quad sys_personality
@@ -1179,6 +1181,7 @@ sys_call_table:
.quad sys_getrusage
.quad sys_wait4 /* 365 */
.quad sys_adjtimex
- .quad sys_ni_syscall
- .quad sys_ni_syscall
- .quad sys_ni_syscall /* 369 */
+ .quad sys_getcwd
+ .quad sys_capget
+ .quad sys_capset
+ .quad sys_ni_syscall /* 370 */
diff --git a/arch/alpha/kernel/es1888.c b/arch/alpha/kernel/es1888.c
new file mode 100644
index 000000000..10115ac8d
--- /dev/null
+++ b/arch/alpha/kernel/es1888.c
@@ -0,0 +1,47 @@
+/*
+ * linux/arch/alpha/kernel/es1888.c
+ *
+ * Init the built-in ES1888 sound chip (SB16 compatible)
+ */
+
+#include <linux/init.h>
+#include <asm/io.h>
+#include "proto.h"
+
+void __init
+es1888_init(void)
+{
+ /* Sequence of IO reads to init the audio controller */
+ inb(0x0229);
+ inb(0x0229);
+ inb(0x0229);
+ inb(0x022b);
+ inb(0x0229);
+ inb(0x022b);
+ inb(0x0229);
+ inb(0x0229);
+ inb(0x022b);
+ inb(0x0229);
+ inb(0x0220); /* This sets the base address to 0x220 */
+
+ /* Sequence to set DMA channels */
+ outb(0x01, 0x0226); /* reset */
+ inb(0x0226); /* pause */
+ outb(0x00, 0x0226); /* release reset */
+ while (!(inb(0x022e) & 0x80)) /* wait for bit 7 to assert*/
+ continue;
+ inb(0x022a); /* pause */
+ outb(0xc6, 0x022c); /* enable extended mode */
+ while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
+ continue;
+ outb(0xb1, 0x022c); /* setup for write to Interrupt CR */
+ while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
+ continue;
+ outb(0x14, 0x022c); /* set IRQ 5 */
+ while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
+ continue;
+ outb(0xb2, 0x022c); /* setup for write to DMA CR */
+ while (inb(0x022c) & 0x80) /* wait for bit 7 to deassert */
+ continue;
+ outb(0x18, 0x022c); /* set DMA channel 1 */
+}
diff --git a/arch/alpha/kernel/fpreg.c b/arch/alpha/kernel/fpreg.c
index 502144058..6da94c0cb 100644
--- a/arch/alpha/kernel/fpreg.c
+++ b/arch/alpha/kernel/fpreg.c
@@ -4,62 +4,58 @@
* (C) Copyright 1998 Linus Torvalds
*/
+#ifdef __alpha_cix__
+#define STT(reg,val) asm volatile ("ftoit $f"#reg",%0" : "=r"(val));
+#else
+#define STT(reg,val) asm volatile ("stt $f"#reg",%0" : "=m"(val));
+#endif
+
unsigned long
alpha_read_fp_reg (unsigned long reg)
{
- unsigned long r;
+ unsigned long val;
switch (reg) {
- case 0: asm ("stt $f0,%0" : "m="(r)); break;
- case 1: asm ("stt $f1,%0" : "m="(r)); break;
- case 2: asm ("stt $f2,%0" : "m="(r)); break;
- case 3: asm ("stt $f3,%0" : "m="(r)); break;
- case 4: asm ("stt $f4,%0" : "m="(r)); break;
- case 5: asm ("stt $f5,%0" : "m="(r)); break;
- case 6: asm ("stt $f6,%0" : "m="(r)); break;
- case 7: asm ("stt $f7,%0" : "m="(r)); break;
- case 8: asm ("stt $f8,%0" : "m="(r)); break;
- case 9: asm ("stt $f9,%0" : "m="(r)); break;
- case 10: asm ("stt $f10,%0" : "m="(r)); break;
- case 11: asm ("stt $f11,%0" : "m="(r)); break;
- case 12: asm ("stt $f12,%0" : "m="(r)); break;
- case 13: asm ("stt $f13,%0" : "m="(r)); break;
- case 14: asm ("stt $f14,%0" : "m="(r)); break;
- case 15: asm ("stt $f15,%0" : "m="(r)); break;
- case 16: asm ("stt $f16,%0" : "m="(r)); break;
- case 17: asm ("stt $f17,%0" : "m="(r)); break;
- case 18: asm ("stt $f18,%0" : "m="(r)); break;
- case 19: asm ("stt $f19,%0" : "m="(r)); break;
- case 20: asm ("stt $f20,%0" : "m="(r)); break;
- case 21: asm ("stt $f21,%0" : "m="(r)); break;
- case 22: asm ("stt $f22,%0" : "m="(r)); break;
- case 23: asm ("stt $f23,%0" : "m="(r)); break;
- case 24: asm ("stt $f24,%0" : "m="(r)); break;
- case 25: asm ("stt $f25,%0" : "m="(r)); break;
- case 26: asm ("stt $f26,%0" : "m="(r)); break;
- case 27: asm ("stt $f27,%0" : "m="(r)); break;
- case 28: asm ("stt $f28,%0" : "m="(r)); break;
- case 29: asm ("stt $f29,%0" : "m="(r)); break;
- case 30: asm ("stt $f30,%0" : "m="(r)); break;
- case 31: asm ("stt $f31,%0" : "m="(r)); break;
- default:
- break;
+ case 0: STT( 0, val); break;
+ case 1: STT( 1, val); break;
+ case 2: STT( 2, val); break;
+ case 3: STT( 3, val); break;
+ case 4: STT( 4, val); break;
+ case 5: STT( 5, val); break;
+ case 6: STT( 6, val); break;
+ case 7: STT( 7, val); break;
+ case 8: STT( 8, val); break;
+ case 9: STT( 9, val); break;
+ case 10: STT(10, val); break;
+ case 11: STT(11, val); break;
+ case 12: STT(12, val); break;
+ case 13: STT(13, val); break;
+ case 14: STT(14, val); break;
+ case 15: STT(15, val); break;
+ case 16: STT(16, val); break;
+ case 17: STT(17, val); break;
+ case 18: STT(18, val); break;
+ case 19: STT(19, val); break;
+ case 20: STT(20, val); break;
+ case 21: STT(21, val); break;
+ case 22: STT(22, val); break;
+ case 23: STT(23, val); break;
+ case 24: STT(24, val); break;
+ case 25: STT(25, val); break;
+ case 26: STT(26, val); break;
+ case 27: STT(27, val); break;
+ case 28: STT(28, val); break;
+ case 29: STT(29, val); break;
+ case 30: STT(30, val); break;
+ case 31: STT(31, val); break;
}
- return r;
+ return val;
}
-#if 1
-/*
- * This is IMHO the better way of implementing LDT(). But it
- * has the disadvantage that gcc 2.7.0 refuses to compile it
- * (invalid operand constraints), so instead, we use the uglier
- * macro below.
- */
-# define LDT(reg,val) \
- asm volatile ("ldt $f"#reg",%0" : : "m"(val));
+#ifdef __alpha_cix__
+#define LDT(reg,val) asm volatile ("itoft %0,$f"#reg : : "r"(val));
#else
-# define LDT(reg,val) \
- asm volatile ("ldt $f"#reg",0(%0)" : : "r"(&val));
+#define LDT(reg,val) asm volatile ("ldt $f"#reg",%0" : : "m"(val));
#endif
void
@@ -98,7 +94,5 @@ alpha_write_fp_reg (unsigned long reg, unsigned long val)
case 29: LDT(29, val); break;
case 30: LDT(30, val); break;
case 31: LDT(31, val); break;
- default:
- break;
}
}
diff --git a/arch/alpha/kernel/head.S b/arch/alpha/kernel/head.S
index a6bcd616d..92e11a82e 100644
--- a/arch/alpha/kernel/head.S
+++ b/arch/alpha/kernel/head.S
@@ -7,7 +7,6 @@
* the kernel global pointer and jump to the kernel entry-point.
*/
-#define __ASSEMBLY__
#include <asm/system.h>
#define halt call_pal PAL_halt
@@ -21,6 +20,7 @@ swapper_pg_dir=SWAPPER_PGD
.ent __start
_stext:
__start:
+ .prologue 0
br $27,1f
1: ldgp $29,0($27)
/* We need to get current loaded up with our first task... */
@@ -39,6 +39,7 @@ __start:
/* on entry here from SRM console, the HWPCB of this processor */
/* has been loaded, and $27 contains the task pointer */
__start_cpu:
+ .prologue 0
/* first order of business, load the GP */
br $26,1f
1: ldgp $29,0($26)
@@ -57,6 +58,7 @@ __start_cpu:
.globl wrent
.ent wrent
wrent:
+ .prologue 0
call_pal PAL_wrent
ret ($26)
.end wrent
@@ -65,6 +67,7 @@ wrent:
.globl wrkgp
.ent wrkgp
wrkgp:
+ .prologue 0
call_pal PAL_wrkgp
ret ($26)
.end wrkgp
@@ -73,6 +76,7 @@ wrkgp:
.globl wrusp
.ent wrusp
wrusp:
+ .prologue 0
call_pal PAL_wrusp
ret ($26)
.end wrusp
@@ -81,6 +85,7 @@ wrusp:
.globl rdusp
.ent rdusp
rdusp:
+ .prologue 0
call_pal PAL_rdusp
ret ($26)
.end rdusp
@@ -89,6 +94,7 @@ rdusp:
.globl rdmces
.ent rdmces
rdmces:
+ .prologue 0
call_pal PAL_rdmces
ret ($26)
.end rdmces
@@ -97,6 +103,7 @@ rdmces:
.globl wrmces
.ent wrmces
wrmces:
+ .prologue 0
call_pal PAL_wrmces
ret ($26)
.end wrmces
@@ -105,6 +112,7 @@ wrmces:
.globl whami
.ent whami
whami:
+ .prologue 0
call_pal PAL_whami
ret ($26)
.end whami
@@ -127,6 +135,7 @@ wripir:
.globl cserve_ena
.ent cserve_ena
cserve_ena:
+ .prologue 0
bis $16,$16,$17
lda $16,52($31)
call_pal PAL_cserve
@@ -137,6 +146,7 @@ cserve_ena:
.globl cserve_dis
.ent cserve_dis
cserve_dis:
+ .prologue 0
bis $16,$16,$17
lda $16,53($31)
call_pal PAL_cserve
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index bcac2da2b..0fee440e1 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -25,14 +25,17 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/bitops.h>
-#include <asm/dma.h>
+#include <asm/machvec.h>
+
+#include "proto.h"
+#include "irq.h"
#define vulp volatile unsigned long *
#define vuip volatile unsigned int *
-extern void timer_interrupt(struct pt_regs * regs);
-extern void cserve_update_hw(unsigned long, unsigned long);
-extern void handle_ipi(struct pt_regs *);
+unsigned int local_irq_count[NR_CPUS];
+unsigned int local_bh_count[NR_CPUS];
+
#define RTC_IRQ 8
#ifdef CONFIG_RTC
@@ -45,497 +48,169 @@ extern void handle_ipi(struct pt_regs *);
# error Unable to handle more than 64 irq levels.
#endif
-/* PROBE_MASK is the bitset of irqs that we consider for autoprobing: */
-#if defined(CONFIG_ALPHA_P2K)
- /* always mask out unused timer irq 0 and RTC irq 8 */
-# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~0x101UL)
-#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
- /* always mask out unused timer irq 0, "irqs" 20-30, and the EISA cascade: */
-# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~0xfff000000001UL)
-#elif defined(CONFIG_ALPHA_RUFFIAN)
- /* must leave timer irq 0 in the mask */
-# define PROBE_MASK ((1UL << NR_IRQS) - 1)
-#elif NR_IRQS == 64
- /* always mask out unused timer irq 0: */
-# define PROBE_MASK (~1UL)
+#ifdef CONFIG_ALPHA_GENERIC
+#define ACTUAL_NR_IRQS alpha_mv.nr_irqs
#else
- /* always mask out unused timer irq 0: */
-# define PROBE_MASK (((1UL << NR_IRQS) - 1) & ~1UL)
+#define ACTUAL_NR_IRQS NR_IRQS
#endif
/* Reserved interrupts. These must NEVER be requested by any driver!
- */
-#define IS_RESERVED_IRQ(irq) ((irq)==2) /* IRQ 2 used by hw cascade */
+ IRQ 2 used by hw cascade */
+#define IS_RESERVED_IRQ(irq) ((irq)==2)
-/*
- * Shadow-copy of masked interrupts.
- * The bits are used as follows:
- * 0.. 7 first (E)ISA PIC (irq level 0..7)
- * 8..15 second (E)ISA PIC (irq level 8..15)
- * Systems with PCI interrupt lines managed by GRU (e.g., Alcor, XLT)
- * or PYXIS (e.g. Miata, PC164-LX):
- * 16..47 PCI interrupts 0..31 (int at xxx_INT_MASK)
- * Mikasa:
- * 16..31 PCI interrupts 0..15 (short at I/O port 536)
- * Other systems (not Mikasa) with 16 PCI interrupt lines:
- * 16..23 PCI interrupts 0.. 7 (char at I/O port 26)
- * 24..31 PCI interrupts 8..15 (char at I/O port 27)
- * Systems with 17 PCI interrupt lines (e.g., Cabriolet and eb164):
- * 16..32 PCI interrupts 0..31 (int at I/O port 804)
- * For SABLE, which is really baroque, we manage 40 IRQ's, but the
- * hardware really only supports 24, not via normal ISA PIC,
- * but cascaded custom 8259's, etc.
- * 0-7 (char at 536)
- * 8-15 (char at 53a)
- * 16-23 (char at 53c)
- */
-static unsigned long irq_mask = ~0UL;
-#ifdef CONFIG_ALPHA_SABLE
/*
- * Note that the vector reported by the SRM PALcode corresponds to the
- * interrupt mask bits, but we have to manage via more normal IRQs.
- *
- * We have to be able to go back and forth between MASK bits and IRQ:
- * these tables help us do so.
+ * Shadow-copy of masked interrupts.
*/
-static char sable_irq_to_mask[NR_IRQS] = {
- -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */
- -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7 */
- -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */
- 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */
-};
-#define IRQ_TO_MASK(irq) (sable_irq_to_mask[(irq)])
-static char sable_mask_to_irq[NR_IRQS] = {
- 34, 33, 32, 12, 35, 36, 1, 6, /* mask 0-7 */
- 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */
- 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */
-};
-#else /* CONFIG_ALPHA_SABLE */
-#define IRQ_TO_MASK(irq) (irq)
-#endif /* CONFIG_ALPHA_SABLE */
+unsigned long alpha_irq_mask = ~0UL;
/*
- * Update the hardware with the irq mask passed in MASK. The function
- * exploits the fact that it is known that only bit IRQ has changed.
+ * The ack_irq routine used by 80% of the systems.
*/
-static inline void
-sable_update_hw(unsigned long irq, unsigned long mask)
+void
+generic_ack_irq(unsigned long irq)
{
- /* The "irq" argument is really the mask bit number */
- switch (irq) {
- case 16 ... 23:
- outb(mask >> 16, 0x53d);
- break;
- case 8 ... 15:
- outb(mask >> 8, 0x53b);
- break;
- case 0 ... 7:
- outb(mask, 0x537);
- break;
+ if (irq < 16) {
+ /* Ack the interrupt making it the lowest priority */
+ /* First the slave .. */
+ if (irq > 7) {
+ outb(0xE0 | (irq - 8), 0xa0);
+ irq = 2;
+ }
+ /* .. then the master */
+ outb(0xE0 | irq, 0x20);
}
}
-static inline void
-noritake_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 32 ... 47:
- outw(~(mask >> 32), 0x54c);
- break;
- case 16 ... 31:
- outw(~(mask >> 16), 0x54a);
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
-}
+/*
+ * Dispatch device interrupts.
+ */
-#ifdef CONFIG_ALPHA_MIATA
-static inline void
-miata_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 16 ... 47:
- /* Make CERTAIN none of the bogus ints get enabled... */
- *(vulp)PYXIS_INT_MASK =
- ~((long)mask >> 16) & ~0x4000000000000e3bUL;
- mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_MASK;
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
-}
-#endif
+/* Handle ISA interrupt via the PICs. */
-#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
-static inline void
-alcor_and_xlt_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 16 ... 47:
- /* On Alcor, at least, lines 20..30 are not connected and can
- generate spurrious interrupts if we turn them on while IRQ
- probing. So explicitly mask them out. */
- mask |= 0x7ff000000000UL;
-
- /* Note inverted sense of mask bits: */
- *(vuip)GRU_INT_MASK = ~(mask >> 16);
- mb();
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
-}
+#if defined(CONFIG_ALPHA_GENERIC)
+# define IACK_SC alpha_mv.iack_sc
+#elif defined(CONFIG_ALPHA_APECS)
+# define IACK_SC APECS_IACK_SC
+#elif defined(CONFIG_ALPHA_LCA)
+# define IACK_SC LCA_IACK_SC
+#elif defined(CONFIG_ALPHA_CIA)
+# define IACK_SC CIA_IACK_SC
+#elif defined(CONFIG_ALPHA_PYXIS)
+# define IACK_SC PYXIS_IACK_SC
+#elif defined(CONFIG_ALPHA_TSUNAMI)
+# define IACK_SC TSUNAMI_PCI0_IACK_SC
+#else
+ /* This is bogus but necessary to get it to compile on all platforms. */
+# define IACK_SC 1L
#endif
-static inline void
-mikasa_update_hw(unsigned long irq, unsigned long mask)
+void
+isa_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- switch (irq) {
- case 16 ... 31:
- outw(~(mask >> 16), 0x536); /* note invert */
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
-}
-
-#if defined(CONFIG_ALPHA_RUFFIAN)
-static inline void
-ruffian_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 16 ... 47:
- /* Note inverted sense of mask bits: */
- /* Make CERTAIN none of the bogus ints get enabled... */
- *(vulp)PYXIS_INT_MASK =
- ~((long)mask >> 16) & 0x00000000ffffffbfUL; mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_MASK;
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
+#if 1
+ /*
+ * Generate a PCI interrupt acknowledge cycle. The PIC will
+ * respond with the interrupt vector of the highest priority
+ * interrupt that is pending. The PALcode sets up the
+ * interrupts vectors such that irq level L generates vector L.
+ */
+ int j = *(vuip) IACK_SC;
+ j &= 0xff;
+ if (j == 7) {
+ if (!(inb(0x20) & 0x80)) {
+ /* It's only a passive release... */
+ return;
+ }
}
-}
-#endif /* RUFFIAN */
-
-#if defined(CONFIG_ALPHA_SX164)
-static inline void
-sx164_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 16 ... 39:
-#if defined(CONFIG_ALPHA_SRM)
- cserve_update_hw(irq, mask);
+ handle_irq(j, j, regs);
#else
- /* make CERTAIN none of the bogus ints get enabled */
- *(vulp)PYXIS_INT_MASK =
- ~((long)mask >> 16) & ~0x000000000000003bUL; mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_MASK;
-#endif /* SRM */
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
+ unsigned long pic;
-}
-#endif /* SX164 */
+ /*
+ * It seems to me that the probability of two or more *device*
+ * interrupts occurring at almost exactly the same time is
+ * pretty low. So why pay the price of checking for
+ * additional interrupts here if the common case can be
+ * handled so much easier?
+ */
+ /*
+ * The first read of gives you *all* interrupting lines.
+ * Therefore, read the mask register and and out those lines
+ * not enabled. Note that some documentation has 21 and a1
+ * write only. This is not true.
+ */
+ pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */
+ pic &= ~alpha_irq_mask; /* apply mask */
+ pic &= 0xFFFB; /* mask out cascade & hibits */
-#if defined(CONFIG_ALPHA_DP264)
-static inline void
-dp264_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 16 ... 63:
- /* make CERTAIN none of the bogus ints get enabled */
- /* HACK ALERT! only CPU#0 is used currently */
- *(vulp)TSUNAMI_CSR_DIM0 =
- ~(mask) & ~0x0000000000000000UL; mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)TSUNAMI_CSR_DIM0;
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
+ while (pic) {
+ int j = ffz(~pic);
+ pic &= pic - 1;
+ handle_irq(j, j, regs);
}
+#endif
}
-#endif /* DP264 */
-#if defined(CONFIG_ALPHA_RAWHIDE)
-static inline void
-rawhide_update_hw(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 16 ... 39: /* PCI bus 0 with EISA bridge */
- *(vuip)MCPCIA_INT_MASK0(0) =
- (~((mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb();
- /* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(0);
- break;
- case 40 ... 63: /* PCI bus 1 with builtin NCR810 SCSI */
- *(vuip)MCPCIA_INT_MASK0(1) =
- (~((mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb();
- /* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(1);
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
-}
-#endif /* RAWHIDE */
+/* Handle interrupts from the SRM, assuming no additional weirdness. */
-/*
- * HW update code for the following platforms:
- *
- * CABRIOLET (AlphaPC64)
- * EB66P
- * EB164
- * PC164
- * LX164
- */
-static inline void
-update_hw_35(unsigned long irq, unsigned long mask)
+void
+srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
{
- switch (irq) {
- case 16 ... 34:
-#if defined(CONFIG_ALPHA_SRM)
- cserve_update_hw(irq, mask);
-#else /* SRM */
- outl(irq_mask >> 16, 0x804);
-#endif /* SRM */
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
- }
-}
+ int irq, ack;
+ unsigned long flags;
-static inline void
-update_hw_32(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 24 ... 31:
- outb(mask >> 24, 0x27);
- break;
- case 16 ... 23:
- outb(mask >> 16, 0x26);
- break;
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
-}
-}
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
-static inline void
-update_hw_16(unsigned long irq, unsigned long mask)
-{
- switch (irq) {
- case 8 ... 15: /* ISA PIC2 */
- outb(mask >> 8, 0xA1);
- break;
- case 0 ... 7: /* ISA PIC1 */
- outb(mask, 0x21);
- break;
-}
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
}
+
/*
- * We manipulate the hardware ourselves.
+ * Initial irq handlers.
*/
-static void update_hw(unsigned long irq, unsigned long mask)
-{
-#if defined(CONFIG_ALPHA_SABLE)
- sable_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_MIATA)
- miata_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_NORITAKE)
- noritake_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
- alcor_and_xlt_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_MIKASA)
- mikasa_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_SX164)
- sx164_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_RUFFIAN)
- ruffian_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_DP264)
- dp264_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_RAWHIDE)
- rawhide_update_hw(irq, mask);
-#elif defined(CONFIG_ALPHA_CABRIOLET) || \
- defined(CONFIG_ALPHA_EB66P) || \
- defined(CONFIG_ALPHA_EB164) || \
- defined(CONFIG_ALPHA_PC164) || \
- defined(CONFIG_ALPHA_LX164)
- update_hw_35(irq, mask);
-#elif defined(CONFIG_ALPHA_EB66) || \
- defined(CONFIG_ALPHA_EB64P)
- update_hw_32(irq, mask);
-#elif NR_IRQS == 16
- update_hw_16(irq, mask);
-#else
-#error "How do I update the IRQ hardware?"
-#endif
-}
+static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
+static struct irqaction *irq_action[NR_IRQS];
-static inline void mask_irq(unsigned long irq)
+
+static inline void
+mask_irq(unsigned long irq)
{
- irq_mask |= (1UL << irq);
- update_hw(irq, irq_mask);
+ alpha_mv.update_irq_hw(irq, alpha_irq_mask |= 1UL << irq, 0);
}
-static inline void unmask_irq(unsigned long irq)
+static inline void
+unmask_irq(unsigned long irq)
{
- irq_mask &= ~(1UL << irq);
- update_hw(irq, irq_mask);
+ alpha_mv.update_irq_hw(irq, alpha_irq_mask &= ~(1UL << irq), 1);
}
-void disable_irq(unsigned int irq_nr)
+void
+disable_irq(unsigned int irq_nr)
{
unsigned long flags;
save_and_cli(flags);
- mask_irq(IRQ_TO_MASK(irq_nr));
+ mask_irq(irq_nr);
restore_flags(flags);
}
-void enable_irq(unsigned int irq_nr)
+void
+enable_irq(unsigned int irq_nr)
{
unsigned long flags;
save_and_cli(flags);
- unmask_irq(IRQ_TO_MASK(irq_nr));
+ unmask_irq(irq_nr);
restore_flags(flags);
}
-/*
- * Initial irq handlers.
- */
-static struct irqaction timer_irq = { NULL, 0, 0, NULL, NULL, NULL};
-static struct irqaction *irq_action[NR_IRQS];
-
-int get_irq_list(char *buf)
-{
- int i, len = 0;
- struct irqaction * action;
- int cpu = smp_processor_id();
-
- for (i = 0; i < NR_IRQS; i++) {
- action = irq_action[i];
- if (!action)
- continue;
- len += sprintf(buf+len, "%2d: %10u %c %s",
- i, kstat.irqs[cpu][i],
- (action->flags & SA_INTERRUPT) ? '+' : ' ',
- action->name);
- for (action=action->next; action; action = action->next) {
- len += sprintf(buf+len, ",%s %s",
- (action->flags & SA_INTERRUPT) ? " +" : "",
- action->name);
- }
- len += sprintf(buf+len, "\n");
- }
- return len;
-}
-
-static inline void ack_irq(int irq)
-{
-#ifdef CONFIG_ALPHA_SABLE
- /* Note that the "irq" here is really the mask bit number */
- switch (irq) {
- case 0 ... 7:
- outb(0xE0 | (irq - 0), 0x536);
- outb(0xE0 | 1, 0x534); /* slave 0 */
- break;
- case 8 ... 15:
- outb(0xE0 | (irq - 8), 0x53a);
- outb(0xE0 | 3, 0x534); /* slave 1 */
- break;
- case 16 ... 24:
- outb(0xE0 | (irq - 16), 0x53c);
- outb(0xE0 | 4, 0x534); /* slave 2 */
- break;
- }
-#elif defined(CONFIG_ALPHA_RUFFIAN)
- if (irq < 16) {
- /* Ack PYXIS ISA interrupt. */
- *(vulp)PYXIS_INT_REQ = 1L << 7; mb();
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_REQ;
- if (irq > 7) {
- outb(0x20, 0xa0);
- }
- outb(0x20, 0x20);
- } else {
- /* Ack PYXIS PCI interrupt. */
- *(vulp)PYXIS_INT_REQ = (1UL << (irq - 16));
- /* ... and read it back to make sure it got written. */
- *(vulp)PYXIS_INT_REQ;
- }
-#else
- if (irq < 16) {
- /* Ack the interrupt making it the lowest priority */
- /* First the slave .. */
- if (irq > 7) {
- outb(0xE0 | (irq - 8), 0xa0);
- irq = 2;
- }
- /* .. then the master */
- outb(0xE0 | irq, 0x20);
-#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
- /* on ALCOR/XLT, need to dismiss interrupt via GRU */
- *(vuip)GRU_INT_CLEAR = 0x80000000; mb();
- *(vuip)GRU_INT_CLEAR = 0x00000000; mb();
-#endif /* ALCOR || XLT */
- }
-#endif
-}
-
-int check_irq(unsigned int irq)
+int
+check_irq(unsigned int irq)
{
struct irqaction **p;
@@ -545,22 +220,21 @@ int check_irq(unsigned int irq)
return -EBUSY;
}
-int request_irq(unsigned int irq,
- void (*handler)(int, void *, struct pt_regs *),
- unsigned long irqflags,
- const char * devname,
- void *dev_id)
+int
+request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+ unsigned long irqflags, const char * devname, void *dev_id)
{
int shared = 0;
struct irqaction * action, **p;
unsigned long flags;
- if (irq >= NR_IRQS)
+ if (irq >= ACTUAL_NR_IRQS)
return -EINVAL;
if (IS_RESERVED_IRQ(irq))
return -EINVAL;
if (!handler)
return -EINVAL;
+
p = irq_action + irq;
action = *p;
if (action) {
@@ -580,11 +254,11 @@ int request_irq(unsigned int irq,
shared = 1;
}
- if (irq == TIMER_IRQ)
- action = &timer_irq;
- else
- action = (struct irqaction *)kmalloc(sizeof(struct irqaction),
- GFP_KERNEL);
+ action = &timer_irq;
+ if (irq != TIMER_IRQ) {
+ action = (struct irqaction *)
+ kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+ }
if (!action)
return -ENOMEM;
@@ -602,18 +276,19 @@ int request_irq(unsigned int irq,
*p = action;
if (!shared)
- unmask_irq(IRQ_TO_MASK(irq));
+ unmask_irq(irq);
restore_flags(flags);
return 0;
}
-void free_irq(unsigned int irq, void *dev_id)
+void
+free_irq(unsigned int irq, void *dev_id)
{
struct irqaction * action, **p;
unsigned long flags;
- if (irq >= NR_IRQS) {
+ if (irq >= ACTUAL_NR_IRQS) {
printk("Trying to free IRQ%d\n",irq);
return;
}
@@ -629,7 +304,7 @@ void free_irq(unsigned int irq, void *dev_id)
save_and_cli(flags);
*p = action->next;
if (!irq[irq_action])
- mask_irq(IRQ_TO_MASK(irq));
+ mask_irq(irq);
restore_flags(flags);
kfree(action);
return;
@@ -637,14 +312,29 @@ void free_irq(unsigned int irq, void *dev_id)
printk("Trying to free free IRQ%d\n",irq);
}
-static inline void handle_nmi(struct pt_regs * regs)
+int get_irq_list(char *buf)
{
- printk("Whee.. NMI received. Probable hardware error\n");
- printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
-}
+ int i, len = 0;
+ struct irqaction * action;
+ int cpu = smp_processor_id();
-unsigned int local_irq_count[NR_CPUS];
-unsigned int local_bh_count[NR_CPUS];
+ for (i = 0; i < NR_IRQS; i++) {
+ action = irq_action[i];
+ if (!action)
+ continue;
+ len += sprintf(buf+len, "%2d: %10u %c %s",
+ i, kstat.irqs[cpu][i],
+ (action->flags & SA_INTERRUPT) ? '+' : ' ',
+ action->name);
+ for (action=action->next; action; action = action->next) {
+ len += sprintf(buf+len, ", %s%s",
+ (action->flags & SA_INTERRUPT) ? "+":"",
+ action->name);
+ }
+ len += sprintf(buf+len, "\n");
+ }
+ return len;
+}
#ifdef __SMP__
/* Who has global_irq_lock. */
@@ -666,10 +356,17 @@ static unsigned long previous_irqholder = NO_PROC_ID;
#define INIT_STUCK 100000000
#undef STUCK
-#define STUCK \
-if (!--stuck) {printk("wait_on_irq CPU#%d stuck at %08lx, waiting for %08lx (local=%d, global=%d)\n", cpu, where, previous_irqholder, local_count, atomic_read(&global_irq_count)); stuck = INIT_STUCK; }
+#define STUCK \
+ if (!--stuck) { \
+ printk("wait_on_irq CPU#%d stuck at %08lx, " \
+ "waiting for %08lx (local=%d, global=%d)\n", \
+ cpu, where, previous_irqholder, local_count, \
+ atomic_read(&global_irq_count)); \
+ stuck = INIT_STUCK; \
+ }
-static inline void wait_on_irq(int cpu, unsigned long where)
+static inline void
+wait_on_irq(int cpu, unsigned long where)
{
int stuck = INIT_STUCK;
int local_count = local_irq_count[cpu];
@@ -706,10 +403,15 @@ static inline void wait_on_irq(int cpu, unsigned long where)
#define INIT_STUCK 10000000
#undef STUCK
-#define STUCK \
-if (!--stuck) {printk("get_irqlock stuck at %08lx, waiting for %08lx\n", where, previous_irqholder); stuck = INIT_STUCK;}
+#define STUCK \
+ if (!--stuck) { \
+ printk("get_irqlock stuck at %08lx, waiting for %08lx\n", \
+ where, previous_irqholder); \
+ stuck = INIT_STUCK; \
+ }
-static inline void get_irqlock(int cpu, unsigned long where)
+static inline void
+get_irqlock(int cpu, unsigned long where)
{
int stuck = INIT_STUCK;
@@ -745,7 +447,8 @@ static inline void get_irqlock(int cpu, unsigned long where)
previous_irqholder = where;
}
-void __global_cli(void)
+void
+__global_cli(void)
{
int cpu = smp_processor_id();
unsigned long where;
@@ -754,27 +457,30 @@ void __global_cli(void)
__cli();
if (!local_irq_count[cpu])
- get_irqlock(smp_processor_id(), where);
+ get_irqlock(smp_processor_id(), where);
}
-void __global_sti(void)
+void
+__global_sti(void)
{
int cpu = smp_processor_id();
if (!local_irq_count[cpu])
- release_irqlock(smp_processor_id());
+ release_irqlock(smp_processor_id());
__sti();
}
#if 0
-unsigned long __global_save_flags(void)
+unsigned long
+__global_save_flags(void)
{
return global_irq_holder == (unsigned char) smp_processor_id();
}
#endif
-void __global_restore_flags(unsigned long flags)
+void
+__global_restore_flags(unsigned long flags)
{
if (flags & 1) {
__global_cli();
@@ -793,12 +499,17 @@ void __global_restore_flags(unsigned long flags)
#define INIT_STUCK 200000000
#undef STUCK
-#define STUCK \
-if (!--stuck) {printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n",irq,cpu,global_irq_holder); stuck = INIT_STUCK;}
+#define STUCK \
+ if (!--stuck) { \
+ printk("irq_enter stuck (irq=%d, cpu=%d, global=%d)\n", \
+ irq, cpu,global_irq_holder); \
+ stuck = INIT_STUCK; \
+ }
#undef VERBOSE_IRQLOCK_DEBUGGING
-void irq_enter(int cpu, int irq)
+void
+irq_enter(int cpu, int irq)
{
#ifdef VERBOSE_IRQLOCK_DEBUGGING
extern void smp_show_backtrace_all_cpus(void);
@@ -813,10 +524,10 @@ void irq_enter(int cpu, int irq)
int globl_icount = atomic_read(&global_irq_count);
int local_count = local_irq_count[cpu];
- /* It is very important that we load the state variables
- * before we do the first call to printk() as printk()
- * could end up changing them...
- */
+ /* It is very important that we load the state
+ variables before we do the first call to
+ printk() as printk() could end up changing
+ them... */
#if 0
printk("CPU[%d]: BAD! Local IRQ's enabled,"
@@ -827,7 +538,7 @@ void irq_enter(int cpu, int irq)
cpu, previous_irqholder, globl_locked,
globl_icount, local_count);
#ifdef VERBOSE_IRQLOCK_DEBUGGING
- printk("Performing backtrace on all cpus,"
+ printk("Performing backtrace on all CPUs,"
" write this down!\n");
smp_show_backtrace_all_cpus();
#endif
@@ -838,13 +549,15 @@ void irq_enter(int cpu, int irq)
}
}
-void irq_exit(int cpu, int irq)
+void
+irq_exit(int cpu, int irq)
{
hardirq_exit(cpu);
release_irqlock(cpu);
}
-static void show(char * str)
+static void
+show(char * str)
{
#if 0
int i;
@@ -873,7 +586,8 @@ static void show(char * str)
#define MAXCOUNT 100000000
-static inline void wait_on_bh(void)
+static inline void
+wait_on_bh(void)
{
int count = MAXCOUNT;
do {
@@ -893,7 +607,8 @@ static inline void wait_on_bh(void)
* Don't wait if we're already running in an interrupt
* context or are inside a bh handler.
*/
-void synchronize_bh(void)
+void
+synchronize_bh(void)
{
if (atomic_read(&global_bh_count)) {
int cpu = smp_processor_id();
@@ -904,7 +619,8 @@ void synchronize_bh(void)
}
/* There has to be a better way. */
-void synchronize_irq(void)
+void
+synchronize_irq(void)
{
int cpu = smp_processor_id();
int local_count = local_irq_count[cpu];
@@ -918,26 +634,35 @@ void synchronize_irq(void)
}
}
-#else
+#else /* !__SMP__ */
+
#define irq_enter(cpu, irq) (++local_irq_count[cpu])
#define irq_exit(cpu, irq) (--local_irq_count[cpu])
-#endif
-static void unexpected_irq(int irq, struct pt_regs * regs)
+#endif /* __SMP__ */
+
+static void
+unexpected_irq(int irq, struct pt_regs * regs)
{
+#if 0
+#if 1
+ printk("device_interrupt: unexpected interrupt %d\n", irq);
+#else
struct irqaction *action;
int i;
printk("IO device interrupt, irq = %d\n", irq);
printk("PC = %016lx PS=%04lx\n", regs->pc, regs->ps);
printk("Expecting: ");
- for (i = 0; i < 16; i++)
+ for (i = 0; i < ACTUAL_NR_IRQS; i++)
if ((action = irq_action[i]))
while (action->handler) {
printk("[%s:%d] ", action->name, i);
action = action->next;
}
printk("\n");
+#endif
+#endif
#if defined(CONFIG_ALPHA_JENSEN)
/* ??? Is all this just debugging, or are the inb's and outb's
@@ -951,30 +676,13 @@ static void unexpected_irq(int irq, struct pt_regs * regs)
#endif
}
-static inline void handle_irq(int irq, struct pt_regs * regs)
-{
- struct irqaction * action = irq_action[irq];
- int cpu = smp_processor_id();
-
- irq_enter(cpu, irq);
- kstat.irqs[cpu][irq] += 1;
- if (!action) {
- unexpected_irq(irq, regs);
- } else {
- do {
- action->handler(irq, action->dev_id, regs);
- action = action->next;
- } while (action);
- }
- irq_exit(cpu, irq);
-}
-
-static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
+void
+handle_irq(int irq, int ack, struct pt_regs * regs)
{
struct irqaction * action;
int cpu = smp_processor_id();
- if ((unsigned) irq > NR_IRQS) {
+ if ((unsigned) irq > ACTUAL_NR_IRQS) {
printk("device_interrupt: illegal interrupt %d\n", irq);
return;
}
@@ -992,8 +700,10 @@ static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
* never unmasked. The autoirq stuff depends on this (it looks
* at the masks before and after doing the probing).
*/
- mask_irq(ack);
- ack_irq(ack);
+ if (ack >= 0) {
+ mask_irq(ack);
+ alpha_mv.ack_irq(ack);
+ }
if (action) {
if (action->flags & SA_SAMPLE_RANDOM)
add_interrupt_randomness(irq);
@@ -1001,622 +711,28 @@ static inline void device_interrupt(int irq, int ack, struct pt_regs * regs)
action->handler(irq, action->dev_id, regs);
action = action->next;
} while (action);
- unmask_irq(ack);
+ if (ack >= 0)
+ unmask_irq(ack);
} else {
-#if 1
- printk("device_interrupt: unexpected interrupt %d\n", irq);
-#endif
+ unexpected_irq(irq, regs);
}
irq_exit(cpu, irq);
}
-#ifdef CONFIG_PCI
-
-/*
- * Handle ISA interrupt via the PICs.
- */
-static inline void isa_device_interrupt(unsigned long vector,
- struct pt_regs * regs)
-{
-#if defined(CONFIG_ALPHA_APECS)
-# define IACK_SC APECS_IACK_SC
-#elif defined(CONFIG_ALPHA_LCA)
-# define IACK_SC LCA_IACK_SC
-#elif defined(CONFIG_ALPHA_CIA)
-# define IACK_SC CIA_IACK_SC
-#elif defined(CONFIG_ALPHA_PYXIS)
-# define IACK_SC PYXIS_IACK_SC
-#elif defined(CONFIG_ALPHA_TSUNAMI)
-# define IACK_SC TSUNAMI_PCI0_IACK_SC
-#else
- /*
- * This is bogus but necessary to get it to compile
- * on all platforms. If you try to use this on any
- * other than the intended platforms, you'll notice
- * real fast...
- */
-# define IACK_SC 1L
-#endif
- int j;
-
-#if 1
- /*
- * Generate a PCI interrupt acknowledge cycle. The PIC will
- * respond with the interrupt vector of the highest priority
- * interrupt that is pending. The PALcode sets up the
- * interrupts vectors such that irq level L generates vector L.
- */
- j = *(vuip) IACK_SC;
- j &= 0xff;
- if (j == 7) {
- if (!(inb(0x20) & 0x80)) {
- /* It's only a passive release... */
- return;
- }
- }
- device_interrupt(j, j, regs);
-#else
- unsigned long pic;
-
- /*
- * It seems to me that the probability of two or more *device*
- * interrupts occurring at almost exactly the same time is
- * pretty low. So why pay the price of checking for
- * additional interrupts here if the common case can be
- * handled so much easier?
- */
- /*
- * The first read of gives you *all* interrupting lines.
- * Therefore, read the mask register and and out those lines
- * not enabled. Note that some documentation has 21 and a1
- * write only. This is not true.
- */
- pic = inb(0x20) | (inb(0xA0) << 8); /* read isr */
- pic &= ~irq_mask; /* apply mask */
- pic &= 0xFFFB; /* mask out cascade & hibits */
-
- while (pic) {
- j = ffz(~pic);
- pic &= pic - 1;
- device_interrupt(j, j, regs);
- }
-#endif
-}
-
-#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
-/* We have to conditionally compile this because of GRU_xxx symbols */
-static inline void
-alcor_and_xlt_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* Read the interrupt summary register of the GRU */
- pld = (*(vuip)GRU_INT_REQ) & GRU_INT_REQ_BITS;
-
-#if 0
- printk("[0x%08lx/0x%04x]", pld, inb(0x20) | (inb(0xA0) << 8));
-#endif
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 31) {
- isa_device_interrupt(vector, regs);
- } else {
- device_interrupt(16 + i, 16 + i, regs);
- }
- }
- restore_flags(flags);
-}
-#endif /* ALCOR || XLT */
-
-static inline void
-cabriolet_and_eb66p_device_interrupt(unsigned long vector,
- struct pt_regs *regs)
-{
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* Read the interrupt summary registers */
- pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);
-
-#if 0
- printk("[0x%04X/0x%04X]", pld, inb(0x20) | (inb(0xA0) << 8));
-#endif
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 4) {
- isa_device_interrupt(vector, regs);
- } else {
- device_interrupt(16 + i, 16 + i, regs);
- }
- }
- restore_flags(flags);
-}
-
-static inline void
-mikasa_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* Read the interrupt summary registers */
- pld = (((unsigned long) (~inw(0x534)) & 0x0000ffffUL) << 16) |
- (((unsigned long) inb(0xa0)) << 8) |
- ((unsigned long) inb(0x20));
-
-#if 0
- printk("[0x%08lx]", pld);
-#endif
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i < 16) {
- isa_device_interrupt(vector, regs);
- } else {
- device_interrupt(i, i, regs);
- }
- }
- restore_flags(flags);
-}
-
-static inline void
-eb66_and_eb64p_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* Read the interrupt summary registers */
- pld = inb(0x26) | (inb(0x27) << 8);
- /*
- * Now, for every possible bit set, work through
- * them and call the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
-
- if (i == 5) {
- isa_device_interrupt(vector, regs);
- } else {
- device_interrupt(16 + i, 16 + i, regs);
- }
- }
- restore_flags(flags);
-}
-
-#if defined(CONFIG_ALPHA_MIATA) || defined(CONFIG_ALPHA_SX164)
-/* We have to conditionally compile this because of PYXIS_xxx symbols */
-static inline void
-miata_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld, tmp;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* Read the interrupt summary register of PYXIS */
- pld = *(vulp)PYXIS_INT_REQ;
-
-#if 0
- printk("[0x%08lx/0x%08lx/0x%04x]", pld,
- *(vulp)PYXIS_INT_MASK, inb(0x20) | (inb(0xA0) << 8));
-#endif
-
-#ifdef CONFIG_ALPHA_MIATA
- /*
- * For now, AND off any bits we are not interested in:
- * HALT (2), timer (6), ISA Bridge (7), 21142/3 (8)
- * then all the PCI slots/INTXs (12-31).
- */
- /* Maybe HALT should only be used for SRM console boots? */
- pld &= 0x00000000fffff1c4UL;
-#endif
-#ifdef CONFIG_ALPHA_SX164
- /*
- * For now, AND off any bits we are not interested in:
- * HALT (2), timer (6), ISA Bridge (7)
- * then all the PCI slots/INTXs (8-23)
- */
- /* Maybe HALT should only be used for SRM console boots? */
- pld &= 0x0000000000ffffc0UL;
-#endif /* SX164 */
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 7) {
- isa_device_interrupt(vector, regs);
- } else if (i == 6)
- continue;
- else { /* if not timer int */
- device_interrupt(16 + i, 16 + i, regs);
- }
- *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
- tmp = *(vulp)PYXIS_INT_REQ;
- }
- restore_flags(flags);
-}
-#endif /* MIATA || SX164 */
-
-static inline void
-noritake_device_interrupt(unsigned long vector, struct pt_regs *regs)
-{
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* Read the interrupt summary registers of NORITAKE */
- pld = ((unsigned long) inw(0x54c) << 32) |
- ((unsigned long) inw(0x54a) << 16) |
- ((unsigned long) inb(0xa0) << 8) |
- ((unsigned long) inb(0x20));
-
-#if 0
- printk("[0x%08lx]", pld);
-#endif
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i < 16) {
- isa_device_interrupt(vector, regs);
- } else {
- device_interrupt(i, i, regs);
- }
- }
- restore_flags(flags);
-}
-
-#if defined(CONFIG_ALPHA_DP264)
-/* we have to conditionally compile this because of TSUNAMI_xxx symbols */
-static inline void dp264_device_interrupt(unsigned long vector,
- struct pt_regs * regs)
-{
- unsigned long pld, tmp;
- unsigned int i;
- unsigned long flags;
-
- __save_and_cli(flags);
-
- /* Read the interrupt summary register of TSUNAMI */
- pld = (*(vulp)TSUNAMI_CSR_DIR0);
-
-#if 0
- printk("[0x%08lx/0x%08lx/0x%04x]", pld,
- *(vulp)TSUNAMI_CSR_DIM0,
- inb(0x20) | (inb(0xA0) << 8));
-#endif
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 55) {
- isa_device_interrupt(vector, regs);
- } else { /* if not timer int */
- device_interrupt(16 + i, 16 + i, regs);
- }
-#if 0
- *(vulp)TSUNAMI_CSR_DIR0 = 1UL << i; mb();
- tmp = *(vulp)TSUNAMI_CSR_DIR0;
-#endif
- }
- __restore_flags(flags);
-}
-#endif /* DP264 */
-
-#if defined(CONFIG_ALPHA_RAWHIDE)
-/* we have to conditionally compile this because of MCPCIA_xxx symbols */
-static inline void rawhide_device_interrupt(unsigned long vector,
- struct pt_regs * regs)
-{
-#if 0
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- __save_and_cli(flags);
-
- /* PLACEHOLDER, perhaps never used if we always do SRM */
-
- __restore_flags(flags);
-#endif
-}
-#endif /* RAWHIDE */
-
-#if defined(CONFIG_ALPHA_RUFFIAN)
-static inline void
-ruffian_device_interrupt(unsigned long vector, struct pt_regs *regs)
-
-{
- unsigned long pld;
- unsigned int i;
- unsigned long flags;
-
- save_and_cli(flags);
-
- /* Read the interrupt summary register of PYXIS */
- pld = *(vulp)PYXIS_INT_REQ;
-
- /* For now, AND off any bits we are not interested in:
- * HALT (2), timer (6), ISA Bridge (7), 21142 (8)
- * then all the PCI slots/INTXs (12-31)
- * flash(5) :DWH:
- */
- pld &= 0x00000000ffffff9fUL;/* was ffff7f */
-
- /*
- * Now for every possible bit set, work through them and call
- * the appropriate interrupt handler.
- */
-
- while (pld) {
- i = ffz(~pld);
- pld &= pld - 1; /* clear least bit set */
- if (i == 7) {
- /* Copy this bit from isa_device_interrupt cause
- we need to hook into int 0 for the timer. I
- refuse to soil device_interrupt with ifdefs. */
-
- /* Generate a PCI interrupt acknowledge cycle.
- The PIC will respond with the interrupt
- vector of the highest priority interrupt
- that is pending. The PALcode sets up the
- interrupts vectors such that irq level L
- generates vector L. */
-
- unsigned int j = *(vuip)PYXIS_IACK_SC & 0xff;
- if (j == 7 && !(inb(0x20) & 0x80)) {
- /* It's only a passive release... */
- } else if (j == 0) {
- timer_interrupt(regs);
- ack_irq(0);
- } else {
- device_interrupt(j, j, regs);
- }
- } else { /* if not timer int */
- device_interrupt(16 + i, 16 + i, regs);
- }
-
- *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
- *(vulp)PYXIS_INT_REQ; /* read to force the write */
- }
- restore_flags(flags);
-}
-#endif /* RUFFIAN */
-
-static inline void takara_device_interrupt(unsigned long vector,
- struct pt_regs * regs)
-{
- unsigned long flags;
- unsigned intstatus;
-
- save_and_cli(flags);
-
- /*
- * The PALcode will have passed us vectors 0x800 or 0x810,
- * which are fairly arbitrary values and serve only to tell
- * us whether an interrupt has come in on IRQ0 or IRQ1. If
- * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
- * probably ISA, but PCI interrupts can come through IRQ0
- * as well if the interrupt controller isn't in accelerated
- * mode.
- *
- * OTOH, the accelerator thing doesn't seem to be working
- * overly well, so what we'll do instead is try directly
- * examining the Master Interrupt Register to see if it's a
- * PCI interrupt, and if _not_ then we'll pass it on to the
- * ISA handler.
- */
-
- intstatus = inw(0x500) & 15;
- if (intstatus) {
- /*
- * This is a PCI interrupt. Check each bit and
- * despatch an interrupt if it's set.
- */
- if (intstatus & 8) device_interrupt(16+3, 16+3, regs);
- if (intstatus & 4) device_interrupt(16+2, 16+2, regs);
- if (intstatus & 2) device_interrupt(16+1, 16+1, regs);
- if (intstatus & 1) device_interrupt(16+0, 16+0, regs);
- } else
- isa_device_interrupt (vector, regs);
-
- restore_flags(flags);
-}
-
-#endif /* CONFIG_PCI */
-
-/*
- * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and
- * 0x9X0 for the local motherboard interrupts..
- *
- * 0x660 - NMI
- *
- * 0x800 - IRQ0 interval timer (not used, as we use the RTC timer)
- * 0x810 - IRQ1 line printer (duh..)
- * 0x860 - IRQ6 floppy disk
- * 0x8E0 - IRQ14 SCSI controller
- *
- * 0x900 - COM1
- * 0x920 - COM2
- * 0x980 - keyboard
- * 0x990 - mouse
- *
- * PCI-based systems are more sane: they don't have the local
- * interrupts at all, and have only normal PCI interrupts from
- * devices. Happily it's easy enough to do a sane mapping from the
- * Jensen.. Note that this means that we may have to do a hardware
- * "ack" to a different interrupt than we report to the rest of the
- * world.
- */
-static inline void
-srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
-{
- int irq, ack;
- unsigned long flags;
-
- __save_and_cli(flags);
-
-#ifdef __SMP__
-if (smp_processor_id()) printk("srm_device_interrupt on other CPU\n");
-#endif
-
- ack = irq = (vector - 0x800) >> 4;
-
-#ifdef CONFIG_ALPHA_JENSEN
- switch (vector) {
- case 0x660: handle_nmi(regs); return;
- /* local device interrupts: */
- case 0x900: handle_irq(4, regs); return; /* com1 -> irq 4 */
- case 0x920: handle_irq(3, regs); return; /* com2 -> irq 3 */
- case 0x980: handle_irq(1, regs); return; /* kbd -> irq 1 */
- case 0x990: handle_irq(9, regs); return; /* mouse -> irq 9 */
- default:
- if (vector > 0x900) {
- printk("Unknown local interrupt %lx\n", vector);
- }
- }
- /* irq1 is supposed to be the keyboard, silly Jensen
- (is this really needed??) */
- if (irq == 1)
- irq = 7;
-#endif /* CONFIG_ALPHA_JENSEN */
-
-#ifdef CONFIG_ALPHA_MIATA
- /*
- * I really hate to do this, but the MIATA SRM console ignores the
- * low 8 bits in the interrupt summary register, and reports the
- * vector 0x80 *lower* than I expected from the bit numbering in
- * the documentation.
- * This was done because the low 8 summary bits really aren't used
- * for reporting any interrupts (the PCI-ISA bridge, bit 7, isn't
- * used for this purpose, as PIC interrupts are delivered as the
- * vectors 0x800-0x8f0).
- * But I really don't want to change the fixup code for allocation
- * of IRQs, nor the irq_mask maintenance stuff, both of which look
- * nice and clean now.
- * So, here's this grotty hack... :-(
- */
- if (irq >= 16)
- ack = irq = irq + 8;
-#endif /* CONFIG_ALPHA_MIATA */
-
-#ifdef CONFIG_ALPHA_NORITAKE
- /*
- * I really hate to do this, too, but the NORITAKE SRM console also
- * reports PCI vectors *lower* than I expected from the bit numbers
- * in the documentation.
- * But I really don't want to change the fixup code for allocation
- * of IRQs, nor the irq_mask maintenance stuff, both of which look
- * nice and clean now.
- * So, here's this additional grotty hack... :-(
- */
- if (irq >= 16)
- ack = irq = irq + 1;
-#endif /* CONFIG_ALPHA_NORITAKE */
-
-#ifdef CONFIG_ALPHA_SABLE
- irq = sable_mask_to_irq[(ack)];
-#if 0
- if (irq == 5 || irq == 9 || irq == 10 || irq == 11 ||
- irq == 14 || irq == 15)
- printk("srm_device_interrupt: vector=0x%lx ack=0x%x"
- " irq=0x%x\n", vector, ack, irq);
-#endif
-#endif /* CONFIG_ALPHA_SABLE */
-
-#ifdef CONFIG_ALPHA_DP264
- /*
- * the DP264 SRM console reports PCI interrupts with a vector
- * 0x100 *higher* than one might expect, as PCI IRQ 0 (ie bit 0)
- * shows up as IRQ 16, etc, etc. We adjust it down by 16 to have
- * it line up with the actual bit numbers from the DIM registers,
- * which is how we manage the interrupts/mask. Sigh...
- */
- if (irq >= 32)
- ack = irq = irq - 16;
-#endif /* DP264 */
-
-#ifdef CONFIG_ALPHA_RAWHIDE
- /*
- * the RAWHIDE SRM console reports PCI interrupts with a vector
- * 0x80 *higher* than one might expect, as PCI IRQ 0 (ie bit 0)
- * shows up as IRQ 24, etc, etc. We adjust it down by 8 to have
- * it line up with the actual bit numbers from the REQ registers,
- * which is how we manage the interrupts/mask. Sigh...
- *
- * also, PCI #1 interrupts are offset some more... :-(
- */
- if (irq == 52)
- ack = irq = 56; /* SCSI on PCI 1 is special */
- else {
- if (irq >= 24) /* adjust all PCI interrupts down 8 */
- ack = irq = irq - 8;
- if (irq >= 48) /* adjust PCI bus 1 interrupts down another 8 */
- ack = irq = irq - 8;
- }
-#endif /* RAWHIDE */
-
- device_interrupt(irq, ack, regs);
-
- __restore_flags(flags);
-}
/*
* Start listening for interrupts..
*/
-unsigned long probe_irq_on(void)
+
+unsigned long
+probe_irq_on(void)
{
struct irqaction * action;
unsigned long irqs = 0;
unsigned long delay;
unsigned int i;
- for (i = NR_IRQS - 1; i > 0; i--) {
+ for (i = ACTUAL_NR_IRQS - 1; i > 0; i--) {
if (!(PROBE_MASK & (1UL << i))) {
continue;
}
@@ -1634,8 +750,8 @@ unsigned long probe_irq_on(void)
for (delay = jiffies + HZ/10; delay > jiffies; )
barrier();
- /* now filter out any obviously spurious interrupts */
- return irqs & ~irq_mask;
+ /* Now filter out any obviously spurious interrupts. */
+ return irqs & ~alpha_irq_mask;
}
/*
@@ -1643,11 +759,13 @@ unsigned long probe_irq_on(void)
* we have several candidates (but we return the lowest-numbered
* one).
*/
-int probe_irq_off(unsigned long irqs)
+
+int
+probe_irq_off(unsigned long irqs)
{
int i;
- irqs &= irq_mask;
+ irqs &= alpha_irq_mask;
if (!irqs)
return 0;
i = ffz(~irqs);
@@ -1656,42 +774,10 @@ int probe_irq_off(unsigned long irqs)
return i;
}
-extern void lca_machine_check (unsigned long vector, unsigned long la,
- struct pt_regs *regs);
-extern void apecs_machine_check(unsigned long vector, unsigned long la,
- struct pt_regs * regs);
-extern void cia_machine_check(unsigned long vector, unsigned long la,
- struct pt_regs * regs);
-extern void pyxis_machine_check(unsigned long vector, unsigned long la,
- struct pt_regs * regs);
-extern void t2_machine_check(unsigned long vector, unsigned long la,
- struct pt_regs * regs);
-extern void tsunami_machine_check(unsigned long vector, unsigned long la,
- struct pt_regs * regs);
-extern void mcpcia_machine_check(unsigned long vector, unsigned long la,
- struct pt_regs * regs);
-
-static void
-machine_check(unsigned long vector, unsigned long la, struct pt_regs *regs)
-{
-#if defined(CONFIG_ALPHA_LCA)
- lca_machine_check(vector, la, regs);
-#elif defined(CONFIG_ALPHA_APECS)
- apecs_machine_check(vector, la, regs);
-#elif defined(CONFIG_ALPHA_CIA)
- cia_machine_check(vector, la, regs);
-#elif defined(CONFIG_ALPHA_PYXIS)
- pyxis_machine_check(vector, la, regs);
-#elif defined(CONFIG_ALPHA_T2)
- t2_machine_check(vector, la, regs);
-#elif defined(CONFIG_ALPHA_TSUNAMI)
- tsunami_machine_check(vector, la, regs);
-#elif defined(CONFIG_ALPHA_MCPCIA)
- mcpcia_machine_check(vector, la, regs);
-#else
- printk("Machine check\n");
-#endif
-}
+
+/*
+ * The main interrupt entry point.
+ */
asmlinkage void
do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
@@ -1701,56 +787,20 @@ do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
switch (type) {
case 0:
#ifdef __SMP__
-/* irq_enter(smp_processor_id(), 0); ??????? */
handle_ipi(&regs);
-/* irq_exit(smp_processor_id(), 0); ??????? */
return;
-#else /* __SMP__ */
+#else
printk("Interprocessor interrupt? You must be kidding\n");
-#endif /* __SMP__ */
+#endif
break;
case 1:
- handle_irq(RTC_IRQ, &regs);
+ handle_irq(RTC_IRQ, -1, &regs);
return;
case 2:
- machine_check(vector, la_ptr, &regs);
+ alpha_mv.machine_check(vector, la_ptr, &regs);
return;
case 3:
-#if defined(CONFIG_ALPHA_JENSEN) || \
- defined(CONFIG_ALPHA_NONAME) || \
- defined(CONFIG_ALPHA_P2K) || \
- defined(CONFIG_ALPHA_SRM)
- srm_device_interrupt(vector, &regs);
-#elif defined(CONFIG_ALPHA_MIATA) || \
- defined(CONFIG_ALPHA_SX164)
- miata_device_interrupt(vector, &regs);
-#elif defined(CONFIG_ALPHA_NORITAKE)
- noritake_device_interrupt(vector, &regs);
-#elif defined(CONFIG_ALPHA_ALCOR) || \
- defined(CONFIG_ALPHA_XLT)
- alcor_and_xlt_device_interrupt(vector, &regs);
-#elif defined(CONFIG_ALPHA_CABRIOLET) || \
- defined(CONFIG_ALPHA_EB66P) || \
- defined(CONFIG_ALPHA_EB164) || \
- defined(CONFIG_ALPHA_PC164) || \
- defined(CONFIG_ALPHA_LX164)
- cabriolet_and_eb66p_device_interrupt(vector, &regs);
-#elif defined(CONFIG_ALPHA_MIKASA)
- mikasa_device_interrupt(vector, &regs);
-#elif defined(CONFIG_ALPHA_EB66) || \
- defined(CONFIG_ALPHA_EB64P)
- eb66_and_eb64p_device_interrupt(vector, &regs);
-#elif defined(CONFIG_ALPHA_RUFFIAN)
- ruffian_device_interrupt(vector, &regs);
-#elif defined(CONFIG_ALPHA_DP264)
- dp264_device_interrupt(vector, &regs);
-#elif defined(CONFIG_ALPHA_RAWHIDE)
- rawhide_device_interrupt(vector, &regs);
-#elif defined(CONFIG_ALPHA_TAKARA)
- takara_device_interrupt(vector, &regs);
-#elif NR_IRQS == 16
- isa_device_interrupt(vector, &regs);
-#endif
+ alpha_mv.device_interrupt(vector, &regs);
return;
case 4:
printk("Performance counter interrupt\n");
@@ -1761,226 +811,9 @@ do_entInt(unsigned long type, unsigned long vector, unsigned long la_ptr,
printk("PC = %016lx PS=%04lx\n", regs.pc, regs.ps);
}
-extern asmlinkage void entInt(void);
-
-static inline void sable_init_IRQ(void)
-{
- outb(irq_mask , 0x537); /* slave 0 */
- outb(irq_mask >> 8, 0x53b); /* slave 1 */
- outb(irq_mask >> 16, 0x53d); /* slave 2 */
- outb(0x44, 0x535); /* enable cascades in master */
-}
-
-#if defined(CONFIG_ALPHA_SX164)
-static inline void sx164_init_IRQ(void)
-{
-#if !defined(CONFIG_ALPHA_SRM)
- /* note invert on MASK bits */
- *(vulp)PYXIS_INT_MASK = ~((long)irq_mask >> 16); mb();
- *(vulp)PYXIS_INT_MASK;
-#endif /* !SRM */
- enable_irq(16 + 6); /* enable timer */
- enable_irq(16 + 7); /* enable ISA PIC cascade */
- enable_irq(2); /* enable cascade */
-}
-#endif /* SX164 */
-
-#if defined(CONFIG_ALPHA_RUFFIAN)
-static inline void ruffian_init_IRQ(void)
-{
- /* invert 6&7 for i82371 */
- *(vulp)PYXIS_INT_HILO = 0x000000c0UL; mb();
- *(vulp)PYXIS_INT_CNFG = 0x00002064UL; mb(); /* all clear */
- *(vulp)PYXIS_INT_MASK = 0x00000000UL; mb();
- *(vulp)PYXIS_INT_REQ = 0xffffffffUL; mb();
-
- outb(0x11,0xA0);
- outb(0x08,0xA1);
- outb(0x02,0xA1);
- outb(0x01,0xA1);
- outb(0xFF,0xA1);
-
- outb(0x11,0x20);
- outb(0x00,0x21);
- outb(0x04,0x21);
- outb(0x01,0x21);
- outb(0xFF,0x21);
-
- /* Send -INTA pulses to clear any pending interrupts ...*/
- *(vuip) IACK_SC;
-
- /* Finish writing the 82C59A PIC Operation Control Words */
- outb(0x20,0xA0);
- outb(0x20,0x20);
-
- /* Turn on the interrupt controller, the timer interrupt */
- enable_irq(16 + 7); /* enable ISA PIC cascade */
- enable_irq(0); /* enable timer */
- enable_irq(2); /* enable 2nd PIC cascade */
-}
-#endif /* RUFFIAN */
-
-#ifdef CONFIG_ALPHA_MIATA
-static inline void miata_init_IRQ(void)
-{
- /* note invert on MASK bits */
- *(vulp)PYXIS_INT_MASK = ~((long)irq_mask >> 16); mb(); /* invert */
-#if 0
- /* these break on MiataGL so we'll try not to do it at all */
- *(vulp)PYXIS_INT_HILO = 0x000000B2UL; mb(); /* ISA/NMI HI */
- *(vulp)PYXIS_RT_COUNT = 0UL; mb(); /* clear count */
-#endif
- /* clear upper timer */
- *(vulp)PYXIS_INT_REQ = 0x4000000000000000UL; mb();
-
- enable_irq(16 + 2); /* enable HALT switch - SRM only? */
- enable_irq(16 + 6); /* enable timer */
- enable_irq(16 + 7); /* enable ISA PIC cascade */
- enable_irq(2); /* enable cascade */
-}
-#endif
-
-static inline void noritake_init_IRQ(void)
-{
- outw(~(irq_mask >> 16), 0x54a); /* note invert */
- outw(~(irq_mask >> 32), 0x54c); /* note invert */
- enable_irq(2); /* enable cascade */
-}
-
-#if defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
-static inline void alcor_and_xlt_init_IRQ(void)
-{
- *(vuip)GRU_INT_MASK = ~(irq_mask >> 16); mb(); /* note invert */
- *(vuip)GRU_INT_EDGE = 0U; mb(); /* all are level */
- *(vuip)GRU_INT_HILO = 0x80000000U; mb(); /* ISA only HI */
- *(vuip)GRU_INT_CLEAR = 0UL; mb(); /* all clear */
-
- enable_irq(16 + 31); /* enable (E)ISA PIC cascade */
- enable_irq(2); /* enable cascade */
-}
-#endif /* ALCOR || XLT */
-
-static inline void mikasa_init_IRQ(void)
-{
- outw(~(irq_mask >> 16), 0x536); /* note invert */
- enable_irq(2); /* enable cascade */
-}
-
-#if defined(CONFIG_ALPHA_DP264)
-static inline void dp264_init_IRQ(void)
-{
- /* note invert on MASK bits */
- *(vulp)TSUNAMI_CSR_DIM0 =
- ~(irq_mask) & ~0x0000000000000000UL; mb();
- *(vulp)TSUNAMI_CSR_DIM0;
- enable_irq(55); /* enable CYPRESS interrupt controller (ISA) */
- enable_irq(2);
-}
-#endif /* DP264 */
-
-#if defined(CONFIG_ALPHA_RAWHIDE)
-static inline void rawhide_init_IRQ(void)
-{
- /* HACK ALERT! only PCI busses 0 and 1 are used currently,
- and routing is only to CPU #1*/
-
- *(vuip)MCPCIA_INT_MASK0(0) =
- (~((irq_mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb();
- /* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(0);
-
- *(vuip)MCPCIA_INT_MASK0(1) =
- (~((irq_mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb();
- /* ... and read it back to make sure it got written. */
- *(vuip)MCPCIA_INT_MASK0(1);
- enable_irq(2);
-}
-#endif /* RAWHIDE */
-
-static inline void takara_init_IRQ(void)
-{
- unsigned int ctlreg = inl(0x500);
-
- ctlreg &= ~0x8000; /* return to non-accelerated mode */
- outw(ctlreg >> 16, 0x502);
- outw(ctlreg & 0xFFFF, 0x500);
- ctlreg = 0x05107c00; /* enable the PCI interrupt register */
- printk("Setting to 0x%08x\n", ctlreg);
- outw(ctlreg >> 16, 0x502);
- outw(ctlreg & 0xFFFF, 0x500);
- enable_irq(2);
-}
-
-static inline void init_IRQ_35(void)
-{
-#if !defined(CONFIG_ALPHA_SRM)
- outl(irq_mask >> 16, 0x804);
-#endif /* !SRM */
- enable_irq(16 + 4); /* enable SIO cascade */
- enable_irq(2); /* enable cascade */
-}
-
-static inline void init_IRQ_32(void)
-{
- outb(irq_mask >> 16, 0x26);
- outb(irq_mask >> 24, 0x27);
- enable_irq(16 + 5); /* enable SIO cascade */
- enable_irq(2); /* enable cascade */
-}
-
-static inline void init_IRQ_16(void)
-{
- enable_irq(2); /* enable cascade */
-}
-
void __init
init_IRQ(void)
{
wrent(entInt, 0);
-
-/* FIXME FIXME FIXME FIXME FIXME */
-#if !defined(CONFIG_ALPHA_DP264)
- /* we need to figure out why these fail on the DP264 */
- outb(0, DMA1_RESET_REG);
- outb(0, DMA2_RESET_REG);
-#endif /* !DP264 */
-/* FIXME FIXME FIXME FIXME FIXME */
-#if !defined(CONFIG_ALPHA_SX164) && !defined(CONFIG_ALPHA_DP264)
- outb(0, DMA1_CLR_MASK_REG);
- /* we need to figure out why this fails on the SX164 */
- outb(0, DMA2_CLR_MASK_REG);
-#endif /* !SX164 && !DP264 */
-/* end FIXMEs */
-
-#if defined(CONFIG_ALPHA_SABLE)
- sable_init_IRQ();
-#elif defined(CONFIG_ALPHA_MIATA)
- miata_init_IRQ();
-#elif defined(CONFIG_ALPHA_SX164)
- sx164_init_IRQ();
-#elif defined(CONFIG_ALPHA_NORITAKE)
- noritake_init_IRQ();
-#elif defined(CONFIG_ALPHA_ALCOR) || defined(CONFIG_ALPHA_XLT)
- alcor_and_xlt_init_IRQ();
-#elif defined(CONFIG_ALPHA_MIKASA)
- mikasa_init_IRQ();
-#elif defined(CONFIG_ALPHA_CABRIOLET) || defined(CONFIG_ALPHA_EB66P) || \
- defined(CONFIG_ALPHA_PC164) || defined(CONFIG_ALPHA_LX164) || \
- defined(CONFIG_ALPHA_EB164)
- init_IRQ_35();
-#elif defined(CONFIG_ALPHA_RUFFIAN)
- ruffian_init_IRQ();
-#elif defined(CONFIG_ALPHA_DP264)
- dp264_init_IRQ();
-#elif defined(CONFIG_ALPHA_RAWHIDE)
- rawhide_init_IRQ();
-#elif defined(CONFIG_ALPHA_TAKARA)
- takara_init_IRQ();
-#elif defined(CONFIG_ALPHA_EB66) || defined(CONFIG_ALPHA_EB64P)
- init_IRQ_32();
-#elif NR_IRQS == 16
- init_IRQ_16();
-#else
-#error "How do I initialize the interrupt hardware?"
-#endif
+ alpha_mv.init_irq();
}
diff --git a/arch/alpha/kernel/irq.h b/arch/alpha/kernel/irq.h
new file mode 100644
index 000000000..08db28ec5
--- /dev/null
+++ b/arch/alpha/kernel/irq.h
@@ -0,0 +1,27 @@
+/*
+ * linux/arch/alpha/kernel/irq.h
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * This file contains declarations and inline functions for interfacing
+ * with the IRQ handling routines in irq.c.
+ */
+
+
+/* FIXME FIXME FIXME FIXME FIXME */
+/* We need to figure out why these fail on the DP264 & SX164. Otherwise
+ we'd just do this in init_IRQ(). */
+#define STANDARD_INIT_IRQ_PROLOG \
+ outb(0, DMA1_RESET_REG); \
+ outb(0, DMA2_RESET_REG); \
+ outb(0, DMA1_CLR_MASK_REG); \
+ outb(0, DMA2_CLR_MASK_REG)
+
+extern unsigned long alpha_irq_mask;
+
+extern void generic_ack_irq(unsigned long irq);
+extern void isa_device_interrupt(unsigned long vector, struct pt_regs * regs);
+extern void srm_device_interrupt(unsigned long vector, struct pt_regs * regs);
+
+extern void handle_irq(int irq, int ack, struct pt_regs * regs);
diff --git a/arch/alpha/kernel/machvec.h b/arch/alpha/kernel/machvec.h
new file mode 100644
index 000000000..6ac7cc6a0
--- /dev/null
+++ b/arch/alpha/kernel/machvec.h
@@ -0,0 +1,137 @@
+/*
+ * linux/arch/alpha/kernel/machvec.h
+ *
+ * Copyright (C) 1997, 1998 Richard Henderson
+ *
+ * This file has goodies to help simplify instantiation of machine vectors.
+ */
+
+#include <linux/config.h>
+
+/* Whee. TSUNAMI doesn't have an HAE. Fix things up for the GENERIC
+ kernel by defining the HAE address to be that of the cache. Now
+ we can read and write it as we like. ;-) */
+#define TSUNAMI_HAE_ADDRESS (&alpha_mv.hae_cache)
+
+/* Only a few systems don't define IACK_SC, handling all interrupts through
+ the SRM console. But splitting out that one case from IO() below
+ seems like such a pain. Define this to get things to compile. */
+#define JENSEN_IACK_SC 1
+#define T2_IACK_SC 1
+
+
+/*
+ * Some helpful macros for filling in the blanks.
+ */
+
+#define CAT1(x,y) x##y
+#define CAT(x,y) CAT1(x,y)
+
+#define DO_DEFAULT_RTC \
+ rtc_port: 0x70, rtc_addr: 0x80
+
+#define DO_EV4_MMU \
+ max_asn: EV4_MAX_ASN, \
+ mmu_context_mask: ~0UL, \
+ mv_get_mmu_context: ev4_get_mmu_context, \
+ mv_flush_tlb_current: ev4_flush_tlb_current, \
+ mv_flush_tlb_other: ev4_flush_tlb_other, \
+ mv_flush_tlb_current_page: ev4_flush_tlb_current_page
+
+#define DO_EV5_MMU \
+ max_asn: EV5_MAX_ASN, \
+ mmu_context_mask: ~0UL, \
+ mv_get_mmu_context: ev5_get_mmu_context, \
+ mv_flush_tlb_current: ev5_flush_tlb_current, \
+ mv_flush_tlb_other: ev5_flush_tlb_other, \
+ mv_flush_tlb_current_page: ev5_flush_tlb_current_page
+
+#define DO_EV6_MMU \
+ max_asn: EV5_MAX_ASN, \
+ mmu_context_mask: 0xfffffffffful, \
+ mv_get_mmu_context: ev5_get_mmu_context, \
+ mv_flush_tlb_current: ev5_flush_tlb_current, \
+ mv_flush_tlb_other: ev5_flush_tlb_other, \
+ mv_flush_tlb_current_page: ev5_flush_tlb_current_page
+
+#define IO_LITE(UP,low1,low2) \
+ hae_register: (unsigned long *) CAT(UP,_HAE_ADDRESS), \
+ iack_sc: CAT(UP,_IACK_SC), \
+ mv_inb: CAT(low1,_inb), \
+ mv_inw: CAT(low1,_inw), \
+ mv_inl: CAT(low1,_inl), \
+ mv_outb: CAT(low1,_outb), \
+ mv_outw: CAT(low1,_outw), \
+ mv_outl: CAT(low1,_outl), \
+ mv_readb: CAT(low1,_readb), \
+ mv_readw: CAT(low1,_readw), \
+ mv_readl: CAT(low1,_readl), \
+ mv_readq: CAT(low1,_readq), \
+ mv_writeb: CAT(low1,_writeb), \
+ mv_writew: CAT(low1,_writew), \
+ mv_writel: CAT(low1,_writel), \
+ mv_writeq: CAT(low1,_writeq), \
+ mv_dense_mem: CAT(low2,_dense_mem)
+
+#define IO(UP,low1,low2) \
+ IO_LITE(UP,low1,low2), \
+ pci_read_config_byte: CAT(low2,_pcibios_read_config_byte), \
+ pci_read_config_word: CAT(low2,_pcibios_read_config_word), \
+ pci_read_config_dword: CAT(low2,_pcibios_read_config_dword), \
+ pci_write_config_byte: CAT(low2,_pcibios_write_config_byte), \
+ pci_write_config_word: CAT(low2,_pcibios_write_config_word), \
+ pci_write_config_dword: CAT(low2,_pcibios_write_config_dword), \
+ dma_win_base: CAT(UP,_DMA_WIN_BASE_DEFAULT), \
+ dma_win_size: CAT(UP,_DMA_WIN_SIZE_DEFAULT)
+
+/* Any assembler that can generate a GENERIC kernel can generate BWX
+ instructions. So always use them for PYXIS I/O. */
+
+#define DO_APECS_IO IO(APECS,apecs,apecs)
+#define DO_CIA_IO IO(CIA,cia,cia)
+#define DO_LCA_IO IO(LCA,lca,lca)
+#define DO_MCPCIA_IO IO(MCPCIA,mcpcia,mcpcia)
+#define DO_PYXIS_IO IO(PYXIS,pyxis_bw,pyxis)
+#define DO_T2_IO IO(T2,t2,t2)
+#define DO_TSUNAMI_IO IO(TSUNAMI,tsunami,tsunami)
+
+#define BUS(which) \
+ mv_virt_to_bus: CAT(which,_virt_to_bus), \
+ mv_bus_to_virt: CAT(which,_bus_to_virt)
+
+#define DO_APECS_BUS BUS(apecs)
+#define DO_CIA_BUS BUS(cia)
+#define DO_LCA_BUS BUS(lca)
+#define DO_MCPCIA_BUS BUS(mcpcia)
+#define DO_PYXIS_BUS BUS(pyxis)
+#define DO_T2_BUS BUS(t2)
+#define DO_TSUNAMI_BUS BUS(tsunami)
+
+
+/*
+ * In a GENERIC kernel, we have lots of these vectors floating about,
+ * all but one of which we want to go away. In a non-GENERIC kernel,
+ * we want only one, ever.
+ *
+ * Accomplish this in the GENERIC kernel by puting all of the vectors
+ * in the .init.data section where they'll go away. We'll copy the
+ * one we want to the real alpha_mv vector in setup_arch.
+ *
+ * Accomplish this in a non-GENERIC kernel by ifdef'ing out all but
+ * one of the vectors, which will not reside in .init.data. We then
+ * alias this one vector to alpha_mv, so no copy is needed.
+ *
+ * Upshot: set __initdata to nothing for non-GENERIC kernels.
+ */
+
+#ifdef CONFIG_ALPHA_GENERIC
+#define __initmv __initdata
+#define ALIAS_MV(x)
+#else
+#define __initmv
+
+/* GCC actually has a syntax for defining aliases, but is under some
+ delusion that you shouldn't be able to declare it extern somewhere
+ else beforehand. Fine. We'll do it ourselves. */
+#define ALIAS_MV(system) asm(".global alpha_mv\nalpha_mv = " #system "_mv");
+#endif
diff --git a/arch/alpha/kernel/mcpcia.c b/arch/alpha/kernel/mcpcia.c
deleted file mode 100644
index 6a9dab59a..000000000
--- a/arch/alpha/kernel/mcpcia.c
+++ /dev/null
@@ -1,977 +0,0 @@
-/*
- * Code common to all MCbus-PCI adaptor chipsets
- *
- * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
- *
- */
-#include <linux/kernel.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/hwrpb.h>
-#include <asm/ptrace.h>
-#include <asm/mmu_context.h>
-#include <asm/delay.h>
-
-/*
- * NOTE: Herein lie back-to-back mb instructions. They are magic.
- * One plausible explanation is that the i/o controller does not properly
- * handle the system transaction. Another involves timing. Ho hum.
- */
-
-extern struct hwrpb_struct *hwrpb;
-extern asmlinkage void wrmces(unsigned long mces);
-
-/*
- * BIOS32-style PCI interface:
- */
-
-#ifdef CONFIG_ALPHA_MCPCIA
-
-#undef DEBUG_CFG
-
-#ifdef DEBUG_CFG
-# define DBG_CFG(args) printk args
-#else
-# define DBG_CFG(args)
-#endif
-
-#undef DEBUG_PCI
-
-#ifdef DEBUG_PCI
-# define DBG_PCI(args) printk args
-#else
-# define DBG_PCI(args)
-#endif
-
-#define DEBUG_MCHECK
-
-#ifdef DEBUG_MCHECK
-# define DBG_MCK(args) printk args
-# define DEBUG_MCHECK_DUMP
-#else
-# define DBG_MCK(args)
-#endif
-
-#define vuip volatile unsigned int *
-#define vulp volatile unsigned long *
-
-static volatile unsigned int MCPCIA_mcheck_expected[NR_CPUS];
-static volatile unsigned int MCPCIA_mcheck_taken[NR_CPUS];
-static unsigned int MCPCIA_jd[NR_CPUS];
-
-#define MCPCIA_MAX_HOSES 2
-static int mcpcia_num_hoses = 0;
-
-static int pci_probe_enabled = 0; /* disable to start */
-
-static struct linux_hose_info *mcpcia_root = NULL, *mcpcia_last_hose;
-
-struct linux_hose_info *bus2hose[256];
-
-static inline unsigned long long_align(unsigned long addr)
-{
- return ((addr + (sizeof(unsigned long) - 1)) &
- ~(sizeof(unsigned long) - 1));
-}
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int MCPCIA_DMA_WIN_BASE = MCPCIA_DMA_WIN_BASE_DEFAULT;
-unsigned int MCPCIA_DMA_WIN_SIZE = MCPCIA_DMA_WIN_SIZE_DEFAULT;
-unsigned long mcpcia_sm_base_r1, mcpcia_sm_base_r2, mcpcia_sm_base_r3;
-#endif /* SRM_SETUP */
-
-/*
- * Given a bus, device, and function number, compute resulting
- * configuration space address and setup the MCPCIA_HAXR2 register
- * accordingly. It is therefore not safe to have concurrent
- * invocations to configuration space access routines, but there
- * really shouldn't be any need for this.
- *
- * Type 0:
- *
- * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
- * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- * 31:11 Device select bit.
- * 10:8 Function number
- * 7:2 Register number
- *
- * Type 1:
- *
- * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
- * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- * 31:24 reserved
- * 23:16 bus number (8 bits = 128 possible buses)
- * 15:11 Device number (5 bits)
- * 10:8 function number
- * 7:2 register number
- *
- * Notes:
- * The function number selects which function of a multi-function device
- * (e.g., scsi and ethernet).
- *
- * The register selects a DWORD (32 bit) register offset. Hence it
- * doesn't get shifted by 2 bits as we want to "drop" the bottom two
- * bits.
- */
-
-static unsigned int
-conf_read(unsigned long addr, unsigned char type1,
- struct linux_hose_info *hose)
-{
- unsigned long flags;
- unsigned long hoseno = hose->pci_hose_index;
- unsigned int stat0, value, temp, cpu;
-
- cpu = smp_processor_id();
-
- save_and_cli(flags);
-
- DBG_CFG(("conf_read(addr=0x%lx, type1=%d, hose=%d)\n",
- addr, type1, hoseno));
-
- /* reset status register to avoid losing errors: */
- stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno);
- *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb();
- temp = *(vuip)MCPCIA_CAP_ERR(hoseno);
- DBG_CFG(("conf_read: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0));
-
- mb();
- draina();
- MCPCIA_mcheck_expected[cpu] = 1;
- MCPCIA_mcheck_taken[cpu] = 0;
- mb();
- /* access configuration space: */
- value = *((vuip)addr);
- mb();
- mb(); /* magic */
- if (MCPCIA_mcheck_taken[cpu]) {
- MCPCIA_mcheck_taken[cpu] = 0;
- value = 0xffffffffU;
- mb();
- }
- MCPCIA_mcheck_expected[cpu] = 0;
- mb();
-
- DBG_CFG(("conf_read(): finished\n"));
-
- restore_flags(flags);
- return value;
-}
-
-
-static void
-conf_write(unsigned long addr, unsigned int value, unsigned char type1,
- struct linux_hose_info *hose)
-{
- unsigned long flags;
- unsigned long hoseno = hose->pci_hose_index;
- unsigned int stat0, temp, cpu;
-
- cpu = smp_processor_id();
-
- save_and_cli(flags); /* avoid getting hit by machine check */
-
- /* reset status register to avoid losing errors: */
- stat0 = *(vuip)MCPCIA_CAP_ERR(hoseno);
- *(vuip)MCPCIA_CAP_ERR(hoseno) = stat0; mb();
- temp = *(vuip)MCPCIA_CAP_ERR(hoseno);
- DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", hoseno, stat0));
-
- draina();
- MCPCIA_mcheck_expected[cpu] = 1;
- mb();
- /* access configuration space: */
- *((vuip)addr) = value;
- mb();
- mb(); /* magic */
- temp = *(vuip)MCPCIA_CAP_ERR(hoseno); /* read to force the write */
- MCPCIA_mcheck_expected[cpu] = 0;
- mb();
-
- DBG_CFG(("conf_write(): finished\n"));
- restore_flags(flags);
-}
-
-static int mk_conf_addr(struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned long *pci_addr,
- unsigned char *type1)
-{
- unsigned long addr;
-
- if (!pci_probe_enabled) /* if doing standard pci_init(), ignore */
- return -1;
-
- DBG_CFG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
- " pci_addr=0x%p, type1=0x%p)\n",
- bus, device_fn, where, pci_addr, type1));
-
- /* type 1 configuration cycle for *ALL* busses */
- *type1 = 1;
-
- if (hose->pci_first_busno == bus)
- bus = 0;
- addr = (bus << 16) | (device_fn << 8) | (where);
- addr <<= 5; /* swizzle for SPARSE */
- addr |= hose->pci_config_space;
-
- *pci_addr = addr;
- DBG_CFG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
- return 0;
-}
-
-
-int hose_read_config_byte (struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
-{
- unsigned long addr;
- unsigned char type1;
-
- *value = 0xff;
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- addr |= 0x00; /* or in length */
-
- *value = conf_read(addr, type1, hose) >> ((where & 3) * 8);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int hose_read_config_word (struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short *value)
-{
- unsigned long addr;
- unsigned char type1;
-
- *value = 0xffff;
-
- if (where & 0x1) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- addr |= 0x08; /* or in length */
-
- *value = conf_read(addr, type1, hose) >> ((where & 3) * 8);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int hose_read_config_dword (struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int *value)
-{
- unsigned long addr;
- unsigned char type1;
-
- *value = 0xffffffff;
-
- if (where & 0x3) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= 0x18; /* or in length */
-
- *value = conf_read(addr, type1, hose);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int hose_write_config_byte (struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char value)
-{
- unsigned long addr;
- unsigned char type1;
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- addr |= 0x00; /* or in length */
-
- conf_write(addr, value << ((where & 3) * 8), type1, hose);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int hose_write_config_word (struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short value)
-{
- unsigned long addr;
- unsigned char type1;
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- addr |= 0x08; /* or in length */
-
- conf_write(addr, value << ((where & 3) * 8), type1, hose);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int hose_write_config_dword (struct linux_hose_info *hose,
- unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int value)
-{
- unsigned long addr;
- unsigned char type1;
-
- if (mk_conf_addr(hose, bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- addr |= 0x18; /* or in length */
-
- conf_write(addr, value << ((where & 3) * 8), type1, hose);
- return PCIBIOS_SUCCESSFUL;
-}
-
-int pcibios_read_config_byte (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned char *value)
-{
- return hose_read_config_byte(bus2hose[bus], bus, devfn, where, value);
-}
-
-int pcibios_read_config_word (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned short *value)
-{
- return hose_read_config_word(bus2hose[bus], bus, devfn, where, value);
-}
-
-int pcibios_read_config_dword (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned int *value)
-{
- return hose_read_config_dword(bus2hose[bus], bus, devfn, where, value);
-}
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned char value)
-{
- return hose_write_config_byte(bus2hose[bus], bus, devfn, where, value);
-}
-
-int pcibios_write_config_word (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned short value)
-{
- return hose_write_config_word(bus2hose[bus], bus, devfn, where, value);
-}
-
-int pcibios_write_config_dword (unsigned char bus, unsigned char devfn,
- unsigned char where, unsigned int value)
-{
- return hose_write_config_dword(bus2hose[bus], bus, devfn, where, value);
-}
-
-unsigned long mcpcia_init(unsigned long mem_start, unsigned long mem_end)
-{
- struct linux_hose_info *hose;
- unsigned int mcpcia_err;
- unsigned int pci_rev;
- int h;
-
- mem_start = long_align(mem_start);
-
- for (h = 0; h < NR_CPUS; h++) {
- MCPCIA_mcheck_expected[h] = 0;
- MCPCIA_mcheck_taken[h] = 0;
- }
-
- /* first, find how many hoses we have */
- for (h = 0; h < MCPCIA_MAX_HOSES; h++) {
- pci_rev = *(vuip)MCPCIA_REV(h);
-#if 0
- printk("mcpcia_init: got 0x%x for PCI_REV for hose %d\n",
- pci_rev, h);
-#endif
- if ((pci_rev >> 16) == PCI_CLASS_BRIDGE_HOST) {
- mcpcia_num_hoses++;
-
- hose = (struct linux_hose_info *)mem_start;
- mem_start = long_align(mem_start + sizeof(*hose));
-
- memset(hose, 0, sizeof(*hose));
-
- if (mcpcia_root)
- mcpcia_last_hose->next = hose;
- else
- mcpcia_root = hose;
- mcpcia_last_hose = hose;
-
- hose->pci_io_space = MCPCIA_IO(h);
- hose->pci_mem_space = MCPCIA_DENSE(h);
- hose->pci_config_space = MCPCIA_CONF(h);
- hose->pci_sparse_space = MCPCIA_SPARSE(h);
- hose->pci_hose_index = h;
- hose->pci_first_busno = 255;
- hose->pci_last_busno = 0;
- }
- }
-
-#if 1
- printk("mcpcia_init: found %d hoses\n", mcpcia_num_hoses);
-#endif
-
- /* now do init for each hose */
- for (hose = mcpcia_root; hose; hose = hose->next) {
- h = hose->pci_hose_index;
-#if 0
-#define PRINTK printk
-PRINTK("mcpcia_init: -------- hose %d --------\n",h);
-PRINTK("mcpcia_init: MCPCIA_REV 0x%x\n", *(vuip)MCPCIA_REV(h));
-PRINTK("mcpcia_init: MCPCIA_WHOAMI 0x%x\n", *(vuip)MCPCIA_WHOAMI(h));
-PRINTK("mcpcia_init: MCPCIA_HAE_MEM 0x%x\n", *(vuip)MCPCIA_HAE_MEM(h));
-PRINTK("mcpcia_init: MCPCIA_HAE_IO 0x%x\n", *(vuip)MCPCIA_HAE_IO(h));
-PRINTK("mcpcia_init: MCPCIA_HAE_DENSE 0x%x\n", *(vuip)MCPCIA_HAE_DENSE(h));
-PRINTK("mcpcia_init: MCPCIA_INT_CTL 0x%x\n", *(vuip)MCPCIA_INT_CTL(h));
-PRINTK("mcpcia_init: MCPCIA_INT_REQ 0x%x\n", *(vuip)MCPCIA_INT_REQ(h));
-PRINTK("mcpcia_init: MCPCIA_INT_TARG 0x%x\n", *(vuip)MCPCIA_INT_TARG(h));
-PRINTK("mcpcia_init: MCPCIA_INT_ADR 0x%x\n", *(vuip)MCPCIA_INT_ADR(h));
-PRINTK("mcpcia_init: MCPCIA_INT_ADR_EXT 0x%x\n", *(vuip)MCPCIA_INT_ADR_EXT(h));
-PRINTK("mcpcia_init: MCPCIA_INT_MASK0 0x%x\n", *(vuip)MCPCIA_INT_MASK0(h));
-PRINTK("mcpcia_init: MCPCIA_INT_MASK1 0x%x\n", *(vuip)MCPCIA_INT_MASK1(h));
-PRINTK("mcpcia_init: MCPCIA_HBASE 0x%x\n", *(vuip)MCPCIA_HBASE(h));
-#endif
-
- /*
- * Set up error reporting. Make sure CPU_PE is OFF in the mask.
- */
-#if 0
- mcpcia_err = *(vuip)MCPCIA_ERR_MASK(h);
- mcpcia_err &= ~4;
- *(vuip)MCPCIA_ERR_MASK(h) = mcpcia_err;
- mb();
- mcpcia_err = *(vuip)MCPCIA_ERR_MASK;
-#endif
-
- mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
- mcpcia_err |= 0x0006; /* master/target abort */
- *(vuip)MCPCIA_CAP_ERR(h) = mcpcia_err;
- mb() ;
- mcpcia_err = *(vuip)MCPCIA_CAP_ERR(h);
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 0 for enabled and mapped to 0 */
- if (((*(vuip)MCPCIA_W0_BASE(h) & 3) == 1) &&
- (*(vuip)MCPCIA_T0_BASE(h) == 0) &&
- ((*(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U) > 0x0ff00000U))
- {
- MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W0_BASE(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W0_MASK(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("mcpcia_init: using Window 0 settings\n");
- printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)MCPCIA_W0_BASE(h),
- *(vuip)MCPCIA_W0_MASK(h),
- *(vuip)MCPCIA_T0_BASE(h));
-#endif
- }
- else /* check window 1 for enabled and mapped to 0 */
- if (((*(vuip)MCPCIA_W1_BASE(h) & 3) == 1) &&
- (*(vuip)MCPCIA_T1_BASE(h) == 0) &&
- ((*(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U) > 0x0ff00000U))
-{
- MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W1_BASE(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W1_MASK(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("mcpcia_init: using Window 1 settings\n");
- printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)MCPCIA_W1_BASE(h),
- *(vuip)MCPCIA_W1_MASK(h),
- *(vuip)MCPCIA_T1_BASE(h));
-#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if (((*(vuip)MCPCIA_W2_BASE(h) & 3) == 1) &&
- (*(vuip)MCPCIA_T2_BASE(h) == 0) &&
- ((*(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U) > 0x0ff00000U))
- {
- MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W2_BASE(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W2_MASK(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("mcpcia_init: using Window 2 settings\n");
- printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)MCPCIA_W2_BASE(h),
- *(vuip)MCPCIA_W2_MASK(h),
- *(vuip)MCPCIA_T2_BASE(h));
-#endif
- }
- else /* check window 3 for enabled and mapped to 0 */
- if (((*(vuip)MCPCIA_W3_BASE(h) & 3) == 1) &&
- (*(vuip)MCPCIA_T3_BASE(h) == 0) &&
- ((*(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U) > 0x0ff00000U))
- {
- MCPCIA_DMA_WIN_BASE = *(vuip)MCPCIA_W3_BASE(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE = *(vuip)MCPCIA_W3_MASK(h) & 0xfff00000U;
- MCPCIA_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("mcpcia_init: using Window 3 settings\n");
- printk("mcpcia_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)MCPCIA_W3_BASE(h),
- *(vuip)MCPCIA_W3_MASK(h),
- *(vuip)MCPCIA_T3_BASE(h));
-#endif
- }
- else /* we must use our defaults which were pre-initialized... */
-#endif /* SRM_SETUP */
- {
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, windows 1,2 and 3 are disabled. In the future, we may
- * want to use them to do scatter/gather DMA. Window 0
- * goes at 1 GB and is 1 GB large.
- */
-
- *(vuip)MCPCIA_W0_BASE(h) = 1U | (MCPCIA_DMA_WIN_BASE & 0xfff00000U);
- *(vuip)MCPCIA_W0_MASK(h) = (MCPCIA_DMA_WIN_SIZE - 1) & 0xfff00000U;
- *(vuip)MCPCIA_T0_BASE(h) = 0;
-
- *(vuip)MCPCIA_W1_BASE(h) = 0x0 ;
- *(vuip)MCPCIA_W2_BASE(h) = 0x0 ;
- *(vuip)MCPCIA_W3_BASE(h) = 0x0 ;
-
- *(vuip)MCPCIA_HBASE(h) = 0x0 ;
- mb();
- }
-
- /*
- * check ASN in HWRPB for validity, report if bad
- */
- if (hwrpb->max_asn != MAX_ASN) {
- printk("mcpcia_init: max ASN from HWRPB is bad (0x%lx)\n",
- hwrpb->max_asn);
- hwrpb->max_asn = MAX_ASN;
- }
-
-#if 0
- {
- unsigned int mcpcia_int_ctl = *((vuip)MCPCIA_INT_CTL(h));
- printk("mcpcia_init: INT_CTL was 0x%x\n", mcpcia_int_ctl);
- *(vuip)MCPCIA_INT_CTL(h) = 1U; mb();
- mcpcia_int_ctl = *(vuip)MCPCIA_INT_CTL(h);
- }
-#endif
-
- {
- unsigned int mcpcia_hae_mem = *(vuip)MCPCIA_HAE_MEM(h);
- unsigned int mcpcia_hae_io = *(vuip)MCPCIA_HAE_IO(h);
-#if 0
- printk("mcpcia_init: HAE_MEM was 0x%x\n", mcpcia_hae_mem);
- printk("mcpcia_init: HAE_IO was 0x%x\n", mcpcia_hae_io);
-#endif
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /*
- sigh... For the SRM setup, unless we know apriori what the HAE
- contents will be, we need to setup the arbitrary region bases
- so we can test against the range of addresses and tailor the
- region chosen for the SPARSE memory access.
-
- see include/asm-alpha/mcpcia.h for the SPARSE mem read/write
- */
- mcpcia_sm_base_r1 = (mcpcia_hae_mem ) & 0xe0000000UL;/* reg 1 */
- mcpcia_sm_base_r2 = (mcpcia_hae_mem << 16) & 0xf8000000UL;/* reg 2 */
- mcpcia_sm_base_r3 = (mcpcia_hae_mem << 24) & 0xfc000000UL;/* reg 3 */
- /*
- Set the HAE cache, so that setup_arch() code
- will use the SRM setting always. Our readb/writeb
- code in mcpcia.h expects never to have to change
- the contents of the HAE.
- */
- hae.cache = mcpcia_hae_mem;
-#else /* SRM_SETUP */
- *(vuip)MCPCIA_HAE_MEM(h) = 0U; mb();
- mcpcia_hae_mem = *(vuip)MCPCIA_HAE_MEM(h);
- *(vuip)MCPCIA_HAE_IO(h) = 0; mb();
- mcpcia_hae_io = *(vuip)MCPCIA_HAE_IO(h);
-#endif /* SRM_SETUP */
- }
- } /* end for-loop on hoses */
- return mem_start;
-}
-
-int mcpcia_pci_clr_err(int h)
-{
- unsigned int cpu = smp_processor_id();
-
- MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h);
-#if 0
- DBG_MCK(("MCPCIA_pci_clr_err: MCPCIA CAP_ERR(%d) after read 0x%x\n",
- h, MCPCIA_jd[cpu]));
-#endif
- *(vuip)MCPCIA_CAP_ERR(h) = 0xffffffff; mb(); /* clear them all */
- MCPCIA_jd[cpu] = *(vuip)MCPCIA_CAP_ERR(h);
- return 0;
-}
-
-static void
-mcpcia_print_uncorrectable(struct el_MCPCIA_uncorrected_frame_mcheck *logout)
-{
- struct el_common_EV5_uncorrectable_mcheck *frame;
- int i;
-
- frame = &logout->procdata;
-
- /* Print PAL fields */
- for (i = 0; i < 24; i += 2) {
- printk("\tpal temp[%d-%d]\t\t= %16lx %16lx\n\r",
- i, i+1, frame->paltemp[i], frame->paltemp[i+1]);
- }
- for (i = 0; i < 8; i += 2) {
- printk("\tshadow[%d-%d]\t\t= %16lx %16lx\n\r",
- i, i+1, frame->shadow[i],
- frame->shadow[i+1]);
- }
- printk("\tAddr of excepting instruction\t= %16lx\n\r",
- frame->exc_addr);
- printk("\tSummary of arithmetic traps\t= %16lx\n\r",
- frame->exc_sum);
- printk("\tException mask\t\t\t= %16lx\n\r",
- frame->exc_mask);
- printk("\tBase address for PALcode\t= %16lx\n\r",
- frame->pal_base);
- printk("\tInterrupt Status Reg\t\t= %16lx\n\r",
- frame->isr);
- printk("\tCURRENT SETUP OF EV5 IBOX\t= %16lx\n\r",
- frame->icsr);
- printk("\tI-CACHE Reg %s parity error\t= %16lx\n\r",
- (frame->ic_perr_stat & 0x800L) ?
- "Data" : "Tag",
- frame->ic_perr_stat);
- printk("\tD-CACHE error Reg\t\t= %16lx\n\r",
- frame->dc_perr_stat);
- if (frame->dc_perr_stat & 0x2) {
- switch (frame->dc_perr_stat & 0x03c) {
- case 8:
- printk("\t\tData error in bank 1\n\r");
- break;
- case 4:
- printk("\t\tData error in bank 0\n\r");
- break;
- case 20:
- printk("\t\tTag error in bank 1\n\r");
- break;
- case 10:
- printk("\t\tTag error in bank 0\n\r");
- break;
- }
- }
- printk("\tEffective VA\t\t\t= %16lx\n\r",
- frame->va);
- printk("\tReason for D-stream\t\t= %16lx\n\r",
- frame->mm_stat);
- printk("\tEV5 SCache address\t\t= %16lx\n\r",
- frame->sc_addr);
- printk("\tEV5 SCache TAG/Data parity\t= %16lx\n\r",
- frame->sc_stat);
- printk("\tEV5 BC_TAG_ADDR\t\t\t= %16lx\n\r",
- frame->bc_tag_addr);
- printk("\tEV5 EI_ADDR: Phys addr of Xfer\t= %16lx\n\r",
- frame->ei_addr);
- printk("\tFill Syndrome\t\t\t= %16lx\n\r",
- frame->fill_syndrome);
- printk("\tEI_STAT reg\t\t\t= %16lx\n\r",
- frame->ei_stat);
- printk("\tLD_LOCK\t\t\t\t= %16lx\n\r",
- frame->ld_lock);
-}
-
-void mcpcia_machine_check(unsigned long type, unsigned long la_ptr,
- struct pt_regs * regs)
-{
-#if 0
- printk("mcpcia machine check ignored\n") ;
-#else
- struct el_common *mchk_header;
- struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout;
- unsigned int cpu = smp_processor_id();
- int h = 0;
-
- mchk_header = (struct el_common *)la_ptr;
- mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr;
-
-#if 0
- DBG_MCK(("mcpcia_machine_check: type=0x%lx la_ptr=0x%lx\n",
- type, la_ptr));
- DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset));
-#endif
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
- mb();
- mb(); /* magic */
- if (MCPCIA_mcheck_expected[cpu]) {
-#if 0
- DBG_MCK(("MCPCIA machine check expected\n"));
-#endif
- MCPCIA_mcheck_expected[cpu] = 0;
- MCPCIA_mcheck_taken[cpu] = 1;
- mb();
- mb(); /* magic */
- draina();
- mcpcia_pci_clr_err(h);
- wrmces(0x7);
- mb();
- }
-#if 1
- else {
- printk("MCPCIA machine check NOT expected on CPU %d\n", cpu);
- DBG_MCK(("mcpcia_machine_check: type=0x%lx pc=0x%lx"
- " code=0x%lx\n",
- type, regs->pc, mchk_header->code));
-
- MCPCIA_mcheck_expected[cpu] = 0;
- MCPCIA_mcheck_taken[cpu] = 1;
- mb();
- mb(); /* magic */
- draina();
- mcpcia_pci_clr_err(h);
- wrmces(0x7);
- mb();
-#ifdef DEBUG_MCHECK_DUMP
- if (type == 0x620)
- printk("MCPCIA machine check: system CORRECTABLE!\n");
- else if (type == 0x630)
- printk("MCPCIA machine check: processor CORRECTABLE!\n");
- else
- mcpcia_print_uncorrectable(mchk_logout);
-#endif /* DEBUG_MCHECK_DUMP */
- }
-#endif
-#endif
-}
-
-/*==========================================================================*/
-
-#define PRIMARY(b) ((b)&0xff)
-#define SECONDARY(b) (((b)>>8)&0xff)
-#define SUBORDINATE(b) (((b)>>16)&0xff)
-
-static int
-hose_scan_bridges(struct linux_hose_info *hose, unsigned char bus)
-{
- unsigned int devfn, l, class;
- unsigned char hdr_type = 0;
- unsigned int found = 0;
-
- for (devfn = 0; devfn < 0xff; ++devfn) {
- if (PCI_FUNC(devfn) == 0) {
- hose_read_config_byte(hose, bus, devfn,
- PCI_HEADER_TYPE, &hdr_type);
- } else if (!(hdr_type & 0x80)) {
- /* not a multi-function device */
- continue;
- }
-
- /* Check if there is anything here. */
- hose_read_config_dword(hose, bus, devfn, PCI_VENDOR_ID, &l);
- if (l == 0xffffffff || l == 0x00000000) {
- hdr_type = 0;
- continue;
- }
-
- /* See if this is a bridge device. */
- hose_read_config_dword(hose, bus, devfn,
- PCI_CLASS_REVISION, &class);
-
- if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
- unsigned int busses;
-
- found++;
-
- hose_read_config_dword(hose, bus, devfn,
- PCI_PRIMARY_BUS, &busses);
-
-DBG_PCI(("hose_scan_bridges: hose %d bus %d slot %d busses 0x%x\n",
- hose->pci_hose_index, bus, PCI_SLOT(devfn), busses));
- /*
- * do something with first_busno and last_busno
- */
- if (hose->pci_first_busno > PRIMARY(busses)) {
- hose->pci_first_busno = PRIMARY(busses);
-DBG_PCI(("hose_scan_bridges: hose %d bus %d slot %d change first to %d\n",
- hose->pci_hose_index, bus, PCI_SLOT(devfn), PRIMARY(busses)));
- }
- if (hose->pci_last_busno < SUBORDINATE(busses)) {
- hose->pci_last_busno = SUBORDINATE(busses);
-DBG_PCI(("hose_scan_bridges: hose %d bus %d slot %d change last to %d\n",
- hose->pci_hose_index, bus, PCI_SLOT(devfn), SUBORDINATE(busses)));
- }
- /*
- * Now scan everything underneath the bridge.
- */
- hose_scan_bridges(hose, SECONDARY(busses));
- }
- }
- return found;
-}
-
-static void
-hose_reconfigure_bridges(struct linux_hose_info *hose, unsigned char bus)
-{
- unsigned int devfn, l, class;
- unsigned char hdr_type = 0;
-
- for (devfn = 0; devfn < 0xff; ++devfn) {
- if (PCI_FUNC(devfn) == 0) {
- hose_read_config_byte(hose, bus, devfn,
- PCI_HEADER_TYPE, &hdr_type);
- } else if (!(hdr_type & 0x80)) {
- /* not a multi-function device */
- continue;
- }
-
- /* Check if there is anything here. */
- hose_read_config_dword(hose, bus, devfn, PCI_VENDOR_ID, &l);
- if (l == 0xffffffff || l == 0x00000000) {
- hdr_type = 0;
- continue;
- }
-
- /* See if this is a bridge device. */
- hose_read_config_dword(hose, bus, devfn,
- PCI_CLASS_REVISION, &class);
-
- if ((class >> 16) == PCI_CLASS_BRIDGE_PCI) {
- unsigned int busses;
-
- hose_read_config_dword(hose, bus, devfn,
- PCI_PRIMARY_BUS, &busses);
-
- /*
- * First reconfigure everything underneath the bridge.
- */
- hose_reconfigure_bridges(hose, (busses >> 8) & 0xff);
-
- /*
- * Unconfigure this bridges bus numbers,
- * pci_scan_bus() will fix this up properly.
- */
- busses &= 0xff000000;
- hose_write_config_dword(hose, bus, devfn,
- PCI_PRIMARY_BUS, busses);
- }
- }
-}
-
-static void mcpcia_fixup_busno(struct linux_hose_info *hose, unsigned char bus)
-{
- unsigned int nbus;
-
- /*
- * First, scan for all bridge devices underneath this hose,
- * to determine the first and last busnos.
- */
- if (!hose_scan_bridges(hose, 0)) {
- /* none found, exit */
- hose->pci_first_busno = bus;
- hose->pci_last_busno = bus;
- } else {
- /*
- * Reconfigure all bridge devices underneath this hose.
- */
- hose_reconfigure_bridges(hose, hose->pci_first_busno);
- }
-
- /*
- * Now reconfigure the hose to it's new bus number and set up
- * our bus2hose mapping for this hose.
- */
- nbus = hose->pci_last_busno - hose->pci_first_busno;
-
- hose->pci_first_busno = bus;
-
-DBG_PCI(("mcpcia_fixup_busno: hose %d startbus %d nbus %d\n",
- hose->pci_hose_index, bus, nbus));
-
- do {
- bus2hose[bus++] = hose;
- } while (nbus-- > 0);
-}
-
-static void mcpcia_probe(struct linux_hose_info *hose,
- unsigned long *mem_start)
-{
- static struct pci_bus *pchain = NULL;
- struct pci_bus *pbus = &hose->pci_bus;
- static unsigned char busno = 0;
-
- /* Hoses include child PCI bridges in bus-range property,
- * but we don't scan each of those ourselves, Linux generic PCI
- * probing code will find child bridges and link them into this
- * hose's root PCI device hierarchy.
- */
-
- pbus->number = pbus->secondary = busno;
- pbus->sysdata = hose;
-
- mcpcia_fixup_busno(hose, busno);
-
- pbus->subordinate = pci_scan_bus(pbus, mem_start); /* the original! */
-
- /*
- * Set the maximum subordinate bus of this hose.
- */
- hose->pci_last_busno = pbus->subordinate;
-#if 0
- hose_write_config_byte(hose, busno, 0, 0x41, hose->pci_last_busno);
-#endif
- busno = pbus->subordinate + 1;
-
- /*
- * Fixup the chain of primary PCI busses.
- */
- if (pchain) {
- pchain->next = &hose->pci_bus;
- pchain = pchain->next;
- } else {
- pchain = &pci_root;
- memcpy(pchain, &hose->pci_bus, sizeof(pci_root));
- }
-}
-
-void mcpcia_fixup(void)
-{
- struct linux_hose_info *hose;
-
- /* turn on Config space access finally! */
- pci_probe_enabled = 1;
-
- /* for each hose, probe and setup the devices on the hose */
- for (hose = mcpcia_root; hose; hose = hose->next) {
- mcpcia_probe(hose, &memory_start);
- }
-}
-#endif /* CONFIG_ALPHA_MCPCIA */
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
index a63fb2be6..b3e919500 100644
--- a/arch/alpha/kernel/osf_sys.c
+++ b/arch/alpha/kernel/osf_sys.c
@@ -30,6 +30,7 @@
#include <linux/mman.h>
#include <linux/shm.h>
#include <linux/poll.h>
+#include <linux/file.h>
#include <asm/fpu.h>
#include <asm/io.h>
@@ -46,7 +47,7 @@ extern struct file_operations *get_chrfops(unsigned int);
extern kdev_t get_unnamed_dev(void);
extern void put_unnamed_dev(kdev_t);
-extern asmlinkage int sys_umount(char *);
+extern asmlinkage int sys_umount(char *, int);
extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags);
extern asmlinkage unsigned long sys_brk(unsigned long);
@@ -137,13 +138,11 @@ asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent,
{
int error;
struct file *file;
+ struct inode *inode;
struct osf_dirent_callback buf;
error = -EBADF;
- if (fd >= NR_OPEN)
- goto out;
-
- file = current->files->fd[fd];
+ file = fget(fd);
if (!file)
goto out;
@@ -154,17 +153,25 @@ asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent *dirent,
error = -ENOTDIR;
if (!file->f_op || !file->f_op->readdir)
- goto out;
+ goto out_putf;
+ /*
+ * Get the inode's semaphore to prevent changes
+ * to the directory while we read it.
+ */
+ inode = file->f_dentry->d_inode;
+ down(&inode->i_sem);
error = file->f_op->readdir(file, &buf, osf_filldir);
+ up(&inode->i_sem);
if (error < 0)
- goto out;
+ goto out_putf;
error = buf.error;
- if (count == buf.count)
- goto out;
+ if (count != buf.count)
+ error = count - buf.count;
- error = count - buf.count;
+out_putf:
+ fput(file);
out:
return error;
}
@@ -248,13 +255,17 @@ asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
lock_kernel();
if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED))
- printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, flags);
+ printk("%s: unimplemented OSF mmap flags %04lx\n",
+ current->comm, flags);
if (!(flags & MAP_ANONYMOUS)) {
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ file = fget(fd);
+ if (!file)
goto out;
}
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
ret = do_mmap(file, addr, len, prot, flags, off);
+ if (file)
+ fput(file);
out:
unlock_kernel();
return ret;
@@ -340,11 +351,13 @@ asmlinkage int osf_fstatfs(unsigned long fd, struct osf_statfs *buffer, unsigned
lock_kernel();
retval = -EBADF;
- if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
+ file = fget(fd);
+ if (!file)
goto out;
dentry = file->f_dentry;
if (dentry)
retval = do_osf_statfs(dentry, buffer, bufsiz);
+ fput(file);
out:
unlock_kernel();
return retval;
@@ -366,8 +379,8 @@ struct cdfs_args {
int flags;
uid_t exroot;
/*
- * this has lots more here, which linux handles with the option block
- * but I'm too lazy to do the translation into ascii..
+ * This has lots more here, which Linux handles with the option block
+ * but I'm too lazy to do the translation into ASCII.
*/
};
@@ -390,38 +403,41 @@ static int getdev(const char *name, int rdonly, struct dentry **dp)
if (IS_ERR(dentry))
return retval;
+ retval = -ENOTBLK;
inode = dentry->d_inode;
- if (!S_ISBLK(inode->i_mode)) {
- dput(dentry);
- return -ENOTBLK;
- }
- if (IS_NODEV(inode)) {
- dput(dentry);
- return -EACCES;
- }
+ if (!S_ISBLK(inode->i_mode))
+ goto out_dput;
+
+ retval = -EACCES;
+ if (IS_NODEV(inode))
+ goto out_dput;
+
+ retval = -ENXIO;
dev = inode->i_rdev;
- if (MAJOR(dev) >= MAX_BLKDEV) {
- dput(dentry);
- return -ENXIO;
- }
+ if (MAJOR(dev) >= MAX_BLKDEV)
+ goto out_dput;
+
+ retval = -ENODEV;
fops = get_blkfops(MAJOR(dev));
- if (!fops) {
- dput(dentry);
- return -ENODEV;
- }
+ if (!fops)
+ goto out_dput;
if (fops->open) {
struct file dummy;
memset(&dummy, 0, sizeof(dummy));
dummy.f_dentry = dentry;
dummy.f_mode = rdonly ? 1 : 3;
retval = fops->open(inode, &dummy);
- if (retval) {
- dput(dentry);
- return retval;
- }
+ if (retval)
+ goto out_dput;
}
*dp = dentry;
- return 0;
+ retval = 0;
+out:
+ return retval;
+
+out_dput:
+ dput(dentry);
+ goto out;
}
static void putdev(struct dentry *dentry)
@@ -435,8 +451,8 @@ static void putdev(struct dentry *dentry)
/*
* We can't actually handle ufs yet, so we translate UFS mounts to
- * ext2fs mounts... I wouldn't mind a UFS filesystem, but the UFS
- * layout is so braindead it's a major headache doing it..
+ * ext2fs mounts. I wouldn't mind a UFS filesystem, but the UFS
+ * layout is so braindead it's a major headache doing it.
*/
static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags)
{
@@ -444,17 +460,19 @@ static int osf_ufs_mount(char *dirname, struct ufs_args *args, int flags)
struct dentry *dentry;
struct cdfs_args tmp;
- retval = verify_area(VERIFY_READ, args, sizeof(*args));
- if (retval)
- return retval;
- copy_from_user(&tmp, args, sizeof(tmp));
+ retval = -EFAULT;
+ if (copy_from_user(&tmp, args, sizeof(tmp)))
+ goto out;
+
retval = getdev(tmp.devname, 0, &dentry);
if (retval)
- return retval;
- retval = do_mount(dentry->d_inode->i_rdev, tmp.devname, dirname, "ext2", flags, NULL);
+ goto out;
+ retval = do_mount(dentry->d_inode->i_rdev, tmp.devname, dirname,
+ "ext2", flags, NULL);
if (retval)
putdev(dentry);
dput(dentry);
+out:
return retval;
}
@@ -464,17 +482,19 @@ static int osf_cdfs_mount(char *dirname, struct cdfs_args *args, int flags)
struct dentry * dentry;
struct cdfs_args tmp;
- retval = verify_area(VERIFY_READ, args, sizeof(*args));
- if (retval)
- return retval;
- copy_from_user(&tmp, args, sizeof(tmp));
+ retval = -EFAULT;
+ if (copy_from_user(&tmp, args, sizeof(tmp)))
+ goto out;
+
retval = getdev(tmp.devname, 1, &dentry);
if (retval)
- return retval;
- retval = do_mount(dentry->d_inode->i_rdev, tmp.devname, dirname, "iso9660", flags, NULL);
+ goto out;
+ retval = do_mount(dentry->d_inode->i_rdev, tmp.devname, dirname,
+ "iso9660", flags, NULL);
if (retval)
putdev(dentry);
dput(dentry);
+out:
return retval;
}
@@ -484,10 +504,8 @@ static int osf_procfs_mount(char *dirname, struct procfs_args *args, int flags)
int retval;
struct procfs_args tmp;
- retval = verify_area(VERIFY_READ, args, sizeof(*args));
- if (retval)
- return retval;
- copy_from_user(&tmp, args, sizeof(tmp));
+ if (copy_from_user(&tmp, args, sizeof(tmp)))
+ return -EFAULT;
dev = get_unnamed_dev();
if (!dev)
return -ENODEV;
@@ -524,7 +542,7 @@ asmlinkage int osf_umount(char *path, int flag)
int ret;
lock_kernel();
- ret = sys_umount(path);
+ ret = sys_umount(path,flag);
unlock_kernel();
return ret;
}
@@ -533,17 +551,22 @@ asmlinkage int osf_utsname(char *name)
{
int error;
- lock_kernel();
- error = verify_area(VERIFY_WRITE, name, 5 * 32);
- if (error)
+ down(&uts_sem);
+ error = -EFAULT;
+ if (copy_to_user(name + 0, system_utsname.sysname, 32))
+ goto out;
+ if (copy_to_user(name + 32, system_utsname.nodename, 32))
goto out;
- copy_to_user(name + 0, system_utsname.sysname, 32);
- copy_to_user(name + 32, system_utsname.nodename, 32);
- copy_to_user(name + 64, system_utsname.release, 32);
- copy_to_user(name + 96, system_utsname.version, 32);
- copy_to_user(name + 128, system_utsname.machine, 32);
+ if (copy_to_user(name + 64, system_utsname.release, 32))
+ goto out;
+ if (copy_to_user(name + 96, system_utsname.version, 32))
+ goto out;
+ if (copy_to_user(name + 128, system_utsname.machine, 32))
+ goto out;
+
+ error = 0;
out:
- unlock_kernel();
+ up(&uts_sem);
return error;
}
@@ -602,11 +625,13 @@ asmlinkage int osf_getdomainname(char *name, int namelen)
if (namelen > 32)
len = 32;
+ down(&uts_sem);
for (i = 0; i < len; ++i) {
- put_user(system_utsname.domainname[i], name + i);
+ __put_user(system_utsname.domainname[i], name + i);
if (system_utsname.domainname[i] == '\0')
break;
}
+ up(&uts_sem);
out:
unlock_kernel();
return error;
@@ -743,6 +768,50 @@ asmlinkage long osf_proplist_syscall(enum pl_code code, union pl_args *args)
return error;
}
+asmlinkage int osf_sigstack(struct sigstack *uss, struct sigstack *uoss)
+{
+ unsigned long usp = rdusp();
+ unsigned long oss_sp, oss_os;
+ int error;
+
+ if (uoss) {
+ oss_sp = current->sas_ss_sp + current->sas_ss_size;
+ oss_os = on_sig_stack(usp);
+ }
+
+ if (uss) {
+ void *ss_sp;
+
+ error = -EFAULT;
+ if (get_user(ss_sp, &uss->ss_sp))
+ goto out;
+
+ /* If the current stack was set with sigaltstack, don't
+ swap stacks while we are on it. */
+ error = -EPERM;
+ if (current->sas_ss_sp && on_sig_stack(usp))
+ goto out;
+
+ /* Since we don't know the extent of the stack, and we don't
+ track onstack-ness, but rather calculate it, we must
+ presume a size. Ho hum this interface is lossy. */
+ current->sas_ss_sp = (unsigned long)ss_sp - SIGSTKSZ;
+ current->sas_ss_size = SIGSTKSZ;
+ }
+
+ if (uoss) {
+ error = -EFAULT;
+ if (! access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))
+ || __put_user(oss_sp, &uoss->ss_sp)
+ || __put_user(oss_os, &uoss->ss_onstack))
+ goto out;
+ }
+
+ error = 0;
+out:
+ return error;
+}
+
/*
* The Linux kernel isn't good at returning values that look
* like negative longs (they are mistaken as error values).
@@ -795,10 +864,12 @@ asmlinkage long osf_sysinfo(int command, char *buf, long count)
lock_kernel();
offset = command-1;
if (offset >= sizeof(sysinfo_table)/sizeof(char *)) {
- /* Digital unix has a few unpublished interfaces here */
+ /* Digital UNIX has a few unpublished interfaces here */
printk("sysinfo(%d)", command);
goto out;
}
+
+ down(&uts_sem);
res = sysinfo_table[offset];
len = strlen(res)+1;
if (len > count)
@@ -807,6 +878,7 @@ asmlinkage long osf_sysinfo(int command, char *buf, long count)
err = -EFAULT;
else
err = 0;
+ up(&uts_sem);
out:
unlock_kernel();
return err;
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 401a7af46..697572e7a 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -5,7 +5,7 @@
*/
/*
- * This file handles the architecture-dependent parts of process handling..
+ * This file handles the architecture-dependent parts of process handling.
*/
#include <linux/config.h>
@@ -28,6 +28,7 @@
#include <linux/mman.h>
#include <linux/elfcore.h>
#include <linux/reboot.h>
+#include <linux/console.h>
#ifdef CONFIG_RTC
#include <linux/mc146818rtc.h>
@@ -41,6 +42,9 @@
#include <asm/hwrpb.h>
#include <asm/fpu.h>
+#include "proto.h"
+#include "bios32.h"
+
/*
* Initial task structure. Make this a per-architecture thing,
* because different architectures tend to have different
@@ -62,34 +66,26 @@ union task_union init_task_union __attribute__((section("init_task")))
/*
* No need to acquire the kernel lock, we're entirely local..
*/
-asmlinkage int sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2,
- unsigned long a3, unsigned long a4, unsigned long a5,
- struct pt_regs regs)
+asmlinkage int
+sys_sethae(unsigned long hae, unsigned long a1, unsigned long a2,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs regs)
{
-#if !defined(CONFIG_ALPHA_TSUNAMI)
(&regs)->hae = hae;
-#endif
return 0;
}
#ifdef __SMP__
/* This is being executed in task 0 'user space'. */
#define resched_needed() 1
-int cpu_idle(void *unused)
+int
+cpu_idle(void *unused)
{
extern volatile int smp_commenced;
current->priority = -100;
while (1) {
- /*
- * tq_scheduler currently assumes we're running in a process
- * context (ie that we hold the kernel lock..)
- */
- if (tq_scheduler) {
- lock_kernel();
- run_task_queue(&tq_scheduler);
- unlock_kernel();
- }
+ run_task_queue(&tq_scheduler);
/* endless idle loop with no priority at all */
current->counter = -100;
if (!smp_commenced || resched_needed()) {
@@ -98,7 +94,8 @@ int cpu_idle(void *unused)
}
}
-asmlinkage int sys_idle(void)
+asmlinkage int
+sys_idle(void)
{
if(current->pid != 0)
return -EPERM;
@@ -109,7 +106,8 @@ asmlinkage int sys_idle(void)
#else /* __SMP__ */
-asmlinkage int sys_idle(void)
+asmlinkage int
+sys_idle(void)
{
int ret = -EPERM;
@@ -120,6 +118,7 @@ asmlinkage int sys_idle(void)
/* endless idle loop with no priority at all */
current->counter = -100;
for (;;) {
+ check_pgt_cache();
schedule();
}
ret = 0;
@@ -129,90 +128,101 @@ out:
}
#endif /* __SMP__ */
-#if defined(CONFIG_ALPHA_SRM_SETUP)
-extern void reset_for_srm(void);
-extern unsigned long srm_hae;
-#endif
-
-static void finish_shutdown(void)
+void
+generic_kill_arch (int mode, char *restart_cmd)
{
-#ifdef CONFIG_RTC /* reset rtc to defaults */
- unsigned char control;
- unsigned long flags;
-
- /* i'm not sure if i really need to disable interrupts here */
- save_and_cli(flags);
-
- /* reset periodic interrupt frequency */
- CMOS_WRITE(0x26, RTC_FREQ_SELECT);
-
- /* turn on periodic interrupts */
- control = CMOS_READ(RTC_CONTROL);
- control |= RTC_PIE;
- CMOS_WRITE(control, RTC_CONTROL);
- CMOS_READ(RTC_INTR_FLAGS);
- restore_flags(flags);
+ /* The following currently only has any effect on SRM. We should
+ fix MILO to understand it. Should be pretty easy. Also we can
+ support RESTART2 via the ipc_buffer machinations pictured below,
+ which SRM ignores. */
+
+ if (alpha_using_srm) {
+ struct percpu_struct *cpup;
+ unsigned long flags;
+
+ cpup = (struct percpu_struct *)
+ ((unsigned long)hwrpb + hwrpb->processor_offset);
+
+ flags = cpup->flags;
+
+ /* Clear reason to "default"; clear "bootstrap in progress". */
+ flags &= ~0x00ff0001UL;
+
+ if (mode == LINUX_REBOOT_CMD_RESTART) {
+ if (!restart_cmd) {
+ flags |= 0x00020000UL; /* "cold bootstrap" */
+ cpup->ipc_buffer[0] = 0;
+ } else {
+ flags |= 0x00030000UL; /* "warm bootstrap" */
+ strncpy(cpup->ipc_buffer, restart_cmd,
+ sizeof(cpup->ipc_buffer));
+ }
+ }
+ else {
+ flags |= 0x00040000UL; /* "remain halted" */
+ }
+
+ cpup->flags = flags;
+ mb();
+
+ if (alpha_use_srm_setup) {
+ reset_for_srm();
+ set_hae(srm_hae);
+ }
+
+#ifdef CONFIG_DUMMY_CONSOLE
+ /* This has the effect of reseting the VGA video origin. */
+ take_over_console(&dummy_con, 0, MAX_NR_CONSOLES-1, 1);
#endif
-#if defined(CONFIG_ALPHA_SRM) && defined(CONFIG_ALPHA_ALCOR)
- /* who said DEC engineer's have no sense of humor? ;-)) */
- *(int *) GRU_RESET = 0x0000dead;
- mb();
+ }
+
+#ifdef CONFIG_RTC
+ /* Reset rtc to defaults. */
+ {
+ unsigned char control;
+ unsigned long flags;
+
+ /* I'm not sure if i really need to disable interrupts here. */
+ save_and_cli(flags);
+
+ /* Reset periodic interrupt frequency. */
+ CMOS_WRITE(0x26, RTC_FREQ_SELECT);
+
+ /* Turn on periodic interrupts. */
+ control = CMOS_READ(RTC_CONTROL);
+ control |= RTC_PIE;
+ CMOS_WRITE(control, RTC_CONTROL);
+ CMOS_READ(RTC_INTR_FLAGS);
+
+ restore_flags(flags);
+ }
#endif
+
+ if (!alpha_using_srm && mode != LINUX_REBOOT_CMD_RESTART) {
+ /* Unfortunately, since MILO doesn't currently understand
+ the hwrpb bits above, we can't reliably halt the
+ processor and keep it halted. So just loop. */
+ return;
+ }
+
halt();
}
-void machine_restart(char * __unused)
+void
+machine_restart(char *restart_cmd)
{
-#if defined(CONFIG_ALPHA_SRM)
- extern struct hwrpb_struct *hwrpb;
- struct percpu_struct *cpup;
- unsigned long flags;
-
- cpup = (struct percpu_struct *)
- ((unsigned long)hwrpb + hwrpb->processor_offset);
- flags = cpup->flags;
- flags &= ~0x0000000000ff0001UL; /* clear reason to "default" */
- flags |= 0x0000000000020000UL; /* this is "cold bootstrap" */
-/* flags |= 0x0000000000030000UL; *//* this is "warm bootstrap" */
- cpup->flags = flags;
- mb();
-#if defined(CONFIG_ALPHA_SRM_SETUP)
- reset_for_srm();
- set_hae(srm_hae);
-#endif
-#endif /* SRM */
-
- finish_shutdown();
+ alpha_mv.kill_arch(LINUX_REBOOT_CMD_RESTART, restart_cmd);
}
-void machine_halt(void)
+void
+machine_halt(void)
{
-#if defined(CONFIG_ALPHA_SRM)
- extern struct hwrpb_struct *hwrpb;
- struct percpu_struct *cpup;
- unsigned long flags;
-
- cpup = (struct percpu_struct *)
- ((unsigned long)hwrpb + hwrpb->processor_offset);
- flags = cpup->flags;
- flags &= ~0x0000000000ff0001UL; /* clear reason to "default" */
- flags |= 0x0000000000040000UL; /* this is "remain halted" */
- cpup->flags = flags;
- mb();
-#if defined(CONFIG_ALPHA_SRM_SETUP)
- reset_for_srm();
- set_hae(srm_hae);
-#endif
-
- finish_shutdown();
-#endif /* SRM */
+ alpha_mv.kill_arch(LINUX_REBOOT_CMD_HALT, NULL);
}
void machine_power_off(void)
{
- /* None of the machines we support, at least, has switchable
- power supplies. */
- machine_halt();
+ alpha_mv.kill_arch(LINUX_REBOOT_CMD_POWER_OFF, NULL);
}
void show_regs(struct pt_regs * regs)
@@ -254,7 +264,7 @@ void exit_thread(void)
void flush_thread(void)
{
/* Arrange for each exec'ed process to start off with a
- clean slate wrt the fpu. */
+ clean slate with respect to the FPU. */
current->tss.flags &= ~IEEE_SW_MASK;
wrfpcr(FPCR_DYN_NORMAL);
}
diff --git a/arch/alpha/kernel/proto.h b/arch/alpha/kernel/proto.h
new file mode 100644
index 000000000..f55a0edba
--- /dev/null
+++ b/arch/alpha/kernel/proto.h
@@ -0,0 +1,131 @@
+/* Prototypes of functions used across modules here in this directory. */
+
+#define vucp volatile unsigned char *
+#define vusp volatile unsigned short *
+#define vip volatile int *
+#define vuip volatile unsigned int *
+#define vulp volatile unsigned long *
+
+/* core_apecs.c */
+extern int apecs_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int apecs_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int apecs_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int apecs_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int apecs_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int apecs_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void apecs_init_arch(unsigned long *, unsigned long *);
+
+extern volatile unsigned int apecs_mcheck_expected;
+extern volatile unsigned int apecs_mcheck_taken;
+extern int apecs_pci_clr_err(void);
+extern void apecs_machine_check(u64, u64, struct pt_regs *);
+
+/* core_cia.c */
+extern int cia_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int cia_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int cia_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int cia_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int cia_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int cia_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void cia_init_arch(unsigned long *, unsigned long *);
+extern void cia_machine_check(u64, u64, struct pt_regs *);
+
+/* core_lca.c */
+extern int lca_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int lca_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int lca_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int lca_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int lca_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int lca_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void lca_init_arch(unsigned long *, unsigned long *);
+extern void lca_machine_check(u64, u64, struct pt_regs *);
+
+/* core_mcpcia.c */
+extern int mcpcia_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int mcpcia_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int mcpcia_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int mcpcia_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int mcpcia_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int mcpcia_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void mcpcia_init_arch(unsigned long *, unsigned long *);
+extern void mcpcia_machine_check(u64, u64, struct pt_regs *);
+extern void mcpcia_pci_fixup(void);
+
+/* core_pyxis.c */
+extern int pyxis_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int pyxis_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int pyxis_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int pyxis_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int pyxis_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int pyxis_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void pyxis_enable_errors (void);
+extern int pyxis_srm_window_setup (void);
+extern void pyxis_native_window_setup(void);
+extern void pyxis_finish_init_arch(void);
+extern void pyxis_init_arch(unsigned long *, unsigned long *);
+extern void pyxis_machine_check(u64, u64, struct pt_regs *);
+
+/* core_t2.c */
+extern int t2_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int t2_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int t2_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int t2_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int t2_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int t2_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void t2_init_arch(unsigned long *, unsigned long *);
+extern void t2_machine_check(u64, u64, struct pt_regs *);
+
+/* core_tsunami.c */
+extern int tsunami_pcibios_read_config_byte (u8, u8, u8, u8 *value);
+extern int tsunami_pcibios_read_config_word (u8, u8, u8, u16 *value);
+extern int tsunami_pcibios_read_config_dword (u8, u8, u8, u32 *value);
+extern int tsunami_pcibios_write_config_byte (u8, u8, u8, u8 value);
+extern int tsunami_pcibios_write_config_word (u8, u8, u8, u16 value);
+extern int tsunami_pcibios_write_config_dword (u8, u8, u8, u32 value);
+extern void tsunami_init_arch(unsigned long *, unsigned long *);
+extern void tsunami_machine_check(u64, u64, struct pt_regs *);
+
+/* setup.c */
+extern void init_pit_rest(void);
+extern void generic_init_pit (void);
+extern unsigned long srm_hae;
+
+/* smp.c */
+extern void setup_smp(void);
+extern char *smp_info(void);
+extern void handle_ipi(struct pt_regs *);
+
+/* bios32.c */
+extern void reset_for_srm(void);
+
+/* time.c */
+extern void timer_interrupt(struct pt_regs * regs);
+
+/* smc37c93x.c */
+extern void SMC93x_Init(void);
+
+/* smc37c669.c */
+extern void SMC669_Init(void);
+
+/* es1888.c */
+extern void es1888_init(void);
+
+/* fpregs.c */
+extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
+extern unsigned long alpha_read_fp_reg (unsigned long reg);
+
+/* head.S */
+extern void wrmces(unsigned long mces);
+extern void cserve_ena(unsigned long);
+extern void cserve_dis(unsigned long);
+
+/* entry.S */
+extern void entArith(void);
+extern void entIF(void);
+extern void entInt(void);
+extern void entMM(void);
+extern void entSys(void);
+extern void entUna(void);
+
+/* process.c */
+void generic_kill_arch (int mode, char *reboot_cmd);
diff --git a/arch/alpha/kernel/ptrace.c b/arch/alpha/kernel/ptrace.c
index c8b31623d..384f534af 100644
--- a/arch/alpha/kernel/ptrace.c
+++ b/arch/alpha/kernel/ptrace.c
@@ -13,7 +13,6 @@
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/user.h>
-#include <linux/debugreg.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
@@ -23,13 +22,13 @@
#ifdef DEBUG
- enum {
- DBG_MEM = (1<<0),
- DBG_BPT = (1<<1),
- DBG_MEM_ALL = (1<<2)
- };
+enum {
+ DBG_MEM = (1<<0),
+ DBG_BPT = (1<<1),
+ DBG_MEM_ALL = (1<<2)
+};
- int debug_mask = DBG_BPT;
+int debug_mask = DBG_BPT;
# define DBG(fac,args) {if ((fac) & debug_mask) printk args;}
@@ -150,7 +149,7 @@ static inline int put_reg(struct task_struct *task, long regno, long data)
* no checking.
*/
static unsigned long get_long(struct task_struct * tsk,
- struct vm_area_struct * vma, unsigned long addr)
+ struct vm_area_struct * vma, unsigned long addr)
{
pgd_t * pgdir;
pmd_t * pgmiddle;
@@ -158,7 +157,7 @@ static unsigned long get_long(struct task_struct * tsk,
unsigned long page;
DBG(DBG_MEM_ALL, ("getting long at 0x%lx\n", addr));
-repeat:
+ repeat:
pgdir = pgd_offset(vma->vm_mm, addr);
if (pgd_none(*pgdir)) {
handle_mm_fault(tsk, vma, addr, 0);
@@ -185,7 +184,7 @@ repeat:
goto repeat;
}
page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
+ /* this is a hack for non-kernel-mapped video buffers and similar */
if (MAP_NR(page) >= max_mapnr)
return 0;
page += addr & ~PAGE_MASK;
@@ -202,14 +201,14 @@ repeat:
* even if a debugger scribbles breakpoints into it. -M.U-
*/
static void put_long(struct task_struct * tsk, struct vm_area_struct * vma,
- unsigned long addr, unsigned long data)
+ unsigned long addr, unsigned long data)
{
pgd_t *pgdir;
pmd_t *pgmiddle;
pte_t *pgtable;
unsigned long page;
-repeat:
+ repeat:
pgdir = pgd_offset(vma->vm_mm, addr);
if (!pgd_present(*pgdir)) {
handle_mm_fault(tsk, vma, addr, 1);
@@ -240,11 +239,14 @@ repeat:
handle_mm_fault(tsk, vma, addr, 1);
goto repeat;
}
-/* this is a hack for non-kernel-mapped video buffers and similar */
+
+ /* This is a hack for non-kernel-mapped video buffers and similar. */
if (MAP_NR(page) < max_mapnr)
*(unsigned long *) (page + (addr & ~PAGE_MASK)) = data;
-/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
-/* this should also re-instate whatever read-only mode there was before */
+
+ /* We're bypassing pagetables, so we have to set the dirty bit
+ ourselves. This should also re-instate whatever read-only
+ mode there was before. */
set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
flush_tlb();
}
@@ -279,10 +281,8 @@ static int read_long(struct task_struct * tsk, unsigned long addr,
struct vm_area_struct * vma = find_extend_vma(tsk, addr);
DBG(DBG_MEM_ALL, ("in read_long\n"));
- if (!vma) {
- printk("Unable to find vma for addr 0x%lx\n",addr);
+ if (!vma)
return -EIO;
- }
if ((addr & ~PAGE_MASK) > (PAGE_SIZE - sizeof(long))) {
struct vm_area_struct * vma_high = vma;
unsigned long low, align;
@@ -296,11 +296,11 @@ static int read_long(struct task_struct * tsk, unsigned long addr,
addr -= align;
low = get_long(tsk, vma, addr);
if (align) {
- unsigned long high;
+ unsigned long high;
- high = get_long(tsk, vma_high, addr + sizeof(long));
- low >>= align * 8;
- low |= high << (64 - align * 8);
+ high = get_long(tsk, vma_high, addr + sizeof(long));
+ low >>= align * 8;
+ low |= high << (64 - align * 8);
}
*result = low;
} else {
@@ -317,7 +317,7 @@ static int read_long(struct task_struct * tsk, unsigned long addr,
* within the task area. It then calls put_long() to write a long.
*/
static int write_long(struct task_struct * tsk, unsigned long addr,
- unsigned long data)
+ unsigned long data)
{
struct vm_area_struct * vma = find_extend_vma(tsk, addr);
@@ -361,7 +361,7 @@ static int read_int(struct task_struct * tsk, unsigned long addr,
res = read_long(tsk, addr, &l);
if (res < 0)
- return res;
+ return res;
if (align == 0) {
*data = l;
@@ -388,7 +388,7 @@ static int write_int(struct task_struct * tsk, unsigned long addr,
res = read_long(tsk, addr, &l);
if (res < 0)
- return res;
+ return res;
if (align == 0) {
l = (l & 0xffffffff00000000UL) | ((unsigned long) data << 0);
@@ -410,7 +410,7 @@ int ptrace_set_bpt(struct task_struct * child)
pc = get_reg(child, REG_PC);
res = read_int(child, pc, &insn);
if (res < 0)
- return res;
+ return res;
op_code = insn >> 26;
if (op_code >= 0x30) {
@@ -423,31 +423,31 @@ int ptrace_set_bpt(struct task_struct * child)
* branch (emulation can be tricky for fp branches).
*/
displ = ((s32)(insn << 11)) >> 9;
- child->debugreg[nsaved++] = pc + 4;
+ child->tss.debugreg[nsaved++] = pc + 4;
if (displ) /* guard against unoptimized code */
- child->debugreg[nsaved++] = pc + 4 + displ;
+ child->tss.debugreg[nsaved++] = pc + 4 + displ;
DBG(DBG_BPT, ("execing branch\n"));
} else if (op_code == 0x1a) {
reg_b = (insn >> 16) & 0x1f;
- child->debugreg[nsaved++] = get_reg(child, reg_b);
+ child->tss.debugreg[nsaved++] = get_reg(child, reg_b);
DBG(DBG_BPT, ("execing jump\n"));
} else {
- child->debugreg[nsaved++] = pc + 4;
+ child->tss.debugreg[nsaved++] = pc + 4;
DBG(DBG_BPT, ("execing normal insn\n"));
}
/* install breakpoints: */
for (i = 0; i < nsaved; ++i) {
- res = read_int(child, child->debugreg[i], &insn);
+ res = read_int(child, child->tss.debugreg[i], &insn);
if (res < 0)
- return res;
- child->debugreg[i + 2] = insn;
- DBG(DBG_BPT, (" -> next_pc=%lx\n", child->debugreg[i]));
- res = write_int(child, child->debugreg[i], BREAKINST);
+ return res;
+ child->tss.debugreg[i + 2] = insn;
+ DBG(DBG_BPT, (" -> next_pc=%lx\n", child->tss.debugreg[i]));
+ res = write_int(child, child->tss.debugreg[i], BREAKINST);
if (res < 0)
- return res;
+ return res;
}
- child->debugreg[4] = nsaved;
+ child->tss.debugreg[4] = nsaved;
return 0;
}
@@ -457,17 +457,18 @@ int ptrace_set_bpt(struct task_struct * child)
*/
int ptrace_cancel_bpt(struct task_struct * child)
{
- int i, nsaved = child->debugreg[4];
+ int i, nsaved = child->tss.debugreg[4];
- child->debugreg[4] = 0;
+ child->tss.debugreg[4] = 0;
if (nsaved > 2) {
- printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
- nsaved = 2;
+ printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
+ nsaved = 2;
}
for (i = 0; i < nsaved; ++i) {
- write_int(child, child->debugreg[i], child->debugreg[i + 2]);
+ write_int(child, child->tss.debugreg[i],
+ child->tss.debugreg[i + 2]);
}
return (nsaved != 0);
}
@@ -506,7 +507,8 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->sgid) ||
- (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+ (current->gid != child->gid))
+ && !capable(CAP_SYS_PTRACE))
goto out;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
@@ -537,107 +539,107 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data,
}
switch (request) {
- /* when I and D space are separate, these will need to be fixed. */
- case PTRACE_PEEKTEXT: /* read word at location addr. */
- case PTRACE_PEEKDATA: {
- unsigned long tmp;
-
- ret = read_long(child, addr, &tmp);
- DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp));
- if (ret < 0)
- goto out;
- regs.r0 = 0; /* special return: no errors */
- ret = tmp;
+ /* When I and D space are separate, these will need to be fixed. */
+ case PTRACE_PEEKTEXT: /* read word at location addr. */
+ case PTRACE_PEEKDATA: {
+ unsigned long tmp;
+
+ ret = read_long(child, addr, &tmp);
+ DBG(DBG_MEM, ("peek %#lx->%#lx\n", addr, tmp));
+ if (ret < 0)
goto out;
- }
+ regs.r0 = 0; /* special return: no errors */
+ ret = tmp;
+ goto out;
+ }
/* read register number ADDR. */
- case PTRACE_PEEKUSR:
- regs.r0 = 0; /* special return: no errors */
- DBG(DBG_MEM, ("peek $%ld=%#lx\n", addr, regs.r0));
- ret = get_reg(child, addr);
- goto out;
+ case PTRACE_PEEKUSR:
+ regs.r0 = 0; /* special return: no errors */
+ DBG(DBG_MEM, ("peek $%ld=%#lx\n", addr, regs.r0));
+ ret = get_reg(child, addr);
+ goto out;
- /* 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:
- DBG(DBG_MEM, ("poke %#lx<-%#lx\n", addr, data));
- ret = write_long(child, addr, data);
- goto out;
+ /* 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:
+ DBG(DBG_MEM, ("poke %#lx<-%#lx\n", addr, data));
+ ret = write_long(child, addr, data);
+ goto out;
- case PTRACE_POKEUSR: /* write the specified register */
- DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
- ret = put_reg(child, addr, data);
- goto out;
+ case PTRACE_POKEUSR: /* write the specified register */
+ DBG(DBG_MEM, ("poke $%ld<-%#lx\n", addr, data));
+ ret = put_reg(child, addr, data);
+ goto out;
- case PTRACE_SYSCALL: /* continue and stop at next
- (return from) syscall */
- case PTRACE_CONT: { /* restart after signal. */
- ret = -EIO;
- if ((unsigned long) data > _NSIG)
- goto out;
- if (request == PTRACE_SYSCALL)
- child->flags |= PF_TRACESYS;
- else
- child->flags &= ~PF_TRACESYS;
- child->exit_code = data;
- wake_up_process(child);
- /* make sure single-step breakpoint is gone. */
- ptrace_cancel_bpt(child);
- ret = data;
+ case PTRACE_SYSCALL: /* continue and stop at next
+ (return from) syscall */
+ case PTRACE_CONT: { /* restart after signal. */
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
goto out;
- }
+ if (request == PTRACE_SYSCALL)
+ child->flags |= PF_TRACESYS;
+ else
+ child->flags &= ~PF_TRACESYS;
+ child->exit_code = data;
+ wake_up_process(child);
+ /* make sure single-step breakpoint is gone. */
+ ptrace_cancel_bpt(child);
+ ret = data;
+ goto out;
+ }
-/*
- * make the child exit. Best I can do is send it a sigkill.
- * perhaps it should be put in the status that it wants to
- * exit.
- */
- case PTRACE_KILL: {
- if (child->state != TASK_ZOMBIE) {
- wake_up_process(child);
- child->exit_code = SIGKILL;
- }
- /* make sure single-step breakpoint is gone. */
- ptrace_cancel_bpt(child);
- ret = 0;
- goto out;
+ /*
+ * Make the child exit. Best I can do is send it a sigkill.
+ * perhaps it should be put in the status that it wants to
+ * exit.
+ */
+ case PTRACE_KILL: {
+ if (child->state != TASK_ZOMBIE) {
+ wake_up_process(child);
+ child->exit_code = SIGKILL;
}
+ /* make sure single-step breakpoint is gone. */
+ ptrace_cancel_bpt(child);
+ ret = 0;
+ goto out;
+ }
- case PTRACE_SINGLESTEP: { /* execute single instruction. */
- ret = -EIO;
- if ((unsigned long) data > _NSIG)
- goto out;
- child->debugreg[4] = -1; /* mark single-stepping */
- child->flags &= ~PF_TRACESYS;
- wake_up_process(child);
- child->exit_code = data;
- /* give it a chance to run. */
- ret = 0;
+ case PTRACE_SINGLESTEP: { /* execute single instruction. */
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
goto out;
- }
+ child->tss.debugreg[4] = -1; /* mark single-stepping */
+ child->flags &= ~PF_TRACESYS;
+ wake_up_process(child);
+ child->exit_code = data;
+ /* give it a chance to run. */
+ ret = 0;
+ goto out;
+ }
- case PTRACE_DETACH: { /* detach a process that was attached. */
- ret = -EIO;
- if ((unsigned long) data > _NSIG)
- goto out;
- child->flags &= ~(PF_PTRACED|PF_TRACESYS);
- wake_up_process(child);
- child->exit_code = data;
- REMOVE_LINKS(child);
- child->p_pptr = child->p_opptr;
- SET_LINKS(child);
- /* make sure single-step breakpoint is gone. */
- ptrace_cancel_bpt(child);
- ret = 0;
+ case PTRACE_DETACH: { /* detach a process that was attached. */
+ ret = -EIO;
+ if ((unsigned long) data > _NSIG)
goto out;
- }
+ child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+ wake_up_process(child);
+ child->exit_code = data;
+ REMOVE_LINKS(child);
+ child->p_pptr = child->p_opptr;
+ SET_LINKS(child);
+ /* make sure single-step breakpoint is gone. */
+ ptrace_cancel_bpt(child);
+ ret = 0;
+ goto out;
+ }
- default:
- ret = -EIO;
- goto out;
- }
-out:
+ default:
+ ret = -EIO;
+ goto out;
+ }
+ out:
unlock_kernel();
return ret;
}
@@ -645,7 +647,7 @@ out:
asmlinkage void syscall_trace(void)
{
if ((current->flags & (PF_PTRACED|PF_TRACESYS))
- != (PF_PTRACED|PF_TRACESYS))
+ != (PF_PTRACED|PF_TRACESYS))
return;
current->exit_code = SIGTRAP;
current->state = TASK_STOPPED;
diff --git a/arch/alpha/kernel/pyxis.c b/arch/alpha/kernel/pyxis.c
deleted file mode 100644
index de3814b66..000000000
--- a/arch/alpha/kernel/pyxis.c
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
- * Code common to all PYXIS chips.
- *
- * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
- *
- */
-#include <linux/config.h> /* CONFIG_ALPHA_RUFFIAN. */
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/hwrpb.h>
-#include <asm/ptrace.h>
-#include <asm/mmu_context.h>
-
-/* NOTE: Herein are back-to-back mb instructions. They are magic.
- One plausible explanation is that the I/O controller does not properly
- handle the system transaction. Another involves timing. Ho hum. */
-
-extern struct hwrpb_struct *hwrpb;
-extern asmlinkage void wrmces(unsigned long mces);
-
-/*
- * BIOS32-style PCI interface:
- */
-
-#ifdef DEBUG
-# define DBG(args) printk args
-#else
-# define DBG(args)
-#endif
-
-#define DEBUG_MCHECK
-#ifdef DEBUG_MCHECK
-# define DBG_MCK(args) printk args
-#define DEBUG_MCHECK_DUMP
-#else
-# define DBG_MCK(args)
-#endif
-
-#define vulp volatile unsigned long *
-#define vuip volatile unsigned int *
-
-static volatile unsigned int PYXIS_mcheck_expected = 0;
-static volatile unsigned int PYXIS_mcheck_taken = 0;
-static unsigned int PYXIS_jd;
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int PYXIS_DMA_WIN_BASE = PYXIS_DMA_WIN_BASE_DEFAULT;
-unsigned int PYXIS_DMA_WIN_SIZE = PYXIS_DMA_WIN_SIZE_DEFAULT;
-unsigned long pyxis_sm_base_r1, pyxis_sm_base_r2, pyxis_sm_base_r3;
-#endif /* SRM_SETUP */
-
-/*
- * Given a bus, device, and function number, compute resulting
- * configuration space address and setup the PYXIS_HAXR2 register
- * accordingly. It is therefore not safe to have concurrent
- * invocations to configuration space access routines, but there
- * really shouldn't be any need for this.
- *
- * Type 0:
- *
- * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
- * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | | |D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|0|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- * 31:11 Device select bit.
- * 10:8 Function number
- * 7:2 Register number
- *
- * Type 1:
- *
- * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
- * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- * 31:24 reserved
- * 23:16 bus number (8 bits = 128 possible buses)
- * 15:11 Device number (5 bits)
- * 10:8 function number
- * 7:2 register number
- *
- * Notes:
- * The function number selects which function of a multi-function device
- * (e.g., scsi and ethernet).
- *
- * The register selects a DWORD (32 bit) register offset. Hence it
- * doesn't get shifted by 2 bits as we want to "drop" the bottom two
- * bits.
- */
-static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned long *pci_addr,
- unsigned char *type1)
-{
- unsigned long addr;
-
- DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x,"
- " pci_addr=0x%p, type1=0x%p)\n",
- bus, device_fn, where, pci_addr, type1));
-
- if (bus == 0) {
- int device;
-
- device = device_fn >> 3;
- /* type 0 configuration cycle: */
-#if NOT_NOW
- if (device > 20) {
- DBG(("mk_conf_addr: device (%d) > 20, returning -1\n",
- device));
- return -1;
- }
-#endif
- *type1 = 0;
- addr = (device_fn << 8) | (where);
- } else {
- /* type 1 configuration cycle: */
- *type1 = 1;
- addr = (bus << 16) | (device_fn << 8) | (where);
- }
- *pci_addr = addr;
- DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
- return 0;
-}
-
-
-static unsigned int conf_read(unsigned long addr, unsigned char type1)
-{
- unsigned long flags;
- unsigned int stat0, value, temp;
- unsigned int pyxis_cfg = 0; /* to keep gcc quiet */
-
- save_and_cli(flags); /* avoid getting hit by machine check */
-
- DBG(("conf_read(addr=0x%lx, type1=%d)\n", addr, type1));
-
- /* reset status register to avoid losing errors: */
- stat0 = *(vuip)PYXIS_ERR;
- *(vuip)PYXIS_ERR = stat0; mb();
- temp = *(vuip)PYXIS_ERR; /* re-read to force write */
- DBG(("conf_read: PYXIS ERR was 0x%x\n", stat0));
- /* if Type1 access, must set PYXIS CFG */
- if (type1) {
- pyxis_cfg = *(vuip)PYXIS_CFG;
- *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- DBG(("conf_read: TYPE1 access\n"));
- }
-
- mb();
- draina();
- PYXIS_mcheck_expected = 1;
- PYXIS_mcheck_taken = 0;
- mb();
- /* access configuration space: */
- value = *(vuip)addr;
- mb();
- mb(); /* magic */
- if (PYXIS_mcheck_taken) {
- PYXIS_mcheck_taken = 0;
- value = 0xffffffffU;
- mb();
- }
- PYXIS_mcheck_expected = 0;
- mb();
-
- /* if Type1 access, must reset IOC CFG so normal IO space ops work */
- if (type1) {
- *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- }
-
- DBG(("conf_read(): finished\n"));
-
- restore_flags(flags);
- return value;
-}
-
-
-static void conf_write(unsigned long addr, unsigned int value,
- unsigned char type1)
-{
- unsigned long flags;
- unsigned int stat0, temp;
- unsigned int pyxis_cfg = 0; /* to keep gcc quiet */
-
- save_and_cli(flags); /* avoid getting hit by machine check */
-
- /* reset status register to avoid losing errors: */
- stat0 = *(vuip)PYXIS_ERR;
- *(vuip)PYXIS_ERR = stat0; mb();
- temp = *(vuip)PYXIS_ERR; /* re-read to force write */
- DBG(("conf_write: PYXIS ERR was 0x%x\n", stat0));
- /* if Type1 access, must set PYXIS CFG */
- if (type1) {
- pyxis_cfg = *(vuip)PYXIS_CFG;
- *(vuip)PYXIS_CFG = pyxis_cfg | 1; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- DBG(("conf_read: TYPE1 access\n"));
- }
-
- draina();
- PYXIS_mcheck_expected = 1;
- mb();
- /* access configuration space: */
- *(vuip)addr = value;
- mb();
- mb(); /* magic */
- temp = *(vuip)PYXIS_ERR; /* do a PYXIS read to force the write */
- PYXIS_mcheck_expected = 0;
- mb();
-
- /* if Type1 access, must reset IOC CFG so normal IO space ops work */
- if (type1) {
- *(vuip)PYXIS_CFG = pyxis_cfg & ~1; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- }
-
- DBG(("conf_write(): finished\n"));
- restore_flags(flags);
-}
-
-
-int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
-{
- unsigned long addr = PYXIS_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- *value = 0xff;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- addr |= (pci_addr << 5) + 0x00;
-
- *value = conf_read(addr, type1) >> ((where & 3) * 8);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short *value)
-{
- unsigned long addr = PYXIS_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- *value = 0xffff;
-
- if (where & 0x1) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- addr |= (pci_addr << 5) + 0x08;
-
- *value = conf_read(addr, type1) >> ((where & 3) * 8);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int *value)
-{
- unsigned long addr = PYXIS_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- *value = 0xffffffff;
- if (where & 0x3) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x18;
- *value = conf_read(addr, type1);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char value)
-{
- unsigned long addr = PYXIS_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x00;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short value)
-{
- unsigned long addr = PYXIS_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x08;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int value)
-{
- unsigned long addr = PYXIS_CONF;
- unsigned long pci_addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &pci_addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
- addr |= (pci_addr << 5) + 0x18;
- conf_write(addr, value << ((where & 3) * 8), type1);
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-unsigned long pyxis_init(unsigned long mem_start, unsigned long mem_end)
-{
- unsigned int pyxis_err ;
-
-#if 0
-printk("pyxis_init: PYXIS_ERR_MASK 0x%x\n", *(vuip)PYXIS_ERR_MASK);
-printk("pyxis_init: PYXIS_ERR 0x%x\n", *(vuip)PYXIS_ERR);
-
-printk("pyxis_init: PYXIS_INT_REQ 0x%lx\n", *(vulp)PYXIS_INT_REQ);
-printk("pyxis_init: PYXIS_INT_MASK 0x%lx\n", *(vulp)PYXIS_INT_MASK);
-printk("pyxis_init: PYXIS_INT_ROUTE 0x%lx\n", *(vulp)PYXIS_INT_ROUTE);
-printk("pyxis_init: PYXIS_INT_HILO 0x%lx\n", *(vulp)PYXIS_INT_HILO);
-printk("pyxis_init: PYXIS_INT_CNFG 0x%x\n", *(vuip)PYXIS_INT_CNFG);
-printk("pyxis_init: PYXIS_RT_COUNT 0x%lx\n", *(vulp)PYXIS_RT_COUNT);
-#endif
-
- /*
- * Set up error reporting. Make sure CPU_PE is OFF in the mask.
- */
- pyxis_err = *(vuip)PYXIS_ERR_MASK;
- pyxis_err &= ~4;
- *(vuip)PYXIS_ERR_MASK = pyxis_err; mb();
- pyxis_err = *(vuip)PYXIS_ERR_MASK; /* re-read to force write */
-
- pyxis_err = *(vuip)PYXIS_ERR ;
- pyxis_err |= 0x180; /* master/target abort */
- *(vuip)PYXIS_ERR = pyxis_err; mb();
- pyxis_err = *(vuip)PYXIS_ERR; /* re-read to force write */
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 0 for enabled and mapped to 0 */
- if (((*(vuip)PYXIS_W0_BASE & 3) == 1) &&
- (*(vuip)PYXIS_T0_BASE == 0) &&
- ((*(vuip)PYXIS_W0_MASK & 0xfff00000U) > 0x0ff00000U))
- {
- PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W0_BASE & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W0_MASK & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("pyxis_init: using Window 0 settings\n");
- printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)PYXIS_W0_BASE,
- *(vuip)PYXIS_W0_MASK,
- *(vuip)PYXIS_T0_BASE);
-#endif
- }
- else /* check window 1 for enabled and mapped to 0 */
- if (((*(vuip)PYXIS_W1_BASE & 3) == 1) &&
- (*(vuip)PYXIS_T1_BASE == 0) &&
- ((*(vuip)PYXIS_W1_MASK & 0xfff00000U) > 0x0ff00000U))
-{
- PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W1_BASE & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W1_MASK & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("pyxis_init: using Window 1 settings\n");
- printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)PYXIS_W1_BASE,
- *(vuip)PYXIS_W1_MASK,
- *(vuip)PYXIS_T1_BASE);
-#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if (((*(vuip)PYXIS_W2_BASE & 3) == 1) &&
- (*(vuip)PYXIS_T2_BASE == 0) &&
- ((*(vuip)PYXIS_W2_MASK & 0xfff00000U) > 0x0ff00000U))
- {
- PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W2_BASE & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W2_MASK & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("pyxis_init: using Window 2 settings\n");
- printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)PYXIS_W2_BASE,
- *(vuip)PYXIS_W2_MASK,
- *(vuip)PYXIS_T2_BASE);
-#endif
- }
- else /* check window 3 for enabled and mapped to 0 */
- if (((*(vuip)PYXIS_W3_BASE & 3) == 1) &&
- (*(vuip)PYXIS_T3_BASE == 0) &&
- ((*(vuip)PYXIS_W3_MASK & 0xfff00000U) > 0x0ff00000U))
- {
- PYXIS_DMA_WIN_BASE = *(vuip)PYXIS_W3_BASE & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE = *(vuip)PYXIS_W3_MASK & 0xfff00000U;
- PYXIS_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("pyxis_init: using Window 3 settings\n");
- printk("pyxis_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vuip)PYXIS_W3_BASE,
- *(vuip)PYXIS_W3_MASK,
- *(vuip)PYXIS_T3_BASE);
-#endif
- }
- else /* we must use our defaults which were pre-initialized... */
-#endif /* SRM_SETUP */
- {
-#if defined(CONFIG_ALPHA_RUFFIAN)
-#if 1
- printk("pyxis_init: skipping window register rewrites... "
- " trust DeskStation firmware!\n");
-#endif
-#else /* RUFFIAN */
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, windows 1,2 and 3 are disabled. In the future, we may
- * want to use them to do scatter/gather DMA. Window 0
- * goes at 1 GB and is 1 GB large.
- */
-
- *(vuip)PYXIS_W0_BASE = 1U | (PYXIS_DMA_WIN_BASE & 0xfff00000U);
- *(vuip)PYXIS_W0_MASK = (PYXIS_DMA_WIN_SIZE - 1) & 0xfff00000U;
- *(vuip)PYXIS_T0_BASE = 0;
-
- *(vuip)PYXIS_W1_BASE = 0x0 ;
- *(vuip)PYXIS_W2_BASE = 0x0 ;
- *(vuip)PYXIS_W3_BASE = 0x0 ;
- mb();
-#endif /* RUFFIAN */
- }
-
- /*
- * check ASN in HWRPB for validity, report if bad
- */
- if (hwrpb->max_asn != MAX_ASN) {
- printk("PYXIS_init: max ASN from HWRPB is bad (0x%lx)\n",
- hwrpb->max_asn);
- hwrpb->max_asn = MAX_ASN;
- }
-
- /*
- * Next, clear the PYXIS_CFG register, which gets used
- * for PCI Config Space accesses. That is the way
- * we want to use it, and we do not want to depend on
- * what ARC or SRM might have left behind...
- */
- {
- unsigned int pyxis_cfg, temp;
- pyxis_cfg = *(vuip)PYXIS_CFG; mb();
- if (pyxis_cfg != 0) {
-#if 1
- printk("PYXIS_init: CFG was 0x%x\n", pyxis_cfg);
-#endif
- *(vuip)PYXIS_CFG = 0; mb();
- temp = *(vuip)PYXIS_CFG; /* re-read to force write */
- }
- }
-
- {
- unsigned int pyxis_hae_mem = *(vuip)PYXIS_HAE_MEM;
- unsigned int pyxis_hae_io = *(vuip)PYXIS_HAE_IO;
-#if 0
- printk("PYXIS_init: HAE_MEM was 0x%x\n", pyxis_hae_mem);
- printk("PYXIS_init: HAE_IO was 0x%x\n", pyxis_hae_io);
-#endif
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /*
- * sigh... For the SRM setup, unless we know apriori what the HAE
- * contents will be, we need to setup the arbitrary region bases
- * so we can test against the range of addresses and tailor the
- * region chosen for the SPARSE memory access.
- *
- * see include/asm-alpha/pyxis.h for the SPARSE mem read/write
- */
- pyxis_sm_base_r1 = (pyxis_hae_mem ) & 0xe0000000UL;/* region 1 */
- pyxis_sm_base_r2 = (pyxis_hae_mem << 16) & 0xf8000000UL;/* region 2 */
- pyxis_sm_base_r3 = (pyxis_hae_mem << 24) & 0xfc000000UL;/* region 3 */
-
- /*
- Set the HAE cache, so that setup_arch() code
- will use the SRM setting always. Our readb/writeb
- code in pyxis.h expects never to have to change
- the contents of the HAE.
- */
- hae.cache = pyxis_hae_mem;
-#else /* SRM_SETUP */
- *(vuip)PYXIS_HAE_MEM = 0U; mb();
- pyxis_hae_mem = *(vuip)PYXIS_HAE_MEM; /* re-read to force write */
- *(vuip)PYXIS_HAE_IO = 0; mb();
- pyxis_hae_io = *(vuip)PYXIS_HAE_IO; /* re-read to force write */
-#endif /* SRM_SETUP */
- }
-
- /*
- * Finally, check that the PYXIS_CTRL1 has IOA_BEN set for
- * enabling byte/word PCI bus space(s) access.
- */
- {
- unsigned int ctrl1;
- ctrl1 = *(vuip) PYXIS_CTRL1;
- if (!(ctrl1 & 1)) {
-#if 1
- printk("PYXIS_init: enabling byte/word PCI space\n");
-#endif
- *(vuip) PYXIS_CTRL1 = ctrl1 | 1; mb();
- ctrl1 = *(vuip)PYXIS_CTRL1; /* re-read to force write */
- }
- }
-
- return mem_start;
-}
-
-int pyxis_pci_clr_err(void)
-{
- PYXIS_jd = *(vuip)PYXIS_ERR;
- DBG(("PYXIS_pci_clr_err: PYXIS ERR after read 0x%x\n", PYXIS_jd));
- *(vuip)PYXIS_ERR = 0x0180; mb();
- PYXIS_jd = *(vuip)PYXIS_ERR; /* re-read to force write */
- return 0;
-}
-
-void pyxis_machine_check(unsigned long vector, unsigned long la_ptr,
- struct pt_regs * regs)
-{
- struct el_common *mchk_header;
- struct el_PYXIS_sysdata_mcheck *mchk_sysdata;
-
- mchk_header = (struct el_common *)la_ptr;
-
- mchk_sysdata = (struct el_PYXIS_sysdata_mcheck *)
- (la_ptr + mchk_header->sys_offset);
-
-#if 0
- DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset));
- DBG_MCK(("pyxis_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
- PYXIS_mcheck_expected, mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear));
-#endif
-#ifdef DEBUG_MCHECK_DUMP
- {
- unsigned long *ptr;
- int i;
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
- }
- }
-#endif /* DEBUG_MCHECK_DUMP */
-
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
- mb();
- mb(); /* magic */
- if (PYXIS_mcheck_expected) {
- DBG(("PYXIS machine check expected\n"));
- PYXIS_mcheck_expected = 0;
- PYXIS_mcheck_taken = 1;
- mb();
- mb(); /* magic */
- draina();
- pyxis_pci_clr_err();
- wrmces(0x7);
- mb();
- }
-#if 1
- else {
- printk("PYXIS machine check NOT expected\n") ;
- DBG_MCK(("pyxis_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x"
- " sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset));
- PYXIS_mcheck_expected = 0;
- PYXIS_mcheck_taken = 1;
- mb();
- mb(); /* magic */
- draina();
- pyxis_pci_clr_err();
- wrmces(0x7);
- mb();
- }
-#endif
-}
-
-#if defined(CONFIG_ALPHA_RUFFIAN)
-/* Note: This is only used by MILO, AFAIK... */
-/*
- * The DeskStation Ruffian motherboard firmware does not place
- * the memory size in the PALimpure area. Therefore, we use
- * the Bank Configuration Registers in PYXIS to obtain the size.
- */
-unsigned long pyxis_get_bank_size(unsigned long offset)
-{
- unsigned long bank_addr, bank, ret = 0;
-
- /* Valid offsets are: 0x800, 0x840 and 0x880
- since Ruffian only uses three banks. */
- bank_addr = (unsigned long)PYXIS_MCR + offset;
- bank = *(vulp)bank_addr;
-
- /* Check BANK_ENABLE */
- if (bank & 0x01) {
- static unsigned long size[] = {
- 0x40000000UL, /* 0x00, 1G */
- 0x20000000UL, /* 0x02, 512M */
- 0x10000000UL, /* 0x04, 256M */
- 0x08000000UL, /* 0x06, 128M */
- 0x04000000UL, /* 0x08, 64M */
- 0x02000000UL, /* 0x0a, 32M */
- 0x01000000UL, /* 0x0c, 16M */
- 0x00800000UL, /* 0x0e, 8M */
- 0x80000000UL, /* 0x10, 2G */
- };
-
- bank = (bank & 0x1e) >> 1;
- if (bank < sizeof(size)/sizeof(*size))
- ret = size[bank];
- }
-
- return ret;
-}
-#endif /* CONFIG_ALPHA_RUFFIAN */
diff --git a/arch/alpha/kernel/setup.c b/arch/alpha/kernel/setup.c
index bcab8667f..419fb47de 100644
--- a/arch/alpha/kernel/setup.c
+++ b/arch/alpha/kernel/setup.c
@@ -5,10 +5,9 @@
*/
/*
- * bootup setup stuff..
+ * Bootup setup stuff.
*/
-#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -23,6 +22,10 @@
#include <linux/config.h> /* CONFIG_ALPHA_LCA etc */
#include <linux/ioport.h>
#include <linux/mc146818rtc.h>
+#include <linux/console.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/string.h>
#ifdef CONFIG_RTC
#include <linux/timex.h>
@@ -35,8 +38,8 @@
#include <asm/dma.h>
#include <asm/io.h>
-extern void setup_smp(void);
-extern char *smp_info(void);
+
+#include "proto.h"
#if 1
# define DBG_SRM(args) printk args
@@ -44,19 +47,23 @@ extern char *smp_info(void);
# define DBG_SRM(args)
#endif
-struct hae hae = {
- 0,
- (unsigned long*) HAE_ADDRESS
-};
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
+struct hwrpb_struct *hwrpb;
unsigned long srm_hae;
-#endif
-struct hwrpb_struct *hwrpb;
+#ifdef CONFIG_ALPHA_GENERIC
+struct alpha_machine_vector alpha_mv;
+int alpha_using_srm, alpha_use_srm_setup;
+#endif
unsigned char aux_device_present = 0xaa;
+#define N(a) (sizeof(a)/sizeof(a[0]))
+
+static unsigned long find_end_memory(void);
+static struct alpha_machine_vector *get_sysvec(long, long, long);
+static struct alpha_machine_vector *get_sysvec_byname(const char *);
+static void get_sysnames(long, long, char **, char **);
+
/*
* This is setup by the secondary bootstrap loader. Because
* the zero page is zeroed out as soon as the vm system is
@@ -67,234 +74,526 @@ unsigned char aux_device_present = 0xaa;
#define COMMAND_LINE ((char*)(PARAM + 0x0000))
#define COMMAND_LINE_SIZE 256
-static char command_line[COMMAND_LINE_SIZE] = { 0, };
- char saved_command_line[COMMAND_LINE_SIZE];
+static char command_line[COMMAND_LINE_SIZE];
+char saved_command_line[COMMAND_LINE_SIZE];
+
/*
* The format of "screen_info" is strange, and due to early
* i386-setup code. This is just enough to make the console
* code think we're on a VGA color display.
*/
+
struct screen_info screen_info = {
-#if defined(CONFIG_ALPHA_BOOK1)
- /* the AlphaBook1 has LCD video fixed at 800x600, 37 rows and 100 cols */
- 0, 37, /* orig-x, orig-y */
- { 0, 0 }, /* unused */
- 0, /* orig-video-page */
- 0, /* orig-video-mode */
- 100, /* orig-video-cols */
- 0,0,0, /* ega_ax, ega_bx, ega_cx */
- 37, /* orig-video-lines */
- 1, /* orig-video-isVGA */
- 16 /* orig-video-points */
-#else
- 0, 25, /* orig-x, orig-y */
- { 0, 0 }, /* unused */
- 0, /* orig-video-page */
- 0, /* orig-video-mode */
- 80, /* orig-video-cols */
- 0,0,0, /* ega_ax, ega_bx, ega_cx */
- 25, /* orig-video-lines */
- 1, /* orig-video-isVGA */
- 16 /* orig-video-points */
-#endif
+ orig_x: 0,
+ orig_y: 25,
+ orig_video_cols: 80,
+ orig_video_lines: 25,
+ orig_video_isVGA: 1,
+ orig_video_points: 16
};
+
/*
* Initialize Programmable Interval Timers with standard values. Some
* drivers depend on them being initialized (e.g., joystick driver).
*/
-static void init_pit (void)
+
+/* It is (normally) only counter 1 that presents config problems, so
+ provide this support function to do the rest of the job. */
+
+void inline
+init_pit_rest(void)
{
#if 0
- /*
- * Leave refresh timer alone---nobody should depend on
- * a particular value anyway.
- */
- outb(0x54, 0x43); /* counter 1: refresh timer */
- outb(0x18, 0x41);
+ /* Leave refresh timer alone---nobody should depend on a
+ particular value anyway. */
+ outb(0x54, 0x43); /* counter 1: refresh timer */
+ outb(0x18, 0x41);
#endif
-#ifdef CONFIG_RTC /* setup interval timer if /dev/rtc is being used */
- outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
- outb(LATCH & 0xff, 0x40); /* LSB */
- outb(LATCH >> 8, 0x40); /* MSB */
- request_region(0x40, 0x20, "timer"); /* reserve pit */
-#else /* RTC */
-#if !defined(CONFIG_ALPHA_RUFFIAN)
- /* Ruffian depends on the system timer established in MILO!! */
- outb(0x36, 0x43); /* counter 0: system timer */
- outb(0x00, 0x40);
- outb(0x00, 0x40);
-#endif /* RUFFIAN */
- request_region(0x70, 0x10, "timer"); /* reserve rtc */
-#endif /* RTC */
-
- outb(0xb6, 0x43); /* counter 2: speaker */
- outb(0x31, 0x42);
- outb(0x13, 0x42);
+ outb(0xb6, 0x43); /* counter 2: speaker */
+ outb(0x31, 0x42);
+ outb(0x13, 0x42);
+
+ if ((CMOS_READ(RTC_FREQ_SELECT) & 0x3f) != 0x26) {
+ printk("Setting RTC_FREQ to 1024 Hz\n");
+ CMOS_WRITE(0x26, RTC_FREQ_SELECT);
+ }
}
-static unsigned long find_end_memory(void)
+#ifdef CONFIG_RTC
+static inline void
+rtc_init_pit (void)
{
- int i;
- unsigned long high = 0;
- struct memclust_struct * cluster;
- struct memdesc_struct * memdesc;
+ /* Setup interval timer if /dev/rtc is being used */
+ outb(0x34, 0x43); /* binary, mode 2, LSB/MSB, ch 0 */
+ outb(LATCH & 0xff, 0x40); /* LSB */
+ outb(LATCH >> 8, 0x40); /* MSB */
+ request_region(0x40, 0x20, "timer"); /* reserve pit */
- memdesc = (struct memdesc_struct *)
- (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB);
- cluster = memdesc->cluster;
- for (i = memdesc->numclusters ; i > 0; i--, cluster++) {
- unsigned long tmp;
- tmp = (cluster->start_pfn + cluster->numpages) << PAGE_SHIFT;
- if (tmp > high)
- high = tmp;
- }
- /* round it up to an even number of pages.. */
- high = (high + PAGE_SIZE) & (PAGE_MASK*2);
- return PAGE_OFFSET + high;
+ init_pit_rest();
}
+#endif
-void setup_arch(char **cmdline_p,
- unsigned long * memory_start_p, unsigned long * memory_end_p)
+void
+generic_init_pit (void)
{
- extern int _end;
+ outb(0x36, 0x43); /* counter 0: system timer */
+ outb(0x00, 0x40);
+ outb(0x00, 0x40);
+ request_region(RTC_PORT(0), 0x10, "timer"); /* reserve rtc */
- init_pit();
+ init_pit_rest();
+}
- if ((CMOS_READ(RTC_FREQ_SELECT) & 0x3f) != 0x26) {
- printk("setup_arch: setting RTC_FREQ to 1024/sec\n");
- CMOS_WRITE(0x26, RTC_FREQ_SELECT);
- }
+/* This probably isn't Right, but it is what the old code did. */
+#if defined(CONFIG_RTC)
+# define init_pit rtc_init_pit
+#else
+# define init_pit alpha_mv.init_pit
+#endif
- hwrpb = (struct hwrpb_struct*)(IDENT_ADDR + INIT_HWRPB->phys_addr);
-#if !defined(CONFIG_ALPHA_TSUNAMI)
-#ifdef CONFIG_ALPHA_SRM_SETUP
- srm_hae = *hae.reg; /* save SRM setting for restoration */
- DBG_SRM(("setup_arch: old HAE base: 0x%016lx\n", srm_hae));
-#endif /* SRM_SETUP */
- set_hae(hae.cache); /* sync HAE register w/hae_cache */
-#endif /* !TSUNAMI */
+/*
+ * Declare all of the machine vectors.
+ */
+
+extern struct alpha_machine_vector alcor_mv;
+extern struct alpha_machine_vector alphabook1_mv;
+extern struct alpha_machine_vector avanti_mv;
+extern struct alpha_machine_vector cabriolet_mv;
+extern struct alpha_machine_vector dp264_mv;
+extern struct alpha_machine_vector eb164_mv;
+extern struct alpha_machine_vector eb64p_mv;
+extern struct alpha_machine_vector eb66_mv;
+extern struct alpha_machine_vector eb66p_mv;
+extern struct alpha_machine_vector jensen_mv;
+extern struct alpha_machine_vector lx164_mv;
+extern struct alpha_machine_vector miata_mv;
+extern struct alpha_machine_vector mikasa_mv;
+extern struct alpha_machine_vector mikasa_primo_mv;
+extern struct alpha_machine_vector noname_mv;
+extern struct alpha_machine_vector noritake_mv;
+extern struct alpha_machine_vector noritake_primo_mv;
+extern struct alpha_machine_vector p2k_mv;
+extern struct alpha_machine_vector pc164_mv;
+extern struct alpha_machine_vector rawhide_mv;
+extern struct alpha_machine_vector ruffian_mv;
+extern struct alpha_machine_vector sable_mv;
+extern struct alpha_machine_vector sable_gamma_mv;
+extern struct alpha_machine_vector sx164_mv;
+extern struct alpha_machine_vector takara_mv;
+extern struct alpha_machine_vector xl_mv;
+extern struct alpha_machine_vector xlt_mv;
+
+
+void __init
+setup_arch(char **cmdline_p, unsigned long * memory_start_p,
+ unsigned long * memory_end_p)
+{
+ extern char _end[];
- wrmces(0x7); /* reset enable correctable error reports */
+ struct alpha_machine_vector *vec = NULL;
+ struct percpu_struct *cpu;
+ char *type_name, *var_name, *p;
- ROOT_DEV = to_kdev_t(0x0802); /* sda2 */
- command_line[COMMAND_LINE_SIZE - 1] = '\0';
+ hwrpb = (struct hwrpb_struct*)(IDENT_ADDR + INIT_HWRPB->phys_addr);
- /* Hack for Jensen... since we're restricted to 8 or 16
- * chars for boot flags depending on the boot mode,
- * we need some shorthand. This should do for
- * installation. Later we'll add other abbreviations
- * as well...
+ /*
+ * Locate the command line.
*/
+
+ /* Hack for Jensen... since we're restricted to 8 or 16 chars for
+ boot flags depending on the boot mode, we need some shorthand.
+ This should do for installation. Later we'll add other
+ abbreviations as well... */
if (strcmp(COMMAND_LINE, "INSTALL") == 0) {
strcpy(command_line, "root=/dev/fd0 load_ramdisk=1");
- strcpy(saved_command_line, command_line);
} else {
- strcpy(command_line, COMMAND_LINE);
- strcpy(saved_command_line, COMMAND_LINE);
+ strncpy(command_line, COMMAND_LINE, sizeof command_line);
+ command_line[sizeof(command_line)-1] = 0;
}
- printk("Command line: %s\n", command_line);
-
+ strcpy(saved_command_line, command_line);
*cmdline_p = command_line;
- *memory_start_p = (unsigned long) &_end;
+
+ /*
+ * Process command-line arguments.
+ */
+
+ for (p = strtok(command_line, " \t"); p ; p = strtok(NULL, " \t")) {
+#ifndef alpha_use_srm_setup
+ /* Allow a command-line option to respect the
+ SRM's configuration. */
+ if (strncmp(p, "srm_setup=", 10) == 0) {
+ alpha_use_srm_setup = (p[10] != '0');
+ continue;
+ }
+#endif
+
+ if (strncmp(p, "alpha_mv=", 9) == 0) {
+ vec = get_sysvec_byname(p+9);
+ continue;
+ }
+ }
+
+ /* Replace the command line, not that we've killed it with strtok. */
+ strcpy(command_line, saved_command_line);
+
+ /*
+ * Indentify and reconfigure for the current system.
+ */
+
+ get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
+ &type_name, &var_name);
+ if (*var_name == '0')
+ var_name = "";
+
+ if (!vec) {
+ cpu = (struct percpu_struct*)
+ ((char*)hwrpb + hwrpb->processor_offset);
+ vec = get_sysvec(hwrpb->sys_type, hwrpb->sys_variation,
+ cpu->type);
+ }
+
+#ifdef CONFIG_ALPHA_GENERIC
+ if (!vec) {
+ panic("Unsupported system type: %s%s%s (%ld %ld)\n",
+ type_name, (*var_name ? " variation " : ""), var_name,
+ hwrpb->sys_type, hwrpb->sys_variation);
+ }
+ alpha_mv = *vec;
+
+ /* Assume that we've booted from SRM if we havn't booted from MILO.
+ Detect the later by looking for "MILO" in the system serial nr. */
+ alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
+#else
+ /* Once we're sure we can reliably identify systems, we should
+ simply panic as we do above. */
+ if (vec != &alpha_mv) {
+ printk("WARNING: Not configured for system type: %s%s%s "
+ "(%ld %ld)\nContinuing with trepidation...\n",
+ type_name, (*var_name ? " variation " : ""), var_name,
+ hwrpb->sys_type, hwrpb->sys_variation);
+ }
+#endif
+
+ /*
+ * Sync with the HAE
+ */
+
+ /* Save the SRM's current value for restoration. */
+ srm_hae = *alpha_mv.hae_register;
+ __set_hae(alpha_mv.hae_cache);
+
+ /* Reset enable correctable error reports. */
+ wrmces(0x7);
+
+ /* Find our memory. */
*memory_end_p = find_end_memory();
+ *memory_start_p = (unsigned long) _end;
+
+ /* Initialize the machine. Usually has to do with setting up
+ DMA windows and the like. */
+ if (alpha_mv.init_arch)
+ alpha_mv.init_arch(memory_start_p, memory_end_p);
-#if defined(CONFIG_ALPHA_LCA)
- *memory_start_p = lca_init(*memory_start_p, *memory_end_p);
-#elif defined(CONFIG_ALPHA_APECS)
- *memory_start_p = apecs_init(*memory_start_p, *memory_end_p);
-#elif defined(CONFIG_ALPHA_CIA)
- *memory_start_p = cia_init(*memory_start_p, *memory_end_p);
-#elif defined(CONFIG_ALPHA_PYXIS)
- *memory_start_p = pyxis_init(*memory_start_p, *memory_end_p);
-#elif defined(CONFIG_ALPHA_T2)
- *memory_start_p = t2_init(*memory_start_p, *memory_end_p);
-#elif defined(CONFIG_ALPHA_TSUNAMI)
- *memory_start_p = tsunami_init(*memory_start_p, *memory_end_p);
-#elif defined(CONFIG_ALPHA_MCPCIA)
- *memory_start_p = mcpcia_init(*memory_start_p, *memory_end_p);
+ /* Initialize the timers. */
+ init_pit();
+
+ /* Default root filesystem to sda2. */
+ ROOT_DEV = to_kdev_t(0x0802);
+
+ /*
+ * Give us a default console. TGA users will see nothing until
+ * chr_dev_init is called, rather late in the boot sequence.
+ */
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+ conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+#endif
#endif
+ /* Delayed so that we've initialized the machine first. */
+ printk("Booting on %s%s%s using machine vector %s\n",
+ type_name, (*var_name ? " variation " : ""),
+ var_name, alpha_mv.vector_name);
+ printk("Command line: %s\n", command_line);
+
+ /*
+ * Check ASN in HWRPB for validity, report if bad.
+ * FIXME: how was this failing? Should we trust it instead,
+ * and copy the value into alpha_mv.max_asn?
+ */
+
+ if (hwrpb->max_asn != MAX_ASN) {
+ printk("Max ASN from HWRPB is bad (0x%lx)\n", hwrpb->max_asn);
+ }
+
+ /*
+ * Identify the flock of penguins.
+ */
+
#ifdef __SMP__
setup_smp();
#endif
}
+static unsigned long __init
+find_end_memory(void)
+{
+ int i;
+ unsigned long high = 0;
+ struct memclust_struct * cluster;
+ struct memdesc_struct * memdesc;
-#define N(a) (sizeof(a)/sizeof(a[0]))
+ memdesc = (struct memdesc_struct *)
+ (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB);
+ cluster = memdesc->cluster;
-/* A change was made to the HWRPB via an ECO and the following code tracks
- * a part of the ECO. The HWRPB version must be 5 or higher or the ECO
- * was not implemented in the console firmware. If its at rev 5 or greater
- * we can get the platform ascii string name from the HWRPB. Thats what this
- * function does. It checks the rev level and if the string is in the HWRPB
- * it returns the addtess of the string ... a pointer to the platform name.
- *
- * Returns:
- * - Pointer to a ascii string if its in the HWRPB
- * - Pointer to a blank string if the data is not in the HWRPB.
- */
-static char *
-platform_string(void)
-{
- struct dsr_struct *dsr;
- static char unk_system_string[] = "N/A";
+ for (i = memdesc->numclusters ; i > 0; i--, cluster++) {
+ unsigned long tmp;
+ tmp = (cluster->start_pfn + cluster->numpages) << PAGE_SHIFT;
+ if (tmp > high)
+ high = tmp;
+ }
- /* Go to the console for the string pointer.
- * If the rpb_vers is not 5 or greater the rpb
- * is old and does not have this data in it.
- */
- if (hwrpb->revision < 5)
- return (unk_system_string);
- else {
- /* The Dynamic System Recognition struct
- * has the system platform name starting
- * after the character count of the string.
- */
- dsr = ((struct dsr_struct *)
- ((char *)hwrpb + hwrpb->dsr_offset));
- return ((char *)dsr + (dsr->sysname_off +
- sizeof(long)));
- }
+ /* Round it up to an even number of pages. */
+ high = (high + PAGE_SIZE) & (PAGE_MASK*2);
+ return PAGE_OFFSET + high;
}
-static void
-get_sysnames(long type, long variation,
- char **type_name, char **variation_name)
+
+static char sys_unknown[] = "Unknown";
+static char systype_names[][16] = {
+ "0",
+ "ADU", "Cobra", "Ruby", "Flamingo", "Mannequin", "Jensen",
+ "Pelican", "Morgan", "Sable", "Medulla", "Noname",
+ "Turbolaser", "Avanti", "Mustang", "Alcor", "Tradewind",
+ "Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1",
+ "Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake",
+ "Cortex", "29", "Miata", "XXM", "Takara", "Yukon",
+ "Tsunami", "Wildfire", "CUSCO"
+};
+
+static char unofficial_names[][8] = {"100", "Ruffian"};
+
+static char eb164_names[][8] = {"EB164", "PC164", "LX164", "SX164"};
+static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3};
+
+static char alcor_names[][16] = {"Alcor", "Maverick", "Bret"};
+static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2};
+
+static char eb64p_names[][16] = {"EB64+", "Cabriolet", "AlphaPCI64"};
+static int eb64p_indices[] = {0,0,1,2};
+
+static char eb66_names[][8] = {"EB66", "EB66+"};
+static int eb66_indices[] = {0,0,1};
+
+static char rawhide_names[][16] = {
+ "Dodge", "Wrangler", "Durango", "Tincup", "DaVinci"
+};
+static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
+
+
+static struct alpha_machine_vector * __init
+get_sysvec(long type, long variation, long cpu)
{
- static char *sys_unknown = "Unknown";
- static char *systype_names[] = {
- "0",
- "ADU", "Cobra", "Ruby", "Flamingo", "Mannequin", "Jensen",
- "Pelican", "Morgan", "Sable", "Medulla", "Noname",
- "Turbolaser", "Avanti", "Mustang", "Alcor", "Tradewind",
- "Mikasa", "EB64", "EB66", "EB64+", "AlphaBook1",
- "Rawhide", "K2", "Lynx", "XL", "EB164", "Noritake",
- "Cortex", "29", "Miata", "XXM", "Takara", "Yukon",
- "Tsunami", "Wildfire", "CUSCO"
+#ifdef CONFIG_ALPHA_GENERIC
+ static struct alpha_machine_vector *systype_vecs[] __initlocaldata =
+ {
+ NULL, /* 0 */
+ NULL, /* ADU */
+ NULL, /* Cobra */
+ NULL, /* Ruby */
+ NULL, /* Flamingo */
+ NULL, /* Mannequin */
+ &jensen_mv,
+ NULL, /* Pelican */
+ NULL, /* Morgan */
+ NULL, /* Sable -- see below. */
+ NULL, /* Medulla */
+ &noname_mv,
+ NULL, /* Turbolaser */
+ &avanti_mv,
+ NULL, /* Mustang */
+ &alcor_mv, /* Alcor, Bret, Maverick. */
+ NULL, /* Tradewind */
+ NULL, /* Mikasa -- see below. */
+ NULL, /* EB64 */
+ NULL, /* EB66 -- see variation. */
+ NULL, /* EB64+ -- see variation. */
+ &alphabook1_mv,
+ &rawhide_mv,
+ NULL, /* K2 */
+ NULL, /* Lynx */
+ &xl_mv,
+ NULL, /* EB164 -- see variation. */
+ NULL, /* Noritake -- see below. */
+ NULL, /* Cortex */
+ NULL, /* 29 */
+ &miata_mv,
+ NULL, /* XXM */
+ &takara_mv,
+ NULL, /* Yukon */
+ &dp264_mv,
+ NULL, /* Wildfire */
+ NULL, /* CUSCO */
+ };
+
+ static struct alpha_machine_vector *unofficial_vecs[] __initlocaldata =
+ {
+ NULL, /* 100 */
+ &ruffian_mv,
+ };
+
+ static struct alpha_machine_vector *alcor_vecs[] __initlocaldata =
+ {
+ &alcor_mv, &xlt_mv, &xlt_mv
};
- static char *unofficial_names[] = {"100", "Ruffian"};
+ static struct alpha_machine_vector *eb164_vecs[] __initlocaldata =
+ {
+ &eb164_mv, &pc164_mv, &lx164_mv, &sx164_mv
+ };
+
+ static struct alpha_machine_vector *eb64p_vecs[] __initlocaldata =
+ {
+ &eb64p_mv,
+ &cabriolet_mv,
+ NULL /* AlphaPCI64 */
+ };
- static char * eb164_names[] = {"EB164", "PC164", "LX164", "SX164"};
- static int eb164_indices[] = {0,0,0,1,1,1,1,1,2,2,2,2,3,3,3,3};
+ static struct alpha_machine_vector *eb66_vecs[] __initlocaldata =
+ {
+ &eb66_mv,
+ &eb66p_mv
+ };
- static char * alcor_names[] = {"Alcor", "Maverick", "Bret"};
- static int alcor_indices[] = {0,0,0,1,1,1,0,0,0,0,0,0,2,2,2,2,2,2};
+ /* ??? Do we need to distinguish between Rawhides? */
- static char * eb64p_names[] = {"EB64+", "Cabriolet", "AlphaPCI64"};
- static int eb64p_indices[] = {0,0,1.2};
+ struct alpha_machine_vector *vec;
- static char * eb66_names[] = {"EB66", "EB66+"};
- static int eb66_indices[] = {0,0,1};
+ /* Restore real CABRIO and EB66+ family names, ie EB64+ and EB66 */
+ if (type < 0)
+ type = -type;
- static char * rawhide_names[] = {"Dodge", "Wrangler", "Durango",
- "Tincup", "DaVinci"};
- static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
+ /* Search the system tables first... */
+ vec = NULL;
+ if (type < N(systype_vecs)) {
+ vec = systype_vecs[type];
+ } else if ((type > ST_UNOFFICIAL_BIAS) &&
+ (type - ST_UNOFFICIAL_BIAS) < N(unofficial_vecs)) {
+ vec = unofficial_vecs[type - ST_UNOFFICIAL_BIAS];
+ }
+
+ /* If we've not found one, try for a variation. */
+
+ if (!vec) {
+ /* Member ID is a bit-field. */
+ long member = (variation >> 10) & 0x3f;
+
+ switch (type) {
+ case ST_DEC_ALCOR:
+ if (member < N(alcor_indices))
+ vec = alcor_vecs[alcor_indices[member]];
+ break;
+ case ST_DEC_EB164:
+ if (member < N(eb164_indices))
+ vec = eb164_vecs[eb164_indices[member]];
+ break;
+ case ST_DEC_EB64P:
+ if (member < N(eb64p_indices))
+ vec = eb64p_vecs[eb64p_indices[member]];
+ break;
+ case ST_DEC_EB66:
+ if (member < N(eb66_indices))
+ vec = eb66_vecs[eb66_indices[member]];
+ break;
+ case ST_DEC_1000:
+ if (cpu == EV5_CPU)
+ vec = &mikasa_primo_mv;
+ else
+ vec = &mikasa_mv;
+ break;
+ case ST_DEC_NORITAKE:
+ if (cpu == EV5_CPU)
+ vec = &noritake_primo_mv;
+ else
+ vec = &noritake_mv;
+ break;
+ case ST_DEC_2100_A500:
+ if (cpu == EV5_CPU)
+ vec = &sable_gamma_mv;
+ else
+ vec = &sable_mv;
+ break;
+ }
+ }
+ return vec;
+#else
+ /* TODO: verify that the system is of the type for which we
+ were configured. For now, cop out and return success. */
+ return &alpha_mv;
+#endif /* GENERIC */
+}
+static struct alpha_machine_vector * __init
+get_sysvec_byname(const char *name)
+{
+#ifdef CONFIG_ALPHA_GENERIC
+ static struct alpha_machine_vector *all_vecs[] __initlocaldata =
+ {
+ &alcor_mv,
+ &alphabook1_mv,
+ &avanti_mv,
+ &cabriolet_mv,
+ &dp264_mv,
+ &eb164_mv,
+ &eb64p_mv,
+ &eb66_mv,
+ &eb66p_mv,
+ &jensen_mv,
+ &lx164_mv,
+ &miata_mv,
+ &mikasa_mv,
+ &mikasa_primo_mv,
+ &noname_mv,
+ &noritake_mv,
+ &noritake_primo_mv,
+ &p2k_mv,
+ &pc164_mv,
+ &rawhide_mv,
+ &ruffian_mv,
+ &sable_mv,
+ &sable_gamma_mv,
+ &sx164_mv,
+ &takara_mv,
+ &xl_mv,
+ &xlt_mv
+ };
+
+ int i, n = sizeof(all_vecs)/sizeof(*all_vecs);
+ for (i = 0; i < n; ++i) {
+ struct alpha_machine_vector *mv = all_vecs[i];
+ if (strcasecmp(mv->vector_name, name) == 0)
+ return mv;
+ }
+ return NULL;
+#else
+ if (strcasecmp(alpha_mv.vector_name, name) == 0)
+ return &alpha_mv;
+ return NULL;
+#endif
+}
+
+static void
+get_sysnames(long type, long variation,
+ char **type_name, char **variation_name)
+{
long member;
/* Restore real CABRIO and EB66+ family names, ie EB64+ and EB66 */
@@ -343,9 +642,47 @@ get_sysnames(long type, long variation,
break;
case ST_DEC_RAWHIDE:
if (member < N(rawhide_indices))
- *variation_name = rawhide_names[rawhide_indices[member]];
+ *variation_name = rawhide_names[rawhide_indices[member]];
break;
- } /* end family switch */
+ }
+}
+
+/*
+ * A change was made to the HWRPB via an ECO and the following code
+ * tracks a part of the ECO. In HWRPB versions less than 5, the ECO
+ * was not implemented in the console firmware. If it's revision 5 or
+ * greater we can get the name of the platform as an ASCII string from
+ * the HWRPB. That's what this function does. It checks the revision
+ * level and if the string is in the HWRPB it returns the address of
+ * the string--a pointer to the name of the platform.
+ *
+ * Returns:
+ * - Pointer to a ASCII string if it's in the HWRPB
+ * - Pointer to a blank string if the data is not in the HWRPB.
+ */
+
+static char *
+platform_string(void)
+{
+ struct dsr_struct *dsr;
+ static char unk_system_string[] = "N/A";
+
+ /* Go to the console for the string pointer.
+ * If the rpb_vers is not 5 or greater the rpb
+ * is old and does not have this data in it.
+ */
+ if (hwrpb->revision < 5)
+ return (unk_system_string);
+ else {
+ /* The Dynamic System Recognition struct
+ * has the system platform name starting
+ * after the character count of the string.
+ */
+ dsr = ((struct dsr_struct *)
+ ((char *)hwrpb + hwrpb->dsr_offset));
+ return ((char *)dsr + (dsr->sysname_off +
+ sizeof(long)));
+ }
}
/*
@@ -353,20 +690,21 @@ get_sysnames(long type, long variation,
*/
int get_cpuinfo(char *buffer)
{
- static char *cpu_names[] = {
- "EV3", "EV4", "Unknown", "LCA4", "EV5", "EV45", "EV56",
- "EV6", "PCA56", "PCA57"
- };
-
extern struct unaligned_stat {
unsigned long count, va, pc;
} unaligned[2];
+ static char cpu_names[][8] = {
+ "EV3", "EV4", "Unknown", "LCA4", "EV5", "EV45", "EV56",
+ "EV6", "PCA56", "PCA57"
+ };
+
struct percpu_struct *cpu;
unsigned int cpu_index;
char *cpu_name;
char *systype_name;
char *sysvariation_name;
+ int len;
cpu = (struct percpu_struct*)((char*)hwrpb + hwrpb->processor_offset);
cpu_index = (unsigned) (cpu->type - 1);
@@ -377,30 +715,25 @@ int get_cpuinfo(char *buffer)
get_sysnames(hwrpb->sys_type, hwrpb->sys_variation,
&systype_name, &sysvariation_name);
- return sprintf(buffer,
- "cpu\t\t\t: Alpha\n"
- "cpu model\t\t: %s\n"
- "cpu variation\t\t: %ld\n"
- "cpu revision\t\t: %ld\n"
- "cpu serial number\t: %s\n"
- "system type\t\t: %s\n"
- "system variation\t: %s\n"
- "system revision\t\t: %ld\n"
- "system serial number\t: %s\n"
- "cycle frequency [Hz]\t: %lu\n"
- "timer frequency [Hz]\t: %lu.%02lu\n"
- "page size [bytes]\t: %ld\n"
- "phys. address bits\t: %ld\n"
- "max. addr. space #\t: %ld\n"
- "BogoMIPS\t\t: %lu.%02lu\n"
- "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
- "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
- "platform string\t\t: %s\n"
-#ifdef __SMP__
- "%s"
-#endif
- ,
-
+ len = sprintf(buffer,
+ "cpu\t\t\t: Alpha\n"
+ "cpu model\t\t: %s\n"
+ "cpu variation\t\t: %ld\n"
+ "cpu revision\t\t: %ld\n"
+ "cpu serial number\t: %s\n"
+ "system type\t\t: %s\n"
+ "system variation\t: %s\n"
+ "system revision\t\t: %ld\n"
+ "system serial number\t: %s\n"
+ "cycle frequency [Hz]\t: %lu\n"
+ "timer frequency [Hz]\t: %lu.%02lu\n"
+ "page size [bytes]\t: %ld\n"
+ "phys. address bits\t: %ld\n"
+ "max. addr. space #\t: %ld\n"
+ "BogoMIPS\t\t: %lu.%02lu\n"
+ "kernel unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
+ "user unaligned acc\t: %ld (pc=%lx,va=%lx)\n"
+ "platform string\t\t: %s\n",
cpu_name, cpu->variation, cpu->revision,
(char*)cpu->serial_no,
systype_name, sysvariation_name, hwrpb->sys_revision,
@@ -414,9 +747,11 @@ int get_cpuinfo(char *buffer)
loops_per_sec / 500000, (loops_per_sec / 5000) % 100,
unaligned[0].count, unaligned[0].pc, unaligned[0].va,
unaligned[1].count, unaligned[1].pc, unaligned[1].va,
- platform_string()
+ platform_string());
+
#ifdef __SMP__
- , smp_info()
+ return len + smp_info(buffer+len);
+#else
+ return len;
#endif
- );
}
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 1943b26f7..22f8742e1 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -203,6 +203,12 @@ do_rt_sigsuspend(sigset_t *uset, size_t sigsetsize,
}
}
+asmlinkage int
+sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+ return do_sigaltstack(uss, uoss, rdusp());
+}
+
/*
* Do a signal return; undo the signal stack.
*/
@@ -225,67 +231,65 @@ struct rt_sigframe
#define INSN_LDI_R0 0x201f0000
#define INSN_CALLSYS 0x00000083
-
-static void
+static long
restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
struct switch_stack *sw)
{
unsigned long usp;
- int i;
+ long i, err = 0;
- __get_user(regs->pc, &sc->sc_pc);
+ err |= __get_user(regs->pc, &sc->sc_pc);
sw->r26 = (unsigned long) ret_from_sys_call;
- __get_user(regs->r0, sc->sc_regs+0);
- __get_user(regs->r1, sc->sc_regs+1);
- __get_user(regs->r2, sc->sc_regs+2);
- __get_user(regs->r3, sc->sc_regs+3);
- __get_user(regs->r4, sc->sc_regs+4);
- __get_user(regs->r5, sc->sc_regs+5);
- __get_user(regs->r6, sc->sc_regs+6);
- __get_user(regs->r7, sc->sc_regs+7);
- __get_user(regs->r8, sc->sc_regs+8);
- __get_user(sw->r9, sc->sc_regs+9);
- __get_user(sw->r10, sc->sc_regs+10);
- __get_user(sw->r11, sc->sc_regs+11);
- __get_user(sw->r12, sc->sc_regs+12);
- __get_user(sw->r13, sc->sc_regs+13);
- __get_user(sw->r14, sc->sc_regs+14);
- __get_user(sw->r15, sc->sc_regs+15);
- __get_user(regs->r16, sc->sc_regs+16);
- __get_user(regs->r17, sc->sc_regs+17);
- __get_user(regs->r18, sc->sc_regs+18);
- __get_user(regs->r19, sc->sc_regs+19);
- __get_user(regs->r20, sc->sc_regs+20);
- __get_user(regs->r21, sc->sc_regs+21);
- __get_user(regs->r22, sc->sc_regs+22);
- __get_user(regs->r23, sc->sc_regs+23);
- __get_user(regs->r24, sc->sc_regs+24);
- __get_user(regs->r25, sc->sc_regs+25);
- __get_user(regs->r26, sc->sc_regs+26);
- __get_user(regs->r27, sc->sc_regs+27);
- __get_user(regs->r28, sc->sc_regs+28);
- __get_user(regs->gp, sc->sc_regs+29);
- __get_user(usp, sc->sc_regs+30);
+ err |= __get_user(regs->r0, sc->sc_regs+0);
+ err |= __get_user(regs->r1, sc->sc_regs+1);
+ err |= __get_user(regs->r2, sc->sc_regs+2);
+ err |= __get_user(regs->r3, sc->sc_regs+3);
+ err |= __get_user(regs->r4, sc->sc_regs+4);
+ err |= __get_user(regs->r5, sc->sc_regs+5);
+ err |= __get_user(regs->r6, sc->sc_regs+6);
+ err |= __get_user(regs->r7, sc->sc_regs+7);
+ err |= __get_user(regs->r8, sc->sc_regs+8);
+ err |= __get_user(sw->r9, sc->sc_regs+9);
+ err |= __get_user(sw->r10, sc->sc_regs+10);
+ err |= __get_user(sw->r11, sc->sc_regs+11);
+ err |= __get_user(sw->r12, sc->sc_regs+12);
+ err |= __get_user(sw->r13, sc->sc_regs+13);
+ err |= __get_user(sw->r14, sc->sc_regs+14);
+ err |= __get_user(sw->r15, sc->sc_regs+15);
+ err |= __get_user(regs->r16, sc->sc_regs+16);
+ err |= __get_user(regs->r17, sc->sc_regs+17);
+ err |= __get_user(regs->r18, sc->sc_regs+18);
+ err |= __get_user(regs->r19, sc->sc_regs+19);
+ err |= __get_user(regs->r20, sc->sc_regs+20);
+ err |= __get_user(regs->r21, sc->sc_regs+21);
+ err |= __get_user(regs->r22, sc->sc_regs+22);
+ err |= __get_user(regs->r23, sc->sc_regs+23);
+ err |= __get_user(regs->r24, sc->sc_regs+24);
+ err |= __get_user(regs->r25, sc->sc_regs+25);
+ err |= __get_user(regs->r26, sc->sc_regs+26);
+ err |= __get_user(regs->r27, sc->sc_regs+27);
+ err |= __get_user(regs->r28, sc->sc_regs+28);
+ err |= __get_user(regs->gp, sc->sc_regs+29);
+ err |= __get_user(usp, sc->sc_regs+30);
wrusp(usp);
for (i = 0; i < 31; i++)
- __get_user(sw->fp[i], sc->sc_fpregs+i);
- __get_user(sw->fp[31], &sc->sc_fpcr);
+ err |= __get_user(sw->fp[i], sc->sc_fpregs+i);
+ err |= __get_user(sw->fp[31], &sc->sc_fpcr);
+
+ return err;
}
asmlinkage void
do_sigreturn(struct sigframe *frame, struct pt_regs *regs,
struct switch_stack *sw)
{
- unsigned long ps;
sigset_t set;
/* Verify that it's a good sigcontext before using it */
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto give_sigsegv;
- if (__get_user(ps, &frame->sc.sc_ps) || ps != 8)
- goto give_sigsegv;
if (__get_user(set.sig[0], &frame->sc.sc_mask)
|| (_NSIG_WORDS > 1
&& __copy_from_user(&set.sig[1], &frame->extramask,
@@ -298,7 +302,8 @@ do_sigreturn(struct sigframe *frame, struct pt_regs *regs,
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
- restore_sigcontext(&frame->sc, regs, sw);
+ if (restore_sigcontext(&frame->sc, regs, sw))
+ goto give_sigsegv;
/* Send SIGTRAP if we're single-stepping: */
if (ptrace_cancel_bpt (current))
@@ -306,22 +311,19 @@ do_sigreturn(struct sigframe *frame, struct pt_regs *regs,
return;
give_sigsegv:
- lock_kernel();
- do_exit(SIGSEGV);
+ force_sig(SIGSEGV, current);
}
asmlinkage void
do_rt_sigreturn(struct rt_sigframe *frame, struct pt_regs *regs,
struct switch_stack *sw)
{
- unsigned long ps;
sigset_t set;
+ stack_t st;
/* Verify that it's a good sigcontext before using it */
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto give_sigsegv;
- if (__get_user(ps, &frame->uc.uc_mcontext.sc_ps) || ps != 8)
- goto give_sigsegv;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto give_sigsegv;
@@ -331,7 +333,14 @@ do_rt_sigreturn(struct rt_sigframe *frame, struct pt_regs *regs,
recalc_sigpending(current);
spin_unlock_irq(&current->sigmask_lock);
- restore_sigcontext(&frame->uc.uc_mcontext, regs, sw);
+ if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
+ goto give_sigsegv;
+
+ if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+ goto give_sigsegv;
+ /* It is more difficult to avoid calling this function than to
+ call it and ignore errors. */
+ do_sigaltstack(&st, NULL, rdusp());
/* Send SIGTRAP if we're single-stepping: */
if (ptrace_cancel_bpt (current))
@@ -339,8 +348,7 @@ do_rt_sigreturn(struct rt_sigframe *frame, struct pt_regs *regs,
return;
give_sigsegv:
- lock_kernel();
- do_exit(SIGSEGV);
+ force_sig(SIGSEGV, current);
}
@@ -348,99 +356,113 @@ give_sigsegv:
* Set up a signal frame.
*/
-static void
+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 - frame_size) & -32ul);
+}
+
+static long
setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
struct switch_stack *sw, unsigned long mask, unsigned long sp)
{
- long i;
-
- __put_user(0, &sc->sc_onstack);
- __put_user(mask, &sc->sc_mask);
- __put_user(regs->pc, &sc->sc_pc);
- __put_user(8, &sc->sc_ps);
-
- __put_user(regs->r0 , sc->sc_regs+0);
- __put_user(regs->r1 , sc->sc_regs+1);
- __put_user(regs->r2 , sc->sc_regs+2);
- __put_user(regs->r3 , sc->sc_regs+3);
- __put_user(regs->r4 , sc->sc_regs+4);
- __put_user(regs->r5 , sc->sc_regs+5);
- __put_user(regs->r6 , sc->sc_regs+6);
- __put_user(regs->r7 , sc->sc_regs+7);
- __put_user(regs->r8 , sc->sc_regs+8);
- __put_user(sw->r9 , sc->sc_regs+9);
- __put_user(sw->r10 , sc->sc_regs+10);
- __put_user(sw->r11 , sc->sc_regs+11);
- __put_user(sw->r12 , sc->sc_regs+12);
- __put_user(sw->r13 , sc->sc_regs+13);
- __put_user(sw->r14 , sc->sc_regs+14);
- __put_user(sw->r15 , sc->sc_regs+15);
- __put_user(regs->r16, sc->sc_regs+16);
- __put_user(regs->r17, sc->sc_regs+17);
- __put_user(regs->r18, sc->sc_regs+18);
- __put_user(regs->r19, sc->sc_regs+19);
- __put_user(regs->r20, sc->sc_regs+20);
- __put_user(regs->r21, sc->sc_regs+21);
- __put_user(regs->r22, sc->sc_regs+22);
- __put_user(regs->r23, sc->sc_regs+23);
- __put_user(regs->r24, sc->sc_regs+24);
- __put_user(regs->r25, sc->sc_regs+25);
- __put_user(regs->r26, sc->sc_regs+26);
- __put_user(regs->r27, sc->sc_regs+27);
- __put_user(regs->r28, sc->sc_regs+28);
- __put_user(regs->gp , sc->sc_regs+29);
- __put_user(sp, sc->sc_regs+30);
- __put_user(0, sc->sc_regs+31);
+ long i, err = 0;
+
+ err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack);
+ err |= __put_user(mask, &sc->sc_mask);
+ err |= __put_user(regs->pc, &sc->sc_pc);
+ err |= __put_user(8, &sc->sc_ps);
+
+ err |= __put_user(regs->r0 , sc->sc_regs+0);
+ err |= __put_user(regs->r1 , sc->sc_regs+1);
+ err |= __put_user(regs->r2 , sc->sc_regs+2);
+ err |= __put_user(regs->r3 , sc->sc_regs+3);
+ err |= __put_user(regs->r4 , sc->sc_regs+4);
+ err |= __put_user(regs->r5 , sc->sc_regs+5);
+ err |= __put_user(regs->r6 , sc->sc_regs+6);
+ err |= __put_user(regs->r7 , sc->sc_regs+7);
+ err |= __put_user(regs->r8 , sc->sc_regs+8);
+ err |= __put_user(sw->r9 , sc->sc_regs+9);
+ err |= __put_user(sw->r10 , sc->sc_regs+10);
+ err |= __put_user(sw->r11 , sc->sc_regs+11);
+ err |= __put_user(sw->r12 , sc->sc_regs+12);
+ err |= __put_user(sw->r13 , sc->sc_regs+13);
+ err |= __put_user(sw->r14 , sc->sc_regs+14);
+ err |= __put_user(sw->r15 , sc->sc_regs+15);
+ err |= __put_user(regs->r16, sc->sc_regs+16);
+ err |= __put_user(regs->r17, sc->sc_regs+17);
+ err |= __put_user(regs->r18, sc->sc_regs+18);
+ err |= __put_user(regs->r19, sc->sc_regs+19);
+ err |= __put_user(regs->r20, sc->sc_regs+20);
+ err |= __put_user(regs->r21, sc->sc_regs+21);
+ err |= __put_user(regs->r22, sc->sc_regs+22);
+ err |= __put_user(regs->r23, sc->sc_regs+23);
+ err |= __put_user(regs->r24, sc->sc_regs+24);
+ err |= __put_user(regs->r25, sc->sc_regs+25);
+ err |= __put_user(regs->r26, sc->sc_regs+26);
+ err |= __put_user(regs->r27, sc->sc_regs+27);
+ err |= __put_user(regs->r28, sc->sc_regs+28);
+ err |= __put_user(regs->gp , sc->sc_regs+29);
+ err |= __put_user(sp, sc->sc_regs+30);
+ err |= __put_user(0, sc->sc_regs+31);
for (i = 0; i < 31; i++)
- __put_user(sw->fp[i], sc->sc_fpregs+i);
- __put_user(0, sc->sc_fpregs+31);
- __put_user(sw->fp[31], &sc->sc_fpcr);
+ err |= __put_user(sw->fp[i], sc->sc_fpregs+i);
+ err |= __put_user(0, sc->sc_fpregs+31);
+ err |= __put_user(sw->fp[31], &sc->sc_fpcr);
+
+ err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0);
+ err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1);
+ err |= __put_user(regs->trap_a2, &sc->sc_traparg_a2);
- __put_user(regs->trap_a0, &sc->sc_traparg_a0);
- __put_user(regs->trap_a1, &sc->sc_traparg_a1);
- __put_user(regs->trap_a2, &sc->sc_traparg_a2);
+ return err;
}
static void
setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
struct pt_regs *regs, struct switch_stack * sw)
{
- unsigned long oldsp;
+ unsigned long oldsp, r26, err = 0;
struct sigframe *frame;
oldsp = rdusp();
- frame = (struct sigframe *)((oldsp - sizeof(*frame)) & -32);
-
- /* XXX: Check here if we would need to switch stacks.. */
+ frame = get_sigframe(ka, oldsp, sizeof(*frame));
if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
- setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
+ err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
if (_NSIG_WORDS > 1) {
- __copy_to_user(frame->extramask, &set->sig[1],
- sizeof(frame->extramask));
+ err |= __copy_to_user(frame->extramask, &set->sig[1],
+ sizeof(frame->extramask));
}
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->ka_restorer) {
- regs->r26 = (unsigned long) ka->ka_restorer;
+ r26 = (unsigned long) ka->ka_restorer;
} else {
- __put_user(INSN_MOV_R30_R16, frame->retcode+0);
- __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
- __put_user(INSN_CALLSYS, frame->retcode+2);
+ err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
+ err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
+ err |= __put_user(INSN_CALLSYS, frame->retcode+2);
imb();
- regs->r26 = (unsigned long) frame->retcode;
+ r26 = (unsigned long) frame->retcode;
}
+ /* Check that everything was written properly. */
+ if (err)
+ goto give_sigsegv;
+
/* "Return" to the handler */
+ regs->r26 = r26;
regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
regs->r16 = sig; /* a0: signal number */
regs->r17 = 0; /* a1: exception code */
regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */
wrusp((unsigned long) frame);
-
+
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
current->comm, current->pid, frame, regs->pc, regs->r26);
@@ -449,47 +471,54 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
return;
give_sigsegv:
- lock_kernel();
- do_exit(SIGSEGV);
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
}
static void
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs, struct switch_stack * sw)
{
- unsigned long oldsp;
+ unsigned long oldsp, r26, err = 0;
struct rt_sigframe *frame;
oldsp = rdusp();
- frame = (struct rt_sigframe *)((oldsp - sizeof(*frame)) & -32);
-
- /* XXX: Check here if we would need to switch stacks.. */
+ frame = get_sigframe(ka, oldsp, sizeof(*frame));
if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
- __copy_to_user(&frame->info, info, sizeof(siginfo_t));
-
- /* Zero all bits of the ucontext besides the sigcontext. */
- __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
+ err |= __copy_to_user(&frame->info, info, sizeof(siginfo_t));
- /* Copy in the bits we actually use. */
- __put_user(set->sig[0], &frame->uc.uc_osf_sigmask);
- setup_sigcontext(&frame->uc.uc_mcontext, regs, sw, set->sig[0], oldsp);
- __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ /* Create the ucontext. */
+ err |= __put_user(0, &frame->uc.uc_flags);
+ err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user(set->sig[0], &frame->uc.uc_osf_sigmask);
+ err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+ err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags);
+ err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw,
+ set->sig[0], oldsp);
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
if (ka->ka_restorer) {
- regs->r26 = (unsigned long) ka->ka_restorer;
+ r26 = (unsigned long) ka->ka_restorer;
} else {
- __put_user(INSN_MOV_R30_R16, frame->retcode+0);
- __put_user(INSN_LDI_R0+__NR_rt_sigreturn, frame->retcode+1);
- __put_user(INSN_CALLSYS, frame->retcode+2);
+ err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
+ err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
+ frame->retcode+1);
+ err |= __put_user(INSN_CALLSYS, frame->retcode+2);
imb();
- regs->r26 = (unsigned long) frame->retcode;
+ r26 = (unsigned long) frame->retcode;
}
+ if (err)
+ goto give_sigsegv;
+
/* "Return" to the handler */
+ regs->r26 = r26;
regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
regs->r16 = sig; /* a0: signal number */
regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
@@ -504,8 +533,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return;
give_sigsegv:
- lock_kernel();
- do_exit(SIGSEGV);
+ if (sig == SIGSEGV)
+ ka->sa.sa_handler = SIG_DFL;
+ force_sig(SIGSEGV, current);
}
diff --git a/arch/alpha/kernel/smc37c669.c b/arch/alpha/kernel/smc37c669.c
index bcc4ed212..3d7cd05f8 100644
--- a/arch/alpha/kernel/smc37c669.c
+++ b/arch/alpha/kernel/smc37c669.c
@@ -6,6 +6,7 @@
#include <linux/malloc.h>
#include <linux/mm.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <asm/hwrpb.h>
#include <asm/io.h>
@@ -1131,7 +1132,7 @@ struct DDB smc_ddb = {
0, /* is a flash update driver */
0, /* is a block device */
0, /* not seekable */
- 0, /* is an ethernet device */
+ 0, /* is an Ethernet device */
0, /* is a filesystem driver */
};
#endif
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index fed91a1c1..53175a0f1 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -1,4 +1,3 @@
-#include <linux/config.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/kernel_stat.h>
@@ -9,12 +8,12 @@
#include <linux/smp_lock.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/delay.h>
#include <asm/hwrpb.h>
#include <asm/ptrace.h>
#include <asm/atomic.h>
-#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/bitops.h>
#include <asm/pgtable.h>
@@ -25,6 +24,8 @@
#define __KERNEL_SYSCALLS__
#include <asm/unistd.h>
+#include "proto.h"
+
struct ipi_msg_flush_tb_struct ipi_msg_flush_tb;
struct cpuinfo_alpha cpu_data[NR_CPUS];
@@ -336,10 +337,8 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs)
#ifdef NOT_YET
clear_profile_irq(mid_xlate[cpu]);
-#ifdef CONFIG_PROFILE
if(!user_mode(regs))
- sparc_do_profile(regs->pc);
-#endif
+ alpha_do_profile(regs->pc);
#endif
if (!--prof_counter[cpu]) {
@@ -349,7 +348,7 @@ void smp_percpu_timer_interrupt(struct pt_regs *regs)
if (--current->counter < 0) {
current->counter = 0;
- need_resched = 1;
+ current->need_resched = 1;
}
spin_lock(&ticker_lock);
@@ -397,9 +396,8 @@ lier);
return -EINVAL;
}
-/* Only broken Intel needs this, thus it should not even be referenced
- * globally...
- */
+/* Only broken Intel needs this, thus it should not even be referenced globally.
+*/
__initfunc(void initialize_secondary(void))
{
printk("initialize_secondary: entry\n");
@@ -463,7 +461,7 @@ printk("Starting secondary cpu %d: state 0x%lx pal_flags 0x%lx\n",
#endif
return;
}
- udelay(1000);
+ mdelay(1);
}
#if 0
printk("secondary_cpu_start: SUCCESS for CPU %d!!!\n", cpuid);
@@ -490,7 +488,7 @@ send_cpu_msg(char *str, int cpuid)
printk("Processor %x not ready\n", cpuid);
return;
}
- udelay(1000);
+ mdelay(1);
}
cp1 = (char *) &cpu->ipc_buffer[1];
@@ -506,7 +504,7 @@ send_cpu_msg(char *str, int cpuid)
printk("Processor %x not ready\n", cpuid);
return;
}
- udelay(1000);
+ mdelay(1);
}
}
@@ -673,7 +671,7 @@ wrapper_local_flush_tlb_page(unsigned int this_cpu)
static int
unknown_ipi(unsigned int this_cpu)
{
- printk("unknown_ipi() on cpu %d: ", this_cpu);
+ printk("unknown_ipi() on CPU %d: ", this_cpu);
return 1;
}
@@ -739,15 +737,11 @@ send_ipi_message(long to_whom, enum ipi_message_type operation)
}
}
-static char smp_buf[256];
-
-char *smp_info(void)
+int smp_info(char *buffer)
{
- sprintf(smp_buf, "CPUs probed %d active %d map 0x%x AKP %d\n",
- smp_num_probed, smp_num_cpus, cpu_present_map,
- klock_info.akp);
-
- return smp_buf;
+ return sprintf(buffer, "CPUs probed %d active %d map 0x%x AKP %d\n",
+ smp_num_probed, smp_num_cpus, cpu_present_map,
+ klock_info.akp);
}
/* wrapper for call from panic() */
@@ -762,7 +756,7 @@ smp_message_pass(int target, int msg, unsigned long data, int wait)
send_ipi_message(CPU_STOP, cpu_present_map ^ (1 << me));
return;
barf:
- printk("Yeeee, trying to send SMP msg(%d) on cpu %d\n", msg, me);
+ printk("Yeeee, trying to send SMP msg(%d) on CPU %d\n", msg, me);
panic("Bogon SMP message pass.");
}
diff --git a/arch/alpha/kernel/sys_alcor.c b/arch/alpha/kernel/sys_alcor.c
new file mode 100644
index 000000000..9b9dd34cf
--- /dev/null
+++ b/arch/alpha/kernel/sys_alcor.c
@@ -0,0 +1,263 @@
+/*
+ * linux/arch/alpha/kernel/sys_alcor.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the ALCOR and XLT (XL-300/366/433).
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/core_cia.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+alcor_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16) {
+ /* On Alcor, at least, lines 20..30 are not connected and can
+ generate spurrious interrupts if we turn them on while IRQ
+ probing. So explicitly mask them out. */
+ mask |= 0x7ff000000000UL;
+
+ /* Note inverted sense of mask bits: */
+ *(vuip)GRU_INT_MASK = ~(mask >> 16);
+ mb();
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+alcor_ack_irq(unsigned long irq)
+{
+ if (irq < 16) {
+ /* Ack the interrupt making it the lowest priority */
+ /* First the slave .. */
+ if (irq > 7) {
+ outb(0xE0 | (irq - 8), 0xa0);
+ irq = 2;
+ }
+ /* .. then the master */
+ outb(0xE0 | irq, 0x20);
+
+ /* On ALCOR/XLT, need to dismiss interrupt via GRU. */
+ *(vuip)GRU_INT_CLEAR = 0x80000000; mb();
+ *(vuip)GRU_INT_CLEAR = 0x00000000; mb();
+ }
+}
+
+static void
+alcor_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary register of the GRU */
+ pld = (*(vuip)GRU_INT_REQ) & GRU_INT_REQ_BITS;
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 31) {
+ isa_device_interrupt(vector, regs);
+ } else {
+ handle_irq(16 + i, 16 + i, regs);
+ }
+ }
+ restore_flags(flags);
+}
+
+static void
+alcor_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm)
+ alpha_mv.device_interrupt = srm_device_interrupt;
+
+ *(vuip)GRU_INT_MASK = ~(alpha_irq_mask >> 16); mb(); /* invert */
+ *(vuip)GRU_INT_EDGE = 0U; mb(); /* all are level */
+ *(vuip)GRU_INT_HILO = 0x80000000U; mb(); /* ISA only HI */
+ *(vuip)GRU_INT_CLEAR = 0UL; mb(); /* all clear */
+
+ enable_irq(16 + 31); /* enable (E)ISA PIC cascade */
+ enable_irq(2); /* enable cascade */
+}
+
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ GRU_INT_REQ:
+ * Bit Meaning
+ * 0 Interrupt Line A from slot 2
+ * 1 Interrupt Line B from slot 2
+ * 2 Interrupt Line C from slot 2
+ * 3 Interrupt Line D from slot 2
+ * 4 Interrupt Line A from slot 1
+ * 5 Interrupt line B from slot 1
+ * 6 Interrupt Line C from slot 1
+ * 7 Interrupt Line D from slot 1
+ * 8 Interrupt Line A from slot 0
+ * 9 Interrupt Line B from slot 0
+ *10 Interrupt Line C from slot 0
+ *11 Interrupt Line D from slot 0
+ *12 Interrupt Line A from slot 4
+ *13 Interrupt Line B from slot 4
+ *14 Interrupt Line C from slot 4
+ *15 Interrupt Line D from slot 4
+ *16 Interrupt Line D from slot 3
+ *17 Interrupt Line D from slot 3
+ *18 Interrupt Line D from slot 3
+ *19 Interrupt Line D from slot 3
+ *20-30 Reserved
+ *31 EISA interrupt
+ *
+ * The device to slot mapping looks like:
+ *
+ * Slot Device
+ * 6 built-in TULIP (XLT only)
+ * 7 PCI on board slot 0
+ * 8 PCI on board slot 3
+ * 9 PCI on board slot 4
+ * 10 PCEB (PCI-EISA bridge)
+ * 11 PCI on board slot 2
+ * 12 PCI on board slot 1
+ *
+ *
+ * This two layered interrupt approach means that we allocate IRQ 16 and
+ * above for PCI interrupts. The IRQ relates to which bit the interrupt
+ * comes in on. This makes interrupt processing much easier.
+ */
+
+static int __init
+alcor_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[7][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ /* note: IDSEL 17 is XLT only */
+ {16+13, 16+13, 16+13, 16+13, 16+13}, /* IdSel 17, TULIP */
+ { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 18, slot 0 */
+ {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 19, slot 3 */
+ {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 20, slot 4 */
+ { -1, -1, -1, -1, -1}, /* IdSel 21, PCEB */
+ { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 2 */
+ { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */
+ };
+ const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static void __init
+alcor_pci_fixup(void)
+{
+ layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(alcor_map_irq, common_swizzle);
+}
+
+
+static void
+alcor_kill_arch (int mode, char *reboot_cmd)
+{
+ /* Who said DEC engineer's have no sense of humor? ;-) */
+ if (alpha_using_srm) {
+ *(vuip) GRU_RESET = 0x0000dead;
+ mb();
+ }
+
+ generic_kill_arch(mode, reboot_cmd);
+}
+
+
+/*
+ * The System Vectors
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_ALCOR)
+struct alpha_machine_vector alcor_mv __initmv = {
+ vector_name: "Alcor",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 48,
+ irq_probe_mask: ALCOR_PROBE_MASK,
+ update_irq_hw: alcor_update_irq_hw,
+ ack_irq: alcor_ack_irq,
+ device_interrupt: alcor_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: alcor_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: alcor_pci_fixup,
+ kill_arch: alcor_kill_arch,
+
+ sys: { cia: {
+ gru_int_req_bits: ALCOR_GRU_INT_REQ_BITS
+ }}
+};
+ALIAS_MV(alcor)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_XLT)
+struct alpha_machine_vector xlt_mv __initmv = {
+ vector_name: "XLT",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 48,
+ irq_probe_mask: ALCOR_PROBE_MASK,
+ update_irq_hw: alcor_update_irq_hw,
+ ack_irq: alcor_ack_irq,
+ device_interrupt: alcor_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: alcor_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: alcor_pci_fixup,
+ kill_arch: alcor_kill_arch,
+
+ sys: { cia: {
+ gru_int_req_bits: XLT_GRU_INT_REQ_BITS
+ }}
+};
+ALIAS_MV(xlt)
+#endif
diff --git a/arch/alpha/kernel/sys_cabriolet.c b/arch/alpha/kernel/sys_cabriolet.c
new file mode 100644
index 000000000..273d53c0b
--- /dev/null
+++ b/arch/alpha/kernel/sys_cabriolet.c
@@ -0,0 +1,395 @@
+/*
+ * linux/arch/alpha/kernel/sys_cabriolet.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the Cabriolet (AlphaPC64), EB66+, and EB164,
+ * PC164 and LX164.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_apecs.h>
+#include <asm/core_cia.h>
+#include <asm/core_lca.h>
+#include <asm/core_pyxis.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+cabriolet_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16)
+ outl(alpha_irq_mask >> 16, 0x804);
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1);
+ else
+ outb(mask, 0x21);
+}
+
+
+/* Under SRM console, we must use the CSERVE PALcode routine to manage
+ the interrupt mask for us. Otherwise, the kernel/HW get out of
+ sync with what the PALcode thinks it needs to deliver/ignore. */
+
+static void
+cabriolet_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmaskp)
+{
+ if (irq >= 16) {
+ if (unmaskp)
+ cserve_ena(irq - 16);
+ else
+ cserve_dis(irq - 16);
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1);
+ else
+ outb(mask, 0x21);
+}
+
+static void
+cabriolet_device_interrupt(unsigned long v, struct pt_regs *r)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary registers */
+ pld = inb(0x804) | (inb(0x805) << 8) | (inb(0x806) << 16);
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 4) {
+ isa_device_interrupt(v, r);
+ } else {
+ handle_irq(16 + i, 16 + i, r);
+ }
+ }
+ restore_flags(flags);
+}
+
+static void
+cabriolet_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm) {
+ alpha_mv.update_irq_hw = cabriolet_srm_update_irq_hw;
+ alpha_mv.device_interrupt = srm_device_interrupt;
+ }
+ else {
+ outl(alpha_irq_mask >> 16, 0x804);
+ }
+
+ enable_irq(16 + 4); /* enable SIO cascade */
+ enable_irq(2); /* enable cascade */
+}
+
+
+/*
+ * The EB66+ is very similar to the EB66 except that it does not have
+ * the on-board NCR and Tulip chips. In the code below, I have used
+ * slot number to refer to the id select line and *not* the slot
+ * number used in the EB66+ documentation. However, in the table,
+ * I've given the slot number, the id select line and the Jxx number
+ * that's printed on the board. The interrupt pins from the PCI slots
+ * are wired into 3 interrupt summary registers at 0x804, 0x805 and
+ * 0x806 ISA.
+ *
+ * In the table, -1 means don't assign an IRQ number. This is usually
+ * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
+ */
+
+static inline int __init
+eb66p_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[5][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ {16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J25 */
+ {16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J26 */
+ { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
+ {16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 9, slot 2, J27 */
+ {16+3, 16+3, 16+8, 16+12, 16+6} /* IdSel 10, slot 3, J28 */
+ };
+ const long min_idsel = 6, max_idsel = 10, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static inline void __init
+eb66p_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+ common_pci_fixup(eb66p_map_irq, common_swizzle);
+ enable_ide(0x398);
+}
+
+
+/*
+ * The AlphaPC64 is very similar to the EB66+ except that its slots
+ * are numbered differently. In the code below, I have used slot
+ * number to refer to the id select line and *not* the slot number
+ * used in the AlphaPC64 documentation. However, in the table, I've
+ * given the slot number, the id select line and the Jxx number that's
+ * printed on the board. The interrupt pins from the PCI slots are
+ * wired into 3 interrupt summary registers at 0x804, 0x805 and 0x806
+ * ISA.
+ *
+ * In the table, -1 means don't assign an IRQ number. This is usually
+ * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
+ */
+
+static inline int __init
+cabriolet_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[5][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5, slot 2, J21 */
+ { 16+0, 16+0, 16+5, 16+9, 16+13}, /* IdSel 6, slot 0, J19 */
+ { 16+1, 16+1, 16+6, 16+10, 16+14}, /* IdSel 7, slot 1, J20 */
+ { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
+ { 16+3, 16+3, 16+8, 16+12, 16+16} /* IdSel 9, slot 3, J22 */
+ };
+ const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static inline void __init
+cabriolet_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+ common_pci_fixup(cabriolet_map_irq, common_swizzle);
+ enable_ide(0x398);
+}
+
+static inline void __init
+eb164_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(cabriolet_map_irq, common_swizzle);
+ enable_ide(0x398);
+}
+
+
+/*
+ * The PC164 and LX164 have 19 PCI interrupts, four from each of the four
+ * PCI slots, the SIO, PCI/IDE, and USB.
+ *
+ * Each of the interrupts can be individually masked. This is
+ * accomplished by setting the appropriate bit in the mask register.
+ * A bit is set by writing a "1" to the desired position in the mask
+ * register and cleared by writing a "0". There are 3 mask registers
+ * located at ISA address 804h, 805h and 806h.
+ *
+ * An I/O read at ISA address 804h, 805h, 806h will return the
+ * state of the 11 PCI interrupts and not the state of the MASKED
+ * interrupts.
+ *
+ * Note: A write to I/O 804h, 805h, and 806h the mask register will be
+ * updated.
+ *
+ *
+ * ISA DATA<7:0>
+ * ISA +--------------------------------------------------------------+
+ * ADDRESS | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ * +==============================================================+
+ * 0x804 | INTB0 | USB | IDE | SIO | INTA3 |INTA2 | INTA1 | INTA0 |
+ * +--------------------------------------------------------------+
+ * 0x805 | INTD0 | INTC3 | INTC2 | INTC1 | INTC0 |INTB3 | INTB2 | INTB1 |
+ * +--------------------------------------------------------------+
+ * 0x806 | Rsrv | Rsrv | Rsrv | Rsrv | Rsrv |INTD3 | INTD2 | INTD1 |
+ * +--------------------------------------------------------------+
+ * * Rsrv = reserved bits
+ * Note: The mask register is write-only.
+ *
+ * IdSel
+ * 5 32 bit PCI option slot 2
+ * 6 64 bit PCI option slot 0
+ * 7 64 bit PCI option slot 1
+ * 8 Saturn I/O
+ * 9 32 bit PCI option slot 3
+ * 10 USB
+ * 11 IDE
+ *
+ */
+
+static inline int __init
+alphapc164_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[7][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { 16+2, 16+2, 16+9, 16+13, 16+17}, /* IdSel 5, slot 2, J20 */
+ { 16+0, 16+0, 16+7, 16+11, 16+15}, /* IdSel 6, slot 0, J29 */
+ { 16+1, 16+1, 16+8, 16+12, 16+16}, /* IdSel 7, slot 1, J26 */
+ { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
+ { 16+3, 16+3, 16+10, 16+14, 16+18}, /* IdSel 9, slot 3, J19 */
+ { 16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 10, USB */
+ { 16+5, 16+5, 16+5, 16+5, 16+5} /* IdSel 11, IDE */
+ };
+ const long min_idsel = 5, max_idsel = 11, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static inline void __init
+alphapc164_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(alphapc164_map_irq, common_swizzle);
+ SMC93x_Init();
+}
+
+/*
+ * The System Vector
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_CABRIOLET)
+struct alpha_machine_vector cabriolet_mv __initmv = {
+ vector_name: "Cabriolet",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_APECS_IO,
+ DO_APECS_BUS,
+ machine_check: apecs_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 35,
+ irq_probe_mask: _PROBE_MASK(35),
+ update_irq_hw: cabriolet_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: cabriolet_device_interrupt,
+
+ init_arch: apecs_init_arch,
+ init_irq: cabriolet_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: cabriolet_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(cabriolet)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB164)
+struct alpha_machine_vector eb164_mv __initmv = {
+ vector_name: "EB164",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 35,
+ irq_probe_mask: _PROBE_MASK(35),
+ update_irq_hw: cabriolet_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: cabriolet_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: cabriolet_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: eb164_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(eb164)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66P)
+struct alpha_machine_vector eb66p_mv __initmv = {
+ vector_name: "EB66+",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_LCA_IO,
+ DO_LCA_BUS,
+ machine_check: lca_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 35,
+ irq_probe_mask: _PROBE_MASK(35),
+ update_irq_hw: cabriolet_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: cabriolet_device_interrupt,
+
+ init_arch: lca_init_arch,
+ init_irq: cabriolet_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: eb66p_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(eb66p)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_LX164)
+struct alpha_machine_vector lx164_mv __initmv = {
+ vector_name: "LX164",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_PYXIS_IO,
+ DO_PYXIS_BUS,
+ machine_check: pyxis_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 35,
+ irq_probe_mask: _PROBE_MASK(35),
+ update_irq_hw: cabriolet_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: cabriolet_device_interrupt,
+
+ init_arch: pyxis_init_arch,
+ init_irq: cabriolet_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: alphapc164_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(lx164)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PC164)
+struct alpha_machine_vector pc164_mv __initmv = {
+ vector_name: "PC164",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 35,
+ irq_probe_mask: _PROBE_MASK(35),
+ update_irq_hw: cabriolet_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: cabriolet_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: cabriolet_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: alphapc164_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(pc164)
+#endif
+
diff --git a/arch/alpha/kernel/sys_dp264.c b/arch/alpha/kernel/sys_dp264.c
new file mode 100644
index 000000000..e110891be
--- /dev/null
+++ b/arch/alpha/kernel/sys_dp264.c
@@ -0,0 +1,231 @@
+/*
+ * linux/arch/alpha/kernel/sys_dp264.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the DP264 (EV6+TSUNAMI).
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_tsunami.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+/*
+ * HACK ALERT! only CPU#0 is used currently
+ */
+
+static void
+dp264_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16) {
+ /* Make CERTAIN none of the bogus ints get enabled */
+ *(vulp)TSUNAMI_CSR_DIM0 =
+ ~(mask) & ~0x0000000000000000UL;
+ mb();
+ /* ... and read it back to make sure it got written. */
+ *(vulp)TSUNAMI_CSR_DIM0;
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+dp264_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+
+ /* Read the interrupt summary register of TSUNAMI */
+ pld = (*(vulp)TSUNAMI_CSR_DIR0);
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 55) {
+ isa_device_interrupt(vector, regs);
+ } else { /* if not timer int */
+ handle_irq(16 + i, 16 + i, regs);
+ }
+#if 0
+ *(vulp)TSUNAMI_CSR_DIR0 = 1UL << i; mb();
+ tmp = *(vulp)TSUNAMI_CSR_DIR0;
+#endif
+ }
+ __restore_flags(flags);
+}
+
+static void
+dp264_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq, ack;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
+
+ /*
+ * The DP264 SRM console reports PCI interrupts with a vector
+ * 0x100 *higher* than one might expect, as PCI IRQ 0 (ie bit 0)
+ * shows up as IRQ 16, etc, etc. We adjust it down by 16 to have
+ * it line up with the actual bit numbers from the DIM registers,
+ * which is how we manage the interrupts/mask. Sigh...
+ */
+ if (irq >= 32)
+ ack = irq = irq - 16;
+
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
+}
+
+static void __init
+dp264_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm)
+ alpha_mv.device_interrupt = dp264_srm_device_interrupt;
+
+ /* Note invert on MASK bits. */
+ *(vulp)TSUNAMI_CSR_DIM0 = ~(alpha_irq_mask) & ~0UL; mb();
+ *(vulp)TSUNAMI_CSR_DIM0;
+
+ enable_irq(55); /* Enable CYPRESS interrupt controller (ISA). */
+ enable_irq(2);
+}
+
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ TSUNAMI_CSR_DIM0:
+ * Bit Meaning
+ * 0-17 Unused
+ *18 Interrupt SCSI B (Adaptec 7895 builtin)
+ *19 Interrupt SCSI A (Adaptec 7895 builtin)
+ *20 Interrupt Line D from slot 2 PCI0
+ *21 Interrupt Line C from slot 2 PCI0
+ *22 Interrupt Line B from slot 2 PCI0
+ *23 Interrupt Line A from slot 2 PCI0
+ *24 Interrupt Line D from slot 1 PCI0
+ *25 Interrupt Line C from slot 1 PCI0
+ *26 Interrupt Line B from slot 1 PCI0
+ *27 Interrupt Line A from slot 1 PCI0
+ *28 Interrupt Line D from slot 0 PCI0
+ *29 Interrupt Line C from slot 0 PCI0
+ *30 Interrupt Line B from slot 0 PCI0
+ *31 Interrupt Line A from slot 0 PCI0
+ *
+ *32 Interrupt Line D from slot 3 PCI1
+ *33 Interrupt Line C from slot 3 PCI1
+ *34 Interrupt Line B from slot 3 PCI1
+ *35 Interrupt Line A from slot 3 PCI1
+ *36 Interrupt Line D from slot 2 PCI1
+ *37 Interrupt Line C from slot 2 PCI1
+ *38 Interrupt Line B from slot 2 PCI1
+ *39 Interrupt Line A from slot 2 PCI1
+ *40 Interrupt Line D from slot 1 PCI1
+ *41 Interrupt Line C from slot 1 PCI1
+ *42 Interrupt Line B from slot 1 PCI1
+ *43 Interrupt Line A from slot 1 PCI1
+ *44 Interrupt Line D from slot 0 PCI1
+ *45 Interrupt Line C from slot 0 PCI1
+ *46 Interrupt Line B from slot 0 PCI1
+ *47 Interrupt Line A from slot 0 PCI1
+ *48-52 Unused
+ *53 PCI0 NMI (from Cypress)
+ *54 PCI0 SMI INT (from Cypress)
+ *55 PCI0 ISA Interrupt (from Cypress)
+ *56-60 Unused
+ *61 PCI1 Bus Error
+ *62 PCI0 Bus Error
+ *63 Reserved
+ *
+ * IdSel
+ * 5 Cypress Bridge I/O
+ * 6 SCSI Adaptec builtin
+ * 7 64 bit PCI option slot 0
+ * 8 64 bit PCI option slot 1
+ * 9 64 bit PCI option slot 2
+ *
+ */
+
+static int __init
+dp264_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[5][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { -1, -1, -1, -1, -1}, /* IdSel 5 ISA Bridge */
+ { 16+ 2, 16+ 2, 16+ 2, 16+ 2, 16+ 2}, /* IdSel 6 SCSI builtin*/
+ { 16+15, 16+15, 16+14, 16+13, 16+12}, /* IdSel 7 slot 0 */
+ { 16+11, 16+11, 16+10, 16+ 9, 16+ 8}, /* IdSel 8 slot 1 */
+ { 16+ 7, 16+ 7, 16+ 6, 16+ 5, 16+ 4} /* IdSel 9 slot 2 */
+ };
+ const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static void __init
+dp264_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(dp264_map_irq, common_swizzle);
+ SMC669_Init();
+}
+
+
+/*
+ * The System Vector
+ */
+
+struct alpha_machine_vector dp264_mv __initmv = {
+ vector_name: "DP264",
+ DO_EV6_MMU,
+ DO_DEFAULT_RTC,
+ DO_TSUNAMI_IO,
+ DO_TSUNAMI_BUS,
+ machine_check: tsunami_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 64,
+ irq_probe_mask: _PROBE_MASK(64),
+ update_irq_hw: dp264_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: dp264_device_interrupt,
+
+ init_arch: tsunami_init_arch,
+ init_irq: dp264_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: dp264_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(dp264)
diff --git a/arch/alpha/kernel/sys_eb64p.c b/arch/alpha/kernel/sys_eb64p.c
new file mode 100644
index 000000000..bffd119f3
--- /dev/null
+++ b/arch/alpha/kernel/sys_eb64p.c
@@ -0,0 +1,206 @@
+/*
+ * linux/arch/alpha/kernel/sys_eb64p.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the EB64+ and EB66.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_apecs.h>
+#include <asm/core_lca.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+eb64p_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16)
+ if (irq >= 24)
+ outb(mask >> 24, 0x27);
+ else
+ outb(mask >> 16, 0x26);
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1);
+ else
+ outb(mask, 0x21);
+}
+
+static void
+eb64p_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary registers */
+ pld = inb(0x26) | (inb(0x27) << 8);
+ /*
+ * Now, for every possible bit set, work through
+ * them and call the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+
+ if (i == 5) {
+ isa_device_interrupt(vector, regs);
+ } else {
+ handle_irq(16 + i, 16 + i, regs);
+ }
+ }
+ restore_flags(flags);
+}
+
+static void __init
+eb64p_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ outb(alpha_irq_mask >> 16, 0x26);
+ outb(alpha_irq_mask >> 24, 0x27);
+ enable_irq(16 + 5); /* enable SIO cascade */
+ enable_irq(2); /* enable cascade */
+}
+
+/*
+ * PCI Fixup configuration.
+ *
+ * There are two 8 bit external summary registers as follows:
+ *
+ * Summary @ 0x26:
+ * Bit Meaning
+ * 0 Interrupt Line A from slot 0
+ * 1 Interrupt Line A from slot 1
+ * 2 Interrupt Line B from slot 0
+ * 3 Interrupt Line B from slot 1
+ * 4 Interrupt Line C from slot 0
+ * 5 Interrupt line from the two ISA PICs
+ * 6 Tulip (slot
+ * 7 NCR SCSI
+ *
+ * Summary @ 0x27
+ * Bit Meaning
+ * 0 Interrupt Line C from slot 1
+ * 1 Interrupt Line D from slot 0
+ * 2 Interrupt Line D from slot 1
+ * 3 RAZ
+ * 4 RAZ
+ * 5 RAZ
+ * 6 RAZ
+ * 7 RAZ
+ *
+ * The device to slot mapping looks like:
+ *
+ * Slot Device
+ * 5 NCR SCSI controller
+ * 6 PCI on board slot 0
+ * 7 PCI on board slot 1
+ * 8 Intel SIO PCI-ISA bridge chip
+ * 9 Tulip - DECchip 21040 Ethernet controller
+ *
+ *
+ * This two layered interrupt approach means that we allocate IRQ 16 and
+ * above for PCI interrupts. The IRQ relates to which bit the interrupt
+ * comes in on. This makes interrupt processing much easier.
+ */
+
+static int __init
+eb64p_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[5][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ {16+7, 16+7, 16+7, 16+7, 16+7}, /* IdSel 5, slot ?, ?? */
+ {16+0, 16+0, 16+2, 16+4, 16+9}, /* IdSel 6, slot ?, ?? */
+ {16+1, 16+1, 16+3, 16+8, 16+10}, /* IdSel 7, slot ?, ?? */
+ { -1, -1, -1, -1, -1}, /* IdSel 8, SIO */
+ {16+6, 16+6, 16+6, 16+6, 16+6}, /* IdSel 9, TULIP */
+ };
+ const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static void __init
+eb64p_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+ common_pci_fixup(eb64p_map_irq, common_swizzle);
+}
+
+
+/*
+ * The System Vector
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB64P)
+struct alpha_machine_vector eb64p_mv __initmv = {
+ vector_name: "EB64+",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_APECS_IO,
+ DO_APECS_BUS,
+ machine_check: apecs_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 32,
+ irq_probe_mask: _PROBE_MASK(32),
+ update_irq_hw: eb64p_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: eb64p_device_interrupt,
+
+ init_arch: apecs_init_arch,
+ init_irq: eb64p_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: eb64p_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(eb64p)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_EB66)
+struct alpha_machine_vector eb66_mv __initmv = {
+ vector_name: "EB66",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_LCA_IO,
+ DO_LCA_BUS,
+ machine_check: lca_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 32,
+ irq_probe_mask: _PROBE_MASK(32),
+ update_irq_hw: eb64p_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: eb64p_device_interrupt,
+
+ init_arch: lca_init_arch,
+ init_irq: eb64p_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: eb64p_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(eb66)
+#endif
diff --git a/arch/alpha/kernel/sys_jensen.c b/arch/alpha/kernel/sys_jensen.c
new file mode 100644
index 000000000..8406661d7
--- /dev/null
+++ b/arch/alpha/kernel/sys_jensen.c
@@ -0,0 +1,146 @@
+/*
+ * linux/arch/alpha/kernel/sys_jensen.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the Jensen.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/io.h>
+#include <asm/jensen.h>
+#undef __EXTERN_INLINE
+
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "machvec.h"
+
+
+static void
+jensen_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 8)
+ outb(mask >> 8, 0xA1);
+ else
+ outb(mask, 0x21);
+}
+
+/*
+ * Jensen is special: the vector is 0x8X0 for EISA interrupt X, and
+ * 0x9X0 for the local motherboard interrupts..
+ *
+ * 0x660 - NMI
+ *
+ * 0x800 - IRQ0 interval timer (not used, as we use the RTC timer)
+ * 0x810 - IRQ1 line printer (duh..)
+ * 0x860 - IRQ6 floppy disk
+ * 0x8E0 - IRQ14 SCSI controller
+ *
+ * 0x900 - COM1
+ * 0x920 - COM2
+ * 0x980 - keyboard
+ * 0x990 - mouse
+ *
+ * PCI-based systems are more sane: they don't have the local
+ * interrupts at all, and have only normal PCI interrupts from
+ * devices. Happily it's easy enough to do a sane mapping from the
+ * Jensen.. Note that this means that we may have to do a hardware
+ * "ack" to a different interrupt than we report to the rest of the
+ * world.
+ */
+
+static void
+handle_nmi(struct pt_regs * regs)
+{
+ printk("Whee.. NMI received. Probable hardware error\n");
+ printk("61=%02x, 461=%02x\n", inb(0x61), inb(0x461));
+}
+
+static void
+jensen_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq, ack;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
+
+ switch (vector) {
+ case 0x660: handle_nmi(regs); return;
+
+ /* local device interrupts: */
+ case 0x900: irq = 4, ack = -1; break; /* com1 -> irq 4 */
+ case 0x920: irq = 3, ack = -1; break; /* com2 -> irq 3 */
+ case 0x980: irq = 1, ack = -1; break; /* kbd -> irq 1 */
+ case 0x990: irq = 9, ack = -1; break; /* mouse -> irq 9 */
+ default:
+ if (vector > 0x900) {
+ printk("Unknown local interrupt %lx\n", vector);
+ }
+
+ /* irq1 is supposed to be the keyboard, silly Jensen
+ (is this really needed??) */
+ if (irq == 1)
+ irq = 7;
+ break;
+ }
+
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
+}
+
+static void
+jensen_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ enable_irq(2); /* enable cascade */
+}
+
+static void
+jensen_machine_check (u64 vector, u64 la, struct pt_regs *regs)
+{
+ printk(KERN_CRIT "Machine check\n");
+}
+
+
+/*
+ * The System Vector
+ */
+
+struct alpha_machine_vector jensen_mv __initmv = {
+ vector_name: "Jensen",
+ DO_EV4_MMU,
+ IO_LITE(JENSEN,jensen,jensen),
+ BUS(jensen),
+ machine_check: jensen_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 16,
+ irq_probe_mask: _PROBE_MASK(16),
+ update_irq_hw: jensen_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: jensen_device_interrupt,
+
+ init_arch: NULL,
+ init_irq: jensen_init_irq,
+ init_pit: generic_init_pit,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(jensen)
diff --git a/arch/alpha/kernel/sys_miata.c b/arch/alpha/kernel/sys_miata.c
new file mode 100644
index 000000000..71ec1b2cc
--- /dev/null
+++ b/arch/alpha/kernel/sys_miata.c
@@ -0,0 +1,307 @@
+/*
+ * linux/arch/alpha/kernel/sys_miata.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the MIATA (EV56+PYXIS).
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_pyxis.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+miata_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16) {
+ /* Make CERTAIN none of the bogus ints get enabled... */
+ *(vulp)PYXIS_INT_MASK =
+ ~((long)mask >> 16) & ~0x4000000000000e3bUL;
+ mb();
+ /* ... and read it back to make sure it got written. */
+ *(vulp)PYXIS_INT_MASK;
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+miata_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld, tmp;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary register of PYXIS */
+ pld = *(vulp)PYXIS_INT_REQ;
+
+ /*
+ * For now, AND off any bits we are not interested in:
+ * HALT (2), timer (6), ISA Bridge (7), 21142/3 (8)
+ * then all the PCI slots/INTXs (12-31).
+ */
+ /* Maybe HALT should only be used for SRM console boots? */
+ pld &= 0x00000000fffff1c4UL;
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 7) {
+ isa_device_interrupt(vector, regs);
+ } else if (i == 6) {
+ continue;
+ } else {
+ /* if not timer int */
+ handle_irq(16 + i, 16 + i, regs);
+ }
+ *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
+ tmp = *(vulp)PYXIS_INT_REQ;
+ }
+ restore_flags(flags);
+}
+
+static void
+miata_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq, ack;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
+
+ /*
+ * I really hate to do this, but the MIATA SRM console ignores the
+ * low 8 bits in the interrupt summary register, and reports the
+ * vector 0x80 *lower* than I expected from the bit numbering in
+ * the documentation.
+ * This was done because the low 8 summary bits really aren't used
+ * for reporting any interrupts (the PCI-ISA bridge, bit 7, isn't
+ * used for this purpose, as PIC interrupts are delivered as the
+ * vectors 0x800-0x8f0).
+ * But I really don't want to change the fixup code for allocation
+ * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which look
+ * nice and clean now.
+ * So, here's this grotty hack... :-(
+ */
+ if (irq >= 16)
+ ack = irq = irq + 8;
+
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
+}
+
+static void __init
+miata_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm)
+ alpha_mv.device_interrupt = miata_srm_device_interrupt;
+
+ /* Note invert on MASK bits. */
+ *(vulp)PYXIS_INT_MASK = ~((long)alpha_irq_mask >> 16); mb();
+#if 0
+ /* These break on MiataGL so we'll try not to do it at all. */
+ *(vulp)PYXIS_INT_HILO = 0x000000B2UL; mb(); /* ISA/NMI HI */
+ *(vulp)PYXIS_RT_COUNT = 0UL; mb(); /* clear count */
+#endif
+ /* Clear upper timer. */
+ *(vulp)PYXIS_INT_REQ = 0x4000000000000000UL; mb();
+
+ enable_irq(16 + 2); /* enable HALT switch - SRM only? */
+ enable_irq(16 + 6); /* enable timer */
+ enable_irq(16 + 7); /* enable ISA PIC cascade */
+ enable_irq(2); /* enable cascade */
+}
+
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ PYXIS_INT_REQ:
+ * Bit Meaning
+ * 0 Fan Fault
+ * 1 NMI
+ * 2 Halt/Reset switch
+ * 3 none
+ * 4 CID0 (Riser ID)
+ * 5 CID1 (Riser ID)
+ * 6 Interval timer
+ * 7 PCI-ISA Bridge
+ * 8 Ethernet
+ * 9 EIDE (deprecated, ISA 14/15 used)
+ *10 none
+ *11 USB
+ *12 Interrupt Line A from slot 4
+ *13 Interrupt Line B from slot 4
+ *14 Interrupt Line C from slot 4
+ *15 Interrupt Line D from slot 4
+ *16 Interrupt Line A from slot 5
+ *17 Interrupt line B from slot 5
+ *18 Interrupt Line C from slot 5
+ *19 Interrupt Line D from slot 5
+ *20 Interrupt Line A from slot 1
+ *21 Interrupt Line B from slot 1
+ *22 Interrupt Line C from slot 1
+ *23 Interrupt Line D from slot 1
+ *24 Interrupt Line A from slot 2
+ *25 Interrupt Line B from slot 2
+ *26 Interrupt Line C from slot 2
+ *27 Interrupt Line D from slot 2
+ *27 Interrupt Line A from slot 3
+ *29 Interrupt Line B from slot 3
+ *30 Interrupt Line C from slot 3
+ *31 Interrupt Line D from slot 3
+ *
+ * The device to slot mapping looks like:
+ *
+ * Slot Device
+ * 3 DC21142 Ethernet
+ * 4 EIDE CMD646
+ * 5 none
+ * 6 USB
+ * 7 PCI-ISA bridge
+ * 8 PCI-PCI Bridge (SBU Riser)
+ * 9 none
+ * 10 none
+ * 11 PCI on board slot 4 (SBU Riser)
+ * 12 PCI on board slot 5 (SBU Riser)
+ *
+ * These are behind the bridge, so I'm not sure what to do...
+ *
+ * 13 PCI on board slot 1 (SBU Riser)
+ * 14 PCI on board slot 2 (SBU Riser)
+ * 15 PCI on board slot 3 (SBU Riser)
+ *
+ *
+ * This two layered interrupt approach means that we allocate IRQ 16 and
+ * above for PCI interrupts. The IRQ relates to which bit the interrupt
+ * comes in on. This makes interrupt processing much easier.
+ */
+
+static int __init
+miata_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[18][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ {16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8}, /* IdSel 14, DC21142 */
+ { -1, -1, -1, -1, -1}, /* IdSel 15, EIDE */
+ { -1, -1, -1, -1, -1}, /* IdSel 16, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 17, none */
+ /* {16+11, 16+11, 16+11, 16+11, 16+11},*//* IdSel 17, USB ?? */
+ { -1, -1, -1, -1, -1}, /* IdSel 18, PCI-ISA */
+ { -1, -1, -1, -1, -1}, /* IdSel 19, PCI-PCI */
+ { -1, -1, -1, -1, -1}, /* IdSel 20, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 21, none */
+ {16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 22, slot 4 */
+ {16+16, 16+16, 16+17, 16+18, 16+19}, /* IdSel 23, slot 5 */
+ /* The following are actually on bus 1, which is
+ across the builtin PCI-PCI bridge. */
+ {16+20, 16+20, 16+21, 16+22, 16+23}, /* IdSel 24, slot 1 */
+ {16+24, 16+24, 16+25, 16+26, 16+27}, /* IdSel 25, slot 2 */
+ {16+28, 16+28, 16+29, 16+30, 16+31}, /* IdSel 26, slot 3 */
+ { -1, -1, -1, -1, -1}, /* IdSel 27, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 28, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 29, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 30, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 31, PCI-PCI */
+ };
+ const long min_idsel = 3, max_idsel = 20, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static int __init
+miata_swizzle(struct pci_dev *dev, int *pinp)
+{
+ int slot, pin = *pinp;
+
+ /* Check first for the built-in bridge. */
+ if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
+ (PCI_SLOT(dev->bus->self->devfn) == 20)) {
+ slot = PCI_SLOT(dev->devfn) + 5;
+ }
+ else
+ {
+ /* Must be a card-based bridge. */
+ do {
+ if ((PCI_SLOT(dev->bus->self->devfn) == 8) ||
+ (PCI_SLOT(dev->bus->self->devfn) == 20)) {
+ slot = PCI_SLOT(dev->devfn) + 5;
+ break;
+ }
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ /* Slot of the next bridge. */
+ slot = PCI_SLOT(dev->devfn);
+ } while (dev->bus->self);
+ }
+ *pinp = pin;
+ return slot;
+}
+
+static void __init
+miata_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(miata_map_irq, miata_swizzle);
+ SMC669_Init(); /* it might be a GL (fails harmlessly if not) */
+ es1888_init();
+}
+
+
+/*
+ * The System Vector
+ */
+
+struct alpha_machine_vector miata_mv __initmv = {
+ vector_name: "Miata",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_PYXIS_IO,
+ DO_PYXIS_BUS,
+ machine_check: pyxis_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 48,
+ irq_probe_mask: _PROBE_MASK(48),
+ update_irq_hw: miata_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: miata_device_interrupt,
+
+ init_arch: pyxis_init_arch,
+ init_irq: miata_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: miata_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(miata)
diff --git a/arch/alpha/kernel/sys_mikasa.c b/arch/alpha/kernel/sys_mikasa.c
new file mode 100644
index 000000000..92af5d372
--- /dev/null
+++ b/arch/alpha/kernel/sys_mikasa.c
@@ -0,0 +1,297 @@
+/*
+ * linux/arch/alpha/kernel/sys_mikasa.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the MIKASA (AlphaServer 1000).
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_apecs.h>
+#include <asm/core_cia.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+static void
+mikasa_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16)
+ outw(~(mask >> 16), 0x536); /* note invert */
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1);
+ else
+ outb(mask, 0x21);
+}
+
+static void
+mikasa_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary registers */
+ pld = (((unsigned long) (~inw(0x534)) & 0x0000ffffUL) << 16) |
+ (((unsigned long) inb(0xa0)) << 8) |
+ ((unsigned long) inb(0x20));
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i < 16) {
+ isa_device_interrupt(vector, regs);
+ } else {
+ handle_irq(i, i, regs);
+ }
+ }
+ restore_flags(flags);
+}
+
+static void __init
+mikasa_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm)
+ alpha_mv.device_interrupt = srm_device_interrupt;
+
+ outw(~(alpha_irq_mask >> 16), 0x536); /* note invert */
+ enable_irq(2); /* enable cascade */
+}
+
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ 0x536:
+ * Bit Meaning
+ * 0 Interrupt Line A from slot 0
+ * 1 Interrupt Line B from slot 0
+ * 2 Interrupt Line C from slot 0
+ * 3 Interrupt Line D from slot 0
+ * 4 Interrupt Line A from slot 1
+ * 5 Interrupt line B from slot 1
+ * 6 Interrupt Line C from slot 1
+ * 7 Interrupt Line D from slot 1
+ * 8 Interrupt Line A from slot 2
+ * 9 Interrupt Line B from slot 2
+ *10 Interrupt Line C from slot 2
+ *11 Interrupt Line D from slot 2
+ *12 NCR 810 SCSI
+ *13 Power Supply Fail
+ *14 Temperature Warn
+ *15 Reserved
+ *
+ * The device to slot mapping looks like:
+ *
+ * Slot Device
+ * 6 NCR SCSI controller
+ * 7 Intel PCI-EISA bridge chip
+ * 11 PCI on board slot 0
+ * 12 PCI on board slot 1
+ * 13 PCI on board slot 2
+ *
+ *
+ * This two layered interrupt approach means that we allocate IRQ 16 and
+ * above for PCI interrupts. The IRQ relates to which bit the interrupt
+ * comes in on. This makes interrupt processing much easier.
+ */
+
+static int __init
+mikasa_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[8][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ {16+12, 16+12, 16+12, 16+12, 16+12}, /* IdSel 17, SCSI */
+ { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
+ { -1, -1, -1, -1, -1}, /* IdSel 19, ???? */
+ { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */
+ { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */
+ { 16+0, 16+0, 16+1, 16+2, 16+3}, /* IdSel 22, slot 0 */
+ { 16+4, 16+4, 16+5, 16+6, 16+7}, /* IdSel 23, slot 1 */
+ { 16+8, 16+8, 16+9, 16+10, 16+11}, /* IdSel 24, slot 2 */
+ };
+ const long min_idsel = 6, max_idsel = 13, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static void __init
+mikasa_pci_fixup(void)
+{
+ layout_all_busses(EISA_DEFAULT_IO_BASE,APECS_AND_LCA_DEFAULT_MEM_BASE);
+ common_pci_fixup(mikasa_map_irq, common_swizzle);
+}
+
+static void __init
+mikasa_primo_pci_fixup(void)
+{
+ layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(mikasa_map_irq, common_swizzle);
+}
+
+static void
+mikasa_machine_check(unsigned long vector, unsigned long la_ptr,
+ struct pt_regs * regs)
+{
+#define MCHK_NO_DEVSEL 0x205L
+#define MCHK_NO_TABT 0x204L
+
+ struct el_common *mchk_header;
+ struct el_apecs_procdata *mchk_procdata;
+ struct el_apecs_mikasa_sysdata_mcheck *mchk_sysdata;
+ unsigned long *ptr;
+ int i;
+
+ mchk_header = (struct el_common *)la_ptr;
+
+ mchk_procdata = (struct el_apecs_procdata *)
+ (la_ptr + mchk_header->proc_offset
+ - sizeof(mchk_procdata->paltemp));
+
+ mchk_sysdata = (struct el_apecs_mikasa_sysdata_mcheck *)
+ (la_ptr + mchk_header->sys_offset);
+
+#ifdef DEBUG
+ printk("mikasa_machine_check: vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr);
+ printk(" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+ regs->pc, mchk_header->size, mchk_header->proc_offset,
+ mchk_header->sys_offset);
+ printk("mikasa_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
+ apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
+ mchk_sysdata->epic_pear);
+ ptr = (unsigned long *)la_ptr;
+ for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+ printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
+ }
+#endif
+
+ /*
+ * Check if machine check is due to a badaddr() and if so,
+ * ignore the machine check.
+ */
+
+ if (apecs_mcheck_expected
+ && ((unsigned int)mchk_header->code == MCHK_NO_DEVSEL
+ || (unsigned int)mchk_header->code == MCHK_NO_TABT)) {
+ apecs_mcheck_expected = 0;
+ apecs_mcheck_taken = 1;
+ mb();
+ mb(); /* magic */
+ apecs_pci_clr_err();
+ wrmces(0x7);
+ mb();
+ draina();
+ }
+ else if (vector == 0x620 || vector == 0x630) {
+ /* Disable correctable from now on. */
+ wrmces(0x1f);
+ mb();
+ draina();
+ printk("mikasa_machine_check: HW correctable (0x%lx)\n",
+ vector);
+ }
+ else {
+ printk(KERN_CRIT "APECS machine check:\n");
+ printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n",
+ vector, la_ptr);
+ printk(KERN_CRIT
+ " pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
+ regs->pc, mchk_header->size, mchk_header->proc_offset,
+ mchk_header->sys_offset);
+ printk(KERN_CRIT " expected %d DCSR 0x%lx PEAR 0x%lx\n",
+ apecs_mcheck_expected, mchk_sysdata->epic_dcsr,
+ mchk_sysdata->epic_pear);
+
+ ptr = (unsigned long *)la_ptr;
+ for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
+ printk(KERN_CRIT " +%lx %lx %lx\n",
+ i*sizeof(long), ptr[i], ptr[i+1]);
+ }
+#if 0
+ /* doesn't work with MILO */
+ show_regs(regs);
+#endif
+ }
+}
+
+
+/*
+ * The System Vector
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
+struct alpha_machine_vector mikasa_mv __initmv = {
+ vector_name: "Mikasa",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_APECS_IO,
+ DO_APECS_BUS,
+ machine_check: mikasa_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 32,
+ irq_probe_mask: _PROBE_MASK(32),
+ update_irq_hw: mikasa_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: mikasa_device_interrupt,
+
+ init_arch: apecs_init_arch,
+ init_irq: mikasa_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: mikasa_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(mikasa)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO)
+struct alpha_machine_vector mikasa_primo_mv __initmv = {
+ vector_name: "Mikasa-Primo",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: mikasa_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 32,
+ irq_probe_mask: _PROBE_MASK(32),
+ update_irq_hw: mikasa_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: mikasa_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: mikasa_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: mikasa_primo_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(mikasa_primo)
+#endif
diff --git a/arch/alpha/kernel/sys_noritake.c b/arch/alpha/kernel/sys_noritake.c
new file mode 100644
index 000000000..c8901ae2f
--- /dev/null
+++ b/arch/alpha/kernel/sys_noritake.c
@@ -0,0 +1,301 @@
+/*
+ * linux/arch/alpha/kernel/sys_noritake.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the NORITAKE (AlphaServer 1000A),
+ * CORELLE (AlphaServer 800), and ALCOR Primo (AlphaStation 600A).
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_apecs.h>
+#include <asm/core_cia.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+noritake_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq <= 15)
+ if (irq <= 7)
+ outb(mask, 0x21); /* ISA PIC1 */
+ else
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else if (irq <= 31)
+ outw(~(mask >> 16), 0x54a);
+ else
+ outw(~(mask >> 32), 0x54c);
+}
+
+static void
+noritake_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary registers of NORITAKE */
+ pld = ((unsigned long) inw(0x54c) << 32) |
+ ((unsigned long) inw(0x54a) << 16) |
+ ((unsigned long) inb(0xa0) << 8) |
+ ((unsigned long) inb(0x20));
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i < 16) {
+ isa_device_interrupt(vector, regs);
+ } else {
+ handle_irq(i, i, regs);
+ }
+ }
+ restore_flags(flags);
+}
+
+static void
+noritake_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq, ack;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
+
+ /*
+ * I really hate to do this, too, but the NORITAKE SRM console also
+ * reports PCI vectors *lower* than I expected from the bit numbers
+ * in the documentation.
+ * But I really don't want to change the fixup code for allocation
+ * of IRQs, nor the alpha_irq_mask maintenance stuff, both of which
+ * look nice and clean now.
+ * So, here's this additional grotty hack... :-(
+ */
+ if (irq >= 16)
+ ack = irq = irq + 1;
+
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
+}
+
+static void __init
+noritake_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm)
+ alpha_mv.device_interrupt = noritake_srm_device_interrupt;
+
+ outw(~(alpha_irq_mask >> 16), 0x54a); /* note invert */
+ outw(~(alpha_irq_mask >> 32), 0x54c); /* note invert */
+ enable_irq(2); /* enable cascade */
+}
+
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ 0x542, summary register #1:
+ * Bit Meaning
+ * 0 All valid ints from summary regs 2 & 3
+ * 1 QLOGIC ISP1020A SCSI
+ * 2 Interrupt Line A from slot 0
+ * 3 Interrupt Line B from slot 0
+ * 4 Interrupt Line A from slot 1
+ * 5 Interrupt line B from slot 1
+ * 6 Interrupt Line A from slot 2
+ * 7 Interrupt Line B from slot 2
+ * 8 Interrupt Line A from slot 3
+ * 9 Interrupt Line B from slot 3
+ *10 Interrupt Line A from slot 4
+ *11 Interrupt Line B from slot 4
+ *12 Interrupt Line A from slot 5
+ *13 Interrupt Line B from slot 5
+ *14 Interrupt Line A from slot 6
+ *15 Interrupt Line B from slot 6
+ *
+ * Summary @ 0x544, summary register #2:
+ * Bit Meaning
+ * 0 OR of all unmasked ints in SR #2
+ * 1 OR of secondary bus ints
+ * 2 Interrupt Line C from slot 0
+ * 3 Interrupt Line D from slot 0
+ * 4 Interrupt Line C from slot 1
+ * 5 Interrupt line D from slot 1
+ * 6 Interrupt Line C from slot 2
+ * 7 Interrupt Line D from slot 2
+ * 8 Interrupt Line C from slot 3
+ * 9 Interrupt Line D from slot 3
+ *10 Interrupt Line C from slot 4
+ *11 Interrupt Line D from slot 4
+ *12 Interrupt Line C from slot 5
+ *13 Interrupt Line D from slot 5
+ *14 Interrupt Line C from slot 6
+ *15 Interrupt Line D from slot 6
+ *
+ * The device to slot mapping looks like:
+ *
+ * Slot Device
+ * 7 Intel PCI-EISA bridge chip
+ * 8 DEC PCI-PCI bridge chip
+ * 11 PCI on board slot 0
+ * 12 PCI on board slot 1
+ * 13 PCI on board slot 2
+ *
+ *
+ * This two layered interrupt approach means that we allocate IRQ 16 and
+ * above for PCI interrupts. The IRQ relates to which bit the interrupt
+ * comes in on. This makes interrupt processing much easier.
+ */
+
+static int __init
+noritake_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[15][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ /* note: IDSELs 16, 17, and 25 are CORELLE only */
+ { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
+ { -1, -1, -1, -1, -1}, /* IdSel 17, S3 Trio64 */
+ { -1, -1, -1, -1, -1}, /* IdSel 18, PCEB */
+ { -1, -1, -1, -1, -1}, /* IdSel 19, PPB */
+ { -1, -1, -1, -1, -1}, /* IdSel 20, ???? */
+ { -1, -1, -1, -1, -1}, /* IdSel 21, ???? */
+ { 16+2, 16+2, 16+3, 32+2, 32+3}, /* IdSel 22, slot 0 */
+ { 16+4, 16+4, 16+5, 32+4, 32+5}, /* IdSel 23, slot 1 */
+ { 16+6, 16+6, 16+7, 32+6, 32+7}, /* IdSel 24, slot 2 */
+ { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 25, slot 3 */
+ /* The following 5 are actually on PCI bus 1, which is
+ across the built-in bridge of the NORITAKE only. */
+ { 16+1, 16+1, 16+1, 16+1, 16+1}, /* IdSel 16, QLOGIC */
+ { 16+8, 16+8, 16+9, 32+8, 32+9}, /* IdSel 17, slot 3 */
+ {16+10, 16+10, 16+11, 32+10, 32+11}, /* IdSel 18, slot 4 */
+ {16+12, 16+12, 16+13, 32+12, 32+13}, /* IdSel 19, slot 5 */
+ {16+14, 16+14, 16+15, 32+14, 32+15}, /* IdSel 20, slot 6 */
+ };
+ const long min_idsel = 5, max_idsel = 19, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static int __init
+noritake_swizzle(struct pci_dev *dev, int *pinp)
+{
+ int slot, pin = *pinp;
+
+ /* Check first for the built-in bridge */
+ if (PCI_SLOT(dev->bus->self->devfn) == 8) {
+ slot = PCI_SLOT(dev->devfn) + 15; /* WAG! */
+ }
+ else
+ {
+ /* Must be a card-based bridge. */
+ do {
+ if (PCI_SLOT(dev->bus->self->devfn) == 8) {
+ slot = PCI_SLOT(dev->devfn) + 15;
+ break;
+ }
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)) ;
+
+ /* Move up the chain of bridges. */
+ dev = dev->bus->self;
+ /* Slot of the next bridge. */
+ slot = PCI_SLOT(dev->devfn);
+ } while (dev->bus->self);
+ }
+ *pinp = pin;
+ return slot;
+}
+
+static void __init
+noritake_pci_fixup(void)
+{
+ layout_all_busses(EISA_DEFAULT_IO_BASE,APECS_AND_LCA_DEFAULT_MEM_BASE);
+ common_pci_fixup(noritake_map_irq, noritake_swizzle);
+}
+
+static void __init
+noritake_primo_pci_fixup(void)
+{
+ layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(noritake_map_irq, noritake_swizzle);
+}
+
+
+/*
+ * The System Vectors
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_PRIMO)
+struct alpha_machine_vector noritake_mv __initmv = {
+ vector_name: "Noritake",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_APECS_IO,
+ DO_APECS_BUS,
+ machine_check: apecs_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 48,
+ irq_probe_mask: _PROBE_MASK(48),
+ update_irq_hw: noritake_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: noritake_device_interrupt,
+
+ init_arch: apecs_init_arch,
+ init_irq: noritake_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: noritake_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(noritake)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_PRIMO)
+struct alpha_machine_vector noritake_primo_mv __initmv = {
+ vector_name: "Noritake-Primo",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 48,
+ irq_probe_mask: _PROBE_MASK(48),
+ update_irq_hw: noritake_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: noritake_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: noritake_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: noritake_primo_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(noritake_primo)
+#endif
diff --git a/arch/alpha/kernel/sys_rawhide.c b/arch/alpha/kernel/sys_rawhide.c
new file mode 100644
index 000000000..0885a232a
--- /dev/null
+++ b/arch/alpha/kernel/sys_rawhide.c
@@ -0,0 +1,195 @@
+/*
+ * linux/arch/alpha/kernel/sys_rawhide.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the RAWHIDE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_mcpcia.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+rawhide_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 40) {
+ /* PCI bus 1 with builtin NCR810 SCSI */
+ *(vuip)MCPCIA_INT_MASK0(1) =
+ (~((mask) >> 40) & 0x00ffffffU) | 0x00fe0000U;
+ mb();
+ /* ... and read it back to make sure it got written. */
+ *(vuip)MCPCIA_INT_MASK0(1);
+ }
+ else if (irq >= 16) {
+ /* PCI bus 0 with EISA bridge */
+ *(vuip)MCPCIA_INT_MASK0(0) =
+ (~((mask) >> 16) & 0x00ffffffU) | 0x00ff0000U;
+ mb();
+ /* ... and read it back to make sure it got written. */
+ *(vuip)MCPCIA_INT_MASK0(0);
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+rawhide_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ int irq, ack;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
+
+ /*
+ * The RAWHIDE SRM console reports PCI interrupts with a vector
+ * 0x80 *higher* than one might expect, as PCI IRQ 0 (ie bit 0)
+ * shows up as IRQ 24, etc, etc. We adjust it down by 8 to have
+ * it line up with the actual bit numbers from the REQ registers,
+ * which is how we manage the interrupts/mask. Sigh...
+ *
+ * also, PCI #1 interrupts are offset some more... :-(
+ */
+ if (irq == 52)
+ ack = irq = 56; /* SCSI on PCI 1 is special */
+ else {
+ if (irq >= 24) /* adjust all PCI interrupts down 8 */
+ ack = irq = irq - 8;
+ if (irq >= 48) /* adjust PCI bus 1 interrupts down another 8 */
+ ack = irq = irq - 8;
+ }
+
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
+}
+
+static void __init
+rawhide_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ /* HACK ALERT! only PCI busses 0 and 1 are used currently,
+ and routing is only to CPU #1*/
+
+ *(vuip)MCPCIA_INT_MASK0(0) =
+ (~((alpha_irq_mask) >> 16) & 0x00ffffffU) | 0x00ff0000U; mb();
+ /* ... and read it back to make sure it got written. */
+ *(vuip)MCPCIA_INT_MASK0(0);
+
+ *(vuip)MCPCIA_INT_MASK0(1) =
+ (~((alpha_irq_mask) >> 40) & 0x00ffffffU) | 0x00fe0000U; mb();
+ /* ... and read it back to make sure it got written. */
+ *(vuip)MCPCIA_INT_MASK0(1);
+
+ enable_irq(2);
+}
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ MCPCIA_PCI0_INT_REQ:
+ * Bit Meaning
+ * 0 Interrupt Line A from slot 2 PCI0
+ * 1 Interrupt Line B from slot 2 PCI0
+ * 2 Interrupt Line C from slot 2 PCI0
+ * 3 Interrupt Line D from slot 2 PCI0
+ * 4 Interrupt Line A from slot 3 PCI0
+ * 5 Interrupt Line B from slot 3 PCI0
+ * 6 Interrupt Line C from slot 3 PCI0
+ * 7 Interrupt Line D from slot 3 PCI0
+ * 8 Interrupt Line A from slot 4 PCI0
+ * 9 Interrupt Line B from slot 4 PCI0
+ * 10 Interrupt Line C from slot 4 PCI0
+ * 11 Interrupt Line D from slot 4 PCI0
+ * 12 Interrupt Line A from slot 5 PCI0
+ * 13 Interrupt Line B from slot 5 PCI0
+ * 14 Interrupt Line C from slot 5 PCI0
+ * 15 Interrupt Line D from slot 5 PCI0
+ * 16 EISA interrupt (PCI 0) or SCSI interrupt (PCI 1)
+ * 17-23 NA
+ *
+ * IdSel
+ * 1 EISA bridge (PCI bus 0 only)
+ * 2 PCI option slot 2
+ * 3 PCI option slot 3
+ * 4 PCI option slot 4
+ * 5 PCI option slot 5
+ *
+ */
+
+static int __init
+rawhide_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[5][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { 16+16, 16+16, 16+16, 16+16, 16+16}, /* IdSel 1 SCSI PCI 1 */
+ { 16+ 0, 16+ 0, 16+ 1, 16+ 2, 16+ 3}, /* IdSel 2 slot 2 */
+ { 16+ 4, 16+ 4, 16+ 5, 16+ 6, 16+ 7}, /* IdSel 3 slot 3 */
+ { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11}, /* IdSel 4 slot 4 */
+ { 16+12, 16+12, 16+13, 16+14, 16+15} /* IdSel 5 slot 5 */
+ };
+ const long min_idsel = 1, max_idsel = 5, irqs_per_slot = 5;
+ int irq = COMMON_TABLE_LOOKUP;
+ if (irq >= 0)
+ irq += 24 * bus2hose[dev->bus->number]->pci_hose_index;
+ return irq;
+}
+
+static void __init
+rawhide_pci_fixup(void)
+{
+ mcpcia_pci_fixup();
+ common_pci_fixup(rawhide_map_irq, common_swizzle);
+}
+
+
+/*
+ * The System Vector
+ */
+
+struct alpha_machine_vector rawhide_mv __initmv = {
+ vector_name: "Rawhide",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_MCPCIA_IO,
+ DO_MCPCIA_BUS,
+ machine_check: mcpcia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 64,
+ irq_probe_mask: _PROBE_MASK(64),
+ update_irq_hw: rawhide_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: rawhide_srm_device_interrupt,
+
+ init_arch: mcpcia_init_arch,
+ init_irq: rawhide_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: rawhide_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(rawhide)
diff --git a/arch/alpha/kernel/sys_ruffian.c b/arch/alpha/kernel/sys_ruffian.c
new file mode 100644
index 000000000..9d32bcb15
--- /dev/null
+++ b/arch/alpha/kernel/sys_ruffian.c
@@ -0,0 +1,267 @@
+/*
+ * linux/arch/alpha/kernel/sys_ruffian.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the RUFFIAN.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_pyxis.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+ruffian_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16) {
+ /* Note inverted sense of mask bits: */
+ /* Make CERTAIN none of the bogus ints get enabled... */
+ *(vulp)PYXIS_INT_MASK =
+ ~((long)mask >> 16) & 0x00000000ffffffbfUL;
+ mb();
+ /* ... and read it back to make sure it got written. */
+ *(vulp)PYXIS_INT_MASK;
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+ruffian_ack_irq(unsigned long irq)
+{
+ if (irq < 16) {
+ /* Ack PYXIS ISA interrupt. */
+ *(vulp)PYXIS_INT_REQ = 1L << 7; mb();
+ /* ... and read it back to make sure it got written. */
+ *(vulp)PYXIS_INT_REQ;
+ if (irq > 7) {
+ outb(0x20, 0xa0);
+ }
+ outb(0x20, 0x20);
+ } else {
+ /* Ack PYXIS PCI interrupt. */
+ *(vulp)PYXIS_INT_REQ = (1UL << (irq - 16));
+ /* ... and read it back to make sure it got written. */
+ *(vulp)PYXIS_INT_REQ;
+ }
+}
+
+static void
+ruffian_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary register of PYXIS */
+ pld = *(vulp)PYXIS_INT_REQ;
+
+ /* For now, AND off any bits we are not interested in:
+ * HALT (2), timer (6), ISA Bridge (7), 21142 (8)
+ * then all the PCI slots/INTXs (12-31)
+ * flash(5) :DWH:
+ */
+ pld &= 0x00000000ffffff9fUL; /* was ffff7f */
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 7) {
+ /* Copy this bit from isa_device_interrupt cause
+ we need to hook into int 0 for the timer. I
+ refuse to soil device_interrupt with ifdefs. */
+
+ /* Generate a PCI interrupt acknowledge cycle.
+ The PIC will respond with the interrupt
+ vector of the highest priority interrupt
+ that is pending. The PALcode sets up the
+ interrupts vectors such that irq level L
+ generates vector L. */
+
+ unsigned int j = *(vuip)PYXIS_IACK_SC & 0xff;
+ if (j == 7 && !(inb(0x20) & 0x80)) {
+ /* It's only a passive release... */
+ } else if (j == 0) {
+ timer_interrupt(regs);
+ ruffian_ack_irq(0);
+ } else {
+ handle_irq(j, j, regs);
+ }
+ } else {
+ /* if not timer int */
+ handle_irq(16 + i, 16 + i, regs);
+ }
+
+ *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
+ *(vulp)PYXIS_INT_REQ; /* read to force the write */
+ }
+ restore_flags(flags);
+}
+
+static void __init
+ruffian_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ /* Invert 6&7 for i82371 */
+ *(vulp)PYXIS_INT_HILO = 0x000000c0UL; mb();
+ *(vulp)PYXIS_INT_CNFG = 0x00002064UL; mb(); /* all clear */
+ *(vulp)PYXIS_INT_MASK = 0x00000000UL; mb();
+ *(vulp)PYXIS_INT_REQ = 0xffffffffUL; mb();
+
+ outb(0x11,0xA0);
+ outb(0x08,0xA1);
+ outb(0x02,0xA1);
+ outb(0x01,0xA1);
+ outb(0xFF,0xA1);
+
+ outb(0x11,0x20);
+ outb(0x00,0x21);
+ outb(0x04,0x21);
+ outb(0x01,0x21);
+ outb(0xFF,0x21);
+
+ /* Send -INTA pulses to clear any pending interrupts ...*/
+ *(vuip) PYXIS_IACK_SC;
+
+ /* Finish writing the 82C59A PIC Operation Control Words */
+ outb(0x20,0xA0);
+ outb(0x20,0x20);
+
+ /* Turn on the interrupt controller, the timer interrupt */
+ enable_irq(16 + 7); /* enable ISA PIC cascade */
+ enable_irq(0); /* enable timer */
+ enable_irq(2); /* enable 2nd PIC cascade */
+}
+
+
+/*
+ * For RUFFIAN, we do not want to make any modifications to the PCI
+ * setup. So just scan the busses.
+ */
+
+static void __init
+ruffian_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+}
+
+
+/*
+ * The DeskStation Ruffian motherboard firmware does not place
+ * the memory size in the PALimpure area. Therefore, we use
+ * the Bank Configuration Registers in PYXIS to obtain the size.
+ */
+static unsigned long __init
+ruffian_get_bank_size(unsigned long offset)
+{
+ unsigned long bank_addr, bank, ret = 0;
+
+ /* Valid offsets are: 0x800, 0x840 and 0x880
+ since Ruffian only uses three banks. */
+ bank_addr = (unsigned long)PYXIS_MCR + offset;
+ bank = *(vulp)bank_addr;
+
+ /* Check BANK_ENABLE */
+ if (bank & 0x01) {
+ static unsigned long size[] __initdata = {
+ 0x40000000UL, /* 0x00, 1G */
+ 0x20000000UL, /* 0x02, 512M */
+ 0x10000000UL, /* 0x04, 256M */
+ 0x08000000UL, /* 0x06, 128M */
+ 0x04000000UL, /* 0x08, 64M */
+ 0x02000000UL, /* 0x0a, 32M */
+ 0x01000000UL, /* 0x0c, 16M */
+ 0x00800000UL, /* 0x0e, 8M */
+ 0x80000000UL, /* 0x10, 2G */
+ };
+
+ bank = (bank & 0x1e) >> 1;
+ if (bank < sizeof(size)/sizeof(*size))
+ ret = size[bank];
+ }
+
+ return ret;
+}
+
+static void __init
+ruffian_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ /* FIXME: What do we do with ruffian_get_bank_size above? */
+
+ pyxis_enable_errors();
+ if (!pyxis_srm_window_setup()) {
+ printk("ruffian_init_arch: Skipping window register rewrites."
+ "\n... Trust DeskStation firmware!\n");
+ }
+ pyxis_finish_init_arch();
+}
+
+
+static void
+ruffian_init_pit (void)
+{
+ /* Ruffian depends on the system timer established in MILO! */
+ request_region(0x70, 0x10, "timer");
+ init_pit_rest();
+}
+
+
+/*
+ * The System Vector
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_RUFFIAN)
+struct alpha_machine_vector ruffian_mv __initmv = {
+ vector_name: "Ruffian",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_PYXIS_IO,
+ DO_PYXIS_BUS,
+ machine_check: pyxis_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 48,
+ irq_probe_mask: RUFFIAN_PROBE_MASK,
+ update_irq_hw: ruffian_update_irq_hw,
+ ack_irq: ruffian_ack_irq,
+ device_interrupt: ruffian_device_interrupt,
+
+ init_arch: ruffian_init_arch,
+ init_irq: ruffian_init_irq,
+ init_pit: ruffian_init_pit,
+ pci_fixup: ruffian_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(ruffian)
+#endif
diff --git a/arch/alpha/kernel/sys_sable.c b/arch/alpha/kernel/sys_sable.c
new file mode 100644
index 000000000..42a1f9c48
--- /dev/null
+++ b/arch/alpha/kernel/sys_sable.c
@@ -0,0 +1,297 @@
+/*
+ * linux/arch/alpha/kernel/sys_sable.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the Sable and Sable-Gamma systems.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_t2.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+/*
+ * For SABLE, which is really baroque, we manage 40 IRQ's, but the
+ * hardware really only supports 24, not via normal ISA PIC,
+ * but cascaded custom 8259's, etc.
+ * 0-7 (char at 536)
+ * 8-15 (char at 53a)
+ * 16-23 (char at 53c)
+ */
+
+/* Note that the vector reported by the SRM PALcode corresponds to the
+ interrupt mask bits, but we have to manage via more normal IRQs. */
+
+static struct
+{
+ char irq_to_mask[40];
+ char mask_to_irq[40];
+ unsigned long shadow_mask;
+} sable_irq_swizzle = {
+ {
+ -1, 6, -1, 8, 15, 12, 7, 9, /* pseudo PIC 0-7 */
+ -1, 16, 17, 18, 3, -1, 21, 22, /* pseudo PIC 8-15 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 0-7 */
+ -1, -1, -1, -1, -1, -1, -1, -1, /* pseudo EISA 8-15 */
+ 2, 1, 0, 4, 5, -1, -1, -1, /* pseudo PCI */
+ },
+ {
+ 34, 33, 32, 12, 35, 36, 1, 6, /* mask 0-7 */
+ 3, 7, -1, -1, 5, -1, -1, 4, /* mask 8-15 */
+ 9, 10, 11, -1, -1, 14, 15, -1, /* mask 16-23 */
+ },
+ 0
+};
+
+
+static void
+sable_update_irq_hw(unsigned long irq, unsigned long unused_mask, int unmask_p)
+{
+ unsigned long bit, mask;
+
+ /* The "irq" argument is really the irq, but we need it to
+ be the mask bit number. Convert it now. */
+
+ irq = sable_irq_swizzle.irq_to_mask[irq];
+ bit = 1UL << irq;
+ mask = sable_irq_swizzle.shadow_mask | bit;
+ if (unmask_p)
+ mask &= ~bit;
+ sable_irq_swizzle.shadow_mask = mask;
+
+ /* The "irq" argument is now really the mask bit number. */
+ if (irq <= 7)
+ outb(mask, 0x537);
+ else if (irq <= 15)
+ outb(mask >> 8, 0x53b);
+ else
+ outb(mask >> 16, 0x53d);
+}
+
+static void
+sable_ack_irq(unsigned long irq)
+{
+ /* Note that the "irq" here is really the mask bit number */
+ switch (irq) {
+ case 0 ... 7:
+ outb(0xE0 | (irq - 0), 0x536);
+ outb(0xE0 | 1, 0x534); /* slave 0 */
+ break;
+ case 8 ... 15:
+ outb(0xE0 | (irq - 8), 0x53a);
+ outb(0xE0 | 3, 0x534); /* slave 1 */
+ break;
+ case 16 ... 24:
+ outb(0xE0 | (irq - 16), 0x53c);
+ outb(0xE0 | 4, 0x534); /* slave 2 */
+ break;
+ }
+}
+
+static void
+sable_srm_device_interrupt(unsigned long vector, struct pt_regs * regs)
+{
+ /* Note that the vector reported by the SRM PALcode corresponds
+ to the interrupt mask bits, but we have to manage via more
+ normal IRQs. */
+
+ int irq, ack;
+ unsigned long flags;
+
+ __save_and_cli(flags);
+ ack = irq = (vector - 0x800) >> 4;
+
+ irq = sable_irq_swizzle.mask_to_irq[(ack)];
+#if 0
+ if (irq == 5 || irq == 9 || irq == 10 || irq == 11 ||
+ irq == 14 || irq == 15)
+ printk("srm_device_interrupt: vector=0x%lx ack=0x%x"
+ " irq=0x%x\n", vector, ack, irq);
+#endif
+
+ handle_irq(irq, ack, regs);
+ __restore_flags(flags);
+}
+
+static void __init
+sable_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ outb(alpha_irq_mask , 0x537); /* slave 0 */
+ outb(alpha_irq_mask >> 8, 0x53b); /* slave 1 */
+ outb(alpha_irq_mask >> 16, 0x53d); /* slave 2 */
+ outb(0x44, 0x535); /* enable cascades in master */
+}
+
+
+/*
+ * PCI Fixup configuration for ALPHA SABLE (2100) - 2100A is different ??
+ *
+ * Summary Registers (536/53a/53c):
+ * Bit Meaning
+ *-----------------
+ * 0 PCI slot 0
+ * 1 NCR810 (builtin)
+ * 2 TULIP (builtin)
+ * 3 mouse
+ * 4 PCI slot 1
+ * 5 PCI slot 2
+ * 6 keyboard
+ * 7 floppy
+ * 8 COM2
+ * 9 parallel port
+ *10 EISA irq 3
+ *11 EISA irq 4
+ *12 EISA irq 5
+ *13 EISA irq 6
+ *14 EISA irq 7
+ *15 COM1
+ *16 EISA irq 9
+ *17 EISA irq 10
+ *18 EISA irq 11
+ *19 EISA irq 12
+ *20 EISA irq 13
+ *21 EISA irq 14
+ *22 NC
+ *23 IIC
+ *
+ * The device to slot mapping looks like:
+ *
+ * Slot Device
+ * 0 TULIP
+ * 1 SCSI
+ * 2 PCI-EISA bridge
+ * 3 none
+ * 4 none
+ * 5 none
+ * 6 PCI on board slot 0
+ * 7 PCI on board slot 1
+ * 8 PCI on board slot 2
+ *
+ *
+ * This two layered interrupt approach means that we allocate IRQ 16 and
+ * above for PCI interrupts. The IRQ relates to which bit the interrupt
+ * comes in on. This makes interrupt processing much easier.
+ */
+/*
+ * NOTE: the IRQ assignments below are arbitrary, but need to be consistent
+ * with the values in the irq swizzling tables above.
+ */
+
+static int __init
+sable_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[9][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { 32+0, 32+0, 32+0, 32+0, 32+0}, /* IdSel 0, TULIP */
+ { 32+1, 32+1, 32+1, 32+1, 32+1}, /* IdSel 1, SCSI */
+ { -1, -1, -1, -1, -1}, /* IdSel 2, SIO */
+ { -1, -1, -1, -1, -1}, /* IdSel 3, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 4, none */
+ { -1, -1, -1, -1, -1}, /* IdSel 5, none */
+ { 32+2, 32+2, 32+2, 32+2, 32+2}, /* IdSel 6, slot 0 */
+ { 32+3, 32+3, 32+3, 32+3, 32+3}, /* IdSel 7, slot 1 */
+ { 32+4, 32+4, 32+4, 32+4, 32+4}, /* IdSel 8, slot 2 */
+ };
+ const long min_idsel = 0, max_idsel = 8, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+void __init
+sable_pci_fixup(void)
+{
+ layout_all_busses(EISA_DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(sable_map_irq, common_swizzle);
+}
+
+
+/*
+ * The System Vectors
+ *
+ * In order that T2_HAE_ADDRESS should be a constant, we play
+ * these games with GAMMA_BIAS.
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || !defined(CONFIG_ALPHA_GAMMA)
+#undef GAMMA_BIAS
+#define GAMMA_BIAS 0
+struct alpha_machine_vector sable_mv __initmv = {
+ vector_name: "Sable",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_T2_IO,
+ DO_T2_BUS,
+ machine_check: t2_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 40,
+ irq_probe_mask: _PROBE_MASK(40),
+ update_irq_hw: sable_update_irq_hw,
+ ack_irq: sable_ack_irq,
+ device_interrupt: sable_srm_device_interrupt,
+
+ init_arch: t2_init_arch,
+ init_irq: sable_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: sable_pci_fixup,
+ kill_arch: generic_kill_arch,
+
+ sys: { t2: {
+ gamma_bias: 0
+ } }
+};
+ALIAS_MV(sable)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_GAMMA)
+#undef GAMMA_BIAS
+#define GAMMA_BIAS _GAMMA_BIAS
+struct alpha_machine_vector sable_gamma_mv __initmv = {
+ vector_name: "Sable-Gamma",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_T2_IO,
+ DO_T2_BUS,
+ machine_check: t2_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 40,
+ irq_probe_mask: _PROBE_MASK(40),
+ update_irq_hw: sable_update_irq_hw,
+ ack_irq: sable_ack_irq,
+ device_interrupt: sable_srm_device_interrupt,
+
+ init_arch: t2_init_arch,
+ init_irq: sable_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: sable_pci_fixup,
+ kill_arch: generic_kill_arch,
+
+ sys: { t2: {
+ gamma_bias: _GAMMA_BIAS
+ } }
+};
+ALIAS_MV(sable_gamma)
+#endif
diff --git a/arch/alpha/kernel/sys_sio.c b/arch/alpha/kernel/sys_sio.c
new file mode 100644
index 000000000..dfd6adaa7
--- /dev/null
+++ b/arch/alpha/kernel/sys_sio.c
@@ -0,0 +1,470 @@
+/*
+ * linux/arch/alpha/kernel/sys_sio.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code for all boards that route the PCI interrupts through the SIO
+ * PCI/ISA bridge. This includes Noname (AXPpci33), Multia (UDB),
+ * Kenetics's Platform 2000, Avanti (AlphaStation), XL, and AlphaBook1.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/compiler.h>
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_apecs.h>
+#include <asm/core_lca.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+static void
+sio_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 8)
+ outb(mask >> 8, 0xA1);
+ else
+ outb(mask, 0x21);
+}
+
+static void __init
+sio_init_irq(void)
+{
+ STANDARD_INIT_IRQ_PROLOG;
+
+ if (alpha_using_srm)
+ alpha_mv.device_interrupt = srm_device_interrupt;
+
+ enable_irq(2); /* enable cascade */
+}
+
+static inline void __init
+xl_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ /*
+ * Set up the PCI->physical memory translation windows. For
+ * the XL we *must* use both windows, in order to maximize the
+ * amount of physical memory that can be used to DMA from the
+ * ISA bus, and still allow PCI bus devices access to all of
+ * host memory.
+ *
+ * See <asm/apecs.h> for window bases and sizes.
+ *
+ * This restriction due to the true XL motherboards' 82379AB SIO
+ * PCI<->ISA bridge chip which passes only 27 bits of address...
+ */
+
+ *(vuip)APECS_IOC_PB1R = 1<<19 | (APECS_XL_DMA_WIN1_BASE & 0xfff00000U);
+ *(vuip)APECS_IOC_PM1R = (APECS_XL_DMA_WIN1_SIZE - 1) & 0xfff00000U;
+ *(vuip)APECS_IOC_TB1R = 0;
+
+ *(vuip)APECS_IOC_PB2R = 1<<19 | (APECS_XL_DMA_WIN2_BASE & 0xfff00000U);
+ *(vuip)APECS_IOC_PM2R = (APECS_XL_DMA_WIN2_SIZE - 1) & 0xfff00000U;
+ *(vuip)APECS_IOC_TB2R = 0;
+
+ /*
+ * Finally, clear the HAXR2 register, which gets used for PCI
+ * Config Space accesses. That is the way we want to use it,
+ * and we do not want to depend on what ARC or SRM might have
+ * left behind...
+ */
+
+ *(vuip)APECS_IOC_HAXR2 = 0; mb();
+}
+
+static inline void __init
+alphabook1_init_arch(unsigned long *mem_start, unsigned long *mem_end)
+{
+ /* The AlphaBook1 has LCD video fixed at 800x600,
+ 37 rows and 100 cols. */
+ screen_info.orig_y = 37;
+ screen_info.orig_video_cols = 100;
+ screen_info.orig_video_lines = 37;
+
+ lca_init_arch(mem_start, mem_end);
+}
+
+
+/*
+ * sio_route_tab selects irq routing in PCI/ISA bridge so that:
+ * PIRQ0 -> irq 15
+ * PIRQ1 -> irq 9
+ * PIRQ2 -> irq 10
+ * PIRQ3 -> irq 11
+ *
+ * This probably ought to be configurable via MILO. For
+ * example, sound boards seem to like using IRQ 9.
+ */
+static unsigned long sio_route_tab __initdata = 0;
+
+static void __init
+sio_pci_fixup(int (*map_irq)(struct pci_dev *dev, int sel, int pin),
+ unsigned long new_route_tab)
+{
+ unsigned int route_tab;
+
+ /* Examine or update the PCI routing table. */
+ pcibios_read_config_dword(0, PCI_DEVFN(7, 0), 0x60, &route_tab);
+
+ sio_route_tab = route_tab;
+ if (PCI_MODIFY) {
+ sio_route_tab = new_route_tab;
+ pcibios_write_config_dword(0, PCI_DEVFN(7, 0), 0x60,
+ new_route_tab);
+ }
+
+ /* Update all the IRQs. */
+ common_pci_fixup(map_irq, common_swizzle);
+}
+
+static unsigned int __init
+sio_collect_irq_levels(void)
+{
+ unsigned int level_bits = 0;
+ struct pci_dev *dev;
+
+ /* Iterate through the devices, collecting IRQ levels. */
+ for (dev = pci_devices; dev; dev = dev->next) {
+ if ((dev->class >> 16 == PCI_BASE_CLASS_BRIDGE) &&
+ (dev->class >> 8 != PCI_CLASS_BRIDGE_PCMCIA))
+ continue;
+
+ if (dev->irq)
+ level_bits |= (1 << dev->irq);
+ }
+ return level_bits;
+}
+
+static void __init
+sio_fixup_irq_levels(unsigned int level_bits)
+{
+ unsigned int old_level_bits;
+
+ /*
+ * Now, make all PCI interrupts level sensitive. Notice:
+ * these registers must be accessed byte-wise. inw()/outw()
+ * don't work.
+ *
+ * Make sure to turn off any level bits set for IRQs 9,10,11,15,
+ * so that the only bits getting set are for devices actually found.
+ * Note that we do preserve the remainder of the bits, which we hope
+ * will be set correctly by ARC/SRM.
+ *
+ * Note: we at least preserve any level-set bits on AlphaBook1
+ */
+ old_level_bits = inb(0x4d0) | (inb(0x4d1) << 8);
+
+ level_bits |= (old_level_bits & 0x71ff);
+
+ outb((level_bits >> 0) & 0xff, 0x4d0);
+ outb((level_bits >> 8) & 0xff, 0x4d1);
+}
+
+static inline int __init
+noname_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ /*
+ * The Noname board has 5 PCI slots with each of the 4
+ * interrupt pins routed to different pins on the PCI/ISA
+ * bridge (PIRQ0-PIRQ3). The table below is based on
+ * information available at:
+ *
+ * http://ftp.digital.com/pub/DEC/axppci/ref_interrupts.txt
+ *
+ * I have no information on the Avanti interrupt routing, but
+ * the routing seems to be identical to the Noname except
+ * that the Avanti has an additional slot whose routing I'm
+ * unsure of.
+ *
+ * pirq_tab[0] is a fake entry to deal with old PCI boards
+ * that have the interrupt pin number hardwired to 0 (meaning
+ * that they use the default INTA line, if they are interrupt
+ * driven at all).
+ */
+ static char irq_tab[][5] __initlocaldata = {
+ /*INT A B C D */
+ { 3, 3, 3, 3, 3}, /* idsel 6 (53c810) */
+ {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */
+ { 2, 2, -1, -1, -1}, /* idsel 8 (Hack: slot closest ISA) */
+ {-1, -1, -1, -1, -1}, /* idsel 9 (unused) */
+ {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
+ { 0, 0, 2, 1, 0}, /* idsel 11 KN25_PCI_SLOT0 */
+ { 1, 1, 0, 2, 1}, /* idsel 12 KN25_PCI_SLOT1 */
+ { 2, 2, 1, 0, 2}, /* idsel 13 KN25_PCI_SLOT2 */
+ { 0, 0, 0, 0, 0}, /* idsel 14 AS255 TULIP */
+ };
+ const long min_idsel = 6, max_idsel = 14, irqs_per_slot = 5;
+ int irq = COMMON_TABLE_LOOKUP, tmp;
+ tmp = __kernel_extbl(sio_route_tab, irq);
+ return irq >= 0 ? tmp : -1;
+}
+
+static inline void __init
+noname_pci_fixup(void)
+{
+ /*
+ * For UDB, the only available PCI slot must not map to IRQ 9,
+ * since that's the builtin MSS sound chip. That PCI slot
+ * will map to PIRQ1 (for INTA at least), so we give it IRQ 15
+ * instead.
+ *
+ * Unfortunately we have to do this for NONAME as well, since
+ * they are co-indicated when the platform type "Noname" is
+ * selected... :-(
+ */
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+ sio_pci_fixup(noname_map_irq, 0x0b0a0f09);
+ sio_fixup_irq_levels(sio_collect_irq_levels());
+ enable_ide(0x26e);
+}
+
+static inline void __init
+avanti_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+ sio_pci_fixup(noname_map_irq, 0x0b0a090f);
+ sio_fixup_irq_levels(sio_collect_irq_levels());
+ enable_ide(0x26e);
+}
+
+static inline void __init
+xl_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, XL_DEFAULT_MEM_BASE);
+ sio_pci_fixup(noname_map_irq, 0x0b0a090f);
+ sio_fixup_irq_levels(sio_collect_irq_levels());
+ enable_ide(0x26e);
+}
+
+static inline int __init
+p2k_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[][5] __initlocaldata = {
+ /*INT A B C D */
+ { 0, 0, -1, -1, -1}, /* idsel 6 (53c810) */
+ {-1, -1, -1, -1, -1}, /* idsel 7 (SIO: PCI/ISA bridge) */
+ { 1, 1, 2, 3, 0}, /* idsel 8 (slot A) */
+ { 2, 2, 3, 0, 1}, /* idsel 9 (slot B) */
+ {-1, -1, -1, -1, -1}, /* idsel 10 (unused) */
+ {-1, -1, -1, -1, -1}, /* idsel 11 (unused) */
+ { 3, 3, -1, -1, -1}, /* idsel 12 (CMD0646) */
+ };
+ const long min_idsel = 6, max_idsel = 12, irqs_per_slot = 5;
+ int irq = COMMON_TABLE_LOOKUP, tmp;
+ tmp = __kernel_extbl(sio_route_tab, irq);
+ return irq >= 0 ? tmp : -1;
+}
+
+static inline void __init
+p2k_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+ sio_pci_fixup(p2k_map_irq, 0x0b0a090f);
+ sio_fixup_irq_levels(sio_collect_irq_levels());
+ enable_ide(0x26e);
+}
+
+static inline void __init
+alphabook1_pci_fixup(void)
+{
+ struct pci_dev *dev;
+ unsigned char orig, config;
+
+ layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
+
+ /* For the AlphaBook1, NCR810 SCSI is 14, PCMCIA controller is 15. */
+ sio_pci_fixup(noname_map_irq, 0x0e0f0a0a);
+
+ /*
+ * On the AlphaBook1, the PCMCIA chip (Cirrus 6729)
+ * is sensitive to PCI bus bursts, so we must DISABLE
+ * burst mode for the NCR 8xx SCSI... :-(
+ *
+ * Note that the NCR810 SCSI driver must preserve the
+ * setting of the bit in order for this to work. At the
+ * moment (2.0.29), ncr53c8xx.c does NOT do this, but
+ * 53c7,8xx.c DOES.
+ */
+ for (dev = pci_devices; dev; dev = dev->next) {
+ if (dev->vendor == PCI_VENDOR_ID_NCR &&
+ (dev->device == PCI_DEVICE_ID_NCR_53C810 ||
+ dev->device == PCI_DEVICE_ID_NCR_53C815 ||
+ dev->device == PCI_DEVICE_ID_NCR_53C820 ||
+ dev->device == PCI_DEVICE_ID_NCR_53C825)) {
+ unsigned int io_port;
+ unsigned char ctest4;
+
+ pcibios_read_config_dword(dev->bus->number,
+ dev->devfn,
+ PCI_BASE_ADDRESS_0,
+ &io_port);
+ io_port &= PCI_BASE_ADDRESS_IO_MASK;
+ ctest4 = inb(io_port+0x21);
+ if (!(ctest4 & 0x80)) {
+ printk("AlphaBook1 NCR init: setting"
+ " burst disable\n");
+ outb(ctest4 | 0x80, io_port+0x21);
+ }
+ }
+ }
+
+ /* Do not set *ANY* level triggers for AlphaBook1. */
+ sio_fixup_irq_levels(0);
+
+ /* Make sure that register PR1 indicates 1Mb mem */
+ outb(0x0f, 0x3ce); orig = inb(0x3cf); /* read PR5 */
+ outb(0x0f, 0x3ce); outb(0x05, 0x3cf); /* unlock PR0-4 */
+ outb(0x0b, 0x3ce); config = inb(0x3cf); /* read PR1 */
+ if ((config & 0xc0) != 0xc0) {
+ printk("AlphaBook1 VGA init: setting 1Mb memory\n");
+ config |= 0xc0;
+ outb(0x0b, 0x3ce); outb(config, 0x3cf); /* write PR1 */
+ }
+ outb(0x0f, 0x3ce); outb(orig, 0x3cf); /* (re)lock PR0-4 */
+}
+
+
+/*
+ * The System Vectors
+ */
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_BOOK1)
+struct alpha_machine_vector alphabook1_mv __initmv = {
+ vector_name: "AlphaBook1",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_LCA_IO,
+ DO_LCA_BUS,
+ machine_check: lca_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 16,
+ irq_probe_mask: _PROBE_MASK(16),
+ update_irq_hw: sio_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: isa_device_interrupt,
+
+ init_arch: alphabook1_init_arch,
+ init_irq: sio_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: alphabook1_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(alphabook1)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_AVANTI)
+struct alpha_machine_vector avanti_mv __initmv = {
+ vector_name: "Avanti",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_APECS_IO,
+ DO_APECS_BUS,
+ machine_check: apecs_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 16,
+ irq_probe_mask: _PROBE_MASK(16),
+ update_irq_hw: sio_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: isa_device_interrupt,
+
+ init_arch: apecs_init_arch,
+ init_irq: sio_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: avanti_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(avanti)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_NONAME)
+struct alpha_machine_vector noname_mv __initmv = {
+ vector_name: "Noname",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_LCA_IO,
+ DO_LCA_BUS,
+ machine_check: lca_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 16,
+ irq_probe_mask: _PROBE_MASK(16),
+ update_irq_hw: sio_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: srm_device_interrupt,
+
+ init_arch: lca_init_arch,
+ init_irq: sio_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: noname_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(noname)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_P2K)
+struct alpha_machine_vector p2k_mv __initmv = {
+ vector_name: "Platform2000",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_LCA_IO,
+ DO_LCA_BUS,
+ machine_check: lca_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 16,
+ irq_probe_mask: P2K_PROBE_MASK,
+ update_irq_hw: sio_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: srm_device_interrupt,
+
+ init_arch: lca_init_arch,
+ init_irq: sio_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: p2k_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(p2k)
+#endif
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_XL)
+struct alpha_machine_vector xl_mv __initmv = {
+ vector_name: "XL",
+ DO_EV4_MMU,
+ DO_DEFAULT_RTC,
+ DO_APECS_IO,
+ BUS(apecs_xl),
+ machine_check: apecs_machine_check,
+ max_dma_address: ALPHA_XL_MAX_DMA_ADDRESS,
+
+ nr_irqs: 16,
+ irq_probe_mask: _PROBE_MASK(16),
+ update_irq_hw: sio_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: isa_device_interrupt,
+
+ init_arch: xl_init_arch,
+ init_irq: sio_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: xl_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(xl)
+#endif
diff --git a/arch/alpha/kernel/sys_sx164.c b/arch/alpha/kernel/sys_sx164.c
new file mode 100644
index 000000000..1219b9626
--- /dev/null
+++ b/arch/alpha/kernel/sys_sx164.c
@@ -0,0 +1,217 @@
+/*
+ * linux/arch/alpha/kernel/sys_sx164.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the SX164 (PCA56+PYXIS).
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_pyxis.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+static void
+sx164_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16) {
+ /* Make CERTAIN none of the bogus ints get enabled */
+ *(vulp)PYXIS_INT_MASK =
+ ~((long)mask >> 16) & ~0x000000000000003bUL;
+ mb();
+ /* ... and read it back to make sure it got written. */
+ *(vulp)PYXIS_INT_MASK;
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+sx164_srm_update_irq_hw(unsigned long irq, unsigned long mask, int unmask_p)
+{
+ if (irq >= 16) {
+ if (unmask_p)
+ cserve_ena(irq - 16);
+ else
+ cserve_dis(irq - 16);
+ }
+ else if (irq >= 8)
+ outb(mask >> 8, 0xA1); /* ISA PIC2 */
+ else
+ outb(mask, 0x21); /* ISA PIC1 */
+}
+
+static void
+sx164_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long pld, tmp;
+ unsigned int i;
+ unsigned long flags;
+
+ save_and_cli(flags);
+
+ /* Read the interrupt summary register of PYXIS */
+ pld = *(vulp)PYXIS_INT_REQ;
+
+ /*
+ * For now, AND off any bits we are not interested in:
+ * HALT (2), timer (6), ISA Bridge (7)
+ * then all the PCI slots/INTXs (8-23)
+ */
+ /* Maybe HALT should only be used for SRM console boots? */
+ pld &= 0x0000000000ffffc0UL;
+
+ /*
+ * Now for every possible bit set, work through them and call
+ * the appropriate interrupt handler.
+ */
+ while (pld) {
+ i = ffz(~pld);
+ pld &= pld - 1; /* clear least bit set */
+ if (i == 7) {
+ isa_device_interrupt(vector, regs);
+ } else if (i == 6) {
+ continue;
+ } else {
+ /* if not timer int */
+ handle_irq(16 + i, 16 + i, regs);
+ }
+ *(vulp)PYXIS_INT_REQ = 1UL << i; mb();
+ tmp = *(vulp)PYXIS_INT_REQ;
+ }
+ restore_flags(flags);
+}
+
+static void
+sx164_init_irq(void)
+{
+ outb(0, DMA1_RESET_REG);
+ outb(0, DMA2_RESET_REG);
+
+ if (alpha_using_srm) {
+ alpha_mv.update_irq_hw = sx164_srm_update_irq_hw;
+ alpha_mv.device_interrupt = srm_device_interrupt;
+ }
+ else {
+ /* Note invert on MASK bits. */
+ *(vulp)PYXIS_INT_MASK = ~((long)alpha_irq_mask >> 16);
+ mb();
+ *(vulp)PYXIS_INT_MASK;
+ }
+
+ enable_irq(16 + 6); /* enable timer */
+ enable_irq(16 + 7); /* enable ISA PIC cascade */
+ enable_irq(2); /* enable cascade */
+}
+
+/*
+ * PCI Fixup configuration.
+ *
+ * Summary @ PYXIS_INT_REQ:
+ * Bit Meaning
+ * 0 RSVD
+ * 1 NMI
+ * 2 Halt/Reset switch
+ * 3 MBZ
+ * 4 RAZ
+ * 5 RAZ
+ * 6 Interval timer (RTC)
+ * 7 PCI-ISA Bridge
+ * 8 Interrupt Line A from slot 3
+ * 9 Interrupt Line A from slot 2
+ *10 Interrupt Line A from slot 1
+ *11 Interrupt Line A from slot 0
+ *12 Interrupt Line B from slot 3
+ *13 Interrupt Line B from slot 2
+ *14 Interrupt Line B from slot 1
+ *15 Interrupt line B from slot 0
+ *16 Interrupt Line C from slot 3
+ *17 Interrupt Line C from slot 2
+ *18 Interrupt Line C from slot 1
+ *19 Interrupt Line C from slot 0
+ *20 Interrupt Line D from slot 3
+ *21 Interrupt Line D from slot 2
+ *22 Interrupt Line D from slot 1
+ *23 Interrupt Line D from slot 0
+ *
+ * IdSel
+ * 5 32 bit PCI option slot 2
+ * 6 64 bit PCI option slot 0
+ * 7 64 bit PCI option slot 1
+ * 8 Cypress I/O
+ * 9 32 bit PCI option slot 3
+ *
+ */
+
+static int __init
+sx164_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[5][5] __initlocaldata = {
+ /*INT INTA INTB INTC INTD */
+ { 16+ 9, 16+ 9, 16+13, 16+17, 16+21}, /* IdSel 5 slot 2 J17 */
+ { 16+11, 16+11, 16+15, 16+19, 16+23}, /* IdSel 6 slot 0 J19 */
+ { 16+10, 16+10, 16+14, 16+18, 16+22}, /* IdSel 7 slot 1 J18 */
+ { -1, -1, -1, -1, -1}, /* IdSel 8 SIO */
+ { 16+ 8, 16+ 8, 16+12, 16+16, 16+20} /* IdSel 9 slot 3 J15 */
+ };
+ const long min_idsel = 5, max_idsel = 9, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+void __init
+sx164_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(sx164_map_irq, common_swizzle);
+ SMC669_Init();
+}
+
+
+/*
+ * The System Vector
+ */
+
+struct alpha_machine_vector sx164_mv __initmv = {
+ vector_name: "SX164",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_PYXIS_IO,
+ DO_PYXIS_BUS,
+ machine_check: pyxis_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 40,
+ irq_probe_mask: _PROBE_MASK(40),
+ update_irq_hw: sx164_update_irq_hw,
+ ack_irq: generic_ack_irq,
+ device_interrupt: sx164_device_interrupt,
+
+ init_arch: pyxis_init_arch,
+ init_irq: sx164_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: sx164_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(sx164)
diff --git a/arch/alpha/kernel/sys_takara.c b/arch/alpha/kernel/sys_takara.c
new file mode 100644
index 000000000..326fd6409
--- /dev/null
+++ b/arch/alpha/kernel/sys_takara.c
@@ -0,0 +1,165 @@
+/*
+ * linux/arch/alpha/kernel/sys_takara.c
+ *
+ * Copyright (C) 1995 David A Rusling
+ * Copyright (C) 1996 Jay A Estabrook
+ * Copyright (C) 1998 Richard Henderson
+ *
+ * Code supporting the TAKARA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/ptrace.h>
+#include <asm/system.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <asm/mmu_context.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/core_cia.h>
+
+#include "proto.h"
+#include "irq.h"
+#include "bios32.h"
+#include "machvec.h"
+
+
+/*
+ * WARNING WARNING WARNING
+ *
+ * This port is missing an update_irq_hw implementation.
+ */
+
+static void
+takara_device_interrupt(unsigned long vector, struct pt_regs *regs)
+{
+ unsigned long flags;
+ unsigned intstatus;
+
+ save_and_cli(flags);
+
+ /*
+ * The PALcode will have passed us vectors 0x800 or 0x810,
+ * which are fairly arbitrary values and serve only to tell
+ * us whether an interrupt has come in on IRQ0 or IRQ1. If
+ * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's
+ * probably ISA, but PCI interrupts can come through IRQ0
+ * as well if the interrupt controller isn't in accelerated
+ * mode.
+ *
+ * OTOH, the accelerator thing doesn't seem to be working
+ * overly well, so what we'll do instead is try directly
+ * examining the Master Interrupt Register to see if it's a
+ * PCI interrupt, and if _not_ then we'll pass it on to the
+ * ISA handler.
+ */
+
+ intstatus = inw(0x500) & 15;
+ if (intstatus) {
+ /*
+ * This is a PCI interrupt. Check each bit and
+ * despatch an interrupt if it's set.
+ */
+
+ if (intstatus & 8) handle_irq(16+3, 16+3, regs);
+ if (intstatus & 4) handle_irq(16+2, 16+2, regs);
+ if (intstatus & 2) handle_irq(16+1, 16+1, regs);
+ if (intstatus & 1) handle_irq(16+0, 16+0, regs);
+ } else
+ isa_device_interrupt (vector, regs);
+
+ restore_flags(flags);
+}
+
+static void __init
+takara_init_irq(void)
+{
+ unsigned int ctlreg;
+
+ STANDARD_INIT_IRQ_PROLOG;
+
+ ctlreg = inl(0x500);
+ ctlreg &= ~0x8000; /* return to non-accelerated mode */
+ outw(ctlreg >> 16, 0x502);
+ outw(ctlreg & 0xFFFF, 0x500);
+ ctlreg = 0x05107c00; /* enable the PCI interrupt register */
+ outw(ctlreg >> 16, 0x502);
+ outw(ctlreg & 0xFFFF, 0x500);
+ enable_irq(2);
+}
+
+
+/*
+ * The Takara has PCI devices 1, 2, and 3 configured to slots 20,
+ * 19, and 18 respectively, in the default configuration. They can
+ * also be jumpered to slots 8, 7, and 6 respectively, which is fun
+ * because the SIO ISA bridge can also be slot 7. However, the SIO
+ * doesn't explicitly generate PCI-type interrupts, so we can
+ * assign it whatever the hell IRQ we like and it doesn't matter.
+ */
+
+static int __init
+takara_map_irq(struct pci_dev *dev, int slot, int pin)
+{
+ static char irq_tab[15][5] __initlocaldata = {
+ { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 6 == device 3 */
+ { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 7 == device 2 */
+ { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 8 == device 1 */
+ { -1, -1, -1, -1, -1}, /* slot 9 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 10 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 11 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 12 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 13 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 14 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 15 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 16 == nothing */
+ { -1, -1, -1, -1, -1}, /* slot 17 == nothing */
+ { 16+3, 16+3, 16+3, 16+3, 16+3}, /* slot 18 == device 3 */
+ { 16+2, 16+2, 16+2, 16+2, 16+2}, /* slot 19 == device 2 */
+ { 16+1, 16+1, 16+1, 16+1, 16+1}, /* slot 20 == device 1 */
+ };
+ const long min_idsel = 6, max_idsel = 20, irqs_per_slot = 5;
+ return COMMON_TABLE_LOOKUP;
+}
+
+static void __init
+takara_pci_fixup(void)
+{
+ layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
+ common_pci_fixup(takara_map_irq, common_swizzle);
+ enable_ide(0x26e);
+}
+
+
+/*
+ * The System Vector
+ */
+
+struct alpha_machine_vector takara_mv __initmv = {
+ vector_name: "Takara",
+ DO_EV5_MMU,
+ DO_DEFAULT_RTC,
+ DO_CIA_IO,
+ DO_CIA_BUS,
+ machine_check: cia_machine_check,
+ max_dma_address: ALPHA_MAX_DMA_ADDRESS,
+
+ nr_irqs: 20,
+ irq_probe_mask: _PROBE_MASK(20),
+ update_irq_hw: NULL,
+ ack_irq: generic_ack_irq,
+ device_interrupt: takara_device_interrupt,
+
+ init_arch: cia_init_arch,
+ init_irq: takara_init_irq,
+ init_pit: generic_init_pit,
+ pci_fixup: takara_pci_fixup,
+ kill_arch: generic_kill_arch,
+};
+ALIAS_MV(takara)
diff --git a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c
index 0456eb171..b1c1a9410 100644
--- a/arch/alpha/kernel/time.c
+++ b/arch/alpha/kernel/time.c
@@ -57,7 +57,7 @@ static struct {
__u32 last_time;
/* ticks/cycle * 2^48 */
unsigned long scaled_ticks_per_cycle;
- /* last time the cmos clock got updated */
+ /* last time the CMOS clock got updated */
time_t last_rtc_update;
} state;
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 42790d3aa..c2fc4c8e6 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -13,15 +13,17 @@
#include <linux/sched.h>
#include <linux/tty.h>
#include <linux/delay.h>
+#include <linux/smp_lock.h>
#include <asm/gentrap.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h>
#include <asm/sysinfo.h>
-#include <asm/smp_lock.h>
+#include "proto.h"
-static void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
+static void
+dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
{
printk("pc = [<%016lx>] ra = [<%016lx>] ps = %04lx\n",
regs->pc, regs->r26, regs->ps);
@@ -51,7 +53,8 @@ static void dik_show_regs(struct pt_regs *regs, unsigned long *r9_15)
printk("gp = %016lx sp = %p\n", regs->gp, regs+1);
}
-static void dik_show_code(unsigned int *pc)
+static void
+dik_show_code(unsigned int *pc)
{
long i;
@@ -65,7 +68,8 @@ static void dik_show_code(unsigned int *pc)
printk("\n");
}
-static void dik_show_trace(unsigned long *sp)
+static void
+dik_show_trace(unsigned long *sp)
{
long i = 0;
printk("Trace:");
@@ -86,8 +90,8 @@ static void dik_show_trace(unsigned long *sp)
printk("\n");
}
-void die_if_kernel(char * str, struct pt_regs *regs, long err,
- unsigned long *r9_15)
+void
+die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
{
if (regs->ps & 8)
return;
@@ -106,21 +110,20 @@ void die_if_kernel(char * str, struct pt_regs *regs, long err,
}
#ifndef CONFIG_MATHEMU
-static long dummy_alpha_fp_emul_imprecise(struct pt_regs *r, unsigned long wm)
-{
- return 0;
-}
-
+static long dummy_emul() { return 0; }
long (*alpha_fp_emul_imprecise)(struct pt_regs *regs, unsigned long writemask)
- = dummy_alpha_fp_emul_imprecise;
+ = (void *)dummy_emul;
+long (*alpha_fp_emul) (unsigned long pc)
+ = (void *)dummy_emul;
#else
long alpha_fp_emul_imprecise(struct pt_regs *regs, unsigned long writemask);
+long alpha_fp_emul (unsigned long pc);
#endif
-asmlinkage void do_entArith(unsigned long summary, unsigned long write_mask,
- unsigned long a2, unsigned long a3,
- unsigned long a4, unsigned long a5,
- struct pt_regs regs)
+asmlinkage void
+do_entArith(unsigned long summary, unsigned long write_mask, unsigned long a2,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs regs)
{
if ((summary & 1)) {
/*
@@ -133,8 +136,10 @@ asmlinkage void do_entArith(unsigned long summary, unsigned long write_mask,
}
lock_kernel();
+#if 0
printk("%s: arithmetic trap at %016lx: %02lx %016lx\n",
current->comm, regs.pc, summary, write_mask);
+#endif
die_if_kernel("Arithmetic fault", &regs, 0, 0);
force_sig(SIGFPE, current);
unlock_kernel();
@@ -202,7 +207,6 @@ asmlinkage void do_entIF(unsigned long type, unsigned long a1,
case 4: /* opDEC */
#ifdef CONFIG_ALPHA_NEED_ROUNDING_EMULATION
{
- extern long alpha_fp_emul (unsigned long pc);
unsigned int opcode;
/* get opcode of faulting instruction: */
@@ -255,9 +259,10 @@ struct unaligned_stat {
#define una_reg(r) (regs.regs[(r) >= 16 && (r) <= 18 ? (r)+19 : (r)])
-asmlinkage void do_entUna(void * va, unsigned long opcode, unsigned long reg,
- unsigned long a3, unsigned long a4, unsigned long a5,
- struct allregs regs)
+asmlinkage void
+do_entUna(void * va, unsigned long opcode, unsigned long reg,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct allregs regs)
{
long error, tmp1, tmp2, tmp3, tmp4;
unsigned long pc = regs.pc - 4;
@@ -497,7 +502,8 @@ got_exception:
* needs to be remapped to preserve non-finite values
* (infinities, not-a-numbers, denormals).
*/
-static inline unsigned long s_mem_to_reg (unsigned long s_mem)
+static inline unsigned long
+s_mem_to_reg (unsigned long s_mem)
{
unsigned long frac = (s_mem >> 0) & 0x7fffff;
unsigned long sign = (s_mem >> 31) & 0x1;
@@ -524,7 +530,8 @@ static inline unsigned long s_mem_to_reg (unsigned long s_mem)
* Convert an s-floating point value in register format to the
* corresponding value in memory format.
*/
-static inline unsigned long s_reg_to_mem (unsigned long s_reg)
+static inline unsigned long
+s_reg_to_mem (unsigned long s_reg)
{
return ((s_reg >> 62) << 30) | ((s_reg << 5) >> 34);
}
@@ -571,12 +578,10 @@ static int unauser_reg_offsets[32] = {
#undef R
-asmlinkage void do_entUnaUser(void * va, unsigned long opcode,
- unsigned long reg, struct pt_regs *regs)
+asmlinkage void
+do_entUnaUser(void * va, unsigned long opcode,
+ unsigned long reg, struct pt_regs *regs)
{
- extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
- extern unsigned long alpha_read_fp_reg (unsigned long reg);
-
static int cnt = 0;
static long last_time = 0;
@@ -868,10 +873,10 @@ give_sigbus:
/*
* Unimplemented system calls.
*/
-asmlinkage long alpha_ni_syscall(unsigned long a0, unsigned long a1,
- unsigned long a2, unsigned long a3,
- unsigned long a4, unsigned long a5,
- struct pt_regs regs)
+asmlinkage long
+alpha_ni_syscall(unsigned long a0, unsigned long a1, unsigned long a2,
+ unsigned long a3, unsigned long a4, unsigned long a5,
+ struct pt_regs regs)
{
/* We only get here for OSF system calls, minus #112;
the rest go to sys_ni_syscall. */
@@ -879,17 +884,11 @@ asmlinkage long alpha_ni_syscall(unsigned long a0, unsigned long a1,
return -ENOSYS;
}
-extern asmlinkage void entMM(void);
-extern asmlinkage void entIF(void);
-extern asmlinkage void entArith(void);
-extern asmlinkage void entUna(void);
-extern asmlinkage void entSys(void);
-
-register unsigned long gptr __asm__("$29");
-
-void trap_init(void)
+void
+trap_init(void)
{
/* Tell PAL-code what global pointer we want in the kernel. */
+ register unsigned long gptr __asm__("$29");
wrkgp(gptr);
wrent(entArith, 1);
diff --git a/arch/alpha/kernel/tsunami.c b/arch/alpha/kernel/tsunami.c
deleted file mode 100644
index 3d0fdde89..000000000
--- a/arch/alpha/kernel/tsunami.c
+++ /dev/null
@@ -1,503 +0,0 @@
-/*
- * Code common to all TSUNAMI chips.
- *
- * Based on code written by David A Rusling (david.rusling@reo.mts.dec.com).
- *
- */
-#include <linux/kernel.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/hwrpb.h>
-#include <asm/ptrace.h>
-#include <asm/mmu_context.h>
-
-/*
- * NOTE: Herein lie back-to-back mb instructions. They are magic.
- * One plausible explanation is that the i/o controller does not properly
- * handle the system transaction. Another involves timing. Ho hum.
- */
-
-extern struct hwrpb_struct *hwrpb;
-extern asmlinkage void wrmces(unsigned long mces);
-
-/*
- * BIOS32-style PCI interface:
- */
-
-#ifdef CONFIG_ALPHA_TSUNAMI
-
-#ifdef DEBUG
-# define DBG(args) printk args
-#else
-# define DBG(args)
-#endif
-
-#define DEBUG_MCHECK
-#ifdef DEBUG_MCHECK
-# define DBG_MCK(args) printk args
-#define DEBUG_MCHECK_DUMP
-#else
-# define DBG_MCK(args)
-#endif
-
-#define vuip volatile unsigned int *
-#define vulp volatile unsigned long *
-
-static volatile unsigned int TSUNAMI_mcheck_expected[NR_CPUS];
-static volatile unsigned int TSUNAMI_mcheck_taken[NR_CPUS];
-static unsigned int TSUNAMI_jd[NR_CPUS];
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
-unsigned int TSUNAMI_DMA_WIN_BASE = TSUNAMI_DMA_WIN_BASE_DEFAULT;
-unsigned int TSUNAMI_DMA_WIN_SIZE = TSUNAMI_DMA_WIN_SIZE_DEFAULT;
-#endif /* SRM_SETUP */
-
-/*
- * Given a bus, device, and function number, compute resulting
- * configuration space address
- * accordingly. It is therefore not safe to have concurrent
- * invocations to configuration space access routines, but there
- * really shouldn't be any need for this.
- *
- * Note that all config space accesses use Type 1 address format.
- *
- * Note also that type 1 is determined by non-zero bus number.
- *
- * Type 1:
- *
- * 3 3|3 3 2 2|2 2 2 2|2 2 2 2|1 1 1 1|1 1 1 1|1 1
- * 3 2|1 0 9 8|7 6 5 4|3 2 1 0|9 8 7 6|5 4 3 2|1 0 9 8|7 6 5 4|3 2 1 0
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | | | | | | | | | | |B|B|B|B|B|B|B|B|D|D|D|D|D|F|F|F|R|R|R|R|R|R|0|1|
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- *
- * 31:24 reserved
- * 23:16 bus number (8 bits = 128 possible buses)
- * 15:11 Device number (5 bits)
- * 10:8 function number
- * 7:2 register number
- *
- * Notes:
- * The function number selects which function of a multi-function device
- * (e.g., scsi and ethernet).
- *
- * The register selects a DWORD (32 bit) register offset. Hence it
- * doesn't get shifted by 2 bits as we want to "drop" the bottom two
- * bits.
- */
-static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned long *pci_addr,
- unsigned char *type1)
-{
- unsigned long addr;
-
- DBG(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, pci_addr=0x%p, type1=0x%p)\n",
- bus, device_fn, where, pci_addr, type1));
-
- if (bus == 0) {
- *type1 = 0;
- } else {
- /* type 1 configuration cycle: */
- *type1 = 1;
- }
- addr = (bus << 16) | (device_fn << 8) | (where);
- *pci_addr = addr;
- DBG(("mk_conf_addr: returning pci_addr 0x%lx\n", addr));
- return 0;
-}
-
-int pcibios_read_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char *value)
-{
- unsigned long addr;
- unsigned char type1;
- unsigned char result;
-
- *value = 0xff;
-
- if (mk_conf_addr(bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- __asm__ __volatile__ (
- "ldbu %0,%1"
- : "=r" (result)
- : "m" (*(unsigned char *)(addr+TSUNAMI_PCI0_CONF)));
-
- *value = result;
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_read_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short *value)
-{
- unsigned long addr;
- unsigned char type1;
- unsigned short result;
-
- *value = 0xffff;
-
- if (where & 0x1) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(bus, device_fn, where, &addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- __asm__ __volatile__ (
- "ldwu %0,%1"
- : "=r" (result)
- : "m" (*(unsigned short *)(addr+TSUNAMI_PCI0_CONF)));
-
- *value = result;
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_read_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int *value)
-{
- unsigned long addr;
- unsigned char type1;
- unsigned int result;
-
- *value = 0xffffffff;
- if (where & 0x3) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(bus, device_fn, where, &addr, &type1)) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- __asm__ __volatile__ (
- "ldl %0,%1"
- : "=r" (result)
- : "m" (*(unsigned int *)(addr+TSUNAMI_PCI0_CONF)));
-
- *value = result;
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_byte (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned char value)
-{
- unsigned long addr;
- unsigned char type1;
-
- if (mk_conf_addr(bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- __asm__ __volatile__ (
- "stb %1,%0\n\t"
- "mb"
- : : "m" (*(unsigned char *)(addr+TSUNAMI_PCI0_CONF)),
- "r" (value));
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_word (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned short value)
-{
- unsigned long addr;
- unsigned char type1;
-
- if (where & 0x1) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- __asm__ __volatile__ (
- "stw %1,%0\n\t"
- "mb"
- : : "m" (*(unsigned short *)(addr+TSUNAMI_PCI0_CONF)),
- "r" (value));
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
- unsigned char where, unsigned int value)
-{
- unsigned long addr;
- unsigned char type1;
-
- if (where & 0x3) {
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (mk_conf_addr(bus, device_fn, where, &addr, &type1) < 0) {
- return PCIBIOS_SUCCESSFUL;
- }
-
- __asm__ __volatile__ (
- "stl %1,%0\n\t"
- "mb"
- : : "m" (*(unsigned int *)(addr+TSUNAMI_PCI0_CONF)),
- "r" (value));
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-unsigned long tsunami_init(unsigned long mem_start, unsigned long mem_end)
-{
- unsigned long tsunami_err;
- unsigned int i;
-
-#if 0
-printk("tsunami_init: CChip registers:\n");
-printk("tsunami_init: CSR_CSC 0x%lx\n", *(vulp)TSUNAMI_CSR_CSC);
-printk("tsunami_init: CSR_MTR 0x%lx\n", *(vulp)TSUNAMI_CSR_MTR);
-printk("tsunami_init: CSR_MISC 0x%lx\n", *(vulp)TSUNAMI_CSR_MISC);
-printk("tsunami_init: CSR_DIM0 0x%lx\n", *(vulp)TSUNAMI_CSR_DIM0);
-printk("tsunami_init: CSR_DIM1 0x%lx\n", *(vulp)TSUNAMI_CSR_DIM1);
-printk("tsunami_init: CSR_DIR0 0x%lx\n", *(vulp)TSUNAMI_CSR_DIR0);
-printk("tsunami_init: CSR_DIR1 0x%lx\n", *(vulp)TSUNAMI_CSR_DIR1);
-printk("tsunami_init: CSR_DRIR 0x%lx\n", *(vulp)TSUNAMI_CSR_DRIR);
-
-printk("tsunami_init: DChip registers:\n");
-printk("tsunami_init: CSR_DSC 0x%lx\n", *(vulp)TSUNAMI_CSR_DSC);
-printk("tsunami_init: CSR_STR 0x%lx\n", *(vulp)TSUNAMI_CSR_STR);
-printk("tsunami_init: CSR_DREV 0x%lx\n", *(vulp)TSUNAMI_CSR_DREV);
-
-printk("tsunami_init: PChip registers:\n");
-printk("tsunami_init: PCHIP0_WSBA0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA0);
-printk("tsunami_init: PCHIP0_WSBA1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA1);
-printk("tsunami_init: PCHIP0_WSBA2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA2);
-printk("tsunami_init: PCHIP0_WSBA3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSBA3);
-printk("tsunami_init: PCHIP0_WSM0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM0);
-printk("tsunami_init: PCHIP0_WSM1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM1);
-printk("tsunami_init: PCHIP0_WSM2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM2);
-printk("tsunami_init: PCHIP0_WSM3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_WSM3);
-printk("tsunami_init: PCHIP0_TBA0 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA0);
-printk("tsunami_init: PCHIP0_TBA1 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA1);
-printk("tsunami_init: PCHIP0_TBA2 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA2);
-printk("tsunami_init: PCHIP0_TBA3 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_TBA3);
-
-printk("tsunami_init: PCHIP0_PCTL 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PCTL);
-printk("tsunami_init: PCHIP0_PLAT 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PLAT);
-printk("tsunami_init: PCHIP0_PERROR 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PERROR);
-printk("tsunami_init: PCHIP0_PERRMASK 0x%lx\n", *(vulp)TSUNAMI_PCHIP0_PERRMASK);
-
-#endif
-
- for (i = 0; i < NR_CPUS; i++) {
- TSUNAMI_mcheck_expected[i] = 0;
- TSUNAMI_mcheck_taken[i] = 0;
- }
-#ifdef NOT_YET
- /*
- * Set up error reporting. Make sure CPU_PE is OFF in the mask.
- */
- tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERRMASK;
- tsunami_err &= ~20;
- *(vulp)TSUNAMI_PCHIP0_PERRMASK = tsunami_err;
- mb();
- tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERRMASK;
-
- tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERROR ;
- tsunami_err |= 0x40; /* master/target abort */
- *(vulp)TSUNAMI_PCHIP0_PERROR = tsunami_err ;
- mb() ;
- tsunami_err = *(vulp)TSUNAMI_PCHIP0_PERROR ;
-#endif /* NOT_YET */
-
-#ifdef CONFIG_ALPHA_SRM_SETUP
- /* check window 0 for enabled and mapped to 0 */
- if (((*(vulp)TSUNAMI_PCHIP0_WSBA0 & 3) == 1) &&
- (*(vulp)TSUNAMI_PCHIP0_TBA0 == 0) &&
- ((*(vulp)TSUNAMI_PCHIP0_WSM0 & 0xfff00000U) > 0x0ff00000U))
- {
- TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA0 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM0 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("tsunami_init: using Window 0 settings\n");
- printk("tsunami_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vulp)TSUNAMI_PCHIP0_WSBA0,
- *(vulp)TSUNAMI_PCHIP0_WSM0,
- *(vulp)TSUNAMI_PCHIP0_TBA0);
-#endif
- }
- else /* check window 1 for enabled and mapped to 0 */
- if (((*(vulp)TSUNAMI_PCHIP0_WSBA1 & 3) == 1) &&
- (*(vulp)TSUNAMI_PCHIP0_TBA1 == 0) &&
- ((*(vulp)TSUNAMI_PCHIP0_WSM1 & 0xfff00000U) > 0x0ff00000U))
-{
- TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA1 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM1 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("tsunami_init: using Window 1 settings\n");
- printk("tsunami_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vulp)TSUNAMI_PCHIP0_WSBA1,
- *(vulp)TSUNAMI_PCHIP0_WSM1,
- *(vulp)TSUNAMI_PCHIP0_TBA1);
-#endif
- }
- else /* check window 2 for enabled and mapped to 0 */
- if (((*(vulp)TSUNAMI_PCHIP0_WSBA2 & 3) == 1) &&
- (*(vulp)TSUNAMI_PCHIP0_TSB2 == 0) &&
- ((*(vulp)TSUNAMI_PCHIP0_WSM2 & 0xfff00000U) > 0x0ff00000U))
- {
- TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA2 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM2 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("tsunami_init: using Window 2 settings\n");
- printk("tsunami_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vulp)TSUNAMI_PCHIP0_WSBA2,
- *(vulp)TSUNAMI_PCHIP0_WSM2,
- *(vulp)TSUNAMI_PCHIP0_TSB2);
-#endif
- }
- else /* check window 3 for enabled and mapped to 0 */
- if (((*(vulp)TSUNAMI_PCHIP0_WSBA3 & 3) == 1) &&
- (*(vulp)TSUNAMI_PCHIP0_TBA3 == 0) &&
- ((*(vulp)TSUNAMI_PCHIP0_WSM3 & 0xfff00000U) > 0x0ff00000U))
- {
- TSUNAMI_DMA_WIN_BASE = *(vulp)TSUNAMI_PCHIP0_WSBA3 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE = *(vulp)TSUNAMI_PCHIP0_WSM3 & 0xfff00000U;
- TSUNAMI_DMA_WIN_SIZE += 0x00100000U;
-#if 1
- printk("tsunami_init: using Window 3 settings\n");
- printk("tsunami_init: BASE 0x%x MASK 0x%x TRANS 0x%x\n",
- *(vulp)TSUNAMI_PCHIP0_WSBA3,
- *(vulp)TSUNAMI_PCHIP0_WSM3,
- *(vulp)TSUNAMI_PCHIP0_TBA3);
-#endif
- }
- else /* we must use our defaults which were pre-initialized... */
-#endif /* SRM_SETUP */
- {
- /*
- * Set up the PCI->physical memory translation windows.
- * For now, windows 1,2 and 3 are disabled. In the future, we may
- * want to use them to do scatter/gather DMA. Window 0
- * goes at 1 GB and is 1 GB large.
- */
-
- *(vulp)TSUNAMI_PCHIP0_WSBA0 = 1L | (TSUNAMI_DMA_WIN_BASE & 0xfff00000U);
- *(vulp)TSUNAMI_PCHIP0_WSM0 = (TSUNAMI_DMA_WIN_SIZE - 1) & 0xfff00000UL;
- *(vulp)TSUNAMI_PCHIP0_TBA0 = 0UL;
-
- *(vulp)TSUNAMI_PCHIP0_WSBA1 = 0UL;
- *(vulp)TSUNAMI_PCHIP0_WSBA2 = 0UL;
- *(vulp)TSUNAMI_PCHIP0_WSBA3 = 0UL;
- mb();
- }
-
- /*
- * check ASN in HWRPB for validity, report if bad
- */
- if (hwrpb->max_asn != MAX_ASN) {
- printk("TSUNAMI_init: max ASN from HWRPB is bad (0x%lx)\n",
- hwrpb->max_asn);
- hwrpb->max_asn = MAX_ASN;
- }
-
- return mem_start;
-}
-
-int tsunami_pci_clr_err(void)
-{
- unsigned int cpu = smp_processor_id();
-
- TSUNAMI_jd[cpu] = *((vulp)TSUNAMI_PCHIP0_PERROR);
- DBG(("TSUNAMI_pci_clr_err: PERROR after read 0x%x\n", TSUNAMI_jd[cpu]));
- *((vulp)TSUNAMI_PCHIP0_PERROR) = 0x040; mb();
- TSUNAMI_jd[cpu] = *((vulp)TSUNAMI_PCHIP0_PERROR);
- return 0;
-}
-
-void tsunami_machine_check(unsigned long vector, unsigned long la_ptr,
- struct pt_regs * regs)
-{
-#if 1
- printk("TSUNAMI machine check ignored\n") ;
-#else
- struct el_common *mchk_header;
- struct el_TSUNAMI_sysdata_mcheck *mchk_sysdata;
- unsigned int cpu = smp_processor_id();
-
- mchk_header = (struct el_common *)la_ptr;
-
- mchk_sysdata =
- (struct el_TSUNAMI_sysdata_mcheck *)(la_ptr + mchk_header->sys_offset);
-
-#if 0
- DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset));
- DBG_MCK(("tsunami_machine_check: expected %d DCSR 0x%lx PEAR 0x%lx\n",
- TSUNAMI_mcheck_expected[cpu], mchk_sysdata->epic_dcsr,
- mchk_sysdata->epic_pear));
-#endif
-#ifdef DEBUG_MCHECK_DUMP
- {
- unsigned long *ptr;
- int i;
-
- ptr = (unsigned long *)la_ptr;
- for (i = 0; i < mchk_header->size / sizeof(long); i += 2) {
- printk(" +%lx %lx %lx\n", i*sizeof(long), ptr[i], ptr[i+1]);
- }
- }
-#endif /* DEBUG_MCHECK_DUMP */
- /*
- * Check if machine check is due to a badaddr() and if so,
- * ignore the machine check.
- */
- mb();
- mb(); /* magic */
- if (TSUNAMI_mcheck_expected[cpu]) {
- DBG(("TSUNAMI machine check expected\n"));
- TSUNAMI_mcheck_expected[cpu] = 0;
- TSUNAMI_mcheck_taken[cpu] = 1;
- mb();
- mb(); /* magic */
- draina();
- tsunami_pci_clr_err();
- wrmces(0x7);
- mb();
- }
-#if 1
- else {
- printk("TSUNAMI machine check NOT expected\n") ;
- DBG_MCK(("tsunami_machine_check: vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr));
- DBG_MCK(("\t\t pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
- regs->pc, mchk_header->size, mchk_header->proc_offset,
- mchk_header->sys_offset));
- TSUNAMI_mcheck_expected[cpu] = 0;
- TSUNAMI_mcheck_taken[cpu] = 1;
- mb();
- mb(); /* magic */
- draina();
- tsunami_pci_clr_err();
- wrmces(0x7);
- mb();
- }
-#endif
-#endif
-}
-
-#endif /* CONFIG_ALPHA_TSUNAMI */
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
index 7c1e37bac..4dd7d591d 100644
--- a/arch/alpha/lib/Makefile
+++ b/arch/alpha/lib/Makefile
@@ -7,7 +7,7 @@ OBJS = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \
strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \
strchr.o strrchr.o \
copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \
- csum_ipv6_magic.o
+ csum_ipv6_magic.o strcasecmp.o
lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS)
diff --git a/arch/alpha/lib/io.c b/arch/alpha/lib/io.c
index 405a3afa8..50cc1fe05 100644
--- a/arch/alpha/lib/io.c
+++ b/arch/alpha/lib/io.c
@@ -3,26 +3,9 @@
* files..
*/
#include <linux/kernel.h>
-
+#include <linux/types.h>
#include <asm/io.h>
-/*
- * Jensen has a separate "local" and "bus" IO space for
- * byte-wide IO.
- */
-#ifdef __is_local
-
-unsigned int _bus_inb(unsigned long addr)
-{
- return __bus_inb(addr);
-}
-
-void _bus_outb(unsigned char b, unsigned long addr)
-{
- __bus_outb(b, addr);
-}
-#endif
-
unsigned int _inb(unsigned long addr)
{
return __inb(addr);
@@ -70,6 +53,10 @@ unsigned long _readl(unsigned long addr)
return __readl(addr);
}
+unsigned long _readq(unsigned long addr)
+{
+ return __readq(addr);
+}
void _writeb(unsigned char b, unsigned long addr)
{
@@ -86,6 +73,11 @@ void _writel(unsigned int b, unsigned long addr)
__writel(b, addr);
}
+void _writeq(unsigned long b, unsigned long addr)
+{
+ __writeq(b, addr);
+}
+
/*
* Read COUNT 8-bit bytes from port PORT into memory starting at
* SRC.
@@ -363,12 +355,48 @@ void outsl (unsigned long port, const void *src, unsigned long count)
* Copy data from IO memory space to "real" memory space.
* This needs to be optimized.
*/
-void _memcpy_fromio(void * to, unsigned long from, unsigned long count)
+void _memcpy_fromio(void * to, unsigned long from, long count)
{
- while (count) {
+ /* Optimize co-aligned transfers. Everything else gets handled
+ a byte at a time. */
+
+ if (count >= 8 && ((long)to & 7) == (from & 7)) {
+ count -= 8;
+ do {
+ *(u64 *)to = readq(from);
+ count -= 8;
+ to += 8;
+ from += 8;
+ } while (count >= 0);
+ count += 8;
+ }
+
+ if (count >= 4 && ((long)to & 3) == (from & 3)) {
+ count -= 4;
+ do {
+ *(u32 *)to = readl(from);
+ count -= 4;
+ to += 4;
+ from += 4;
+ } while (count >= 0);
+ count += 4;
+ }
+
+ if (count >= 2 && ((long)to & 1) == (from & 1)) {
+ count -= 2;
+ do {
+ *(u16 *)to = readw(from);
+ count -= 2;
+ to += 2;
+ from += 2;
+ } while (count >= 0);
+ count += 2;
+ }
+
+ while (count > 0) {
+ *(u8 *) to = readb(from);
count--;
- *(char *) to = readb(from);
- ((char *) to)++;
+ to++;
from++;
}
}
@@ -377,25 +405,105 @@ void _memcpy_fromio(void * to, unsigned long from, unsigned long count)
* Copy data from "real" memory space to IO memory space.
* This needs to be optimized.
*/
-void _memcpy_toio(unsigned long to, void * from, unsigned long count)
+void _memcpy_toio(unsigned long to, void * from, long count)
{
- while (count) {
+ /* Optimize co-aligned transfers. Everything else gets handled
+ a byte at a time. */
+
+ if (count >= 8 && (to & 7) == ((long)from & 7)) {
+ count -= 8;
+ do {
+ writeq(*(u64 *)from, to);
+ count -= 8;
+ to += 8;
+ from += 8;
+ } while (count >= 0);
+ count += 8;
+ }
+
+ if (count >= 4 && (to & 3) == ((long)from & 3)) {
+ count -= 4;
+ do {
+ writel(*(u32 *)from, to);
+ count -= 4;
+ to += 4;
+ from += 4;
+ } while (count >= 0);
+ count += 4;
+ }
+
+ if (count >= 2 && (to & 1) == ((long)from & 1)) {
+ count -= 2;
+ do {
+ writew(*(u16 *)from, to);
+ count -= 2;
+ to += 2;
+ from += 2;
+ } while (count >= 0);
+ count += 2;
+ }
+
+ while (count > 0) {
+ writeb(*(u8 *) from, to);
count--;
- writeb(*(char *) from, to);
- ((char *) from)++;
to++;
+ from++;
}
}
/*
* "memset" on IO memory space.
- * This needs to be optimized.
*/
-void _memset_io(unsigned long dst, int c, unsigned long count)
+void _memset_c_io(unsigned long to, unsigned long c, long count)
{
- while (count) {
+ /* Handle any initial odd byte */
+ if (count > 0 && (to & 1)) {
+ writeb(c, to);
+ to++;
count--;
- writeb(c, dst);
- dst++;
+ }
+
+ /* Handle any initial odd halfword */
+ if (count >= 2 && (to & 2)) {
+ writew(c, to);
+ to += 2;
+ count -= 2;
+ }
+
+ /* Handle any initial odd word */
+ if (count >= 4 && (to & 4)) {
+ writel(c, to);
+ to += 4;
+ count -= 4;
+ }
+
+ /* Handle all full-sized quadwords: we're aligned (or have a small count) */
+ count -= 8;
+ if (count >= 0) {
+ do {
+ writeq(c, to);
+ to += 8;
+ count -= 8;
+ } while (count >= 0);
+ }
+ count += 8;
+
+ /* The tail is word-aligned if we still have count >= 4 */
+ if (count >= 4) {
+ writel(c, to);
+ to += 4;
+ count -= 4;
+ }
+
+ /* The tail is half-word aligned if we have count >= 2 */
+ if (count >= 2) {
+ writew(c, to);
+ to += 2;
+ count -= 2;
+ }
+
+ /* And finally, one last byte.. */
+ if (count) {
+ writeb(c, to);
}
}
diff --git a/arch/alpha/lib/memset.S b/arch/alpha/lib/memset.S
index dc2075e1f..f39197dee 100644
--- a/arch/alpha/lib/memset.S
+++ b/arch/alpha/lib/memset.S
@@ -18,6 +18,7 @@
.set noreorder
.text
.globl __memset
+ .globl __memsetw
.globl __constant_c_memset
.ent __memset
.align 5
@@ -25,8 +26,8 @@ __memset:
.frame $30,0,$26,0
.prologue 0
- zapnot $17,1,$17 /* E0 */
- sll $17,8,$1 /* E1 (p-c latency, next cycle) */
+ and $17,255,$1 /* E1 */
+ insbl $17,1,$17 /* .. E0 */
bis $17,$1,$17 /* E0 (p-c latency, next cycle) */
sll $17,16,$1 /* E1 (p-c latency, next cycle) */
@@ -52,9 +53,9 @@ __constant_c_memset:
insql $17,$16,$2 /* E0 */
subq $3,8,$3 /* .. E1 */
- addq $18,$3,$18 /* E0 $18 is new count ($3 is negative) */
+ addq $18,$3,$18 /* E0 $18 is new count ($3 is negative) */
mskql $4,$16,$4 /* .. E1 (and possible load stall) */
- subq $16,$3,$16 /* E0 $16 is new aligned destination */
+ subq $16,$3,$16 /* E0 $16 is new aligned destination */
bis $2,$4,$1 /* .. E1 */
bis $31,$31,$31 /* E0 */
@@ -103,6 +104,22 @@ end:
ret $31,($26),1 /* E1 */
.end __memset
+ .align 5
+ .ent __memsetw
+__memsetw:
+ .prologue 0
+
+ inswl $17,0,$1 /* E0 */
+ inswl $17,2,$2 /* E0 */
+ inswl $17,4,$3 /* E0 */
+ or $1,$2,$1 /* .. E1 */
+ inswl $17,6,$4 /* E0 */
+ or $1,$3,$1 /* .. E1 */
+ or $1,$4,$17 /* E0 */
+ br __constant_c_memset /* .. E1 */
+
+ .end __memsetw
+
#ifdef __ELF__
.weak memset; memset = __memset
#else
diff --git a/arch/alpha/lib/strcasecmp.c b/arch/alpha/lib/strcasecmp.c
new file mode 100644
index 000000000..4e57a216f
--- /dev/null
+++ b/arch/alpha/lib/strcasecmp.c
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/alpha/lib/strcasecmp.c
+ */
+
+#include <linux/string.h>
+
+
+/* We handle nothing here except the C locale. Since this is used in
+ only one place, on strings known to contain only 7 bit ASCII, this
+ is ok. */
+
+int strcasecmp(const char *a, const char *b)
+{
+ int ca, cb;
+
+ do {
+ ca = *a++ & 0xff;
+ cb = *b++ & 0xff;
+ if (ca >= 'A' && ca <= 'Z')
+ ca += 'a' - 'A';
+ if (cb >= 'A' && cb <= 'Z')
+ cb += 'a' - 'A';
+ } while (ca == cb && ca != '\0');
+
+ return ca - cb;
+}
diff --git a/arch/alpha/lib/strlen_user.S b/arch/alpha/lib/strlen_user.S
index b84d9a4c3..cdf71158f 100644
--- a/arch/alpha/lib/strlen_user.S
+++ b/arch/alpha/lib/strlen_user.S
@@ -2,7 +2,7 @@
* arch/alpha/lib/strlen_user.S
*
* Return the length of the string including the NUL terminator
- * (strlen+1) or zero if an error occured.
+ * (strlen+1) or zero if an error occurred.
*/
#include <alpha/regdef.h>
diff --git a/arch/alpha/math-emu/fp-emul.c b/arch/alpha/math-emu/fp-emul.c
index 543044019..97f4bc326 100644
--- a/arch/alpha/math-emu/fp-emul.c
+++ b/arch/alpha/math-emu/fp-emul.c
@@ -61,22 +61,33 @@ extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
MODULE_DESCRIPTION("FP Software completion module");
extern long (*alpha_fp_emul_imprecise)(struct pt_regs *, unsigned long);
-static long (*save_emul)(struct pt_regs *, unsigned long);
+extern long (*alpha_fp_emul) (unsigned long pc);
+
+static long (*save_emul_imprecise)(struct pt_regs *, unsigned long);
+static long (*save_emul) (unsigned long pc);
+
long do_alpha_fp_emul_imprecise(struct pt_regs *, unsigned long);
+long do_alpha_fp_emul(unsigned long);
int init_module(void)
{
- save_emul = alpha_fp_emul_imprecise;
+ save_emul_imprecise = alpha_fp_emul_imprecise;
+ save_emul = alpha_fp_emul;
alpha_fp_emul_imprecise = do_alpha_fp_emul_imprecise;
+ alpha_fp_emul = do_alpha_fp_emul;
return 0;
}
void cleanup_module(void)
{
- alpha_fp_emul_imprecise = save_emul;
+ alpha_fp_emul_imprecise = save_emul_imprecise;
+ alpha_fp_emul = save_emul;
}
-#define alpha_fp_emul_imprecise do_alpha_fp_emul_imprecise
+#undef alpha_fp_emul_imprecise
+#define alpha_fp_emul_imprecise do_alpha_fp_emul_imprecise
+#undef alpha_fp_emul
+#define alpha_fp_emul do_alpha_fp_emul
#endif /* MODULE */
@@ -95,6 +106,8 @@ alpha_fp_emul (unsigned long pc)
unsigned long va, vb, vc, res, fpcr;
__u32 insn;
+ MOD_INC_USE_COUNT;
+
get_user(insn, (__u32*)pc);
fc = (insn >> 0) & 0x1f; /* destination register */
func = (insn >> 5) & 0x7ff;
@@ -104,8 +117,8 @@ alpha_fp_emul (unsigned long pc)
va = alpha_read_fp_reg(fa);
vb = alpha_read_fp_reg(fb);
-
fpcr = rdfpcr();
+
/*
* Try the operation in software. First, obtain the rounding
* mode...
@@ -212,8 +225,10 @@ alpha_fp_emul (unsigned long pc)
default:
printk("alpha_fp_emul: unexpected function code %#lx at %#lx\n",
func & 0x3f, pc);
+ MOD_DEC_USE_COUNT;
return 0;
}
+
/*
* Take the appropriate action for each possible
* floating-point result:
@@ -236,8 +251,10 @@ alpha_fp_emul (unsigned long pc)
wrfpcr(fpcr);
/* Do we generate a signal? */
- if (res >> 51 & fpcw & IEEE_TRAP_ENABLE_MASK)
+ if (res >> 51 & fpcw & IEEE_TRAP_ENABLE_MASK) {
+ MOD_DEC_USE_COUNT;
return 0;
+ }
}
/*
@@ -246,6 +263,8 @@ alpha_fp_emul (unsigned long pc)
* result:
*/
alpha_write_fp_reg(fc, vc);
+
+ MOD_DEC_USE_COUNT;
return 1;
}
diff --git a/arch/alpha/mm/fault.c b/arch/alpha/mm/fault.c
index 603b33149..f3a923064 100644
--- a/arch/alpha/mm/fault.c
+++ b/arch/alpha/mm/fault.c
@@ -4,23 +4,30 @@
* Copyright (C) 1995 Linus Torvalds
*/
-#include <linux/signal.h>
#include <linux/sched.h>
-#include <linux/head.h>
#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#define __EXTERN_INLINE inline
+#include <asm/mmu_context.h>
+#include <asm/pgtable.h>
+#undef __EXTERN_INLINE
+
+#include <linux/signal.h>
+#include <linux/head.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ptrace.h>
#include <linux/mman.h>
-#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <asm/system.h>
#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/mmu_context.h>
+
+extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *);
+
#ifdef __SMP__
unsigned long last_asn[NR_CPUS] = { /* gag */
@@ -61,21 +68,26 @@ unsigned long last_asn[NR_CPUS] = { /* gag */
unsigned long asn_cache = ASN_FIRST_VERSION;
#endif /* __SMP__ */
-#ifndef BROKEN_ASN
/*
- * Select a new ASN and reload the context. This is
- * not inlined as this expands to a pretty large
- * function.
+ * Select a new ASN for a task.
*/
-void get_new_asn_and_reload(struct task_struct *tsk, struct mm_struct *mm)
+
+void
+get_new_mmu_context(struct task_struct *p, struct mm_struct *mm)
{
- mm->context = 0;
- get_new_mmu_context(tsk, mm);
- reload_context(tsk);
-}
-#endif
+ unsigned long asn = asn_cache;
-extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *);
+ if ((asn & HARDWARE_ASN_MASK) < MAX_ASN)
+ ++asn;
+ else {
+ tbiap();
+ imb();
+ asn = (asn & ~HARDWARE_ASN_MASK) + ASN_FIRST_VERSION;
+ }
+ asn_cache = asn;
+ mm->context = asn; /* full version + asn */
+ p->tss.asn = asn & HARDWARE_ASN_MASK; /* just asn */
+}
/*
* This routine handles page faults. It determines the address,
@@ -99,23 +111,24 @@ extern void die_if_kernel(char *,struct pt_regs *,long, unsigned long *);
*/
/* Macro for exception fixup code to access integer registers. */
-#define dpf_reg(r) \
- (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 : \
+#define dpf_reg(r) \
+ (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 : \
(r) <= 18 ? (r)+8 : (r)-10])
-asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr,
- long cause, struct pt_regs *regs)
+asmlinkage void
+do_page_fault(unsigned long address, unsigned long mmcsr,
+ long cause, struct pt_regs *regs)
{
struct vm_area_struct * vma;
struct mm_struct *mm = current->mm;
unsigned fixup;
/* As of EV6, a load into $31/$f31 is a prefetch, and never faults
- (or is suppressed by the PALcode). Support that for older cpu's
+ (or is suppressed by the PALcode). Support that for older CPUs
by ignoring such an instruction. */
if (cause == 0) {
- /* No need for get_user.. we know the insn is there. */
- unsigned int insn = *(unsigned int *)regs->pc;
+ unsigned int insn;
+ __get_user(insn, (unsigned int *)regs->pc);
if ((insn >> 21 & 0x1f) == 0x1f &&
/* ldq ldl ldt lds ldg ldf ldwu ldbu */
(1ul << (insn >> 26) & 0x30f00001400ul)) {
@@ -124,8 +137,8 @@ asmlinkage void do_page_fault(unsigned long address, unsigned long mmcsr,
}
}
- lock_kernel();
down(&mm->mmap_sem);
+ lock_kernel();
vma = find_vma(mm, address);
if (!vma)
goto bad_area;
diff --git a/arch/alpha/mm/init.c b/arch/alpha/mm/init.c
index 7562f6709..85b1e3e07 100644
--- a/arch/alpha/mm/init.c
+++ b/arch/alpha/mm/init.c
@@ -28,6 +28,86 @@ extern void show_net_buffers(void);
struct thread_struct * original_pcb_ptr;
+#ifndef __SMP__
+struct pgtable_cache_struct quicklists;
+#endif
+
+void
+__bad_pmd(pgd_t *pgd)
+{
+ printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
+ pgd_set(pgd, BAD_PAGETABLE);
+}
+
+void
+__bad_pte(pmd_t *pmd)
+{
+ printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
+ pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
+}
+
+pmd_t *
+get_pmd_slow(pgd_t *pgd, unsigned long offset)
+{
+ pmd_t *pmd;
+
+ pmd = (pmd_t *) __get_free_page(GFP_KERNEL);
+ if (pgd_none(*pgd)) {
+ if (pmd) {
+ clear_page((unsigned long)pmd);
+ pgd_set(pgd, pmd);
+ return pmd + offset;
+ }
+ pgd_set(pgd, BAD_PAGETABLE);
+ return NULL;
+ }
+ free_page((unsigned long)pmd);
+ if (pgd_bad(*pgd)) {
+ __bad_pmd(pgd);
+ return NULL;
+ }
+ return (pmd_t *) pgd_page(*pgd) + offset;
+}
+
+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((unsigned long)pte);
+ pmd_set(pmd, pte);
+ return pte + offset;
+ }
+ pmd_set(pmd, (pte_t *) BAD_PAGETABLE);
+ return NULL;
+ }
+ free_page((unsigned long)pte);
+ if (pmd_bad(*pmd)) {
+ __bad_pte(pmd);
+ return NULL;
+ }
+ return (pte_t *) pmd_page(*pmd) + offset;
+}
+
+int do_check_pgt_cache(int low, int high)
+{
+ int freed = 0;
+ if(pgtable_cache_size > high) {
+ do {
+ if(pgd_quicklist)
+ free_pgd_slow(get_pgd_fast()), freed++;
+ if(pmd_quicklist)
+ free_pmd_slow(get_pmd_fast()), freed++;
+ if(pte_quicklist)
+ free_pte_slow(get_pte_fast()), freed++;
+ } while(pgtable_cache_size > low);
+ }
+ return freed;
+}
+
/*
* BAD_PAGE is the page that is used for page faults when linux
* is out-of-memory. Older versions of linux just did a
@@ -41,22 +121,25 @@ struct thread_struct * original_pcb_ptr;
* ZERO_PAGE is a special page that is used for zero-initialized
* data and COW.
*/
-pmd_t * __bad_pagetable(void)
+pmd_t *
+__bad_pagetable(void)
{
memset((void *) EMPTY_PGT, 0, PAGE_SIZE);
return (pmd_t *) EMPTY_PGT;
}
-pte_t __bad_page(void)
+pte_t
+__bad_page(void)
{
memset((void *) EMPTY_PGE, 0, PAGE_SIZE);
return pte_mkdirty(mk_pte((unsigned long) EMPTY_PGE, PAGE_SHARED));
}
-void show_mem(void)
+void
+show_mem(void)
{
- int i,free = 0,total = 0,reserved = 0;
- int shared = 0;
+ long i,free = 0,total = 0,reserved = 0;
+ long shared = 0, cached = 0;
printk("\nMem-info:\n");
show_free_areas();
@@ -66,15 +149,19 @@ void show_mem(void)
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 free pages\n",free);
- printk("%d reserved pages\n",reserved);
- printk("%d pages shared\n",shared);
+ printk("%ld pages of RAM\n",total);
+ printk("%ld free pages\n",free);
+ printk("%ld reserved pages\n",reserved);
+ printk("%ld pages shared\n",shared);
+ printk("%ld pages swap cached\n",cached);
+ printk("%ld pages in page table cache\n",pgtable_cache_size);
show_buffers();
#ifdef CONFIG_NET
show_net_buffers();
@@ -83,29 +170,20 @@ void show_mem(void)
extern unsigned long free_area_init(unsigned long, unsigned long);
-static struct thread_struct * load_PCB(struct thread_struct * pcb)
+static struct thread_struct *
+load_PCB(struct thread_struct * pcb)
{
- struct thread_struct *old_pcb;
-
- __asm__ __volatile__(
- "stq $30,0(%1)\n\t"
- "bis %1,%1,$16\n\t"
-#ifdef CONFIG_ALPHA_DP264
- "zap $16,0xe0,$16\n\t"
-#endif /* DP264 */
- "call_pal %2\n\t"
- "bis $0,$0,%0"
- : "=r" (old_pcb)
- : "r" (pcb), "i" (PAL_swpctx)
- : "$0", "$1", "$16", "$22", "$23", "$24", "$25");
- return old_pcb;
+ register unsigned long sp __asm__("$30");
+ pcb->ksp = sp;
+ return __reload_tss(pcb);
}
/*
* paging_init() sets up the page tables: in the alpha version this actually
* unmaps the bootup page table (as we're now in KSEG, so we don't need it).
*/
-unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
+unsigned long
+paging_init(unsigned long start_mem, unsigned long end_mem)
{
int i;
unsigned long newptbr;
@@ -162,7 +240,8 @@ printk("OKSP 0x%lx OPTBR 0x%lx\n",
* note that current should be pointing at the idle thread task struct
* for this CPU.
*/
-void paging_init_secondary(void)
+void
+paging_init_secondary(void)
{
current->tss.ptbr = init_task.tss.ptbr;
current->tss.pal_flags = 1;
@@ -180,7 +259,8 @@ printk("paging_init_secondary: KSP 0x%lx PTBR 0x%lx\n",
}
#endif /* __SMP__ */
-void mem_init(unsigned long start_mem, unsigned long end_mem)
+void
+mem_init(unsigned long start_mem, unsigned long end_mem)
{
unsigned long tmp;
@@ -211,22 +291,24 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
return;
}
-void free_initmem (void)
+void
+free_initmem (void)
{
- extern char __init_begin, __init_end;
- unsigned long addr;
-
- addr = (unsigned long)(&__init_begin);
- for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
- mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
- atomic_set(&mem_map[MAP_NR(addr)].count, 1);
- free_page(addr);
- }
- printk ("Freeing unused kernel memory: %ldk freed\n",
+ extern char __init_begin, __init_end;
+ unsigned long addr;
+
+ addr = (unsigned long)(&__init_begin);
+ for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+ mem_map[MAP_NR(addr)].flags &= ~(1 << PG_reserved);
+ atomic_set(&mem_map[MAP_NR(addr)].count, 1);
+ free_page(addr);
+ }
+ printk ("Freeing unused kernel memory: %ldk freed\n",
(&__init_end - &__init_begin) >> 10);
}
-void si_meminfo(struct sysinfo *val)
+void
+si_meminfo(struct sysinfo *val)
{
int i;