Linux 5.4.163 with MCST patches (2.23)

This commit is contained in:
Nobody 2022-08-11 22:29:58 +03:00 committed by Alibek Omarov
parent c98ea5e20a
commit 5a2e97a12d
3437 changed files with 1410016 additions and 1426 deletions

View File

@ -0,0 +1,101 @@
====
AltHa
====
AltHa is a Linux Security Module currently has three userspace hardening options:
* ignore SUID on binaries (with exceptions possible);
* prevent running selected script interpreters in interactive mode;
* disable open file unlinking in selected dirs.
* enable kiosk mode
It is selectable at build-time with ``CONFIG_SECURITY_ALTHA``, and should be
enabled in runtime by command line option ``altha=1`` and configured
through sysctls in ``/proc/sys/kernel/altha``.
NoSUID
============
Modern Linux systems can be used with minimal (or even zero at least for OWL and ALT) usage of SUID programms, but in many cases in full-featured desktop or server systems there are plenty of them: uncounted and sometimes unnecessary. Privileged programms are always an attack surface, but mounting filesystems with ``nosuid`` flag doesn't provide enough granularity in SUID binaries management. This LSM module provides a single control point for all SUID binaries. When this submodule is enabled, SUID bits on all binaries except explicitly listed are system-wide ignored.
Sysctl parameters and defaults:
* ``kernel.altha.nosuid.enabled = 0``, set to 1 to enable
* ``kernel.altha.nosuid.exceptions =``, colon-separated list of enabled SUID binaries, for example: ``/bin/su:/usr/libexec/hasher-priv/hasher-priv``
RestrScript
============
There is a one way to hardening: prevent users from executing ther own arbitrary code. Traditionally it can be done setting on user-writable filesystems ``noexec`` flag. But modern script languages such as Python also can be used to write exploits or even load arbitary machine code via ``dlopen`` and users can start scripts from ``noexec`` filesystem starting interpreter directly.
Restrscript LSM submodule provides a way to restrict some programms to be executed directly, but allows to execute them as shebang handler.
Sysctl parameters and defaults:
* ``kernel.altha.rstrscript.enabled = 0``, set to 1 to enable
* ``kernel.altha.rstrscript.interpreters =``, colon-separated list of restricted interpreters for example: ``/lib64/ld-linux-x86-64.so.2:/usr/bin/python:/usr/bin/python3:/usr/bin/perl:/usr/bin/tclsh``. Symlinks are supported in both ways: you can set symlink to interpreter as exception and interpreter and all symlinks on it will be restricted.
Adding ld-linux into blocking list prevents running interpreters via ``ld-linux interpreter``.
Note: in this configuration all scripts starting with ``#!/usr/bin/env python`` will be blocked.
OLock
============
Unlink disabling for open files needed for Russian certification, but this is a nasty feature leading to DOS.
Sysctl parameters and defaults:
* ``kernel.altha.olock.enabled = 0``, set to 1 to enable
* ``kernel.altha.olock.dirs =``, colon-separated list of dirs, for example: ``/var/lib/something:/tmp/something``.
Kiosk
===========
Disable execution for everything and everyone (including system users
and root, if required) except given whitelists.
Kiosk interface uses generic netlink framework.
Interface name: ``altha``
Kiosk packet attributes::
static struct nla_policy kiosk_attrs_policy[KIOSK_MAX_ATTR] = {
[KIOSK_ACTION] = {
.type = NLA_S16,
},
[KIOSK_DATA] = {
.type = NLA_STRING,
.maxlen = MAX_DATA /* 1024 */
},
};
Possible kiosk modes::
enum kiosk_mode {
KIOSK_PERMISSIVE = 0, /* kiosk is disabled */
KIOSK_NONSYSTEM, /* kiosk is enabled for users with uid >= 500 */
KIOSK_ALL, /* kiosk is enabled for all users */
};
In ``KIOSK_ALL`` mode root will be restricted if running from tty
Otherwise application will be executed anyway,
enabling the system to boot without garbage in whitelists.
Possible kiosk actions::
enum altha_kiosk_action {
KIOSK_SET_MODE = 0, /* set or get mode, see below */
KIOSK_USERLIST_ADD, /* add app to user whitelist */
KIOSK_USERLIST_DEL, /* remove app from user whitelist */
KIOSK_SYSLIST_ADD, /* add app to system whitelist */
KIOSK_SYSLIST_DEL, /* remove app from system whitelist */
KIOSK_USER_LIST, /* retrieve user whitelist, see below */
KIOSK_SYSTEM_LIST, /* retrieve system whitelist */
};
``KIOSK_ACTION`` attribute is used.
``SET_MODE`` action will send current mode if ``KIOSK_DATA`` is empty.
When ``KIOSK_USER_LIST`` or ``KIOSK_SYSTEM_LIST`` action is requested, kernel sends
the first item from the list and waits for another request.
When end of list is reached, it sends an empty string and it will be safe
for client to request another list.
``LD_*`` cheats will not be applied when kiosk is activated.

View File

@ -47,3 +47,4 @@ subdirectories.
tomoyo
Yama
SafeSetID
AltHa

View File

@ -3425,6 +3425,14 @@
nomsi [MSI] If the PCI_MSI kernel config parameter is
enabled, this kernel boot option can be used to
disable the use of MSI interrupts system-wide.
pci_acs_override [PCIE] Override missing PCIe ACS support for:
downstream
All downstream ports - full ACS capabilities
multifunction
Add multifunction devices - multifunction ACS subset
id:nnnn:nnnn
Specific device - full ACS capabilities
Specified as vid:did (vendor/device ID) in hex
noioapicquirk [APIC] Disable all boot interrupt quirks.
Safety option to keep boot IRQs enabled. This
should never be necessary.

View File

@ -0,0 +1,60 @@
EMC2305 (I2C)
This device is a RPM-based PWM Fan Speed Controller for up to 5 fans.
Each fan can beconfigured individually:
- pwm-enable defines the PWM mode:
0: PWM is disabled
3: RPM based PWM
- fan-div sets the fan divisor (for RPM mesaurement)
1, 2 ,4 or 8
- fan-target sets the target RPM speed (for RPM based PWM mode)
max 16000 (according to data sheet)
1) The /emc2305 node
Required properties:
- compatible : must be "smsc,emc2305"
- reg : I2C bus address of the device
- #address-cells : must be <1>
- #size-cells : must be <0>
The node may contain child nodes for each fan that the platform uses.
If no child nodes are given, all possible fan control channels are exposed.
If at least one child node is given, only the configured fans are exposed.
Example EMC2305 node:
emc2305@2C {
compatible = "smsc,emc2305";
reg = <0x2C>;
#address-cells = <1>;
#size-cells = <0>;
[ child node definitions... ]
}
2) fan nodes
Required properties:
- reg : the fan number (0 based)
Optional properties:
- fan-div : the fan divisor setting
- fan-target : the fan target speed
- pwm-enable : PWM mode
Example EMC2305 fan node:
fan@1 {
reg = <1>;
fan-div = <4>;
pwm-enable = <0>;
};

View File

@ -0,0 +1,33 @@
Kernel driver emc2305
=====================
Supported chips:
* SMSC EMC2305, EMC2303, EMC2302, EMC2301
Adresses scanned: I2C 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d
Prefixes: 'emc2305', 'emc2303', 'emc2302', 'emc2301'
Datasheet: Publicly available at the SMSC website :
http://www.smsc.com/Products/Thermal_and_Power_Management/Fan_Controllers
Authors:
Reinhard Pfau, Guntermann & Drunck GmbH <pfau@gdsys.de>
Description
-----------
The SMSC EMC2305 is a fan controller for up to 5 fans.
The EMC2303 has the same functionality but supports only up to 3 fans.
The EMC2302 supports 2 fans and the EMC2301 1 fan. These chips support less
possible I2C addresses.
Fan rotation speeds are reported in RPM.
The driver supports the RPM based PWM control to keep a fan at a desired speed.
To enable this function for a fan, write 3 to pwm<num>_enable and the desired
fan speed to fan<num>_target.
Devicetree
----------
Configuration is also possible via devicetree:
Documentation/devicetree/bindings/hwmon/emc2305.txt

View File

@ -14975,6 +14975,14 @@ S: Maintained
F: Documentation/hwmon/emc2103.rst
F: drivers/hwmon/emc2103.c
SMSC EMC2305 HARDWARE MONITOR DRIVER
M: Reinhard Pfau <pfau@gdsys.de>
L: lm-sensors@lm-sensors.org
S: Maintained
F: Documentation/hwmon/emc2305
F: Documentation/devicetree/bindings/hwmon/emc2305.txt
F: drivers/mcst/emc/emc2305.c
SMSC SCH5627 HARDWARE MONITOR DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: linux-hwmon@vger.kernel.org
@ -15401,6 +15409,14 @@ M: H Hartley Sweeten <hsweeten@visionengravers.com>
S: Odd Fixes
F: drivers/staging/comedi/
STAGING - CRYSTAL HD VIDEO DECODER
M: Naren Sankar <nsankar@broadcom.com>
M: Jarod Wilson <jarod@wilsonet.com>
M: Scott Davilla <davilla@4pi.com>
M: Manu Abraham <abraham.manu@gmail.com>
S: Odd Fixes
F: drivers/staging/crystalhd/
STAGING - FIELDBUS SUBSYSTEM
M: Sven Van Asbroeck <TheSven73@gmail.com>
S: Maintained
@ -16690,6 +16706,15 @@ F: include/linux/visorbus.h
F: drivers/visorbus/
F: drivers/staging/unisys/
UNION FILE SYSTEM
M: Erez Zadok <ezk@cs.sunysb.edu>
L: unionfs@filesystems.org
W: http://unionfs.filesystems.org/
T: git git://git.fsl.cs.sunysb.edu/unionfs-latest.git
S: Maintained
F: Documentation/filesystems/unionfs/
F: fs/unionfs/
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER
R: Alim Akhtar <alim.akhtar@samsung.com>
R: Avri Altman <avri.altman@wdc.com>

View File

@ -2,7 +2,7 @@
VERSION = 5
PATCHLEVEL = 4
SUBLEVEL = 163
EXTRAVERSION =
EXTRAVERSION = -2.23
NAME = Kleptomaniac Octopus
# *DOCUMENTATION*
@ -422,6 +422,16 @@ OBJSIZE = llvm-size
STRIP = llvm-strip
else
CC = $(CROSS_COMPILE)gcc
ifeq ($(call cc-lcc-yn),y)
LD := $(shell $(CC) -print-prog-name=ld)
AR := $(shell $(CC) -print-prog-name=ar)
NM := $(shell $(CC) -print-prog-name=nm)
OBJCOPY := $(shell $(CC) -print-prog-name=objcopy)
OBJDUMP := $(shell $(CC) -print-prog-name=objdump)
READELF := $(shell $(CC) -print-prog-name=readelf)
OBJSIZE := $(shell $(CC) -print-prog-name=size)
STRIP := $(shell $(CC) -print-prog-name=strip)
else
LD = $(CROSS_COMPILE)ld
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
@ -431,6 +441,7 @@ READELF = $(CROSS_COMPILE)readelf
OBJSIZE = $(CROSS_COMPILE)size
STRIP = $(CROSS_COMPILE)strip
endif
endif
PAHOLE = pahole
LEX = flex
YACC = bison
@ -447,7 +458,7 @@ KBZIP2 = bzip2
KLZOP = lzop
LZMA = lzma
LZ4 = lz4c
XZ = xz
XZ = xz
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
-Wbitwise -Wno-return-void -Wno-unknown-attribute $(CF)
@ -459,6 +470,8 @@ CFLAGS_KERNEL =
AFLAGS_KERNEL =
LDFLAGS_vmlinux =
-include .kernelvariables
# Use USERINCLUDE when you must reference the UAPI directories only.
USERINCLUDE := \
-I$(srctree)/arch/$(SRCARCH)/include/uapi \
@ -477,11 +490,22 @@ LINUXINCLUDE := \
$(USERINCLUDE)
KBUILD_AFLAGS := -D__ASSEMBLY__ -fno-PIE
ifeq ($(call cc-lcc-yn),y)
# Although lcc-1.24 supports -fshort-wchar many users are still
# using lcc-1.23, so when they compile kernel modules themselves
# we must avoid passing "-fshort-wchar" to it.
KBUILD_CFLAGS := -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE \
-fno-strict-aliasing -fno-common -fno-PIE \
-Werror=implicit-function-declaration -Werror=implicit-int \
-Werror=return-type -Wno-format-security \
-std=gnu89
else
KBUILD_CFLAGS := -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE \
-Werror=implicit-function-declaration -Werror=implicit-int \
-Wno-format-security \
-std=gnu89
endif
KBUILD_CPPFLAGS := -D__KERNEL__
KBUILD_AFLAGS_KERNEL :=
KBUILD_CFLAGS_KERNEL :=
@ -649,9 +673,14 @@ endif # KBUILD_EXTMOD
# Defaults to vmlinux, but the arch makefile usually adds further targets
all: vmlinux
ifneq ($(call cc-lcc-yn),y)
CFLAGS_GCOV := -fprofile-arcs -ftest-coverage \
$(call cc-option,-fno-tree-loop-im) \
$(call cc-disable-warning,maybe-uninitialized,)
else
CFLAGS_GCOV := -fprofile-arcs -ftest-coverage \
$(call cc-disable-warning,maybe-uninitialized,)
endif
export CFLAGS_GCOV
# The arch Makefiles can override CC_FLAGS_FTRACE. We may also append it later.
@ -890,8 +919,13 @@ KBUILD_CFLAGS += $(call cc-disable-warning, restrict)
# Enabled with W=2, disabled by default as noisy
KBUILD_CFLAGS += $(call cc-disable-warning, maybe-uninitialized)
# MCST: The original gcc bug which caused introduction of -fno-strict-overflow
# (optimizing away pointer overflow checking) does not exist in lcc, and this
# option prohibits many compiler optimizations.
ifneq ($(call cc-lcc-yn),y)
# disable invalid "can't wrap" optimizations for signed / pointers
KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow)
endif
# clang sets -fmerge-all-constants by default as optimization, but this
# is non-conforming behavior for C and in fact breaks the kernel, so we
@ -1036,7 +1070,7 @@ PHONY += prepare0
export MODORDER := $(extmod-prefix)modules.order
ifeq ($(KBUILD_EXTMOD),)
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ ltt/
vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
$(core-y) $(core-m) $(drivers-y) $(drivers-m) \

View File

@ -60,6 +60,9 @@ config OPROFILE_NMI_TIMER
def_bool y
depends on PERF_EVENTS && HAVE_PERF_EVENTS_NMI && !PPC64
config HAVE_EL_POSIX_SYSCALL
bool
config KPROBES
bool "Kprobes"
depends on MODULES

3
arch/e2k/3p/Makefile Normal file
View File

@ -0,0 +1,3 @@
subdir-ccflags-y := -Werror -Wswitch -Wenum-compare
obj-y := global_sp.o umalloc.o binfmt_elf32_3P.o binfmt_elf64_3P.o

View File

@ -0,0 +1,38 @@
#include <linux/elfcore-compat.h>
#include <linux/irqflags.h>
typedef Elf32_Dyn elf_dyntab_entry_t;
#define sys_load_cu sys_load_cu_elf32_3P
#define sys_unload_cu sys_unload_cu_elf32_3P
#define ELF_CL_SZ 32
#define DEBUG_PROTECTED_ELFLOADER 0
#define DBPL if (DEBUG_PROTECTED_ELFLOADER) printk
/*
* Rename the basic ELF layout types to refer to the 32-bit class of files.
*/
#undef ELF_CLASS
#define ELF_CLASS ELFCLASS32
#undef elfhdr
#undef elf_phdr
#undef elf_note
#undef elf_addr_t
#define elfhdr elf32_hdr
#define elf_phdr elf32_phdr
#define elf_note elf32_note
#define elf_addr_t Elf32_Addr
/*
* Rename a few of the symbols that binfmt_elfe2kp.c will define.
* These are all local so the names don't really matter, but it
* might make some debugging less confusing not to duplicate them.
*/
#define elf_format protected_32_elf_format
#define init_elf_binfmt init_protected_32_elf_binfmt
#define exit_elf_binfmt exit_protected_32_elf_binfmt
#include "./binfmt_elfe2kp.c"

View File

@ -0,0 +1,18 @@
#include <linux/elf.h>
typedef Elf64_Dyn elf_dyntab_entry_t;
#define sys_load_cu sys_load_cu_elf64_3P
#define sys_unload_cu sys_unload_cu_elf64_3P
#define ELF_CL_SZ 64
#define DEBUG_PROTECTED_ELFLOADER 0
#define DBPL if (DEBUG_PROTECTED_ELFLOADER) printk
#define elf_format protected_64_elf_format
#define init_elf_binfmt init_protected_64_elf_binfmt
#define exit_elf_binfmt exit_protected_64_elf_binfmt
#include "./binfmt_elfe2kp.c"

1348
arch/e2k/3p/binfmt_elfe2kp.c Normal file

File diff suppressed because it is too large Load Diff

1593
arch/e2k/3p/global_sp.c Normal file

File diff suppressed because it is too large Load Diff

1130
arch/e2k/3p/umalloc.c Normal file

File diff suppressed because it is too large Load Diff

1248
arch/e2k/Kconfig Normal file

File diff suppressed because it is too large Load Diff

51
arch/e2k/Kconfig.debug Normal file
View File

@ -0,0 +1,51 @@
config TRACE_IRQFLAGS_SUPPORT
def_bool y
config E2K_DEBUG_KERNEL
bool "Enable e2k arch kernel debugging"
depends on DEBUG_KERNEL
default y
config NESTED_PAGE_FAULT_INJECTION
bool "Inject nested page faults when handling trap cellar"
depends on E2K_DEBUG_KERNEL && DEBUG_FS
default n
help
Makes do_page_fault() return success without doing anything with
some probability. This way recovery operation will fail, and the
code path in nested page fault handler will be tested.
config DEBUG_LCC_VOLATILE_ATOMIC
bool "Mark GNU asm with atomic operations as volatile"
depends on E2K_DEBUG_KERNEL
default n
config DEBUG_IRQ
bool "Check of IRQ enabled/disabled using both PSR & UPSR"
depends on E2K_DEBUG_KERNEL
default n
config DEBUG_PT_REGS
bool "Enable checker of pt_regs structure linking"
depends on E2K_DEBUG_KERNEL
default n
config DEBUG_KMEM_AREA
bool "Enable checker of kernel memory area getting and freeing"
depends on E2K_DEBUG_KERNEL
default n
config DEBUG_STACK_USAGE
bool "Stack utilization instrumentation"
depends on DEBUG_KERNEL
help
Enables the display of the minimum amount of free stack which each
task has ever had available in the sysrq-T and sysrq-P debug output.
This option will slow down process creation somewhat.
config ARCH_SUPPORTS_DEBUG_PAGEALLOC
def_bool y
source "arch/l/Kconfig.debug"

22
arch/e2k/Kconfig.virt Normal file
View File

@ -0,0 +1,22 @@
#
# Virtualiztion configuration
#
menuconfig VIRTUALIZATION
bool "Virtualization"
default n
---help---
Say Y here to get to see options for using your Linux host to run other
operating systems inside virtual machines (guests).
This option alone does not add any kernel code.
If you say N, all options in this submenu will be skipped and disabled.
if VIRTUALIZATION
source "arch/e2k/kvm/Kconfig"
select VIRTIO
source "drivers/virtio/Kconfig"
endif # VIRTUALIZATION

252
arch/e2k/Makefile Normal file
View File

@ -0,0 +1,252 @@
# e2k/Makefile
#
# This file is included by the global makefile so that you can add your own
# architecture-specific flags and dependencies. Remember to do have actions
# for "archclean" and "archdep" for cleaning up and making dependencies for
# this architecture
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
KBUILD_DEFCONFIG ?= defconfig
AS = $(shell $(CC) -print-prog-name=as)
OBJDUMP = $(shell $(CC) -print-prog-name=objdump)
LD = $(shell $(CC) -print-prog-name=ld)
OBJCOPY = $(shell $(CC) -print-prog-name=objcopy)
KBUILD_CFLAGS += -fkernel -gline -masm-inline $(call cc-option,-fforbid-fp) \
$(call cc-option,-fmax-errors=5) $(call cc-option,-fno-loop-apb) \
-fno-ident
ifeq ($(PROFILE_GENERATE), 1)
KBUILD_CFLAGS += -fprofile-generate-kernel
endif
ifeq ($(origin PROFILE_USE), undefined)
else
KBUILD_CFLAGS += -fprofile-use="$(PROFILE_USE)"
endif
KBUILD_CFLAGS += $(call cc-option,-finline-functions,) \
$(call cc-option,-finline-functions-called-once,)
# Some uninteresting or broken warnings can be disabled with #pragma's only
KBUILD_CFLAGS += -Wno-array-bounds -Wno-duplicate-type-qualifier \
-Wno-builtin-functions-redefined -Wno-reduced-alignment \
-Wno-unused-value -Wno-overflow -Wno-signed-one-bit-field \
-include $(srctree)/arch/e2k/include/asm/override-lcc-warnings.h
LDFLAGS_vmlinux :=
CHECKFLAGS += -D__e2k__
CFLAGS += -pipe -D__linux__
KBUILD_CFLAGS += $(CFLAGS)
ifdef CONFIG_SMP_DAM_BUG
KBUILD_CFLAGS += -fno-dam-call
endif
CFLAGS_GENERIC := -march=elbrus-v$(CONFIG_E2K_MINVER)
CFLAGS_ES2 := -mtune=elbrus-2c+
CFLAGS_E2S := -mtune=elbrus-4c
CFLAGS_E8C := -mtune=elbrus-8c
CFLAGS_E1CP := -mtune=elbrus-1c+
CFLAGS_E8C2 := -mtune=elbrus-8c2
CFLAGS_E12C := -mtune=elbrus-12c
CFLAGS_E16C := -mtune=elbrus-16c
CFLAGS_E2C3 := -mtune=elbrus-2c3
CFLAGS_ALL_CPUS := $(CFLAGS_ES2) $(CFLAGS_E2S) $(CFLAGS_E8C) $(CFLAGS_E1CP) \
$(CFLAGS_E8C2) $(CFLAGS_E12C) $(CFLAGS_E16C) $(CFLAGS_E2C3)
export CFLAGS_ALL_CPUS
CFLAGS_E2K_SIC := $(CFLAGS_ES2)
export CFLAGS_ES2 CFLAGS_E2S CFLAGS_E8C CFLAGS_E1CP CFLAGS_E8C2 CFLAGS_E2C3 \
CFLAGS_E12C CFLAGS_E16C CFLAGS_E2K_SIC
ifeq ($(CONFIG_E2K_MACHINE),y)
ifeq ($(CONFIG_E2K_ES2_DSP),y)
KBUILD_CFLAGS += $(CFLAGS_ES2)
KBUILD_AFLAGS += $(CFLAGS_ES2)
TARGET_MDL := 04
else
ifeq ($(CONFIG_E2K_ES2_RU),y)
KBUILD_CFLAGS += $(CFLAGS_ES2)
KBUILD_AFLAGS += $(CFLAGS_ES2)
TARGET_MDL := 06
else
ifeq ($(CONFIG_E2K_E2S),y)
KBUILD_CFLAGS += $(CFLAGS_E2S)
KBUILD_AFLAGS += $(CFLAGS_E2S)
TARGET_MDL := 03
else
ifeq ($(CONFIG_E2K_E8C),y)
KBUILD_CFLAGS += $(CFLAGS_E8C)
KBUILD_AFLAGS += $(CFLAGS_E8C)
TARGET_MDL := 07
else
ifeq ($(CONFIG_E2K_E1CP),y)
KBUILD_CFLAGS += $(CFLAGS_E1CP)
KBUILD_AFLAGS += $(CFLAGS_E1CP)
TARGET_MDL := 08
else
ifeq ($(CONFIG_E2K_E8C2),y)
KBUILD_CFLAGS += $(CFLAGS_E8C2)
KBUILD_AFLAGS += $(CFLAGS_E8C2)
TARGET_MDL := 09
else
ifeq ($(CONFIG_E2K_E12C),y)
KBUILD_CFLAGS += $(CFLAGS_E12C)
KBUILD_AFLAGS += $(CFLAGS_E12C)
TARGET_MDL := 0a
else
ifeq ($(CONFIG_E2K_E16C),y)
KBUILD_CFLAGS += $(CFLAGS_E16C)
KBUILD_AFLAGS += $(CFLAGS_E16C)
TARGET_MDL := 0b
else
ifeq ($(CONFIG_E2K_E2C3),y)
KBUILD_CFLAGS += $(CFLAGS_E2C3)
KBUILD_AFLAGS += $(CFLAGS_E2C3)
TARGET_MDL := 0c
else
error "Invalid e2k machine type"
endif # ifeq ($(CONFIG_E2K_E2C3),y)
endif # ifeq ($(CONFIG_E2K_E16C),y)
endif # ifeq ($(CONFIG_E2K_E12C),y)
endif # ifeq ($(CONFIG_E2K_E8C2),y)
endif # ifeq ($(CONFIG_E2K_E1CP),y)
endif # ifeq ($(CONFIG_E2K_E8C),y)
endif # ifeq ($(CONFIG_E2K_E2S),y)
endif # ifeq ($(CONFIG_E2K_ES2_RU),y)
endif # ifeq ($(CONFIG_E2K_ES2_DSP),y)
else # ! ifeq ($(CONFIG_E2K_MACHINE),y)
KBUILD_CFLAGS += $(CFLAGS_GENERIC)
KBUILD_AFLAGS += $(CFLAGS_GENERIC)
TARGET_MDL := 00
endif
KBUILD_LDFLAGS += --relaxed-e2k-machine-check
KBUILD_CFLAGS += $(cflags-y)
libs-y += arch/e2k/lib/
core-y += arch/e2k/kernel/ \
arch/e2k/mm/ \
arch/e2k/p2v/ \
arch/e2k/fast_syscalls/
core-$(CONFIG_PROTECTED_MODE) += arch/e2k/3p/
drivers-$(CONFIG_PCI) += arch/e2k/pci/
# suspend and hibernation support
drivers-$(CONFIG_PM) += arch/e2k/power/
#KVM hypervisor and guest support
core-$(CONFIG_KVM) += arch/e2k/kvm/
# Elbrus common modules
core-y += arch/l/
drivers-$(CONFIG_PCI) += arch/l/pci/
boot := arch/e2k/boot
all: es2boot
MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
.PHONY: clean archclean archmrproper archdep bootimage image zImage
es2boot: vmlinux
$(Q)$(MAKE) $(build)=$(boot) CONFIG_ES2=y boot
e2sboot: vmlinux
$(Q)$(MAKE) $(build)=$(boot) CONFIG_E2S=y boot
e8cboot: vmlinux
$(Q)$(MAKE) $(build)=$(boot) CONFIG_E8C=y boot
e1cpboot: vmlinux
$(Q)$(MAKE) $(build)=$(boot) CONFIG_E1CP=y boot
e8c2boot: vmlinux
$(Q)$(MAKE) $(build)=$(boot) CONFIG_E8C2=y CONFIG_E8C=y boot
e12cboot: vmlinux
$(Q)$(MAKE) $(build)=$(boot) CONFIG_E12C=y boot
e16cboot: vmlinux
$(Q)$(MAKE) $(build)=$(boot) CONFIG_E16C=y boot
e2c3boot: vmlinux
$(Q)$(MAKE) $(build)=$(boot) CONFIG_E2C3=y boot
image: vmlinux
$(Q)$(MAKE) $(build)=$(boot) CONFIG_BOOT=y $(objtree)/image.boot
$(Q)echo "Target mdl: $(TARGET_MDL)"; \
echo $(TARGET_MDL) | \
xxd -r -p | \
dd of=$(objtree)/image.boot bs=1 seek=258 count=1 conv=notrunc 2>/dev/null; \
echo 00000000 | xxd -r -p | \
dd of=$(objtree)/image.boot bs=1 seek=1588 count=4 conv=notrunc 2>/dev/null; \
e2k_kernel_csum=`cksum $(objtree)/image.boot | awk '{ printf "%08x\n", $$1 }'`; \
echo "Kernel image check sum: $$e2k_kernel_csum"; \
echo $$e2k_kernel_csum | \
sed 's/\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)/\7\8\5\6\3\4\1\2/' | \
xxd -r -p | \
dd of=$(objtree)/image.boot bs=1 seek=1588 count=4 conv=notrunc 2>/dev/null; \
echo 'Kernel: image.boot is ready' ' (#'`cat .version`')'
zImage: vmlinux
$(Q)$(MAKE) $(build)=$(boot) CONFIG_BOOT=y $(objtree)/zImage
$(Q)echo "Target mdl: $(TARGET_MDL)"; \
echo $(TARGET_MDL) | \
xxd -r -p | \
dd of=$(objtree)/zImage bs=1 seek=258 count=1 conv=notrunc 2>/dev/null; \
echo 00000000 | xxd -r -p | \
dd of=$(objtree)/zImage bs=1 seek=1588 count=4 conv=notrunc 2>/dev/null; \
e2k_kernel_csum=`cksum $(objtree)/zImage | awk '{ printf "%08x\n", $$1 }'`; \
echo "Kernel image check sum: $$e2k_kernel_csum"; \
echo $$e2k_kernel_csum | \
sed 's/\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)/\7\8\5\6\3\4\1\2/' | \
xxd -r -p | \
dd of=$(objtree)/zImage bs=1 seek=1588 count=4 conv=notrunc 2>/dev/null; \
echo 'Kernel: zImage is ready' ' (#'`cat .version`')'
image.boot: bootimage
bootimage: image
archclean:
$(Q)$(MAKE) $(clean)=arch/e2k/boot
archmrproper:
archdep:
@$(MAKEBOOT) dep
install-headers:
@$(MAKEBOOT) install-headers
install-includes: include/linux/version.h arch/e2k/include FORCE
$(CONFIG_SHELL) scripts/gen-osl-include -l $(srctree) -r $(ROOT_WA)
build-install: FORCE
$(CONFIG_SHELL) scripts/gen-osl-build -l $(srctree) -m $(MODLIB)
define archhelp
echo '* image/bootimage - Kernel boot image (image.boot)'
echo ' zImage - Compressed kernel boot image (image.boot)'
echo ' install-headers - Install kernel headers in '
echo ' <basedir>/usr/include'
echo ' es2boot - Build kernel boot image with small embedded boot for es2 simulator'
echo ' e2sboot - Build kernel boot image with small embedded boot for e2s simulator'
echo ' e8cboot - Build kernel boot image with small embedded boot for e8c simulator'
echo ' e1cpboot - Build kernel boot image with small embedded boot for e1cp simulator'
echo ' e8c2boot - Build kernel boot image with small embedded boot for e8c2 simulator'
echo ' e12cboot - Build kernel boot image with small embedded boot for e12c simulator'
echo ' e16cboot - Build kernel boot image with small embedded boot for e16c simulator'
echo ' e2c3boot - Build kernel boot image with small embedded boot for e2c3 simulator'
echo ' [with_kernel=1] - When building boot, build in compressed kernel into the boot image'
endef

5
arch/e2k/boot/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
image
bimage
cimage
image.bios
System.map

237
arch/e2k/boot/Am85C30.c Normal file
View File

@ -0,0 +1,237 @@
#include <linux/pci_ids.h>
#include <asm/e2k_api.h>
#include <asm/e2k.h>
#include <asm/bootinfo.h>
#include "bios/pci.h"
#include "bios/bios.h"
#include "bios/southbridge.h"
#include "Am85C30.h"
#undef DEBUG_CONSOLE_MODE
#undef DebugC
#define DEBUG_CONSOLE_MODE 0 /* Console initialization */
#define DebugC if (DEBUG_CONSOLE_MODE) printk
#define PCI_DEVICE_ID_PAR_SER 0x8000
#ifdef CONFIG_EIOH
#define PCI_DEV_ID_SERIAL PCI_DEVICE_ID_MCST_SERIAL
#define SERIAL_BAR 0
#else
#define PCI_DEV_ID_SERIAL PCI_DEVICE_ID_MCST_PARALLEL_SERIAL
#define SERIAL_BAR 1
#endif
unsigned long com_port;
unsigned long ch_a_control;
unsigned long ch_a_data;
unsigned long ch_b_control;
unsigned long ch_b_data;
#define NOT_BIOS 0
extern boot_info_t *boot_info;
static void com_outb(u64 port, u8 byte)
{
NATIVE_WRITE_MAS_B(port, byte, MAS_IOADDR);
}
static u8 com_inb(u64 port)
{
return NATIVE_READ_MAS_B(port, MAS_IOADDR);
}
static u8 com_inb_command(u64 port, u8 reg_num)
{
NATIVE_WRITE_MAS_B(port, reg_num, MAS_IOADDR);
return NATIVE_READ_MAS_B(port, MAS_IOADDR);
}
static void com_outb_command(u64 port, u8 reg_num, u8 val)
{
NATIVE_WRITE_MAS_B(port, reg_num, MAS_IOADDR);
NATIVE_WRITE_MAS_B(port, val, MAS_IOADDR);
}
void
serial_putc(unsigned long com_port, unsigned char c)
{
while ((com_inb_command(com_port, RR0) & D2) == 0){
}
com_outb((com_port + 0x01), c);
}
unsigned char
serial_getc(unsigned long com_port)
{
while (((com_inb_command(com_port, RR0)) & D0) == 0){
}
return com_inb(com_port + 0x01);
}
unsigned short zilog_serial_init(void)
{
struct bios_pci_dev *dev;
unsigned char val = 0;
rom_printk("Scanning PCI bus for ieee1284/rs232 device ...\n");
dev = bios_pci_find_device(INTEL_MULTIFUNC_VENDOR,
PCI_DEVICE_ID_PAR_SER, NULL);
if (dev == NULL) {
dev = bios_pci_find_device(PCI_VENDOR_ID_MCST_TMP,
PCI_DEV_ID_SERIAL, dev);
}
if (dev){
ch_a_control = (dev->base_address[SERIAL_BAR] & ~0x01);
ch_a_data = (dev->base_address[SERIAL_BAR] & ~0x01) + 0x01;
ch_b_control = (dev->base_address[SERIAL_BAR] & ~0x01) + 0x02;
ch_b_data = (dev->base_address[SERIAL_BAR] & ~0x01) + 0x03;
DebugC("zilog_serial_init: ch_a_control = 0x%x, ch_a_data = 0x%x\n"
" ch_b_control = 0x%x, ch_b_data = 0x%x\n",
(unsigned int)ch_a_control, (unsigned int)ch_a_data,
(unsigned int)ch_b_control, (unsigned int)ch_b_data);
com_port = ch_a_control;
/* Hardware Reset */
val = (val | D7 | D6); /* Force Hardware Reset */
DebugC("zilog_serial_init: Hardware Reset: WR9 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR9, val);
/* It seems not neccesary due to WR9 sharing for both channels */
com_outb_command(ch_b_control, WR9, val);
#if NOT_BIOS
/* Enabling interrupts */
val = 0; val |= D3; /* Master Interrupt Enable */
DebugC("zilog_serial_init: Hardware Reset: WR9 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR9, val);
/* It seems not neccesary due to WR9 sharing for both channels */
com_outb_command(ch_b_control, WR9, val);
#else
/* Interrupts disabled */
#endif
#if NOT_BIOS
/* Detailed interrupt installations */
val = 0;
val |= D1; /* Transmit interrupt enabling. An interrupt will be
* generated each time a packet is transmitted */
val |= D2; /* The parity error for recieved packet is Special
* Condition from now */
val |= D4; /* Enabling interrupt for each packet recieving and when
* Special Condition occurs */
DebugC("zilog_serial_init: Hardware Reset: WR1 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR1, val);
com_outb_command(ch_b_control, WR1, val);
#else
/* poll mode */
val = 0;
DebugC("zilog_serial_init: Hardware Reset: WR1 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR1, val);
com_outb_command(ch_b_control, WR1, val);
#endif
/* Operation mode */
val = 0;
#if NOT_BIOS
val |= D0; /* Parity Enable */
/* Parity bit is present */
val |= (D2 | D3); /* Setup stop bits, if any setuped the mode is asynchronus */
/* 2 stop bits */
#else
val |= D2; /* stop bit = 1 */
#endif
val |= D6; /* x16 mode */
DebugC("zilog_serial_init: Hardware Reset: WR4 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR4, val);
com_outb_command(ch_b_control, WR4, val);
/* xN Mode Enable */
val = 0;
val |= D7; /* xN Mode Enable */
DebugC("zilog_serial_init: Hardware Reset: WR7 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR7, val);
com_outb_command(ch_b_control, WR7, val);
/* setup xN constant */
val = 0;
val |= (D0 | D2 | D4); /* 15_h = 21_d; xN = 0.5 * 21 = 10.5 */
DebugC("zilog_serial_init: Hardware Reset: WR6 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR6, val);
com_outb_command(ch_b_control, WR6, val);
/* Bits per symbol to recieve */
val = 0;
val |= (D7 | D6); /* 8 bits per symbol */
DebugC("zilog_serial_init: Hardware Reset: WR3 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR3, val);
com_outb_command(ch_b_control, WR3, val);
/* Bits per symbol to transmit */
val = 0;
val |= (D6 | D5); /* 8 bits per symbol */
DebugC("zilog_serial_init: Hardware Reset: WR5 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR5, val);
com_outb_command(ch_b_control, WR5, val);
/* Encoding setup */
val = 0;
#if NOT_BIOS
val |= D5; /* NRZI encoding */
#else
/* NRZ encoding */
#endif
DebugC("zilog_serial_init: Hardware Reset: WR10 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR10, val);
com_outb_command(ch_b_control, WR10, val);
/* Clock setup */
val = 0;
val |= (D4 | D6); /* Transmit Clock = BRG output;
* Receive Clock = BRG output */
DebugC("zilog_serial_init: Hardware Reset: WR11 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR11, val);
com_outb_command(ch_b_control, WR11, val);
/* Lower Byte of Time Constant */
val = 0;
val |= (D4 | D3 | D2 | D1); /* = 1e_h (4800) */
DebugC("zilog_serial_init: Hardware Reset: WR12 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR12, val);
com_outb_command(ch_b_control, WR12, val);
/* Upper Byte of Time Constant */
val = 0; /* determine 115200 baud rate when pclk = 4.9152 MHz */
DebugC("zilog_serial_init: Hardware Reset: WR13 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR13, val);
com_outb_command(ch_b_control, WR13, val);
/* Determine synchronization source for BGR */
val = 0; /* the source is RTxC pin */
DebugC("zilog_serial_init: Hardware Reset: WR14 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR14, val);
com_outb_command(ch_b_control, WR14, val);
/* switch on the reciver */
val = 0;
val |= D0; /* turn on */
val |= (D7 | D6); /* 8 bits per symbol */
DebugC("zilog_serial_init: Hardware Reset: WR3 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR3, val);
com_outb_command(ch_b_control, WR3, val);
/* switch on the transmitter */
val = 0;
val |= D3; /* turn on */
val |= (D6 | D5); /* 8 bits per symbol */
DebugC("zilog_serial_init: Hardware Reset: WR5 val = 0x%x\n", val);
com_outb_command(ch_a_control, WR5, val);
com_outb_command(ch_b_control, WR5, val);
com_port = ch_a_control;
rom_printk("Initialization compleete ");
if (boot_info) {
boot_info->serial_base = com_port;
rom_printk("AM85C30 Serial console enabled at "
"0x%X base\n", com_port);
} else {
rom_printk("Unable to init boot_info BUG!!!\n");
}
hardware.serial = 1;
} else {
rom_printk("!!! NOT FOUND !!!\n");
}
return 0;
}

416
arch/e2k/boot/Am85C30.h Normal file
View File

@ -0,0 +1,416 @@
#ifdef CONFIG_E2K_SIC
extern unsigned short zilog_serial_init(void);
#endif
/* WRITE Registers */
#define WR0 0x00
#define WR1 0x01
#define WR2 0x02
#define WR3 0x03
#define WR4 0x04
#define WR5 0x05
#define WR6 0x06
#define WR7 0x07
#define WR8 0x08
#define WR9 0x09
#define WR10 0x0a
#define WR11 0x0b
#define WR12 0x0c
#define WR13 0x0d
#define WR14 0x0e
#define WR15 0x0f
/* READ (Status) Registers */
#define RR0 0x00
#define RR1 0x01
#define RR2 0x02
#define RR3 0x03
#define RR8 0x08
#define RR10 0x0a
#define RR12 0x0c
#define RR13 0x0d
#define D0 (0x01 << 0)
#define D1 (0x01 << 1)
#define D2 (0x01 << 2)
#define D3 (0x01 << 3)
#define D4 (0x01 << 4)
#define D5 (0x01 << 5)
#define D6 (0x01 << 6)
#define D7 (0x01 << 7)
/* WR0 */
/* D2,D1,D0
* Register Access Pointer
*
* 000 - N0, [N8]*
* 001 - N1, [N9]*
* 010 - N2, [N10]*
* 011 - N3, [N11]*
* 100 - N4, [N12]*
* 101 - N5, [N13]*
* 110 - N6, [N14]*
* 111 - N7, [N15]*
*
* if Point High Register Group = 1
*
* D5,D4,D3
*
* SCC Command
*
* 000 - Null Code
* 001 - Point High Register Group
* 010 - Reset Ext/Status Interrupts
* 011 - Send Abort
* 100 - Enable Int. on Next Rx Character
* 101 - Reset Tx Int. Pending
* 110 - Error Reset
* 111 - Reset Highest IUS
*
* D7,D6
* SCC Command
*
* 00 - Null Code
* 01 - Reset Rx CRC Checker
* 10 - Reset Tx CRC Generator
* 11 - Reset Tx Underrun/EOM Latch
*/
/* WR1 */
/* D0
* Ext. Int. Enable
* D1
* Tx Int. Enable
* D2
* Parity is Special Condition
* D4,D3
* Rx Int Mode
*
* 00 - Rx Int Disable
* 01 - Rx Int on First Char. or Special Condition
* 10 - Int on All Rx Char. or Special Condition
* 11 - Rx Int. on Special Condition Only
* D5
* Wait/DMA Request on Receive/Transmit
* D6
* Wait/DMA Request Function
* D7
* Wait/DMA Request Enable
*/
/* WR2 */
/* D7 - D0
* Interrupt Vector
*/
/* WR3 */
/* D0
* Rx Enable
* D1
* Sync Character Load Inhibit
* D2
* Address Search Mode (SDLC)
* D3
* Rx CRC Enable
* D4
* Enter Hunt Mode
* D5
* Auto Enable
* D7,D6
*
* 00 - Rx 5 Bits / Character
* 01 - Rx 6 Bits / Character
* 10 - Rx 7 Bits / Character
* 11 - Rx 8 Bits / Character
*/
/* WR4 */
/* D0
* ParityEnable
* D1
* Parity Even(0) / Odd(1)
* D3,D2
*
* 00 - Sync Modes Enable
* 01 - 1 Stop Bit / Character
* 10 - 1.5 Stop Bits / Character
* 11 - 2 Stop Bits / Character
* D5,D4
*
* 00 - 8-Bit Sync Character
* 01 - 16-Bit Sync Character
* 10 - SDLC Mode
* 11 - External Sync Mode
* D7,D6
*
* 00 - X1 Clock Mode
* 01 - X16 Clock Mode
* 10 - X32 Clock Mode
* 11 - X64 Clock Mode
*/
/* WR5 */
/* D0
* Tx CRC Enable
* D1
* RTS
* D2
* SDLC-/CRC-16
* D3
* Tx Enable
* D4
* Send Break
* D6,D5
*
* 00 - Tx 5 Bits / Character
* 01 - Tx 6 Bits / Character
* 10 - Tx 7 Bits / Character
* 11 - Tx 8 Bits / Character
* D7
* DTR
*/
/* WR6 */
/* D5-D0
* xN constant
* D7,D6
* Reserved (not used in asynchronous mode)
*/
/* WR7 */
/* D6-D0
* Reserved (not used in asynchronous mode)
* D7
* xN Mode Enable
*/
/* WR8 */
/* D7-D0
* Transmit Buffer
*/
/* WR9 */
/* D0
* Vector Includes Status
* D1
* No Vector
* D2
* Disable Lower Chain
* D3
* Master Interrupt Enable
* D4
* Status High/Low_
* D5
* Interrupt Masking Without INTACK_
* D7-D6
*
* 00 - No Reset
* 01 - Channel B Reset
* 10 - Channel A Reset
* 11 - Force Hardware Reset
*/
/* WR10 */
/* D0
* 6 bit / 8 bit SYNC
* D1
* Loop Mode
* D2
* Abort/Flag on Underrun
* D3
* Mark/Flag Idle
* D4
* Go Active on Poll
* D6-D5
*
* 00 - NRZ
* 01 - NRZI
* 10 - FM1 (Transition = 1)
* 11 - FM0 (Transition = 0)
* D7
* CRC Preset '1' or '0'
*/
/* WR11 */
/* D1-D0
*
* 00 - TRxC Out = XTAL output
* 01 - TRxC Out = Transmit Clock
* 10 - TRxC Out = BRG output
* 11 - TRxC Out = DPLL output
* D2
* TRxC O/I
* D4-D3
*
* 00 - Transmit Clock = RTxC pin
* 01 - Transmit Clock = TRxC pin
* 10 - Transmit Clock = BRG output
* 11 - Transmit Clock = DPLL output
* D6-D5
*
* 00 - Receive Clock = RTxC pin
* 01 - Receive Clock = TRxC pin
* 10 - Receive Clock = BRG output
* 11 - Receive Clock = DPLL output
* D7
* RTxC XTAL / NO XTAL
*/
/* WR12 */
/* D7-D0
* Lower Byte of Time Constant
*/
/* WR13 */
/* D7-D0
* Upper Byte of Time Constant
*/
/* WR14 */
/* D0
* BRG Enable
* D1
* BRG Source
* D2
* DTR / REQUESTt Function
* D3
* Auto Echo
* D4
* Local Loopback
* D7-D5
*
* 000 - Null Command
* 001 - Enter Search Mode
* 010 - Reset Missing Clock
* 011 - Disable DPLL
* 100 - Set Source = BR Generator
* 101 - Set Source = RTxC_
* 110 - Set FM Mode
* 111 - Set NRZI Mode
*/
/* WR15 */
/* D0
* SDLC/HDLC Enhancement Enable
* D1
* Zero Count IE (Interrupt Enable)
* D2
* 10 * 19-bit Frame Status FIFO Enable
* D3
* DCD IE
* D4
* Sync/Hunt IE
* D5
* CTS IE
* D6
* Tx Underrun / EOM IE
* D7
* Break/Abort IE
*/
/* RR0 */
/* D0
* Rx Character Availiable
* D1
* Zero Count
* D2
* Tx Buffer Empty
* D3
* DCD
* D4
* Sync/Hunt
* D5
* CTS
* D6
* Tx Underrun / EOM
* D7
* Break/Abort
*/
/* RR1 */
/* D0
* All Sent
* D1
* Residue Code 2
* D2
* Residue Code 1
* D3
* Residue Code 0
* D4
* Parity Error
* D5
* Rx Overrun Error
* D6
* CRC / Framing Error
* D7
* End of Frame (SDLC)
*/
/* RR2 */
/* D7-D0
* Interrupt Vector
*
* Channel A RR2 = WR2
* Channel B RR2 = Interrupt Vector Modified*
*
* *
* D3 D2 D1 Status High/Low = 0
* D4 D5 D6 Status High/Low = 1
*
* 0 0 0 Ch B Transmit Buffer Empty
* 0 0 1 Ch B External/Status Change
* 0 1 0 Ch B Receive Char. Availiable
* 0 1 1 Ch B Special Receive Condition
* 1 0 0 Ch A Transmit Buffer Empty
* 1 0 1 Ch A External/Status Change
* 1 1 0 Ch A Receive Char. Availiable
* 1 1 1 Ch A Special Receive Condition
*/
/* RR3 */
/* D0
* Channel B Ext/Status IP (Interrupt Pending)
* D1
* Channel B Tx IP
* D2
* Channel B Rx IP
* D3
* Channel A Ext/Status IP
* D4
* Channel A Tx IP
* D5
* Channel A Rx IP
* D7-D6
* Always 00
*/
/* RR8 */
/* D7-D0
* Receive Buffer
*/
/* RR10 */
/* D7-D0
* Reserved (not used in asynchronous mode)
*/
/* RR12 */
/* D7-D0
* Lower Byte of Time Constant
*/
/* RR13 */
/* D7-D0
* Upper Byte of Time Constant
*/

321
arch/e2k/boot/Makefile Normal file
View File

@ -0,0 +1,321 @@
GCOV_PROFILE := n
OBJCOPY += -O binary -R .note -R .comment -S
OBJCOPYFLAGS := -O binary -R .note -R .comment -S
ccflags-y := -DCONFIG_BOOT_E2K
ifeq ($(call cc-option-yn,-fno-semi-spec-ld -fno-spec-ld),y)
ccflags-y += -fno-semi-spec-ld -fno-spec-ld
else
ccflags-y += -fno-ld-spec
endif
targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.xz \
vmlinux.bin.lzma vmlinux.bin.lzo vmlinux.bin.lz4 cimage image \
bimage cpiggy.o bpiggy.o epiggy.o zpiggy.o piggy.o System.map
empty:=
space:= $(empty) $(empty)
ORIG_CFLAGS := $(KBUILD_CFLAGS)
ORIG_CFLAGS := $(subst $(space)-fprofile-generate-kernel$(space),$(space),$(ORIG_CFLAGS))
ORIG_CFLAGS := $(subst $(space)-fprofile-use="$(PROFILE_USE)"$(space),$(space),$(ORIG_CFLAGS))
KBUILD_CFLAGS = $(ORIG_CFLAGS)
RANLIB = $(shell $(CC) -print-prog-name=ranlib)
ROMSCRIPT = $(obj)/aploader.lds
KBUILD_CFLAGS += -DCONFIG_E2K_SIC
KBUILD_AFLAGS += -DCONFIG_E2K_SIC
FLAGS_EPIC_EIOH := -DCONFIG_BOOT_EPIC -DCONFIG_EIOH
ifeq ($(CONFIG_ES2),y)
KBUILD_CFLAGS += -DCONFIG_ES2 -DCONFIG_E2K_FULL_SIC
KBUILD_AFLAGS += -DCONFIG_ES2 -DCONFIG_E2K_FULL_SIC
else
ifeq ($(CONFIG_E2S),y)
KBUILD_CFLAGS += -DCONFIG_E2S -DCONFIG_E2K_FULL_SIC
KBUILD_AFLAGS += -DCONFIG_E2S -DCONFIG_E2K_FULL_SIC
else
ifeq ($(CONFIG_E8C),y)
KBUILD_CFLAGS += -DCONFIG_E8C \
-DCONFIG_E2K_FULL_SIC \
-DCONFIG_L_IOH2
KBUILD_AFLAGS += -DCONFIG_E8C \
-DCONFIG_E2K_FULL_SIC \
-DCONFIG_L_IOH2
else
ifeq ($(CONFIG_E1CP),y)
KBUILD_CFLAGS += -DCONFIG_E1CP \
-DCONFIG_E2K_LEGACY_SIC \
-DCONFIG_L_IOH2
KBUILD_AFLAGS += -DCONFIG_E1CP \
-DCONFIG_E2K_LEGACY_SIC \
-DCONFIG_L_IOH2
else
ifeq ($(CONFIG_E8C2),y)
KBUILD_CFLAGS += -DCONFIG_E8C2 \
-DCONFIG_E2K_FULL_SIC \
-DCONFIG_L_IOH2
KBUILD_AFLAGS += -DCONFIG_E8C2 \
-DCONFIG_E2K_FULL_SIC \
-DCONFIG_L_IOH2
else
ifeq ($(CONFIG_E12C),y)
KBUILD_CFLAGS += -DCONFIG_E12C \
-DCONFIG_E2K_FULL_SIC \
-DCONFIG_L_IOH2 \
$(FLAGS_EPIC_EIOH)
KBUILD_AFLAGS += -DCONFIG_E12C \
-DCONFIG_E2K_FULL_SIC \
-DCONFIG_L_IOH2 \
$(FLAGS_EPIC_EIOH)
else
ifeq ($(CONFIG_E16C),y)
KBUILD_CFLAGS += -DCONFIG_E16C \
-DCONFIG_E2K_FULL_SIC \
-DCONFIG_L_IOH2 \
$(FLAGS_EPIC_EIOH)
KBUILD_AFLAGS += -DCONFIG_E16C \
-DCONFIG_E2K_FULL_SIC \
-DCONFIG_L_IOH2 \
$(FLAGS_EPIC_EIOH)
else
ifeq ($(CONFIG_E2C3),y)
KBUILD_CFLAGS += -DCONFIG_E2C3 \
-DCONFIG_E2K_FULL_SIC \
-DCONFIG_L_IOH2 \
$(FLAGS_EPIC_EIOH)
KBUILD_AFLAGS += -DCONFIG_E2C3 \
-DCONFIG_E2K_FULL_SIC \
-DCONFIG_L_IOH2 \
$(FLAGS_EPIC_EIOH)
endif
endif
endif
endif
endif
endif
endif
endif
# remove profile flags
ORIG_CFLAGS := $(KBUILD_CFLAGS)
KBUILD_CFLAGS =$(subst -pg,,$(ORIG_CFLAGS))
START_OBJ = $(obj)/romstartup.o $(obj)/apstartup.o
targets += romstartup.o apstartup.o
obj-y := romloader.o jumpstart.o keyboard.o zip.o malloc.o stdio.o \
string.o recovery_string.o recovery_string_v5.o epic.o
AFLAGS_REMOVE_recovery_string_v5.o = $(CFLAGS_ALL_CPUS)
AFLAGS_recovery_string_v5.o += -march=elbrus-v5
obj-$(CONFIG_SMP) += aploader.o smp.o
obj-$(CONFIG_L_LOCAL_APIC) += apic.o
obj-$(CONFIG_SERIAL_AM85C30_BOOT_CONSOLE) += Am85C30.o
obj-$(CONFIG_VGA_CONSOLE) += vga.o
obj-$(CONFIG_LMS_CONSOLE) += console.o
obj-$(CONFIG_BIOS) += bios/
BIOS_ELF = image
ROM_LDFLAGS = -e start -T $(TOPDIR)/$(ROMSCRIPT)
# lcc option '-fvisibility=hidden' allows us to reduce
# .got section size - this is a small optimization.
CFLAGS_decompress.o += -fpic -fvisibility=hidden -DE2K_P2V -O4
CFLAGS_machdep_fpic.o += -fpic -fvisibility=hidden -DE2K_P2V -O4
CFLAGS_string_fpic.o += -fpic -fvisibility=hidden -DE2K_P2V -O4
CFLAGS_string_guest_fpic.o += -fpic -fvisibility=hidden -DE2K_P2V -O4
AFLAGS_recovery_string_fpic.o += -fpic -fvisibility=hidden -DE2K_P2V
AFLAGS_REMOVE_recovery_string_v5_fpic.o = $(CFLAGS_ALL_CPUS)
AFLAGS_recovery_string_v5_fpic.o += -march=elbrus-v5 -fpic \
-fvisibility=hidden -DE2K_P2V
CFLAGS_bootblock.o += -fno-toplevel-reorder
targets += bootblock.o decompress.o machdep_fpic.o string_fpic.o \
recovery_string_fpic.o recovery_string_v5_fpic.o
TOPDIR = $(srctree)
SYSTEM = vmlinux
SYSTEM_IMAGE = $(objtree)/image.boot
CVS_TOPDIR = ../../../../..
ifdef CONFIG_BLK_DEV_INITRD
INITRD = /tmp/initrd
INITRDO = initrd.o
else
INITRD =
INITRDO =
endif
PIGGYO = $(obj)/piggy.o
targets += $(objtree)/image.boot
targets += image.bios $(objtree)/image.bios $(objtree)/vmlinux.bin
all: boot
dep:
$(TOPDIR)/scripts/mkdep *.[Sch] > .depend
clean:
rm -rf $(obj)/built-in-sym.o $(START_OBJ) $(BIOS_ELF) $(BIOS_IMAGE) _tmp_*
$(Q)$(MAKE) $(build)=arch/e2k/boot/bios clean
$(INITRDO):
tmpinitrd=_tmp_$$$$initrd; \
rm -f $$tmpinitrd $$tmpinitrd.lnk; \
if [ -x $(INITRD) ]; then \
cp $(INITRD) $$tmpinitrd; \
else \
> $$tmpinitrd; \
fi; \
echo "SECTIONS { .initrd : { initrd_len = .; initrd_data = .; *(.data) initrd_data_end = .; }}" \
> $$tmpinitrd.lnk; \
$(LD) -r -o $(INITRDO) -b binary $$tmpinitrd -b elf64-e2k \
-T $$tmpinitrd.lnk; \
rm -f $$tmpinitrd $$tmpinitrd.lnk
bios: FORCE
$(Q)$(MAKE) $(build)=arch/e2k/boot/bios bios
# piggy is gzipped kernel
LDFLAGS_zpiggy.o = -r -b binary --oformat elf64-e2k -T $(srctree)/$(src)/vmlinux.bin.lds \
-defsym input_data_noncomp_size=$(shell wc -c < $(objtree)/$(obj)/vmlinux.bin) \
-defsym boot_mode=0
$(obj)/zpiggy.o: $(obj)/vmlinux.bin.gz FORCE
$(call if_changed,ld)
# piggy is empty
LDFLAGS_epiggy.o = -r -b binary --oformat elf64-e2k -T $(srctree)/$(src)/epiggy.lds \
-defsym input_data_noncomp_size=$(shell wc -c < $(objtree)/$(obj)/vmlinux.bin) \
-defsym boot_mode=1 -defsym input_data=0 -defsym input_data_end=0
$(obj)/epiggy.o: $(obj)/vmlinux.bin FORCE
$(call if_changed,ld)
ifeq ($(with_kernel), 1)
$(PIGGYO): $(obj)/zpiggy.o
@cp $(obj)/zpiggy.o $(obj)/piggy.o; \
rm -f $(obj)/epiggy.o
$(objtree)/vmlinux.bin: ;
else
$(PIGGYO): $(obj)/epiggy.o
@cp $(obj)/epiggy.o $(obj)/piggy.o; \
rm -f $(obj)/zpiggy.o
$(objtree)/vmlinux.bin: $(obj)/vmlinux.bin
@cp $(obj)/vmlinux.bin $(objtree)/vmlinux.bin
endif
$(obj)/built-in-sym.o: $(obj)/built-in.a
@cp $(obj)/built-in.a $(obj)/built-in-sym.o; \
$(RANLIB) $(obj)/built-in-sym.o
LDFLAGS_bimage := $(ROM_LDFLAGS)
$(obj)/bimage: $(obj)/built-in-sym.o $(START_OBJ) $(PIGGYO) $(INITRDO) FORCE
$(call if_changed,ld)
$(obj)/image.bios: $(obj)/bimage FORCE
$(call if_changed,objcopy)
$(objtree)/image.bios: $(obj)/image.bios
@cp $(obj)/image.bios $(objtree)/image.bios
$(obj)/System.map: $(obj)/bimage
@$(NM) $(obj)/bimage | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\<L\)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > $(obj)/System.map
boot: $(objtree)/image.bios $(objtree)/vmlinux.bin $(obj)/System.map
$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy)
@ksize=`ls -l $(obj)/vmlinux.bin | awk '{print $$5;}'`; \
echo "Non-compressed kernel size:" $$ksize
suffix-y :=
suffix-$(CONFIG_KERNEL_GZIP) := .gz
suffix-$(CONFIG_KERNEL_BZIP2) := .bz2
suffix-$(CONFIG_KERNEL_LZ4) := .lz4
suffix-$(CONFIG_KERNEL_LZMA) := .lzma
suffix-$(CONFIG_KERNEL_XZ) := .xz
suffix-$(CONFIG_KERNEL_LZO) := .lzo
$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE
$(call if_changed,gzip)
@ksize=`ls -l $(obj)/vmlinux.bin.gz | awk '{print $$5;}'`; \
echo "Compressed kernel size:" $$ksize
$(obj)/vmlinux.bin.bz2: $(obj)/vmlinux.bin FORCE
$(call if_changed,bzip2)
@ksize=`ls -l $(obj)/vmlinux.bin.bz2 | awk '{print $$5;}'`; \
echo "Compressed kernel size:" $$ksize
$(obj)/vmlinux.bin.lz4: $(obj)/vmlinux.bin FORCE
$(call if_changed,lz4)
@ksize=`ls -l $(obj)/vmlinux.bin.lz4 | awk '{print $$5;}'`; \
echo "Compressed kernel size:" $$ksize
$(obj)/vmlinux.bin.lzma: $(obj)/vmlinux.bin FORCE
$(call if_changed,lzma)
@ksize=`ls -l $(obj)/vmlinux.bin.lzma | awk '{print $$5;}'`; \
echo "Compressed kernel size:" $$ksize
$(obj)/vmlinux.bin.xz: $(obj)/vmlinux.bin FORCE
$(call if_changed,xzkern)
@ksize=`ls -l $(obj)/vmlinux.bin.xz | awk '{print $$5;}'`; \
echo "Compressed kernel size:" $$ksize
$(obj)/vmlinux.bin.lzo: $(obj)/vmlinux.bin FORCE
$(call if_changed,lzo)
@ksize=`ls -l $(obj)/vmlinux.bin.lzo | awk '{print $$5;}'`; \
echo "Compressed kernel size:" $$ksize
LDFLAGS_bpiggy.o := -r -b binary --oformat elf64-e2k -T $(srctree)/$(src)/vmlinux.bin.lds
$(obj)/bpiggy.o: $(obj)/vmlinux.bin FORCE
$(call if_changed,ld)
LDFLAGS_cpiggy.o := -r -b binary --oformat elf64-e2k -T $(srctree)/$(src)/vmlinux.bin.lds
$(obj)/cpiggy.o: $(obj)/vmlinux.bin$(suffix-y) FORCE
$(call if_changed,ld)
LDFLAGS_image = -static -e gap -T $(srctree)/$(src)/boot.lds \
-defsym __kernel_size=$(shell wc -c < $(objtree)/$(obj)/vmlinux.bin)
$(obj)/image: $(obj)/bpiggy.o $(obj)/bootblock.o FORCE
$(call if_changed,ld)
ifdef CONFIG_KVM_GUEST_KERNEL
targets += string_guest_fpic.o
STRING_GUEST_FPIC_O=$(obj)/string_guest_fpic.o
COMPRESSED_SCRIPT=compressed_guest.lds
else
STRING_GUEST_FPIC_O=
COMPRESSED_SCRIPT=compressed.lds
endif
LDFLAGS_cimage = -static -e decompress_kernel -T $(srctree)/$(src)/$(COMPRESSED_SCRIPT) \
-defsym __orig_kernel_size=$(shell wc -c < $(objtree)/$(obj)/vmlinux.bin) \
-defsym __kernel_size=$(shell wc -c < $(objtree)/$(obj)/vmlinux.bin$(suffix-y))
$(obj)/cimage: $(obj)/cpiggy.o $(obj)/bootblock.o $(obj)/decompress.o \
$(obj)/string_fpic.o $(STRING_GUEST_FPIC_O) \
$(obj)/recovery_string_fpic.o $(obj)/recovery_string_v5_fpic.o \
$(obj)/machdep_fpic.o FORCE
$(call if_changed,ld)
$(objtree)/image.boot: $(obj)/image FORCE
$(call if_changed,objcopy)
$(objtree)/zImage: $(obj)/cimage FORCE
$(call if_changed,objcopy)
install-headers:
rm -rf $(CVS_TOPDIR)/usr/include; \
mkdir -p $(CVS_TOPDIR)/usr/include; \
ln -s $(TOPDIR)/include/linux $(CVS_TOPDIR)/usr/include/linux; \
ln -s $(TOPDIR)/include/asm $(CVS_TOPDIR)/usr/include/asm; \
ln -s $(TOPDIR)/include/asm-generic $(CVS_TOPDIR)/usr/include/asm-generic

265
arch/e2k/boot/apic.c Normal file
View File

@ -0,0 +1,265 @@
/*
* Local APIC handling, local APIC timers
*/
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/irq.h>
#include <linux/types.h>
#include <asm/atomic.h>
#include <asm/head.h>
#include <asm/apic.h>
#include <asm/bootinfo.h>
#include <asm/e2k_debug.h>
#include <asm/e2k_api.h>
#include "boot_io.h"
#include "pic.h"
#define SET_APIC_VERSION(x) ((x) & 0xFF)
/**************************** DEBUG DEFINES *****************************/
#undef DEBUG_BOOT_MODE
#undef Dprintk
#define DEBUG_BOOT_MODE 1 /* SMP CPU boot */
#define Dprintk if (DEBUG_BOOT_MODE) rom_printk
/************************************************************************/
void
setup_local_apic(int cpu)
{
unsigned int value, ver;
value = native_apic_read(APIC_LVR);
ver = GET_APIC_VERSION(value);
if (ver == 0) {
ver = APIC_VERSION;
value |= SET_APIC_VERSION(ver);
native_apic_write(APIC_LVR, value);
}
Dprintk("APIC_LVR : 0x%x version 0x%x maxlvt 0x%x\n",
value, ver, GET_APIC_MAXLVT(value));
/*
* Put the APIC into flat delivery mode.
* Must be "all ones" explicitly for 82489DX.
*/
value = native_apic_read(APIC_DFR);
Dprintk("APIC_DFR before setup : 0x%x delivery mode 0x%x\n",
value, GET_APIC_DLVR_MODE(value));
native_apic_write(APIC_DFR, 0xffffffff);
value = native_apic_read(APIC_DFR);
Dprintk("APIC_DFR after setup : 0x%x delivery mode 0x%x\n",
value, GET_APIC_DLVR_MODE(value));
/*
* Set up the logical destination ID.
*/
value = native_apic_read(APIC_LDR);
Dprintk("APIC_LDR before setup : 0x%x logical ID 0x%x\n",
value, GET_APIC_LOGICAL_ID(value));
value &= ~APIC_LDR_MASK;
value |= SET_APIC_LOGICAL_ID(cpu);
native_apic_write(APIC_LDR, value);
value = native_apic_read(APIC_LDR);
Dprintk("APIC_LDR after setup : 0x%x logical ID 0x%x\n",
value, GET_APIC_LOGICAL_ID(value));
/*
* Reset all not masked interrupts
*/
value = native_apic_read(APIC_NM);
Dprintk("APIC_NM before setup : 0x%x\n",
value);
native_apic_write(APIC_NM, APIC_NM_BIT_MASK);
#if DEBUG_BOOT_MODE
value = native_apic_read(APIC_NM);
native_apic_write(APIC_NM, APIC_NM_BIT_MASK);
Dprintk("APIC_NM after setup : 0x%x\n", value);
#endif
/*
* Now that we are all set up, enable the APIC
*/
value = native_apic_read(APIC_BSP);
Dprintk("APIC_BSP before setup : 0x%x apic enable %d, BSP flag %d\n",
value, APIC_ENABLE(value) != 0, BootStrap(value) != 0);
value |= APIC_BSP_ENABLE;
native_apic_write(APIC_BSP, value);
value = native_apic_read(APIC_BSP);
Dprintk("APIC_BSP after setup : 0x%x apic enable %d, BSP flag %d\n",
value, APIC_ENABLE(value) != 0, BootStrap(value) != 0);
value = native_apic_read(APIC_SPIV);
Dprintk("APIC_SPIV before setup : 0x%x apic soft enabled %d, "
"focus processor disabled %d, spurious vector 0x%x\n",
value, APIC_SOFT_ENABLED(value) != 0,
APIC_FOCUS_DISABLED(value) != 0,
GET_SPURIOUS_VECTOR(value));
// value &= ~APIC_VECTOR_MASK;
/*
* Enable APIC
*/
value |= APIC_SPIV_APIC_ENABLED;
/*
* Some unknown Intel IO/APIC (or APIC) errata is biting us with
* certain networking cards. If high frequency interrupts are
* happening on a particular IOAPIC pin, plus the IOAPIC routing
* entry is masked/unmasked at a high rate as well then sooner or
* later IOAPIC line gets 'stuck', no more interrupts are received
* from the device. If focus CPU is disabled then the hang goes
* away, oh well :-(
*
* [ This bug can be reproduced easily with a level-triggered
* PCI Ne2000 networking cards and PII/PIII processors, dual
* BX chipset. ]
*/
/* Disable focus processor (bit==1) */
value |= APIC_SPIV_FOCUS_DISABLED;
native_apic_write(APIC_SPIV, value);
Dprintk("APIC_SPIV after setup : 0x%x apic soft enabled %d, "
"focus processor disabled %d, spurious vector 0x%x\n",
value, APIC_SOFT_ENABLED(value) != 0,
APIC_FOCUS_DISABLED(value) != 0,
GET_SPURIOUS_VECTOR(value));
value = native_apic_read(APIC_LVT0);
Dprintk("APIC_LVT0 before setup : 0x%x apic lvt masked %d\n",
value, (value & APIC_LVT_MASKED) != 0);
if (!cpu) {
value = APIC_DM_EXTINT;
} else {
value = APIC_DM_EXTINT | APIC_LVT_MASKED;
}
native_apic_write(APIC_LVT0, value);
Dprintk("APIC_LVT0 after setup : 0x%x apic lvt masked %d, "
"Ext Int enabled 0x%d\n",
value, (value & APIC_LVT_MASKED) != 0,
(value & APIC_DM_EXTINT) != 0);
/*
* only the BP should see the LINT1 NMI signal, obviously.
*/
if (!cpu)
value = APIC_DM_NMI;
else
value = APIC_DM_NMI | APIC_LVT_MASKED;
native_apic_write(APIC_LVT1, value);
}
void
clear_local_apic(void)
{
native_apic_write(APIC_BSP, 0);
native_apic_write(APIC_SPIV, 0);
}
void
print_local_apic(void)
{
unsigned int v, ver, maxlvt;
v = native_apic_read(APIC_BSP);
if (!APIC_ENABLE(v)) {
rom_printk(" APIC disable\n");
return;
}
if (BootStrap(v))
rom_printk("... BootStrap processor\n");
else
rom_printk("... Aplication processor\n");
v = native_apic_read(APIC_ID);
rom_printk("... APIC ID: %08x (%01x)\n", v, GET_APIC_ID(v));
v = native_apic_read(APIC_LVR);
rom_printk("... APIC VERSION: %08x\n", v);
ver = GET_APIC_VERSION(v);
maxlvt = GET_APIC_MAXLVT(v);
v = native_apic_read(APIC_TASKPRI);
rom_printk("... APIC TASKPRI: %08x (%02x)\n", v, v & APIC_TPRI_MASK);
if (APIC_INTEGRATED(ver)) { /* !82489DX */
v = native_apic_read(APIC_ARBPRI);
rom_printk( "... APIC ARBPRI: %08x (%02x)\n", v,
v & APIC_ARBPRI_MASK);
v = native_apic_read(APIC_PROCPRI);
rom_printk( "... APIC PROCPRI: %08x\n", v);
}
/* v = native_apic_read(APIC_EOI); */
/* rom_printk( "... APIC EOI: %08x\n", v); */
v = native_apic_read(APIC_LDR);
rom_printk( "... APIC LDR: %08x\n", v);
v = native_apic_read(APIC_DFR);
rom_printk( "... APIC DFR: %08x\n", v);
v = native_apic_read(APIC_SPIV);
rom_printk( "... APIC SPIV: %08x\n", v);
if (APIC_INTEGRATED(ver)) { /* !82489DX */
if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */
native_apic_write(APIC_ESR, 0);
v = native_apic_read(APIC_ESR);
rom_printk( "... APIC ESR: %08x\n", v);
}
v = native_apic_read(APIC_ICR);
rom_printk( "... APIC ICR: %08x\n", v);
v = native_apic_read(APIC_ICR2);
rom_printk( "... APIC ICR2: %08x\n", v);
v = native_apic_read(APIC_LVTT);
rom_printk( "... APIC LVTT: %08x\n", v);
if (maxlvt > 3) { /* PC is LVT#4. */
v = native_apic_read(APIC_LVTPC);
rom_printk( "... APIC LVTPC: %08x\n", v);
}
v = native_apic_read(APIC_LVT0);
rom_printk( "... APIC LVT0: %08x\n", v);
v = native_apic_read(APIC_LVT1);
rom_printk( "... APIC LVT1: %08x\n", v);
if (maxlvt > 2) { /* ERR is LVT#3. */
v = native_apic_read(APIC_LVTERR);
rom_printk( "... APIC LVTERR: %08x\n", v);
}
v = native_apic_read(APIC_TMICT);
rom_printk( "... APIC TMICT: %08x\n", v);
v = native_apic_read(APIC_TMCCT);
rom_printk( "... APIC TMCCT: %08x\n", v);
v = native_apic_read(APIC_TDCR);
rom_printk( "... APIC TDCR: %08x\n", v);
v = native_apic_read(APIC_M_ERM);
rom_printk( "... APIC_M_ERM: %08x\n", v);
v = native_apic_read(APIC_NM);
native_apic_write(APIC_NM, APIC_NM_BIT_MASK);
rom_printk( "... APIC_NM: %08x\n", v);
rom_printk("\n");
}
void debug_apic_startup(int cpu, unsigned int value, unsigned long startup_addr)
{
unsigned long addr;
Dprintk("CPU #%d : APIC_NM value = 0x%x\n", cpu, value);
if (!(value & APIC_NM_STARTUP))
rom_printk("CPU #%d : ERROR: APIC startup bit is not set\n",
cpu);
addr = value & APIC_NM_STARTUP_ADDR;
Dprintk("CPU #%d : APIC received STARTUP with addr 0x%x\n", cpu, addr);
if (addr != startup_addr >> 12)
rom_printk("CPU #%d : ERROR : APIC incorrect startup addr\n",
cpu);
}

125
arch/e2k/boot/aploader.S Normal file
View File

@ -0,0 +1,125 @@
//
// aploader.s, written by <atic@mcst.ru>
// secondary linux kernel loader module on application processor
//
#ifdef _E2K_SIMULATION_MODE_
#include <asm/simul.h>
#endif /* _E2K_SIMULATION_MODE_ */
#include <asm/head.h>
#include <asm/cpu_regs_types.h>
#define MMU_TRAP_CELLAR_MAX_SIZE 64 /* double-words */
#define RW 0x1800000000000000
#define R 0x0800000000000000
#define RW_NONP 0x1800000000000000
#define RBS 0x10 /* 10 quadwords */
.text
.global aploader
.global _data
.global __bios_size_ld
.global __bios_fsize_ld
.global __bios_entry_ld
.global __bios_start_data
.global __bios_size_data
.global __bios_size_data_plus_bss
// loader will call start_secondary() to continue. See smp.c
.global start_secondary
.global free_memory_p
aploader:
// [OS]{CUD|GD} setup
addd 0, [__bios_size_ld], %r8 // EOS size
addd 0, [EOS_RAM_BASE_LABEL+R], %r2
addd %r2,1<<58 , %r2 // set CUD.c flag
rwd %r2, %oscud.lo
addd 0, [EOS_RAM_BASE_LABEL+RW], %r6
// shld %r8, 32, %r10
addd 0, 0x01f0000000000000, %r10 // *D size (all space 1M upward)
rwd %r2, %cud.lo
rwd %r6, %osgd.lo
rwd %r6, %gd.lo
rwd %r10, %oscud.hi
rwd %r10, %osgd.hi
rwd %r10, %cud.hi
rwd %r10, %gd.hi
ldd [free_memory_p] , %dr4
// PSP - procedure stack pointer
// 'E2K_ALIGN_PSTACK' kernel loader procedure stack align
addd %r4, E2K_ALIGN_PSTACK_MASK, %r4
andd %r4, (~(E2K_ALIGN_PSTACK_MASK)),%r4
// 'E2K_KERNEL_PS_PAGE_SIZE' kernel loader procedure stack align
addd %r4, (E2K_KERNEL_PS_PAGE_SIZE - 1), %r4
andd %r4, (~(E2K_KERNEL_PS_PAGE_SIZE - 1)),%r4
rwd E2K_BOOT_KERNEL_PS_SIZE << 32, %psp.hi
addd %r4, RW, %r6
rwd %r6, %psp.lo
addd %r4, (E2K_BOOT_KERNEL_PS_SIZE + E2K_KERNEL_PS_PAGE_SIZE), %r4
// 'E2K_KERNEL_PS_PAGE_SIZE' kernel loader procedure stack align
addd %r4, (E2K_KERNEL_PS_PAGE_SIZE - 1), %r4
andd %r4, (~(E2K_KERNEL_PS_PAGE_SIZE - 1)),%r4
// PCSP - procedure chain stack pointer
// 'E2K_ALIGN_PCSTACK' kernel loader procedure chain stack align
addd %r4, E2K_ALIGN_PCSTACK_MASK, %r4
andd %r4, (~(E2K_ALIGN_PCSTACK_MASK)),%r4
// 'E2K_KERNEL_PCS_PAGE_SIZE' kernel loader procedure chain stack align
addd %r4, (E2K_KERNEL_PCS_PAGE_SIZE - 1), %r4
andd %r4, (~(E2K_KERNEL_PCS_PAGE_SIZE - 1)),%r4
rwd E2K_BOOT_KERNEL_PCS_SIZE << 32, %pcsp.hi
addd %r4, RW, %r6
rwd %r6, %pcsp.lo
addd %r4, (E2K_BOOT_KERNEL_PCS_SIZE + E2K_KERNEL_PCS_PAGE_SIZE), %r4
// 'E2K_KERNEL_PCS_PAGE_SIZE' kernel loader procedure chain stack align
addd %r4, (E2K_KERNEL_PCS_PAGE_SIZE - 1), %r4
andd %r4, (~(E2K_KERNEL_PCS_PAGE_SIZE - 1)),%r4
// US - user (kernel loader) stack pointer
// 'E2K_ALIGN_USTACK' kernel loader stack align
addd %r4, E2K_ALIGN_USTACK_MASK, %r4
andd %r4, (~(E2K_ALIGN_USTACK_MASK)),%r4
// 'E2K_KERNEL_US_PAGE_SIZE' kernel loader stack align
// User Stack is supposed to grow from higher memory addresses to lower ones
// Switch to higher memory addresses of stack
addd %r4, E2K_BOOT_KERNEL_US_SIZE, %r4
addd %r4, (E2K_KERNEL_US_PAGE_SIZE - 1), %r4
andd %r4, (~(E2K_KERNEL_US_PAGE_SIZE - 1)),%r4
rwd E2K_BOOT_KERNEL_US_SIZE << 32, %usd.hi
addd %r4, E2K_ALIGN_STACKS_BASE_MASK, %r4
andd %r4, (~(E2K_ALIGN_STACKS_BASE_MASK)), %r4
rwd %r4, %sbr
addd %r4, RW_NONP, %r6
rwd %r6, %usd.lo
// Trap Cellar
std %r0, [0x0] 71
std %r4, [0x00000050] 71
addd %dr4, MMU_TRAP_CELLAR_MAX_SIZE * 8, %dr4
std %dr4, [free_memory_p]
// Jump to the rtc0 (preparation)
addd 0, [start_secondary], %r2
movtd %r2, %ctpr1
setwd wsz=RBS+4
// Call start_secondary() and fly away
call %ctpr1, wbs=RBS

View File

@ -0,0 +1,99 @@
OUTPUT_FORMAT("elf64-e2k", "elf64-e2k", "elf64-e2k")
/* OUTPUT_ARCH(e2k) Defined by Makefile */
ENTRY(start)
MEMORY {
ROM (RX) : ORIGIN = 0x100000000, LENGTH = 16M
RAM (W) : ORIGIN = 1M, LENGTH = 31M
/* ROM chunks */
ROML (RX) : ORIGIN = 0x100000800, LENGTH = 16M - 16K - 2048
ROMH (RX) : ORIGIN = 0x100ff0000, LENGTH = 16K
CPUSTART (RX) : ORIGIN = 0x100000000, LENGTH = 2048
}
SECTIONS {
_start = .;
.text : {
_text = .; /* Text and read-only data */
*(EXCLUDE_FILE (arch/e2k/boot/romstartup.o arch/e2k/boot/apstartup.o) .text .gnu.linkonce.t.*)
*(EXCLUDE_FILE (arch/e2k/boot/romstartup.o arch/e2k/boot/piggy.o) .rodata)
. = ALIGN(4096);
arch/e2k/boot/piggy.o(.rodata)
_etext = .; /* End of text section */
} > ROML
.data : AT ( ADDR(.text) + SIZEOF ( .text ) ) {
_data = .; /* Data section */
__apstartup_start = .;
arch/e2k/boot/apstartup.o(.text)
__apstartup_end = .;
*(EXCLUDE_FILE (arch/e2k/boot/romstartup.o) .data .gnu.linkonce.d.*)
_edata = .; /* End of data section */
} > RAM
.bss : {
__bss_start = .; /* BSS */
*(EXCLUDE_FILE (arch/e2k/boot/romstartup.o) .bss COMMON)
__bss_stop = . ;
} > RAM
.initrd : {
. = ALIGN(4096);
*(.initrd)
} > ROMH
.symtable : {
. = ALIGN(4096);
*(.symtable)
} > ROMH
.strtable : {
. = ALIGN(4096);
*(.strtable)
} > ROMH
.text.startup : {
__startup_start = .;
arch/e2k/boot/romstartup.o(.text)
arch/e2k/boot/romstartup.o(.rodata)
arch/e2k/boot/romstartup.o(.data)
arch/e2k/boot/romstartup.o(.bss)
__startup_end = .;
. = ALIGN(2048); /* Round up the image size exactly to 16M. */
} > CPUSTART
/* Sections to be discarded */
/DISCARD/ : {
*(.info)
/* Do not bother with updating alternatives in boot,
* just discard the sections to reduce binary size. */
*(.altinstructions)
*(.altinstr_replacement)
}
__bios_start_code = ADDR(.text);
__bios_size_code = SIZEOF(.text);
__bios_start_data = ADDR(.text) + SIZEOF( .text );
__bios_size_data = SIZEOF(.data);
__bios_size_data_plus_bss = SIZEOF(.data) + SIZEOF( .bss );
/* lld compatibility items. These calculations may be not quite accurate. */
__bios_size_ld = SIZEOF ( .text );
__bios_fsize_ld = SIZEOF ( .text ) + SIZEOF ( .text ) + SIZEOF ( .bss );
__bios_entry_ld = _text - __startup_start;
}

42
arch/e2k/boot/apstartup.S Normal file
View File

@ -0,0 +1,42 @@
/* $Id: apstartup.S,v 1.3 2005/08/16 12:32:40 atic Exp $ */
//
// primary application processor startup module
//
#define WSZ 0x20 /* 20 quadwords */
#define RBS 0x10 /* 10 quadwords */
#define RSZ 0x10 /* 10 quadwords */
#define UPSR 0x1 /* fpu enabled */
#define OSEM_LO 0x0 /* no software traps enabled */
#define OSEM_HI 0x0
.text
.global apstart
.global loader
#ifdef CONFIG_SMP
.global aploader
#endif /* CONFIG_SMP */
// We are starting first steps on AP and branch to ap_loader(). See aploader.S
// Static memory allocation is defined by romloader.lds
apstart:
{
setwd wsz = WSZ
setbn rbs = RBS, rsz = RSZ, rcur = 0x0
setbp psz = 0
}
rws UPSR, %upsr
#ifdef CONFIG_SMP
addd 0, [aploader], %r0
#else
addd 0, [loader], %r0
#endif /* CONFIG_SMP */
movtd %r0, %ctpr1
rwd OSEM_LO, %osem
ct %ctpr1
.size apstart, . - apstart

View File

@ -0,0 +1,12 @@
ccflags-y += -DCONFIG_BOOT_E2K
obj-y := bios.o southbridge.o superio.o init_kbd.o \
newpci.o linuxpci.o io.o
obj-$(CONFIG_ENABLE_BIOS_MPTABLE) += mpspec.o mptable.o
obj-$(CONFIG_ENABLE_MGA) += mga.o
obj-y += video/

361
arch/e2k/boot/bios/bios.c Normal file
View File

@ -0,0 +1,361 @@
#include "bios.h"
#include <linux/pci_ids.h>
#include "pci.h"
#include "../Am85C30.h"
#if defined(CONFIG_LMS_CONSOLE)
extern void console_probe(void);
#endif
bios_hardware_t hardware = {0};
/*
* First part of BIOS initialization
*
* No any memory available yet. Minimum initializations for the moment.
*/
void bios_first(void)
{
#if defined(CONFIG_LMS_CONSOLE)
console_probe();
#endif
}
/*
* Rest of BIOS initialization
*
* Most of the job can be completed here. PCI should be inited before.
*/
#undef TEST_RDMA_REGS
#ifdef TEST_RDMA_REGS
static void test_rdma(void)
{
struct bios_pci_dev *dev;
unsigned int val = 0;
rom_printk("test_rdma: scanning for RDMA device on PCI bus\n");
dev = bios_pci_find_device(0x1544, 0x7112, 0); /* 0x71121544 - lms */
if (dev) {
rom_printk("found on bus %d device %d\n",
dev->bus->number, PCI_SLOT(dev->devfn));
}else{
rom_printk("!!! NOT FOUND !!!\n");
return;
}
rom_printk("test_rdma: check it's own bars\n");
rom_printk("test_rdma: bar[0] = 0x%x\n",dev->base_address[0]);
rom_printk("test_rdma: bar[1] = 0x%x\n",dev->base_address[1]);
rom_printk("RDMA controler regs : \n");
rom_printk("0 = 0x%x\n", *(u32*)(dev->base_address[0]));
rom_printk("1 = 0x%x\n", *(u32*)(dev->base_address[0] + 0x4));
rom_printk("2 = 0x%x\n", *(u32*)(dev->base_address[0] + 0x8));
rom_printk("3 = 0x%x\n", *(u32*)(dev->base_address[0] + 0xc));
pcibios_read_config_dword(dev->bus->number, dev->devfn, 0x00, &val);
rom_printk("conf space: 0x00 = 0x%x\n", val);
pcibios_read_config_dword(dev->bus->number, dev->devfn, 0x04, &val);
rom_printk("conf space: 0x04 = 0x%x\n", val);
pcibios_read_config_dword(dev->bus->number, dev->devfn, 0x08, &val);
rom_printk("conf space: 0x08 = 0x%x\n", val);
pcibios_read_config_dword(dev->bus->number, dev->devfn, 0x0c, &val);
rom_printk("conf space: 0x0c = 0x%x\n", val);
pcibios_read_config_dword(dev->bus->number, dev->devfn, 0x10, &val);
rom_printk("conf space: 0x10 = 0x%x\n", val);
pcibios_read_config_dword(dev->bus->number, dev->devfn, 0x14, &val);
rom_printk("conf space: 0x14 = 0x%x\n", val);
pcibios_read_config_dword(dev->bus->number, dev->devfn, 0x18, &val);
rom_printk("conf space: 0x18 = 0x%x\n", val);
}
#endif
#ifdef CONFIG_E2K_SIC
//#define TEST_FM33256
#ifdef TEST_FM33256
#include <asm/e2k_api.h>
#include <asm/mas.h>
#include <asm/e2k_debug.h>
#include <asm/e2k.h>
#include "printk.h"
#include "pci.h"
#define MAX_SPI_DEVICE_NR 3
#define SPI_CONTROL 0x00
#define SPI_STATUS 0x04
#define SPI_OPCODE 0x08
#define SPI_ADDRESS 0x0C
#define SPI_MODE 0x10
#define SPI_WREN_CMD 6
#define SPI_WRDI_CMD 4
#define SPI_WRSR_CMD 5
#define SPI_RDSR_CMD 1
#define SPI_READ_CMD 3
#define SPI_WRITE_CMD 2
#define SPI_RDPC_CMD 0x13
#define SPI_WRPC_CMD 0x12
#define SPI_STATUS_BUSY_SHIFT 0
#define SPI_STATUS_INTR_SHIFT 1
#define SPI_STATUS_FAIL_SHIFT 2
#define SPI_STATUS_BUSY (1 << SPI_STATUS_BUSY_SHIFT)
#define SPI_STATUS_INTR (1 << SPI_STATUS_INTR_SHIFT)
#define SPI_STATUS_FAIL (1 << SPI_STATUS_FAIL_SHIFT)
#define SPI_DEVICE_0 0
#define SPI_DEVICE_1 1
#define SPI_DEVICE_2 2
#define SPI_DEVICE_3 3
#define SPI_ADDRESS_SIZE_8 0
#define SPI_ADDRESS_SIZE_16 1
#define SPI_ADDRESS_SIZE_24 2
#define SPI_ADDRESS_SIZE_32 3
#define MAX_SPI_BYTES 64
#define SPI_DEVICE_SHIFT 0
#define MAX_SPI_ADDRESS_SIZE_SHIFT 3
#define SPI_ADDRESS_SIZE_SHIFT 2
#define SPI_DATA_SIZE_SHIFT 4
#define SPI_ADDRESS_PHASE_SHIFT 11
#define SPI_ADDRESS_PHASE_ENABLE (1 << SPI_ADDRESS_PHASE_SHIFT)
#define SPI_ADDRESS_PHASE_DISABLE (0 << SPI_ADDRESS_PHASE_SHIFT)
#define SPI_DATA_PHASE_SHIFT 12
#define SPI_DATA_PHASE_ENABLE (1 << SPI_DATA_PHASE_SHIFT)
#define SPI_DATA_PHASE_DISABLE (0 << SPI_DATA_PHASE_SHIFT)
#define SPI_TRANS_TYPE_SHIFT 13
#define SPI_TRANS_READ (0 << SPI_TRANS_TYPE_SHIFT)
#define SPI_TRANS_WRITE (1 << SPI_TRANS_TYPE_SHIFT)
#define SPI_START_SHIFT 14
#define SPI_START (1 << SPI_START_SHIFT)
#define SPI_KILL_SHIFT 15
#define SPI_KILL (1 << SPI_KILL_SHIFT)
static void error(char *x)
{
rom_puts("\n\n");
rom_puts(x);
rom_puts("\n\n -- System halted");
E2K_LMS_HALT_ERROR(0xdead); /* Halt */
}
struct i2c_spi {
unsigned long cntrl_base;
unsigned long data_base;
unsigned char dev_number;
};
struct i2c_spi i2c_spi;
/* cmos_addr - entire registers offset in
* Processor Companion case
* (SPI_RDPC_CMD or SPI_WRPC_CMD) or
* entire flash offset in the case of
* (SPI_READ_CMD or SPI_READ_CMD)
* i2c_spi_cntrl.cntrl_base i2c/spi control bar = bar[0] for pci device
* i2c_spi_cntrl.data_base i2c/spi memory buffer bar = bar[1] for pci device */
int spi_read(unsigned int cmos_addr)
{
unsigned long i2c_spi_cntrl = i2c_spi.cntrl_base;
unsigned long i2c_spi_data = i2c_spi.data_base;
unsigned char data;
unsigned int cmd = 0;
/* Set READ operation code */
E2K_WRITE_MAS_W(i2c_spi_cntrl + SPI_OPCODE, SPI_RDPC_CMD, MAS_IOADDR);
/* Set addr offset */
E2K_WRITE_MAS_W(i2c_spi_cntrl + SPI_ADDRESS, cmos_addr, MAS_IOADDR);
/* Set Device number, Address size, Data size offset */
cmd = i2c_spi.dev_number << SPI_DEVICE_SHIFT |
SPI_ADDRESS_SIZE_16 << SPI_ADDRESS_SIZE_SHIFT |
1 << SPI_DATA_SIZE_SHIFT |
SPI_ADDRESS_PHASE_ENABLE |
SPI_DATA_PHASE_ENABLE |
SPI_TRANS_READ |
SPI_START;
E2K_WRITE_MAS_W(i2c_spi_cntrl + SPI_CONTROL, cmd, MAS_IOADDR);
while((E2K_READ_MAS_W(i2c_spi_cntrl + SPI_STATUS, MAS_IOADDR) &
(SPI_STATUS_INTR | SPI_STATUS_FAIL)) == 0)
if (E2K_READ_MAS_W(i2c_spi_cntrl + SPI_STATUS, MAS_IOADDR) & SPI_STATUS_FAIL) {
rom_printk("spi_read: Error - Transfer Failed");
return -1;
}
data = E2K_READ_MAS_B(i2c_spi_data, MAS_IOADDR);
return (int)data;
}
int spi_ops(unsigned int dev_number, unsigned char cmd_code)
{
unsigned int cmd;
unsigned long i2c_spi_cntrl = i2c_spi.cntrl_base;
if (dev_number > MAX_SPI_DEVICE_NR) {
rom_printk("spi_ops: Error - Device number is to large: %d (Max: %d)", dev_number, MAX_SPI_DEVICE_NR);
return -1;
}
switch(cmd_code) {
case SPI_READ_CMD:
case SPI_WRITE_CMD:
case SPI_RDPC_CMD:
case SPI_WRPC_CMD:
rom_printk("spi_ops: Error - Wrong command code: %d", cmd_code);
return -1;
default:
break;
}
E2K_WRITE_MAS_W(i2c_spi_cntrl + SPI_OPCODE, cmd_code, MAS_IOADDR);
cmd = dev_number << SPI_DEVICE_SHIFT |
SPI_ADDRESS_PHASE_DISABLE |
SPI_DATA_PHASE_DISABLE |
SPI_START;
E2K_WRITE_MAS_W(i2c_spi_cntrl + SPI_CONTROL, cmd, MAS_IOADDR);
while((E2K_READ_MAS_W(i2c_spi_cntrl + SPI_STATUS, MAS_IOADDR) &
(SPI_STATUS_INTR | SPI_STATUS_FAIL)) == 0)
if (E2K_READ_MAS_W(i2c_spi_cntrl + SPI_STATUS, MAS_IOADDR) & SPI_STATUS_FAIL) {
rom_printk("spi_ops: Error - Operation Failed");
return -1;
}
return 1;
}
int spi_write(unsigned char val, unsigned int cmos_addr)
{
unsigned int cmd;
unsigned long i2c_spi_cntrl = i2c_spi.cntrl_base;
unsigned long i2c_spi_data = i2c_spi.data_base;
if(spi_ops(i2c_spi.dev_number, SPI_WREN_CMD) == -1) {
rom_printk("%s: Error - Failed to enable write operation", __FUNCTION__);
return -1;
}
E2K_WRITE_MAS_B(i2c_spi_data, val, MAS_IOADDR);
/* Set WRITE operation code */
E2K_WRITE_MAS_W(i2c_spi_cntrl + SPI_OPCODE, SPI_WRPC_CMD, MAS_IOADDR);
/* Set addr offset */
E2K_WRITE_MAS_W(i2c_spi_cntrl + SPI_ADDRESS, cmos_addr, MAS_IOADDR);
/* Set Device number, Address size, Data size offset */
cmd = i2c_spi.dev_number << SPI_DEVICE_SHIFT |
SPI_ADDRESS_SIZE_16 << SPI_ADDRESS_SIZE_SHIFT |
1 << SPI_DATA_SIZE_SHIFT |
SPI_ADDRESS_PHASE_ENABLE |
SPI_DATA_PHASE_ENABLE |
SPI_TRANS_READ |
SPI_START;
E2K_WRITE_MAS_W(i2c_spi_cntrl + SPI_CONTROL, cmd, MAS_IOADDR);
while((E2K_READ_MAS_W(i2c_spi_cntrl + SPI_STATUS, MAS_IOADDR) &
(SPI_STATUS_INTR | SPI_STATUS_FAIL)) == 0)
if (E2K_READ_MAS_W(i2c_spi_cntrl + SPI_STATUS, MAS_IOADDR) & SPI_STATUS_FAIL) {
rom_printk("spi_read: Error - Transfer Failed");
return -1;
}
return 1;
}
int cmos_read(unsigned int cmos_addr)
{
int data = spi_read(cmos_addr);
if (data == -1) {
rom_printk("%s: read operation failed", __FUNCTION__);
return -1;
}
return data;
}
int cmos_write(unsigned char val, unsigned int cmos_addr)
{
if (spi_write(val, cmos_addr) == -1) {
rom_printk("%s: write operation failed", __FUNCTION__);
return -1;
}
return 1;
}
void test_fm33256(void){
int tmp;
struct bios_pci_dev *dev;
rom_printk("test_fm33256: Scanning PCI bus for ioapic/pic/timer i2c/spi controller ...");
dev = bios_pci_find_device(INTEL_MULTIFUNC_VENDOR,
INTEL_MULTIFUNC_DEVICE, 0);
if (dev) {
rom_printk("found on bus %d device %d\n",
dev->bus->number, PCI_SLOT(dev->devfn));
}else{
rom_printk("!!! NOT FOUND !!!\n");
return;
}
rom_printk("test_fm33256: control base addr = 0x%x, data base addr = 0x%x\n",
(unsigned int)dev->base_address[0], (unsigned int)dev->base_address[1]);
i2c_spi.cntrl_base = dev->base_address[0];
i2c_spi.data_base = dev->base_address[1];
i2c_spi.dev_number = 1;
tmp = cmos_read(0x18);
rom_printk("test_fm33256: tmp = 0x%x\n", tmp);
}
#endif
#endif
void bios_rest(void)
{
#ifdef CONFIG_ENABLE_IOAPIC
#ifdef CONFIG_E2K_SIC
configure_pic_system();
configure_system_timer();
#ifdef CONFIG_SERIAL_AM85C30_BOOT_CONSOLE
zilog_serial_init();
#endif
#endif
#endif
#ifdef TEST_RDMA_REGS
test_rdma();
#endif
#ifdef CONFIG_E2K_SIC
#ifdef TEST_FM33256
test_fm33256();
#endif
#endif
#ifdef CONFIG_E2K_LEGACY_SIC
enable_embeded_graphic();
#else /* ! CONFIG_E2K_LEGACY_SIC */
#ifdef CONFIG_ENABLE_MGA
enable_mga();
#endif /* CONFIG_ENABLE_MGA */
#endif /* CONFIG_E2K_LEGACY_SIC */
}

41
arch/e2k/boot/bios/bios.h Normal file
View File

@ -0,0 +1,41 @@
void rom_printk(char const *fmt, ...);
extern void sb_enable_itself(void);
#ifndef CONFIG_E2K_SIC
extern void sb_enable_ioapic(void);
#endif
#ifdef CONFIG_E2K_SIC
extern void configure_pic_system(void);
extern void configure_system_timer(void);
#endif
extern void sb_enable_rtc(void);
extern void sb_enable_ide(void);
extern void enable_serial_ports(void);
extern void enable_parallel_port(void);
extern void enable_mouse(void);
extern void enable_keyboard(void);
extern void enable_rtc(void);
extern void enable_floppy(void);
extern void enable_mga(void);
extern void vga_init(void);
#ifdef CONFIG_E2K_LEGACY_SIC
extern void enable_embeded_graphic(void);
#endif /* CONFIG_E2K_LEGACY_SIC */
extern void init_kbd(void);
struct bios_hardware {
unsigned char serial :1;
unsigned char parallel :1;
unsigned char rtc :1;
unsigned char keyboard :1;
unsigned char mouse :1;
unsigned char floppy :1;
unsigned char video :1;
unsigned char dbgport :1;
};
typedef struct bios_hardware bios_hardware_t;
extern bios_hardware_t hardware;

View File

@ -0,0 +1,18 @@
/*
* $Id: ide_config.h,v 1.1 2006/03/30 16:53:22 kostin Exp $
* Southbridge configuration.
* IDE Configuration Registers (Function 1)
*/
#ifndef _IDE_CONFIG_H_
#define _IDE_CONFIG_H_
#define SB_PCICMD 0x4 // 0x4-0x5
#define SB_PCICMD_IOSE 0x1 // access to the Legacy IDE ports
#define SB_IDETIM 0x40 // 0x40-0x41=Primary Cnannel
// 0x42-0x43=Secondary Channel
#define SB_IDETIM_DECODE_ENABLE 0x8000
#define SB_IDETIM_SHIFT 16
#endif

View File

@ -0,0 +1,134 @@
#include <asm/head.h>
#include "init_kbd.h"
#include "../boot_io.h"
#undef DEBUG_KBD_MODE
#undef DebugKBD
#define DEBUG_KBD_MODE 0 /* keyboard debug */
#define DebugKBD if (DEBUG_KBD_MODE) rom_printk
void wait_kbd_write(void)
{
unsigned char in = bios_inb(KBD_STATUS_REG);
while (in & KBD_STAT_IBF) {
in = bios_inb(KBD_STATUS_REG);
}
}
void wait_kbd_read(void)
{
unsigned char in = bios_inb(KBD_STATUS_REG);
DebugKBD("wait_kbd_read() status 0x%x\n", in);
while ((~in) & KBD_STAT_OBF) {
in = bios_inb(KBD_STATUS_REG);
DebugKBD("wait_kbd_read() while status 0x%x\n", in);
}
}
void send_kbd_cmd(unsigned int cmd)
{
wait_kbd_write();
DebugKBD("send_kbd_cmd() cmd 0x%x\n", cmd);
bios_outb(cmd, KBD_CNTL_REG);
}
void send_kbd_data(unsigned int data)
{
wait_kbd_write();
DebugKBD("send_kbd_data() data out 0x%x\n", data);
bios_outb(data, KBD_DATA_REG);
}
unsigned int recv_kbd_data(void)
{
unsigned int in;
wait_kbd_read();
in = (unsigned int)bios_inb(KBD_DATA_REG);
DebugKBD("recv_kbd_data() data in 0x%x\n", in);
return in;
}
void init_kbd(void)
{
int check = 0;
rom_printk("kbd init ...\n");
// init KBC
send_kbd_cmd(KBD_CCMD_KBD_DISABLE);
check = 1;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_cmd(KBD_CCMD_SELF_TEST);
if (recv_kbd_data() != 0x55) goto failed;
check = 2;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_cmd(KBD_CCMD_GET_VERSION);
recv_kbd_data();
check = 3;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_cmd(KBD_CCMD_KBD_TEST);
if (recv_kbd_data() != 0x00) goto failed;
check = 4;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_cmd(KBD_CCMD_KBD_ENABLE);
//
check = 5;
DebugKBD("init_kbd() check #%d\n", check);
#if 1
send_kbd_data(KBD_CMD_RESET);
if (recv_kbd_data() != KBD_REPLY_ACK) goto failed;
if (recv_kbd_data() != KBD_REPLY_POR) goto failed;
check = 6;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_data(KBD_CMD_DISABLE);
if (recv_kbd_data() != KBD_REPLY_ACK) goto failed;
check = 7;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_data(KBD_CMD_SET_LEDS);
if (recv_kbd_data() != KBD_REPLY_ACK) goto failed;
check = 8;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_data(0x07);
if (recv_kbd_data() != KBD_REPLY_ACK) goto failed;
check = 9;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_data(KBD_CMD_ECHO);
if (recv_kbd_data() != 0xee) goto failed;
check = 10;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_data(KBD_CMD_READ_ID);
if (recv_kbd_data() != KBD_REPLY_ACK) goto failed;
check = 11;
DebugKBD("init_kbd() check #%d\n", check);
recv_kbd_data();
recv_kbd_data();
check = 12;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_data(KBD_CMD_SET_RATE);
if (recv_kbd_data() != KBD_REPLY_ACK) goto failed;
check = 13;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_data(0x0);
// if (recv_kbd_data() != KBD_REPLY_ACK) goto failed;
check = 14;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_data(KBD_CMD_SET_LEDS);
if (recv_kbd_data() != KBD_REPLY_ACK) goto failed;
check = 15;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_data(0x0);
if (recv_kbd_data() != KBD_REPLY_ACK) goto failed;
check = 16;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_data(KBD_CMD_ENABLE);
if (recv_kbd_data() != KBD_REPLY_ACK) goto failed;
check = 17;
DebugKBD("init_kbd() check #%d\n", check);
send_kbd_cmd(KBD_CCMD_WRITE_MODE);
send_kbd_data(KBD_MODE_KBD_INT | KBD_MODE_SYS | KBD_MODE_KCC);
#endif
rom_printk("kbd init passed ...\n");
return;
failed:
rom_printk("kbd init faled... check %d\n", check);
return;
}

View File

@ -0,0 +1,103 @@
#ifndef _INIT_KEYB_H_
#define _INIT_KEYB_H_
/*
* Keyboard Controller Registers
*
* NOTE: These are offsets from pcikbd_iobase, not absolute.
*/
#define KBD_STATUS_REG 0x64
#define KBD_CNTL_REG KBD_STATUS_REG
#define KBD_DATA_REG 0x60
/*
* Keyboard Controller Commands
*/
#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */
#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */
#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */
#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */
#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */
#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */
#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */
#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */
#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */
#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */
#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */
/*
* Keyboard Commands
*/
#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
#define KBD_CMD_ECHO 0xEE /* Echo */
#define KBD_CMD_READ_ID 0xF2 /* Get keyboard ID */
#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
#define KBD_CMD_DISABLE 0xF5 /* Disable scanning */
#define KBD_CMD_RESET 0xFF /* Reset */
/*
* Keyboard Replies
*/
#define KBD_REPLY_POR 0xAA /* Power on reset */
#define KBD_REPLY_ACK 0xFA /* Command ACK */
#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
/*
* Status Register Bits
*/
#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
#define KBD_STAT_SELFTEST 0x04 /* Self test successful */
#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */
#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */
#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */
#define KBD_STAT_PERR 0x80 /* Parity error */
#define AUX_STAT_OBF (KBD_STAT_OBF | KBD_STAT_MOUSE_OBF)
/*
* Controller Mode Register Bits
*/
#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generage IRQ1 */
#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */
#define KBD_MODE_SYS 0x04 /* The system flag (?) */
#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */
#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */
#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */
#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */
#define KBD_MODE_RFU 0x80
/*
* Mouse Commands
*/
#define AUX_SET_RES 0xE8 /* Set resolution */
#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
#define AUX_GET_SCALE 0xE9 /* Get scaling factor */
#define AUX_SET_STREAM 0xEA /* Set stream mode */
#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
#define AUX_RESET 0xFF /* Reset aux device */
#define KBD_INIT_TIMEOUT 1000 /* Timeout in ms for initializing the keyboard */
#define KBC_TIMEOUT 250 /* Timeout in ms for sending to keyboard controller */
#define KBD_TIMEOUT 1000 /* Timeout in ms for keyboard command acknowledge */
/* How to access the keyboard macros on this platform. */
#define kbd_read_input() inb(KBD_DATA_REG)
#define kbd_read_status() inb(KBD_STATUS_REG)
#define kbd_write_output(val) outb(val, KBD_DATA_REG)
#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
#define KBD_NO_DATA (-1) /* No data */
#define KBD_BAD_DATA (-2) /* Parity or other error */
#endif

623
arch/e2k/boot/bios/io.c Normal file
View File

@ -0,0 +1,623 @@
#include "pci.h"
#include <asm/types.h>
#include <asm/e2k_api.h>
#include <asm/head.h>
#include "../boot_io.h"
#undef DEBUG_IO
#undef DebugIO
#define DEBUG_IO 0
#define DebugIO if (DEBUG_IO) rom_printk
#undef DEBUG_IOH
#undef DebugIOH
#define DEBUG_IOH 0
#define DebugIOH if (DEBUG_IOH) rom_printk
#ifdef CONFIG_E2K_SIC
#define es2_domain_pci_conf_base(domain) (ES2_PCICFG_AREA_PHYS_BASE + \
ES2_PCICFG_AREA_SIZE * ((unsigned long) domain))
#define e2s_domain_pci_conf_base(domain) (E2S_PCICFG_AREA_PHYS_BASE + \
E2S_PCICFG_AREA_SIZE * ((unsigned long) domain))
#define e8c_domain_pci_conf_base(domain) (E8C_PCICFG_AREA_PHYS_BASE + \
E8C_PCICFG_AREA_SIZE * ((unsigned long) domain))
#define e1cp_domain_pci_conf_base(domain) (E1CP_PCICFG_AREA_PHYS_BASE)
#define e8c2_domain_pci_conf_base(domain) (E8C2_PCICFG_AREA_PHYS_BASE + \
E8C2_PCICFG_AREA_SIZE * ((unsigned long) domain))
#define e12c_domain_pci_conf_base(domain) (E12C_PCICFG_AREA_PHYS_BASE + \
E12C_PCICFG_AREA_SIZE * ((unsigned long) domain))
#define e16c_domain_pci_conf_base(domain) (E16C_PCICFG_AREA_PHYS_BASE + \
E16C_PCICFG_AREA_SIZE * ((unsigned long) domain))
#define e2c3_domain_pci_conf_base(domain) (E2C3_PCICFG_AREA_PHYS_BASE + \
E2C3_PCICFG_AREA_SIZE * ((unsigned long) domain))
static inline unsigned long bios_get_domain_pci_conf_base(unsigned int domain)
{
unsigned long conf_base;
#if defined(CONFIG_ES2)
conf_base = es2_domain_pci_conf_base(domain);
#elif defined(CONFIG_E2S)
conf_base = e2s_domain_pci_conf_base(domain);
#elif defined(CONFIG_E8C)
conf_base = e8c_domain_pci_conf_base(domain);
#elif defined(CONFIG_E8C2)
conf_base = e8c2_domain_pci_conf_base(domain);
#elif defined(CONFIG_E12C)
conf_base = e12c_domain_pci_conf_base(domain);
#elif defined(CONFIG_E16C)
conf_base = e16c_domain_pci_conf_base(domain);
#elif defined(CONFIG_E2C3)
conf_base = e2c3_domain_pci_conf_base(domain);
#else
#error "Invalid e2k machine type"
#endif /* CONFIG_E3S */
return (conf_base);
}
unsigned char bios_conf_inb(int domain, unsigned char bus, unsigned long port)
{
unsigned char byte;
unsigned long conf_base;
conf_base = bios_get_domain_pci_conf_base(domain);
port = conf_base + port;
byte = NATIVE_READ_MAS_B(port, MAS_IOADDR);
DebugIO("conf_inb(): value %x read from port %x\n",
(int) byte, (int) port);
return byte;
}
#endif
unsigned char bios_inb(unsigned short port)
{
unsigned char byte;
DebugIO("bios_inb entered.\n");
byte = NATIVE_READ_MAS_B(PHYS_X86_IO_BASE + port, MAS_IOADDR);
DebugIO("value %x read from port %x\n", (int) byte, (int) port);
DebugIO("bios_inb exited.\n");
return byte;
}
unsigned char bios_inb_p(unsigned long port)
{
unsigned char byte;
DebugIO("bios_inb_p entered.\n");
byte = NATIVE_READ_MAS_B(PHYS_X86_IO_BASE + port, MAS_IOADDR);
DebugIO("bios_inb_p exited.\n");
return byte;
}
void bios_outb_p(unsigned char byte, unsigned long port)
{
DebugIO("bios_outb_p entered.\n");
NATIVE_WRITE_MAS_B(PHYS_X86_IO_BASE + port, byte, MAS_IOADDR);
DebugIO("bios_outb_p exited.\n");
}
#ifdef CONFIG_E2K_SIC
void bios_conf_outb(int domain, unsigned char bus, unsigned char byte,
unsigned long port)
{
unsigned long conf_base;
conf_base = bios_get_domain_pci_conf_base(domain);
port = conf_base + port;
DebugIO("conf_outb(): port = %x\n", (int) port);
NATIVE_WRITE_MAS_B(port, byte, MAS_IOADDR);
DebugIO("conf_outb exited.\n");
}
void bios_ioh_e3s_outb(int domain, unsigned char bus, unsigned char byte,
unsigned long port)
{
unsigned long addr;
addr = IOHUB_SCRB_DOMAIN_START(domain);
addr += port;
NATIVE_WRITE_MAS_B(addr, byte, MAS_IOADDR);
DebugIOH("ioh_e3s_outb write 0x%x to domain %d bus 0x%x, port = 0x%x.\n",
byte, domain, bus, addr);
}
u8 bios_ioh_e3s_inb(int domain, unsigned char bus, unsigned long port)
{
unsigned long addr;
u8 byte;
addr = IOHUB_SCRB_DOMAIN_START(domain);
addr += port;
byte = NATIVE_READ_MAS_B(addr, MAS_IOADDR);
DebugIOH("bios_ioh_e3s_inb() read 0x%x from domain %d bus 0x%x, "
"port = 0x%x\n",
byte, domain, bus, addr);
return (byte);
}
#endif
void bios_outb(unsigned char byte, unsigned short port)
{
DebugIO("outb entered.\n");
NATIVE_WRITE_MAS_B(PHYS_X86_IO_BASE + port, byte, MAS_IOADDR);
DebugIO("outb exited.\n");
}
#ifdef CONFIG_E2K_SIC
void bios_conf_outw(int domain, unsigned char bus, u16 halfword,
unsigned long port)
{
unsigned long conf_base;
conf_base = bios_get_domain_pci_conf_base(domain);
port = conf_base + port;
DebugIO("conf_outw(): port = %x\n", (int) port);
NATIVE_WRITE_MAS_H(port, halfword, MAS_IOADDR);
DebugIO("conf_outw exited.\n");
}
void bios_ioh_e3s_outw(int domain, unsigned char bus, u16 halfword,
unsigned long port)
{
unsigned long addr;
addr = IOHUB_SCRB_DOMAIN_START(domain);
addr += port;
NATIVE_WRITE_MAS_H(addr, halfword, MAS_IOADDR);
DebugIOH("ioh_e3s_outw write 0x%x to domain %d bus 0x%x, port = 0x%x\n",
halfword, domain, bus, addr);
}
u16 bios_ioh_e3s_inw(int domain, unsigned char bus, unsigned long port)
{
unsigned long addr;
u16 halfword;
addr = IOHUB_SCRB_DOMAIN_START(domain);
addr += port;
halfword = NATIVE_READ_MAS_B(addr, MAS_IOADDR);
DebugIOH("bios_ioh_e3s_inw() read 0x%x from domain %d bus 0x%x, "
"port = 0x%x\n",
halfword, domain, bus, addr);
return (halfword);
}
#endif
void bios_outw(u16 halfword, unsigned short port)
{
DebugIO("outw entered.\n");
NATIVE_WRITE_MAS_H(PHYS_X86_IO_BASE + port, halfword, MAS_IOADDR);
DebugIO("outw exited.\n");
}
void bios_outw_p(u16 halfword, unsigned long port)
{
DebugIO("outw_p entered.\n");
NATIVE_WRITE_MAS_H(PHYS_X86_IO_BASE + port, halfword, MAS_IOADDR);
DebugIO("outw_p exited.\n");
}
#ifdef CONFIG_E2K_SIC
u16 bios_conf_inw(int domain, unsigned char bus, unsigned long port)
{
u16 hword;
unsigned long conf_base;
conf_base = bios_get_domain_pci_conf_base(domain);
port = conf_base + port;
hword = NATIVE_READ_MAS_H(port, MAS_IOADDR);
DebugIO("conf_inw(): value %x read from port %x\n",hword, (int)port);
DebugIO("conf_inw exited.\n");
return hword;
}
#endif
u16 bios_inw(unsigned short port)
{
u16 hword;
DebugIO("inw entered.\n");
hword = NATIVE_READ_MAS_H(PHYS_X86_IO_BASE + port, MAS_IOADDR);
DebugIO("inw exited.\n");
return hword;
}
u16 bios_inw_p(unsigned long port)
{
u16 hword;
DebugIO("inw_p entered.\n");
hword = NATIVE_READ_MAS_H(PHYS_X86_IO_BASE + port, MAS_IOADDR);
DebugIO("inw_p exited.\n");
return hword;
}
/*
* 'unsigned long' for I/O means 'u32', because IN/OUT ops are IA32-specific
*/
#ifdef CONFIG_E2K_SIC
void bios_conf_outl(int domain, unsigned char bus, u32 word, unsigned long port)
{
unsigned long conf_base;
conf_base = bios_get_domain_pci_conf_base(domain);
port = conf_base + port;
NATIVE_WRITE_MAS_W(port, word, MAS_IOADDR);
DebugIO("conf_outl exited.\n");
}
u32 bios_conf_inl(int domain, unsigned char bus, unsigned long port)
{
u32 word;
unsigned long conf_base;
conf_base = bios_get_domain_pci_conf_base(domain);
port = conf_base + port;
word = NATIVE_READ_MAS_W(port, MAS_IOADDR);
DebugIO("conf_inl(): value %x read from port %x\n",
(int) word, (int) port);
DebugIO("conf_inl exited.\n");
return word;
}
void bios_ioh_e3s_outl(int domain, unsigned char bus, u32 word,
unsigned long port)
{
unsigned long addr;
addr = IOHUB_SCRB_DOMAIN_START(domain);
addr += port;
NATIVE_WRITE_MAS_W(addr, word, MAS_IOADDR);
DebugIOH("ioh_e3s_outl write 0x%x to domain %d bus 0x%x, port = 0x%x\n",
word, domain, bus, addr);
}
u32 bios_ioh_e3s_inl(int domain, unsigned char bus, unsigned long port)
{
unsigned long addr;
u32 word;
addr = IOHUB_SCRB_DOMAIN_START(domain);
addr += port;
word = NATIVE_READ_MAS_W(addr, MAS_IOADDR);
DebugIOH("bios_ioh_e3s_inl read 0x%x from domain %d bus 0x%x, "
"port = 0x%x\n",
word, domain, bus, addr);
return (word);
}
#endif
void bios_outl(u32 word, unsigned short port)
{
DebugIO("outl entered.\n");
NATIVE_WRITE_MAS_W(PHYS_X86_IO_BASE + port, word, MAS_IOADDR);
DebugIO("outl exited.\n");
}
u32 bios_inl(unsigned short port)
{
u32 word;
DebugIO("inl entered.\n");
word = NATIVE_READ_MAS_W(PHYS_X86_IO_BASE + port, MAS_IOADDR);
DebugIO("inl(): value %x read from port %x\n", (int) word, (int) port);
DebugIO("inl exited.\n");
return word;
}
void bios_outll(unsigned long data, unsigned short port)
{
DebugIO("outb entered.\n");
NATIVE_WRITE_MAS_D(PHYS_X86_IO_BASE + port, data, MAS_IOADDR);
DebugIO("outb exited.\n");
}
unsigned long bios_inll(unsigned short port)
{
unsigned long dword;
DebugIO("inl entered.\n");
dword = NATIVE_READ_MAS_D(PHYS_X86_IO_BASE + port, MAS_IOADDR);
DebugIO("inl(): value %lx read from port %x\n",
(unsigned long)dword, (int)port);
DebugIO("inl exited.\n");
return dword;
}
static inline void fast_outw_p(u16 halfword, unsigned long port)
{
NATIVE_WRITE_MAS_H(PHYS_X86_IO_BASE + port, halfword, MAS_IOADDR);
}
void bios_outsw(unsigned long port, const void *src, unsigned long count)
{
u16 *hw_p = (u16 *)src;
DebugIO("outsw entered.\n");
DebugIO("outsw(): port=%lx src=%px count=%lx\n", port, src, count);
if (((unsigned long)src) & 0x1) {
rom_printk("outsw: memory address is not short aligned");
}
if (!count)
return;
while (count--) {
fast_outw_p(*hw_p++, port);
}
DebugIO("outsw exited.\n");
}
static inline u16 fast_inw_p(unsigned long port)
{
return NATIVE_READ_MAS_H(PHYS_X86_IO_BASE + port, MAS_IOADDR);
}
void bios_insw(unsigned long port, void *dst, unsigned long count)
{
u16 *hw_p = (u16 *)dst;
DebugIO("insw entered.\n");
DebugIO("insw(): port=%lx dst=%px count=%lx\n",port, dst, count);
if (((unsigned long)dst) & 0x1) {
rom_printk("insw: memory address is not short aligned");
}
if (!count)
return;
while (count--) {
*hw_p++ = fast_inw_p(port);
}
DebugIO("insw exited.\n");
}
/*
* Read COUNT 32-bit words from port PORT into memory starting at
* SRC. Now works with any alignment in SRC. Performance is important,
* but the interfaces seems to be slow: just using the inlined version
* of the bios_inl() breaks things.
*
* The source code was taken from Alpha's lib/io.c
*/
void bios_insl(unsigned long port, void *dst, unsigned long count)
{
unsigned int l = 0, l2;
if (!count)
return;
switch (((unsigned long) dst) & 0x3)
{
case 0x00: /* Buffer 32-bit aligned */
while (count--)
{
*(unsigned int *) dst = bios_inl(port);
dst += 4;
}
break;
/* Assuming little endian in cases 0x01 -- 0x03 ... */
case 0x02: /* Buffer 16-bit aligned */
--count;
l = bios_inl(port);
*(unsigned short *) dst = l;
dst += 2;
while (count--)
{
l2 = bios_inl(port);
*(unsigned int *) dst = l >> 16 | l2 << 16;
dst += 4;
l = l2;
}
*(unsigned short *) dst = l >> 16;
break;
case 0x01: /* Buffer 8-bit aligned */
--count;
l = bios_inl(port);
*(unsigned char *) dst = l;
dst += 1;
*(unsigned short *) dst = l >> 8;
dst += 2;
while (count--)
{
l2 = bios_inl(port);
*(unsigned int *) dst = l >> 24 | l2 << 8;
dst += 4;
l = l2;
}
*(unsigned char *) dst = l >> 24;
break;
case 0x03: /* Buffer 8-bit aligned */
--count;
l = bios_inl(port);
*(unsigned char *) dst = l;
dst += 1;
while (count--)
{
l2 = bios_inl(port);
*(unsigned int *) dst = l << 24 | l2 >> 8;
dst += 4;
l = l2;
}
*(unsigned short *) dst = l >> 8;
dst += 2;
*(unsigned char *) dst = l >> 24;
break;
}
}
/*
* Like insl but in the opposite direction. This is used by the IDE
* driver to write disk sectors. Works with any alignment in SRC.
* Performance is important, but the interfaces seems to be slow:
* just using the inlined version of the outl() breaks things.
*
* The source code was taken from Alpha's lib/io.c
*/
void bios_outsl(unsigned long port, const void *src, unsigned long count)
{
unsigned int l = 0, l2;
if (!count)
return;
switch (((unsigned long) src) & 0x3)
{
case 0x00: /* Buffer 32-bit aligned */
while (count--)
{
bios_outl(*(unsigned int *) src, port);
src += 4;
}
break;
case 0x02: /* Buffer 16-bit aligned */
--count;
l = *(unsigned short *) src << 16;
src += 2;
while (count--)
{
l2 = *(unsigned int *) src;
src += 4;
bios_outl(l >> 16 | l2 << 16, port);
l = l2;
}
l2 = *(unsigned short *) src;
bios_outl(l >> 16 | l2 << 16, port);
break;
case 0x01: /* Buffer 8-bit aligned */
--count;
l = *(unsigned char *) src << 8;
src += 1;
l |= *(unsigned short *) src << 16;
src += 2;
while (count--)
{
l2 = *(unsigned int *) src;
src += 4;
bios_outl(l >> 8 | l2 << 24, port);
l = l2;
}
l2 = *(unsigned char *) src;
bios_outl(l >> 8 | l2 << 24, port);
break;
case 0x03: /* Buffer 8-bit aligned */
--count;
l = *(unsigned char *) src << 24;
src += 1;
while (count--)
{
l2 = *(unsigned int *) src;
src += 4;
bios_outl(l >> 24 | l2 << 8, port);
l = l2;
}
l2 = *(unsigned short *) src;
src += 2;
l2 |= *(unsigned char *) src << 16;
bios_outl(l >> 24 | l2 << 8, port);
break;
}
}
/*
* Read COUNT 8-bit bytes from port PORT into memory starting at
* SRC.
*
* The source code was taken from Alpha's lib/io.c
*/
void bios_insb(unsigned long port, void *dst, unsigned long count)
{
while (((unsigned long)dst) & 0x3) {
if (!count)
return;
count--;
*(unsigned char *) dst = bios_inb(port);
dst += 1;
}
while (count >= 4) {
unsigned int w;
count -= 4;
w = bios_inb(port);
w |= bios_inb(port) << 8;
w |= bios_inb(port) << 16;
w |= bios_inb(port) << 24;
*(unsigned int *) dst = w;
dst += 4;
}
while (count) {
--count;
*(unsigned char *) dst = bios_inb(port);
dst += 1;
}
}
/*
* Like insb but in the opposite direction.
* Don't worry as much about doing aligned memory transfers:
* doing byte reads the "slow" way isn't nearly as slow as
* doing byte writes the slow way (no r-m-w cycle).
*
* The source code was taken from Alpha's lib/io.c
*/
void bios_outsb(unsigned long port, const void *src, unsigned long count)
{
while (count) {
count--;
bios_outb(*(char *)src, port);
src += 1;
}
}

View File

@ -0,0 +1,681 @@
/*
* $Id: linuxpci.c,v 1.10 2008/05/23 20:26:35 alexmipt Exp $
*
* PCI Bus Services, see include/linux/pci.h for further explanation.
*
* Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter,
* David Mosberger-Tang
*
* Copyright 1997 -- 1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*/
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/types.h>
#include <asm/e2k_api.h>
#include "asm/string.h"
#include <asm/cpu_regs_access.h>
#include <asm/head.h>
#include "pci.h"
#define GCC_WORKS_ON_O2 0
/**************************** DEBUG DEFINES *****************************/
#undef DEBUG_BOOT_MODE
#undef Dprintk
#define DEBUG_BOOT_MODE 0 /* PCI scanning */
#define Dprintk if (DEBUG_BOOT_MODE) rom_printk
#undef DEBUG_VERBOSE_BOOT_MODE
#undef VDprintk
#define DEBUG_VERBOSE_BOOT_MODE 0 /* verbose PCI scanning */
#define VDprintk if (DEBUG_VERBOSE_BOOT_MODE) rom_printk
/************************************************************************/
/**
* This is the root of the PCI tree. A PCI tree always has
* one bus, bus 0. Bus 0 contains devices and bridges.
*/
struct bios_pci_bus pci_root[MAX_NUMIOHUBS];
int pci_root_num = 0;
/// Linked list of PCI devices. ALL devices are on this list
struct bios_pci_dev *pci_devices = 0;
/// pointer to the last device */
static struct bios_pci_dev **pci_last_dev_p = &pci_devices;
/// We're going to probably delete this -- flag to add in reverse order */
static int pci_reverse = 0;
/**
* Given a bus and a devfn number, find the device structure
* @param bus The bus number
* @param devfn a device/function number
* @return pointer to the device structure
*/
struct bios_pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn)
{
struct bios_pci_dev *dev;
for (dev = pci_devices; dev; dev = dev->next)
if (dev->bus->number == bus && dev->devfn == devfn)
break;
return dev;
}
/** Find a device of a given vendor and type
* @param vendor Vendor ID (e.g. 0x8086 for Intel)
* @param device Device ID
* @param from Pointer to the device structure, used as a starting point
* in the linked list of devices, which can be 0 to start at the
* head of the list (i.e. pci_devices)
* @return Pointer to the device struct
*/
struct bios_pci_dev *bios_pci_find_device(unsigned int vendor,
unsigned int device, struct bios_pci_dev *from)
{
if (!from)
from = pci_devices;
else
from = from->next;
while (from && (from->vendor != vendor || from->device != device))
from = from->next;
return from;
}
/** Find a device of a given class
* @param class Class of the device
* @param from Pointer to the device structure, used as a starting point
* in the linked list of devices, which can be 0 to start at the
* head of the list (i.e. pci_devices)
* @return Pointer to the device struct
*/
struct bios_pci_dev *pci_find_class(unsigned int class,
struct bios_pci_dev *from)
{
if (!from)
from = pci_devices;
else
from = from->next;
while (from && from->class != class)
from = from->next;
return from;
}
/** Given a device, set the PCI_COMMAND_MASTER bit in the command register
* @param dev Pointer to the device structure
*/
void bios_pci_set_master(struct bios_pci_dev *dev)
{
u16 cmd;
u8 lat;
bios_pci_read_config_word(dev, PCI_COMMAND, &cmd);
if (!(cmd & PCI_COMMAND_MASTER)) {
printk_debug("PCI: Enabling bus mastering for device %02x:%02x\n",
dev->bus->number, dev->devfn);
cmd |= PCI_COMMAND_MASTER;
bios_pci_write_config_word(dev, PCI_COMMAND, cmd);
}
bios_pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
if (lat < 16) {
printk_debug("PCI: Increasing latency timer of device %02x:%02x to 64\n",
dev->bus->number, dev->devfn);
bios_pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
}
}
/** Given a device and register, read the size of the BAR for that register.
* @param dev Pointer to the device structure
* @param reg Which register to use
* @param addr Address to load into the register after size is found
*/
void pci_get_size(struct bios_pci_dev *dev, unsigned long reg,
unsigned long addr)
{
u32 size;
unsigned long type;
/* FIXME: more consideration for 64-bit PCI devices */
// get the size
bios_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2), ~0);
bios_pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2),
&size);
// restore addr
bios_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2),
addr);
// some broken hardware has read-only registers that do not
// really size correctly. You can tell this if addr == size
// Example: the acer m7229 has BARs 1-4 normally read-only.
// so BAR1 at offset 0x10 reads 0x1f1. If you size that register
// by writing 0xffffffff to it, it will read back as 0x1f1 -- a
// violation of the spec.
// We catch this case and ignore it by settting size and type to 0.
// This incidentally catches the common case where registers
// read back as 0 for both address and size.
#if 0 /* DON'T WORk on E2K */
if (addr == size) {
printk_debug(
"pci_get_size: dev_fn 0x%x, register %d, read-only"
" SO, ignoring it\n",
dev->devfn, reg);
printk_debug("addr was 0x%x, size was 0x%x\n",addr,size);
type = 0;
size = 0;
}
// Now compute the actual size, See PCI Spec 6.2.5.1 ...
else
#endif
if (size & PCI_BASE_ADDRESS_SPACE_IO) {
type = size & (~PCI_BASE_ADDRESS_IO_MASK);
size &= (PCI_BASE_ADDRESS_IO_MASK);
// BUG! Top 16 bits can be zero (or not)
// So set them to 0xffff so they go away ...
size |= 0xffff0000;
size = ~size;
size++;
} else {
type = size & (~PCI_BASE_ADDRESS_MEM_MASK);
size &= (PCI_BASE_ADDRESS_MEM_MASK);
size = ~size;
size++;
}
dev->size[reg] = size | type;
Dprintk("BAR%d = %x (size %x, type %x)\n",
reg, size | type, size, type);
}
/** Read the base address registers for a given device.
* @param dev Pointer to the dev structure
* @param howmany How many registers to read (6 for device, 2 for bridge)
*/
void pci_read_bases(struct bios_pci_dev *dev, unsigned int howmany)
{
unsigned int reg;
u32 /* unsigned long for 64 bits ?? */ addr;
/* FIXME: to deal with 64-bits PCI */
Dprintk("pci_read_bases bus 0x%x, devfn 0x%x\n",
dev->bus->number, dev->devfn);
for (reg = 0; reg < howmany; reg++) {
bios_pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + (reg << 2),
&addr);
if (addr == 0xffffffff)
continue;
/* get address space size */
pci_get_size(dev, reg, addr);
addr &= (PCI_BASE_ADDRESS_SPACE |
PCI_BASE_ADDRESS_MEM_TYPE_MASK);
if (addr == (PCI_BASE_ADDRESS_SPACE_MEMORY |
PCI_BASE_ADDRESS_MEM_TYPE_64)) {
printk_debug("reg %d is 64-bit\n", reg);
/* this is a 64-bit memory base address */
reg++;
bios_pci_read_config_dword(dev,
PCI_BASE_ADDRESS_0 + (reg << 2), &addr);
if (addr) {
#if BITS_PER_LONG == 64
dev->base_address[reg - 1] |=
((unsigned long) addr) << 32;
#else
printk_err("PCI: Unable to handle 64-bit "
"address for device %02x:%02x\n",
dev->bus->number, dev->devfn);
dev->base_address[reg - 1] = 0;
#endif
}
}
}
}
/*
* Find the extent of a PCI decode..
*/
static unsigned int pci_size(unsigned int base, unsigned int maxbase, unsigned long mask)
{
unsigned int size = mask & maxbase; /* Find the significant bits */
if (!size)
return 0;
// Dprintk("pci_size: base = %x maxbase = %x\n", base, maxbase);
/* Get the lowest of them to find the decode size, and
from that the extent. */
size = (size & ~(size-1)) ; /* - 1; NEEDSWORK: Linar */
/* base == maxbase can be valid only if the BAR has
already been programmed with all 1s. */
if (base == maxbase && ((base | size) & mask) != mask)
return 0;
return size;
}
#ifdef CONFIG_E2K_SIC
/* That means the level of buses hierarchy. The 0 level means the main bus called
* the pci_root. The main bus may has several subbuses due to the CPU amount.
* Each system on CPU has its own PCI2PCI bridge that serves the link between
* the main bus pci_root and other devices chiped in that system on CPU. So each
* system has its own configuration space. */
int level = -1;
#endif
/** Scan the bus, first for bridges and next for devices.
* @param bios_pci_bus pointer to the bus structure
* @return The maximum bus number found, after scanning all subordinate busses
*/
static unsigned int bios_pci_scan_bus(struct bios_pci_bus *bus)
{
unsigned int devfn, max;
struct bios_pci_dev *dev, **bus_last;
struct bios_pci_bus *child;
int domain = bios_pci_domain_nr(bus);
#if 0
unsigned int msg_st[2], msg_end[2];
unsigned long start, end;
#endif
#ifdef CONFIG_E2K_SIC
/* Each time we enter the bios_pci_scan_bus function we must to
* encrease the bus hierarchy level */
level++;
Dprintk("PCI #%d: bios_pci_scan_bus enter for level %d\n",
domain, level);
#endif
Dprintk("PCI #%d: bios_pci_scan_bus for bus %d\n",
domain, bus->number);
bus_last = &bus->devices;
max = bus->secondary;
/* probe all devices on this bus with some optimization for non-existance and
single funcion devices */
for (devfn = 0; devfn < 0xff; devfn++) {
u32 id, class, addr, size;
u8 cmd, tmp, hdr_type;
u16 subsystem;
#if 0
u32 tmphdr;
#endif /* 0 */
// gcc just went to hell. Don't test -- this always
// returns 0 anyway.
#if GCC_WORKS_ON_O2
if (pcibios_read_config_dword(domain, bus->number, devfn, PCI_VENDOR_ID, &id)) {
printk_spew("PCI #%d: devfn 0x%x, read_config_dword fails\n",
domain, devfn);
continue;
}
#endif
pcibios_read_config_dword(domain, bus->number, devfn, PCI_VENDOR_ID, &id);
/* some broken boards return 0 if a slot is empty: */
if (id == 0xffffffff || id == 0x00000000 || id == 0x0000ffff || id == 0xffff0000) {
VDprintk("PCI #%d: devfn 0x%x, bad id 0x%x\n",
domain, devfn, id);
if (PCI_FUNC(devfn) == 0x00) {
/* if this is a function 0 device and it is not present,
skip to next device */
devfn += 0x07;
}
/* multi function device, skip to next function */
continue;
}
if (pcibios_read_config_byte(domain, bus->number, devfn, PCI_HEADER_TYPE, &hdr_type)){
Dprintk("PCI #%d: devfn 0x%x, header type read fails\n",
domain, devfn);
continue;
}
if (pcibios_read_config_dword(domain, bus->number, devfn, PCI_CLASS_REVISION, &class)) {
Dprintk("PCI #%d: devfn 0x%x, class read fails\n",
domain, devfn);
continue;
}
if (pcibios_read_config_word(domain, bus->number, devfn, PCI_SUBSYSTEM_ID, &subsystem)){
Dprintk("PCI #%d: devfn 0x%x, subsystem id read fails\n",
domain, devfn);
continue;
}
if ((dev = malloc(sizeof(*dev))) == 0) {
printk_err("PCI: out of memory.\n");
continue;
}
memset(dev, 0, sizeof(*dev));
dev->bus = bus;
dev->devfn = devfn;
dev->vendor = id & 0xffff;
dev->device = (id >> 16) & 0xffff;
dev->hdr_type = hdr_type;
dev->revision = (unsigned char) class & 0xff;
/* class code, the upper 3 bytes of PCI_CLASS_REVISION */
dev->class = class >> 8;
class >>= 16;
dev->subsys_id = subsystem ;
/* non-destructively determine if device can be a master: */
pcibios_read_config_byte(domain, bus->number, devfn,
PCI_COMMAND, &cmd);
pcibios_write_config_byte(domain, bus->number, devfn,
PCI_COMMAND,
cmd | PCI_COMMAND_MASTER);
pcibios_read_config_byte(domain, bus->number, devfn,
PCI_COMMAND, &tmp);
dev->master = ((tmp & PCI_COMMAND_MASTER) != 0);
pcibios_read_config_byte(domain, bus->number, devfn,
PCI_COMMAND, &cmd);
Dprintk("PCI %d:%d:%d:%d CMD %02x\n",
domain, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn),
cmd);
switch (hdr_type & 0x7f) { /* header type */
case PCI_HEADER_TYPE_NORMAL: /* standard header */
Dprintk("PCI #%d: detected header type PCI_HEADER_TYPE_NORMAL\n",
domain);
if (class == PCI_CLASS_BRIDGE_PCI)
goto bad;
/* read base address registers, again pci_fixup() can tweak these */
pci_read_bases(dev, 6);
pcibios_read_config_dword(domain, bus->number, devfn, PCI_ROM_ADDRESS, &addr);
pcibios_write_config_dword(domain, bus->number, devfn, PCI_ROM_ADDRESS, ~PCI_ROM_ADDRESS_ENABLE);
pcibios_read_config_dword(domain, bus->number, devfn, PCI_ROM_ADDRESS, &size);
pcibios_write_config_dword(domain, bus->number, devfn, PCI_ROM_ADDRESS, addr);
if (addr == 0xffffffff)
addr = 0;
if (size && size != 0xffffffff) {
size = pci_size(addr, size, PCI_ROM_ADDRESS_MASK);
if (size) {
dev->rom_address = addr;
dev->rom_address &= PCI_ROM_ADDRESS_MASK;
dev->rom_size = size;
}
}
break;
case PCI_HEADER_TYPE_BRIDGE: /* bridge header */
Dprintk("PCI #%d: detected header type PCI_HEADER_TYPE_BRIDGE\n",
domain);
if (class != PCI_CLASS_BRIDGE_PCI)
goto bad;
pci_read_bases(dev, 2);
pcibios_read_config_dword(domain, bus->number, devfn, PCI_ROM_ADDRESS1, &addr);
dev->rom_address = (addr == 0xffffffff) ? 0 : addr;
break;
case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */
Dprintk("PCI #%d: detected header type PCI_HEADER_TYPE_CARDBUS\n",
domain);
if (class != PCI_CLASS_BRIDGE_CARDBUS)
goto bad;
pci_read_bases(dev, 1);
break;
default: /* unknown header */
bad:
printk_err("PCI: %02x:%02x [%04x/%04x/%06x] has unknown header "
"type %02x, ignoring.\n",
bus->number, dev->devfn, dev->vendor, dev->device, class,
hdr_type);
continue;
}
Dprintk("PCI #%d: %02x:%02x [%04x/%04x]\n",
domain, bus->number, dev->devfn,
dev->vendor, dev->device);
/* Put it into the global PCI device chain. It's used to find devices once
everything is set up. */
if (!pci_reverse) {
*pci_last_dev_p = dev;
pci_last_dev_p = &dev->next;
} else {
dev->next = pci_devices;
pci_devices = dev;
}
/* Now insert it into the list of devices held by the parent bus. */
*bus_last = dev;
bus_last = &dev->sibling;
if (PCI_FUNC(devfn) == 0x00 && (hdr_type & 0x80) != 0x80) {
/* if this is not a multi function device, don't waste time probe
another function. Skip to next device. */
devfn += 0x07;
}
}
/*
* The fixup code may have just found some peer pci bridges on this
* machine. Update the max variable if that happened so we don't
* get duplicate bus numbers.
*/
for (dev = bus->devices; dev; dev = dev->sibling)
/* If it's a bridge, scan the bus behind it. */
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
u32 buses;
unsigned int devfn = dev->devfn;
unsigned short cr;
#define NOTUSED
#ifdef NOTUSED
/*
* Check for a duplicate bus. If we already scanned
* this bus number as a peer bus, don't also scan it
* as a child bus
*/
if (((dev->vendor == PCI_VENDOR_ID_SERVERWORKS) &&
((dev->device == PCI_DEVICE_ID_SERVERWORKS_HE) ||
(dev->device == PCI_DEVICE_ID_SERVERWORKS_LE))) ||
((dev->vendor == PCI_VENDOR_ID_INTEL) &&
((dev->device == PCI_DEVICE_ID_INTEL_82454NX)||
(dev->device == PCI_DEVICE_ID_INTEL_82451NX))))
continue;
/* Read the existing primary/secondary/subordinate bus number
configuration to determine if the PCI bridge has already been
configured by the system. If so, check to see if we've already
scanned this bus as a result of peer bus scanning, if so, skip this.
FIMXE: We are BIOS, is there anyone else doing this dirty job BEFORE us ?? */
pcibios_read_config_dword(domain, bus->number, devfn, PCI_PRIMARY_BUS, &buses);
if ((buses & 0xFFFFFF) != 0) {
for (child = pci_root[domain].next; child; child = child->next)
if (child->number == ((buses >> 8) & 0xff))
goto skip_it;
}
#endif
/* Insert it into the tree of buses. */
if ((child = malloc(sizeof(*child))) == 0) {
printk_err("PCI: out of memory for bridge.\n");
continue;
}
memset(child, 0, sizeof(*child));
child->next = bus->children;
bus->children = child;
child->self = dev;
child->parent = bus;
/* Set up the primary, secondary and subordinate bus numbers. We have
no idea how many buses are behind this bridge yet, so we set the
subordinate bus number to 0xff for the moment */
bios_set_pci_domain_nr(child, domain);
child->number = child->secondary = ++max;
child->primary = bus->secondary;
child->subordinate = 0xff;
#ifdef CONFIG_E2K_SIC
/* you are programming the main bus bridges when
* the level is 0
* FIXME must be reconstructed using NSR number
* FIXME now for 1 iohub only
*/
if (child->number >= 255) {
Dprintk("bios_pci_scan_bus: too large amount "
"of bridges,encrease the option "
"please!!!\n");
break;
}
#endif
/* Clear all status bits and turn off memory, I/O and master enables. */
pcibios_read_config_word(domain, bus->number, devfn, PCI_COMMAND, &cr);
pcibios_write_config_word(domain, bus->number, devfn, PCI_COMMAND, 0x0000);
pcibios_write_config_word(domain, bus->number, devfn, PCI_STATUS, 0xffff);
/*
* Read the existing primary/secondary/subordinate bus
* number configuration to determine if the PCI bridge
* has already been configured by the system. If so,
* do not modify the configuration, merely note it.
*/
pcibios_read_config_dword(domain, bus->number, devfn, PCI_PRIMARY_BUS, &buses);
#ifdef BRIDGE_CONFIGURED_AT_POWERUP
// There is some hardware (ALPHA) that configures bridges in hardware, at bootup.
// We need to take that into account at some point.
// At the same time, we're finding buggy bridge hardware that comes up
// with these registers non-zero (VIA VT8601). Hence this #ifdef -- in some cases,
// you should never check the buses; in other cases, you have no choice.
if ((buses & 0xFFFFFF) != 0) {
unsigned int cmax;
child->primary = buses & 0xFF;
child->secondary = (buses >> 8) & 0xFF;
child->subordinate = (buses >> 16) & 0xFF;
child->number = child->secondary;
cmax = bios_pci_scan_bus(child);
if (cmax > max)
max = cmax;
} else
#endif
{
/* Configure the bus numbers for this bridge: the configuration
transactions will not be propagated by the bridge if it is not
correctly configured */
buses &= 0xff000000;
buses |= (((unsigned int) (child->primary) << 0) |
((unsigned int) (child->secondary) << 8) |
((unsigned int) (child->subordinate) << 16));
pcibios_write_config_dword(domain, bus->number, devfn,
PCI_PRIMARY_BUS, buses);
#ifdef CONFIG_E2K_SIC
#ifndef CONFIG_L_IOH2
/* Here we need to setup system commutator register for PCI bridges
* (PCI Bridge Bus Number Reg - 0x18 - 0x1b ) that is in accordance with
* that of current bridge. We are interested only Subordinate Bus Number
* and Secondary Bus Number fields so it is useless to write Primary.
* According to iset manual aren't required for virtual PCI_2_PCI on
* bus 0 */
if ((dev->device !=
PCI_DEVICE_ID_MCST_VIRT_PCI_BRIDGE) &&
(dev->device !=
PCI_DEVICE_ID_MCST_PCIE_BRIDGE)) {
Dprintk("PCI #%d: bios_pci_scan_bus: "
"setup iohub for buses\n",
domain);
system_commutator_es2_ioh_write_dword(
domain, bus->number, B1_BN,
buses);
} else if (dev->device ==
PCI_DEVICE_ID_MCST_VIRT_PCI_BRIDGE) {
unsigned long scrb_base;
unsigned char iohub_num;
pcibios_read_config_byte(domain,
bus->number, devfn,
IOHUB_DevNum, &iohub_num);
Dprintk("PCI #%d: bios_pci_scan_bus: "
"IOHUB.DevNum = 0x%x\n",
domain, iohub_num);
scrb_base =
IOHUB_SCRB_DOMAIN_START(domain);
/* Setup SCBA_0, SCBA_1 seems to be 0.
* If E2K_SCRB_PHYS_BASE has
* more then 32 bits you should setup
* SCBA_1 register. Its only for
* virtual PCI_2_PCI BRIDGE
*/
Dprintk("PCI #%d: bios_pci_scan_bus: "
"setup for SCRB table ... "
"virtual PCI_2_PCI on bus 0x%x "
"slot %d func %d\n",
domain, bus->number,
PCI_SLOT(devfn),
PCI_FUNC(devfn));
pcibios_write_config_dword(domain,
bus->number, devfn, PCI_SCBA_0,
(scrb_base | 0x1));
Dprintk("PCI #%d: bios_pci_scan_bus: "
"SCBA_0 = 0x%x\n",
domain, (scrb_base | 0x1));
}
#endif /* ! CONFIG_L_IOH2 */
#endif
/* Now we can scan all subordinate buses i.e. the bus hehind the bridge */
max = bios_pci_scan_bus(child);
/* We know the number of buses behind this
* bridge. Set the subordinate
* bus number to its real value
*/
child->subordinate = max;
buses = (buses & 0xff00ffff) |
((unsigned int) (child->subordinate) <<
16);
pcibios_write_config_dword(domain, bus->number,
devfn, PCI_PRIMARY_BUS, buses);
#ifdef CONFIG_E2K_SIC
#ifndef CONFIG_L_IOH2
if ((dev->device !=
PCI_DEVICE_ID_MCST_VIRT_PCI_BRIDGE) &&
(dev->device !=
PCI_DEVICE_ID_MCST_PCIE_BRIDGE)) {
system_commutator_es2_ioh_write_dword(
domain, bus->number, B1_BN,
buses);
}
#endif /* ! CONFIG_L_IOH2 */
#endif
Dprintk("PCI #%d: bios_pci_scan_bus: found "
"Bridge, primary = %d, number = %d, "
"subordinate = %d\n",
domain, child->primary, child->number,
child->subordinate);
}
pcibios_write_config_word(domain, bus->number, devfn,
PCI_COMMAND, cr);
skip_it:
;
}
/*
* We've scanned the bus and so we know all about what's on
* the other side of any bridges that may be on this bus plus
* any devices.
*
* Return how far we've got finding sub-buses.
*/
Dprintk("PCI #%d: bios_pci_scan_bus returning with max=%02x\n",
domain, max);
#ifdef CONFIG_E2K_SIC
/* Each time we leave bios_pci_scan_bus function we must to decrease
* the bus hierarchy level */
level--;
#endif
return max;
}
/** Initialize pci root struct, then scan starting at the root.
* Note that this function will recurse at each bridge.
*/
struct bios_pci_bus *pci_init(domain)
{
struct bios_pci_bus *root_bus;
root_bus = &pci_root[pci_root_num];
memset(root_bus, 0, sizeof(*root_bus));
bios_set_pci_domain_nr(root_bus, domain);
set_iohub_dev_num(domain);
pci_root->subordinate = bios_pci_scan_bus(root_bus);
pci_root_num ++;
return (root_bus);
}

View File

@ -0,0 +1,194 @@
/*
* $Id: mc146818rtc.h,v 1.7 2006/11/10 15:39:48 kostin Exp $
*/
#ifndef _MCRTC_
#define _MCRTC_
#include "../boot_io.h"
#define RTC_BASE_PORT 0x70
#define RTC_PORT(x) (RTC_BASE_PORT + (x))
/* On PCs, the checksum is built only over bytes 16..45 */
#define PC_CKS_RANGE_START 16
#define PC_CKS_RANGE_END 45
#define PC_CKS_LOC 46
/* Linux bios checksum is built only over bytes 49..125 */
#define LB_CKS_RANGE_START 49
#define LB_CKS_RANGE_END 125
#define LB_CKS_LOC 126
#define CMOS_READ(addr) ({ \
bios_outb((addr), RTC_PORT(0)); \
bios_inb(RTC_PORT(1)); \
})
#define CMOS_WRITE(val, addr) ({ \
bios_outb((addr), RTC_PORT(0)); \
bios_outb((val), RTC_PORT(1)); \
})
/* control registers - Moto names
*/
#define RTC_REG_A 10
#define RTC_REG_B 11
#define RTC_REG_C 12
#define RTC_REG_D 13
/**********************************************************************
* register details
**********************************************************************/
#define RTC_FREQ_SELECT RTC_REG_A
/* update-in-progress - set to "1" 244 microsecs before RTC goes off the bus,
* reset after update (may take 1.984ms @ 32768Hz RefClock) is complete,
* totalling to a max high interval of 2.228 ms.
*/
# define RTC_UIP 0x80
# define RTC_DIV_CTL 0x70
/* divider control: refclock values 4.194 / 1.049 MHz / 32.768 kHz */
# define RTC_REF_CLCK_4MHZ 0x00
# define RTC_REF_CLCK_1MHZ 0x10
# define RTC_REF_CLCK_32KHZ 0x20
/* 2 values for divider stage reset, others for "testing purposes only" */
# define RTC_DIV_RESET1 0x60
# define RTC_DIV_RESET2 0x70
/* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */
# define RTC_RATE_SELECT 0x0F
# define RTC_RATE_NONE 0x00
# define RTC_RATE_32786HZ 0x01
# define RTC_RATE_16384HZ 0x02
# define RTC_RATE_8192HZ 0x03
# define RTC_RATE_4096HZ 0x04
# define RTC_RATE_2048HZ 0x05
# define RTC_RATE_1024HZ 0x06
# define RTC_RATE_512HZ 0x07
# define RTC_RATE_256HZ 0x08
# define RTC_RATE_128HZ 0x09
# define RTC_RATE_64HZ 0x0a
# define RTC_RATE_32HZ 0x0b
# define RTC_RATE_16HZ 0x0c
# define RTC_RATE_8HZ 0x0d
# define RTC_RATE_4HZ 0x0e
# define RTC_RATE_2HZ 0x0f
/**********************************************************************/
#define RTC_CONTROL RTC_REG_B
# define RTC_SET 0x80 /* disable updates for clock setting */
# define RTC_PIE 0x40 /* periodic interrupt enable */
# define RTC_AIE 0x20 /* alarm interrupt enable */
# define RTC_UIE 0x10 /* update-finished interrupt enable */
# define RTC_SQWE 0x08 /* enable square-wave output */
# define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */
# define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */
# define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */
/**********************************************************************/
#define RTC_INTR_FLAGS RTC_REG_C
/* caution - cleared by read */
# define RTC_IRQF 0x80 /* any of the following 3 is active */
# define RTC_PF 0x40
# define RTC_AF 0x20
# define RTC_UF 0x10
/**********************************************************************/
#define RTC_VALID RTC_REG_D
# define RTC_VRT 0x80 /* valid RAM and time */
/**********************************************************************/
#if 0
static int rtc_checksum_valid(int range_start, int range_end, int cks_loc)
{
int i;
unsigned sum, old_sum;
sum = 0;
for(i = range_start; i <= range_end; i++) {
sum += CMOS_READ(i);
}
sum = (~sum)&0x0ffff;
old_sum = ((CMOS_READ(cks_loc)<<8) | CMOS_READ(cks_loc+1))&0x0ffff;
return sum == old_sum;
}
static void rtc_set_checksum(int range_start, int range_end, int cks_loc)
{
int i;
unsigned sum;
sum = 0;
for(i = range_start; i <= range_end; i++) {
sum += CMOS_READ(i);
}
sum = ~(sum & 0x0ffff);
CMOS_WRITE(((sum >> 8) & 0x0ff), cks_loc);
CMOS_WRITE(((sum >> 0) & 0x0ff), cks_loc+1);
}
#endif
#define RTC_CONTROL_DEFAULT (RTC_24H)
#define RTC_FREQ_SELECT_DEFAULT (RTC_REF_CLCK_32KHZ | RTC_RATE_1024HZ)
static inline void rtc_init(int invalid)
{
// unsigned char x;
// int cmos_invalid, checksum_invalid;
rom_printk("RTC Init\n");
#if 0
/* See if there has been a CMOS power problem. */
x = CMOS_READ(RTC_VALID);
cmos_invalid = !(x & RTC_VRT);
/* See if there is a CMOS checksum error */
checksum_invalid = !rtc_checksum_valid(PC_CKS_RANGE_START,
PC_CKS_RANGE_END,PC_CKS_LOC);
if (invalid || cmos_invalid || checksum_invalid) {
// int i;
rom_printk("RTC:%s%s%s zeroing cmos\n",
invalid?" Clear requested":"",
cmos_invalid?" Power Problem":"",
checksum_invalid?" Checksum invalid":"");
CMOS_WRITE(0, 0x01);
CMOS_WRITE(0, 0x03);
CMOS_WRITE(0, 0x05);
for(i = 10; i < 48; i++) {
CMOS_WRITE(0, i);
}
if (cmos_invalid) {
/* Now setup a default date of Sat 1 January 2000 */
CMOS_WRITE(0, 0x00); /* seconds */
CMOS_WRITE(0, 0x02); /* minutes */
CMOS_WRITE(1, 0x04); /* hours */
CMOS_WRITE(7, 0x06); /* day of week */
CMOS_WRITE(1, 0x07); /* day of month */
CMOS_WRITE(1, 0x08); /* month */
CMOS_WRITE(0, 0x09); /* year */
}
}
/* See if there is a LB CMOS checksum error */
checksum_invalid = !rtc_checksum_valid(LB_CKS_RANGE_START,
LB_CKS_RANGE_END,LB_CKS_LOC);
if(checksum_invalid)
rom_printk("Invalid CMOS LB checksum\n");
#endif
/* Setup the real time clock */
CMOS_WRITE(RTC_CONTROL_DEFAULT, RTC_CONTROL);
/* Setup the frequency it operates at */
CMOS_WRITE(RTC_FREQ_SELECT_DEFAULT, RTC_FREQ_SELECT);
/* Make certain we have a valid checksum */
#if 0
rtc_set_checksum(PC_CKS_RANGE_START,
PC_CKS_RANGE_END,PC_CKS_LOC);
/* Clear any pending interrupts */
(void) CMOS_READ(RTC_INTR_FLAGS);
#endif
}
#endif

558
arch/e2k/boot/bios/mga.c Normal file
View File

@ -0,0 +1,558 @@
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <asm/e2k_debug.h>
#include <asm/e2k.h>
#include "pci_isa_config.h"
#include "ide_config.h"
#include "southbridge.h"
#include "pci.h"
#include "mga.h"
#ifdef CONFIG_E2K_LEGACY_SIC
#include <asm/hb_regs.h>
#endif /* CONFIG_E2K_LEGACY_SIC */
#undef DEBUG_MGA_MODE
#undef DebugMGA
#define DEBUG_MGA_MODE 0
#define DebugMGA if (DEBUG_MGA_MODE) rom_printk
#undef TRACE_MSG
#define DBG_MODE 0
#define DEBUG_MSG if (DBG_MODE) rom_printk
typedef struct {
int div; // [6:0] Linear output divider
int q; // [7:0] PPL*_Q
int p; // [9:0] PPL*_P
int po; // [0:0] PPL_PO
int pixclock;
} clk_t;
clk_t __calc( int pixclock )
{
clk_t res;
DEBUG_MSG("__calc start\n");
res.pixclock = 39721;
res.div = 0x2;
res.q = 0x95;
res.p = 0x106;
res.po = 0x1;
DEBUG_MSG("__calc finish\n");
DEBUG_MSG( "Calulated: pixclock %d div %x q %x p %x po %x\n", res.pixclock, res.div, res.q, res.p, res.po );
return res;
}
static inline void mga_write(unsigned long v, unsigned long reg)
{
NATIVE_WRITE_MAS_W(reg, v, MAS_IOADDR);
}
static inline unsigned long mga_read(unsigned long reg)
{
return NATIVE_READ_MAS_W(reg, MAS_IOADDR);
}
static inline void i2c_write(unsigned long i2c_vbase, unsigned long reg, uint8_t val )
{
#ifdef MGA_TRACE
uint32_t rdval;
#endif
DEBUG_MSG( " i2c_write: I2C[0x%03lx] <= 0x%02x\n", reg, val );
mga_write( val, ((unsigned long)i2c_vbase + reg));
#ifdef MGA_TRACE
rdval = mga_read(((unsigned long)i2c_vbase + reg));
TRACE_MSG( " i2c_write: I2C[0x%03lx] => 0x%02x\n", reg, rdval );
#endif
}
static inline uint8_t i2c_read(unsigned long i2c_vbase, unsigned long reg )
{
uint32_t result = 0;
result = mga_read(((unsigned long)i2c_vbase + reg) );
DEBUG_MSG( " i2c_read: I2C[0x%03lx] => 0x%02x\n", reg, result );
return result;
}
static void i2c_send(unsigned long i2c_vbase, int cmd, int data )
{
#if 0
unsigned char status;
#endif
if (cmd & I2C_CR_WR)
i2c_write(i2c_vbase, I2C_REG_TXR, data );
i2c_write(i2c_vbase, I2C_REG_CR, cmd );
#if 0
while ( ( status = i2c_read(i2c_vbase, I2C_REG_SR ) & I2C_SR_TIP ) ) {
// mdelay(1);
DEBUG_MSG( "waiting 1 msec...\n" );
}
#endif
}
static int ramdac_write(unsigned long i2c_vbase, unsigned long ramdac_reg, uint8_t val )
{
// Sending RAMDAC device address
i2c_send(i2c_vbase, I2C_CR_STA | I2C_CR_WR, (I2C_RAMDAC_ADDR << 1) & I2C_WRITE_OP);
if ( i2c_read(i2c_vbase, I2C_REG_SR ) & I2C_SR_RxACK) {
DEBUG_MSG( "RAMDAC[0x%02lx] <= 0x%02x\t[FAILED]", ramdac_reg, val );
return -1;
}
// Sending RAMDAC register address
i2c_send(i2c_vbase, I2C_CR_WR, ramdac_reg );
if ( i2c_read(i2c_vbase, I2C_REG_SR ) & I2C_SR_RxACK) {
DEBUG_MSG( "RAMDAC[0x%02lx] <= 0x%02x\t[FAILED]", ramdac_reg, val );
return -1;
}
// Sending RAMDAC register data
i2c_send(i2c_vbase, I2C_CR_STO | I2C_CR_WR, val);
if ( i2c_read(i2c_vbase, I2C_REG_SR ) & I2C_SR_RxACK) {
DEBUG_MSG( "RAMDAC[0x%02lx] <= 0x%02x\t[FAILED]", ramdac_reg, val );
return -1;
}
return 0;
}
static uint8_t ramdac_read(unsigned long i2c_vbase, unsigned long ramdac_reg )
{
uint8_t val = 0;
// Sending RAMDAC device address
i2c_send(i2c_vbase, I2C_CR_STA | I2C_CR_WR, (I2C_RAMDAC_ADDR << 1) & I2C_WRITE_OP);
if ( i2c_read(i2c_vbase, I2C_REG_SR ) & I2C_SR_RxACK) {
DEBUG_MSG( "RAMDAC[0x%02lx] => ????\t[FAILED]", ramdac_reg );
return -1;
}
// Sending RAMDAC register address
i2c_send(i2c_vbase, I2C_CR_WR, ramdac_reg );
if ( i2c_read(i2c_vbase, I2C_REG_SR ) & I2C_SR_RxACK) {
DEBUG_MSG( "RAMDAC[0x%02lx] => ????\t[FAILED]", ramdac_reg );
return -1;
}
// Sending RAMDAC device address
i2c_send(i2c_vbase, I2C_CR_STA | I2C_CR_WR, (I2C_RAMDAC_ADDR << 1) | I2C_READ_OP);
if ( i2c_read(i2c_vbase, I2C_REG_SR ) & I2C_SR_RxACK) {
DEBUG_MSG( "RAMDAC[0x%02lx] => ????\t[FAILED]", ramdac_reg );
return -1;
}
// Sending RAMDAC register data
i2c_send(i2c_vbase, I2C_CR_STO | I2C_CR_RD | I2C_CR_NACK, 0);
val = i2c_read(i2c_vbase, I2C_REG_RXR );
return val;
}
static void set_prescaler(unsigned long i2c_vbase, int value)
{
DEBUG_MSG("set_prescaler start\n");
i2c_write(i2c_vbase, I2C_REG_PRER_LO, value & 0xFF );
i2c_write(i2c_vbase, I2C_REG_PRER_HI, (value >> 8) & 0xFF );
DEBUG_MSG("set_prescaler finish\n");
}
static void __set_clk_fs(unsigned long i2c_vbase, uint8_t a, uint8_t b, uint8_t c )
{
uint8_t d = FS_REF;
DEBUG_MSG("__set_clk_fs start\n");
// ClkA_FS[2:0]
ramdac_write(i2c_vbase, 0x08, ( ramdac_read(i2c_vbase, 0x08 ) & 0x7F ) | ( ( a & 0x01 ) << 7 ) );
ramdac_write(i2c_vbase, 0x0E, ( ramdac_read(i2c_vbase, 0x0E ) & 0xFC ) | ( ( a & 0x06 ) >> 1 ) );
// ClkB_FS[2:0]
ramdac_write(i2c_vbase, 0x0A, ( ramdac_read(i2c_vbase, 0x0A ) & 0x7F ) | ( ( b & 0x01 ) << 7 ) );
ramdac_write(i2c_vbase, 0x0E, ( ramdac_read(i2c_vbase, 0x0E ) & 0xF3 ) | ( ( b & 0x06 ) << 1 ) );
// ClkC_FS[2:0]
ramdac_write(i2c_vbase, 0x0C, ( ramdac_read(i2c_vbase, 0x0C ) & 0x7F ) | ( ( c & 0x01 ) << 7 ) );
ramdac_write(i2c_vbase, 0x0E, ( ramdac_read(i2c_vbase, 0x0E ) & 0xCF ) | ( ( c & 0x06 ) << 3 ) );
// ClkD_FS[2:0]
ramdac_write(i2c_vbase, 0x0D, ( ramdac_read(i2c_vbase, 0x0D ) & 0x7F ) | ( ( d & 0x01 ) << 7 ) );
ramdac_write(i2c_vbase, 0x0E, ( ramdac_read(i2c_vbase, 0x0E ) & 0x3F ) | ( ( d & 0x06 ) << 5 ) );
DEBUG_MSG("__set_clk_fs finish\n");
}
static void __set_ppl(unsigned long i2c_vbase, int index, uint8_t Q, uint16_t P, uint8_t PO )
{
unsigned long base;
switch( index ) {
case 2 :
base = 0x11;
break;
case 3 :
base = 0x14;
break;
default :
rom_printk( "Invalid PPL index %d\n", index );
return;
}
DEBUG_MSG("__set_ppl start\n");
// PPL*_Q[7:0]
ramdac_write(i2c_vbase, base + 0, Q );
// PPL*_P[7:0]
ramdac_write(i2c_vbase, base + 1, P & 0xFF );
{
uint8_t val;
uint8_t LF = 0x0;
int P_T = ( 2 * ( (P & 0x3FF) + 3 ) ) + (PO & 0x01);
if ( P_T <= 231 )
LF = 0x0;
else if ( P_T <= 626 )
LF = 0x1;
else if ( P_T <= 834 )
LF = 0x2;
else if ( P_T <= 1043 )
LF = 0x3;
else if ( P_T <= 1600 )
LF = 0x4;
// PPL*_En, PPL*_LF, PPL*_PO, PPL*_P[9:8]
val = ( P & 0x300 ) >> 8;
val |= ( PO & 0x1 ) << 2;
val |= LF << 3;
//val |= (enabled & 0x01) << 6;
ramdac_write(i2c_vbase, base + 2, val );
}
DEBUG_MSG("__set_ppl finish\n");
}
static void __set_enabled(unsigned long i2c_vbase, int index, uint8_t enabled )
{
unsigned long base;
uint8_t val;
switch( index ) {
case 2 :
base = 0x11;
break;
case 3 :
base = 0x14;
break;
default :
rom_printk( "Invalid PPL index %d\n", index );
return;
}
DEBUG_MSG("__set_enabled start\n");
val = ramdac_read(i2c_vbase, base + 2 );
val = val & (~(0x01 << 6));
val |= (enabled & 0x01) << 6;
ramdac_write(i2c_vbase, base + 2, val );
DEBUG_MSG("__set_enabled finish\n");
}
void __set_pixclock( unsigned long i2c_vbase, uint32_t pixclock )
{
clk_t vidclk = __calc( pixclock );
set_prescaler(i2c_vbase, NORMAL_SCL );
// Enable I2C core
i2c_write(i2c_vbase, I2C_REG_CTR, I2C_CTR_EN );
ramdac_write(i2c_vbase, 0x08, 0x0 );
ramdac_write(i2c_vbase, 0x0C, 0x0 );
__set_clk_fs(i2c_vbase, FS_REF, FS_REF, FS_REF );
// Reset vidclk enabled bit
__set_enabled(i2c_vbase, 2, 0 );
__set_ppl(i2c_vbase, 2, vidclk.q, vidclk.p, vidclk.po );
__set_clk_fs(i2c_vbase, FS_PPL2_0, FS_REF, FS_PPL2_0 );
ramdac_write(i2c_vbase, 0x08, ( ( FS_PPL2_0 & 0x01 ) << 7 ) | (vidclk.div & 0x7F) );
ramdac_write(i2c_vbase, 0x0C, ( ( FS_PPL2_0 & 0x01 ) << 7 ) | (vidclk.div & 0x7F) );
// Set vidclk enabled bit
__set_enabled(i2c_vbase, 2, 1 );
// Disable I2C core
i2c_write(i2c_vbase, I2C_REG_CTR, 0x0 );
}
static void MMIO_WRITE( struct mgam83fb_par* p, unsigned long reg, uint32_t val )
{
DEBUG_MSG( "MMIO[0x%03lx] <= 0x%08x\n", reg, val );
mga_write( val, ((unsigned long)p->mmio.vbase + reg) );
DEBUG_MSG( "Sleeping 10 msecs...\n" );
// mdelay(10);
}
struct fb_bitfield {
__u32 offset; /* beginning of bitfield */
__u32 length; /* length of bitfield */
__u32 msb_right; /* != 0 : Most significant bit is */
/* right */
};
#undef MGA_TEST
#ifdef MGA_TEST
static struct { struct fb_bitfield transp, red, green, blue; } colors = {
{ 0, 8, 0}, { 8, 8, 0}, { 16, 8, 0}, { 24, 8, 0}
};
#endif
int __set_mode( struct mgam83fb_par* p )
{
int hsync = p->hsync_len; // The Horizontal Syncronization Time (Sync Pulse )
int hgdel = p->left_margin; // The Horizontal Gate Delay Time (Back Porch)
int hgate = p->xres; // The Horizontal Gate Time (Active Time)
int hlen = hsync + hgdel + hgate + p->right_margin; // The Horizontal Length Time (Line Total)
int vsync = p->vsync_len; // The Vertical Syncronization Time (Sync Pulse )
int vgdel = p->upper_margin; // The Vertical Gate Delay Time (Back Porch)
int vgate = p->yres; // The Vertical Gate Time (Active Time)
int vlen = vsync + vgdel + vgate + p->lower_margin; // The Vertical Length Time (Frame total)
int vbl = CTRL_VBL1024; // Video Memory Burst Length
int ctrl = CTRL_BL_NEG | vbl;
DEBUG_MSG("__set_mode: start\n");
switch( p->bits_per_pixel ) {
case 8 :
ctrl |= CTRL_CD_8BPP | CTRL_PC_PSEUDO;
break;
case 16 :
ctrl |= CTRL_CD_16BPP;
#ifdef __LITTLE_ENDIAN
// ctrl |= CTRL_IBBO;
#endif
break;
case 24 :
ctrl |= CTRL_CD_24BPP;
#ifdef __LITTLE_ENDIAN
// ctrl |= CTRL_IBBO;
#endif
break;
case 32 :
ctrl |= CTRL_CD_32BPP;
#ifdef __LITTLE_ENDIAN
// ctrl |= CTRL_IBBO;
#endif
break;
default:
rom_printk( "Invalid color depth: %s %s %d\n", __FILE__, __FUNCTION__, __LINE__ );
return -1;
}
ctrl |= ( p->sync & FB_SYNC_COMP_HIGH_ACT ) ? CTRL_CSYNC_HIGH : CTRL_CSYNC_LOW;
ctrl |= ( p->sync & FB_SYNC_VERT_HIGH_ACT ) ? CTRL_VSYNC_HIGH : CTRL_VSYNC_LOW;
ctrl |= ( p->sync & FB_SYNC_HOR_HIGH_ACT ) ? CTRL_HSYNC_HIGH : CTRL_HSYNC_LOW;
hsync--, hgdel--, hgate--, vsync--, vgdel--, vgate--, hlen--, vlen--;
MMIO_WRITE( p, REG_CTRL, ctrl );
MMIO_WRITE( p, REG_HTIM, hsync << 24 | hgdel << 16 | hgate );
MMIO_WRITE( p, REG_VTIM, vsync << 24 | vgdel << 16 | vgate );
MMIO_WRITE( p, REG_HVLEN, hlen << 16 | vlen );
MMIO_WRITE( p, REG_VBARa, 0x0 );
DEBUG_MSG( "hsync: %d hgdel: %d hgate %d\n", hsync, hgdel, hgate );
DEBUG_MSG( "vsync: %d vgdel: %d vgate %d\n", vsync, vgdel, vgate );
DEBUG_MSG( "hlen: %d vlen: %d\n", hlen, vlen );
MMIO_WRITE( p, REG_CTRL, ctrl | CTRL_VEN );
DEBUG_MSG("__set_mode: finish\n");
return 0;
}
#ifdef MGA_TEST
static inline void
bios_writel(u32 l, volatile void *addr)
{
NATIVE_WRITE_MAS_W((e2k_addr_t)addr, l, MAS_IOADDR);
}
static inline void
bios_writell(u64 q, volatile void *addr)
{
NATIVE_WRITE_MAS_D((e2k_addr_t)addr, q, MAS_IOADDR);
}
void drawStripe( unsigned long addr,
int yB, int yE,
int rB, int rE, int gB, int gE, int bB, int bE )
{
int x, y;
int xres = 640;
int bpp = 32;
// unsigned int once = 0;
addr += yB * xres * (bpp >> 3);
/* rom_printk("addr = 0x%x, yB = %d, yE = %d, rB = %d, rE = %d, gB = %d, gE = %d"
" bB = %d, bE = %d\n", addr, yB, yE, rB, rE, gB, gE, bB, bE); */
for ( y = yB; y < yE; y++ ) {
for ( x = 0; x < xres; x++ ) {
/* float factor = (float)x / (float)xres;
unsigned int r = rB + factor * ( rE - rB );
unsigned int g = gB + factor * ( gE - gB );
unsigned int b = bB + factor * ( bE - bB );*/
unsigned int r = rB + 1 * ( rE - rB );
unsigned int g = gB + 1 * ( gE - gB );
unsigned int b = bB + 1 * ( bE - bB );
#if 0
if (once != 757){
rom_printk("r = %d, g = %d, b = %d\n", r, g, b);
once++;
}
#endif
bios_writel(r << colors.red.offset |
g << colors.green.offset |
b << colors.blue.offset, (void *)addr);
addr += bpp >> 3;
}
}
}
#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
void draw(struct bios_pci_dev *dev)
{
u64 fb_phys_addr;
int stripeHeight = 480 / 4;
int rE = ( 1 << colors.red.length ) - 1;
int gE = ( 1 << colors.red.length ) - 1;
int bE = ( 1 << colors.red.length ) - 1;
fb_phys_addr = dev->base_address[PCI_MEM_BAR];
drawStripe( fb_phys_addr, 0, 1 * stripeHeight, 0, rE, 0, gE, 0, bE );
drawStripe( fb_phys_addr, 1 * stripeHeight, 2 * stripeHeight, 0, 0, 0, 0, 0, bE );
drawStripe( fb_phys_addr, 2 * stripeHeight, 3 * stripeHeight, 0, 0, 0, gE, 0, 0 );
drawStripe( fb_phys_addr, 3 * stripeHeight, 4 * stripeHeight, 0, rE, 0, 0, 0, 0 );
};
#endif
void enable_mga(void)
{
struct bios_pci_dev *dev;
struct mgam83fb_par p;
rom_printk("Scanning PCI bus for MGA video card ...");
dev = bios_pci_find_device(PCI_VENDOR_ID_MGAM83, PCI_DEVICE_ID_MGAM83,
NULL);
if (dev) {
SB_bus = dev->bus->number;
SB_device = PCI_SLOT(dev->devfn);
rom_printk("found on bus %d device %d\n", SB_bus, SB_device);
DebugMGA("--------- VIDEO BIOS ------\n");
DebugMGA("Class: %X\n", dev->class);
DebugMGA("command: %x\n", dev->command);
DebugMGA("base_address[0]: %04x\n", dev->base_address[0]);
DebugMGA("size[0]: %04x\n", dev->size[0]);
DebugMGA("base_address[1]: %04x\n", dev->base_address[1]);
DebugMGA("size[1]: %04x\n", dev->size[1]);
DebugMGA("base_address[2]: %04x\n", dev->base_address[2]);
DebugMGA("size[2]: %04x\n", dev->size[2]);
DebugMGA("base_address[3]: %04x\n", dev->base_address[3]);
DebugMGA("size[0]: %04x\n", dev->size[3]);
DebugMGA("base_address[4]: %04x\n", dev->base_address[4]);
DebugMGA("size[4]: %04x\n", dev->size[4]);
DebugMGA("base_address[5]: %04x\n", dev->base_address[5]);
DebugMGA("size[5]: %04x\n", dev->size[5]);
DebugMGA("rom_address: %04x\n", dev->rom_address);
DebugMGA("rom_size %04x\n", dev->rom_size);
p.mem.base = dev->base_address[PCI_MEM_BAR];
p.mem.len = dev->size[PCI_MEM_BAR];
p.mem.vbase = dev->base_address[PCI_MEM_BAR];
p.mmio.base = dev->base_address[PCI_MMIO_BAR];
p.mmio.len = dev->size[PCI_MMIO_BAR];
p.mmio.vbase = dev->base_address[PCI_MMIO_BAR];
p.i2c.base = dev->base_address[PCI_I2C_BAR];
p.i2c.len = dev->size[PCI_I2C_BAR];
p.i2c.vbase = dev->base_address[PCI_I2C_BAR];
/* Update par */
p.xres = 0x280;
p.yres = 0x1e0;
p.xres_virtual = 0x280;
p.yres_virtual = 0x1e0;
p.xoffset = 0;
p.yoffset = 0;
p.left_margin = 0x28;
p.right_margin = 0x18;
p.hsync_len = 0x60;
p.upper_margin = 0x20;
p.lower_margin = 0xb;
p.vsync_len = 0x2;
p.bits_per_pixel = 0x20;
p.pixclock = 0x9b29;
p.sync = 0;
DEBUG_MSG("!!! enable_mga: setting pixclock !!!\n");
__set_pixclock( (unsigned long)p.i2c.vbase, p.pixclock );
__set_mode( &p );
rom_printk("MGA Initialization complete\n");
#ifdef MGA_TEST
draw(dev);
#endif
} else {
rom_printk("!!! NOT FOUND !!!\n");
}
}
#ifdef CONFIG_E2K_LEGACY_SIC
void enable_embeded_graphic(void)
{
struct bios_pci_dev *dev;
unsigned int hb_cfg;
unsigned short vpci_cmd;
hb_cfg = early_readl_hb_reg(HB_PCI_CFG);
if (!(hb_cfg & HB_CFG_IntegratedGraphicsEnable)) {
rom_printk("Embeded graphic disabled, "
"legacy VGA mode impossible\n");
return;
}
rom_printk("Scanning PCI bus for Embeded MGA2 card ...");
dev = bios_pci_find_device(PCI_VENDOR_ID_MCST_TMP,
PCI_DEVICE_ID_MCST_MGA2, NULL);
if (dev) {
rom_printk("found on %d:%d:%d\n",
dev->bus->number,
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
} else {
rom_printk("!!! NOT FOUND !!!\n");
return;
}
hb_cfg |= HB_CFG_IntegratedVgaEnable;
hb_cfg &= ~HB_CFG_ShareGraphicsInterrupts;
early_writel_hb_reg(hb_cfg, HB_PCI_CFG);
rom_printk("host bridge CFG: enable legacy VGA mode 0x%X\n",
early_readl_hb_reg(HB_PCI_CFG));
vpci_cmd = early_readw_eg_reg(PCI_COMMAND);
vpci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
early_writew_eg_reg(vpci_cmd, PCI_COMMAND);
rom_printk("Embeded Graphic CMD: enable IO/MMIO/DMA 0x%04x\n",
vpci_cmd);
}
#endif /* CONFIG_E2K_LEGACY_SIC */

283
arch/e2k/boot/bios/mga.h Normal file
View File

@ -0,0 +1,283 @@
#ifndef MGA_H
#define MGA_H
# define PCI_VENDOR_ID_MGAM83 0x108e
# define PCI_DEVICE_ID_MGAM83 0x8000
// Indexes of pci_dev.resource[]
# define PCI_MMIO_BAR 0
# define PCI_MEM_BAR 1
# define PCI_I2C_BAR 2
/*******************************************************************************
* MMIO Registers
*******************************************************************************
*/
#define REG_CTRL 0x000 // Control Register
#define REG_STAT 0x004 // Status Register
#define REG_HTIM 0x008 // Horizontal Timing Register
#define REG_VTIM 0x00c // Vertical Timing Register
#define REG_HVLEN 0x010 // Horizontal and Vertical Length Register
#define REG_VBARa 0x014 // Video Memory Base Address Register A
#define REG_VBARb 0x018 // Video Memory Base Address Register B
#define REG_C0XY 0x030 // Cursor 0 X,Y Register
#define REG_C0BAR 0x034 // Cursor0 Base Address register
#define REG_C0CR 0x040 // Cursor0 Color Registers
#define REG_C1XY 0x070 // Cursor 0 X,Y Register
#define REG_C1BAR 0x074 // Cursor0 Base Address register
#define REG_C1CR 0x080 // Cursor0 Color Registers
#define REG_PCLT 0x800 // 8bpp Pseudo Color Lockup Table
#define REG_TST_D 0x01C // Test Mode
// BitBlt module registers
#define BBR0 0x1000 // CTRL_REG if writing
// STAT_REG if reading
#define BBR1 0x1004 // WINDOW_REG (size of the window to copy)
#define BBR2 0x1008 // SADDR_REG (Source address reg - byte offset
// inside framebuffer) invisible framebuffer part
#define BBR3 0x100c // DADDR_REG (Destination address reg - byte offset
// inside framebuffer) visible framebuffer part
#define BBR4 0x1010 // PITCH_REG (value to increment both SADDR_REG and
// DADDR_REG to have them pointing to the next
// lines of WINDOWS (source and destination windows
// respecteviely)). PITCH_REG has 2 parts. The highest 16
// little-endian bits are for the destination and the lowest
// ones are for the source. Determined in bytes
#define BBR5 0x1014 // BG_REG - Background color (color extenshion mode for
// originally monochromed color only)
#define BBR6 0x1018 // FG_REG - Foreground color (color extenshion mode for
// originally monochromed color only)
#define BBR7 0x101c // RESERVED
/* Bit feilds for CTRL_REG (little-endian mode) */
#define CE_EN (1 << 0) // Enable color extenshion (for
// originally monochromed color only)
#define PAT_EN (1 << 1) // Enable 8x8 pattern multiplication
// (Pattern Copy). Doesn't work if
// continuous address generation for source
// is enabled.
#define SFILL_EN (1 << 2) // Enable continuous color pouring mode
// Works only in color extenshion mode
#define INV_EN (1 << 3) // monochromed image invertion mode
// Works only in color extenshion mode
#define TR_EN (1 << 4) // Transparency mode
// Works only in color extenshion mode
#define HDIR (1 << 5) // Horizontal (when drawing a line of WINDOW)
// incrementation sign (0 --->; 1 <---;)
#define VDIR (1 << 6) // Vertical incrementation sign (0 --->; 1 <---;)
// The same as PITCH_REG parts sign
#define SRC_MODE (1 << 7) // Enable address generation for source
// If enabled makes module to increment source
// address continuously inspite of lowest part of
// PITCH_REG. (This mode has to be enabled if you
// want to have your image object continuous in
// invisible part of framebuffer memory due to economy
// reason i think)
/*#define TERM_MODE*///FIXME // 32 bits word alignment when reached end of a line
// Address generation for source mode only
#define BPP_08 (0x00 << 10)
#define BPP_16 (0x01 << 10)
#define BPP_24 (0x02 << 10)
#define BPP_32 (0x03 << 10)
#define ROP_02 (0x02 << 12) // DST = DST &~ SRC
#define ROP_03 (0x03 << 12) // DST = DST
#define ROP_04 (0x04 << 12) // DST = ~DST & SRC
#define ROP_05 (0x05 << 12) // DST = SRC
#define ROP_06 (0x06 << 12) // DST = DST != SRC
#define ROP_07 (0x07 << 12) // DST = DST | SRC
#define ROP_08 (0x08 << 12) // DST = ~DST &~ SRC
#define ROP_09 (0x09 << 12) // DST = DST == SRC
#define ROP_0A (0x0a << 12) // DST = ~SRC
#define ROP_0B (0x0b << 12) // DST = DST | ~SRC
#define ROP_0C (0x0c << 12) // DST = ~DST
#define ROP_0D (0x0d << 12) // DST = ~DST | SRC
#define ROP_0E (0x0e << 12) // DST = ~DST | ~SRC
#define ROP_0F (0x0f << 12) // DST = {1}
/*#define SOFFS*///FIXME
#define SDMA_EN (1 << 20) // Enable DMA for Source
#define DDMA_EN (1 << 21) // Enable DMA for Destination
#define PAUSE (1 << 27) // BitBlt operation delay
// Used for the executive control only
#define NFIE (1 << 28) // Enable interrupt in the case of unfilling
// task buffer
// Used for the executive control only
#define NPIE (1 << 29) // Enable interrupt in the case of unexecuting
// of BitBlt operation
// Used for the executive control only
#define ABORT (1 << 30) // BitBlt operation abortion
#define START (1 << 31) // BitBlt operation starting
/* Bit feilds for STAT_REG (little-endian mode) */
#define FULL (1 << 30) // Double buffering state
// 0 - Buffer isn't filled up, so another
// operation may be initiated
// 1 - Buffer is filled up
#define PROCESS (1 << 31) // BitBlt operation carring out state
// 0 - The module isn't carring out BitBlt operation
// 1 - BitBlt operation is running
// Control Register REG_CTRL
#define CTRL_IBBO (0x1<<31) // Inverse Bus Byte Order
#define CTRL_SAP
#define CTRL_HC1R_32 0 // Hardware Cursor1 Resolution 32x32
#define CTRL_HC1R_64 (0x1<<25) // 64x64
#define CTRL_HC1E (0x1<<24) // Hardware Cursor1 Enabled
#define CTRL_HC0R_32 0 // Hardware Cursor0 Resolution 32x32
#define CTRL_HC0R_64 (0x1<<21) // 64x64
#define CTRL_HC0E (0x1<<20) // Hardware Cursor0 Enabled
#define CTRL_TST (0x1<<17) // TODO: ?????
#define CTRL_BL_POS 0 // Blanking Polarization Level Positive
#define CTRL_BL_NEG (0x1<<15) // Negative
#define CTRL_CSYNC_HIGH 0 // Composite Synchronization Pulse Polarization Level Positive
#define CTRL_CSYNC_LOW (0x1<<14) // Negative
#define CTRL_VSYNC_HIGH 0 // Vertical Synchronization Pulse Polarization Level Positive
#define CTRL_VSYNC_LOW (0x1<<13) // Negative
#define CTRL_HSYNC_HIGH 0 // Horizontal Synchronization Pulse polarization Level Positive
#define CTRL_HSYNC_LOW (0x1<<12) // Negative
#define CTRL_PC_GRAY 0 // 8-bit Pseudo Color Grayscale
#define CTRL_PC_PSEUDO (0x1<<11) // Pseudo Color
#define CTRL_CD_8BPP 0 // Color Depth 8bpp
#define CTRL_CD_16BPP (0x1<<9) // 16bpp
#define CTRL_CD_24BPP (0x2<<9) // 24bpp
#define CTRL_CD_32BPP (0x3<<9) // 32bpp
#define CTRL_VBL_1 0 // Video Memory Burst Length 1 cycle
#define CTRL_VBL_2 (0x1<<7) // 2 cycles
#define CTRL_VBL_4 (0x2<<7) // 4 cycles
#define CTRL_VBL_8 (0x3<<7) // 8 cycles
#define CTRL_VBL1024 (0x203<<7) // 16 cycles (extension)
#define CTRL_CBSWE (0x1<<6) // CLUT Bank Switching Enable
#define CTRL_VBSWE (0x1<<5) // Video Bank Switching Enable
#define CTRL_CBSIE (0x1<<4) // CLUT Bank Switch Interrupt Enable
#define CTRL_VBSIE (0x1<<3) // VideoBank Switch Interrupt Enable
#define CTRL_HIE (0x1<<2) // HSync Interrupt Enable
#define CTRL_VIE (0x1<<1) // VSync Interrupt Enable
#define CTRL_VEN (0x1<<0) // Video Enable
// Status Register REG_STAT
#define STAT_HC1A (0x1<<24) // Hardware cursor1 available
#define STAT_HC0A (0x1<<20) // Hardware cursor0 available
#define STAT_ACMP (0x1<<17) // Active CLUT Memory Page
#define STAT_AVMP (0x1<<16) // Active Video Memory Page
#define STAT_CBSINT (0x1<<7) // CLUT Bank Switch Interrupt Pending
#define STAT_VBSINT (0x1<<6) // Bank Switch Interrupt Pending
#define STAT_HINT (0x1<<5) // Horizontal Interrupt Pending
#define STAT_VINT (0x1<<4) // Vertical Interrupt Pending
#define STAT_LUINT (0x1<<1) // Line FIFO Under-Run Interrupt Pending
#define STAT_SINT (0x1<<0) // System Error Interrupt Pending
#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */
#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */
#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */
/*******************************************************************************
* I2C Registers
*******************************************************************************
*/
#define I2C_REG_PRER_LO (0x00 << 2) // Clock Prescale register lo-byte (RW)
#define I2C_REG_PRER_HI (0x01 << 2) // Clock Prescale register hi-byte (RW)
#define I2C_REG_CTR (0x02 << 2) // Control Register (RW)
#define I2C_REG_TXR (0x03 << 2) // Transmit Register (W)
#define I2C_REG_RXR (0x03 << 2) // Receive Register (R)
#define I2C_REG_CR (0x04 << 2) // Command Register (W)
#define I2C_REG_SR (0x06 << 2) // Status Register (R)
#define I2C_REG_RESET (0x07 << 2) // Reset Register
// Prescaler divider evaluates as (PCICLK/(5*SCLK))-1
#define NORMAL_SCL 0x3F
// Control Register bits
#define I2C_CTR_EN (1 << 7) // I2C core enable bit
#define I2C_CTR_IEN (1 << 6) // I2C core interrupt enable bit
// Command Register bits
#define I2C_CR_STA (1 << 7) // generate (repeated) start condition
#define I2C_CR_STO (1 << 6) // generate stop condition
#define I2C_CR_RD (1 << 5) // read from slave
#define I2C_CR_WR (1 << 4) // write to slave
#define I2C_CR_NACK (1 << 3) // when a receiver, sent I2C_CR_NACK
#define I2C_CR_IACK (1 << 0) // Interrupt acknowledge. When set, clears pending interrrupt
// Status Register bits
#define I2C_SR_RxACK (1 << 7) // Receive acknowledge from slave. '1' - no acknowledge received
#define I2C_SR_BUSY (1 << 6) // I2C bus busy. '1' after START, '0' after STOP
#define I2C_SR_AL (1 << 5) // Arbitration lost
#define I2C_SR_TIP (1 << 1) // Transfer in progress. '1' when transferring data
#define I2C_SR_IF (1 << 0) // Interrupt flag
// Transmit Register operations
#define I2C_READ_OP 0x01 // Reading from slave ( x << 1 | I2C_READ_OP )
#define I2C_WRITE_OP 0xFE // Writing to slave ( x << 1 & I2C_WRITE_OP )
/*******************************************************************************
* RAMDAC
*******************************************************************************
*/
#define I2C_RAMDAC_ADDR 0x69
#define FS_REF 0x0 // Reference clock [000]
#define FS_PPL1_0 0x2 // PPL1 0* Phase
#define FS_PPL1_180 0x3 // PPL1 180* Phase
#define FS_PPL2_0 0x4 // PPL2 0* Phase
#define FS_PPL2_180 0x5 // PPL2 180* Phase
#define FS_PPL3_0 0x6 // PPL3 0* Phase
#define FS_PPL3_180 0x7 // PPL3 180* Phase
// External clock frequency 14.3181 Mhz
#define PIXCLOCK_EXT 69841
struct mgam83fb_par {
int bus_type; // 0 - PCI, 1 - SBUS
int index; // MGAM index
struct {
unsigned long base; // phys address
unsigned long vbase; // virtual address
unsigned int len;
} mem;
struct {
unsigned long base; // phys address
unsigned long vbase; // virtual address
unsigned int len;
} mmio;
struct {
unsigned long base; // phys address
unsigned long vbase; // virtual address
unsigned int len;
} i2c;
/* Current videomode **************************************************/
__u32 xres; // visible resolution
__u32 yres;
__u32 xres_virtual; // virtual resolution
__u32 yres_virtual;
__u32 xoffset; // offset from virtual to visible
__u32 yoffset; // resolution
__u32 bits_per_pixel; // Bits per pixel
__u32 pixclock; // pixel clock in ps (pico seconds)
__u32 left_margin; // time from sync to picture
__u32 right_margin; // time from picture to sync
__u32 upper_margin; // time from sync to picture
__u32 lower_margin;
__u32 hsync_len; // length of horizontal sync
__u32 vsync_len; // length of vertical sync
__u32 sync;
u32 pseudo_palette[16];
};
#endif /* MGA_H */

371
arch/e2k/boot/bios/mpspec.c Normal file
View File

@ -0,0 +1,371 @@
/*
* $Id: mpspec.c,v 1.8 2009/02/24 15:13:21 atic Exp $
* From linuxbios.org
*/
#include <linux/threads.h>
#include <linux/cpumask.h>
#include <asm/glob_regs.h>
#include <asm/mpspec.h>
#include "../pic.h"
#include "pci.h"
#undef BIOS_DEBUG
#define MPSPEC_DEBUG 0
#define BIOS_DEBUG MPSPEC_DEBUG
#define CONFIG_DEBUG_MPTABLE 0
#include "printk.h"
unsigned char smp_compute_checksum(void *v, int len)
{
unsigned char *bytes;
unsigned char checksum;
int i;
bytes = v;
checksum = 0;
for(i = 0; i < len; i++) {
checksum -= bytes[i];
}
return checksum;
}
static int
mpf_do_checksum(unsigned char *mp, int len)
{
int sum = 0;
while (len--)
sum += *mp++;
return 0x100 - (sum & 0xFF);
}
void smp_write_floating_table(struct intel_mp_floating *mpf)
{
mpf->mpf_signature[0] = '_';
mpf->mpf_signature[1] = 'M';
mpf->mpf_signature[2] = 'P';
mpf->mpf_signature[3] = '_';
mpf->mpf_physptr = (unsigned long)(((char *)mpf) + SMP_FLOATING_TABLE_LEN);
mpf->mpf_length = 1;
mpf->mpf_specification = 4;
mpf->mpf_checksum = 0;
mpf->mpf_feature1 = 0;
mpf->mpf_feature2 = 0;
mpf->mpf_feature3 = 0;
mpf->mpf_feature4 = 0;
mpf->mpf_feature5 = 0;
/// mpf->mpf_checksum = smp_compute_checksum(mpf, mpf->mpf_length*16);
mpf->mpf_checksum = mpf_do_checksum((unsigned char *)mpf, sizeof (*mpf));
}
void *smp_next_mpc_entry(struct mpc_table *mc)
{
void *v;
v = (void *)(((char *)mc) + mc->mpc_length);
return v;
}
static void smp_add_mpc_entry(struct mpc_table *mc, unsigned length)
{
mc->mpc_length += length;
mc->mpc_oemcount++;
}
void *smp_next_mpe_entry(struct mpc_table *mc)
{
void *v;
v = (void *)(((char *)mc) + mc->mpc_length + mc->mpe_length);
return v;
}
static void smp_add_mpe_entry(struct mpc_table *mc, mpe_t mpe)
{
mc->mpe_length += mpe->mpe_length;
}
void smp_write_processor(struct mpc_table *mc,
unsigned char apicid, unsigned char apicver,
unsigned char cpuflag, unsigned int cpufeature,
unsigned int featureflag, unsigned int cepictimerfreq)
{
struct mpc_config_processor *mpc;
mpc = smp_next_mpc_entry(mc);
memset(mpc, '\0', sizeof(*mpc));
mpc->mpc_type = MP_PROCESSOR;
mpc->mpc_apicid = apicid;
mpc->mpc_apicver = apicver;
mpc->mpc_cpuflag = cpuflag;
mpc->mpc_cpufeature = cpufeature;
mpc->mpc_featureflag = featureflag;
mpc->mpc_cepictimerfreq = cepictimerfreq;
smp_add_mpc_entry(mc, sizeof(*mpc));
}
//unsigned int initial_apicid[MAX_CPUS] =
//{
// 0, 1, [2 ... MAX_CPUS - 1] = -1
//};
/* If we assume a symmetric processor configuration we can
* get all of the information we need to write the processor
* entry from the bootstrap processor.
* Plus I don't think linux really even cares.
* Having the proper apicid's in the table so the non-bootstrap
* processors can be woken up should be enough.
*/
void smp_write_processors(struct mpc_table *mc,
unsigned int phys_cpu_num)
{
int i;
int processor_id;
unsigned int pic_version;
unsigned cpu_flags;
unsigned cpu_features;
unsigned cpu_feature_flags;
unsigned int cepic_timer_freq;
processor_id = NATIVE_READ_PIC_ID();
pic_version = native_pic_read_version();
#ifndef CONFIG_CEPIC_TIMER_FREQUENCY
cepic_timer_freq = 100 * 1000000; /* 100 MHz for LMS */
#else
cepic_timer_freq = CONFIG_CEPIC_TIMER_FREQUENCY * 1000000;
#endif /* CONFIG_CEPIC_TIMER_FREQUENCY */
cpu_features = 0x0f;
cpu_features = 0x0f;
cpu_feature_flags = 1 << 9;
for(i = 0; i < NR_CPUS; i++) {
#ifdef CONFIG_SMP
unsigned int cpu_picid = all_pic_ids[i];
#else /* ! CONFIG_SMP */
unsigned int cpu_picid = processor_id;
#endif /* CONFIG_SMP */
/// if(initial_apicid[i]==-1)
/// continue;
if((i+1) > phys_cpu_num)
continue;
#ifdef CONFIG_SMP
if (processor_id == all_pic_ids[i])
#endif /* CONFIG_SMP */
cpu_flags = CPU_BOOTPROCESSOR | CPU_ENABLED;
#ifdef CONFIG_SMP
else
cpu_flags = CPU_ENABLED;
#endif /* CONFIG_SMP */
smp_write_processor(mc, cpu_picid, pic_version,
cpu_flags,
cpu_features, cpu_feature_flags, cepic_timer_freq
);
}
}
void smp_write_bus(struct mpc_table *mc,
unsigned char id, unsigned char *bustype)
{
struct mpc_config_bus *mpc;
mpc = smp_next_mpc_entry(mc);
memset(mpc, '\0', sizeof(*mpc));
mpc->mpc_type = MP_BUS;
mpc->mpc_busid = id;
memcpy(mpc->mpc_bustype, bustype, sizeof(mpc->mpc_bustype));
smp_add_mpc_entry(mc, sizeof(*mpc));
}
void smp_write_ioapic(struct mpc_table *mc,
unsigned char id, unsigned char ver,
unsigned long apicaddr)
{
struct mpc_ioapic *mpc;
mpc = smp_next_mpc_entry(mc);
memset(mpc, '\0', sizeof(*mpc));
mpc->type = MP_IOAPIC;
mpc->apicid = id;
mpc->apicver = ver;
mpc->flags = MPC_APIC_USABLE;
mpc->apicaddr = apicaddr;
smp_add_mpc_entry(mc, sizeof(*mpc));
}
void smp_write_iolink(struct mpc_table *mc,
int node, int link,
short bus_min, short bus_max,
short picid,
unsigned long pci_mem_start, unsigned long pci_mem_end)
{
struct mpc_config_iolink *mpc;
mpc = smp_next_mpc_entry(mc);
memset(mpc, '\0', sizeof(*mpc));
mpc->mpc_type = MP_IOLINK;
mpc->mpc_iolink_type = MP_IOLINK_IOHUB;
mpc->mpc_iolink_ver = MP_IOHUB_FPGA_VER;
mpc->node = node;
mpc->link = link;
mpc->bus_min = bus_min;
mpc->bus_max = bus_max;
mpc->apicid = picid;
mpc->pci_mem_start = pci_mem_start;
mpc->pci_mem_end = pci_mem_end;
smp_add_mpc_entry(mc, sizeof(*mpc));
}
void smp_write_ioepic(struct mpc_table *mc,
unsigned short id, unsigned short nodeid,
unsigned char ver, unsigned long epicaddr)
{
struct mpc_ioepic *mpc;
mpc = smp_next_mpc_entry(mc);
memset(mpc, '\0', sizeof(*mpc));
mpc->type = MP_IOEPIC;
mpc->epicid = id;
mpc->nodeid = nodeid;
mpc->epicver = ver;
mpc->epicaddr = epicaddr;
smp_add_mpc_entry(mc, sizeof(*mpc));
}
void smp_write_intsrc(struct mpc_table *mc,
unsigned char irqtype, unsigned short irqflag,
unsigned char srcbus, unsigned char srcbusirq,
unsigned char dstapic, unsigned char dstirq)
{
struct mpc_intsrc *mpc;
mpc = smp_next_mpc_entry(mc);
memset(mpc, '\0', sizeof(*mpc));
mpc->type = MP_INTSRC;
mpc->irqtype = irqtype;
mpc->irqflag = irqflag;
mpc->srcbus = srcbus;
mpc->srcbusirq = srcbusirq;
mpc->dstapic = dstapic;
mpc->dstirq = dstirq;
smp_add_mpc_entry(mc, sizeof(*mpc));
#if CONFIG_DEBUG_MPTABLE
printk_info("add intsrc srcbus 0x%x srcbusirq 0x%x, dstapic 0x%x, dstirq 0x%x\n",
srcbus, srcbusirq, dstapic, dstirq);
hexdump(__FUNCTION__, mpc, sizeof(*mpc));
#endif
}
void smp_i2c_spi_timer(struct mpc_table *mc,
unsigned char timertype, unsigned char timerver,
unsigned char timerflags, unsigned long timeraddr)
{
struct mpc_config_timer *mpc;
mpc = smp_next_mpc_entry(mc);
memset(mpc, '\0', sizeof(*mpc));
mpc->mpc_type = MP_TIMER;
mpc->mpc_timertype = timertype;
mpc->mpc_timerver = timerver;
mpc->mpc_timerflags = timerflags;
mpc->mpc_timeraddr = timeraddr;
smp_add_mpc_entry(mc, sizeof(*mpc));
}
void smp_i2c_spi_dev(struct mpc_table *mc, unsigned char max_channel,
unsigned char irq, unsigned long pcidevaddr)
{
struct mpc_config_i2c *mpc;
mpc = smp_next_mpc_entry(mc);
memset(mpc, '\0', sizeof(*mpc));
mpc->mpc_type = MP_I2C_SPI;
mpc->mpc_i2ccntrladdr =
((struct bios_pci_dev *)pcidevaddr)->base_address[0];
mpc->mpc_i2cdataaddr =
((struct bios_pci_dev *)pcidevaddr)->base_address[1];
mpc->mpc_max_channel = max_channel;
mpc->mpc_i2c_irq = irq;
#if CONFIG_DEBUG_MPTABLE
rom_printk("add i2c/spi dev addr to mptable, "
" base[0] = 0x%x, base[1] = 0x%x. IRQ %d\n",
((struct bios_pci_dev *)pcidevaddr)->base_address[0],
((struct bios_pci_dev *)pcidevaddr)->base_address[1],
irq);
#endif
smp_add_mpc_entry(mc, sizeof(*mpc));
}
void smp_write_lintsrc(struct mpc_table *mc,
unsigned char irqtype, unsigned short irqflag,
unsigned char srcbusid, unsigned char srcbusirq,
unsigned char destapic, unsigned char destapiclint)
{
struct mpc_config_lintsrc *mpc;
mpc = smp_next_mpc_entry(mc);
memset(mpc, '\0', sizeof(*mpc));
mpc->mpc_type = MP_LINTSRC;
mpc->mpc_irqtype = irqtype;
mpc->mpc_irqflag = irqflag;
mpc->mpc_srcbusid = srcbusid;
mpc->mpc_srcbusirq = srcbusirq;
mpc->mpc_destapic = destapic;
mpc->mpc_destapiclint = destapiclint;
smp_add_mpc_entry(mc, sizeof(*mpc));
}
void smp_write_address_space(struct mpc_table *mc,
unsigned char busid, unsigned char address_type,
unsigned int address_base_low, unsigned int address_base_high,
unsigned int address_length_low, unsigned int address_length_high)
{
struct mp_exten_system_address_space *mpe;
mpe = smp_next_mpe_entry(mc);
memset(mpe, '\0', sizeof(*mpe));
mpe->mpe_type = MPE_SYSTEM_ADDRESS_SPACE;
mpe->mpe_length = sizeof(*mpe);
mpe->mpe_busid = busid;
mpe->mpe_address_type = address_type;
mpe->mpe_address_base_low = address_base_low;
mpe->mpe_address_base_high = address_base_high;
mpe->mpe_address_length_low = address_length_low;
mpe->mpe_address_length_high = address_length_high;
smp_add_mpe_entry(mc, (mpe_t)mpe);
}
void smp_write_bus_hierarchy(struct mpc_table *mc,
unsigned char busid, unsigned char bus_info,
unsigned char parent_busid)
{
struct mp_exten_bus_hierarchy *mpe;
mpe = smp_next_mpe_entry(mc);
memset(mpe, '\0', sizeof(*mpe));
mpe->mpe_type = MPE_BUS_HIERARCHY;
mpe->mpe_length = sizeof(*mpe);
mpe->mpe_busid = busid;
mpe->mpe_bus_info = bus_info;
mpe->mpe_parent_busid = parent_busid;
smp_add_mpe_entry(mc, (mpe_t)mpe);
}
void smp_write_compatibility_address_space(struct mpc_table *mc,
unsigned char busid, unsigned char address_modifier,
unsigned int range_list)
{
struct mp_exten_compatibility_address_space *mpe;
mpe = smp_next_mpe_entry(mc);
memset(mpe, '\0', sizeof(*mpe));
mpe->mpe_type = MPE_COMPATIBILITY_ADDRESS_SPACE;
mpe->mpe_length = sizeof(*mpe);
mpe->mpe_busid = busid;
mpe->mpe_address_modifier = address_modifier;
mpe->mpe_range_list = range_list;
smp_add_mpe_entry(mc, (mpe_t)mpe);
}
#if 0
/* memcpy standard block */
const static char smpblock[] =
{0x5F, 0x4D, 0x50, 0x5F, 0x00, 0x00, 0x00,
0x00, 0x01, 0x04, 0x9B, 0x05, 0x00, 0x00, 0x00, 0x00
};
void write_smp_table(void *v)
{
memcpy(v, smpblock, sizeof(smpblock));
}
#endif /* 0 */

View File

@ -0,0 +1,422 @@
/*
* $Id: mptable.c,v 1.22 2009/02/24 15:13:30 atic Exp $
*/
#include <linux/types.h>
#include <linux/cpumask.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <asm/mpspec.h>
#include <asm/e2k_debug.h>
#include <asm/e2k_api.h>
#include <asm/e2k.h>
#include "printk.h"
#include "pci.h"
#include "../boot_io.h"
#undef BIOS_DEBUG
#define MTABLE_DEBUG 0
#define BIOS_DEBUG MTABLE_DEBUG
#define MP_IRQ_EDGE_HIGH (MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH)
#define MP_IRQ_LEVEL_HIGH (MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_HIGH)
#define MP_BUS_ISA_NUM 0x1f
/* Setting resources for iopic, timer and cmos to mptable */
void smp_write_ioepic_i2c_spi_info(struct mpc_table *mc,
struct bios_pci_dev *dev, unsigned int ioepicid)
{
unsigned int timer_base;
unsigned int domain = bios_pci_domain_nr(dev->bus);
unsigned int ioepic_base;
pcibios_read_config_dword(domain, dev->bus->number,
dev->devfn, PCI_BASE_ADDRESS_2, &timer_base);
rom_printk("Reading timer_base from I2C-SPI: 0x%x\n", timer_base);
timer_base = timer_base & 0xfffffff0; /* Masking the lower bits */
smp_i2c_spi_timer(mc, MP_LT_TYPE, MP_LT_VERSION, MP_LT_FLAGS,
timer_base);
smp_i2c_spi_timer(mc, MP_RTC_TYPE, MP_RTC_VER_CY14B101P, 0,
0xffffffff);
pcibios_read_config_dword(domain, dev->bus->number,
dev->devfn, PCI_BASE_ADDRESS_3, &ioepic_base);
rom_printk("Reading ioepic_base from I2C-SPI: 0x%x\n", ioepic_base);
ioepic_base = ioepic_base & 0xfffffff0; /* Masking the lower bits */
smp_write_ioepic(mc, ioepicid, domain, 0x0, ioepic_base);
smp_i2c_spi_dev(mc, 1, 15, (unsigned long)dev);
/*
* Additionally, write IO-link info for EIOHub. Otherwise, kernel
* will try to construct one by default, discover that IO-APIC entry
* is missing from the MP table (nr_ioapics) and panic.
* Includes new mpc_config_iolink fields for IOMMU: PCI MEM area
*/
rom_printk("Passing PCI MEM area for IOMMU (node %d): 0x%x - 0x%x\n",
domain, PCI_MEM_DOMAIN_START(domain),
PCI_MEM_DOMAIN_END(domain));
smp_write_iolink(mc, domain, 0, 0, 1, ioepicid,
PCI_MEM_DOMAIN_START(domain), PCI_MEM_DOMAIN_END(domain));
}
/* Setting resources for iopic, timer and cmos to mptable */
void smp_write_ioapic_i2c_spi_info(struct mpc_table *mc,
struct bios_pci_dev *dev, unsigned int ioapicid)
{
unsigned int timer_base;
unsigned long timeraddr;
unsigned int timer_upper32;
unsigned int domain = bios_pci_domain_nr(dev->bus);
pcibios_read_config_dword(domain, dev->bus->number,
dev->devfn, SYSTEM_TIMER_BASE_ADDRESS, &timer_base);
pcibios_read_config_dword(domain, dev->bus->number, dev->devfn,
SYSTEM_TIMER_UPPER_ADDRESS, &timer_upper32);
rom_printk("MP: setting timeraddr to mptable:\n"
"timer_upper32 = 0x%x, timer_base = 0x%x\n",
timer_upper32, timer_base);
timeraddr = timer_upper32;
timeraddr = (timeraddr << 32);
timeraddr |= timer_base;
smp_i2c_spi_timer(mc, MP_LT_TYPE, MP_LT_VERSION, MP_LT_FLAGS,
timeraddr);
smp_write_ioapic(mc, ioapicid, 0x11, 0xfec00000 + domain * 0x1000);
smp_i2c_spi_dev(mc, 1, 23, (unsigned long)dev);
smp_write_iolink(mc, domain, 0, 1, 3, ioapicid, 0, 0);
}
void smp_write_ioapic_intsrc_info(struct mpc_table *mc, unsigned int node,
unsigned int bus, unsigned int ioapicid)
{
smp_write_intsrc(mc, mp_ExtINT, 0x05, 0x00, 0x00, ioapicid, 0x00); /* PIC */
smp_write_intsrc(mc, mp_FixINT, 0x05, 0x1f, 0x00, ioapicid, 0x02); /* System Timer */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x1f, 0x16, ioapicid, 0x16); /* SERR */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x1f, 0x09, ioapicid, 0x09); /* gpio 1 */
#ifdef CONFIG_L_IOH2
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(1, 0),
ioapicid, 0x0a); /* Ethernet */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(10, 0),
ioapicid, 0x0c); /* USB */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(10, 1),
ioapicid, 0x0c); /* USB */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(11, 0),
ioapicid, 0x0d); /* USB */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(11, 1),
ioapicid, 0x0d); /* USB */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(2, 0),
ioapicid, 0x0b); /* IDE */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(2, 0),
ioapicid, 0x17); /* IDE hidden */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(2, 0),
ioapicid, 0x0b); /* IDE cable */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(2, 0),
ioapicid, 0x0b); /* IDE cable */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(2, 1),
ioapicid, 0x08); /* WD TIMER + gpio 0 */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(2, 1),
ioapicid, 0x0f); /* I2c/spi */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(2, 2),
ioapicid, 0x03); /* Serial Port */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(2, 2),
ioapicid, 0x04); /* Serial Port */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(2, 2),
ioapicid, 0x07); /* Parallel Port */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(2, 3),
ioapicid, 0x05); /* AC-97 */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(3, 0),
ioapicid, 0x14); /* SATA */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(3, 1),
ioapicid, 0x15); /* SATA */
#else /* IOHUB version 1 */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x02, PCI_DEVFN(1, 0),
ioapicid, 0x0a); /* Ethernet */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x03, PCI_DEVFN(1, 0),
ioapicid, 0x14); /* USB */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x02, PCI_DEVFN(2, 0),
ioapicid, 0x0b); /* IDE */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x02, PCI_DEVFN(2, 0),
ioapicid, 0x0d); /* IDE hidden */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x02, PCI_DEVFN(2, 0),
ioapicid, 0x0e); /* IDE cable */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x02, PCI_DEVFN(2, 0),
ioapicid, 0x0f); /* IDE cable */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x02, PCI_DEVFN(2, 1),
ioapicid, 0x08); /* WD TIMER + gpio 0 */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x02, PCI_DEVFN(2, 1),
ioapicid, 0x17); /* I2c/spi */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x02, PCI_DEVFN(2, 2),
ioapicid, 0x03); /* Serial Port */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x02, PCI_DEVFN(2, 2),
ioapicid, 0x04); /* Serial Port */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x02, PCI_DEVFN(2, 2),
ioapicid, 0x07); /* Parallel Port */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x02, PCI_DEVFN(2, 3),
ioapicid, 0x05); /* AC-97 */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x02, PCI_DEVFN(3, 0),
ioapicid, 0x15); /* SATA */
#endif /* CONFIG_L_IOH2 */
/* On bus 0 device 0 PCI -> PCIexp bridge pin 2 (intb) */
smp_write_intsrc(mc, mp_INT, 0x0f, 0x00, 0x01, ioapicid, 0x11); /* IOAPIC IRQ B */
/* On bus 0 device 1 virtual PCI -> PCI bridge interrupt pin unused */
/* On bus 2 device 0 PCI -> PCI bridge pin 1 */
smp_write_intsrc(mc, mp_INT, 0x0f, 0x02, 0x00, ioapicid, 0x10); /* IOAPIC IRQ A */
#if defined(CONFIG_ES2) && !defined(CONFIG_ADC_DISABLE)
smp_write_ioapic(mc, ioapicid + 1, 0x11, 0xfec01000);
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(1, 0), ioapicid + 1, 0x0a); /* ADC */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x01, PCI_DEVFN(2, 0), ioapicid + 1, 0x17); /* I2c/spi */
#endif /* CONFIG_ES2 && ! CONFIG_ADC_DISABLE */
#ifdef CONFIG_E2K_LEGACY_SIC
/* Configure embeded IO-APIC */
smp_write_ioapic(mc, ioapicid + 1, 0x11, E1CP_EMBEDED_IOAPIC_BASE);
/* IRQ0 - GC2500 level high */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x1f, 0x00, ioapicid + 1, 0x00);
/* IRQ1 - MGA2 level high */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x1f, 0x01, ioapicid + 1, 0x01);
/* IRQ2 - PMC level high */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x1f, 0x02, ioapicid + 1, 0x02);
/* IRQ3 - IIC level high */
smp_write_intsrc(mc, mp_FixINT, 0x0d, 0x1f, 0x03, ioapicid + 1, 0x03);
/* IRQ4 - IOMMU edge high */
smp_write_intsrc(mc, mp_FixINT, 0x05, 0x1f, 0x04, ioapicid + 1, 0x04);
/* IRQ5 - WLCC edge high */
smp_write_intsrc(mc, mp_FixINT, 0x05, 0x1f, 0x05, ioapicid + 1, 0x05);
/* IRQ6 - SIC edge high */
smp_write_intsrc(mc, mp_FixINT, 0x05, 0x1f, 0x06, ioapicid + 1, 0x06);
#endif /* CONFIG_E2K_LEGACY_SIC */
}
void smp_write_ioepic_intsrc_info(struct mpc_table *mc, unsigned int node,
unsigned int bus, unsigned int ioepicid)
{
if (node == 0)
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH,
MP_BUS_ISA_NUM, 0, ioepicid, 0); /* IPMB */
else
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH,
bus, PCI_DEVFN(2, 1), ioepicid, 0); /* IPMB */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus,
PCI_DEVFN(9, 0), ioepicid, 1); /* SCI */
if (node == 0)
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_EDGE_HIGH,
MP_BUS_ISA_NUM, 0, ioepicid, 2); /* System Timer */
else
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_EDGE_HIGH,
bus, PCI_DEVFN(2, 1), ioepicid, 2); /* System Timer */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(1, 0),
ioepicid, 3); /* Ethernet0_tx0 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(1, 0),
ioepicid, 4); /* Ethernet0_tx1 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(1, 0),
ioepicid, 5); /* Ethernet0_rx0 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(1, 0),
ioepicid, 6); /* Ethernet0_rx1 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(1, 0),
ioepicid, 7); /* Ethernet0_sys */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(2, 3),
ioepicid, 8); /* HDA (eioh) */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(2, 0),
ioepicid, 9); /* Mpv_timers0 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(2, 0),
ioepicid, 10); /* Mpv_timers1 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(2, 0),
ioepicid, 11); /* Mpv_timers2 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(2, 0),
ioepicid, 12); /* GPIO0 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(2, 0),
ioepicid, 13); /* GPIO1 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(2, 2),
ioepicid, 14); /* Serial port */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(2, 1),
ioepicid, 15); /* I2c/spi */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(2, 1),
ioepicid, 16); /* PCI IRQ A */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(2, 1),
ioepicid, 17); /* PCI IRQ B */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(2, 1),
ioepicid, 18); /* PCI IRQ C */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(2, 1),
ioepicid, 19); /* PCI IRQ D */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(2, 1),
ioepicid, 20); /* WD Timer */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(3, 0),
ioepicid, 21); /* SATA-3 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, MP_BUS_ISA_NUM, 22,
ioepicid, 22); /* SERR */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(1, 1),
ioepicid, 23); /* Ethernet1_tx0 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(1, 1),
ioepicid, 24); /* Ethernet2_tx1 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(1, 1),
ioepicid, 25); /* Ethernet1_rx0 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(1, 1),
ioepicid, 26); /* Ethernet1_rx1 */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(1, 1),
ioepicid, 27); /* Ethernet1_sys */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, bus, PCI_DEVFN(0, 0),
ioepicid, 28); /* USB */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_EDGE_HIGH, bus,
PCI_DEVFN(10, 0), ioepicid, 29); /* WLCC */
#ifdef CONFIG_E2C3
/* Embedded devices */
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, 0,
PCI_DEVFN(26, 0), ioepicid, 32);
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, 0,
PCI_DEVFN(26, 1), ioepicid, 33);
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, 0,
PCI_DEVFN(26, 2), ioepicid, 34);
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_LEVEL_HIGH, 0,
PCI_DEVFN(27, 0), ioepicid, 35);
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_EDGE_HIGH, 0,
PCI_DEVFN(28, 0), ioepicid, 36);
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_EDGE_HIGH, 0,
PCI_DEVFN(29, 0), ioepicid, 37);
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_EDGE_HIGH, 0,
PCI_DEVFN(30, 0), ioepicid, 38);
smp_write_intsrc(mc, mp_FixINT, MP_IRQ_EDGE_HIGH, 0,
PCI_DEVFN(31, 0), ioepicid, 39);
#endif
}
void *smp_write_config_table(struct intel_mp_floating *mpf,
unsigned int phys_cpu_num)
{
int iopic_id = 0;
static const char sig[4] = "PCMP";
static const char oem[8] = "LNXI ";
static const char productid[12] = "440GX ";
struct mpc_table *mc;
struct bios_pci_dev *dev;
unsigned int domain, bus;
mc = (void *)(((char *)mpf) + SMP_FLOATING_TABLE_LEN);
memset(mc, 0, sizeof(*mc));
memcpy(mc->mpc_signature, sig, sizeof(sig));
mc->mpc_length = sizeof(*mc); /* initially just the header */
mc->mpc_spec = 0x04;
mc->mpc_checksum = 0; /* not yet computed */
memcpy(mc->mpc_oem, oem, sizeof(oem));
memcpy(mc->mpc_productid, productid, sizeof(productid));
mc->mpc_oemptr = 0;
mc->mpc_oemsize = 0;
mc->mpc_oemcount = 0; /* No entries yet... */
mc->mpc_lapic = LAPIC_ADDR;
mc->mpe_length = 0;
mc->mpe_checksum = 0;
mc->reserved = 0;
smp_write_processors(mc, phys_cpu_num);
iopic_id = NR_CPUS /*phys_cpu_num*/;
smp_write_bus(mc, 0, "PCI ");
smp_write_bus(mc, 1, "PCI ");
smp_write_bus(mc, 2, "PCI ");
#ifdef CONFIG_E2K_SIC
smp_write_bus(mc, 3, "PCI ");
#endif /* ! CONFIG_E2K_SIC */
smp_write_bus(mc, 0x1f, "ISA ");
#ifdef CONFIG_E2K_SIC
#ifdef CONFIG_EIOH
rom_printk("MP: Scanning PCI bus for eiohub i2c/spi+ioepic\n");
dev = NULL;
do {
dev = bios_pci_find_device(PCI_VENDOR_ID_MCST_TMP,
PCI_DEVICE_ID_MCST_I2C_SPI_EPIC, dev);
if (dev) {
domain = bios_pci_domain_nr(dev->bus);
bus = dev->bus->number;
rom_printk("found on domain %d bus %d "
"device %d\n",
domain, bus, PCI_SLOT(dev->devfn));
smp_write_ioepic_i2c_spi_info(mc, dev, iopic_id);
smp_write_ioepic_intsrc_info(mc, domain, bus, iopic_id);
iopic_id++;
}
} while (dev);
#endif
rom_printk("MP: Scanning PCI bus for iohub1 i2c/spi+ioapic\n");
dev = NULL;
do {
dev = bios_pci_find_device(INTEL_MULTIFUNC_VENDOR,
INTEL_MULTIFUNC_DEVICE, dev);
if (dev) {
domain = bios_pci_domain_nr(dev->bus);
bus = dev->bus->number;
rom_printk("IOHub found on domain %d bus %d "
"device %d\n",
domain, bus, PCI_SLOT(dev->devfn));
smp_write_ioapic_i2c_spi_info(mc, dev, iopic_id);
smp_write_ioapic_intsrc_info(mc, domain, bus, iopic_id);
iopic_id++;
}
} while (dev);
rom_printk("MP: Scanning PCI bus for iohub2 i2c/spi+ioapic\n");
dev = NULL;
do {
dev = bios_pci_find_device(PCI_VENDOR_ID_MCST_TMP,
PCI_DEVICE_ID_MCST_I2C_SPI, dev);
if (dev) {
domain = bios_pci_domain_nr(dev->bus);
bus = dev->bus->number;
rom_printk("IOHub-2 found on domain %d bus %d "
"device %d\n",
domain, bus, PCI_SLOT(dev->devfn));
smp_write_ioapic_i2c_spi_info(mc, dev, iopic_id);
smp_write_ioapic_intsrc_info(mc, domain, bus, iopic_id);
iopic_id++;
}
} while (dev);
#endif
#ifndef CONFIG_EIOH
/* Standard local interrupt assignments */
smp_write_lintsrc(mc, mp_ExtINT, 0x05, 0x03, 0x00, MP_APIC_ALL, 0x00); /* local connection pic->ioapic */
smp_write_lintsrc(mc, mp_NMI, 0x05, 0x00, 0x00, MP_APIC_ALL, 0x01); /* local connection lapic->ioapic */
#endif
mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);
mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
printk_debug("Wrote the mp table end at: %px - %px\n",
mc, smp_next_mpe_entry(mc));
return smp_next_mpe_entry(mc);
}
unsigned int write_smp_table(struct intel_mp_floating *mpf, unsigned int phys_cpu_num)
{
rom_printk("write_smp_table() will create floating table\n");
smp_write_floating_table(mpf);
return (unsigned long)smp_write_config_table(mpf, phys_cpu_num);
}

1707
arch/e2k/boot/bios/newpci.c Normal file

File diff suppressed because it is too large Load Diff

605
arch/e2k/boot/bios/pci.h Normal file
View File

@ -0,0 +1,605 @@
/*
* $Id: pci.h,v 1.13 2009/01/27 11:34:42 atic Exp $
*
* PCI defines and function prototypes
* Copyright 1994, Drew Eckhardt
* Copyright 1997--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*
* For more information, please consult the following manuals (look at
* http://www.pcisig.com/ for how to get them):
*
* PCI BIOS Specification
* PCI Local Bus Specification
* PCI to PCI Bridge Specification
* PCI System Design Guide
*/
#ifndef PCI_H
#define PCI_H
#include <linux/types.h>
#include <linux/pci.h>
#include "../boot_io.h"
extern void *malloc(int size);
#undef BIOS_DEBUG
#define PCIBIOS_DEBUG 0
#define BIOS_DEBUG PCIBIOS_DEBUG
#include "printk.h"
#undef DEBUG_PCI_MODE
#undef DebugCI
#define DEBUG_PCI_MODE 0 /* PCI scanning */
#define DebugPCI(fmt, args...) \
({ if (DEBUG_PCI_MODE) \
rom_printk(fmt, ##args); })
/*
* PCI memory and IO ports mapping
*/
#ifdef CONFIG_E2K_SIC
#define PCI_IO_START 0x00000000
#define PCI_IO_DOMAIN_SIZE 0x00004000
#define PCI_IO_END 0x00010000
#define PCI_MEM_START 0x80000000UL
#define PCI_MEM_DOMAIN_SIZE 0x10000000UL
#define PCI_MEM_END E2K_PCI_MEM_AREA_PHYS_END // f800_0000
#define IOHUB_SCRB_DOMAIN_SIZE E2K_SCRB_SIZE // 1000
#define PCI_IO_DOMAIN_START(domain) \
(PCI_IO_START + PCI_IO_DOMAIN_SIZE * (domain))
#define PCI_IO_DOMAIN_END(domain) \
({ \
unsigned long io_end; \
io_end = (PCI_IO_DOMAIN_START(domain) + PCI_IO_DOMAIN_SIZE); \
if (io_end > PCI_IO_END) \
io_end = PCI_IO_END; \
io_end; \
})
#define PCI_MEM_DOMAIN_START(domain) \
(PCI_MEM_START + PCI_MEM_DOMAIN_SIZE * (domain))
#define PCI_MEM_DOMAIN_END(domain) \
({ \
unsigned long mem_end; \
mem_end = (PCI_MEM_DOMAIN_START(domain) + PCI_MEM_DOMAIN_SIZE); \
if (mem_end > PCI_MEM_END) \
mem_end = PCI_MEM_END; \
mem_end; \
})
#define IOHUB_SCRB_DOMAIN_START(domain) \
(PCI_MEM_DOMAIN_END(domain) - IOHUB_SCRB_DOMAIN_SIZE)
#define IOHUB_SCRB_DOMAIN_END(domain) \
(PCI_MEM_DOMAIN_END(domain))
#endif /* CONFIG_E2K_SIC */
/*
* Under PCI, each device has 256 bytes of configuration address space,
* of which the first 64 bytes are standardized as follows:
*/
#ifdef CONFIG_E2K_SIC
/* Additional registers in PCI configuration space for virtual PCI to PCI bridges */
#if defined(CONFIG_L_IOH2)
/* IOHUB Device Number register */
#define IOH2_DevNum 0x44 /* IOHUB Device Number */
#define IOHUB_DevNum IOH2_DevNum
#define IOHUB_DevNum_valid 0x0100
#define set_IOHUB_DevNum(num) ((num) & 0x000f)
#else /* IOHUB version 1 */
#define PCI_SCBA_0 0xf0 /* System commutator base address [31:00] */
#define PCI_SCBA_1 0xf4 /* System commutator base address [63:32] */
/* IOHUB Device Number register */
#define IOH_DevNum 0xf8
#define IOHUB_DevNum IOH_DevNum
#define IOHUB_DevNum_valid 0x10
#define set_IOHUB_DevNum(num) ((num) & 0x0f)
#endif /* CONFIG_L_IOH2 */
/* Additional registers in PCI configuration space for I2C/SPI controller */
/** IOAPIC Base Address(SCRB: "ioapic" Mem Base Address Register 0) **/
#define IOAPIC_BASE_ADDRESS 0x40 // [31:5]-RWS [4:0]-RO
/** IOAPIC Upper Base Address(SCRB: "ioapic" Mem Base Address Register 0 Upper 32 bits) **/
#define IOAPIC_UPPER_ADDRESS 0x44
/** MSI TRANSACTION ADDRESS (SCRB: "ioapic" Mem Base Address Register 1) **/
#define MSI_TRANSACTION_ADDRESS 0x48 // [31:2]-RWS [1:0]-RO
/** MSI TRANSACTION UPPER ADDRESS(SCRB: "ioapic" Mem Base Address Register 1 Upper 32 bits) **/
#define MSI_TRANSACTION_UPPER_ADDRESS 0x4c
/** IOPIC Message Base Address(SCRB: "ioapic" Mem Base Address Register 2) **/
#define IOAPIC_MESSAGE_BASE_ADDRESS 0x50 // [31:12]-RWS [11:0]-RO
/** IOPIC Upper Base Address(SCRB: "ioapic" Mem Base Address Register 2 Upper 32 bits) **/
#define IOAPIC_MESSAGE_UPPER_ADDRESS 0x54
/** System Timer Base Address(SCRB: "timer" Mem Base Address Register 0) **/
#define SYSTEM_TIMER_BASE_ADDRESS 0x58 // [31:6]-RWS [5:0]-RO
/** System Timer Upper Base Address(SCRB: "timer" Mem Base Address Register 0 Upper 32 bits) **/
#define SYSTEM_TIMER_UPPER_ADDRESS 0x5c
/** Reset Control **/
#define RESET_CONTROL 0x60
/** Software Reset Control **/
#define SOFTWARE_RESET_CONTROL 0x64
/** Software Reset Duration **/
#define SOFTWARE_RESET_DURATION 0x68
/** LAPIC Message Base Address **/
#define LAPIC_MESSAGE_BASE_ADDRESS 0x6c
/** LAPIC Message Upper Address **/
#define LAPIC_MESSAGE_UPPER_ADDRESS 0x70
#define IOAPICINT_BASE 0x13000000
#define SAPICINT_BASE 0x1f000000
#define LAPICINT_BASE 0x17000000
#define APICINT_SIZE 0x01000000
#define ES2_LAPICINT_BASE 0x120000000
#define ES2_IOAPICINT_BASE 0x130000000
#define ES2_SAPICINT_BASE 0x140000000
#define E2S_LAPICINT_BASE ES2_LAPICINT_BASE
#define E2S_IOAPICINT_BASE ES2_IOAPICINT_BASE
#define E2S_SAPICINT_BASE ES2_SAPICINT_BASE
#define E8C_LAPICINT_BASE ES2_LAPICINT_BASE
#define E8C_IOAPICINT_BASE ES2_IOAPICINT_BASE
#define E8C_SAPICINT_BASE ES2_SAPICINT_BASE
#define E1CP_EMBEDED_IOAPIC_BASE 0x00000010fec01000
#define E1CP_LEGACY_NBSR_BASE 0x0000001100000000
#define E1CP_LAPICINT_BASE 0x0000001200000000
#define E1CP_IOAPICINT_BASE 0x0000001300000000
#define E1CP_PMC_BASE 0x0000001400000000
#define E12C_IOAPICINT_BASE 0x122000000
#define E16C_IOAPICINT_BASE E12C_IOAPICINT_BASE
#define E2C3_IOAPICINT_BASE E12C_IOAPICINT_BASE
/* LAPICINT and SAPICINT do not exist on EPIC systems */
#ifndef CONFIG_BOOT_EPIC
#define E12C_LAPICINT_BASE E8C_LAPICINT_BASE
#define E12C_SAPICINT_BASE E8C_SAPICINT_BASE
#define E16C_LAPICINT_BASE E8C_LAPICINT_BASE
#define E16C_SAPICINT_BASE E8C_SAPICINT_BASE
#define E2C3_LAPICINT_BASE E8C_LAPICINT_BASE
#define E2C3_SAPICINT_BASE E8C_SAPICINT_BASE
#endif
#endif
#define INTEL_MULTIFUNC_VENDOR PCI_VENDOR_ID_INTEL
#define INTEL_MULTIFUNC_DEVICE 0x0002
#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */
#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */
#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
#ifdef CONFIG_E2K_SIC
/* SCRB registers only for bus after virual bus */
#define B0_SE 0x104 /* 8/0x03 PCIe brigde Spaces Enable 0:N:0{04} */
#define B0_BN 0x118 /* 32/0x00ffffff PCIe brigde Bus Number 0:N:0{0x18-0x1b} */
#define B0_IOBL 0x11c /* 16/0xf0f0 PCIe bridge I/O Base and
* Limit Register 0:N:0{0x1c-0x1d} */
#define B0_IOBLU 0x130 /* 32/0xffffffff PCIe bridge I/O Base and
* Limit Upper 16 bits 0:N:0{0x30-0x33} */
#define B0_MBL 0x120 /* 32/0xfff0fff0 PCIe bridge Mem Base and
* Limit Register 0:N:0{0x20-0x23} */
#define B0_PMBL 0x124 /* 32/0xfff0fff0 PCIe bridge Prefetchable
* Mem Base and Limit Register 0:N:0{0x24-0x27} */
#define B0_PMBU32 0x128 /* 32/0xffffffff PCIe bridge Prefetchable
* Memory Base Upper 32 bits 0:N:0{0x28-0x2b} */
#define B0_PMLU32 0x12c /* 32/0xffffffff PCIe bridge Prefetchable
* Memory Limit Upper 32 bits 0:N:0{0x2c-0x2f} */
#define B0_BA0 0x17c /* 32/0xfffffff0 PCIe bridge Base Address
* Register 0:N:0{0x7c-0x7f} */
#define B0_BUA0 0x180 /* 32/0xffffffff PCIe bridge Base Address
* Upper 32 bits 0:N:0{0x80-0x83} */
#define B0_BCTRL 0x13e /* 8/0x03 PCIe bridge control 0:N:0{0x3e} */
#define B1_SE 0x204 /* 8/0x03 PCI bridge Spaces Enable m:0:0{0x04} */
#define B1_BN 0x218 /* 32/0x00ffffff PCI bridge Bus Number m:0:0{0x18-0x1b} */
#define B1_IOBL 0x21c /* 16/0xf0f0 PCI bridge I/O Base and
* Limit Register m:0:0{0x1c-0x1d} */
#define B1_IOBLU 0x230 /* 32/0xffffffff PCI bridge I/O Base and
* Limit Upper 16 bits m:0:0{0x30-0x33} */
#define B1_MBL 0x220 /* 32/0xfff0fff0 PCI bridge Mem Base and
* Limit Register m:0:0{0x20-0x23} */
#define B1_PMBL 0x224 /* 32/0xfff0fff0 PCI bridge Prefetchable
* Mem Base and Limit Register m:0:0{0x24-0x27} */
#define B1_PMBU32 0x228 /* 32/0xffffffff PCI bridge Prefetchable
* Memory Base Upper 32 bits m:0:0{0x28-0x2b} */
#define B1_PMLU32 0x22c /* 32/0xffffffff PCI bridge Prefetchable
* Memory Limit Upper 32 bits m:0:0{0x2c-0x2f} */
#define B1_BCTRL 0x23e /* 8/0x1c PCI bridge control m:0:0{0x3e} */
#define A0_SE 0x304 /* 8/0x02 "AC97" Mem Space Enable m:2:3{0x04} */
#define A0_BA0 0x310 /* 32/0xfffff000 "AC97" Mem Base Address
* Register 0 m:2:3{0x10-0x13} */
#define A0_BA1 0x314 /* 32/0xfffff000 "gpio" Mem Base Address
* Register 1 m:2:3{0x14-0x17} */
#define A1_SE 0x404 /* 8/0x02 "i2c/spi/ioapic" Mem Space
* Enable m:2:1{0x04} */
#define A1_BA0 0x410 /* 32/0xffffffc0 "i2c/spi" Mem Base Address
* Register 0 m:2:1{0x10-0x13} */
#define A1_BA1 0x414 /* 32/0xffffffc0 "i2c/spi" Mem Base Address
* Register 1 m:2:1{0x14-0x17} */
#define A2_BA0 0x440 /* 32/0xffffffe0 "ioapic" Mem Base Address
* Register 0 m:2:1{0x40-0x43} */
#define A2_BUA0 0x444 /* 32/0xffffffff "ioapic" Mem Base Address 0
* Upper 32 bits m:2:1{0x44-0x47} */
#define A2_BA1 0x448 /* 32/0xfffffffc "ioapic" Mem Base Address
* Register 1 m:2:1{0x48-0x4b} */
#define A2_BUA1 0x44c /* 32/0xffffffff "ioapic" Mem Base Address 1
* Upper 32 bits m:2:1{0x4c-0x4f} */
#define A2_BA2 0x450 /* 32/0xfffff000 "ioapic" Mem Base Address
* Register 2 m:2:1{0x50-0x53} */
#define A2_BUA2 0x454 /* 32/0xffffffff "ioapic" Mem Base Address 2
* Upper 32 bits m:2:1{0x54-0x57} */
#define A3_BA0 0x458 /* 32/0xffffffc0 "timer" Mem Base Address
* Register 0 m:2:1{0x58-0x5b} */
#define A3_BUA0 0x45c /* 32/0xffffffff "timer" Mem Base Address
* Upper 32 bits m:2:1{0x5c-0x5f} */
#define A4_SE 0x504 /* 8/0x02 "eth" Mem Space Enable m:1:0{0x04} */
#define A4_BA0 0x510 /* 32/0xffffffe0 "eth" Mem Base Address
* Register m:1:0{0x10-0x13} */
#define A5_SE 0x604 /* 8/0x03 "parport/rs232" Spaces
* Enable m:2:2{0x04} */
#define A5_BA0 0x610 /* 32/0xffffffe0 "parport" IO Base Address
* Register m:2:2{0x10-0x13} */
#define A6_BA0 0x614 /* 32/?? "rs232" Mem Base Address
* Register m:2:2{0x14-0x17} */
#define A7_SE 0x704 /* 8/0x03 "IDE" Spaces Enable m:2:0{0x04} */
#define A7_AMR 0x709 /* 8/0x05 "IDE" Addressing Mode
* Register m:2:0{0x09} */
#define A7_BA0 0x710 /* 32/0xfffffff8 "IDE" IO Base Address
* Register 0 m:2:0{0x10-0x13} */
#define A7_BA1 0x714 /* 32/0xfffffffc "IDE" IO Base Address
* Register 1 m:2:0{0x14-0x17} */
#define A7_BA2 0x718 /* 32/0xfffffff8 "IDE" IO Base Address
* Register 2 m:2:0{0x18-0x1b} */
#define A7_BA3 0x71c /* 32/0xfffffffc "IDE" IO Base Address
* Register 3 m:2:0{0x1c-0x1f} */
#define A7_BA4 0x720 /* 32/0x0000fff0 "IDE" IO Base Address
* Register 4 m:2:0{0x20-0x23} */
#define A7_HCE 0x750 /* 8/0x40 "IDE" Hidden Channel
* Enable m:2:0{0x50} */
#define A7_BA5 0x758 /* 32/0xffffffe0 "IDE" Mem Base Address
* Register 5 m:2:0{0x58-0x5b} */
#define A7_BUA5 0x75c /* 32/0xffffffff "IDE" Mem Base Address 5
* Upper 32 bits m:2:0{0x5c-0x5f} */
#define A7_BA6 0x760 /* 32/0xfffffff0 "IDE" Mem Base Address
* Register 6 m:2:0{0x60-0x63} */
#define A7_BUA6 0x764 /* 32/0xffffffff "IDE" Mem Base Address 6
* Upper 32 bits m:2:0{0x64-0x67} */
#define A7_BA7 0x768 /* 32/0xfffffff0 "IDE" Mem Base Address
* Register 7 m:2:0{0x68-0x6b} */
#define A7_BUA7 0x76c /* 32/0xffffffff "IDE" Mem Base Address 7
* Upper 32 bits m:2:0{0x6c-0x6f} */
/* 8/0x02 "SATA" Spaces Enable m:2:0{0x04} */
#define A8_SE 0x804
/* 8/0x24-0x27 "SATA" Mem Base Address Register m:3:0{0x24-0x27} */
#define A8_ABAR 0x824
/* Control Register */
#define AHOM 0xa00 /* Abonent Hide Operation Mode R/W */
/* Registers for Real Pci 2 Pci Bridge */
#define Arb_CtlSta 0x78 /* Arbitration Control (Real Pci 2 Pci Configuration Space) */
#endif
/*
* There is one bios_pci_dev structure for each slot-number/function-number
* combination:
*/
struct bios_pci_dev {
struct bios_pci_bus *bus; /* bus this device is on */
struct bios_pci_dev *sibling; /* next device on this bus */
struct bios_pci_dev *next; /* chain of all devices */
void *sysdata; /* hook for sys-specific extension */
struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */
unsigned int devfn; /* encoded device & function index */
unsigned short vendor;
unsigned short device;
unsigned char revision; /* chip revision */
unsigned int class; /* 3 bytes: (base,sub,prog-if) */
unsigned char subsys_id; /* subsystem ID */
unsigned int hdr_type; /* PCI header type */
unsigned int master : 1; /* set if device is master capable */
u8 command;
/*
* In theory, the irq level can be read from configuration
* space and all would be fine. However, old PCI chips don't
* support these registers and return 0 instead. For example,
* the Vision864-P rev 0 chip can uses INTA, but returns 0 in
* the interrupt line and pin registers. pci_init()
* initializes this field with the value at PCI_INTERRUPT_LINE
* and it is the job of pcibios_fixup() to change it if
* necessary. The field must not be 0 unless the device
* cannot generate interrupts at all.
*/
unsigned int irq; /* irq generated by this device */
/* Base registers for this device, can be adjusted by
* pcibios_fixup() as necessary.
*/
unsigned long base_address[6];
unsigned long size[6];
unsigned long rom_address;
unsigned long rom_size;
};
struct bios_pci_bus {
struct bios_pci_bus *parent; /* parent bus this bridge is on */
struct bios_pci_bus *children; /* chain of P2P bridges on this bus */
struct bios_pci_bus *next; /* chain of all PCI buses */
struct bios_pci_dev *self; /* bridge device as seen by parent */
struct bios_pci_dev *devices; /* devices behind this bridge */
void *sysdata; /* hook for sys-specific extension */
struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */
unsigned char number; /* bus number */
unsigned char primary; /* number of primary bridge */
unsigned char secondary; /* number of secondary bridge */
unsigned char subordinate; /* max number of subordinate buses */
unsigned long mem, prefmem, io; /* amount of mem, prefetch mem,
* and I/O needed for this bridge.
* computed by compute_resources,
* inclusive of all child bridges
* and devices
*/
u32 membase, memlimit;
u32 prefmembase, prefmemlimit;
u32 iobase, iolimit;
};
extern struct bios_pci_bus pci_root[]; /* root buses */
extern int pci_root_num;
extern struct bios_pci_dev *pci_devices; /* list of all devices */
#ifdef CONFIG_E2K_SIC
static inline int bios_pci_domain_nr(struct bios_pci_bus *bus)
{
return ((unsigned long)bus->sysdata);
}
static inline void bios_set_pci_domain_nr(struct bios_pci_bus *bus, int domain)
{
bus->sysdata = (void *)domain;
}
#endif /* CONFIG_E2K_SIC */
/*
* Error values that may be returned by the PCI bios.
*/
#define PCIBIOS_SUCCESSFUL 0x00
#define PCIBIOS_FUNC_NOT_SUPPORTED 0x81
#define PCIBIOS_BAD_VENDOR_ID 0x83
#define PCIBIOS_DEVICE_NOT_FOUND 0x86
#define PCIBIOS_BAD_REGISTER_NUMBER 0x87
#define PCIBIOS_SET_FAILED 0x88
#define PCIBIOS_BUFFER_TOO_SMALL 0x89
/* Class Code register */
#define NATIVE_MODE_PRIMARY_CLASSC 0x01 /* primary channel in native */
/* mode */
#define NATIVE_MODE_SECONDARY_CLASSC 0x04 /* secondary channel in */
/* native mode */
#define NATIVE_MODE_CLASSC (NATIVE_MODE_PRIMARY_CLASSC | \
NATIVE_MODE_SECONDARY_CLASSC)
/* Low-level architecture-dependent routines */
int pcibios_present (void);
void pcibios_init(void);
void pcibios_fixup(void);
char *pcibios_setup (char *str);
int bios_pci_read_config_byte(struct bios_pci_dev *dev, u8 where, u8 *val);
int bios_pci_read_config_word(struct bios_pci_dev *dev, u8 where, u16 *val);
int bios_pci_read_config_dword(struct bios_pci_dev *dev, u8 where, u32 *val);
int bios_pci_write_config_byte(struct bios_pci_dev *dev, u8 where, u8 val);
int bios_pci_write_config_word(struct bios_pci_dev *dev, u8 where, u16 val);
int bios_pci_write_config_dword(struct bios_pci_dev *dev, u8 where, u32 val);
int pcibios_read_config_byte(int domain, unsigned char bus, unsigned char dev_fn,
unsigned char where, u8 *val);
int pcibios_read_config_word(int domain, unsigned char bus, unsigned char dev_fn,
unsigned char where, u16 *val);
int pcibios_read_config_dword(int domain, unsigned char bus, unsigned char dev_fn,
unsigned char where, u32 *val);
int pcibios_write_config_byte(int domain, unsigned char bus, unsigned char dev_fn,
unsigned char where, u8 val);
int pcibios_write_config_word(int domain, unsigned char bus, unsigned char dev_fn,
unsigned char where, u16 val);
int pcibios_write_config_dword(int domain, unsigned char bus, unsigned char dev_fn,
unsigned char where, u32 val);
int pcibios_debugwrite_config_byte(int domain, unsigned char bus, unsigned char dev_fn,
unsigned char where, u8 val);
int pcibios_debugwrite_config_word(int domain, unsigned char bus, unsigned char dev_fn,
unsigned char where, u16 val);
int pcibios_debugwrite_config_dword(int domain, unsigned char bus, unsigned char dev_fn,
unsigned char where, u32 val);
#ifdef CONFIG_E2K_SIC
#ifndef CONFIG_L_IOH2
int system_commutator_es2_ioh_write_byte(int domain, unsigned char bus,
int where, u8 value);
int system_commutator_es2_ioh_read_byte(int domain, unsigned char bus,
int where, u8 *value);
int system_commutator_es2_ioh_write_word(int domain, unsigned char bus,
int where, u16 value);
int system_commutator_es2_ioh_read_word(int domain, unsigned char bus,
int where, u16 *value);
int system_commutator_es2_ioh_write_dword(int domain, unsigned char bus,
int where, u32 value);
int system_commutator_es2_ioh_read_dword(int domain, unsigned char bus,
int where, u32 *value);
#else /* CONFIG_L_IOH2 */
/* IOHUB #2 has not SCRB registers to read/write */
#define system_commutator_es2_ioh_write_byte(domain, bus, where, value) 0
#define system_commutator_es2_ioh_read_byte(domain, bus, where, value) 0
#define system_commutator_es2_ioh_write_word(domain, bus, where, value) 0
#define system_commutator_es2_ioh_read_word(domain, bus, where, value) 0
#define system_commutator_es2_ioh_write_dword(domain, bus, where, value) 0
#define system_commutator_es2_ioh_read_dword(domain, bus, where, value) 0
#endif /* ! CONFIG_L_IOH2 */
#endif /* CONFIG_E2K_SIC */
/* Don't use these in new code, use pci_find_... instead */
int pcibios_find_class (unsigned int class_code, unsigned short index, unsigned char *bus, unsigned char *dev_fn);
int pcibios_find_device (unsigned short vendor, unsigned short dev_id,
unsigned short index, unsigned char *bus,
unsigned char *dev_fn);
/* Generic PCI interface functions */
struct bios_pci_bus *pci_init(int domain);
void pci_setup(char *str, int *ints);
void pci_quirks_init(void);
void pci_proc_init(void);
void proc_old_pci_init(void);
int get_pci_list(char *buf);
int pci_proc_attach_device(struct bios_pci_dev *dev);
int pci_proc_detach_device(struct bios_pci_dev *dev);
struct bios_pci_dev *bios_pci_find_device(unsigned int vendor,
unsigned int device, struct bios_pci_dev *from);
struct bios_pci_dev *pci_find_class(unsigned int class,
struct bios_pci_dev *from);
struct bios_pci_dev *pci_find_slot(unsigned int bus, unsigned int devfn);
#define pci_present pcibios_present
int pci_debugwrite_config_byte(struct bios_pci_dev *dev, u8 where, u8 val);
int pci_debugwrite_config_word(struct bios_pci_dev *dev, u8 where, u16 val);
int pci_debugwrite_config_dword(struct bios_pci_dev *dev, u8 where, u32 val);
void bios_pci_set_master(struct bios_pci_dev *dev);
void pci_set_method(void);
struct bios_pci_bus *pci_enumerate(int domain);
void pci_configure(struct bios_pci_bus *root_bus);
void pci_enable(struct bios_pci_bus *root_bus);
void pci_zero_irq_settings(void);
// historical functions ...
void intel_conf_writeb(unsigned long port, unsigned char value);
unsigned char intel_conf_readb(unsigned long port);
#ifdef CONFIG_E2K_SIC
static inline void set_iohub_dev_num(int domain)
{
int devfn;
unsigned int reg;
reg = set_IOHUB_DevNum(domain) | IOHUB_DevNum_valid;
#ifdef CONFIG_L_IOH2
devfn = domain * 8;
pcibios_write_config_word(domain, 0, devfn, IOHUB_DevNum, (u16)reg);
pcibios_read_config_word(domain, 0, devfn, IOHUB_DevNum, (u16 *)&reg);
#else /* IOHUB-1 */
devfn = (domain * 2 + 1) * 8; /* slot #0 PCIe, #1: virt PCI to PCI */
pcibios_write_config_byte(domain, 0, devfn, IOHUB_DevNum, (u8)reg);
pcibios_read_config_byte(domain, 0, devfn, IOHUB_DevNum, (u8 *)&reg);
#endif /* CONFIG_L_IOH2 */
DebugPCI("set_iohub_dev_num() set device number to 0x%04x\n", reg);
}
#endif /* CONFIG_E2K_SIC */
// Rounding for boundaries.
// Due to some chip bugs, go ahead and roung IO to 16
#define IO_ALIGN 16
#define IO_BRIDGE_ALIGN 4096
#define MEM_ALIGN 4096
#include "pciconf.h"
/* linkages from devices of a type (e.g. superio devices)
* to the actual physical PCI device. This type is used in an array of
* structs built by NLBConfig.py. We owe this idea to Plan 9.
*/
struct superio;
struct superio_control {
void (*pre_pci_init)(struct superio *s);
void (*init)(struct superio *s);
void (*finishup)(struct superio *s);
unsigned int defaultport; /* the defaultport. Can be overridden
* by commands in config
*/
// This is the print name for debugging
char *name;
};
struct com_ports {
unsigned int enable,baud, base, irq;
};
// lpt port description.
// Note that for many superios you only really need to define the
// enable.
struct lpt_ports {
unsigned int enable, // 1 if this port is enabled
mode, // pp mode
base, // IO base of the parallel port
irq; // irq
};
struct superio {
struct superio_control *super; // the ops for the device.
unsigned int port; // if non-zero, overrides the default port
// com ports. This is not done as an array (yet).
// We think it's easier to set up from python if it is not an array.
struct com_ports com1, com2, com3, com4;
// DMA, if it exists.
struct lpt_ports lpt1, lpt2;
/* flags for each device type. Unsigned int. */
// low order bit ALWAYS means enable. Next bit means to enable
// LPT is in transition, so we leave this here for the moment.
// The winbond chips really stretched the way this works.
// so many functions!
unsigned int ide, floppy, lpt;
unsigned int keyboard, cir, game;
unsigned int gpio1, gpio2, gpio3;
unsigned int acpi,hwmonitor;
};
struct southbridge;
struct southbridge_control {
void (*pre_pci_init)(struct southbridge *s);
void (*init)(struct southbridge *s);
void (*finishup)(struct southbridge *s);
// this is the vendor and device id
unsigned int vendor, device;
// This is the print name for debugging
char *name;
};
struct southbridge {
struct bios_pci_dev *device; /* the device. */
struct southbridge_control *southbridge; /* the ops for the device. */
unsigned int devfn; /* the devfn.
* if devfn is known, the device can be
* configured for PCI discovery.
* this is needed for some devices
* such as acer m1535
*/
/* flags for each device type. Unsigned int.
* low order bit ALWAYS means enable. Next bit means to enable
* DMA, if it exists.
*/
unsigned int ide;
};
#endif /* PCI_H */

View File

@ -0,0 +1,83 @@
/*
* Southbridge configuration.
* PCI/ISA Bridge Configuration Registers (Function 0).
*/
#ifndef _PCI_ISA_CONFIG_H_
#define _PCI_ISA_CONFIG_H_
#include <asm/head.h>
#include <asm/mas.h>
#include <asm/e2k_api.h>
#define PSI_ISA_CONFIG_REGS_FUNC 0
/* REG XBCS
* X-BUS CHIP SELECT REGISTER 4E-4F default 0x3
*/
#define SB_XBCS 0x4E // 4E-4F
#define SB_XBCS_io_lo 0x4E // 4E-4F
#define SB_XBCS_io_hi 0x4F // 4E-4F
#define SB_XBCS_DEFAULT 0x0003
#define SB_XBCS_RTC_ENABLE 0x0001
#define SB_XBCS_KBC_ENABLE 0x0002
#define SB_XBCS_BIOSWP_ENABLE 0x0004
#define SB_XBCS_PORT61ALIAS_ENABLE 0x0008
#define SB_XBCS_IRQ12_MOUSE_ENABLE 0x0010
#define SB_XBCS_COERR_ENABLE 0x0020
#define SB_XBCS_LOWER_BIOS_ENABLE 0x0040
#define SB_XBCS_EXT_BIOS_ENABLE 0x0080
#define SB_XBCS_IOAPIC_ENABLE 0x0100
#define SB_XBCS_1M_EXT_BIOS_ENABLE 0x0200
/* Micro Controller Adress Location */
#define SB_XBCS_MCA_LOCATION_ENABLE 0x0400
#define SB_XBCS_MASK 0x07FF
/* REG SERIRQC
* SERIAL IRQ CONTROL REGISTER 64H default 0x10
*/
#define SB_SERIRQC 0x64
/* Start Frame Pulse Width bits 1:0 */
#define SB_SERIRQC_SFP_4CLOCK 0x00
#define SB_SERIRQC_SFP_6CLOCK 0x01
#define SB_SERIRQC_SFP_8CLOCK 0x02
#define SB_SERIRQC_SFP_RESERVED 0x03
#define SB_SERIRQC_SFP_MASK 0x03
/* Serial IRQ Frame Size bits 5:2, only 0100b supported by PIIX4 */
#define SB_SERIRQC_FRAME_SIZE 0x10
#define SB_SERIRQC_FRAME_MASK 0x3C
/* Serial IRQ Mode Select bit 6, 0 - quite mode 1 - continuous mode */
#define SB_SERIRQC_SHIFT 6
#define SB_SERIRQC_CONT_MODE 0x40
/* Serial IRQ Enable, bit 16 in register offset B0h-B3h must also be 1 */
#define SB_SERIRQC_IRQ_ENABLE 0x80
/* REG GENCFG
* GENERAL CONFIGURATION REGISTER B0-B3h default 0
*/
#define SB_GENCFG 0XB0 // B0 - B4
#define SB_GENCFG1 0XB0
#define SB_GENCFG2 0XB1
#define SB_GENCFG3 0XB2
#define SB_GENCFG4 0XB3
/* 0=EOI 1=ISA */
#define SB_GENCFG_ISA_SELECT 0x00000001
#define SB_GENCFG_DECODE_CONFIG 0x00000002
#define SB_GENCFG_CONFIG_1 0x00000004
#define SB_GENCFG_CONFIG_2 0x00000008
/* 0 - primary&secondary interface, 1 - primary0&primary1 */
#define SB_GENCFG_IDE_INTERFACE 0x00000010
#define SB_GENCFG_ALT_ACCESS_MODE 0x00000020
#define SB_GENCFG_PnP_ADDR_DECODE_ENABLE 0x00000040
//#define SB_GENCFG_RESERVED 0x00000080
#define SB_GENCFG_SIGNAL_PIN_SELECTED8 0x00000100
#define SB_GENCFG_SIGNAL_PIN_SELECTED9 0x00000200
#define SB_GENCFG_SIGNAL_PIN_SELECTED10 0x00000400
#define SB_GENCFG_PRIMARY_IDE_SigIn 0x00000800
#define SB_GENCFG_SECONDARY_IDE_SigIn 0x00001000
//#define SB_GENCFG_RESERVED 0x00002000
/* 14 - 31 bits Signal Pin Selected*/
#define SB_GENCFG_SIGNAL_PIN_SELECTED14 0x00004000
#define SB_GENCFG_SERIRQ_PIN_SELECTED 0x00010000
#endif /* _PCI_ISA_CONFIG_H_ */

View File

@ -0,0 +1,7 @@
#ifndef PCI_CONF_REG_INDEX
// These are defined in the PCI spec, and hence are theoretically
// inclusive of ANYTHING that uses a PCI bus.
#define PCI_CONF_REG_INDEX 0xcf8
#define PCI_CONF_REG_DATA 0xcfc
#define CONFIG_ADDR(bus,devfn,where) (((bus) << 16) | ((devfn) << 8) | (where))
#endif

View File

@ -0,0 +1,43 @@
/*
* $Id: printk.h,v 1.1 2005/08/19 13:17:27 kostin Exp $
*/
#ifndef _PRINTK_H_
#define _PRINTK_H_
extern void rom_printk(char const *fmt, ...);
#define do_printk rom_printk
#undef printk_emerg
#undef printk_alert
#undef printk_crit
#undef printk_err
#undef printk_warning
#undef printk_notice
#undef printk_info
#undef printk_debug
#undef printk_spew
#ifdef BIOS_DEBUG
#define printk_emerg(fmt, arg...) do_printk(fmt, ##arg)
#define printk_alert(fmt, arg...) do_printk(fmt, ##arg)
#define printk_crit(fmt, arg...) do_printk(fmt, ##arg)
#define printk_err(fmt, arg...) do_printk(fmt, ##arg)
#define printk_warning(fmt, arg...) do_printk(fmt, ##arg)
#define printk_notice(fmt, arg...) do_printk(fmt, ##arg)
#define printk_info(fmt, arg...) do_printk(fmt, ##arg)
#define printk_debug(fmt, arg...) if (BIOS_DEBUG > 0) do_printk(fmt, ##arg)
#define printk_spew(fmt, arg...) if (BIOS_DEBUG > 1) do_printk(fmt, ##arg)
#else
#define printk_emerg(fmt, arg...) do_printk(fmt, ##arg)
#define printk_alert(fmt, arg...) do_printk(fmt, ##arg)
#define printk_crit(fmt, arg...) do_printk(fmt, ##arg)
#define printk_err(fmt, arg...) do_printk(fmt, ##arg)
#define printk_warning(fmt, arg...) do_printk(fmt, ##arg)
#define printk_notice(fmt, arg...) do_printk(fmt, ##arg)
#define printk_info(fmt, arg...) do_printk(fmt, ##arg)
#define printk_debug(fmt, arg...)
#define printk_spew(fmt, arg...)
#endif
#endif

View File

@ -0,0 +1,362 @@
/*
* $Id: southbridge.c,v 1.18 2009/02/24 15:14:04 atic Exp $
*/
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include "../boot_io.h"
#include <asm/e2k_debug.h>
#include <asm/e2k.h>
#include <asm/timer.h>
#include <asm/sic_regs.h>
#include <asm/l_timer.h>
#include "pci_isa_config.h"
#include "ide_config.h"
#include "southbridge.h"
#include "mc146818rtc.h"
#include "pci.h"
#define DEBUG_IOSB 1
#define DebugSB if (DEBUG_IOSB) rom_printk
extern volatile unsigned long phys_node_pres_map;
extern int phys_node_num;
extern volatile unsigned long online_iohubs_map;
extern int online_iohubs_num;
extern volatile unsigned long possible_iohubs_map;
extern int possible_iohubs_num;
int SB_bus, SB_device;
#ifdef CONFIG_E2K_SIC
# define E2K_IO_APIC_AREA_PHYS_BASE 0x00000000fec00000UL
static void configure_iohub_apic(int domain)
{
struct bios_pci_dev *dev = NULL;
unsigned int ioapic_base, ioapic_upper32;
#ifndef CONFIG_BOOT_EPIC
unsigned int lapic_base, lapic_upper32;
#ifdef CONFIG_E2K_FULL_SIC
unsigned int sapic_base;
unsigned int sapic_upper32;
#endif /* CONFIG_E2K_FULL_SIC */
#endif
unsigned long tmp;
rom_printk("Scanning PCI domain %d bus for ioapic/pic/timer i2c/spi "
"controller ...", domain);
do {
dev = bios_pci_find_device(INTEL_MULTIFUNC_VENDOR,
INTEL_MULTIFUNC_DEVICE, dev);
if (dev) {
if (bios_pci_domain_nr(dev->bus) != domain)
continue;
rom_printk("found on domain %d bus %d device %d\n",
bios_pci_domain_nr(dev->bus), dev->bus->number,
PCI_SLOT(dev->devfn));
break;
}
} while (dev);
if (dev == NULL) {
do {
dev = bios_pci_find_device(PCI_VENDOR_ID_MCST_TMP,
PCI_DEVICE_ID_MCST_I2C_SPI, dev);
if (dev) {
if (bios_pci_domain_nr(dev->bus) != domain)
continue;
rom_printk("found on domain %d bus %d "
"device %d\n",
bios_pci_domain_nr(dev->bus),
dev->bus->number,
PCI_SLOT(dev->devfn));
break;
}
} while (dev);
if (dev == NULL) {
rom_printk("!!! NOT FOUND !!!\n");
return;
}
}
/* configure configuration space for ioapic on domain */
ioapic_base = E2K_IO_APIC_AREA_PHYS_BASE + domain * 0x1000;
DebugSB("configure_apic_system: --> to i2c & scrb (iohub)\n"
"ioapic_upper32 = 0x%x, ioapic_base = 0x%x\n",
0, ioapic_base);
pcibios_write_config_dword(domain, dev->bus->number, dev->devfn,
IOAPIC_BASE_ADDRESS, ioapic_base);
pcibios_write_config_dword(domain, dev->bus->number, dev->devfn,
IOAPIC_UPPER_ADDRESS, 0);
system_commutator_es2_ioh_write_dword(domain, dev->bus->number,
A2_BA0, ioapic_base);
system_commutator_es2_ioh_write_dword(domain, dev->bus->number,
A2_BUA0, 0);
/* LAPICINT and SAPICINT should not be written on EPIC systems */
#ifndef CONFIG_BOOT_EPIC
#ifdef CONFIG_E2K_FULL_SIC
/* configure configuration space for sapic on BSP */
#if defined(CONFIG_ES2)
tmp = ES2_SAPICINT_BASE + (domain * APICINT_SIZE);
#elif defined(CONFIG_E2S)
tmp = E2S_SAPICINT_BASE + (domain * APICINT_SIZE);
#elif defined(CONFIG_E8C) || defined(CONFIG_E8C2)
tmp = E8C_SAPICINT_BASE + (domain * (APICINT_SIZE));
#elif defined(CONFIG_E12C)
tmp = E12C_SAPICINT_BASE + (domain * (APICINT_SIZE));
#elif defined(CONFIG_E16C)
tmp = E16C_SAPICINT_BASE + (domain * (APICINT_SIZE));
#elif defined(CONFIG_E2C3)
tmp = E2C3_SAPICINT_BASE + (domain * (APICINT_SIZE));
#else
#error "Invalid e2k machine type"
#endif /* CONFIG_ES2 */
sapic_base = tmp & 0xffffffff;
sapic_upper32 = (tmp >> 32) & 0xffffffff;
DebugSB("configure_apic_system: --> to i2c & scrb (iohub)\n"
"sapic_message_upper32 = 0x%x, sapic_message_base = 0x%x\n",
sapic_upper32, sapic_base);
pcibios_write_config_dword(domain, dev->bus->number, dev->devfn,
MSI_TRANSACTION_ADDRESS, sapic_base);
pcibios_write_config_dword(domain, dev->bus->number, dev->devfn,
MSI_TRANSACTION_UPPER_ADDRESS, sapic_upper32);
system_commutator_es2_ioh_write_dword(domain, dev->bus->number, A2_BA1,
sapic_base);
system_commutator_es2_ioh_write_dword(domain, dev->bus->number, A2_BUA1,
sapic_upper32);
#endif /* CONFIG_E2K_FULL_SIC */
/* configure configuration space for lapic on BSP */
#if defined(CONFIG_ES2)
tmp = ES2_LAPICINT_BASE + (domain * APICINT_SIZE);
#elif defined(CONFIG_E2S)
tmp = E2S_LAPICINT_BASE + (domain * APICINT_SIZE);
#elif defined(CONFIG_E8C) || defined(CONFIG_E8C2)
tmp = E8C_LAPICINT_BASE + (domain * (APICINT_SIZE));
#elif defined(CONFIG_E1CP)
tmp = E1CP_LAPICINT_BASE + (domain * (APICINT_SIZE));
#elif defined(CONFIG_E12C)
tmp = E12C_LAPICINT_BASE + (domain * (APICINT_SIZE));
#elif defined(CONFIG_E16C)
tmp = E16C_LAPICINT_BASE + (domain * (APICINT_SIZE));
#elif defined(CONFIG_E2C3)
tmp = E2C3_LAPICINT_BASE + (domain * (APICINT_SIZE));
#else
#error "Invalid e2k machine type"
#endif /* CONFIG_ES2 */
lapic_base = tmp & 0xffffffff;
lapic_upper32 = (tmp >> 32) & 0xffffffff;
DebugSB("configure_apic_system: --> to i2c & scrb (iohub)\n"
"lapic_message_upper32 = 0x%x, lapic_message_base = 0x%x\n",
lapic_upper32, lapic_base);
#ifdef CONFIG_E2K_LEGACY_SIC
early_sic_write_node_nbsr_reg(0, SIC_rt_lapicintb, tmp >> 12);
DebugSB("configure_apic_system: NBSR lapicint base = 0x%x\n",
early_sic_read_node_nbsr_reg(0, SIC_rt_lapicintb));
#endif /* CONFIG_E2K_LEGACY_SIC */
pcibios_write_config_dword(domain, dev->bus->number, dev->devfn,
LAPIC_MESSAGE_BASE_ADDRESS, lapic_base);
pcibios_write_config_dword(domain, dev->bus->number, dev->devfn,
LAPIC_MESSAGE_UPPER_ADDRESS, lapic_upper32);
#endif
/* configure configuration space for ioapic on BSP */
#if defined(CONFIG_ES2)
tmp = ES2_IOAPICINT_BASE + (domain * APICINT_SIZE);
#elif defined(CONFIG_E2S)
tmp = E2S_IOAPICINT_BASE + (domain * APICINT_SIZE);
#elif defined(CONFIG_E8C) || defined(CONFIG_E8C2)
tmp = E8C_IOAPICINT_BASE + (domain * (APICINT_SIZE));
#elif defined(CONFIG_E1CP)
tmp = E1CP_IOAPICINT_BASE + (domain * (APICINT_SIZE));
#elif defined(CONFIG_E12C)
tmp = E12C_IOAPICINT_BASE + (domain * (APICINT_SIZE));
#elif defined(CONFIG_E16C)
tmp = E16C_IOAPICINT_BASE + (domain * (APICINT_SIZE));
#elif defined(CONFIG_E2C3)
tmp = E2C3_IOAPICINT_BASE + (domain * (APICINT_SIZE));
#else
#error "Invalid e2k machine type"
#endif /* CONFIG_ES2 */
ioapic_base = tmp & 0xffffffff;
ioapic_upper32 = (tmp >> 32) & 0xffffffff;
DebugSB("configure_apic_system: --> to i2c\n"
"ioapic_message_upper32 = 0x%x, ioapic_message_base = 0x%x\n",
ioapic_upper32, ioapic_base);
#ifdef CONFIG_E2K_LEGACY_SIC
early_sic_write_node_nbsr_reg(0, SIC_rt_ioapicintb, tmp >> 12);
DebugSB("configure_apic_system: NBSR ioapicint base = 0x%x\n",
early_sic_read_node_nbsr_reg(0, SIC_rt_ioapicintb));
#endif /* CONFIG_E2K_LEGACY_SIC */
system_commutator_es2_ioh_write_dword(domain, dev->bus->number,
A2_BA2, ioapic_base);
system_commutator_es2_ioh_write_dword(domain, dev->bus->number,
A2_BUA2, ioapic_upper32);
pcibios_write_config_dword(domain, dev->bus->number, dev->devfn,
IOAPIC_MESSAGE_BASE_ADDRESS, ioapic_base);
pcibios_write_config_dword(domain, dev->bus->number, dev->devfn,
IOAPIC_MESSAGE_UPPER_ADDRESS, ioapic_upper32);
}
#ifdef CONFIG_E2K_LEGACY_SIC
void configure_embeded_apic(void)
{
unsigned long ioapic_base;
unsigned int hb_cfg;
/* configure configuration space for ioapic: */
/* embeded IOAPIC always is #1 */
ioapic_base = E1CP_EMBEDED_IOAPIC_BASE;
early_writell_hb_reg(ioapic_base, HB_PCI_IOAPICBASE);
rom_printk("set embeded ioapic base to 0x%X\n",
early_readll_hb_reg(HB_PCI_IOAPICBASE));
/* enable embeded IOAPIC and IRQs at host bridge CFG */
hb_cfg = early_readl_hb_reg(HB_PCI_CFG);
DebugSB("configure_embeded_apic: host bridge CFG 0x%08x\n",
hb_cfg);
hb_cfg |= HB_CFG_InternalIoApicEnable;
hb_cfg |= (HB_CFG_MaskIntSic | HB_CFG_MaskIntWlcc |
HB_CFG_MaskIntIommu);
hb_cfg &= ~HB_CFG_ShareHostInterrupts;
early_writel_hb_reg(hb_cfg, HB_PCI_CFG);
rom_printk("host bridge CFG: enable embeded IOAPIC AND IRQs 0x%X\n",
early_readl_hb_reg(HB_PCI_CFG));
}
#endif /* CONFIG_E2K_LEGACY_SIC */
void configure_pic_system(void)
{
int domain;
for (domain = 0; domain < MAX_NUMIOHUBS; domain ++) {
if (!(online_iohubs_map & (1 << domain)))
continue;
configure_iohub_apic(domain);
}
#ifdef CONFIG_E2K_LEGACY_SIC
configure_embeded_apic();
#endif /* CONFIG_E2K_LEGACY_SIC */
}
#define ONEMEG (1 << 20)
/** round a number to an alignment.
* @param val the starting value
* @param roundup Alignment as a power of two
* @returns rounded up number
*/
extern unsigned long round(unsigned long val, unsigned long roundup);
static void configure_iohub_system_timer(int domain)
{
struct bios_pci_dev *dev;
unsigned int timer_base, timer_upper32;
wd_control_t wd_control;
unsigned long addr = 0;
DebugSB("start configure_system_timer\n");
rom_printk("Scanning PCI #%d bus for ioapic/pic/timer i2c/spi controller ...",
domain);
dev = bios_pci_find_device(INTEL_MULTIFUNC_VENDOR,
INTEL_MULTIFUNC_DEVICE, NULL);
if (dev == NULL) {
do {
dev = bios_pci_find_device(PCI_VENDOR_ID_MCST_TMP,
PCI_DEVICE_ID_MCST_I2C_SPI, dev);
if (dev) {
if (bios_pci_domain_nr(dev->bus) != domain)
continue;
rom_printk("found on domain %d bus %d "
"device %d\n",
bios_pci_domain_nr(dev->bus),
dev->bus->number,
PCI_SLOT(dev->devfn));
break;
}
} while (dev);
}
if (dev && bios_pci_domain_nr(dev->bus) == domain) {
rom_printk("found on bus %d device %d\n",
dev->bus->number, PCI_SLOT(dev->devfn));
} else {
rom_printk("!!! NOT FOUND !!!\n");
return;
}
/* configure configuration space for timer on BSP */
timer_base = round(pci_root[0].prefmemlimit, ONEMEG);
timer_upper32 = 0;
DebugSB("configure_system_timer:\n"
"timer_upper32 = 0x%x, timer_base = 0x%x\n",
timer_upper32, timer_base);
pcibios_write_config_dword(domain, dev->bus->number, dev->devfn,
SYSTEM_TIMER_BASE_ADDRESS, timer_base);
pcibios_write_config_dword(domain, dev->bus->number, dev->devfn,
SYSTEM_TIMER_UPPER_ADDRESS, timer_upper32);
system_commutator_es2_ioh_write_dword(domain, dev->bus->number,
A3_BA0, timer_base);
system_commutator_es2_ioh_write_dword(domain, dev->bus->number,
A3_BUA0, timer_upper32);
/* Disable WD timer */
AS_WORD(wd_control) = 0;
addr = timer_base + WD_CONTROL;
AS_WORD(wd_control) = NATIVE_READ_MAS_W(addr, MAS_IOADDR);
if (AS_STRUCT(wd_control).w_out_e){
DebugSB("configure_system_timer: wd timer found to be enabled.\n");
DebugSB("configure_system_timer: Set wd timer to disable mode\n");
AS_STRUCT(wd_control).w_out_e = 0;
AS_STRUCT(wd_control).w_m = 1; /* Interrupt mode */
NATIVE_WRITE_MAS_W(addr, AS_WORD(wd_control), MAS_IOADDR);
}
}
void configure_system_timer(void)
{
int domain;
for (domain = 0; domain < MAX_NUMIOHUBS; domain ++) {
if (!(online_iohubs_map & (1 << domain)))
continue;
configure_iohub_system_timer(domain);
}
}
#endif
void sb_enable_rtc(void)
{
int xdata;
rom_printk("southbridge enable rtc ...\n");
xdata = SB_read_config32(SB_GENCFG, 0);
xdata |= SB_GENCFG_SIGNAL_PIN_SELECTED14;
SB_write_config32(xdata, SB_GENCFG, 0);
DebugSB("GENCFG = 0x%x\n",
SB_read_config32(SB_GENCFG, 0));
rtc_init(0);
}
void sb_enable_ide(void)
{
int xdata;
rom_printk("southbridge enable ide ...\n");
xdata = SB_read_config32(SB_IDETIM, 1);
xdata |= ((SB_IDETIM_DECODE_ENABLE << SB_IDETIM_SHIFT) |
SB_IDETIM_DECODE_ENABLE);
SB_write_config32(xdata, SB_IDETIM, 1);
DebugSB("IDETIM = 0x%x\n",
SB_read_config32(SB_IDETIM, 1));
xdata = SB_read_config16(SB_PCICMD, 1);
xdata |= SB_PCICMD_IOSE;
SB_write_config32(xdata, SB_PCICMD, 1);
DebugSB("PCICMD = 0x%x\n",
SB_read_config16(SB_PCICMD, 1) & 0xffff);
}

View File

@ -0,0 +1,158 @@
/* PIIX4 southbridge configuration registers */
#ifndef _SOUTHBRIDGE_H_
#define _SOUTHBRIDGE_H_
#include <asm/head.h>
#include <asm/mas.h>
#include <asm/e2k_api.h>
#include "../boot_io.h"
extern int SB_bus, SB_device, SB_function;
#if 0
#define PCI_BUS 0
#define PHYS_DEV 7
#else
#define PCI_BUS SB_bus
#define PHYS_DEV SB_device
#endif
/* Nothbridge addr i/o ports 0xcf8 - 0xcfb */
#define SB_IO_ADDR_BASE 0x0CF8
#define SB_IO_ADDR_PORT0 0x0CF8
#define SB_IO_ADDR_PORT1 0x0CF9
#define SB_IO_ADDR_PORT2 0x0CFA
#define SB_IO_ADDR_PORT3 0x0CFB
/* Nothbridge data i/o ports 0xcfc - 0xcff */
#define SB_IO_DATA_BASE 0x0CFC
#define SB_IO_DATA_PORT0 0x0CFC
#define SB_IO_DATA_PORT1 0x0CFD
#define SB_IO_DATA_PORT2 0x0CFE
#define SB_IO_DATA_PORT3 0x0CFF
#define pci_cfg_xaddr(bus,physdev,fun,byte) \
((byte&~3)|(fun<<8)|(physdev<<11)|(bus<<16)|(1<<31))
#define data_port PHYS_X86_IO_BASE + SB_IO_DATA_BASE
#define addr_port PHYS_X86_IO_BASE + SB_IO_ADDR_BASE
static inline unsigned int SB_read_config(int reg, int func, int size)
{
unsigned int xaddr;
int mask = reg & 0x3;
int rval = 0;
int cnt = 0;
xaddr = pci_cfg_xaddr(PCI_BUS, PHYS_DEV, func, reg);
NATIVE_WRITE_MAS_W(addr_port, xaddr, MAS_IOADDR);
while (mask) {
rval |= (NATIVE_READ_MAS_B(data_port + mask,
MAS_IOADDR) << (cnt * 8));
if (!--size)
break;
++mask;
++cnt;
if (mask == 4) {
xaddr = pci_cfg_xaddr(PCI_BUS, PHYS_DEV,
func, (reg + 4));
NATIVE_WRITE_MAS_W(addr_port, xaddr, MAS_IOADDR);
mask = 0;
break;
}
}
while (size & (reg & 0x3)) {
rval |= (NATIVE_READ_MAS_B(data_port + mask,
MAS_IOADDR) << (cnt * 8));
if (!--size)
break;
++mask;
++cnt;
}
switch (size) {
case 0:
break;
case 1:
rval = NATIVE_READ_MAS_B(data_port, MAS_IOADDR);
break;
case 2:
rval = NATIVE_READ_MAS_H(data_port, MAS_IOADDR);
break;
case 4:
rval = NATIVE_READ_MAS_W(data_port, MAS_IOADDR);
break;
default:
break;
}
return rval;
}
#define SB_read_config8(reg, func) \
((char)SB_read_config(reg, func, sizeof(char)))
#define SB_read_config16(reg, func) \
((short)SB_read_config(reg, func, sizeof(short)))
#define SB_read_config32(reg, func) \
((int)SB_read_config(reg, func, sizeof(int)))
static inline void SB_write_config(int xdata, int reg, int func, int size)
{
unsigned int xaddr;
int mask = reg & 0x3;
int data;
int cnt = 0;
xaddr = pci_cfg_xaddr(PCI_BUS, PHYS_DEV, func, reg);
NATIVE_WRITE_MAS_W(addr_port, xaddr, MAS_IOADDR);
while (mask) {
data = xdata >> (8 * cnt);
NATIVE_WRITE_MAS_B(data_port + mask, data, MAS_IOADDR);
if (!--size)
break;
++mask;
++cnt;
if (mask == 4) {
xaddr = pci_cfg_xaddr(PCI_BUS, PHYS_DEV,
func, (reg + 4));
NATIVE_WRITE_MAS_W(addr_port, xaddr, MAS_IOADDR);
mask = 0;
break;
}
}
while (size & (reg & 0x3)) {
data = xdata >> (8 * cnt);
NATIVE_WRITE_MAS_B(data_port + mask, data, MAS_IOADDR);
if (!--size)
break;
++mask;
++cnt;
}
switch (size) {
case 0:
break;
case 1:
NATIVE_WRITE_MAS_B(data_port, xdata, MAS_IOADDR);
break;
case 2:
NATIVE_WRITE_MAS_H(data_port, xdata, MAS_IOADDR);
break;
case 4:
NATIVE_WRITE_MAS_W(data_port, xdata, MAS_IOADDR);
break;
default:
break;
}
}
#define SB_write_config8(xdata, reg, func) \
SB_write_config(xdata, reg, func, sizeof(char))
#define SB_write_config16(xdata, reg, func) \
SB_write_config(xdata, reg, func, sizeof(short))
#define SB_write_config32(xdata, reg, func) \
SB_write_config(xdata, reg, func, sizeof(int))
#endif /* _SOUTHBRIDGE_H_ */

View File

@ -0,0 +1,197 @@
#include <asm/mas.h>
#include "bios.h"
#include "mc146818rtc.h"
#include "../boot_io.h"
/* Control */
#define UART_IER 0x01
#define UART_IIR 0x02
#define UART_FCR 0x02
#define UART_LCR 0x03
#define UART_MCR 0x04
#define UART_DLL 0x00
#define UART_DLM 0x01
/* Status */
#define UART_LSR 0x05
#define UART_MSR 0x06
#define UART_SCR 0x07
#define UART_LCS 0x3
#define BASE_BAUD1 ( 1280000 / 16 )
static int set_irq = 0;
void set_irq_pin(void);
void write_sio(int index,int data)
{
bios_outb(index, 0x3f0);
bios_outb(data, 0x3f1);
}
unsigned char read_sio(int index)
{
bios_outb(index, 0x3f0);
return bios_inb(0x3f1);
}
inline void uart_init (unsigned base_port)
{
int divisor = BASE_BAUD1;
/* enable interrupts */
bios_outb(0x7, base_port + UART_IER);
/* enable fifo's */
bios_outb(0x01, base_port + UART_FCR);
bios_outb(0x80 | UART_LCS, base_port + UART_LCR);
bios_outb(divisor & 0xFF, base_port + UART_DLL);
bios_outb((divisor >> 8) & 0xFF, base_port + UART_DLM);
bios_outb(UART_LCS, base_port + UART_LCR);
}
void enable_parallel_port(void)
{
unsigned char byte;
rom_printk("enable superio parallel port ...\n");
bios_outb(0x55, 0x3f0);
// [0]-FDC,[4]COM1,[5]COM2,[3]LPT
byte = read_sio(0x22);
byte |= (1 << 3);
write_sio(0x22, byte); // lpt power on
write_sio(0x7, 0x3);
write_sio(0x30, 0);
write_sio(0x60, 0x3);
write_sio(0x61, 0x78);
write_sio(0x70, 0x7);
write_sio(0x74, 0x4); // no dma
write_sio(0xf0, 0x3c); // default
write_sio(0xf1, 0x00); // default
write_sio(0x30, 0x1);
bios_outb(0xAA, 0x3f0);
if (!set_irq) set_irq_pin();
set_irq = 1;
hardware.parallel = 1;
}
void enable_rtc(void)
{
rom_printk("enable superio rtc ...\n");
bios_outb(0x55, 0x3f0);
write_sio(0x7, 0x6);
write_sio(0x30, 0);
write_sio(0x70, 0x8);
write_sio(0x30, 0x1);
bios_outb(0xAA, 0x3f0);
if (!set_irq) set_irq_pin();
set_irq = 1;
hardware.rtc = 1;
}
void enable_keyboard(void)
{
rom_printk("enable superio keyboard ...\n");
bios_outb(0x55, 0x3f0);
write_sio(0x7, 0x7);
write_sio(0x30, 0);
write_sio(0x70, 0x1);
write_sio(0xf0, 0x3);
write_sio(0x30, 0x1);
bios_outb(0xAA, 0x3f0);
if (!set_irq) set_irq_pin();
set_irq = 1;
init_kbd();
hardware.keyboard = 1;
}
void enable_mouse(void)
{
rom_printk("enable superio mouse ...\n");
bios_outb(0x55, 0x3f0);
write_sio(0x7, 0x7);
write_sio(0x30, 0);
write_sio(0x72, 0xc);
write_sio(0xf0, 0x3);
write_sio(0x30, 0x1);
bios_outb(0xAA, 0x3f0);
if (!set_irq) set_irq_pin();
set_irq = 1;
hardware.mouse = 1;
}
void enable_floppy(void)
{
unsigned char byte;
rom_printk("enable superio fdc ...\n");
bios_outb(0x55, 0x3f0);
byte = read_sio(0x22);
byte |= (1 << 0);
write_sio(0x22, byte); // fdc power on
write_sio(0x7, 0x0);
write_sio(0x30, 0); // disable fdc
write_sio(0x70, 0x06); // irq
write_sio(0x30, 0x1); // enable fdc
bios_outb(0xAA, 0x3f0);
if (!set_irq) set_irq_pin();
set_irq = 1;
/* 0x10 CMOS fd drive type (2 nibbles: high=fd0, low=fd1)
* values:
* 1: 360K 5.25"
* 2: 1.2MB 5.25"
* 3: 720K 3.5"
* 4: 1.44MB 3.5"
* 5: 2.88MB 3.5"
*/
if (!CMOS_READ(0x10))
CMOS_WRITE(0x40, 0x10);
hardware.floppy = 1;
}
void set_irq_pin(void)
{
bios_outb(0x55, 0x3f0);
write_sio(0x07, 0x08);
write_sio(0x30, 0x00);
write_sio(0xc0, 0x03);
write_sio(0xcc, (1<<3)); // irq12
write_sio(0xd0, (1<<3)); // irq1
write_sio(0xd1, (1<<3)); // irq3
write_sio(0xd2, (1<<3)); // irq4
write_sio(0xd3, (1<<3)); // irq5
write_sio(0xd4, (1<<3)); // irq6
write_sio(0xd5, (1<<3)); // irq7
write_sio(0x30, 0x01);
bios_outb(0xAA, 0x3f0);
}

View File

@ -0,0 +1,9 @@
KBUILD_CFLAGS += -I$(obj)/.. -I$(obj)/x86emu/include -DIN_MODULE
obj-y := int10.o int15.o int16.o int1a.o \
inte6.o init.o helper_exec.o helper_mem.o \
pci-iface.o
obj-y += x86emu/src/x86emu/

View File

@ -0,0 +1,269 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/helper_exec.c,v 1.16 2001/04/30 14:34:57 tsi Exp $ */
/*
* XFree86 int10 module
* execute BIOS int 10h calls in x86 real mode environment
* Copyright 1999 Egbert Eich
*
* Part of this is based on code taken from DOSEMU
* (C) Copyright 1992, ..., 1999 the "DOSEMU-Development-Team"
*/
/*
* To debug port accesses define PRINT_PORT.
* Note! You also have to comment out ioperm()
* in xf86EnableIO(). Otherwise we won't trap
* on PIO.
*/
#include <x86emu.h>
#include "init.h"
#include "printk.h"
#include "pci.h"
int port_rep_inb(u16 port, u32 base, int d_f, u32 count);
u8 x_inb(u16 port);
u16 x_inw(u16 port);
void x_outb(u16 port, u8 val);
void x_outw(u16 port, u16 val);
u32 x_inl(u16 port);
void x_outl(u16 port, u32 val);
/* general software interrupt handler */
u32 getIntVect(int num)
{
return MEM_RW(num << 2) + (MEM_RW((num << 2) + 2) << 4);
}
void pushw(u16 val)
{
X86_ESP -= 2;
MEM_WW(((u32) X86_SS << 4) + X86_SP, val);
}
int run_bios_int(int num)
{
u32 eflags;
eflags = X86_EFLAGS;
pushw(eflags);
pushw(X86_CS);
pushw(X86_IP);
X86_CS = MEM_RW((num << 2) + 2);
X86_IP = MEM_RW(num << 2);
// printf("%s: INT %x CS:IP = %x:%x\n", __FUNCTION__,
// num, MEM_RW((num << 2) + 2), MEM_RW(num << 2));
return 1;
}
int port_rep_inb(u16 port, u32 base, int d_f, u32 count)
{
register int inc = d_f ? -1 : 1;
u32 dst = base;
while (count--) {
MEM_WB(dst, x_inb(port));
dst += inc;
}
return dst - base;
}
int port_rep_inw(u16 port, u32 base, int d_f, u32 count)
{
register int inc = d_f ? -2 : 2;
u32 dst = base;
while (count--) {
MEM_WW(dst, x_inw(port));
dst += inc;
}
return dst - base;
}
int port_rep_inl(u16 port, u32 base, int d_f, u32 count)
{
register int inc = d_f ? -4 : 4;
u32 dst = base;
while (count--) {
MEM_WL(dst, x_inl(port));
dst += inc;
}
return dst - base;
}
int port_rep_outb(u16 port, u32 base, int d_f, u32 count)
{
register int inc = d_f ? -1 : 1;
u32 dst = base;
while (count--) {
x_outb(port, MEM_RB(dst));
dst += inc;
}
return dst - base;
}
int port_rep_outw(u16 port, u32 base, int d_f, u32 count)
{
register int inc = d_f ? -2 : 2;
u32 dst = base;
while (count--) {
x_outw(port, MEM_RW(dst));
dst += inc;
}
return dst - base;
}
int port_rep_outl(u16 port, u32 base, int d_f, u32 count)
{
register int inc = d_f ? -4 : 4;
u32 dst = base;
while (count--) {
x_outl(port, MEM_RL(dst));
dst += inc;
}
return dst - base;
}
u8 x_inb(u16 port)
{
u8 val;
val = bios_inb(port);
// printf("%x inb(0x%04x) = 0x%02x\n", X86_IP, port, val);
return val;
}
u16 x_inw(u16 port)
{
u16 val;
val = bios_inw(port);
// printf("%x inw(0x%04x) = 0x%04x\n", X86_IP, port, val);
return val;
}
u32 x_inl(u16 port)
{
u32 val;
val = bios_inl(port);
// printf("%x inl(0x%04x) = 0x%08x\n", X86_IP, port, val);
return val;
}
void x_outb(u16 port, u8 val)
{
// printf("%x outb(0x%02x, 0x%04x)\n", X86_IP, val, port);
bios_outb(val, port);
}
void x_outw(u16 port, u16 val)
{
// printf("%x outw(0x%04x, 0x%04x)\n", X86_IP, val, port);
bios_outw(val, port);
}
void x_outl(u16 port, u32 val)
{
// printf("%x outl(0x%08x, 0x%04x)\n", X86_IP, val, port);
bios_outl(val, port);
}
u8 Mem_rb(int addr)
{
return (*currentp->mem->rb) (currentp, addr);
}
u16 Mem_rw(int addr)
{
return (*currentp->mem->rw) (currentp, addr);
}
u32 Mem_rl(int addr)
{
return (*currentp->mem->rl) (currentp, addr);
}
void Mem_wb(int addr, u8 val)
{
(*currentp->mem->wb) (currentp, addr, val);
}
void Mem_ww(int addr, u16 val)
{
(*currentp->mem->ww) (currentp, addr, val);
}
void Mem_wl(int addr, u32 val)
{
(*currentp->mem->wl) (currentp, addr, val);
}
#if 0
void getsecs(unsigned long *sec, unsigned long *usec)
{
struct timeval tv;
gettimeofday(&tv, 0);
*sec = tv.tv_sec;
*usec = tv.tv_usec;
}
#endif
#define TAG(Cfg1Addr) (Cfg1Addr & 0xffff00)
#define OFFSET(Cfg1Addr) (Cfg1Addr & 0xff)
u8 bios_checksum(u8 * start, int size)
{
u8 sum = 0;
while (size-- > 0)
sum += *start++;
return sum;
}
/*
* Lock/Unlock legacy VGA. Some Bioses try to be very clever and make
* an attempt to detect a legacy ISA card. If they find one they might
* act very strange: for example they might configure the card as a
* monochrome card. This might cause some drivers to choke.
* To avoid this we attempt legacy VGA by writing to all know VGA
* disable registers before we call the BIOS initialization and
* restore the original values afterwards. In beween we hold our
* breath. To get to a (possibly exising) ISA card need to disable
* our currentp PCI card.
*/
/*
* This is just for booting: we just want to catch pure
* legacy vga therefore we don't worry about mmio etc.
* This stuff should really go into vgaHW.c. However then
* the driver would have to load the vga-module prior to
* doing int10.
*/
/*void
LockLegacyVGA(int screenIndex,legacyVGAPtr vga)
{
xf86SetCurrentAccess(FALSE, xf86Screens[screenIndex]);
vga->save_msr = inb(0x3CC);
vga->save_vse = inb(0x3C3);
vga->save_46e8 = inb(0x46e8);
vga->save_pos102 = inb(0x102);
outb(0x3C2, ~(u8)0x03 & vga->save_msr);
outb(0x3C3, ~(u8)0x01 & vga->save_vse);
outb(0x46e8, ~(u8)0x08 & vga->save_46e8);
outb(0x102, ~(u8)0x01 & vga->save_pos102);
xf86SetCurrentAccess(TRUE, xf86Screens[screenIndex]);
}
void
UnlockLegacyVGA(int screenIndex, legacyVGAPtr vga)
{
xf86SetCurrentAccess(FALSE, xf86Screens[screenIndex]);
outb(0x102, vga->save_pos102);
outb(0x46e8, vga->save_46e8);
outb(0x3C3, vga->save_vse);
outb(0x3C2, vga->save_msr);
xf86SetCurrentAccess(TRUE, xf86Screens[screenIndex]);
}
*/

View File

@ -0,0 +1,326 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/helper_mem.c,v 1.21 2001/05/22 16:24:37 tsi Exp $ */
/*
* XFree86 int10 module
* execute BIOS int 10h calls in x86 real mode environment
* Copyright 1999 Egbert Eich
*/
#include "init.h"
#define _INT10_PRIVATE
#define SYS_BIOS 0xF0000
#define REG pInt
#if 0
typedef enum {
OPT_NOINT10,
OPT_INIT_PRIMARY,
OPT_BIOS_LOCATION
} INT10Opts;
static const OptionInfoRec INT10Options[] = {
{OPT_NOINT10, "NoINT10", OPTV_BOOLEAN, {0}, FALSE},
{OPT_INIT_PRIMARY, "InitPrimary", OPTV_BOOLEAN, {0}, FALSE},
{OPT_BIOS_LOCATION, "BiosLocation", OPTV_STRING, {0}, FALSE},
{-1, NULL, OPTV_NONE, {0}, FALSE},
};
#endif
void reset_int_vect(void);
#ifdef DEBUG
void dprint(unsigned long start, unsigned long size)
{
int i, j;
char *c = (char *) start;
for (j = 0; j < (size >> 4); j++) {
char *d = c;
printf("\n0x%lx: ", (unsigned long) c);
for (i = 0; i < 16; i++)
printf("%2.2x ", (unsigned char) (*(c++)));
c = d;
for (i = 0; i < 16; i++) {
printf("%c", ((((u8) (*c)) > 32) && (((u8) (*c)) < 128)) ?
(unsigned char) (*(c)) : '.');
c++;
}
}
printf("\n");
}
#endif /* DEBUG */
#if 1
#ifndef _PC
/*
* here we are really paranoid about faking a "real"
* BIOS. Most of this information was pulled from
* dosemu.
*/
void setup_int_vect(void)
{
int i;
/* let the int vects point to the SYS_BIOS seg */
for (i = 0; i < 0x80; i++) {
MEM_WW(i << 2, 0);
MEM_WW((i << 2) + 2, SYS_BIOS >> 4);
}
reset_int_vect();
/* font tables default location (int 1F) */
MEM_WW(0x1f << 2, 0xfa6e);
/* int 11 default location (Get Equipment Configuration) */
MEM_WW(0x11 << 2, 0xf84d);
/* int 12 default location (Get Conventional Memory Size) */
MEM_WW(0x12 << 2, 0xf841);
/* int 15 default location (I/O System Extensions) */
MEM_WW(0x15 << 2, 0xf859);
/* int 1A default location (RTC, PCI and others) */
MEM_WW(0x1a << 2, 0xff6e);
/* int 05 default location (Bound Exceeded) */
MEM_WW(0x05 << 2, 0xff54);
/* int 08 default location (Double Fault) */
MEM_WW(0x08 << 2, 0xfea5);
/* int 13 default location (Disk) */
MEM_WW(0x13 << 2, 0xec59);
/* int 0E default location (Page Fault) */
MEM_WW(0x0e << 2, 0xef57);
/* int 17 default location (Parallel Port) */
MEM_WW(0x17 << 2, 0xefd2);
/* fdd table default location (int 1e) */
MEM_WW(0x1e << 2, 0xefc7);
/* Set Equipment flag to VGA */
i = MEM_RB(0x0410) & 0xCF;
MEM_WB(0x0410, i);
/* XXX Perhaps setup more of the BDA here. See also int42(0x00). */
}
#endif
#if 0
int setup_system_bios(void *base_addr)
{
char *base = (char *) base_addr;
/*
* we trap the "industry standard entry points" to the BIOS
* and all other locations by filling them with "hlt"
* TODO: implement hlt-handler for these
*/
memset(base, 0xf4, 0x10000);
/* set bios date */
strcpy(base + 0x0FFF5, "06/11/99");
/* set up eisa ident string */
strcpy(base + 0x0FFD9, "PCI_ISA");
/* write system model id for IBM-AT */
*((unsigned char *) (base + 0x0FFFE)) = 0xfc;
return 1;
}
#endif
void reset_int_vect(void)
{
/*
* This table is normally located at 0xF000:0xF0A4. However, int 0x42,
* function 0 (Mode Set) expects it (or a copy) somewhere in the bottom
* 64kB. Note that because this data doesn't survive POST, int 0x42 should
* only be used during EGA/VGA BIOS initialisation.
*/
static const unsigned char VideoParms[] = {
/* Timing for modes 0x00 & 0x01 */
0x38, 0x28, 0x2d, 0x0a, 0x1f, 0x06, 0x19, 0x1c,
0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
/* Timing for modes 0x02 & 0x03 */
0x71, 0x50, 0x5a, 0x0a, 0x1f, 0x06, 0x19, 0x1c,
0x02, 0x07, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
/* Timing for modes 0x04, 0x05 & 0x06 */
0x38, 0x28, 0x2d, 0x0a, 0x7f, 0x06, 0x64, 0x70,
0x02, 0x01, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00,
/* Timing for mode 0x07 */
0x61, 0x50, 0x52, 0x0f, 0x19, 0x06, 0x19, 0x19,
0x02, 0x0d, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00,
/* Display page lengths in little endian order */
0x00, 0x08, /* Modes 0x00 and 0x01 */
0x00, 0x10, /* Modes 0x02 and 0x03 */
0x00, 0x40, /* Modes 0x04 and 0x05 */
0x00, 0x40, /* Modes 0x06 and 0x07 */
/* Number of columns for each mode */
40, 40, 80, 80, 40, 40, 80, 80,
/* CGA Mode register value for each mode */
0x2c, 0x28, 0x2d, 0x29, 0x2a, 0x2e, 0x1e, 0x29,
/* Padding */
0x00, 0x00, 0x00, 0x00
};
int i;
for (i = 0; i < sizeof(VideoParms); i++)
MEM_WB(i + (0x1000 - sizeof(VideoParms)), VideoParms[i]);
MEM_WW(0x1d << 2, 0x1000 - sizeof(VideoParms));
MEM_WW((0x1d << 2) + 2, 0);
// rom_printk("SETUP INT\n");
MEM_WW(0x10 << 2, 0xf065);
MEM_WW((0x10 << 2) + 2, SYS_BIOS >> 4);
MEM_WW(0x42 << 2, 0xf065);
MEM_WW((0x42 << 2) + 2, SYS_BIOS >> 4);
MEM_WW(0x6D << 2, 0xf065);
MEM_WW((0x6D << 2) + 2, SYS_BIOS >> 4);
}
#endif
#if 0
void set_return_trap(void)
{
/*
* Here we set the exit condition: We return when we encounter
* 'hlt' (=0xf4), which we locate at address 0x600 in x86 memory.
*/
MEM_WB(0x0600, 0xf4);
/*
* Allocate a segment for the stack
*/
xf86Int10AllocPages(1, current->stackseg);
}
void *xf86HandleInt10Options(ScrnInfoPtr pScrn, int entityIndex)
{
EntityInfoPtr pEnt = xf86GetEntityInfo(entityIndex);
OptionInfoPtr options = NULL;
if (pEnt->device) {
pointer configOptions = NULL;
/* Check if xf86CollectOptions() has already been called */
if (((pEnt->index < 0) ||
!xf86Screens[pEnt->index] ||
!(configOptions = xf86Screens[pEnt->index]->options)) &&
pEnt->device)
configOptions = pEnt->device->options;
if (configOptions) {
if (!(options = (OptionInfoPtr) xalloc(sizeof(INT10Options))))
return NULL;
(void) memcpy(options, INT10Options, sizeof(INT10Options));
xf86ProcessOptions(pScrn->scrnIndex, configOptions, options);
}
}
xfree(pEnt);
return options;
}
Bool int10skip(void *options)
{
Bool noint10 = FALSE;
if (!options)
return FALSE;
xf86GetOptValBool(options, OPT_NOINT10, &noint10);
return noint10;
}
Bool int10_check_bios(int scrnIndex, int codeSeg, unsigned char *vbiosMem)
{
int size;
if ((codeSeg & 0x1f) || /* Not 512-byte aligned otherwise */
((codeSeg << 4) < V_BIOS) || ((codeSeg << 4) >= SYS_SIZE))
return FALSE;
if (xf86IsPc98())
return FALSE;
if ((*vbiosMem != 0x55) || (*(vbiosMem + 1) != 0xAA) || !*(vbiosMem + 2))
return FALSE;
size = *(vbiosMem + 2) * 512;
if ((size + (codeSeg << 4)) > SYS_SIZE)
return FALSE;
if (bios_checksum(vbiosMem, size))
xf86DrvMsg(scrnIndex, X_WARNING, "Bad V_BIOS checksum\n");
return TRUE;
}
Bool initPrimary(void *options)
{
Bool initPrimary = FALSE;
if (!options)
return FALSE;
xf86GetOptValBool(options, OPT_INIT_PRIMARY, &initPrimary);
return initPrimary;
}
void xf86int10ParseBiosLocation(void *options, xf86int10BiosLocationPtr bios)
{
char *s;
char *p;
char *str = NULL;
if (options)
str = xf86GetOptValString(options, OPT_BIOS_LOCATION);
bios->bus = BUS_NONE;
if (!str)
return;
s = xstrdup(str);
p = strtok(s, ":");
if (xf86NameCmp(p, "pci"))
bios->bus = BUS_PCI;
else if (xf86NameCmp(p, "primary"))
bios->bus = BUS_ISA;
xfree(s);
if (bios->bus == BUS_NONE)
return;
s = xstrdup(str);
p = strchr(s, ':');
switch (bios->bus) {
case BUS_ISA:
if (p)
bios->location.legacy = atoi(++p);
else
bios->location.legacy = 0;
break;
case BUS_PCI:
if (p) {
bios->location.pci.bus = atoi(++p);
if ((p = strchr(p, ':'))) {
bios->location.pci.dev = atoi(++p);
if ((p = strchr(p, ':'))) {
bios->location.pci.func = atoi(++p);
break;
}
}
}
/* fall through */
bios->bus = BUS_NONE;
break;
default:
break;
}
xfree(s);
}
#endif

View File

@ -0,0 +1,592 @@
#include <x86emu.h>
#include "init.h"
#include "printk.h"
#include <linux/pci_ids.h>
#include "pci-iface.h"
#include "bios.h"
#define die(x) { rom_printk(x); }
#define warn(x) { rom_printk(x); }
#define DEBUG_VIDEO 0
#define DebugV(fmt, args...) \
({ if (DEBUG_VIDEO) \
rom_printk(fmt, ##args); })
void x86emu_dump_xregs(void);
int int15_handler(void);
int int16_handler(void);
int int1A_handler(void);
#ifndef _PC
int int42_handler(void);
#endif
int intE6_handler(void);
void setup_int_vect(void);
int run_bios_int(int num);
u32 getIntVect(int num);
void pushw(u16 val);
_ptr p;
ptr currentp = 0;
unsigned char biosmem[1024 * 1024];
int verbose = 1;
/* Interrupt multiplexer */
void do_int(int num)
{
int ret = 0;
// rom_printk("int%x vector at %x\n", num, getIntVect(num));
/* This is a pInt leftover */
currentp->num = num;
switch (num) {
#ifndef _PC
case 0x10:
case 0x42:
case 0x6D:
if (getIntVect(num) == 0xFF065) {
ret = int42_handler();
}
break;
#endif
case 0x15:
ret = int15_handler();
break;
case 0x16:
ret = int16_handler();
break;
case 0x1A:
ret = int1A_handler();
break;
case 0xe6:
ret = intE6_handler();
break;
default:
break;
}
if (!ret)
ret = run_bios_int(num);
if (!ret) {
rom_printk("\nint%x: not implemented\n", num);
//x86emu_dump_xregs();
}
}
static void x_outb(u16 port, u8 val)
{
bios_outb(val, port);
}
static void x_outw(u16 port, u16 val)
{
bios_outw(val, port);
}
static void x_outl(u16 port, u32 val)
{
bios_outl(val, port);
}
X86EMU_pioFuncs myfuncs = {
bios_inb, bios_inw, bios_inl,
x_outb, x_outw, x_outl
};
void X86EMU_setMemBase(void *base, unsigned int size);
void X86EMU_setabseg(void *abseg);
void x86emu_dump_xregs(void);
int X86EMU_set_debug(int debug);
X86EMU_intrFuncs intFuncs[256];
int pci_video_bios_init(struct bios_pci_dev *dev)
{
void *abseg = 0;
int i;
unsigned char *cp;
unsigned int size = 0;
int base = 0;
unsigned short initialip = 0, initialcs = 0, devfn = 0;
char *date = "01/01/99";
#ifdef DEBUG
int debugflag = 0;
int trace = 0;
#endif
// size = 64 * 1024;
size = dev->rom_size;
base = 0xc0000;
initialcs = 0xc000;
initialip = 0x0003;
// rom_printk("Point 1 int%x vector at %x\n", 0x42, getIntVect(0x42));
abseg = (void *) 0xa0000;
currentp = &p;
X86EMU_setMemBase(biosmem, sizeof(biosmem));
X86EMU_setabseg(abseg);
X86EMU_setupPioFuncs(&myfuncs);
/* Setting up interrupt environment.
* basically this means initializing PCI and
* intXX handlers.
*/
pciInit();
setup_int_vect();
for (i = 0; i < 256; i++)
intFuncs[i] = do_int;
X86EMU_setupIntrFuncs(intFuncs);
cp = (unsigned char *) dev->rom_address ;
devfn = (PCI_SLOT(dev->devfn) << 3) |
PCI_FUNC(dev->devfn);
currentp->ax = devfn ? devfn : 0xff;
currentp->dx = 0x80;
for (i = 0; i < size; i++) {
wrb(base + i, cp[i]);
}
/* Put a date into ROM */
for (i = 0; date[i]; i++)
wrb(0xffff5 + i, date[i]);
wrb(0xffff7, '/');
wrb(0xffffa, '/');
/* cpu setup */
X86_AX = devfn ? devfn : 0xff;
X86_DX = 0x80;
X86_EIP = initialip;
X86_CS = initialcs;
/* Initialize stack and data segment */
X86_SS = 0x0030;
X86_DS = 0x0040;
X86_SP = 0xfffe;
/* We need a sane way to return from bios
* execution. A hlt instruction and a pointer
* to it, both kept on the stack, will do.
*/
pushw(0xf4f4); /* hlt; hlt */
pushw(X86_SS);
pushw(X86_SP + 2);
X86_ES = 0x0000;
#ifdef DEBUG
if (trace) {
rom_printk("Switching to single step mode.\n");
X86EMU_trace_on();
}
#endif
#if 0
debugflag = DEBUG_MEM_TRACE_F |
DEBUG_DECODE_F | DEBUG_DISASSEMBLE_F |
DEBUG_TRACE_F |
DEBUG_SYSINT_F;
#endif
#ifdef DEBUG
// debugflag = 0x00ffffff;
if (debugflag) {
X86EMU_set_debug(debugflag);
}
#endif
X86EMU_exec();
/* Cleaning up */
pciExit();
return 0;
}
/* VGA index register ports */
#define GRA_I 0x3CE /* Graphics Controller Index */
#define SEQ_I 0x3C4 /* Sequencer Index */
/* VGA data register ports */
#define GRA_D 0x3CF /* Graphics Controller Data Register */
#define SEQ_D 0x3C5 /* Sequencer Data Register */
#define CRT_IC 0x3D4 /* CRT Controller Index - color emulation */
#define CRT_DC 0x3D5 /* CRT Controller Data Register - color emulation */
#define IS1_RC 0x3DA /* Input Status Register 1 - color emulation */
#define ATT_IW 0x3C0 /* Attribute Controller Index & Data Write Register */
#define ATT_R 0x3C1 /* Attribute Controller Data Read Register */
#define ATC_MODE 0x10
#define ATC_COLOR_PAGE 0x14
#define CRTC_H_TOTAL 0
#define CRTC_H_DISP 1
#define CRTC_H_BLANK_START 2
#define CRTC_H_BLANK_END 3
#define CRTC_H_SYNC_START 4
#define CRTC_H_SYNC_END 5
#define CRTC_V_TOTAL 6
#define CRTC_OVERFLOW 7
#define CRTC_PRESET_ROW 8
#define CRTC_MAX_SCAN 9
#define CRTC_CURSOR_START 0x0A
#define CRTC_CURSOR_END 0x0B
#define CRTC_START_HI 0x0C
#define CRTC_START_LO 0x0D
#define CRTC_CURSOR_HI 0x0E
#define CRTC_CURSOR_LO 0x0F
#define CRTC_V_SYNC_START 0x10
#define CRTC_V_SYNC_END 0x11
#define CRTC_V_DISP_END 0x12
#define CRTC_OFFSET 0x13
#define CRTC_UNDERLINE 0x14
#define CRTC_V_BLANK_START 0x15
#define CRTC_V_BLANK_END 0x16
#define CRTC_MODE 0x17
#define CRTC_LINE_COMPARE 0x18
// macros for writing to vga regs
#define write_seq(data, addr) \
({ \
bios_outb(addr, SEQ_I); \
bios_outb(data, SEQ_D); \
})
#define write_gra(data, addr) \
({ \
bios_outb(addr, GRA_I); \
bios_outb(data, GRA_D); \
})
#define write_crtc(data, addr) \
({ \
bios_outb(addr, CRT_IC); \
bios_outb(data, CRT_DC); \
})
#define write_att(data, addr) \
({ \
bios_inb(IS1_RC); \
bios_inb(0x80); \
bios_outb(addr, ATT_IW); \
bios_inb(0x80); \
bios_outb(data, ATT_IW); \
bios_inb(0x80); \
})
#define SEQ_CLOCK_MODE 0x01
#define SEQ_PLANE_WRITE 0x02
#define SEQ_CHARACTER_MAP 0x03
#define SEQ_MEMORY_MODE 0x04
#define GDC_PLANE_READ 0x04
#define GDC_MODE 0x05
#define GDC_MISC 0x06
#define GDC_BIT_MASK 0x08
#define VGA_FONT_BASE 0xa8000
#define CHAR_HEIGHT 16
unsigned char read_seq_b(unsigned short addr) {
bios_outb(addr, SEQ_I);
return bios_inb(SEQ_D);
}
unsigned char read_gra_b(unsigned short addr) {
bios_outb(addr, GRA_I);
return bios_inb(GRA_D);
}
unsigned char read_crtc_b(unsigned short addr) {
bios_outb(addr, CRT_IC);
return bios_inb(CRT_DC);
}
unsigned char read_att_b(unsigned short addr) {
bios_inb(IS1_RC);
bios_inb(0x80);
bios_outb(addr, ATT_IW);
return bios_inb(ATT_R);
}
#if 0
void vga_set_amode (void) {
unsigned char byte;
rom_printk("Switching into alpha mode...");
write_att(0x0c, ATC_MODE);
//reset palette to normal in the case it was changed
write_att(0x0, ATC_COLOR_PAGE);
//
// display is off at this point
write_seq(0x3, SEQ_PLANE_WRITE); /* planes 0 & 1 */
byte = read_seq_b(SEQ_MEMORY_MODE) & ~0x04;
write_seq(byte, SEQ_MEMORY_MODE);
byte = read_gra_b(GDC_MODE) & ~0x60;
write_gra(byte|0x10, GDC_MODE);
write_gra(0x0e, GDC_MISC);
write_crtc(0x00, CRTC_CURSOR_START);
write_crtc(CHAR_HEIGHT-1, CRTC_CURSOR_END);
byte = read_crtc_b(CRTC_MODE) & ~0xe0;
write_crtc(byte|0xa0, CRTC_MODE);
byte = read_crtc_b(CRTC_MAX_SCAN) & ~0x01f;
write_crtc(byte | (CHAR_HEIGHT-1), CRTC_MAX_SCAN);
// turn on display, disable access to attr palette
bios_inb(IS1_RC);
bios_outb(0x20, ATT_IW);
rom_printk("done.\n");
}
#endif
/*
* by Steve M. Gehlbach, Ph.D. <steve@kesa.com>
*
* vga_font_load loads a font into font memory. It
* assumes alpha mode has been set.
*
* The font load code follows technique used
* in the tiara project, which came from
* the Universal Talkware Boot Loader,
* http://www.talkware.net.
*/
void atyr128_font_enable(unsigned char *vidmem, int height, int num_chars) {
/* Note: the font table is 'height' long but the font storage area
* is 32 bytes long.
*/
int i;
unsigned char byte;
// rom_printk("Loading VGA font...");
// set sequencer map 2, odd/even off
byte = read_seq_b(SEQ_PLANE_WRITE) & ~0xf;
// rom_printk("SEQ_PLANE_WRITE %x\n", byte);
write_seq(byte|4,SEQ_PLANE_WRITE);
byte = read_seq_b(SEQ_MEMORY_MODE);
// rom_printk("SEQ_MEMORY_MODE %x\n", byte);
write_seq(byte|4,SEQ_MEMORY_MODE);
// select graphics map 2, odd/even off, map starts at 0xa0000
write_gra(2,GDC_PLANE_READ);
byte = read_gra_b(GDC_MODE) & ~0x10;
// rom_printk("GDC_MODE %x\n", byte);
write_gra(byte,GDC_MODE);
write_gra(0,GDC_MISC);
/* Clear 256K */
for (i = 0; i<(256 * 1024); i++) {
vidmem[i] = 0;
}
// set sequencer back to maps 0,1, odd/even on
byte = read_seq_b(SEQ_PLANE_WRITE) & ~0xf;
write_seq(byte|3,SEQ_PLANE_WRITE);
byte = read_seq_b(SEQ_MEMORY_MODE) & ~0x4;
write_seq(byte,SEQ_MEMORY_MODE);
byte = read_seq_b(SEQ_CHARACTER_MAP);
// rom_printk("SEQ_CHARACTER_MAP %x\n", byte);
write_seq(0x0a, SEQ_CHARACTER_MAP);
// select graphics back to map 0,1, odd/even on
write_gra(0,GDC_PLANE_READ);
byte = read_gra_b(GDC_MODE);
write_gra(byte|0x10,GDC_MODE);
write_gra(0xe,GDC_MISC);
// rom_printk("done\n");
}
void video_bios(void)
{
struct bios_pci_dev *dev;
int adpt_cnt;
unsigned char *code = 0;
int pcirom = 0;
int atyr128 = 0;
int cl5446 = 0;
int mga2 = 0;
adpt_cnt = 0;
DebugV("video_bios() started\n");
dev = pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, NULL);
adpt_cnt++;
if (dev) {
#if DEBUG_VIDEO
rom_printk("--------- VIDEO BIOS ------\n");
rom_printk("Class: %X\n", dev->class);
rom_printk("command: %x\n", dev->command);
rom_printk("base_address[0]: %04x\n", dev->base_address[0]);
rom_printk("size[0]: %04x\n", dev->size[0]);
rom_printk("base_address[1]: %04x\n", dev->base_address[1]);
rom_printk("size[1]: %04x\n", dev->size[1]);
rom_printk("base_address[2]: %04x\n", dev->base_address[2]);
rom_printk("size[2]: %04x\n", dev->size[2]);
rom_printk("base_address[3]: %04x\n", dev->base_address[3]);
rom_printk("size[0]: %04x\n", dev->size[3]);
rom_printk("base_address[4]: %04x\n", dev->base_address[4]);
rom_printk("size[4]: %04x\n", dev->size[4]);
rom_printk("base_address[5]: %04x\n", dev->base_address[5]);
rom_printk("size[5]: %04x\n", dev->size[5]);
rom_printk("rom_address: %04x\n", dev->rom_address);
rom_printk("rom_size %04x\n", dev->rom_size);
#endif
code = (unsigned char *) dev->rom_address;
if (code[0] == 0x55U &&
code[1] == 0xAAU ) {
rom_printk("VIDEO BIOS found at %X\n", code);
} else {
rom_printk("No ROM signature found."
" Skipping BIOS init...\n");
rom_printk("BYTES: %x %x\n", code[0],
code[1]);
}
switch (dev->vendor)
{
case PCI_VENDOR_ID_CIRRUS:
if (dev->device == PCI_DEVICE_ID_CIRRUS_5446) {
rom_printk("Cirrus Logic GD 5446 detected!\n");
cl5446 = 1;
};
break;
case PCI_VENDOR_ID_ATI:
switch(dev->device)
{
case PCI_DEVICE_ID_ATI_RAGE128_PP:
rom_printk("ATI Rage 128 PP detected!\n");
atyr128 = 1;
break;
case PCI_DEVICE_ID_ATI_RAGE128_TR:
rom_printk("ATI Rage 128 TR detected!\n");
atyr128 = 1;
break;
default:
rom_printk("Unknown ATI display adapter detected!\n");
break;
};
break;
case PCI_VENDOR_ID_MCST_TMP:
if (dev->device == PCI_DEVICE_ID_MCST_MGA2) {
rom_printk("Embeded Graphic MGA2/GC2500 "
"detected!\n");
mga2 = 1;
};
break;
default:
rom_printk("Unknown display adapter found!\n");
break;
}
} else {
rom_printk("No PCI display adaplers found!\n");
}
if (pcirom) {
pci_video_bios_init(dev);
} else if (mga2) {
#ifdef CONFIG_VGA_CONSOLE
vga_init();
#endif /* CONFIG_VGA_CONSOLE */
} else {
return;
}
if (atyr128) {
atyr128_font_enable( (unsigned char *) VGA_FONT_BASE,
CHAR_HEIGHT, 256);
#if 0
unsigned char *vidmem = (unsigned char *) dev->base_address[0];
int i;
for (i=0; i < (1 * 1024 * 1024); i++) {
vidmem[i] = 0;
};
#endif
}
// vga_set_amode();
hardware.video = 1;
if (atyr128)
{
long int i;
/* delay to relax ATI hardware */
for (i=0; i<77000000L; i++) {
do {
(void) (i);
} while (0) ;
}
}
#if 0
if (cl5446)
{
long int i;
// rom_printk("qwertyuiopasdfghjklzxcvbnm\n");
// rom_printk("qwertyuiopasdfghjklzxcvbnm\n");
// rom_printk("qwertyuiopasdfghjklzxcvbnm\n");
for (i=0; i<2000000L; i++) { do {i; } while (0) ; }
}
#endif
}

View File

@ -0,0 +1,89 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/xf86x86emu.h,v 1.2 2001/01/06 20:19:13 tsi Exp $ */
/*
* XFree86 int10 module
* execute BIOS int 10h calls in x86 real mode environment
* Copyright 1999 Egbert Eich
*/
#ifndef XF86X86EMU_H_
#define XF86X86EMU_H_
#include <x86emu.h>
#define M _X86EMU_env
#define X86_EAX M.x86.R_EAX
#define X86_EBX M.x86.R_EBX
#define X86_ECX M.x86.R_ECX
#define X86_EDX M.x86.R_EDX
#define X86_ESI M.x86.R_ESI
#define X86_EDI M.x86.R_EDI
#define X86_EBP M.x86.R_EBP
#define X86_EIP M.x86.R_EIP
#define X86_ESP M.x86.R_ESP
#define X86_EFLAGS M.x86.R_EFLG
#define X86_FLAGS M.x86.R_FLG
#define X86_AX M.x86.R_AX
#define X86_BX M.x86.R_BX
#define X86_CX M.x86.R_CX
#define X86_DX M.x86.R_DX
#define X86_SI M.x86.R_SI
#define X86_DI M.x86.R_DI
#define X86_BP M.x86.R_BP
#define X86_IP M.x86.R_IP
#define X86_SP M.x86.R_SP
#define X86_CS M.x86.R_CS
#define X86_DS M.x86.R_DS
#define X86_ES M.x86.R_ES
#define X86_SS M.x86.R_SS
#define X86_FS M.x86.R_FS
#define X86_GS M.x86.R_GS
#define X86_AL M.x86.R_AL
#define X86_BL M.x86.R_BL
#define X86_CL M.x86.R_CL
#define X86_DL M.x86.R_DL
#define X86_AH M.x86.R_AH
#define X86_BH M.x86.R_BH
#define X86_CH M.x86.R_CH
#define X86_DH M.x86.R_DH
/* int10 info structure */
typedef struct {
u16 BIOSseg;
u16 inb40time;
struct _mem *mem;
int num;
int ax;
int bx;
int cx;
int dx;
int si;
int di;
int es;
int bp;
int flags;
int stackseg;
} _ptr, *ptr;
typedef struct _mem {
u8(*rb) (ptr, int);
u16(*rw) (ptr, int);
u32(*rl) (ptr, int);
void (*wb) (ptr, int, u8);
void (*ww) (ptr, int, u16);
void (*wl) (ptr, int, u32);
} mem;
#define MEM_WB(where, what) wrb(where,what)
#define MEM_WW(where, what) wrw(where, what)
#define MEM_WL(where, what) wrl(where, what)
#define MEM_RB(where) rdb(where)
#define MEM_RW(where) rdw(where)
#define MEM_RL(where) rdl(where)
extern ptr currentp;
#endif

View File

@ -0,0 +1,489 @@
#ifndef IN_MODULE
#include <stdio.h>
#endif
#include "init.h"
#include "pci.h"
void x86emu_dump_xregs(void);
extern int verbose;
#ifndef _PC
/*
* This is derived from a number of PC system BIOS'es. The intent here is to
* provide very primitive video support, before an EGA/VGA BIOS installs its
* own interrupt vector. Here, "Ignored" calls should remain so. "Not
* Implemented" denotes functionality that can be implemented should the need
* arise. What are "Not Implemented" throughout are video memory accesses.
* Also, very little input validity checking is done here.
*/
int int42_handler(void)
{
#if 0
if (verbose && X86_AH != 0x0e) {
rom_printk("int%x\n", current->num);
x86emu_dump_xregs();
}
switch (X86_AH) {
case 0x00:
/* Set Video Mode */
/* Enter: AL = video mode number */
/* Leave: Nothing */
/* Implemented (except for clearing the screen) */
{ /* Localise */
int i;
u16 ioport, int1d, regvals, tmp;
u8 mode, cgamode, cgacolour;
/*
* Ignore all mode numbers but 0x00-0x13. Some systems also ignore
* 0x0B and 0x0C, but don't do that here.
*/
if (X86_AL > 0x13)
break;
/*
* You didn't think that was really the mode set, did you? There
* are only so many slots in the video parameter table...
*/
mode = X86_AL;
ioport = 0x03D4;
/* Linar */
tmp = MEM_RB(0x0410) & 0x30;
rom_printk("tmp: %x mode %x\n", tmp, mode);
if (mode == 7 || tmp == 0x30) {
mode = 3;
tmp = 0x20;
}
// switch (MEM_RB(0x0410) & 0x30) {
switch (tmp) {
case 0x30: /* MDA */
mode = 0x07; /* Force mode to 0x07 */
ioport = 0x03B4;
break;
case 0x10: /* CGA 40x25 */
if (mode >= 0x07)
mode = 0x01;
break;
case 0x20: /* CGA 80x25 (MCGA?) */
if (mode >= 0x07)
mode = 0x03;
break;
case 0x00: /* EGA/VGA */
if (mode >= 0x07) /* Don't try MDA timings */
mode = 0x01; /* !?!?! */
break;
}
/* Locate data in video parameter table */
int1d = MEM_RW(0x1d << 2);
regvals = ((mode >> 1) << 4) + int1d;
cgacolour = 0x30;
if (mode == 0x06) {
regvals -= 0x10;
cgacolour = 0x3F;
}
/** Update BIOS Data Area **/
/* Video mode */
MEM_WB(0x0449, mode);
/* Columns */
tmp = MEM_RB(mode + int1d + 0x48);
MEM_WW(0x044A, tmp);
/* Page length */
tmp = MEM_RW((mode & 0x06) + int1d + 0x40);
MEM_WW(0x044C, tmp);
/* Start Address */
MEM_WW(0x044E, 0);
/* Cursor positions, one for each display page */
for (i = 0x0450; i < 0x0460; i += 2)
MEM_WW(i, 0);
/* Cursor start & end scanlines */
tmp = MEM_RB(regvals + 0x0B);
MEM_WB(0x0460, tmp);
tmp = MEM_RB(regvals + 0x0A);
MEM_WB(0x0461, tmp);
/* Current display page number */
MEM_WB(0x0462, 0);
/* CRTC I/O address */
MEM_WW(0x0463, ioport);
/* CGA Mode register value */
cgamode = MEM_RB(mode + int1d + 0x50);
MEM_WB(0x0465, cgamode);
/* CGA Colour register value */
MEM_WB(0x0466, cgacolour);
/* Rows */
MEM_WB(0x0484, (25 - 1));
/* Programme the mode */
outb(ioport + 4, cgamode & 0x37); /* Turn off screen */
for (i = 0; i < 0x10; i++) {
tmp = MEM_RB(regvals + i);
outb(ioport, i);
outb(ioport + 1, tmp);
}
outb(ioport + 5, cgacolour); /* Select colour mode */
outb(ioport + 4, cgamode); /* Turn on screen */
}
break;
case 0x01:
/* Set Cursor Type */
/* Enter: CH = starting line for cursor */
/* CL = ending line for cursor */
/* Leave: Nothing */
/* Implemented */
{ /* Localise */
u16 ioport = MEM_RW(0x0463);
MEM_WB(0x0460, X86_CL);
MEM_WB(0x0461, X86_CH);
outb(ioport, 0x0A);
outb(ioport + 1, X86_CH);
outb(ioport, 0x0B);
outb(ioport + 1, X86_CL);
}
break;
case 0x02:
/* Set Cursor Position */
/* Enter: BH = display page number */
/* DH = row */
/* DL = column */
/* Leave: Nothing */
/* Implemented */
{ /* Localise */
u16 offset, ioport;
MEM_WB((X86_BH << 1) + 0x0450, X86_DL);
MEM_WB((X86_BH << 1) + 0x0451, X86_DH);
if (X86_BH != MEM_RB(0x0462))
break;
offset = (X86_DH * MEM_RW(0x044A)) + X86_DL;
offset += MEM_RW(0x044E) << 1;
ioport = MEM_RW(0x0463);
outb(ioport, 0x0E);
outb(ioport + 1, offset >> 8);
outb(ioport, 0x0F);
outb(ioport + 1, offset & 0xFF);
}
break;
case 0x03:
/* Get Cursor Position */
/* Enter: BH = display page number */
/* Leave: CH = starting line for cursor */
/* CL = ending line for cursor */
/* DH = row */
/* DL = column */
/* Implemented */
{ /* Localise */
X86_CL = MEM_RB(0x0460);
X86_CH = MEM_RB(0x0461);
X86_DL = MEM_RB((X86_BH << 1) + 0x0450);
X86_DH = MEM_RB((X86_BH << 1) + 0x0451);
}
break;
case 0x04:
/* Get Light Pen Position */
/* Enter: Nothing */
/* Leave: AH = 0x01 (down/triggered) or 0x00 (not) */
/* BX = pixel column */
/* CX = pixel row */
/* DH = character row */
/* DL = character column */
/* Not Implemented */
{ /* Localise */
rom_printk("int%x - Get Light Pen Position. "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
X86_AH = X86_BX = X86_CX = X86_DX = 0;
}
break;
case 0x05:
/* Set Display Page */
/* Enter: AL = display page number */
/* Leave: Nothing */
/* Implemented */
{ /* Localise */
u16 start, ioport = MEM_RW(0x0463);
u8 x, y;
/* Calculate new start address */
MEM_WB(0x0462, X86_AL);
start = X86_AL * MEM_RW(0x044C);
MEM_WW(0x044E, start);
start <<= 1;
/* Update start address */
outb(ioport, 0x0C);
outb(ioport + 1, start >> 8);
outb(ioport, 0x0D);
outb(ioport + 1, start & 0xFF);
/* Switch cursor position */
y = MEM_RB((X86_AL << 1) + 0x0450);
x = MEM_RB((X86_AL << 1) + 0x0451);
start += (y * MEM_RW(0x044A)) + x;
/* Update cursor position */
outb(ioport, 0x0E);
outb(ioport + 1, start >> 8);
outb(ioport, 0x0F);
outb(ioport + 1, start & 0xFF);
}
break;
case 0x06:
/* Initialise or Scroll Window Up */
/* Enter: AL = lines to scroll up */
/* BH = attribute for blank */
/* CH = upper y of window */
/* CL = left x of window */
/* DH = lower y of window */
/* DL = right x of window */
/* Leave: Nothing */
/* Not Implemented */
{ /* Localise */
rom_printk("int%x: Initialise or Scroll Window Up - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
}
break;
case 0x07:
/* Initialise or Scroll Window Down */
/* Enter: AL = lines to scroll down */
/* BH = attribute for blank */
/* CH = upper y of window */
/* CL = left x of window */
/* DH = lower y of window */
/* DL = right x of window */
/* Leave: Nothing */
/* Not Implemented */
{ /* Localise */
rom_printk("int%x: Initialise or Scroll Window Down - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
}
break;
case 0x08:
/* Read Character and Attribute at Cursor */
/* Enter: BH = display page number */
/* Leave: AH = attribute */
/* AL = character */
/* Not Implemented */
{ /* Localise */
rom_printk
("int%x: Read Character and Attribute at Cursor - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
X86_AX = 0;
}
break;
case 0x09:
/* Write Character and Attribute at Cursor */
/* Enter: AL = character */
/* BH = display page number */
/* BL = attribute (text) or colour (graphics) */
/* CX = replication count */
/* Leave: Nothing */
/* Not Implemented */
{ /* Localise */
rom_printk
("int%x: Write Character and Attribute at Cursor - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
}
break;
case 0x0a:
/* Write Character at Cursor */
/* Enter: AL = character */
/* BH = display page number */
/* BL = colour */
/* CX = replication count */
/* Leave: Nothing */
/* Not Implemented */
{ /* Localise */
rom_printk("int%x: Write Character at Cursor - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
}
break;
case 0x0b:
/* Set Palette, Background or Border */
/* Enter: BH = 0x00 or 0x01 */
/* BL = colour or palette (respectively) */
/* Leave: Nothing */
/* Implemented */
{ /* Localise */
u16 ioport = MEM_RW(0x0463) + 5;
u8 cgacolour = MEM_RB(0x0466);
if (X86_BH) {
cgacolour &= 0xDF;
cgacolour |= (X86_BL & 0x01) << 5;
} else {
cgacolour &= 0xE0;
cgacolour |= X86_BL & 0x1F;
}
MEM_WB(0x0466, cgacolour);
outb(ioport, cgacolour);
}
break;
case 0x0c:
/* Write Graphics Pixel */
/* Enter: AL = pixel value */
/* BH = display page number */
/* CX = column */
/* DX = row */
/* Leave: Nothing */
/* Not Implemented */
{ /* Localise */
rom_printk("int%x: Write Graphics Pixel - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
}
break;
case 0x0d:
/* Read Graphics Pixel */
/* Enter: BH = display page number */
/* CX = column */
/* DX = row */
/* Leave: AL = pixel value */
/* Not Implemented */
{ /* Localise */
rom_printk("int%x: Write Graphics Pixel - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
X86_AL = 0;
}
break;
case 0x0e:
/* Write Character in Teletype Mode */
/* Enter: AL = character */
/* BH = display page number */
/* BL = foreground colour */
/* Leave: Nothing */
/* Not Implemented */
/* WARNING: Emulation of BEL characters will require */
/* emulation of RTC and PC speaker I/O. */
/* Also, this recurses through int 0x10 */
/* which might or might not have been */
/* installed yet. */
{ /* Localise */
#ifdef PARANOID
rom_printk("int%x: Write Character in Teletype Mode - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
#endif
rom_printk("%c", X86_AL);
}
break;
case 0x0f:
/* Get Video Mode */
/* Enter: Nothing */
/* Leave: AH = number of columns */
/* AL = video mode number */
/* BH = display page number */
/* Implemented */
{ /* Localise */
X86_AH = MEM_RW(0x044A);
X86_AL = MEM_RB(0x0449);
X86_BH = MEM_RB(0x0462);
}
break;
case 0x10:
/* Colour Control (subfunction in AL) */
/* Enter: Various */
/* Leave: Various */
/* Ignored */
break;
case 0x11:
/* Font Control (subfunction in AL) */
/* Enter: Various */
/* Leave: Various */
/* Ignored */
break;
case 0x12:
/* Miscellaneous (subfunction in BL) */
/* Enter: Various */
/* Leave: Various */
/* Ignored. Previous code here optionally allowed */
/* the enabling and disabling of VGA, but no system */
/* BIOS I've come across actually implements it. */
break;
case 0x13:
/* Write String in Teletype Mode */
/* Enter: AL = write mode */
/* BL = attribute (if (AL & 0x02) == 0) */
/* CX = string length */
/* DH = row */
/* DL = column */
/* ES:BP = string segment:offset */
/* Leave: Nothing */
/* Not Implemented */
/* WARNING: Emulation of BEL characters will require */
/* emulation of RTC and PC speaker I/O. */
/* Also, this recurses through int 0x10 */
/* which might or might not have been */
/* installed yet. */
{ /* Localise */
rom_printk("int%x: Write String in Teletype Mode - "
"Function not implemented.\n", current->num);
x86emu_dump_xregs();
}
break;
default:
/* Various extensions */
/* Enter: Various */
/* Leave: Various */
/* Ignored */
break;
}
#endif
return 1;
}
#endif

View File

@ -0,0 +1,19 @@
#ifndef IN_MODULE
#include <stdio.h>
#endif
#include "init.h"
#include "printk.h"
void x86emu_dump_xregs(void);
int int15_handler(void)
{
#ifdef DEBUG
rom_printk("\nint15 encountered.\n");
x86emu_dump_xregs();
#endif
X86_EAX = 0;
return 1;
}

View File

@ -0,0 +1,12 @@
#ifndef IN_MODULE
#include <stdio.h>
#endif
#include "printk.h"
int int16_handler(void)
{
rom_printk("\nint16: keyboard not supported right now.\n");
return 1;
}

View File

@ -0,0 +1,187 @@
#ifndef IN_MODULE
#include <stdio.h>
#endif
#include <x86emu.h>
#include "init.h"
#include "pci-iface.h"
#include "pci.h"
#include "printk.h"
#define DEBUG_INT1A
#define SUCCESSFUL 0x00
#define DEVICE_NOT_FOUND 0x86
#define BAD_REGISTER_NUMBER 0x87
void x86emu_dump_xregs(void);
extern int verbose;
int int1A_handler(void)
{
PCITAG tag;
pciVideoPtr pvp = NULL;
if (verbose) {
rom_printk("\nint1a encountered.\n");
x86emu_dump_xregs();
}
rom_printk("int1a: X86_AX = %x\n", X86_AX);
switch (X86_AX) {
case 0xb101:
X86_EAX = 0x00; /* no config space/special cycle support */
X86_AL = 0x01; /* config mechanism 1 */
X86_EDX = 0x20494350; /* " ICP" */
X86_EBX = 0x0210; /* Version 2.10 */
X86_ECX &= 0xFF00;
X86_ECX |= (pciNumBuses & 0xFF); /* Max bus number in system */
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
#ifdef DEBUG_INT1A
if (verbose)
rom_printk("PCI bios present.\n");
#endif
return 1;
case 0xb102:
if (X86_DX == pvp->vendor && X86_CX == pvp->device && X86_ESI == 0) {
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
X86_EBX = pciSlotBX(pvp);
}
#ifdef SHOW_ALL_DEVICES
else if ((pvp = xf86FindPciDeviceVendor(X86_EDX, X86_ECX, X86_ESI, pvp))) {
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
X86_EBX = pciSlotBX(pvp);
}
#endif
else {
X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
rom_printk("eax=0x%x ebx=0x%x eflags=0x%x\n", X86_EAX, X86_EBX, X86_EFLAGS);
#endif
return 1;
case 0xb103:
#if 0
if (X86_CL == pvp->interface &&
X86_CH == pvp->subclass &&
((X86_ECX & 0xFFFF0000) >> 16) == pvp->class) {
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EBX = pciSlotBX(pvp);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
}
#else
/* FIXME: dirty hack */
if (0);
#endif
#ifdef SHOW_ALL_DEVICES
else if ((pvp = FindPciClass(X86_CL, X86_CH,
(X86_ECX & 0xffff0000) >> 16,
X86_ESI, pvp))) {
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
X86_EBX = pciSlotBX(pvp);
}
#endif
else {
X86_EAX = X86_AL | (DEVICE_NOT_FOUND << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
rom_printk("eax=0x%x eflags=0x%x\n", X86_EAX, X86_EFLAGS);
#endif
return 1;
case 0xb108:
if ((tag = findPci(X86_EBX))) {
X86_CL = pciReadByte(tag, X86_EDI);
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
} else {
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
rom_printk("eax=0x%x ecx=0x%x eflags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS);
#endif
return 1;
case 0xb109:
rom_printk("int1a: X86_EBX = %x X86_EDI = %x\n", X86_EBX, X86_EDI);
if ((tag = findPci(X86_EBX))) {
X86_CX = pciReadWord(tag, X86_EDI);
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
} else {
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
rom_printk("eax=0x%x ecx=0x%x eflags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS);
#endif
return 1;
case 0xb10a:
if ((tag = findPci(X86_EBX))) {
X86_ECX = pciReadLong(tag, X86_EDI);
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
} else {
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
rom_printk("eax=0x%x ecx=0x%x eflags=0x%x\n", X86_EAX, X86_ECX, X86_EFLAGS);
#endif
return 1;
case 0xb10b:
if ((tag = findPci(X86_EBX))) {
pciWriteByte(tag, X86_EDI, X86_CL);
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
} else {
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
rom_printk("eax=0x%x eflags=0x%x\n", X86_EAX, X86_EFLAGS);
#endif
return 1;
case 0xb10c:
rom_printk("int1a: X86_EBX = %x X86_EDI = %x X86_CX = %x\n",
X86_EBX, X86_EDI, X86_CX);
if ((tag = findPci(X86_EBX))) {
pciWriteWord(tag, X86_EDI, X86_CX);
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
} else {
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
rom_printk("eax=0x%x eflags=0x%x\n", X86_EAX, X86_EFLAGS);
#endif
return 1;
case 0xb10d:
if ((tag = findPci(X86_EBX))) {
pciWriteLong(tag, X86_EDI, X86_ECX);
X86_EAX = X86_AL | (SUCCESSFUL << 8);
X86_EFLAGS &= ~((unsigned long) 0x01); /* clear carry flag */
} else {
X86_EAX = X86_AL | (BAD_REGISTER_NUMBER << 8);
X86_EFLAGS |= ((unsigned long) 0x01); /* set carry flag */
}
#ifdef DEBUG_INT1A
rom_printk("eax=0x%x eflags=0x%x\n", X86_EAX, X86_EFLAGS);
#endif
return 1;
default:
rom_printk("int1a: subfunction not implemented.\n");
return 0;
}
}

View File

@ -0,0 +1,23 @@
#ifndef IN_MODULE
#include <stdio.h>
#endif
#include "printk.h"
int intE6_handler(void)
{
#if 0
pciVideoPtr pvp;
if ((pvp = xf86GetPciInfoForEntity(pInt->entityIndex)))
X86_AX = (pvp->bus << 8) | (pvp->device << 3) | (pvp->func & 0x7);
pushw(X86_CS);
pushw(X86_IP);
X86_CS = pInt->BIOSseg;
X86_EIP = 0x0003;
X86_ES = 0; /* standard pc es */
#endif
rom_printk("intE6 not supported right now.\n");
return 1;
}

View File

@ -0,0 +1,150 @@
#ifndef IN_MODULE
#include <stdio.h>
#include <pci/pci.h>
#endif
#include <x86emu.h>
#include "pci-iface.h"
#include "pci.h"
#define PCITAG struct pci_filter *
#define DEBUG_PCI 1
struct pci_access *pacc;
struct bios_pci_dev *dev;
struct pci_filter ltag;
int pciNumBuses = 0;
int pciInit(void)
{
return 0;
}
int pciExit(void)
{
return 0;
}
PCITAG findPci(unsigned short bx)
{
PCITAG tag = &ltag;
int bus = (bx >> 8) & 0xFF;
int slot = (bx >> 3) & 0x1F;
int func = bx & 0x7;
tag->bus = bus;
tag->slot = slot;
tag->func = func;
if (pci_find_slot(bus, PCI_DEVFN(slot, func)))
return tag;
return NULL;
}
u32 pciSlotBX(pciVideoPtr pvp)
{
PCITAG tag = &ltag;
tag->bus = pvp->bus->number;
tag->slot = PCI_SLOT(pvp->devfn);
tag->func = PCI_FUNC(pvp->devfn);
return (tag->bus << 8) | (tag->slot << 3) | (tag->func);
}
u8 pciReadByte(PCITAG tag, u32 idx)
{
struct bios_pci_dev *d;
u8 res;
if ((d = pci_find_slot(tag->bus, PCI_DEVFN(tag->slot, tag->func)))) {
bios_pci_read_config_byte(d, (u8) idx, &res);
return res;
}
#ifdef DEBUG_PCI
printf("PCI: device not found while read byte (%x:%x.%x)\n",
tag->bus, tag->slot, tag->func);
#endif
return 0;
}
u16 pciReadWord(PCITAG tag, u32 idx)
{
struct bios_pci_dev *d;
u16 res;
if ((d = pci_find_slot(tag->bus, PCI_DEVFN(tag->slot, tag->func)))) {
bios_pci_read_config_word(d, (u8) idx, &res);
return res;
}
#ifdef DEBUG_PCI
printf("PCI: device not found while read word (%x:%x.%x)\n",
tag->bus, tag->slot, tag->func);
#endif
return 0;
}
u32 pciReadLong(PCITAG tag, u32 idx)
{
struct bios_pci_dev *d;
u32 res;
if ((d = pci_find_slot(tag->bus, PCI_DEVFN(tag->slot, tag->func)))) {
bios_pci_read_config_dword(d, (u8) idx, &res);
return res;
}
#ifdef DEBUG_PCI
printf("PCI: device not found while read long (%x:%x.%x)\n",
tag->bus, tag->slot, tag->func);
#endif
return 0;
}
void pciWriteLong(PCITAG tag, u32 idx, u32 data)
{
struct bios_pci_dev *d;
if ((d = pci_find_slot(tag->bus, PCI_DEVFN(tag->slot, tag->func))))
bios_pci_write_config_dword(d, (u8) idx, data);
#ifdef DEBUG_PCI
else
printf("PCI: device not found while write long (%x:%x.%x)\n",
tag->bus, tag->slot, tag->func);
#endif
}
void pciWriteWord(PCITAG tag, u32 idx, u16 data)
{
struct bios_pci_dev *d;
if ((d = pci_find_slot(tag->bus, PCI_DEVFN(tag->slot, tag->func))))
bios_pci_write_config_word(d, (u8) idx, data);
#ifdef DEBUG_PCI
else
printf("PCI: device not found while write word (%x:%x.%x)\n",
tag->bus, tag->slot, tag->func);
#endif
}
void pciWriteByte(PCITAG tag, u32 idx, u8 data)
{
struct bios_pci_dev *d;
if ((d = pci_find_slot(tag->bus, PCI_DEVFN(tag->slot, tag->func))))
bios_pci_write_config_byte(d, (u8) idx, data);
#ifdef DEBUG_PCI
else
printf("PCI: device not found while write long (%x:%x.%x)\n",
tag->bus, tag->slot, tag->func);
#endif
}

View File

@ -0,0 +1,32 @@
#include "pci.h"
typedef unsigned long pciaddr_t;
typedef u8 byte;
typedef u16 word;
struct pci_filter {
int bus, slot, func; /* -1 = ANY */
int vendor, device;
};
#define PCITAG struct pci_filter *
#define pciVideoPtr struct bios_pci_dev *
extern int pciNumBuses;
int pciInit(void);
int pciExit(void);
PCITAG findPci(unsigned short bx);
u32 pciSlotBX(pciVideoPtr pvp);
void pciWriteLong(PCITAG tag, u32 idx, u32 data);
void pciWriteWord(PCITAG tag, u32 idx, u16 data);
void pciWriteByte(PCITAG tag, u32 idx, u8 data);
u32 pciReadLong(PCITAG tag, u32 idx);
u16 pciReadWord(PCITAG tag, u32 idx);
u8 pciReadByte(PCITAG tag, u32 idx);

View File

@ -0,0 +1,33 @@
#ifndef CPU_P6_MSR_H
#define CPU_P6_MSR_H
/*
* Access to machine-specific registers (available on 586 and better only)
* Note: the rd* operations modify the parameters directly (without using
* pointer indirection), this allows gcc to optimize better
*/
#define rdmsr(msr,val1,val2) \
__asm__ __volatile__("rdmsr" \
: "=a" (val1), "=d" (val2) \
: "c" (msr))
#define wrmsr(msr,val1,val2) \
__asm__ __volatile__("wrmsr" \
: /* no outputs */ \
: "c" (msr), "a" (val1), "d" (val2))
#define rdtsc(low,high) \
__asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
#define rdtscl(low) \
__asm__ __volatile__ ("rdtsc" : "=a" (low) : : "edx")
#define rdtscll(val) \
__asm__ __volatile__ ("rdtsc" : "=A" (val))
#define rdpmc(counter,low,high) \
__asm__ __volatile__("rdpmc" \
: "=a" (low), "=d" (high) \
: "c" (counter))
#endif /* CPU_P6_MSR_H */

View File

@ -0,0 +1,205 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1996-1999 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for public specific functions.
* Any application linking against us should only
* include this header
*
****************************************************************************/
/* $XFree86: xc/extras/x86emu/include/x86emu.h,v 1.2 2000/11/21 23:10:25 tsi Exp $ */
#ifndef __X86EMU_X86EMU_H
#define __X86EMU_X86EMU_H
extern void rom_printk(char const *fmt, ...);
#undef printf
#define printf(...) rom_printk(##__VA_ARGS__)
#ifndef NULL
#define NULL (void *) 0
#endif
#ifdef SCITECH
#include "scitech.h"
#define X86API _ASMAPI
#define X86APIP _ASMAPIP
typedef int X86EMU_pioAddr;
#else
#include "x86emu/types.h"
#define X86API
#define X86APIP *
#endif
#include "x86emu/regs.h"
/*---------------------- Macros and type definitions ----------------------*/
#pragma pack(1)
/****************************************************************************
REMARKS:
Data structure containing ponters to programmed I/O functions used by the
emulator. This is used so that the user program can hook all programmed
I/O for the emulator to handled as necessary by the user program. By
default the emulator contains simple functions that do not do access the
hardware in any way. To allow the emualtor access the hardware, you will
need to override the programmed I/O functions using the X86EMU_setupPioFuncs
function.
HEADER:
x86emu.h
MEMBERS:
inb - Function to read a byte from an I/O port
inw - Function to read a word from an I/O port
inl - Function to read a dword from an I/O port
outb - Function to write a byte to an I/O port
outw - Function to write a word to an I/O port
outl - Function to write a dword to an I/O port
****************************************************************************/
typedef struct {
u8 (X86APIP inb_func)(X86EMU_pioAddr addr);
u16 (X86APIP inw_func)(X86EMU_pioAddr addr);
u32 (X86APIP inl_func)(X86EMU_pioAddr addr);
void (X86APIP outb_func)(X86EMU_pioAddr addr, u8 val);
void (X86APIP outw_func)(X86EMU_pioAddr addr, u16 val);
void (X86APIP outl_func)(X86EMU_pioAddr addr, u32 val);
} X86EMU_pioFuncs;
/****************************************************************************
REMARKS:
Data structure containing ponters to memory access functions used by the
emulator. This is used so that the user program can hook all memory
access functions as necessary for the emulator. By default the emulator
contains simple functions that only access the internal memory of the
emulator. If you need specialised functions to handle access to different
types of memory (ie: hardware framebuffer accesses and BIOS memory access
etc), you will need to override this using the X86EMU_setupMemFuncs
function.
HEADER:
x86emu.h
MEMBERS:
rdb - Function to read a byte from an address
rdw - Function to read a word from an address
rdl - Function to read a dword from an address
wrb - Function to write a byte to an address
wrw - Function to write a word to an address
wrl - Function to write a dword to an address
****************************************************************************/
typedef struct {
u8 (X86APIP rdb)(u32 addr);
u16 (X86APIP rdw)(u32 addr);
u32 (X86APIP rdl)(u32 addr);
void (X86APIP wrb)(u32 addr, u8 val);
void (X86APIP wrw)(u32 addr, u16 val);
void (X86APIP wrl)(u32 addr, u32 val);
} X86EMU_memFuncs;
/****************************************************************************
Here are the default memory read and write
function in case they are needed as fallbacks.
***************************************************************************/
extern u8 X86API rdb(u32 addr);
extern u16 X86API rdw(u32 addr);
extern u32 X86API rdl(u32 addr);
extern void X86API wrb(u32 addr, u8 val);
extern void X86API wrw(u32 addr, u16 val);
extern void X86API wrl(u32 addr, u32 val);
#pragma pack()
/*--------------------- type definitions -----------------------------------*/
typedef void (X86APIP X86EMU_intrFuncs)(int num);
extern X86EMU_intrFuncs _X86EMU_intrTab[256];
/*-------------------------- Function Prototypes --------------------------*/
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
void X86EMU_setupMemFuncs(X86EMU_memFuncs *funcs);
void X86EMU_setupPioFuncs(X86EMU_pioFuncs *funcs);
void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[]);
void X86EMU_prepareForInt(int num);
/* decode.c */
void X86EMU_exec(void);
void X86EMU_halt_sys(void);
#ifdef DEBUG
#define HALT_SYS() \
rom_printk("halt_sys: file %s, line %d\n", __FILE__, __LINE__), \
X86EMU_halt_sys()
#else
#define HALT_SYS() X86EMU_halt_sys()
#endif
/* Debug options */
#define DEBUG_DECODE_F 0x000001 /* print decoded instruction */
#define DEBUG_TRACE_F 0x000002 /* dump regs before/after execution */
#define DEBUG_STEP_F 0x000004
#define DEBUG_DISASSEMBLE_F 0x000008
#define DEBUG_BREAK_F 0x000010
#define DEBUG_SVC_F 0x000020
#define DEBUG_FS_F 0x000080
#define DEBUG_PROC_F 0x000100
#define DEBUG_SYSINT_F 0x000200 /* bios system interrupts. */
#define DEBUG_TRACECALL_F 0x000400
#define DEBUG_INSTRUMENT_F 0x000800
#define DEBUG_MEM_TRACE_F 0x001000
#define DEBUG_IO_TRACE_F 0x002000
#define DEBUG_TRACECALL_REGS_F 0x004000
#define DEBUG_DECODE_NOPRINT_F 0x008000
#define DEBUG_SAVE_IP_CS_F 0x010000
#define DEBUG_EXIT 0x020000
#define DEBUG_SAVE_CS_IP 0x040000
#define DEBUG_SYS_F (DEBUG_SVC_F|DEBUG_FS_F|DEBUG_PROC_F)
void X86EMU_trace_regs(void);
void X86EMU_trace_xregs(void);
void X86EMU_dump_memory(u16 seg, u16 off, u32 amt);
int X86EMU_trace_on(void);
int X86EMU_trace_off(void);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_X86EMU_H */

View File

@ -0,0 +1,115 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1996-1999 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for FPU register definitions.
*
****************************************************************************/
#ifndef __X86EMU_FPU_REGS_H
#define __X86EMU_FPU_REGS_H
#ifdef X86_FPU_SUPPORT
#pragma pack(1)
/* Basic 8087 register can hold any of the following values: */
union x86_fpu_reg_u {
s8 tenbytes[10];
double dval;
float fval;
s16 sval;
s32 lval;
};
struct x86_fpu_reg {
union x86_fpu_reg_u reg;
char tag;
};
/*
* Since we are not going to worry about the problems of aliasing
* registers, every time a register is modified, its result type is
* set in the tag fields for that register. If some operation
* attempts to access the type in a way inconsistent with its current
* storage format, then we flag the operation. If common, we'll
* attempt the conversion.
*/
#define X86_FPU_VALID 0x80
#define X86_FPU_REGTYP(r) ((r) & 0x7F)
#define X86_FPU_WORD 0x0
#define X86_FPU_SHORT 0x1
#define X86_FPU_LONG 0x2
#define X86_FPU_FLOAT 0x3
#define X86_FPU_DOUBLE 0x4
#define X86_FPU_LDBL 0x5
#define X86_FPU_BSD 0x6
#define X86_FPU_STKTOP 0
struct x86_fpu_registers {
struct x86_fpu_reg x86_fpu_stack[8];
int x86_fpu_flags;
int x86_fpu_config; /* rounding modes, etc. */
short x86_fpu_tos, x86_fpu_bos;
};
#pragma pack()
/*
* There are two versions of the following macro.
*
* One version is for opcode D9, for which there are more than 32
* instructions encoded in the second byte of the opcode.
*
* The other version, deals with all the other 7 i87 opcodes, for
* which there are only 32 strings needed to describe the
* instructions.
*/
#endif /* X86_FPU_SUPPORT */
#ifdef DEBUG
# define DECODE_PRINTINSTR32(t,mod,rh,rl) \
DECODE_PRINTF(t[(mod<<3)+(rh)]);
# define DECODE_PRINTINSTR256(t,mod,rh,rl) \
DECODE_PRINTF(t[(mod<<6)+(rh<<3)+(rl)]);
#else
# define DECODE_PRINTINSTR32(t,mod,rh,rl)
# define DECODE_PRINTINSTR256(t,mod,rh,rl)
#endif
#endif /* __X86EMU_FPU_REGS_H */

View File

@ -0,0 +1,338 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1996-1999 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for x86 register definitions.
*
****************************************************************************/
/* $XFree86: xc/extras/x86emu/include/x86emu/regs.h,v 1.3 2001/10/28 03:32:25 tsi Exp $ */
#ifndef __X86EMU_REGS_H
#define __X86EMU_REGS_H
//#include <x86emu.h>
/*---------------------- Macros and type definitions ----------------------*/
#pragma pack(1)
/*
* General EAX, EBX, ECX, EDX type registers. Note that for
* portability, and speed, the issue of byte swapping is not addressed
* in the registers. All registers are stored in the default format
* available on the host machine. The only critical issue is that the
* registers should line up EXACTLY in the same manner as they do in
* the 386. That is:
*
* EAX & 0xff === AL
* EAX & 0xffff == AX
*
* etc. The result is that alot of the calculations can then be
* done using the native instruction set fully.
*/
#ifdef __BIG_ENDIAN__
typedef struct {
u32 e_reg;
} I32_reg_t;
typedef struct {
u16 filler0, x_reg;
} I16_reg_t;
typedef struct {
u8 filler0, filler1, h_reg, l_reg;
} I8_reg_t;
#else /* !__BIG_ENDIAN__ */
typedef struct {
u32 e_reg;
} I32_reg_t;
typedef struct {
u16 x_reg;
} I16_reg_t;
typedef struct {
u8 l_reg, h_reg;
} I8_reg_t;
#endif /* BIG_ENDIAN */
typedef union {
I32_reg_t I32_reg;
I16_reg_t I16_reg;
I8_reg_t I8_reg;
} i386_general_register;
struct i386_general_regs {
i386_general_register A, B, C, D;
};
typedef struct i386_general_regs Gen_reg_t;
struct i386_special_regs {
i386_general_register SP, BP, SI, DI, IP;
u32 FLAGS;
};
/*
* Segment registers here represent the 16 bit quantities
* CS, DS, ES, SS.
*/
struct i386_segment_regs {
u16 CS, DS, SS, ES, FS, GS;
};
/* 8 bit registers */
#define R_AH gen.A.I8_reg.h_reg
#define R_AL gen.A.I8_reg.l_reg
#define R_BH gen.B.I8_reg.h_reg
#define R_BL gen.B.I8_reg.l_reg
#define R_CH gen.C.I8_reg.h_reg
#define R_CL gen.C.I8_reg.l_reg
#define R_DH gen.D.I8_reg.h_reg
#define R_DL gen.D.I8_reg.l_reg
/* 16 bit registers */
#define R_AX gen.A.I16_reg.x_reg
#define R_BX gen.B.I16_reg.x_reg
#define R_CX gen.C.I16_reg.x_reg
#define R_DX gen.D.I16_reg.x_reg
/* 32 bit extended registers */
#define R_EAX gen.A.I32_reg.e_reg
#define R_EBX gen.B.I32_reg.e_reg
#define R_ECX gen.C.I32_reg.e_reg
#define R_EDX gen.D.I32_reg.e_reg
/* special registers */
#define R_SP spc.SP.I16_reg.x_reg
#define R_BP spc.BP.I16_reg.x_reg
#define R_SI spc.SI.I16_reg.x_reg
#define R_DI spc.DI.I16_reg.x_reg
#define R_IP spc.IP.I16_reg.x_reg
#define R_FLG spc.FLAGS
/* special registers */
#define R_SP spc.SP.I16_reg.x_reg
#define R_BP spc.BP.I16_reg.x_reg
#define R_SI spc.SI.I16_reg.x_reg
#define R_DI spc.DI.I16_reg.x_reg
#define R_IP spc.IP.I16_reg.x_reg
#define R_FLG spc.FLAGS
/* special registers */
#define R_ESP spc.SP.I32_reg.e_reg
#define R_EBP spc.BP.I32_reg.e_reg
#define R_ESI spc.SI.I32_reg.e_reg
#define R_EDI spc.DI.I32_reg.e_reg
#define R_EIP spc.IP.I32_reg.e_reg
#define R_EFLG spc.FLAGS
/* segment registers */
#define R_CS seg.CS
#define R_DS seg.DS
#define R_SS seg.SS
#define R_ES seg.ES
#define R_FS seg.FS
#define R_GS seg.GS
/* flag conditions */
#define FB_CF 0x0001 /* CARRY flag */
#define FB_PF 0x0004 /* PARITY flag */
#define FB_AF 0x0010 /* AUX flag */
#define FB_ZF 0x0040 /* ZERO flag */
#define FB_SF 0x0080 /* SIGN flag */
#define FB_TF 0x0100 /* TRAP flag */
#define FB_IF 0x0200 /* INTERRUPT ENABLE flag */
#define FB_DF 0x0400 /* DIR flag */
#define FB_OF 0x0800 /* OVERFLOW flag */
/* 80286 and above always have bit#1 set */
#define F_ALWAYS_ON (0x0002) /* flag bits always on */
/*
* Define a mask for only those flag bits we will ever pass back
* (via PUSHF)
*/
#define F_MSK (FB_CF|FB_PF|FB_AF|FB_ZF|FB_SF|FB_TF|FB_IF|FB_DF|FB_OF)
/* following bits masked in to a 16bit quantity */
#define F_CF 0x0001 /* CARRY flag */
#define F_PF 0x0004 /* PARITY flag */
#define F_AF 0x0010 /* AUX flag */
#define F_ZF 0x0040 /* ZERO flag */
#define F_SF 0x0080 /* SIGN flag */
#define F_TF 0x0100 /* TRAP flag */
#define F_IF 0x0200 /* INTERRUPT ENABLE flag */
#define F_DF 0x0400 /* DIR flag */
#define F_OF 0x0800 /* OVERFLOW flag */
#define TOGGLE_FLAG(flag) (M.x86.R_FLG ^= (flag))
#define SET_FLAG(flag) (M.x86.R_FLG |= (flag))
#define CLEAR_FLAG(flag) (M.x86.R_FLG &= ~(flag))
#define ACCESS_FLAG(flag) (M.x86.R_FLG & (flag))
#define CLEARALL_FLAG(m) (M.x86.R_FLG = 0)
#define CONDITIONAL_SET_FLAG(COND,FLAG) \
if (COND) SET_FLAG(FLAG); else CLEAR_FLAG(FLAG)
#define F_PF_CALC 0x010000 /* PARITY flag has been calced */
#define F_ZF_CALC 0x020000 /* ZERO flag has been calced */
#define F_SF_CALC 0x040000 /* SIGN flag has been calced */
#define F_ALL_CALC 0xff0000 /* All have been calced */
/*
* Emulator machine state.
* Segment usage control.
*/
#define SYSMODE_SEG_DS_SS 0x00000001
#define SYSMODE_SEGOVR_CS 0x00000002
#define SYSMODE_SEGOVR_DS 0x00000004
#define SYSMODE_SEGOVR_ES 0x00000008
#define SYSMODE_SEGOVR_FS 0x00000010
#define SYSMODE_SEGOVR_GS 0x00000020
#define SYSMODE_SEGOVR_SS 0x00000040
#define SYSMODE_PREFIX_REPE 0x00000080
#define SYSMODE_PREFIX_REPNE 0x00000100
#define SYSMODE_PREFIX_DATA 0x00000200
#define SYSMODE_PREFIX_ADDR 0x00000400
#define SYSMODE_INTR_PENDING 0x10000000
#define SYSMODE_EXTRN_INTR 0x20000000
#define SYSMODE_HALTED 0x40000000
#define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | \
SYSMODE_SEGOVR_CS | \
SYSMODE_SEGOVR_DS | \
SYSMODE_SEGOVR_ES | \
SYSMODE_SEGOVR_FS | \
SYSMODE_SEGOVR_GS | \
SYSMODE_SEGOVR_SS)
#define SYSMODE_CLRMASK (SYSMODE_SEG_DS_SS | \
SYSMODE_SEGOVR_CS | \
SYSMODE_SEGOVR_DS | \
SYSMODE_SEGOVR_ES | \
SYSMODE_SEGOVR_FS | \
SYSMODE_SEGOVR_GS | \
SYSMODE_SEGOVR_SS | \
SYSMODE_PREFIX_DATA | \
SYSMODE_PREFIX_ADDR)
#define INTR_SYNCH 0x1
#define INTR_ASYNCH 0x2
#define INTR_HALTED 0x4
typedef struct {
struct i386_general_regs gen;
struct i386_special_regs spc;
struct i386_segment_regs seg;
/*
* MODE contains information on:
* REPE prefix 2 bits repe,repne
* SEGMENT overrides 5 bits normal,DS,SS,CS,ES
* Delayed flag set 3 bits (zero, signed, parity)
* reserved 6 bits
* interrupt # 8 bits instruction raised interrupt
* BIOS video segregs 4 bits
* Interrupt Pending 1 bits
* Extern interrupt 1 bits
* Halted 1 bits
*/
u32 mode;
volatile int intr; /* mask of pending interrupts */
int debug;
#ifdef DEBUG
int check;
u16 saved_ip;
u16 saved_cs;
int enc_pos;
int enc_str_pos;
char decode_buf[32]; /* encoded byte stream */
char decoded_buf[256]; /* disassembled strings */
#endif
u8 intno;
u8 __pad[3];
} X86EMU_regs;
/****************************************************************************
REMARKS:
Structure maintaining the emulator machine state.
MEMBERS:
mem_base - Base real mode memory for the emulator
abseg - Base for the absegment
mem_size - Size of the real mode memory block for the emulator
private - private data pointer
x86 - X86 registers
****************************************************************************/
typedef struct {
unsigned long mem_base;
unsigned long mem_size;
unsigned long abseg;
void* private;
X86EMU_regs x86;
} X86EMU_sysEnv;
#pragma pack()
/*----------------------------- Global Variables --------------------------*/
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
/* Global emulator machine state.
*
* We keep it global to avoid pointer dereferences in the code for speed.
*/
extern X86EMU_sysEnv _X86EMU_env;
#define M _X86EMU_env
/*-------------------------- Function Prototypes --------------------------*/
/* Function to log information at runtime */
//void printk(const char *fmt, ...);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_REGS_H */

View File

@ -0,0 +1,51 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1996-1999 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for x86 emulator type definitions.
*
****************************************************************************/
/* $XFree86: xc/extras/x86emu/include/x86emu/types.h,v 1.4 2000/09/26 15:56:44 tsi Exp $ */
#ifndef __X86EMU_TYPES_H
#define __X86EMU_TYPES_H
#include <linux/types.h>
/*---------------------- Macros and type definitions ----------------------*/
typedef int sint;
typedef u16 X86EMU_pioAddr;
#endif /* __X86EMU_TYPES_H */

View File

@ -0,0 +1,17 @@
License information
-------------------
The x86emu library is under a BSD style license, comaptible
with the XFree86 and X licenses used by XFree86. The
original x86emu libraries were under the GNU General Public
License. Due to license incompatibilities between the GPL
and the XFree86 license, the original authors of the code
decided to allow a license change. If you have submitted
code to the original x86emu project, and you don't agree
with the license change, please contact us and let you
know. Your code will be removed to comply with your wishes.
If you have any questions about this, please send email to
x86emu@linuxlabs.com or KendallB@scitechsoft.com for
clarification.

View File

@ -0,0 +1,6 @@
obj-y := decode.o fpu.o ops.o ops2.o prim_ops.o sys.o debug.o
INCS = -I$(obj)/. -I$(obj)/../../../../../../../../include -I$(obj)/../../../.. -I$(obj)/../../include -I$(obj)/../../include/x86emu
KBUILD_CFLAGS += -D__DRIVER__ -DFORCE_POST $(INCS)

View File

@ -0,0 +1,439 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: This file contains the code to handle debugging of the
* emulator.
*
****************************************************************************/
#include "x86emu/x86emui.h"
#include <stdarg.h>
/*----------------------------- Implementation ----------------------------*/
#ifdef DEBUG
static void print_encoded_bytes (u16 s, u16 o);
static void print_decoded_instruction (void);
static int parse_line (char *s, int *ps, int *n);
/* should look something like debug's output. */
void X86EMU_trace_regs (void)
{
if (DEBUG_TRACE()) {
x86emu_dump_regs();
}
if (DEBUG_DECODE() && ! DEBUG_DECODE_NOPRINT()) {
rom_printk("%04x:%04x ",M.x86.saved_cs, M.x86.saved_ip);
print_encoded_bytes( M.x86.saved_cs, M.x86.saved_ip);
print_decoded_instruction();
}
}
void X86EMU_trace_xregs (void)
{
if (DEBUG_TRACE()) {
x86emu_dump_xregs();
}
}
void x86emu_just_disassemble (void)
{
/*
* This routine called if the flag DEBUG_DISASSEMBLE is set kind
* of a hack!
*/
rom_printk("%04x:%04x ",M.x86.saved_cs, M.x86.saved_ip);
print_encoded_bytes( M.x86.saved_cs, M.x86.saved_ip);
print_decoded_instruction();
}
static void disassemble_forward (u16 seg, u16 off, int n)
{
X86EMU_sysEnv tregs;
int i;
u8 op1;
/*
* hack, hack, hack. What we do is use the exact machinery set up
* for execution, except that now there is an additional state
* flag associated with the "execution", and we are using a copy
* of the register struct. All the major opcodes, once fully
* decoded, have the following two steps: TRACE_REGS(r,m);
* SINGLE_STEP(r,m); which disappear if DEBUG is not defined to
* the preprocessor. The TRACE_REGS macro expands to:
*
* if (debug&DEBUG_DISASSEMBLE)
* {just_disassemble(); goto EndOfInstruction;}
* if (debug&DEBUG_TRACE) trace_regs(r,m);
*
* ...... and at the last line of the routine.
*
* EndOfInstruction: end_instr();
*
* Up to the point where TRACE_REG is expanded, NO modifications
* are done to any register EXCEPT the IP register, for fetch and
* decoding purposes.
*
* This was done for an entirely different reason, but makes a
* nice way to get the system to help debug codes.
*/
tregs = M;
tregs.x86.R_IP = off;
tregs.x86.R_CS = seg;
/* reset the decoding buffers */
tregs.x86.enc_str_pos = 0;
tregs.x86.enc_pos = 0;
/* turn on the "disassemble only, no execute" flag */
tregs.x86.debug |= DEBUG_DISASSEMBLE_F;
/* DUMP NEXT n instructions to screen in straight_line fashion */
/*
* This looks like the regular instruction fetch stream, except
* that when this occurs, each fetched opcode, upon seeing the
* DEBUG_DISASSEMBLE flag set, exits immediately after decoding
* the instruction. XXX --- CHECK THAT MEM IS NOT AFFECTED!!!
* Note the use of a copy of the register structure...
*/
for (i=0; i<n; i++) {
op1 = (*sys_rdb)(((u32)M.x86.R_CS<<4) + (M.x86.R_IP++));
(x86emu_optab[op1])(op1);
}
/* end major hack mode. */
}
void x86emu_check_ip_access (void)
{
/* NULL as of now */
}
void x86emu_check_sp_access (void)
{
}
void x86emu_check_mem_access (u32 dummy)
{
/* check bounds, etc */
}
void x86emu_check_data_access (uint dummy1, uint dummy2)
{
/* check bounds, etc */
}
void x86emu_inc_decoded_inst_len (int x)
{
M.x86.enc_pos += x;
}
void x86emu_decode_printf (char *x)
{
rom_sprintk(M.x86.decoded_buf+M.x86.enc_str_pos,"%s",x);
M.x86.enc_str_pos += rom_strlen(x);
}
void x86emu_decode_printf2 (char *x, int y)
{
char temp[100];
rom_sprintk(temp,x,y);
rom_sprintk(M.x86.decoded_buf+M.x86.enc_str_pos,"%s",temp);
M.x86.enc_str_pos += rom_strlen(temp);
}
void x86emu_end_instr (void)
{
M.x86.enc_str_pos = 0;
M.x86.enc_pos = 0;
}
static void print_encoded_bytes (u16 s, u16 o)
{
int i;
char buf1[64];
for (i=0; i< M.x86.enc_pos; i++) {
rom_sprintk(buf1+2*i,"%02x", fetch_data_byte_abs(s,o+i));
}
rom_printk("%s",buf1);
}
static void print_decoded_instruction (void)
{
rom_printk("%s", M.x86.decoded_buf);
}
void x86emu_print_int_vect (u16 iv)
{
u16 seg,off;
if (iv > 256) return;
seg = fetch_data_word_abs(0,iv*4);
off = fetch_data_word_abs(0,iv*4+2);
rom_printk("%04x:%04x ", seg, off);
}
void X86EMU_dump_memory (u16 seg, u16 off, u32 amt)
{
u32 start = off & 0xfffffff0;
u32 end = (off+16) & 0xfffffff0;
u32 i;
u32 current;
current = start;
while (end <= off + amt) {
rom_printk("%04x:%04x ", seg, start);
for (i=start; i< off; i++)
rom_printk(" ");
for ( ; i< end; i++)
rom_printk("%02x ", fetch_data_byte_abs(seg,i));
rom_printk("\n");
start = end;
end = start + 16;
}
}
#if 0
void x86emu_single_step (void)
{
char s[1024];
int ps[10];
int ntok;
int cmd;
int done;
int segment;
int offset;
static int breakpoint;
static int noDecode = 1;
char *p;
if (DEBUG_BREAK()) {
if (M.x86.saved_ip != breakpoint) {
return;
} else {
M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
M.x86.debug |= DEBUG_TRACE_F;
M.x86.debug &= ~DEBUG_BREAK_F;
print_decoded_instruction ();
X86EMU_trace_regs();
}
}
done=0;
offset = M.x86.saved_ip;
while (!done) {
rom_printk("-");
p = fgets(s, 1023, stdin);
cmd = parse_line(s, ps, &ntok);
switch(cmd) {
case 'u':
disassemble_forward(M.x86.saved_cs,(u16)offset,10);
break;
case 'd':
if (ntok == 2) {
segment = M.x86.saved_cs;
offset = ps[1];
X86EMU_dump_memory(segment,(u16)offset,16);
offset += 16;
} else if (ntok == 3) {
segment = ps[1];
offset = ps[2];
X86EMU_dump_memory(segment,(u16)offset,16);
offset += 16;
} else {
segment = M.x86.saved_cs;
X86EMU_dump_memory(segment,(u16)offset,16);
offset += 16;
}
break;
case 'c':
M.x86.debug ^= DEBUG_TRACECALL_F;
break;
case 's':
M.x86.debug ^= DEBUG_SVC_F | DEBUG_SYS_F | DEBUG_SYSINT_F;
break;
case 'r':
X86EMU_trace_regs();
break;
case 'x':
X86EMU_trace_xregs();
break;
case 'g':
if (ntok == 2) {
breakpoint = ps[1];
if (noDecode) {
M.x86.debug |= DEBUG_DECODE_NOPRINT_F;
} else {
M.x86.debug &= ~DEBUG_DECODE_NOPRINT_F;
}
M.x86.debug &= ~DEBUG_TRACE_F;
M.x86.debug |= DEBUG_BREAK_F;
done = 1;
}
break;
case 'q':
M.x86.debug |= DEBUG_EXIT;
return;
case 'P':
noDecode = (noDecode)?0:1;
rom_printk("Toggled decoding to %s\n",(noDecode)?"FALSE":"TRUE");
break;
case 't':
case 0:
done = 1;
break;
}
}
}
#endif
int X86EMU_trace_on(void)
{
return M.x86.debug |= DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F;
}
int X86EMU_trace_off(void)
{
return M.x86.debug &= ~(DEBUG_STEP_F | DEBUG_DECODE_F | DEBUG_TRACE_F);
}
int X86EMU_set_debug(int debug)
{
return M.x86.debug = debug;
}
#if 0
static int parse_line (char *s, int *ps, int *n)
{
int cmd;
*n = 0;
while(*s == ' ' || *s == '\t') s++;
ps[*n] = *s;
switch (*s) {
case '\n':
*n += 1;
return 0;
default:
cmd = *s;
*n += 1;
}
while (1) {
while (*s != ' ' && *s != '\t' && *s != '\n') s++;
if (*s == '\n')
return cmd;
while(*s == ' ' || *s == '\t') s++;
sscanf(s,"%x",&ps[*n]);
*n += 1;
}
}
#endif
#endif /* DEBUG */
void x86emu_dump_regs (void)
{
rom_printk("\tAX=%04x ", M.x86.R_AX );
rom_printk("BX=%04x ", M.x86.R_BX );
rom_printk("CX=%04x ", M.x86.R_CX );
rom_printk("DX=%04x ", M.x86.R_DX );
rom_printk("SP=%04x ", M.x86.R_SP );
rom_printk("BP=%04x ", M.x86.R_BP );
rom_printk("SI=%04x ", M.x86.R_SI );
rom_printk("DI=%04x\n", M.x86.R_DI );
rom_printk("\tDS=%04x ", M.x86.R_DS );
rom_printk("ES=%04x ", M.x86.R_ES );
rom_printk("SS=%04x ", M.x86.R_SS );
rom_printk("CS=%04x ", M.x86.R_CS );
rom_printk("IP=%04x ", M.x86.R_IP );
if (ACCESS_FLAG(F_OF)) rom_printk("OV "); /* CHECKED... */
else rom_printk("NV ");
if (ACCESS_FLAG(F_DF)) rom_printk("DN ");
else rom_printk("UP ");
if (ACCESS_FLAG(F_IF)) rom_printk("EI ");
else rom_printk("DI ");
if (ACCESS_FLAG(F_SF)) rom_printk("NG ");
else rom_printk("PL ");
if (ACCESS_FLAG(F_ZF)) rom_printk("ZR ");
else rom_printk("NZ ");
if (ACCESS_FLAG(F_AF)) rom_printk("AC ");
else rom_printk("NA ");
if (ACCESS_FLAG(F_PF)) rom_printk("PE ");
else rom_printk("PO ");
if (ACCESS_FLAG(F_CF)) rom_printk("CY ");
else rom_printk("NC ");
rom_printk("\n");
}
void x86emu_dump_xregs (void)
{
rom_printk("\tEAX=%08x ", M.x86.R_EAX );
rom_printk("EBX=%08x ", M.x86.R_EBX );
rom_printk("ECX=%08x ", M.x86.R_ECX );
rom_printk("EDX=%08x \n", M.x86.R_EDX );
rom_printk("\tESP=%08x ", M.x86.R_ESP );
rom_printk("EBP=%08x ", M.x86.R_EBP );
rom_printk("ESI=%08x ", M.x86.R_ESI );
rom_printk("EDI=%08x\n", M.x86.R_EDI );
rom_printk("\tDS=%04x ", M.x86.R_DS );
rom_printk("ES=%04x ", M.x86.R_ES );
rom_printk("SS=%04x ", M.x86.R_SS );
rom_printk("CS=%04x ", M.x86.R_CS );
rom_printk("EIP=%08x\n\t", M.x86.R_EIP );
if (ACCESS_FLAG(F_OF)) rom_printk("OV "); /* CHECKED... */
else rom_printk("NV ");
if (ACCESS_FLAG(F_DF)) rom_printk("DN ");
else rom_printk("UP ");
if (ACCESS_FLAG(F_IF)) rom_printk("EI ");
else rom_printk("DI ");
if (ACCESS_FLAG(F_SF)) rom_printk("NG ");
else rom_printk("PL ");
if (ACCESS_FLAG(F_ZF)) rom_printk("ZR ");
else rom_printk("NZ ");
if (ACCESS_FLAG(F_AF)) rom_printk("AC ");
else rom_printk("NA ");
if (ACCESS_FLAG(F_PF)) rom_printk("PE ");
else rom_printk("PO ");
if (ACCESS_FLAG(F_CF)) rom_printk("CY ");
else rom_printk("NC ");
rom_printk("\n");
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,945 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: This file contains the code to implement the decoding and
* emulation of the FPU instructions.
*
****************************************************************************/
#include "x86emu/x86emui.h"
/*----------------------------- Implementation ----------------------------*/
/* opcode=0xd8 */
void x86emuOp_esc_coprocess_d8(u8 X86EMU_UNUSED(op1))
{
START_OF_INSTR();
DECODE_PRINTF("ESC D8\n");
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}
#ifdef DEBUG
static char *x86emu_fpu_op_d9_tab[] = {
"FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
"FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
"FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
"FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
"FLD\tDWORD PTR ", "ESC_D9\t", "FST\tDWORD PTR ", "FSTP\tDWORD PTR ",
"FLDENV\t", "FLDCW\t", "FSTENV\t", "FSTCW\t",
};
static char *x86emu_fpu_op_d9_tab1[] = {
"FLD\t", "FLD\t", "FLD\t", "FLD\t",
"FLD\t", "FLD\t", "FLD\t", "FLD\t",
"FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
"FXCH\t", "FXCH\t", "FXCH\t", "FXCH\t",
"FNOP", "ESC_D9", "ESC_D9", "ESC_D9",
"ESC_D9", "ESC_D9", "ESC_D9", "ESC_D9",
"FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
"FSTP\t", "FSTP\t", "FSTP\t", "FSTP\t",
"FCHS", "FABS", "ESC_D9", "ESC_D9",
"FTST", "FXAM", "ESC_D9", "ESC_D9",
"FLD1", "FLDL2T", "FLDL2E", "FLDPI",
"FLDLG2", "FLDLN2", "FLDZ", "ESC_D9",
"F2XM1", "FYL2X", "FPTAN", "FPATAN",
"FXTRACT", "ESC_D9", "FDECSTP", "FINCSTP",
"FPREM", "FYL2XP1", "FSQRT", "ESC_D9",
"FRNDINT", "FSCALE", "ESC_D9", "ESC_D9",
};
#endif /* DEBUG */
/* opcode=0xd9 */
void x86emuOp_esc_coprocess_d9(u8 X86EMU_UNUSED(op1))
{
int mod, rl, rh;
uint destoffset;
u8 stkelem;
START_OF_INSTR();
FETCH_DECODE_MODRM(mod, rh, rl);
#ifdef DEBUG
if (mod != 3) {
DECODE_PRINTINSTR32(x86emu_fpu_op_d9_tab, mod, rh, rl);
} else {
DECODE_PRINTF(x86emu_fpu_op_d9_tab1[(rh << 3) + rl]);
}
#endif
switch (mod) {
case 0:
destoffset = decode_rm00_address(rl);
DECODE_PRINTF("\n");
break;
case 1:
destoffset = decode_rm01_address(rl);
DECODE_PRINTF("\n");
break;
case 2:
destoffset = decode_rm10_address(rl);
DECODE_PRINTF("\n");
break;
case 3: /* register to register */
stkelem = (u8)rl;
if (rh < 4) {
DECODE_PRINTF2("ST(%d)\n", stkelem);
} else {
DECODE_PRINTF("\n");
}
break;
}
#ifdef X86EMU_FPU_PRESENT
/* execute */
switch (mod) {
case 3:
switch (rh) {
case 0:
x86emu_fpu_R_fld(X86EMU_FPU_STKTOP, stkelem);
break;
case 1:
x86emu_fpu_R_fxch(X86EMU_FPU_STKTOP, stkelem);
break;
case 2:
switch (rl) {
case 0:
x86emu_fpu_R_nop();
break;
default:
x86emu_fpu_illegal();
break;
}
case 3:
x86emu_fpu_R_fstp(X86EMU_FPU_STKTOP, stkelem);
break;
case 4:
switch (rl) {
case 0:
x86emu_fpu_R_fchs(X86EMU_FPU_STKTOP);
break;
case 1:
x86emu_fpu_R_fabs(X86EMU_FPU_STKTOP);
break;
case 4:
x86emu_fpu_R_ftst(X86EMU_FPU_STKTOP);
break;
case 5:
x86emu_fpu_R_fxam(X86EMU_FPU_STKTOP);
break;
default:
/* 2,3,6,7 */
x86emu_fpu_illegal();
break;
}
break;
case 5:
switch (rl) {
case 0:
x86emu_fpu_R_fld1(X86EMU_FPU_STKTOP);
break;
case 1:
x86emu_fpu_R_fldl2t(X86EMU_FPU_STKTOP);
break;
case 2:
x86emu_fpu_R_fldl2e(X86EMU_FPU_STKTOP);
break;
case 3:
x86emu_fpu_R_fldpi(X86EMU_FPU_STKTOP);
break;
case 4:
x86emu_fpu_R_fldlg2(X86EMU_FPU_STKTOP);
break;
case 5:
x86emu_fpu_R_fldln2(X86EMU_FPU_STKTOP);
break;
case 6:
x86emu_fpu_R_fldz(X86EMU_FPU_STKTOP);
break;
default:
/* 7 */
x86emu_fpu_illegal();
break;
}
break;
case 6:
switch (rl) {
case 0:
x86emu_fpu_R_f2xm1(X86EMU_FPU_STKTOP);
break;
case 1:
x86emu_fpu_R_fyl2x(X86EMU_FPU_STKTOP);
break;
case 2:
x86emu_fpu_R_fptan(X86EMU_FPU_STKTOP);
break;
case 3:
x86emu_fpu_R_fpatan(X86EMU_FPU_STKTOP);
break;
case 4:
x86emu_fpu_R_fxtract(X86EMU_FPU_STKTOP);
break;
case 5:
x86emu_fpu_illegal();
break;
case 6:
x86emu_fpu_R_decstp();
break;
case 7:
x86emu_fpu_R_incstp();
break;
}
break;
case 7:
switch (rl) {
case 0:
x86emu_fpu_R_fprem(X86EMU_FPU_STKTOP);
break;
case 1:
x86emu_fpu_R_fyl2xp1(X86EMU_FPU_STKTOP);
break;
case 2:
x86emu_fpu_R_fsqrt(X86EMU_FPU_STKTOP);
break;
case 3:
x86emu_fpu_illegal();
break;
case 4:
x86emu_fpu_R_frndint(X86EMU_FPU_STKTOP);
break;
case 5:
x86emu_fpu_R_fscale(X86EMU_FPU_STKTOP);
break;
case 6:
case 7:
default:
x86emu_fpu_illegal();
break;
}
break;
default:
switch (rh) {
case 0:
x86emu_fpu_M_fld(X86EMU_FPU_FLOAT, destoffset);
break;
case 1:
x86emu_fpu_illegal();
break;
case 2:
x86emu_fpu_M_fst(X86EMU_FPU_FLOAT, destoffset);
break;
case 3:
x86emu_fpu_M_fstp(X86EMU_FPU_FLOAT, destoffset);
break;
case 4:
x86emu_fpu_M_fldenv(X86EMU_FPU_WORD, destoffset);
break;
case 5:
x86emu_fpu_M_fldcw(X86EMU_FPU_WORD, destoffset);
break;
case 6:
x86emu_fpu_M_fstenv(X86EMU_FPU_WORD, destoffset);
break;
case 7:
x86emu_fpu_M_fstcw(X86EMU_FPU_WORD, destoffset);
break;
}
}
}
#endif /* X86EMU_FPU_PRESENT */
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}
#ifdef DEBUG
char *x86emu_fpu_op_da_tab[] = {
"FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
"FICOMP\tDWORD PTR ",
"FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
"FIDIVR\tDWORD PTR ",
"FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
"FICOMP\tDWORD PTR ",
"FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
"FIDIVR\tDWORD PTR ",
"FIADD\tDWORD PTR ", "FIMUL\tDWORD PTR ", "FICOM\tDWORD PTR ",
"FICOMP\tDWORD PTR ",
"FISUB\tDWORD PTR ", "FISUBR\tDWORD PTR ", "FIDIV\tDWORD PTR ",
"FIDIVR\tDWORD PTR ",
"ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ",
"ESC_DA ", "ESC_DA ", "ESC_DA ", "ESC_DA ",
};
#endif /* DEBUG */
/* opcode=0xda */
void x86emuOp_esc_coprocess_da(u8 X86EMU_UNUSED(op1))
{
int mod, rl, rh;
uint destoffset;
u8 stkelem;
START_OF_INSTR();
FETCH_DECODE_MODRM(mod, rh, rl);
DECODE_PRINTINSTR32(x86emu_fpu_op_da_tab, mod, rh, rl);
switch (mod) {
case 0:
destoffset = decode_rm00_address(rl);
DECODE_PRINTF("\n");
break;
case 1:
destoffset = decode_rm01_address(rl);
DECODE_PRINTF("\n");
break;
case 2:
destoffset = decode_rm10_address(rl);
DECODE_PRINTF("\n");
break;
case 3: /* register to register */
stkelem = (u8)rl;
DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
break;
}
#ifdef X86EMU_FPU_PRESENT
switch (mod) {
case 3:
x86emu_fpu_illegal();
break;
default:
switch (rh) {
case 0:
x86emu_fpu_M_iadd(X86EMU_FPU_SHORT, destoffset);
break;
case 1:
x86emu_fpu_M_imul(X86EMU_FPU_SHORT, destoffset);
break;
case 2:
x86emu_fpu_M_icom(X86EMU_FPU_SHORT, destoffset);
break;
case 3:
x86emu_fpu_M_icomp(X86EMU_FPU_SHORT, destoffset);
break;
case 4:
x86emu_fpu_M_isub(X86EMU_FPU_SHORT, destoffset);
break;
case 5:
x86emu_fpu_M_isubr(X86EMU_FPU_SHORT, destoffset);
break;
case 6:
x86emu_fpu_M_idiv(X86EMU_FPU_SHORT, destoffset);
break;
case 7:
x86emu_fpu_M_idivr(X86EMU_FPU_SHORT, destoffset);
break;
}
}
#endif
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}
#ifdef DEBUG
char *x86emu_fpu_op_db_tab[] = {
"FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
"ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
"FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
"ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
"FILD\tDWORD PTR ", "ESC_DB\t19", "FIST\tDWORD PTR ", "FISTP\tDWORD PTR ",
"ESC_DB\t1C", "FLD\tTBYTE PTR ", "ESC_DB\t1E", "FSTP\tTBYTE PTR ",
};
#endif /* DEBUG */
/* opcode=0xdb */
void x86emuOp_esc_coprocess_db(u8 X86EMU_UNUSED(op1))
{
int mod, rl, rh;
uint destoffset;
START_OF_INSTR();
FETCH_DECODE_MODRM(mod, rh, rl);
#ifdef DEBUG
if (mod != 3) {
DECODE_PRINTINSTR32(x86emu_fpu_op_db_tab, mod, rh, rl);
} else if (rh == 4) { /* === 11 10 0 nnn */
switch (rl) {
case 0:
DECODE_PRINTF("FENI\n");
break;
case 1:
DECODE_PRINTF("FDISI\n");
break;
case 2:
DECODE_PRINTF("FCLEX\n");
break;
case 3:
DECODE_PRINTF("FINIT\n");
break;
}
} else {
DECODE_PRINTF2("ESC_DB %0x\n", (mod << 6) + (rh << 3) + (rl));
}
#endif /* DEBUG */
switch (mod) {
case 0:
destoffset = decode_rm00_address(rl);
break;
case 1:
destoffset = decode_rm01_address(rl);
break;
case 2:
destoffset = decode_rm10_address(rl);
break;
case 3: /* register to register */
break;
}
#ifdef X86EMU_FPU_PRESENT
/* execute */
switch (mod) {
case 3:
switch (rh) {
case 4:
switch (rl) {
case 0:
x86emu_fpu_R_feni();
break;
case 1:
x86emu_fpu_R_fdisi();
break;
case 2:
x86emu_fpu_R_fclex();
break;
case 3:
x86emu_fpu_R_finit();
break;
default:
x86emu_fpu_illegal();
break;
}
break;
default:
x86emu_fpu_illegal();
break;
}
break;
default:
switch (rh) {
case 0:
x86emu_fpu_M_fild(X86EMU_FPU_SHORT, destoffset);
break;
case 1:
x86emu_fpu_illegal();
break;
case 2:
x86emu_fpu_M_fist(X86EMU_FPU_SHORT, destoffset);
break;
case 3:
x86emu_fpu_M_fistp(X86EMU_FPU_SHORT, destoffset);
break;
case 4:
x86emu_fpu_illegal();
break;
case 5:
x86emu_fpu_M_fld(X86EMU_FPU_LDBL, destoffset);
break;
case 6:
x86emu_fpu_illegal();
break;
case 7:
x86emu_fpu_M_fstp(X86EMU_FPU_LDBL, destoffset);
break;
}
}
#endif
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}
#ifdef DEBUG
char *x86emu_fpu_op_dc_tab[] = {
"FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
"FCOMP\tQWORD PTR ",
"FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
"FDIVR\tQWORD PTR ",
"FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
"FCOMP\tQWORD PTR ",
"FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
"FDIVR\tQWORD PTR ",
"FADD\tQWORD PTR ", "FMUL\tQWORD PTR ", "FCOM\tQWORD PTR ",
"FCOMP\tQWORD PTR ",
"FSUB\tQWORD PTR ", "FSUBR\tQWORD PTR ", "FDIV\tQWORD PTR ",
"FDIVR\tQWORD PTR ",
"FADD\t", "FMUL\t", "FCOM\t", "FCOMP\t",
"FSUBR\t", "FSUB\t", "FDIVR\t", "FDIV\t",
};
#endif /* DEBUG */
/* opcode=0xdc */
void x86emuOp_esc_coprocess_dc(u8 X86EMU_UNUSED(op1))
{
int mod, rl, rh;
uint destoffset;
u8 stkelem;
START_OF_INSTR();
FETCH_DECODE_MODRM(mod, rh, rl);
DECODE_PRINTINSTR32(x86emu_fpu_op_dc_tab, mod, rh, rl);
switch (mod) {
case 0:
destoffset = decode_rm00_address(rl);
DECODE_PRINTF("\n");
break;
case 1:
destoffset = decode_rm01_address(rl);
DECODE_PRINTF("\n");
break;
case 2:
destoffset = decode_rm10_address(rl);
DECODE_PRINTF("\n");
break;
case 3: /* register to register */
stkelem = (u8)rl;
DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
break;
}
#ifdef X86EMU_FPU_PRESENT
/* execute */
switch (mod) {
case 3:
switch (rh) {
case 0:
x86emu_fpu_R_fadd(stkelem, X86EMU_FPU_STKTOP);
break;
case 1:
x86emu_fpu_R_fmul(stkelem, X86EMU_FPU_STKTOP);
break;
case 2:
x86emu_fpu_R_fcom(stkelem, X86EMU_FPU_STKTOP);
break;
case 3:
x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
break;
case 4:
x86emu_fpu_R_fsubr(stkelem, X86EMU_FPU_STKTOP);
break;
case 5:
x86emu_fpu_R_fsub(stkelem, X86EMU_FPU_STKTOP);
break;
case 6:
x86emu_fpu_R_fdivr(stkelem, X86EMU_FPU_STKTOP);
break;
case 7:
x86emu_fpu_R_fdiv(stkelem, X86EMU_FPU_STKTOP);
break;
}
break;
default:
switch (rh) {
case 0:
x86emu_fpu_M_fadd(X86EMU_FPU_DOUBLE, destoffset);
break;
case 1:
x86emu_fpu_M_fmul(X86EMU_FPU_DOUBLE, destoffset);
break;
case 2:
x86emu_fpu_M_fcom(X86EMU_FPU_DOUBLE, destoffset);
break;
case 3:
x86emu_fpu_M_fcomp(X86EMU_FPU_DOUBLE, destoffset);
break;
case 4:
x86emu_fpu_M_fsub(X86EMU_FPU_DOUBLE, destoffset);
break;
case 5:
x86emu_fpu_M_fsubr(X86EMU_FPU_DOUBLE, destoffset);
break;
case 6:
x86emu_fpu_M_fdiv(X86EMU_FPU_DOUBLE, destoffset);
break;
case 7:
x86emu_fpu_M_fdivr(X86EMU_FPU_DOUBLE, destoffset);
break;
}
}
#endif
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}
#ifdef DEBUG
static char *x86emu_fpu_op_dd_tab[] = {
"FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
"FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
"FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
"FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
"FLD\tQWORD PTR ", "ESC_DD\t29,", "FST\tQWORD PTR ", "FSTP\tQWORD PTR ",
"FRSTOR\t", "ESC_DD\t2D,", "FSAVE\t", "FSTSW\t",
"FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
"ESC_DD\t2C,", "ESC_DD\t2D,", "ESC_DD\t2E,", "ESC_DD\t2F,",
};
#endif /* DEBUG */
/* opcode=0xdd */
void x86emuOp_esc_coprocess_dd(u8 X86EMU_UNUSED(op1))
{
int mod, rl, rh;
uint destoffset;
u8 stkelem;
START_OF_INSTR();
FETCH_DECODE_MODRM(mod, rh, rl);
DECODE_PRINTINSTR32(x86emu_fpu_op_dd_tab, mod, rh, rl);
switch (mod) {
case 0:
destoffset = decode_rm00_address(rl);
DECODE_PRINTF("\n");
break;
case 1:
destoffset = decode_rm01_address(rl);
DECODE_PRINTF("\n");
break;
case 2:
destoffset = decode_rm10_address(rl);
DECODE_PRINTF("\n");
break;
case 3: /* register to register */
stkelem = (u8)rl;
DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
break;
}
#ifdef X86EMU_FPU_PRESENT
switch (mod) {
case 3:
switch (rh) {
case 0:
x86emu_fpu_R_ffree(stkelem);
break;
case 1:
x86emu_fpu_R_fxch(stkelem);
break;
case 2:
x86emu_fpu_R_fst(stkelem); /* register version */
break;
case 3:
x86emu_fpu_R_fstp(stkelem); /* register version */
break;
default:
x86emu_fpu_illegal();
break;
}
break;
default:
switch (rh) {
case 0:
x86emu_fpu_M_fld(X86EMU_FPU_DOUBLE, destoffset);
break;
case 1:
x86emu_fpu_illegal();
break;
case 2:
x86emu_fpu_M_fst(X86EMU_FPU_DOUBLE, destoffset);
break;
case 3:
x86emu_fpu_M_fstp(X86EMU_FPU_DOUBLE, destoffset);
break;
case 4:
x86emu_fpu_M_frstor(X86EMU_FPU_WORD, destoffset);
break;
case 5:
x86emu_fpu_illegal();
break;
case 6:
x86emu_fpu_M_fsave(X86EMU_FPU_WORD, destoffset);
break;
case 7:
x86emu_fpu_M_fstsw(X86EMU_FPU_WORD, destoffset);
break;
}
}
#endif
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}
#ifdef DEBUG
static char *x86emu_fpu_op_de_tab[] =
{
"FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
"FICOMP\tWORD PTR ",
"FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
"FIDIVR\tWORD PTR ",
"FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
"FICOMP\tWORD PTR ",
"FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
"FIDIVR\tWORD PTR ",
"FIADD\tWORD PTR ", "FIMUL\tWORD PTR ", "FICOM\tWORD PTR ",
"FICOMP\tWORD PTR ",
"FISUB\tWORD PTR ", "FISUBR\tWORD PTR ", "FIDIV\tWORD PTR ",
"FIDIVR\tWORD PTR ",
"FADDP\t", "FMULP\t", "FCOMP\t", "FCOMPP\t",
"FSUBRP\t", "FSUBP\t", "FDIVRP\t", "FDIVP\t",
};
#endif /* DEBUG */
/* opcode=0xde */
void x86emuOp_esc_coprocess_de(u8 X86EMU_UNUSED(op1))
{
int mod, rl, rh;
uint destoffset;
u8 stkelem;
START_OF_INSTR();
FETCH_DECODE_MODRM(mod, rh, rl);
DECODE_PRINTINSTR32(x86emu_fpu_op_de_tab, mod, rh, rl);
switch (mod) {
case 0:
destoffset = decode_rm00_address(rl);
DECODE_PRINTF("\n");
break;
case 1:
destoffset = decode_rm01_address(rl);
DECODE_PRINTF("\n");
break;
case 2:
destoffset = decode_rm10_address(rl);
DECODE_PRINTF("\n");
break;
case 3: /* register to register */
stkelem = (u8)rl;
DECODE_PRINTF2("\tST(%d),ST\n", stkelem);
break;
}
#ifdef X86EMU_FPU_PRESENT
switch (mod) {
case 3:
switch (rh) {
case 0:
x86emu_fpu_R_faddp(stkelem, X86EMU_FPU_STKTOP);
break;
case 1:
x86emu_fpu_R_fmulp(stkelem, X86EMU_FPU_STKTOP);
break;
case 2:
x86emu_fpu_R_fcomp(stkelem, X86EMU_FPU_STKTOP);
break;
case 3:
if (stkelem == 1)
x86emu_fpu_R_fcompp(stkelem, X86EMU_FPU_STKTOP);
else
x86emu_fpu_illegal();
break;
case 4:
x86emu_fpu_R_fsubrp(stkelem, X86EMU_FPU_STKTOP);
break;
case 5:
x86emu_fpu_R_fsubp(stkelem, X86EMU_FPU_STKTOP);
break;
case 6:
x86emu_fpu_R_fdivrp(stkelem, X86EMU_FPU_STKTOP);
break;
case 7:
x86emu_fpu_R_fdivp(stkelem, X86EMU_FPU_STKTOP);
break;
}
break;
default:
switch (rh) {
case 0:
x86emu_fpu_M_fiadd(X86EMU_FPU_WORD, destoffset);
break;
case 1:
x86emu_fpu_M_fimul(X86EMU_FPU_WORD, destoffset);
break;
case 2:
x86emu_fpu_M_ficom(X86EMU_FPU_WORD, destoffset);
break;
case 3:
x86emu_fpu_M_ficomp(X86EMU_FPU_WORD, destoffset);
break;
case 4:
x86emu_fpu_M_fisub(X86EMU_FPU_WORD, destoffset);
break;
case 5:
x86emu_fpu_M_fisubr(X86EMU_FPU_WORD, destoffset);
break;
case 6:
x86emu_fpu_M_fidiv(X86EMU_FPU_WORD, destoffset);
break;
case 7:
x86emu_fpu_M_fidivr(X86EMU_FPU_WORD, destoffset);
break;
}
}
#endif
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}
#ifdef DEBUG
static char *x86emu_fpu_op_df_tab[] = {
/* mod == 00 */
"FILD\tWORD PTR ", "ESC_DF\t39\n", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
"FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
"FISTP\tQWORD PTR ",
/* mod == 01 */
"FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
"FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
"FISTP\tQWORD PTR ",
/* mod == 10 */
"FILD\tWORD PTR ", "ESC_DF\t39 ", "FIST\tWORD PTR ", "FISTP\tWORD PTR ",
"FBLD\tTBYTE PTR ", "FILD\tQWORD PTR ", "FBSTP\tTBYTE PTR ",
"FISTP\tQWORD PTR ",
/* mod == 11 */
"FFREE\t", "FXCH\t", "FST\t", "FSTP\t",
"ESC_DF\t3C,", "ESC_DF\t3D,", "ESC_DF\t3E,", "ESC_DF\t3F,"
};
#endif /* DEBUG */
/* opcode=0xdf */
void x86emuOp_esc_coprocess_df(u8 X86EMU_UNUSED(op1))
{
int mod, rl, rh;
uint destoffset;
u8 stkelem;
START_OF_INSTR();
FETCH_DECODE_MODRM(mod, rh, rl);
DECODE_PRINTINSTR32(x86emu_fpu_op_df_tab, mod, rh, rl);
switch (mod) {
case 0:
destoffset = decode_rm00_address(rl);
DECODE_PRINTF("\n");
break;
case 1:
destoffset = decode_rm01_address(rl);
DECODE_PRINTF("\n");
break;
case 2:
destoffset = decode_rm10_address(rl);
DECODE_PRINTF("\n");
break;
case 3: /* register to register */
stkelem = (u8)rl;
DECODE_PRINTF2("\tST(%d)\n", stkelem);
break;
}
#ifdef X86EMU_FPU_PRESENT
switch (mod) {
case 3:
switch (rh) {
case 0:
x86emu_fpu_R_ffree(stkelem);
break;
case 1:
x86emu_fpu_R_fxch(stkelem);
break;
case 2:
x86emu_fpu_R_fst(stkelem); /* register version */
break;
case 3:
x86emu_fpu_R_fstp(stkelem); /* register version */
break;
default:
x86emu_fpu_illegal();
break;
}
break;
default:
switch (rh) {
case 0:
x86emu_fpu_M_fild(X86EMU_FPU_WORD, destoffset);
break;
case 1:
x86emu_fpu_illegal();
break;
case 2:
x86emu_fpu_M_fist(X86EMU_FPU_WORD, destoffset);
break;
case 3:
x86emu_fpu_M_fistp(X86EMU_FPU_WORD, destoffset);
break;
case 4:
x86emu_fpu_M_fbld(X86EMU_FPU_BSD, destoffset);
break;
case 5:
x86emu_fpu_M_fild(X86EMU_FPU_LONG, destoffset);
break;
case 6:
x86emu_fpu_M_fbstp(X86EMU_FPU_BSD, destoffset);
break;
case 7:
x86emu_fpu_M_fistp(X86EMU_FPU_LONG, destoffset);
break;
}
}
#endif
DECODE_CLEAR_SEGOVR();
END_OF_INSTR_NO_TRACE();
}

View File

@ -0,0 +1,63 @@
#############################################################################
#
# Realmode X86 Emulator Library
#
# Copyright (C) 1991-2004 SciTech Software, Inc.
#
# ========================================================================
#
# Permission to use, copy, modify, distribute, and sell this software and
# its documentation for any purpose is hereby granted without fee,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of the authors not be used
# in advertising or publicity pertaining to distribution of the software
# without specific, written prior permission. The authors makes no
# representations about the suitability of this software for any purpose.
# It is provided "as is" without express or implied warranty.
#
# THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
# EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
#
# ========================================================================
#
# Descripton: Generic makefile for the x86emu library. Requires
# the SciTech Software makefile definitions package to be
# installed, which uses the DMAKE make program.
#
#############################################################################
.IMPORT .IGNORE: DEBUG
#----------------------------------------------------------------------------
# Define the lists of object files
#----------------------------------------------------------------------------
OBJECTS = sys$O decode$O ops$O ops2$O prim_ops$O fpu$O debug$O
CFLAGS += -DSCITECH
.IF $(DEBUG)
CFLAGS += -DDEBUG
.ENDIF
LIBCLEAN = *.dll *.lib *.a
LIBFILE = $(LP)x86emu$L
#----------------------------------------------------------------------------
# Sample test programs
#----------------------------------------------------------------------------
all: $(LIBFILE)
validate$E: validate$O $(LIBFILE)
#----------------------------------------------------------------------------
# Define the list of object files to create dependency information for
#----------------------------------------------------------------------------
DEPEND_OBJ = validate$O $(OBJECTS)
.INCLUDE: "$(SCITECH)/makedefs/common.mk"

View File

@ -0,0 +1,73 @@
#############################################################################
#
# Realmode X86 Emulator Library
#
# Copyright (C) 1996-1999 SciTech Software, Inc.
#
# ========================================================================
#
# Permission to use, copy, modify, distribute, and sell this software and
# its documentation for any purpose is hereby granted without fee,
# provided that the above copyright notice appear in all copies and that
# both that copyright notice and this permission notice appear in
# supporting documentation, and that the name of the authors not be used
# in advertising or publicity pertaining to distribution of the software
# without specific, written prior permission. The authors makes no
# representations about the suitability of this software for any purpose.
# It is provided "as is" without express or implied warranty.
#
# THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
# EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
#
# ========================================================================
#
# Descripton: Linux specific makefile for the x86emu library.
#
#############################################################################
TARGETLIB = libx86emu.a
TARGETDEBUGLIB =libx86emud.a
OBJS=\
decode.o \
fpu.o \
ops.o \
ops2.o \
prim_ops.o \
sys.o \
debug.o
DEBUGOBJS=debug.d \
decode.d \
fpu.d \
ops.d \
ops2.d \
prim_ops.d \
sys.d
.SUFFIXES: .d
FORCE:
lib: $(TARGETLIB) # $(TARGETDEBUGLIB)
$(TARGETLIB): FORCE $(OBJS)
$(AR) rv $(TARGETLIB) $(OBJS)
$(TARGETDEBUGLIB): $(DEBUGOBJS)
$(AR) rv $(TARGETDEBUGLIB) $(DEBUGOBJS)
INCS = -I. -I../../../../../../../../include -I../../../.. -I../../include -I../../include/x86emu
#CFLAGS = -D__DRIVER__ -DFORCE_POST -D_CEXPORT= -DNO_LONG_LONG
CFLAGS += -D__DRIVER__ -DFORCE_POST $(INCS)
CDEBUGFLAGS = -DDEBUG
clean:
rm -f *.a *.o *.d

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,646 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1996-1999 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: This file includes subroutines which are related to
* programmed I/O and memory access. Included in this module
* are default functions with limited usefulness. For real
* uses these functions will most likely be overriden by the
* user library.
*
****************************************************************************/
/* $XFree86: xc/extras/x86emu/src/x86emu/sys.c,v 1.5 2000/08/23 22:10:01 tsi Exp $ */
#include "x86emu.h"
#include "x86emu/regs.h"
#include "x86emu/debug.h"
#include "x86emu/prim_ops.h"
#include "pci.h"
//#include <asm/io.h>
//#ifdef IN_MODULE
//#include "xf86_ansic.h"
//#else
//#include <string.h>
//#endif
/*------------------------- Global Variables ------------------------------*/
X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */
X86EMU_intrFuncs _X86EMU_intrTab[256];
/*----------------------------- Implementation ----------------------------*/
#if defined(__alpha__) || defined(__alpha)
/* to cope with broken egcs-1.1.2 :-(((( */
/*
* inline functions to do unaligned accesses
* from linux/include/asm-alpha/unaligned.h
*/
/*
* EGCS 1.1 knows about arbitrary unaligned loads. Define some
* packed structures to talk about such things with.
*/
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
struct __una_u64 {
unsigned long x __attribute__ ((packed));
};
struct __una_u32 {
unsigned int x __attribute__ ((packed));
};
struct __una_u16 {
unsigned short x __attribute__ ((packed));
};
#endif
static __inline__ unsigned long ldq_u(unsigned long *r11)
{
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
const struct __una_u64 *ptr = (const struct __una_u64 *) r11;
return ptr->x;
#else
unsigned long r1, r2;
__asm__("ldq_u %0,%3\n\t" "ldq_u %1,%4\n\t" "extql %0,%2,%0\n\t" "extqh %1,%2,%1":"=&r"(r1),
"=&r"
(r2)
: "r"(r11), "m"(*r11),
"m"(*(const unsigned long *) (7 + (char *) r11)));
return r1 | r2;
#endif
}
static __inline__ unsigned long ldl_u(unsigned int *r11)
{
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
const struct __una_u32 *ptr = (const struct __una_u32 *) r11;
return ptr->x;
#else
unsigned long r1, r2;
__asm__("ldq_u %0,%3\n\t" "ldq_u %1,%4\n\t" "extll %0,%2,%0\n\t" "extlh %1,%2,%1":"=&r"(r1),
"=&r"
(r2)
: "r"(r11), "m"(*r11),
"m"(*(const unsigned long *) (3 + (char *) r11)));
return r1 | r2;
#endif
}
static __inline__ unsigned long ldw_u(unsigned short *r11)
{
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
const struct __una_u16 *ptr = (const struct __una_u16 *) r11;
return ptr->x;
#else
unsigned long r1, r2;
__asm__("ldq_u %0,%3\n\t" "ldq_u %1,%4\n\t" "extwl %0,%2,%0\n\t" "extwh %1,%2,%1":"=&r"(r1),
"=&r"
(r2)
: "r"(r11), "m"(*r11),
"m"(*(const unsigned long *) (1 + (char *) r11)));
return r1 | r2;
#endif
}
/*
* Elemental unaligned stores
*/
static __inline__ void stq_u(unsigned long r5, unsigned long *r11)
{
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
struct __una_u64 *ptr = (struct __una_u64 *) r11;
ptr->x = r5;
#else
unsigned long r1, r2, r3, r4;
__asm__("ldq_u %3,%1\n\t" "ldq_u %2,%0\n\t" "insqh %6,%7,%5\n\t" "insql %6,%7,%4\n\t" "mskqh %3,%7,%3\n\t" "mskql %2,%7,%2\n\t" "bis %3,%5,%3\n\t" "bis %2,%4,%2\n\t" "stq_u %3,%1\n\t" "stq_u %2,%0":"=m"(*r11),
"=m"(*(unsigned long *) (7 + (char *) r11)),
"=&r"(r1), "=&r"(r2), "=&r"(r3), "=&r"(r4)
: "r"(r5), "r"(r11));
#endif
}
static __inline__ void stl_u(unsigned long r5, unsigned int *r11)
{
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
struct __una_u32 *ptr = (struct __una_u32 *) r11;
ptr->x = r5;
#else
unsigned long r1, r2, r3, r4;
__asm__("ldq_u %3,%1\n\t" "ldq_u %2,%0\n\t" "inslh %6,%7,%5\n\t" "insll %6,%7,%4\n\t" "msklh %3,%7,%3\n\t" "mskll %2,%7,%2\n\t" "bis %3,%5,%3\n\t" "bis %2,%4,%2\n\t" "stq_u %3,%1\n\t" "stq_u %2,%0":"=m"(*r11),
"=m"(*(unsigned long *) (3 + (char *) r11)),
"=&r"(r1), "=&r"(r2), "=&r"(r3), "=&r"(r4)
: "r"(r5), "r"(r11));
#endif
}
static __inline__ void stw_u(unsigned long r5, unsigned short *r11)
{
#if __GNUC__ > 2 || __GNUC_MINOR__ >= 91
struct __una_u16 *ptr = (struct __una_u16 *) r11;
ptr->x = r5;
#else
unsigned long r1, r2, r3, r4;
__asm__("ldq_u %3,%1\n\t" "ldq_u %2,%0\n\t" "inswh %6,%7,%5\n\t" "inswl %6,%7,%4\n\t" "mskwh %3,%7,%3\n\t" "mskwl %2,%7,%2\n\t" "bis %3,%5,%3\n\t" "bis %2,%4,%2\n\t" "stq_u %3,%1\n\t" "stq_u %2,%0":"=m"(*r11),
"=m"(*(unsigned long *) (1 + (char *) r11)),
"=&r"(r1), "=&r"(r2), "=&r"(r3), "=&r"(r4)
: "r"(r5), "r"(r11));
#endif
}
#endif
/* compute a pointer. This replaces code scattered all over the place! */
u8 *mem_ptr(u32 addr, int size)
{
u8 *retaddr = 0;
if (addr > M.mem_size - size) {
DB(rom_printk("mem_ptr: address %x out of range!\n", addr);
)
HALT_SYS();
}
/* a or b segment? */
/* & with e to clear low-order bit, if it is a or b it will be a */
if (((addr & 0xfffe0000) == 0xa0000) && M.abseg) {
//rom_printk("It's a0000\n");
addr &= ~0xfffe0000;
retaddr = (u8 *) (M.abseg + addr);
//rom_printk("retaddr now 0x%px\n", retaddr);
} else if (addr < 0x200) {
// rom_printk("addr 0x%x updating int vector 0x%x\n",
// addr, addr >> 2);
retaddr = (u8 *) (M.mem_base + addr);
} else {
retaddr = (u8 *) (M.mem_base + addr);
}
return retaddr;
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
RETURNS:
Byte value read from emulator memory.
REMARKS:
Reads a byte value from the emulator memory.
****************************************************************************/
u8 X86API rdb(u32 addr)
{
u8 val;
u8 *ptr;
ptr = mem_ptr(addr, 1);
val = *ptr;
DB(if (DEBUG_MEM_TRACE())
rom_printk("%x 1 -> %x\n", addr, val);)
return val;
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
RETURNS:
Word value read from emulator memory.
REMARKS:
Reads a word value from the emulator memory.
****************************************************************************/
u16 X86API rdw(u32 addr)
{
u16 val = 0;
u8 *ptr;
ptr = mem_ptr(addr, 2);
if (addr > M.mem_size - 2) {
DB(rom_printk("mem_read: address %x out of range!\n", (unsigned long) addr);
)
HALT_SYS();
}
#ifdef __BIG_ENDIAN__
if (addr & 0x1) {
val = (*ptr | (*(ptr + 1) << 8));
} else
#endif
#if defined(__alpha__) || defined(__alpha)
val = ldw_u((u16 *) (ptr));
#else
val = *(u16 *) (ptr);
#endif
DB(if (DEBUG_MEM_TRACE())
rom_printk("%x 2 -> %x\n", addr, val);)
return val;
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
RETURNS:
Long value read from emulator memory.
REMARKS:
Reads a long value from the emulator memory.
****************************************************************************/
u32 X86API rdl(u32 addr)
{
u32 val = 0;
u8 *ptr;
ptr = mem_ptr(addr, 4);
#ifdef __BIG_ENDIAN__
if (addr & 0x3) {
val = (*(u8 *) (ptr + 0) |
(*(u8 *) (ptr + 1) << 8) |
(*(u8 *) (ptr + 2) << 16) | (*(u8 *) (ptr + 3) << 24));
} else
#endif
#if defined(__alpha__) || defined(__alpha)
val = ldl_u((u32 *) (ptr));
#else
val = *(u32 *) (ptr);
#endif
DB(if (DEBUG_MEM_TRACE())
rom_printk("%x 4 -> %x\n", addr, val);)
return val;
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
val - Value to store
REMARKS:
Writes a byte value to emulator memory.
****************************************************************************/
void X86API wrb(u32 addr, u8 val)
{
u8 *ptr;
ptr = mem_ptr(addr, 1);
// if (addr >= 0xc0000 && addr < 0xd0000 ) {
// rom_printk("WARNING! Attempt to overwrite ROM 0x%x\n", addr);
// } else {
DB(if (DEBUG_MEM_TRACE())
rom_printk("%x 1 <- %x\n", addr, val);)
*(u8 *) (ptr) = val;
// }
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
val - Value to store
REMARKS:
Writes a word value to emulator memory.
****************************************************************************/
void X86API wrw(u32 addr, u16 val)
{
u8 *ptr;
ptr = mem_ptr(addr, 2);
// if (addr >= 0xc0000 && addr < 0xd0000 ) {
// rom_printk("WARNING! Attempt to overwrite ROM 0x%x\n", addr);
// } else {
DB(if (DEBUG_MEM_TRACE())
rom_printk("%x 2 <- %x\n", addr, val);)
#ifdef __BIG_ENDIAN__
if (addr & 0x1) {
*(u8 *) (ptr + 0) = (val >> 0) & 0xff;
*(u8 *) (ptr + 1) = (val >> 8) & 0xff;
} else
#endif
#if defined(__alpha__) || defined(__alpha)
stw_u(val, (u16 *) (ptr));
#else
*(u16 *) (ptr) = val;
#endif
// }
}
/****************************************************************************
PARAMETERS:
addr - Emulator memory address to read
val - Value to store
REMARKS:
Writes a long value to emulator memory.
****************************************************************************/
void X86API wrl(u32 addr, u32 val)
{
u8 *ptr;
ptr = mem_ptr(addr, 4);
// if (addr >= 0xc0000 && addr < 0xd0000 ) {
// rom_printk("WARNING! Attempt to overwrite ROM 0x%x\n", addr);
// } else {
DB(if (DEBUG_MEM_TRACE())
rom_printk("%x 4 <- %x\n", addr, val);)
#ifdef __BIG_ENDIAN__
if (addr & 0x1) {
*(u8 *) (ptr + 0) = (val >> 0) & 0xff;
*(u8 *) (ptr + 1) = (val >> 8) & 0xff;
*(u8 *) (ptr + 2) = (val >> 16) & 0xff;
*(u8 *) (ptr + 3) = (val >> 24) & 0xff;
} else
#endif
#if defined(__alpha__) || defined(__alpha)
stl_u(val, (u32 *) (ptr));
#else
*(u32 *) (ptr) = val;
#endif
// }
}
/****************************************************************************
PARAMETERS:
addr - PIO address to read
RETURN:
0
REMARKS:
Default PIO byte read function. Doesn't perform real inb.
****************************************************************************/
static u8 X86API p_inb(X86EMU_pioAddr addr)
{
DB(if (DEBUG_IO_TRACE())
rom_printk("inb %x \n", addr);)
/* return 0;*/
#ifndef IN_MODULE
if (ioperm(0x3c0, 0xdf, 1) == -1) {
rom_printk("Permission not set on port 0x%x.\n", addr);
}
#endif
return bios_inb(addr);
}
/****************************************************************************
PARAMETERS:
addr - PIO address to read
RETURN:
0
REMARKS:
Default PIO word read function. Doesn't perform real inw.
****************************************************************************/
static u16 X86API p_inw(X86EMU_pioAddr addr)
{
DB(if (DEBUG_IO_TRACE())
rom_printk("inw %#04x \n", addr);)
/* return 0;*/
#ifndef IN_MODULE
if (ioperm(0x3c0, 0xdf, 1) == -1) {
rom_printk("Permission not set on port 0x%x.\n", addr);
}
#endif
return bios_inw(addr);
}
/****************************************************************************
PARAMETERS:
addr - PIO address to read
RETURN:
0
REMARKS:
Default PIO long read function. Doesn't perform real inl.
****************************************************************************/
static u32 X86API p_inl(X86EMU_pioAddr addr)
{
DB(if (DEBUG_IO_TRACE())
rom_printk("inl %#04x \n", addr);)
/* return 0;*/
#ifndef IN_MODULE
if (ioperm(0x3c0, 0xdf, 1) == -1) {
rom_printk("Permission not set on port 0x%x.\n", addr);
}
#endif
return bios_inl(addr);
}
/****************************************************************************
PARAMETERS:
addr - PIO address to write
val - Value to store
REMARKS:
Default PIO byte write function. Doesn't perform real outb.
****************************************************************************/
static void X86API p_outb(X86EMU_pioAddr addr, u8 val)
{
DB(if (DEBUG_IO_TRACE())
rom_printk("outb %#02x -> %#04x \n", val, addr);)
#ifndef IN_MODULE
if (ioperm(0x3c0, 0xdf, 1) == -1) {
rom_printk("Permission not set on port 0x%x.\n", addr);
}
#endif
bios_outb(val, addr);
return;
}
/****************************************************************************
PARAMETERS:
addr - PIO address to write
val - Value to store
REMARKS:
Default PIO word write function. Doesn't perform real outw.
****************************************************************************/
static void X86API p_outw(X86EMU_pioAddr addr, u16 val)
{
DB(if (DEBUG_IO_TRACE())
rom_printk("outw %#04x -> %#04x \n", val, addr);)
#ifndef IN_MODULE
if (ioperm(0x3c0, 0xdf, 1) == -1) {
rom_printk("Permission not set on port 0x%x.\n", addr);
}
#endif
bios_outw(val, addr);
return;
}
/****************************************************************************
PARAMETERS:
addr - PIO address to write
val - Value to store
REMARKS:
Default PIO ;ong write function. Doesn't perform real outl.
****************************************************************************/
static void X86API p_outl(X86EMU_pioAddr addr, u32 val)
{
DB(if (DEBUG_IO_TRACE())
rom_printk("outl %#08x -> %#04x \n", val, addr);)
#ifndef IN_MODULE
if (ioperm(0x3c0, 0xdf, 1) == -1) {
rom_printk("Permission not set on port 0x%x.\n", addr);
}
#endif
bios_outl(val, addr);
return;
}
/*------------------------- Global Variables ------------------------------*/
u8(X86APIP sys_rdb) (u32 addr) = rdb;
u16(X86APIP sys_rdw) (u32 addr) = rdw;
u32(X86APIP sys_rdl) (u32 addr) = rdl;
void (X86APIP sys_wrb) (u32 addr, u8 val) = wrb;
void (X86APIP sys_wrw) (u32 addr, u16 val) = wrw;
void (X86APIP sys_wrl) (u32 addr, u32 val) = wrl;
u8(X86APIP sys_inb) (X86EMU_pioAddr addr) = p_inb;
u16(X86APIP sys_inw) (X86EMU_pioAddr addr) = p_inw;
u32(X86APIP sys_inl) (X86EMU_pioAddr addr) = p_inl;
void (X86APIP sys_outb) (X86EMU_pioAddr addr, u8 val) = p_outb;
void (X86APIP sys_outw) (X86EMU_pioAddr addr, u16 val) = p_outw;
void (X86APIP sys_outl) (X86EMU_pioAddr addr, u32 val) = p_outl;
/*----------------------------- Setup -------------------------------------*/
/****************************************************************************
PARAMETERS:
funcs - New memory function pointers to make active
REMARKS:
This function is used to set the pointers to functions which access
memory space, allowing the user application to override these functions
and hook them out as necessary for their application.
****************************************************************************/
void X86EMU_setupMemFuncs(X86EMU_memFuncs * funcs)
{
sys_rdb = funcs->rdb;
sys_rdw = funcs->rdw;
sys_rdl = funcs->rdl;
sys_wrb = funcs->wrb;
sys_wrw = funcs->wrw;
sys_wrl = funcs->wrl;
}
/****************************************************************************
PARAMETERS:
funcs - New programmed I/O function pointers to make active
REMARKS:
This function is used to set the pointers to functions which access
I/O space, allowing the user application to override these functions
and hook them out as necessary for their application.
****************************************************************************/
void X86EMU_setupPioFuncs(X86EMU_pioFuncs * funcs)
{
sys_inb = funcs->inb_func;
sys_inw = funcs->inw_func;
sys_inl = funcs->inl_func;
sys_outb = funcs->outb_func;
sys_outw = funcs->outw_func;
sys_outl = funcs->outl_func;
}
/****************************************************************************
PARAMETERS:
funcs - New interrupt vector table to make active
REMARKS:
This function is used to set the pointers to functions which handle
interrupt processing in the emulator, allowing the user application to
hook interrupts as necessary for their application. Any interrupts that
are not hooked by the user application, and reflected and handled internally
in the emulator via the interrupt vector table. This allows the application
to get control when the code being emulated executes specific software
interrupts.
****************************************************************************/
void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[])
{
int i;
for (i = 0; i < 256; i++)
_X86EMU_intrTab[i] = NULL;
if (funcs) {
for (i = 0; i < 256; i++)
_X86EMU_intrTab[i] = funcs[i];
}
}
/****************************************************************************
PARAMETERS:
int - New software interrupt to prepare for
REMARKS:
This function is used to set up the emulator state to exceute a software
interrupt. This can be used by the user application code to allow an
interrupt to be hooked, examined and then reflected back to the emulator
so that the code in the emulator will continue processing the software
interrupt as per normal. This essentially allows system code to actively
hook and handle certain software interrupts as necessary.
****************************************************************************/
void X86EMU_prepareForInt(int num)
{
push_word((u16) M.x86.R_FLG);
CLEAR_FLAG(F_IF);
CLEAR_FLAG(F_TF);
push_word(M.x86.R_CS);
M.x86.R_CS = mem_access_word(num * 4 + 2);
push_word(M.x86.R_IP);
M.x86.R_IP = mem_access_word(num * 4);
M.x86.intr = 0;
}
void X86EMU_setMemBase(void *base, unsigned int size)
{
M.mem_base = (unsigned long) base;
M.mem_size = size;
}
void X86EMU_setabseg(void *abseg)
{
M.abseg = (unsigned long) abseg;
}

View File

@ -0,0 +1,789 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: Watcom C 10.6 or later
* Environment: 32-bit DOS
* Developer: Kendall Bennett
*
* Description: Program to validate the x86 emulator library for
* correctness. We run the emulator primitive operations
* functions against the real x86 CPU, and compare the result
* and flags to ensure correctness.
*
* We use inline assembler to compile and build this program.
*
****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "x86emu.h"
#include "x86emu/prim_asm.h"
#include "x86emu/prim_ops.h"
/*-------------------------- Implementation -------------------------------*/
#define true 1
#define false 0
u32 cur_flags_mask = 0;
int flags_are_different(u32 flags1, u32 flags2)
{
return (flags1&cur_flags_mask) != (flags2&cur_flags_mask);
}
#define ALL_FLAGS (F_CF | F_PF | F_AF | F_ZF | F_SF | F_OF)
#define VAL_START_BINARY(parm_type,res_type,dmax,smax,dincr,sincr) \
{ \
parm_type d,s; \
res_type r,r_asm; \
u32 flags,inflags; \
int f,failed = false; \
char buf1[80],buf2[80]; \
for (d = 0; d < dmax; d += dincr) { \
for (s = 0; s < smax; s += sincr) { \
M.x86.R_EFLG = inflags = flags = def_flags; \
for (f = 0; f < 2; f++) {
#define VAL_TEST_BINARY(name) \
r_asm = name##_asm(&flags,d,s); \
r = name(d,s); \
if (r != r_asm || flags_are_different(M.x86.R_EFLG, flags)) \
failed = true; \
if (failed || trace) {
#define VAL_TEST_BINARY_VOID(name) \
name##_asm(&flags,d,s); \
name(d,s); \
r = r_asm = 0; \
if (flags_are_different(M.x86.R_EFLG, flags)) \
failed = true; \
if (failed || trace) {
#define VAL_FAIL_BYTE_BYTE_BINARY(name) \
if (failed) \
printk("fail\n"); \
printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%02X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
#define VAL_FAIL_WORD_WORD_BINARY(name) \
if (failed) \
printk("fail\n"); \
printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
#define VAL_FAIL_LONG_LONG_BINARY(name) \
if (failed) \
printk("fail\n"); \
printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags));
#define VAL_END_BINARY() \
} \
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (!failed) \
printk("passed\n"); \
}
#define VAL_BYTE_BYTE_BINARY(name) \
printk("Validating %s ... ", #name); \
VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \
VAL_TEST_BINARY(name) \
VAL_FAIL_BYTE_BYTE_BINARY(name) \
VAL_END_BINARY()
#define VAL_WORD_WORD_BINARY(name) \
printk("Validating %s ... ", #name); \
VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \
VAL_TEST_BINARY(name) \
VAL_FAIL_WORD_WORD_BINARY(name) \
VAL_END_BINARY()
#define VAL_LONG_LONG_BINARY(name) \
printk("Validating %s ... ", #name); \
VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \
VAL_TEST_BINARY(name) \
VAL_FAIL_LONG_LONG_BINARY(name) \
VAL_END_BINARY()
#define VAL_VOID_BYTE_BINARY(name) \
printk("Validating %s ... ", #name); \
VAL_START_BINARY(u8,u8,0xFF,0xFF,1,1) \
VAL_TEST_BINARY_VOID(name) \
VAL_FAIL_BYTE_BYTE_BINARY(name) \
VAL_END_BINARY()
#define VAL_VOID_WORD_BINARY(name) \
printk("Validating %s ... ", #name); \
VAL_START_BINARY(u16,u16,0xFF00,0xFF00,0x100,0x100) \
VAL_TEST_BINARY_VOID(name) \
VAL_FAIL_WORD_WORD_BINARY(name) \
VAL_END_BINARY()
#define VAL_VOID_LONG_BINARY(name) \
printk("Validating %s ... ", #name); \
VAL_START_BINARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000) \
VAL_TEST_BINARY_VOID(name) \
VAL_FAIL_LONG_LONG_BINARY(name) \
VAL_END_BINARY()
#define VAL_BYTE_ROTATE(name) \
printk("Validating %s ... ", #name); \
VAL_START_BINARY(u8,u8,0xFF,8,1,1) \
VAL_TEST_BINARY(name) \
VAL_FAIL_BYTE_BYTE_BINARY(name) \
VAL_END_BINARY()
#define VAL_WORD_ROTATE(name) \
printk("Validating %s ... ", #name); \
VAL_START_BINARY(u16,u16,0xFF00,16,0x100,1) \
VAL_TEST_BINARY(name) \
VAL_FAIL_WORD_WORD_BINARY(name) \
VAL_END_BINARY()
#define VAL_LONG_ROTATE(name) \
printk("Validating %s ... ", #name); \
VAL_START_BINARY(u32,u32,0xFF000000,32,0x1000000,1) \
VAL_TEST_BINARY(name) \
VAL_FAIL_LONG_LONG_BINARY(name) \
VAL_END_BINARY()
#define VAL_START_TERNARY(parm_type,res_type,dmax,smax,dincr,sincr,maxshift)\
{ \
parm_type d,s; \
res_type r,r_asm; \
u8 shift; \
u32 flags,inflags; \
int f,failed = false; \
char buf1[80],buf2[80]; \
for (d = 0; d < dmax; d += dincr) { \
for (s = 0; s < smax; s += sincr) { \
for (shift = 0; shift < maxshift; shift += 1) { \
M.x86.R_EFLG = inflags = flags = def_flags; \
for (f = 0; f < 2; f++) {
#define VAL_TEST_TERNARY(name) \
r_asm = name##_asm(&flags,d,s,shift); \
r = name(d,s,shift); \
if (r != r_asm || flags_are_different(M.x86.R_EFLG, flags)) \
failed = true; \
if (failed || trace) {
#define VAL_FAIL_WORD_WORD_TERNARY(name) \
if (failed) \
printk("fail\n"); \
printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \
r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%04X = %-15s(0x%04X,0x%04X,%d), flags = %s -> %s\n", \
r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags));
#define VAL_FAIL_LONG_LONG_TERNARY(name) \
if (failed) \
printk("fail\n"); \
printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \
r, #name, d, s, shift, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%08X = %-15s(0x%08X,0x%08X,%d), flags = %s -> %s\n", \
r_asm, #name"_asm", d, s, shift, print_flags(buf1,inflags), print_flags(buf2,flags));
#define VAL_END_TERNARY() \
} \
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (!failed) \
printk("passed\n"); \
}
#define VAL_WORD_ROTATE_DBL(name) \
printk("Validating %s ... ", #name); \
VAL_START_TERNARY(u16,u16,0xFF00,0xFF00,0x100,0x100,16) \
VAL_TEST_TERNARY(name) \
VAL_FAIL_WORD_WORD_TERNARY(name) \
VAL_END_TERNARY()
#define VAL_LONG_ROTATE_DBL(name) \
printk("Validating %s ... ", #name); \
VAL_START_TERNARY(u32,u32,0xFF000000,0xFF000000,0x1000000,0x1000000,32) \
VAL_TEST_TERNARY(name) \
VAL_FAIL_LONG_LONG_TERNARY(name) \
VAL_END_TERNARY()
#define VAL_START_UNARY(parm_type,max,incr) \
{ \
parm_type d,r,r_asm; \
u32 flags,inflags; \
int f,failed = false; \
char buf1[80],buf2[80]; \
for (d = 0; d < max; d += incr) { \
M.x86.R_EFLG = inflags = flags = def_flags; \
for (f = 0; f < 2; f++) {
#define VAL_TEST_UNARY(name) \
r_asm = name##_asm(&flags,d); \
r = name(d); \
if (r != r_asm || flags_are_different(M.x86.R_EFLG, flags)) { \
failed = true;
#define VAL_FAIL_BYTE_UNARY(name) \
printk("fail\n"); \
printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \
r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%02X = %-15s(0x%02X), flags = %s -> %s\n", \
r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
#define VAL_FAIL_WORD_UNARY(name) \
printk("fail\n"); \
printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \
r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%04X = %-15s(0x%04X), flags = %s -> %s\n", \
r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
#define VAL_FAIL_LONG_UNARY(name) \
printk("fail\n"); \
printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \
r, #name, d, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%08X = %-15s(0x%08X), flags = %s -> %s\n", \
r_asm, #name"_asm", d, print_flags(buf1,inflags), print_flags(buf2,flags));
#define VAL_END_UNARY() \
} \
M.x86.R_EFLG = inflags = flags = def_flags | ALL_FLAGS; \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (!failed) \
printk("passed\n"); \
}
#define VAL_BYTE_UNARY(name) \
printk("Validating %s ... ", #name); \
VAL_START_UNARY(u8,0xFF,0x1) \
VAL_TEST_UNARY(name) \
VAL_FAIL_BYTE_UNARY(name) \
VAL_END_UNARY()
#define VAL_WORD_UNARY(name) \
printk("Validating %s ... ", #name); \
VAL_START_UNARY(u16,0xFF00,0x100) \
VAL_TEST_UNARY(name) \
VAL_FAIL_WORD_UNARY(name) \
VAL_END_UNARY()
#define VAL_WORD_BYTE_UNARY(name) \
printk("Validating %s ... ", #name); \
VAL_START_UNARY(u16,0xFF,0x1) \
VAL_TEST_UNARY(name) \
VAL_FAIL_WORD_UNARY(name) \
VAL_END_UNARY()
#define VAL_LONG_UNARY(name) \
printk("Validating %s ... ", #name); \
VAL_START_UNARY(u32,0xFF000000,0x1000000) \
VAL_TEST_UNARY(name) \
VAL_FAIL_LONG_UNARY(name) \
VAL_END_UNARY()
#define VAL_BYTE_MUL(name) \
printk("Validating %s ... ", #name); \
{ \
u8 d,s; \
u16 r,r_asm; \
u32 flags,inflags; \
int f,failed = false; \
char buf1[80],buf2[80]; \
for (d = 0; d < 0xFF; d += 1) { \
for (s = 0; s < 0xFF; s += 1) { \
M.x86.R_EFLG = inflags = flags = def_flags; \
for (f = 0; f < 2; f++) { \
name##_asm(&flags,&r_asm,d,s); \
M.x86.R_AL = d; \
name(s); \
r = M.x86.R_AX; \
if (r != r_asm || flags_are_different(M.x86.R_EFLG, flags)) \
failed = true; \
if (failed || trace) { \
if (failed) \
printk("fail\n"); \
printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
r, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%04X = %-15s(0x%02X,0x%02X), flags = %s -> %s\n", \
r_asm, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
} \
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (!failed) \
printk("passed\n"); \
}
#define VAL_WORD_MUL(name) \
printk("Validating %s ... ", #name); \
{ \
u16 d,s; \
u16 r_lo,r_asm_lo; \
u16 r_hi,r_asm_hi; \
u32 flags,inflags; \
int f,failed = false; \
char buf1[80],buf2[80]; \
for (d = 0; d < 0xFF00; d += 0x100) { \
for (s = 0; s < 0xFF00; s += 0x100) { \
M.x86.R_EFLG = inflags = flags = def_flags; \
for (f = 0; f < 2; f++) { \
name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \
M.x86.R_AX = d; \
name(s); \
r_lo = M.x86.R_AX; \
r_hi = M.x86.R_DX; \
if (r_lo != r_asm_lo || r_hi != r_asm_hi || flags_are_different(M.x86.R_EFLG, flags))\
failed = true; \
if (failed || trace) { \
if (failed) \
printk("fail\n"); \
printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%04X:0x%04X = %-15s(0x%04X,0x%04X), flags = %s -> %s\n", \
r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
} \
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (!failed) \
printk("passed\n"); \
}
#define VAL_LONG_MUL(name) \
printk("Validating %s ... ", #name); \
{ \
u32 d,s; \
u32 r_lo,r_asm_lo; \
u32 r_hi,r_asm_hi; \
u32 flags,inflags; \
int f,failed = false; \
char buf1[80],buf2[80]; \
for (d = 0; d < 0xFF000000; d += 0x1000000) { \
for (s = 0; s < 0xFF000000; s += 0x1000000) { \
M.x86.R_EFLG = inflags = flags = def_flags; \
for (f = 0; f < 2; f++) { \
name##_asm(&flags,&r_asm_lo,&r_asm_hi,d,s); \
M.x86.R_EAX = d; \
name(s); \
r_lo = M.x86.R_EAX; \
r_hi = M.x86.R_EDX; \
if (r_lo != r_asm_lo || r_hi != r_asm_hi || flags_are_different(M.x86.R_EFLG, flags))\
failed = true; \
if (failed || trace) { \
if (failed) \
printk("fail\n"); \
printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
r_hi,r_lo, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%08X:0x%08X = %-15s(0x%08X,0x%08X), flags = %s -> %s\n", \
r_asm_hi,r_asm_lo, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
} \
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (!failed) \
printk("passed\n"); \
}
#define VAL_BYTE_DIV(name) \
printk("Validating %s ... ", #name); \
{ \
u16 d,s; \
u8 r_quot,r_rem,r_asm_quot,r_asm_rem; \
u32 flags,inflags; \
int f,failed = false; \
char buf1[80],buf2[80]; \
for (d = 0; d < 0xFF00; d += 0x100) { \
for (s = 1; s < 0xFF; s += 1) { \
M.x86.R_EFLG = inflags = flags = def_flags; \
for (f = 0; f < 2; f++) { \
M.x86.intr = 0; \
M.x86.R_AX = d; \
name(s); \
r_quot = M.x86.R_AL; \
r_rem = M.x86.R_AH; \
if (M.x86.intr & INTR_SYNCH) \
continue; \
name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,s); \
if (r_quot != r_asm_quot || r_rem != r_asm_rem || flags_are_different(M.x86.R_EFLG, flags)) \
failed = true; \
if (failed || trace) { \
if (failed) \
printk("fail\n"); \
printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \
r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%02X:0x%02X = %-15s(0x%04X,0x%02X), flags = %s -> %s\n", \
r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
} \
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (!failed) \
printk("passed\n"); \
}
#define VAL_WORD_DIV(name) \
printk("Validating %s ... ", #name); \
{ \
u32 d,s; \
u16 r_quot,r_rem,r_asm_quot,r_asm_rem; \
u32 flags,inflags; \
int f,failed = false; \
char buf1[80],buf2[80]; \
for (d = 0; d < 0xFF000000; d += 0x1000000) { \
for (s = 0x100; s < 0xFF00; s += 0x100) { \
M.x86.R_EFLG = inflags = flags = def_flags; \
for (f = 0; f < 2; f++) { \
M.x86.intr = 0; \
M.x86.R_AX = d & 0xFFFF; \
M.x86.R_DX = d >> 16; \
name(s); \
r_quot = M.x86.R_AX; \
r_rem = M.x86.R_DX; \
if (M.x86.intr & INTR_SYNCH) \
continue; \
name##_asm(&flags,&r_asm_quot,&r_asm_rem,d & 0xFFFF,d >> 16,s);\
if (r_quot != r_asm_quot || r_rem != r_asm_rem || flags_are_different(M.x86.R_EFLG, flags)) \
failed = true; \
if (failed || trace) { \
if (failed) \
printk("fail\n"); \
printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \
r_quot, r_rem, #name, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%04X:0x%04X = %-15s(0x%08X,0x%04X), flags = %s -> %s\n", \
r_asm_quot, r_asm_rem, #name"_asm", d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
} \
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (!failed) \
printk("passed\n"); \
}
#define VAL_LONG_DIV(name) \
printk("Validating %s ... ", #name); \
{ \
u32 d,s; \
u32 r_quot,r_rem,r_asm_quot,r_asm_rem; \
u32 flags,inflags; \
int f,failed = false; \
char buf1[80],buf2[80]; \
for (d = 0; d < 0xFF000000; d += 0x1000000) { \
for (s = 0x100; s < 0xFF00; s += 0x100) { \
M.x86.R_EFLG = inflags = flags = def_flags; \
for (f = 0; f < 2; f++) { \
M.x86.intr = 0; \
M.x86.R_EAX = d; \
M.x86.R_EDX = 0; \
name(s); \
r_quot = M.x86.R_EAX; \
r_rem = M.x86.R_EDX; \
if (M.x86.intr & INTR_SYNCH) \
continue; \
name##_asm(&flags,&r_asm_quot,&r_asm_rem,d,0,s); \
if (r_quot != r_asm_quot || r_rem != r_asm_rem || flags_are_different(M.x86.R_EFLG, flags)) \
failed = true; \
if (failed || trace) { \
if (failed) \
printk("fail\n"); \
printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \
r_quot, r_rem, #name, 0, d, s, print_flags(buf1,inflags), print_flags(buf2,M.x86.R_EFLG)); \
printk("0x%08X:0x%08X = %-15s(0x%08X:0x%08X,0x%08X), flags = %s -> %s\n", \
r_asm_quot, r_asm_rem, #name"_asm", 0, d, s, print_flags(buf1,inflags), print_flags(buf2,flags)); \
} \
M.x86.R_EFLG = inflags = flags = def_flags | (ALL_FLAGS & ~F_OF); \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (failed) \
break; \
} \
if (!failed) \
printk("passed\n"); \
}
void printk(const char *fmt, ...)
{
va_list argptr;
va_start(argptr, fmt);
vfprintf(stdout, fmt, argptr);
fflush(stdout);
va_end(argptr);
}
char * print_flags(char *buf,ulong flags)
{
char *separator = "";
buf[0] = 0;
if (flags & F_CF) {
strcat(buf,separator);
strcat(buf,"CF");
separator = ",";
}
if (flags & F_PF) {
strcat(buf,separator);
strcat(buf,"PF");
separator = ",";
}
if (flags & F_AF) {
strcat(buf,separator);
strcat(buf,"AF");
separator = ",";
}
if (flags & F_ZF) {
strcat(buf,separator);
strcat(buf,"ZF");
separator = ",";
}
if (flags & F_SF) {
strcat(buf,separator);
strcat(buf,"SF");
separator = ",";
}
if (flags & F_OF) {
strcat(buf,separator);
strcat(buf,"OF");
separator = ",";
}
if (separator[0] == 0)
strcpy(buf,"None");
return buf;
}
int main(int argc, char *argv[])
{
u32 def_flags;
int trace = false;
if (argc > 1)
trace = true;
memset(&M, 0, sizeof(M));
def_flags = get_flags_asm() & ~ALL_FLAGS;
cur_flags_mask = F_AF | F_CF;
VAL_WORD_UNARY(aaa_word);
VAL_WORD_UNARY(aas_word);
cur_flags_mask = F_SF | F_ZF | F_PF;
VAL_WORD_UNARY(aad_word);
VAL_WORD_UNARY(aam_word);
cur_flags_mask = ALL_FLAGS;
VAL_BYTE_BYTE_BINARY(adc_byte);
VAL_WORD_WORD_BINARY(adc_word);
VAL_LONG_LONG_BINARY(adc_long);
VAL_BYTE_BYTE_BINARY(add_byte);
VAL_WORD_WORD_BINARY(add_word);
VAL_LONG_LONG_BINARY(add_long);
cur_flags_mask = ALL_FLAGS & (~F_AF);
VAL_BYTE_BYTE_BINARY(and_byte);
VAL_WORD_WORD_BINARY(and_word);
VAL_LONG_LONG_BINARY(and_long);
cur_flags_mask = ALL_FLAGS;
VAL_BYTE_BYTE_BINARY(cmp_byte);
VAL_WORD_WORD_BINARY(cmp_word);
VAL_LONG_LONG_BINARY(cmp_long);
cur_flags_mask = ALL_FLAGS & (~F_OF);
VAL_BYTE_UNARY(daa_byte);
VAL_BYTE_UNARY(das_byte); // Fails for 0x9A (out of range anyway)
cur_flags_mask = ALL_FLAGS;
VAL_BYTE_UNARY(dec_byte);
VAL_WORD_UNARY(dec_word);
VAL_LONG_UNARY(dec_long);
VAL_BYTE_UNARY(inc_byte);
VAL_WORD_UNARY(inc_word);
VAL_LONG_UNARY(inc_long);
cur_flags_mask = ALL_FLAGS & (~F_AF);
VAL_BYTE_BYTE_BINARY(or_byte);
VAL_WORD_WORD_BINARY(or_word);
VAL_LONG_LONG_BINARY(or_long);
cur_flags_mask = ALL_FLAGS;
VAL_BYTE_UNARY(neg_byte);
VAL_WORD_UNARY(neg_word);
VAL_LONG_UNARY(neg_long);
VAL_BYTE_UNARY(not_byte);
VAL_WORD_UNARY(not_word);
VAL_LONG_UNARY(not_long);
cur_flags_mask = ALL_FLAGS & (~F_OF);
VAL_BYTE_ROTATE(rcl_byte);
VAL_WORD_ROTATE(rcl_word);
VAL_LONG_ROTATE(rcl_long);
VAL_BYTE_ROTATE(rcr_byte);
VAL_WORD_ROTATE(rcr_word);
VAL_LONG_ROTATE(rcr_long);
VAL_BYTE_ROTATE(rol_byte);
VAL_WORD_ROTATE(rol_word);
VAL_LONG_ROTATE(rol_long);
VAL_BYTE_ROTATE(ror_byte);
VAL_WORD_ROTATE(ror_word);
VAL_LONG_ROTATE(ror_long);
cur_flags_mask = ALL_FLAGS & (~(F_AF | F_OF));
VAL_BYTE_ROTATE(shl_byte);
VAL_WORD_ROTATE(shl_word);
VAL_LONG_ROTATE(shl_long);
VAL_BYTE_ROTATE(shr_byte);
VAL_WORD_ROTATE(shr_word);
VAL_LONG_ROTATE(shr_long);
VAL_BYTE_ROTATE(sar_byte);
VAL_WORD_ROTATE(sar_word);
VAL_LONG_ROTATE(sar_long);
cur_flags_mask = ALL_FLAGS & (~(F_AF | F_OF));
VAL_WORD_ROTATE_DBL(shld_word);
VAL_LONG_ROTATE_DBL(shld_long);
VAL_WORD_ROTATE_DBL(shrd_word);
VAL_LONG_ROTATE_DBL(shrd_long);
cur_flags_mask = ALL_FLAGS;
VAL_BYTE_BYTE_BINARY(sbb_byte);
VAL_WORD_WORD_BINARY(sbb_word);
VAL_LONG_LONG_BINARY(sbb_long);
VAL_BYTE_BYTE_BINARY(sub_byte);
VAL_WORD_WORD_BINARY(sub_word);
VAL_LONG_LONG_BINARY(sub_long);
cur_flags_mask = ALL_FLAGS & (~F_AF);
VAL_BYTE_BYTE_BINARY(xor_byte);
VAL_WORD_WORD_BINARY(xor_word);
VAL_LONG_LONG_BINARY(xor_long);
VAL_VOID_BYTE_BINARY(test_byte);
VAL_VOID_WORD_BINARY(test_word);
VAL_VOID_LONG_BINARY(test_long);
cur_flags_mask = F_CF | F_OF;
VAL_BYTE_MUL(imul_byte);
VAL_WORD_MUL(imul_word);
VAL_LONG_MUL(imul_long);
VAL_BYTE_MUL(mul_byte);
VAL_WORD_MUL(mul_word);
VAL_LONG_MUL(mul_long);
cur_flags_mask = 0;
VAL_BYTE_DIV(idiv_byte);
VAL_WORD_DIV(idiv_word);
VAL_LONG_DIV(idiv_long);
VAL_BYTE_DIV(div_byte);
VAL_WORD_DIV(div_word);
VAL_LONG_DIV(div_long);
return 0;
}

View File

@ -0,0 +1,212 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for debug definitions.
*
****************************************************************************/
#ifndef __X86EMU_DEBUG_H
#define __X86EMU_DEBUG_H
#include "x86emu/types.h"
/*---------------------- Macros and type definitions ----------------------*/
/* checks to be enabled for "runtime" */
#define CHECK_IP_FETCH_F 0x1
#define CHECK_SP_ACCESS_F 0x2
#define CHECK_MEM_ACCESS_F 0x4 /*using regular linear pointer */
#define CHECK_DATA_ACCESS_F 0x8 /*using segment:offset*/
#ifdef DEBUG
# define CHECK_IP_FETCH() (M.x86.check & CHECK_IP_FETCH_F)
# define CHECK_SP_ACCESS() (M.x86.check & CHECK_SP_ACCESS_F)
# define CHECK_MEM_ACCESS() (M.x86.check & CHECK_MEM_ACCESS_F)
# define CHECK_DATA_ACCESS() (M.x86.check & CHECK_DATA_ACCESS_F)
#else
# define CHECK_IP_FETCH()
# define CHECK_SP_ACCESS()
# define CHECK_MEM_ACCESS()
# define CHECK_DATA_ACCESS()
#endif
#ifdef DEBUG
# define DEBUG_INSTRUMENT() (M.x86.debug & DEBUG_INSTRUMENT_F)
# define DEBUG_DECODE() (M.x86.debug & DEBUG_DECODE_F)
# define DEBUG_TRACE() (M.x86.debug & DEBUG_TRACE_F)
# define DEBUG_STEP() (M.x86.debug & DEBUG_STEP_F)
# define DEBUG_DISASSEMBLE() (M.x86.debug & DEBUG_DISASSEMBLE_F)
# define DEBUG_BREAK() (M.x86.debug & DEBUG_BREAK_F)
# define DEBUG_SVC() (M.x86.debug & DEBUG_SVC_F)
# define DEBUG_SAVE_IP_CS() (M.x86.debug & DEBUG_SAVE_CS_IP)
# define DEBUG_FS() (M.x86.debug & DEBUG_FS_F)
# define DEBUG_PROC() (M.x86.debug & DEBUG_PROC_F)
# define DEBUG_SYSINT() (M.x86.debug & DEBUG_SYSINT_F)
# define DEBUG_TRACECALL() (M.x86.debug & DEBUG_TRACECALL_F)
# define DEBUG_TRACECALLREGS() (M.x86.debug & DEBUG_TRACECALL_REGS_F)
# define DEBUG_SYS() (M.x86.debug & DEBUG_SYS_F)
# define DEBUG_MEM_TRACE() (M.x86.debug & DEBUG_MEM_TRACE_F)
# define DEBUG_IO_TRACE() (M.x86.debug & DEBUG_IO_TRACE_F)
# define DEBUG_DECODE_NOPRINT() (M.x86.debug & DEBUG_DECODE_NOPRINT_F)
#else
# define DEBUG_INSTRUMENT() 0
# define DEBUG_DECODE() 0
# define DEBUG_TRACE() 0
# define DEBUG_STEP() 0
# define DEBUG_DISASSEMBLE() 0
# define DEBUG_BREAK() 0
# define DEBUG_SVC() 0
# define DEBUG_SAVE_IP_CS() 0
# define DEBUG_FS() 0
# define DEBUG_PROC() 0
# define DEBUG_SYSINT() 0
# define DEBUG_TRACECALL() 0
# define DEBUG_TRACECALLREGS() 0
# define DEBUG_SYS() 0
# define DEBUG_MEM_TRACE() 0
# define DEBUG_IO_TRACE() 0
# define DEBUG_DECODE_NOPRINT() 0
#endif
#ifdef DEBUG
# define DECODE_PRINTF(x) if (DEBUG_DECODE()) \
x86emu_decode_printf(x)
# define DECODE_PRINTF2(x,y) if (DEBUG_DECODE()) \
x86emu_decode_printf2(x,y)
/*
* The following allow us to look at the bytes of an instruction. The
* first INCR_INSTRN_LEN, is called everytime bytes are consumed in
* the decoding process. The SAVE_IP_CS is called initially when the
* major opcode of the instruction is accessed.
*/
#define INC_DECODED_INST_LEN(x) \
if (DEBUG_DECODE()) \
x86emu_inc_decoded_inst_len(x)
#define SAVE_IP_CS(x,y) \
if (DEBUG_DECODE() | DEBUG_TRACECALL() | DEBUG_BREAK() \
| DEBUG_IO_TRACE() | DEBUG_SAVE_IP_CS()) { \
M.x86.saved_cs = x; \
M.x86.saved_ip = y; \
}
#else
# define INC_DECODED_INST_LEN(x)
# define DECODE_PRINTF(x)
# define DECODE_PRINTF2(x,y)
# define SAVE_IP_CS(x,y)
#endif
#ifdef DEBUG
#define TRACE_REGS() \
if (DEBUG_DISASSEMBLE()) { \
x86emu_just_disassemble(); \
goto EndOfTheInstructionProcedure; \
} \
if (DEBUG_TRACE() || DEBUG_DECODE()) X86EMU_trace_regs()
#else
# define TRACE_REGS()
#endif
#ifdef DEBUG
# define SINGLE_STEP() if (DEBUG_STEP()) x86emu_single_step()
#else
# define SINGLE_STEP()
#endif
#define TRACE_AND_STEP() \
TRACE_REGS(); \
SINGLE_STEP()
#ifdef DEBUG
# define START_OF_INSTR()
# define END_OF_INSTR() EndOfTheInstructionProcedure: x86emu_end_instr();
# define END_OF_INSTR_NO_TRACE() x86emu_end_instr();
#else
# define START_OF_INSTR()
# define END_OF_INSTR()
# define END_OF_INSTR_NO_TRACE()
#endif
#ifdef DEBUG
# define CALL_TRACE(u,v,w,x,s) \
if (DEBUG_TRACECALLREGS()) \
x86emu_dump_regs(); \
if (DEBUG_TRACECALL()) \
printk("%04x:%04x: CALL %s%04x:%04x\n", u , v, s, w, x);
# define RETURN_TRACE(n,u,v) \
if (DEBUG_TRACECALLREGS()) \
x86emu_dump_regs(); \
if (DEBUG_TRACECALL()) \
printk("%04x:%04x: %s\n",u,v,n);
#else
# define CALL_TRACE(u,v,w,x,s)
# define RETURN_TRACE(n,u,v)
#endif
#ifdef DEBUG
#define DB(x) x
#else
#define DB(x)
#endif
/*-------------------------- Function Prototypes --------------------------*/
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
extern void x86emu_inc_decoded_inst_len (int x);
extern void x86emu_decode_printf (char *x);
extern void x86emu_decode_printf2 (char *x, int y);
extern void x86emu_just_disassemble (void);
extern void x86emu_single_step (void);
extern void x86emu_end_instr (void);
extern void x86emu_dump_regs (void);
extern void x86emu_dump_xregs (void);
extern void x86emu_print_int_vect (u16 iv);
extern void x86emu_instrument_instruction (void);
extern void x86emu_check_ip_access (void);
extern void x86emu_check_sp_access (void);
extern void x86emu_check_mem_access (u32 p);
extern void x86emu_check_data_access (uint s, uint o);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_DEBUG_H */

View File

@ -0,0 +1,88 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for instruction decoding logic.
*
****************************************************************************/
#ifndef __X86EMU_DECODE_H
#define __X86EMU_DECODE_H
/*---------------------- Macros and type definitions ----------------------*/
/* Instruction Decoding Stuff */
#define FETCH_DECODE_MODRM(mod,rh,rl) fetch_decode_modrm(&mod,&rh,&rl)
#define DECODE_RM_BYTE_REGISTER(r) decode_rm_byte_register(r)
#define DECODE_RM_WORD_REGISTER(r) decode_rm_word_register(r)
#define DECODE_RM_LONG_REGISTER(r) decode_rm_long_register(r)
#define DECODE_CLEAR_SEGOVR() M.x86.mode &= ~SYSMODE_CLRMASK
/*-------------------------- Function Prototypes --------------------------*/
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
void x86emu_intr_raise (u8 type);
void fetch_decode_modrm (int *mod,int *regh,int *regl);
u8 fetch_byte_imm (void);
u16 fetch_word_imm (void);
u32 fetch_long_imm (void);
u8 fetch_data_byte (uint offset);
u8 fetch_data_byte_abs (uint segment, uint offset);
u16 fetch_data_word (uint offset);
u16 fetch_data_word_abs (uint segment, uint offset);
u32 fetch_data_long (uint offset);
u32 fetch_data_long_abs (uint segment, uint offset);
void store_data_byte (uint offset, u8 val);
void store_data_byte_abs (uint segment, uint offset, u8 val);
void store_data_word (uint offset, u16 val);
void store_data_word_abs (uint segment, uint offset, u16 val);
void store_data_long (uint offset, u32 val);
void store_data_long_abs (uint segment, uint offset, u32 val);
u8* decode_rm_byte_register(int reg);
u16* decode_rm_word_register(int reg);
u32* decode_rm_long_register(int reg);
u16* decode_rm_seg_register(int reg);
unsigned decode_rm00_address(int rm);
unsigned decode_rm01_address(int rm);
unsigned decode_rm10_address(int rm);
unsigned decode_rmXX_address(int mod, int rm);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_DECODE_H */

View File

@ -0,0 +1,61 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for FPU instruction decoding.
*
****************************************************************************/
#ifndef __X86EMU_FPU_H
#define __X86EMU_FPU_H
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
/* these have to be defined, whether 8087 support compiled in or not. */
extern void x86emuOp_esc_coprocess_d8 (u8 op1);
extern void x86emuOp_esc_coprocess_d9 (u8 op1);
extern void x86emuOp_esc_coprocess_da (u8 op1);
extern void x86emuOp_esc_coprocess_db (u8 op1);
extern void x86emuOp_esc_coprocess_dc (u8 op1);
extern void x86emuOp_esc_coprocess_dd (u8 op1);
extern void x86emuOp_esc_coprocess_de (u8 op1);
extern void x86emuOp_esc_coprocess_df (u8 op1);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_FPU_H */

View File

@ -0,0 +1,45 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for operand decoding functions.
*
****************************************************************************/
#ifndef __X86EMU_OPS_H
#define __X86EMU_OPS_H
extern void (*x86emu_optab[0x100])(u8 op1);
extern void (*x86emu_optab2[0x100])(u8 op2);
#endif /* __X86EMU_OPS_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,142 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for primitive operation functions.
*
****************************************************************************/
#ifndef __X86EMU_PRIM_OPS_H
#define __X86EMU_PRIM_OPS_H
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
u16 aaa_word (u16 d);
u16 aas_word (u16 d);
u16 aad_word (u16 d);
u16 aam_word (u8 d);
u8 adc_byte (u8 d, u8 s);
u16 adc_word (u16 d, u16 s);
u32 adc_long (u32 d, u32 s);
u8 add_byte (u8 d, u8 s);
u16 add_word (u16 d, u16 s);
u32 add_long (u32 d, u32 s);
u8 and_byte (u8 d, u8 s);
u16 and_word (u16 d, u16 s);
u32 and_long (u32 d, u32 s);
u8 cmp_byte (u8 d, u8 s);
u16 cmp_word (u16 d, u16 s);
u32 cmp_long (u32 d, u32 s);
u8 daa_byte (u8 d);
u8 das_byte (u8 d);
u8 dec_byte (u8 d);
u16 dec_word (u16 d);
u32 dec_long (u32 d);
u8 inc_byte (u8 d);
u16 inc_word (u16 d);
u32 inc_long (u32 d);
u8 or_byte (u8 d, u8 s);
u16 or_word (u16 d, u16 s);
u32 or_long (u32 d, u32 s);
u8 neg_byte (u8 s);
u16 neg_word (u16 s);
u32 neg_long (u32 s);
u8 not_byte (u8 s);
u16 not_word (u16 s);
u32 not_long (u32 s);
u8 rcl_byte (u8 d, u8 s);
u16 rcl_word (u16 d, u8 s);
u32 rcl_long (u32 d, u8 s);
u8 rcr_byte (u8 d, u8 s);
u16 rcr_word (u16 d, u8 s);
u32 rcr_long (u32 d, u8 s);
u8 rol_byte (u8 d, u8 s);
u16 rol_word (u16 d, u8 s);
u32 rol_long (u32 d, u8 s);
u8 ror_byte (u8 d, u8 s);
u16 ror_word (u16 d, u8 s);
u32 ror_long (u32 d, u8 s);
u8 shl_byte (u8 d, u8 s);
u16 shl_word (u16 d, u8 s);
u32 shl_long (u32 d, u8 s);
u8 shr_byte (u8 d, u8 s);
u16 shr_word (u16 d, u8 s);
u32 shr_long (u32 d, u8 s);
u8 sar_byte (u8 d, u8 s);
u16 sar_word (u16 d, u8 s);
u32 sar_long (u32 d, u8 s);
u16 shld_word (u16 d, u16 fill, u8 s);
u32 shld_long (u32 d, u32 fill, u8 s);
u16 shrd_word (u16 d, u16 fill, u8 s);
u32 shrd_long (u32 d, u32 fill, u8 s);
u8 sbb_byte (u8 d, u8 s);
u16 sbb_word (u16 d, u16 s);
u32 sbb_long (u32 d, u32 s);
u8 sub_byte (u8 d, u8 s);
u16 sub_word (u16 d, u16 s);
u32 sub_long (u32 d, u32 s);
void test_byte (u8 d, u8 s);
void test_word (u16 d, u16 s);
void test_long (u32 d, u32 s);
u8 xor_byte (u8 d, u8 s);
u16 xor_word (u16 d, u16 s);
u32 xor_long (u32 d, u32 s);
void imul_byte (u8 s);
void imul_word (u16 s);
void imul_long (u32 s);
void imul_long_direct(u32 *res_lo, u32* res_hi,u32 d, u32 s);
void mul_byte (u8 s);
void mul_word (u16 s);
void mul_long (u32 s);
void idiv_byte (u8 s);
void idiv_word (u16 s);
void idiv_long (u32 s);
void div_byte (u8 s);
void div_word (u16 s);
void div_long (u32 s);
void ins (int size);
void outs (int size);
u16 mem_access_word (int addr);
void push_word (u16 w);
void push_long (u32 w);
u16 pop_word (void);
u32 pop_long (void);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_PRIM_OPS_H */

View File

@ -0,0 +1,101 @@
/****************************************************************************
*
* Realmode X86 Emulator Library
*
* Copyright (C) 1991-2004 SciTech Software, Inc.
* Copyright (C) David Mosberger-Tang
* Copyright (C) 1999 Egbert Eich
*
* ========================================================================
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of the authors not be used
* in advertising or publicity pertaining to distribution of the software
* without specific, written prior permission. The authors makes no
* representations about the suitability of this software for any purpose.
* It is provided "as is" without express or implied warranty.
*
* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* ========================================================================
*
* Language: ANSI C
* Environment: Any
* Developer: Kendall Bennett
*
* Description: Header file for system specific functions. These functions
* are always compiled and linked in the OS depedent libraries,
* and never in a binary portable driver.
*
****************************************************************************/
#ifndef __X86EMU_X86EMUI_H
#define __X86EMU_X86EMUI_H
/* If we are compiling in C++ mode, we can compile some functions as
* inline to increase performance (however the code size increases quite
* dramatically in this case).
*/
#if defined(__cplusplus) && !defined(_NO_INLINE)
#define _INLINE inline
#else
#define _INLINE static
#endif
/* Get rid of unused parameters in C++ compilation mode */
#ifdef __cplusplus
#define X86EMU_UNUSED(v)
#else
#define X86EMU_UNUSED(v) v
#endif
#include "x86emu.h"
#include "x86emu/regs.h"
#include "x86emu/debug.h"
#include "x86emu/decode.h"
#include "x86emu/ops.h"
#include "x86emu/prim_ops.h"
#include "x86emu/fpu.h"
#include "x86emu/fpu_regs.h"
#ifndef __KERNEL__
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
/*--------------------------- Inline Functions ----------------------------*/
#ifdef __cplusplus
extern "C" { /* Use "C" linkage when in C++ mode */
#endif
extern u8 (X86APIP sys_rdb)(u32 addr);
extern u16 (X86APIP sys_rdw)(u32 addr);
extern u32 (X86APIP sys_rdl)(u32 addr);
extern void (X86APIP sys_wrb)(u32 addr,u8 val);
extern void (X86APIP sys_wrw)(u32 addr,u16 val);
extern void (X86APIP sys_wrl)(u32 addr,u32 val);
extern u8 (X86APIP sys_inb)(X86EMU_pioAddr addr);
extern u16 (X86APIP sys_inw)(X86EMU_pioAddr addr);
extern u32 (X86APIP sys_inl)(X86EMU_pioAddr addr);
extern void (X86APIP sys_outb)(X86EMU_pioAddr addr,u8 val);
extern void (X86APIP sys_outw)(X86EMU_pioAddr addr,u16 val);
extern void (X86APIP sys_outl)(X86EMU_pioAddr addr,u32 val);
#ifdef __cplusplus
} /* End of "C" linkage for C++ */
#endif
#endif /* __X86EMU_X86EMUI_H */

38
arch/e2k/boot/boot.h Normal file
View File

@ -0,0 +1,38 @@
/*
* Small boot for simulator
*/
#include <linux/types.h>
#include <asm/bootinfo.h>
#ifndef _E2K_BOOT_BOOT_H_
#define _E2K_BOOT_BOOT_H_
/*
* E2K physical memory layout
*/
#define E2K_MAIN_MEM_REGION_START 0x0000000000000000UL /* from 0 */
#define E2K_MAIN_MEM_REGION_END 0x0000000080000000UL /* up to 2Gb */
#define E2K_EXT_MEM_REGION_START 0x0000000100000000UL /* from 4Gb */
#define E2K_EXT_MEM_REGION_END 0x0000001000000000UL /* up to 64Gb */
extern void *malloc_aligned(int size, int alignment);
extern void *malloc(int size);
extern void bios_mem_init(long membase, long memsize);
extern e2k_addr_t get_busy_memory_end(void);
extern int decompress_kernel(ulong base);
extern void rom_putc(char c);
extern int rom_getc(void);
extern int rom_tstc(void);
#ifdef CONFIG_SMP
extern void smp_start_cpus(void);
#endif /* CONFIG_SMP */
#ifdef CONFIG_STATE_SAVE
extern void load_machine_state_new(boot_info_t *boot_info);
#endif /* CONFIG_STATE_SAVE */
#endif /* _E2K_BOOT_BOOT_H_ */

19
arch/e2k/boot/boot.lds Normal file
View File

@ -0,0 +1,19 @@
OUTPUT_FORMAT("elf64-e2k", "elf64-e2k", "elf64-e2k")
/* OUTPUT_ARCH(e2k) Defined by Makefile */
ENTRY(start)
SECTIONS {
.bootblock : {
_bootblock = .;
arch/e2k/boot/bootblock.o(.rodata)
_ebootblock = .;
}
. = _bootblock + 0x10000;
.kernel : {
_kernel = .;
arch/e2k/boot/bpiggy.o(.rodata)
_ekernel = .;
}
}

55
arch/e2k/boot/boot_io.h Normal file
View File

@ -0,0 +1,55 @@
#ifndef _E2K_BOOT_IO_H_
#define _E2K_BOOT_IO_H_
//#include <asm/e2k_api.h>
//#include <asm/types.h>
#include <asm/head.h>
/*
* E2K I/O ports for BIOS
*/
#if defined(CONFIG_E2K_FULL_SIC)
#define PHYS_X86_IO_BASE E2K_FULL_SIC_IO_AREA_PHYS_BASE
#elif defined(CONFIG_E2K_LEGACY_SIC)
#define PHYS_X86_IO_BASE E2K_LEGACY_SIC_IO_AREA_PHYS_BASE
#else
#error "Undefined machine or SIC type"
#endif
extern unsigned char bios_inb(unsigned short port);
extern unsigned short bios_inw(unsigned short port);
extern unsigned int bios_inl(unsigned short port);
extern unsigned long bios_inll(unsigned short port);
extern void bios_outb(unsigned char byte, unsigned short port);
extern void bios_outw(unsigned short byte, unsigned short port);
extern void bios_outl(unsigned int byte, unsigned short port);
extern void bios_outll(unsigned long byte, unsigned short port);
#ifdef CONFIG_E2K_SIC
extern u8 bios_conf_inb(int domain, unsigned char bus, unsigned long port);
extern u16 bios_conf_inw(int domain, unsigned char bus, unsigned long port);
extern u32 bios_conf_inl(int domain, unsigned char bus, unsigned long port);
extern void bios_conf_outb(int domain, unsigned char bus, u8 byte,
unsigned long port);
extern void bios_conf_outw(int domain, unsigned char bus, u16 halwword,
unsigned long port);
extern void bios_conf_outl(int domain, unsigned char bus, u32 word,
unsigned long port);
extern u8 bios_ioh_e3s_inb(int domain, unsigned char bus, unsigned long port);
extern u16 bios_ioh_e3s_inw(int domain, unsigned char bus, unsigned long port);
extern u32 bios_ioh_e3s_inl(int domain, unsigned char bus, unsigned long port);
extern void bios_ioh_e3s_outb(int domain, unsigned char bus, unsigned char byte,
unsigned long port);
extern void bios_ioh_e3s_outw(int domain, unsigned char bus, u16 halfword,
unsigned long port);
extern void bios_ioh_e3s_outl(int domain, unsigned char bus, u32 word,
unsigned long port);
#endif /* CONFIG_E2K_SIC */
extern void rom_puts(char *s);
extern void rom_printk(char const *fmt, ...);
#endif /* _E2K_BOOT_IO_H_ */

18
arch/e2k/boot/bootblock.c Normal file
View File

@ -0,0 +1,18 @@
#include <asm/types.h>
#include <asm/bootinfo.h>
extern u64 __kernel_size;
const char gap[256] = {0};
const struct bootblock_struct boot_block =
{
info: {
signature : X86BOOT_SIGNATURE, /* signature */
kernel_size : (u64)&__kernel_size, /* kernel size */
kernel_args_string : CONFIG_CMDLINE, /* kernel command line */
},
bootblock_ver : BOOTBLOCK_VER, /* bootblock version number */
x86_marker : 0xAA55 /* x86 marker */
};

View File

@ -0,0 +1,37 @@
OUTPUT_FORMAT("elf64-e2k", "elf64-e2k", "elf64-e2k")
/* OUTPUT_ARCH(e2k) Defined by Makefile */
ENTRY(start)
SECTIONS {
_start = .;
.bootblock : {
_bootblock = .;
arch/e2k/boot/bootblock.o(.rodata)
_ebootblock = .;
}
. = _bootblock + 0x10000;
.loader : {
. += 0x6000;
*(.boot_entry)
*(.text)
*(EXCLUDE_FILE (arch/e2k/boot/cpiggy.o) .rodata)
*(.data)
_bss = .;
*(.bss)
_ebss = .;
}
.kernel : {
_kernel = .;
arch/e2k/boot/cpiggy.o(.rodata)
_ekernel = .;
}
.got : {
_got = .;
*(.got)
_egot = .;
}
_end = .;
}

View File

@ -0,0 +1,37 @@
OUTPUT_FORMAT("elf64-e2k", "elf64-e2k", "elf64-e2k")
/* OUTPUT_ARCH(e2k) Defined by Makefile */
ENTRY(start)
SECTIONS {
_start = .;
.bootblock : {
_bootblock = .;
arch/e2k/boot/bootblock.o(.rodata)
_ebootblock = .;
}
. = _bootblock + 0x10000;
.loader : {
. += 0x10000;
*(.boot_entry)
*(.text)
*(EXCLUDE_FILE (arch/e2k/boot/cpiggy.o) .rodata)
*(.data)
_bss = .;
*(.bss)
_ebss = .;
}
.kernel : {
_kernel = .;
arch/e2k/boot/cpiggy.o(.rodata)
_ekernel = .;
}
.got : {
_got = .;
*(.got)
_egot = .;
}
_end = .;
}

46
arch/e2k/boot/console.c Normal file
View File

@ -0,0 +1,46 @@
#include <linux/types.h>
#include <stdarg.h>
#include <asm/e2k.h>
#include "boot_io.h"
#if defined(CONFIG_BIOS)
#include "bios/bios.h"
#endif
static inline unsigned int e2k_rom_debug_inl(__u16 port)
{
unsigned int ret;
ret = NATIVE_READ_MAS_W(PHYS_X86_IO_BASE + port, MAS_IOADDR);
return ret;
}
static inline void e2k_rom_debug_outb(__u16 port, __u8 byte)
{
NATIVE_WRITE_MAS_B(PHYS_X86_IO_BASE + port, byte, MAS_IOADDR);
}
static inline void e2k_rom_debug_putc(char c)
{
while (e2k_rom_debug_inl(LMS_CONS_DATA_PORT));
e2k_rom_debug_outb(LMS_CONS_DATA_PORT, c);
e2k_rom_debug_outb(LMS_CONS_DATA_PORT, 0);
}
void console_probe(void)
{
#if defined(CONFIG_BIOS)
if (e2k_rom_debug_inl(LMS_CONS_DATA_PORT) != 0xFFFFFFFF) {
hardware.dbgport = 1;
};
#endif
}
void console_putc(char c)
{
e2k_rom_debug_putc(c);
}

720
arch/e2k/boot/decompress.c Normal file
View File

@ -0,0 +1,720 @@
#define DEBUG_BOOT_MODE 0
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <asm/pic.h>
#include <asm/bootinfo.h>
#include <asm/cpu_regs.h>
#include <asm/e2k_api.h>
#include <asm/head.h>
#include <asm/string.h>
#include <asm/mpspec.h>
#include <asm/kvm/hypercall.h>
#define BOOT_HEAP_SIZE 0x1000000
static unsigned long free_mem_ptr;
static unsigned long free_mem_end_ptr;
#define STATIC static
static void error_loop(char *s);
#define assert(condition) \
do { \
if (unlikely(!(condition))) \
error_loop("Assertion failed: " #condition); \
} while (0)
#ifdef CONFIG_KERNEL_GZIP
#include "../../../../lib/decompress_inflate.c"
#endif
#ifdef CONFIG_KERNEL_BZIP2
#include "../../../../lib/decompress_bunzip2.c"
#endif
#ifdef CONFIG_KERNEL_LZ4
#include "../../../../lib/decompress_unlz4.c"
#endif
#ifdef CONFIG_KERNEL_XZ
#define memmove memmove
#include "../../../../lib/decompress_unxz.c"
#endif
#ifdef CONFIG_KERNEL_LZMA
#include "../../../../lib/decompress_unlzma.c"
#endif
#ifdef CONFIG_KERNEL_LZO
#include "../../../../lib/decompress_unlzo.c"
#endif
/* Symbols defined by linker scripts */
extern char _bss[], _ebss[];
extern char _got[], _egot[];
extern char _kernel[], _ekernel[];
extern char _start[], _end[];
extern char __orig_kernel_size[];
struct mem_bank {
unsigned long mb_bottom;
unsigned long mb_top;
};
/* Add some number to account for banks being broken by reserved memory */
#define MAX_MEM_BANKS (L_MAX_MEM_NUMNODES * L_MAX_NODE_PHYS_BANKS + 64)
struct board_mem {
unsigned long bm_size;
unsigned bm_nBanks;
struct mem_bank bm_Banks[MAX_MEM_BANKS];
};
/*
* Put 'got_updating_in_progress' and 'unpacking_in_progress' into
* compiler-initialized .data section so that all processors can access it
* before .bss section is cleared.
*/
static int got_updating_in_progress = 1;
static int unpacking_in_progress = 1;
static boot_info_t *boot_info;
static unsigned long kernel_address;
static unsigned long io_area_phys_base;
#ifdef CONFIG_KVM_GUEST_KERNEL
#define STARTUP_TTABLE_ENTRY_OFFSET 0x10000
static unsigned long
dec_guest_mmio(unsigned long addr, u64 value, u8 size, u8 is_write)
{
unsigned long data[1];
if (is_write)
data[0] = value;
assert(!HYPERVISOR_guest_mmio_request(addr, data, size, is_write));
return data[0];
}
static void dec_writeb(u8 b, void __iomem *addr)
{
dec_guest_mmio((unsigned long) addr, b, 1, 1);
}
static u8 dec_readb(void __iomem *addr)
{
return dec_guest_mmio((unsigned long) addr, 0, 1, 0);
}
static u32 dec_readl(void __iomem *addr)
{
return dec_guest_mmio((unsigned long) addr, 0, 4, 0);
}
#else
#define STARTUP_TTABLE_ENTRY_OFFSET 0x6000
static void dec_writeb(u8 b, void __iomem *addr)
{
NATIVE_WRITE_MAS_B((unsigned long) addr, b, MAS_IOADDR);
}
static u8 dec_readb(void __iomem *addr)
{
return NATIVE_READ_MAS_B((unsigned long) addr, MAS_IOADDR);
}
static u32 dec_readl(void __iomem *addr)
{
return NATIVE_READ_MAS_W((unsigned long) addr, MAS_IOADDR);
}
#endif
static inline u8 am85c30_com_inb_command(u64 iomem_addr, u8 reg_num)
{
dec_writeb(reg_num, (void __iomem *) iomem_addr);
return dec_readb((void __iomem *) iomem_addr);
}
static inline void am85c30_com_outb(u64 iomem_addr, u8 byte)
{
dec_writeb(byte, (void __iomem *) iomem_addr);
}
static inline unsigned int dec_epic_is_bsp(void)
{
union cepic_ctrl reg;
reg.raw = dec_readl((void __iomem *)(EPIC_DEFAULT_PHYS_BASE + CEPIC_CTRL));
return reg.bits.bsp_core;
}
static inline unsigned int dec_apic_is_bsp(void)
{
return BootStrap(dec_readl((void __iomem *)(APIC_DEFAULT_PHYS_BASE + APIC_BSP)));
}
#define AM85C30_RR0 0x00
#define AM85C30_D2 (0x01 << 2)
static void am85c30_putc(unsigned long port, char c)
{
/*
* Output to ttyS0
*/
while ((am85c30_com_inb_command(port, AM85C30_RR0) & AM85C30_D2) == 0)
E2K_NOP(7);
am85c30_com_outb(port + 0x01, c);
/*
* Output to ttyS1
*/
port += 2;
while ((am85c30_com_inb_command(port, AM85C30_RR0) & AM85C30_D2) == 0)
E2K_NOP(7);
am85c30_com_outb(port + 0x01, c);
}
static void __putc(unsigned long port, char c)
{
am85c30_putc(port, c);
}
static void putc(char c)
{
unsigned long port = boot_info->serial_base;
if (!port)
return;
__putc(port, c);
if (c == '\n')
__putc(port, '\r');
}
static void puts(char *s)
{
while (*s)
putc(*s++);
}
/*
* Use global variables to prevent using data stack
*/
static const char hex_numbers_for_debug[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
static void put_u64(u64 num, int newline)
{
char u64_char[18];
int i;
if (newline) {
u64_char[16] = '\n';
u64_char[17] = 0;
} else {
u64_char[16] = 0;
}
for (i = 0; i < 16; i++) {
u64_char[15 - i] = hex_numbers_for_debug[num % 16];
num = num / 16;
}
puts(u64_char);
}
static void error(char *str)
{
puts(str);
putc('\n');
}
static void error_loop(char *s)
{
puts(s);
for (;;)
E2K_NOP(7);
}
static void probe_node_memory(bootblock_struct_t *bootblock, int node,
bank_info_t *bank_info, bank_info_t **bank_info_ex_p,
struct board_mem *bm)
{
boot_info_t *bootinfo = &bootblock->info;
bank_info_t *bank_info_ex = *bank_info_ex_p;
int bank, bm_bank;
for (bank = 0; bank < L_MAX_NODE_PHYS_BANKS; bank++) {
unsigned long bank_start, bank_end;
if (bank >= L_MAX_NODE_PHYS_BANKS_FUSTY) {
int banks_ex_id = bank_info - bootinfo->bios.banks_ex;
if (bank == L_MAX_NODE_PHYS_BANKS_FUSTY) {
bank_info = bank_info_ex;
banks_ex_id = bank_info -
bootinfo->bios.banks_ex;
}
if (banks_ex_id >= L_MAX_PHYS_BANKS_EX) {
bank_info_ex = bank_info;
puts("WARNING: Node has phys banks in extended area, but extended area is full, ignored\n");
goto out;
}
}
if (bank_info->size == 0) {
if (bank >= L_MAX_NODE_PHYS_BANKS_FUSTY)
bank_info_ex = bank_info + 1;
goto out; /* no more banks on node */
}
bank_start = bank_info->address;
bank_end = bank_start + bank_info->size;
#ifdef DEBUG
puts("Memory bank from 0x");
put_u64(bank_start, false);
puts(" to 0x");
put_u64(bank_end, true);
#endif
bm_bank = bm->bm_nBanks;
if (bm_bank > 0 &&
bm->bm_Banks[bm_bank - 1].mb_top == bank_start) {
/* Continue previous bank */
--bm_bank;
bm->bm_Banks[bm_bank].mb_top = bank_end;
} else {
/* Add new bank */
assert(bm_bank < MAX_MEM_BANKS);
bm->bm_Banks[bm_bank].mb_bottom = bank_start;
bm->bm_Banks[bm_bank].mb_top = bank_end;
++bm->bm_nBanks;
}
++bank_info;
}
if (bank == L_MAX_NODE_PHYS_BANKS) {
bank_info_ex = bank_info;
puts("WARNING: Node last phys bank for node in extended area is not null, ignored\n");
goto out;
}
if (bank < L_MAX_NODE_PHYS_BANKS_FUSTY) {
for (; bank < L_MAX_NODE_PHYS_BANKS_FUSTY; bank++) {
if (!bank_info++->size)
goto out;
}
} else {
bank_info_ex = bank_info;
}
while (bank_info_ex++->size) {
if (++bank >= L_MAX_NODE_PHYS_BANKS) {
puts("WARNING: Node last phys bank for node in extended area is not null, ignored\n");
break;
}
if (bank_info_ex - bootinfo->bios.banks_ex >=
L_MAX_PHYS_BANKS_EX) {
puts("WARNING: Node last phys bank in extended area is not null, ignored\n");
break;
}
}
out:
*bank_info_ex_p = bank_info_ex;
}
/*
* probe_memory - initialize free memory list
*/
static void probe_memory(bootblock_struct_t *bootblock, struct board_mem *bm)
{
boot_info_t *bootinfo = &bootblock->info;
bank_info_t *bank_info_ex = bootinfo->bios.banks_ex;
u_int64_t phys_nodes_map = bootinfo->nodes_map;
int node;
for (node = 0; node < L_MAX_MEM_NUMNODES; node++) {
bank_info_t *bank_info = bootinfo->nodes_mem[node].banks;
if (!(phys_nodes_map & (1UL << node)) || bank_info->size == 0)
continue;
probe_node_memory(bootblock, node, bank_info,
&bank_info_ex, bm);
}
}
static int intersect(struct mem_bank *b1, const struct mem_bank *b2,
struct mem_bank *b3, int ignore_busy)
{
assert(b1->mb_top >= b1->mb_bottom && b2->mb_top >= b2->mb_bottom);
if (b1->mb_bottom < b2->mb_bottom && b1->mb_top > b2->mb_top) {
/* Cut one bank into two */
b3->mb_bottom = b1->mb_bottom;
b3->mb_top = b2->mb_bottom;
b3++;
b3->mb_bottom = b2->mb_top;
b3->mb_top = b1->mb_top;
return 2;
}
if (b1->mb_bottom >= b2->mb_top || b1->mb_top <= b2->mb_bottom) {
/* No intersection */
*b3 = *b1;
} else {
/* Do not allow double reservations */
assert(ignore_busy || (b1->mb_bottom <= b2->mb_bottom &&
b1->mb_top >= b2->mb_top));
/* Intersection */
b3->mb_bottom = (b1->mb_bottom < b2->mb_bottom) ?
b1->mb_bottom : b2->mb_top;
b3->mb_top = (b1->mb_top > b2->mb_top) ? b1->mb_top :
b2->mb_bottom;
}
if (b3->mb_bottom < b3->mb_top)
return 1;
*b3 = (struct mem_bank) {0, 0};
return 0;
}
static void sub(struct board_mem *from, const struct mem_bank *b,
struct board_mem *to, int ignore_busy)
{
int n, i;
for(i = 0, n = 0; i < from->bm_nBanks; i++)
n += intersect(&from->bm_Banks[i], b,
&to->bm_Banks[n], ignore_busy);
to->bm_nBanks = n;
}
static struct board_mem bm_tmp;
static void reserve_memory_area(struct board_mem *bm, unsigned long phys_addr,
unsigned long mem_size, int ignore_busy,
char *name)
{
struct mem_bank reserved;
unsigned long end_addr = phys_addr + mem_size;
assert(mem_size);
phys_addr = round_down(phys_addr, PAGE_SIZE);
end_addr = round_up(end_addr, PAGE_SIZE);
mem_size = end_addr - phys_addr;
#ifdef DEBUG
puts("Reserved ");
puts(name);
puts(" area: address 0x");
put_u64(phys_addr, false);
puts(", size 0x");
put_u64(mem_size, true);
#endif
reserved.mb_bottom = phys_addr;
reserved.mb_top = end_addr;
sub(bm, &reserved, &bm_tmp, ignore_busy);
/* Do not allow double reservations */
assert(ignore_busy || bm->bm_nBanks != bm_tmp.bm_nBanks ||
memcmp(bm->bm_Banks, &bm_tmp.bm_Banks, sizeof(*bm)));
memcpy(bm, &bm_tmp, sizeof(*bm));
}
/*
* Reserve the needed memory from MP - tables
*/
static void boot_reserve_mp_table(boot_info_t *bootinfo, struct board_mem *bm)
{
struct intel_mp_floating *mpf;
if (bootinfo->mp_table_base == 0UL)
return;
/*
* MP floating specification table
*/
reserve_memory_area(bm, bootinfo->mp_table_base, PAGE_SIZE,
1, "MP floating table");
mpf = (struct intel_mp_floating *) bootinfo->mp_table_base;
/*
* MP configuration table
*/
if (mpf->mpf_physptr != 0UL)
reserve_memory_area(bm, mpf->mpf_physptr, PAGE_SIZE,
1, "MP configuration table");
}
static void reserve_memory(boot_info_t *bootinfo, struct board_mem *bm)
{
unsigned long area_base, area_size;
psp_struct_t PSP = {{{0}}, {{0}}};
pcsp_struct_t PCSP = {{{0}}, {{0}}};
e2k_usbr_t USBR = {{0}};
usd_struct_t USD = {{{0}}, {{0}}};
int bank;
reserve_memory_area(bm, 0, PAGE_SIZE, 0, "0-page");
reserve_memory_area(bm, (unsigned long)_start,
(unsigned long) (_end - _start), 0, "kernel image");
reserve_memory_area(bm, 640 * 1024 /* ROM, VGA ... */,
(1024 - 640) * 1024, 0, "PC");
for (bank = 0; bank < bootinfo->num_of_busy; bank++) {
bank_info_t *busy_area = &bootinfo->busy[bank];
reserve_memory_area(bm, busy_area->address, busy_area->size,
1, "BIOS data");
}
if (boot_info->ramdisk_size)
reserve_memory_area(bm, boot_info->ramdisk_base,
boot_info->ramdisk_size, 1, "ramdisk");
reserve_memory_area(bm, 0x7ee00000, PAGE_SIZE, 1, "APIC page");
boot_reserve_mp_table(bootinfo, bm);
PSP = READ_PSP_REG();
reserve_memory_area(bm, PSP.PSP_base, PSP.PSP_size, 1,
"kernel boot-time procedures stack");
PCSP = READ_PCSP_REG();
reserve_memory_area(bm, PCSP.PCSP_base, PCSP.PCSP_size, 1,
"kernel boot-time procedure chain stack");
USBR = read_USBR_reg();
area_base = USBR.USBR_base;
read_USD_reg(&USD);
area_size = area_base - USD.USD_base + USD.USD_size;
area_base -= area_size;
reserve_memory_area(bm, area_base, area_size, 1,
"kernel boot-time data stack");
}
static unsigned long find_free_memory(struct board_mem *bm,
unsigned long size, unsigned long align)
{
unsigned long start, end;
struct mem_bank *bank;
int search_low = 0;
int i;
retry:
for (i = 0; i < bm->bm_nBanks; i++) {
bank = &bm->bm_Banks[i];
start = round_up(bank->mb_bottom, align);
end = round_down(bank->mb_top, align);
if (start < end && size <= end - start &&
(search_low || start >= 0x100000000UL)) {
reserve_memory_area(bm, start, size, 0, "allocated");
return start;
}
}
/* First try to find non-DMA memory */
if (!search_low) {
search_low = 1;
goto retry;
}
return -ENOMEM;
}
static __always_inline void jump_to_image(unsigned long kernel_address,
int n, bootblock_struct_t *bootblock)
{
e2k_oscud_lo_t oscud_lo;
/*
* Before jumping we must correct %oscud and %cud
* registers which contain kernel entry address.
*/
oscud_lo = READ_OSCUD_LO_REG();
AS(oscud_lo).base = kernel_address;
WRITE_OSCUD_LO_REG(oscud_lo);
WRITE_CUD_LO_REG(oscud_lo);
E2K_JUMP_ABSOLUTE_WITH_ARGUMENTS_2(kernel_address + STARTUP_TTABLE_ENTRY_OFFSET,
n, bootblock);
}
static struct board_mem memory;
extern int machdep_setup_features(int cpu, int revision);
/*
* Now we can use global variables (i.e. machine) and linker defined symbols (i.e. _bss)
*/
noinline void decompress_kernel_updated_got(int n, bootblock_struct_t *bootblock,
int bsp, e2k_idr_t idr, unsigned long orig_kernel_size)
{
struct board_mem *bm = &memory;
int ret;
if (!bsp) {
while (unpacking_in_progress)
E2K_NOP(7);
/* Barrier between reading `unpacking_in_progress'
* and reading unpacked kernel */
smp_rmb();
jump_to_image(kernel_address, n, bootblock);
}
/*
* Setup machine features
*/
assert(!machdep_setup_features(idr.IDR_mdl, idr.IDR_rev));
/*
* Clear .bss (guest variant uses machine)
*/
memset(_bss, 0, _ebss - _bss);
/*
* Initialize console and say hello
*/
boot_info = &bootblock->info;
if (read_IDR_reg().mdl == IDR_E1CP_MDL)
io_area_phys_base = E2K_LEGACY_SIC_IO_AREA_PHYS_BASE;
else
io_area_phys_base = E2K_FULL_SIC_IO_AREA_PHYS_BASE;
puts("\nDecompressor started\n");
#ifdef DEBUG
puts("Cleared .bss at 0x");
put_u64(_bss, false);
puts(", size 0x");
put_u64(_ebss - _bss, true);
#endif
/*
* Mark free and reserved memory
*/
probe_memory(bootblock, bm);
reserve_memory(&bootblock->info, bm);
/*
* Find free memory area for heap
*/
free_mem_ptr = find_free_memory(bm, BOOT_HEAP_SIZE + PAGE_SIZE, 8);
if (IS_ERR_VALUE(free_mem_ptr))
error_loop("ERROR: could not find free memory area for heap\n");
/* free_mem_ptr must not be equal to 0 */
if (!free_mem_ptr)
free_mem_ptr += PAGE_SIZE;
free_mem_end_ptr = free_mem_ptr + BOOT_HEAP_SIZE;
puts("Heap from 0x");
put_u64(free_mem_ptr, false);
puts(" to 0x");
put_u64(free_mem_end_ptr, true);
/*
* Decompress the kernel
*/
kernel_address = find_free_memory(bm,
orig_kernel_size, 0x400000);
if (IS_ERR_VALUE(kernel_address))
error_loop("ERROR: could not find free memory area to unpack kernel to\n");
puts("Unpacking 0x");
put_u64(orig_kernel_size, false);
puts(" bytes from 0x");
put_u64((unsigned long)_kernel, false);
puts(" to 0x");
put_u64(kernel_address, false);
puts("...\n");
ret = __decompress(_kernel, _ekernel - _kernel, NULL,
NULL, (char *) kernel_address, 0, NULL, error);
if (ret)
error_loop("ERROR: failed to unpack kernel\n");
puts("Done\n");
/*
* Tell others they can proceed
*/
bootblock->info.kernel_base = kernel_address;
bootblock->info.kernel_size = orig_kernel_size;
smp_wmb(); /* Wait for unpacked kernel and bootblock changes */
unpacking_in_progress = 0;
/*
* Jump to the kernel
*/
jump_to_image(kernel_address, n, bootblock);
}
/*
* Updating GOT should be done in a separate function. Otherwise compiler might put
* GOT load before GOT update (even ignoring the memory clobbers).
* Using global variables isn't allowed here.
*/
__section(.boot_entry)
void decompress_kernel(int n, bootblock_struct_t *bootblock)
{
unsigned long load_offset, got, egot, addr;
unsigned long orig_kernel_size = 0;
e2k_idr_t idr;
int bsp;
/*
* Only bootstrap processor proceeds to unpacking
*/
idr = read_IDR_reg();
if (idr.mdl >= IDR_E12C_MDL)
bsp = dec_epic_is_bsp();
else
bsp = dec_apic_is_bsp();
if (!bsp) {
while (got_updating_in_progress)
E2K_NOP(7);
/* Barrier between reading `got_updating_in_progress'
* and reading GOT */
smp_rmb();
} else {
load_offset = AS(READ_OSCUD_LO_REG()).base - 0x10000;
got = (unsigned long)_got + load_offset;
egot = (unsigned long)_egot + load_offset;
/* orig_kernel_size should not be shifted by load_offset */
orig_kernel_size = (unsigned long)__orig_kernel_size;
/* Update GOT */
for (addr = got; addr < egot; addr += 8)
*((unsigned long *)addr) += load_offset;
smp_wmb(); /* Wait for GOT changes */
got_updating_in_progress = 0;
}
decompress_kernel_updated_got(n, bootblock, bsp, idr, orig_kernel_size);
}

262
arch/e2k/boot/defkeymap.c Normal file
View File

@ -0,0 +1,262 @@
/* Do not edit this file! It was automatically generated by */
/* loadkeys --mktable defkeymap.map > defkeymap.c */
#include <linux/types.h>
#include <linux/keyboard.h>
#include <linux/kd.h>
u_short plain_map[NR_KEYS] = {
0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009,
0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c,
0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307,
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03c, 0xf10a,
0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
u_short shift_map[NR_KEYS] = {
0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009,
0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53,
0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c,
0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e,
0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307,
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a,
0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
u_short altgr_map[NR_KEYS] = {
0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200,
0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73,
0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200,
0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76,
0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510,
0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911,
0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b,
0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516,
0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
u_short ctrl_map[NR_KEYS] = {
0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c,
0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307,
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf10a,
0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
u_short shift_ctrl_map[NR_KEYS] = {
0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013,
0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307,
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
u_short alt_map[NR_KEYS] = {
0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809,
0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873,
0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b,
0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876,
0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c,
0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907,
0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901,
0xf902, 0xf903, 0xf900, 0xf310, 0xf206, 0xf200, 0xf83c, 0xf50a,
0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
u_short ctrl_alt_map[NR_KEYS] = {
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813,
0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307,
0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a,
0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c,
0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
};
ushort *key_maps[MAX_NR_KEYMAPS] = {
plain_map, shift_map, altgr_map, NULL,
ctrl_map, shift_ctrl_map, NULL, NULL,
alt_map, NULL, NULL, NULL,
ctrl_alt_map, NULL
};
unsigned int keymap_count = 7;
/*
* Philosophy: most people do not define more strings, but they who do
* often want quite a lot of string space. So, we statically allocate
* the default and allocate dynamically in chunks of 512 bytes.
*/
char func_buf[] = {
'\033', '[', '[', 'A', 0,
'\033', '[', '[', 'B', 0,
'\033', '[', '[', 'C', 0,
'\033', '[', '[', 'D', 0,
'\033', '[', '[', 'E', 0,
'\033', '[', '1', '7', '~', 0,
'\033', '[', '1', '8', '~', 0,
'\033', '[', '1', '9', '~', 0,
'\033', '[', '2', '0', '~', 0,
'\033', '[', '2', '1', '~', 0,
'\033', '[', '2', '3', '~', 0,
'\033', '[', '2', '4', '~', 0,
'\033', '[', '2', '5', '~', 0,
'\033', '[', '2', '6', '~', 0,
'\033', '[', '2', '8', '~', 0,
'\033', '[', '2', '9', '~', 0,
'\033', '[', '3', '1', '~', 0,
'\033', '[', '3', '2', '~', 0,
'\033', '[', '3', '3', '~', 0,
'\033', '[', '3', '4', '~', 0,
'\033', '[', '1', '~', 0,
'\033', '[', '2', '~', 0,
'\033', '[', '3', '~', 0,
'\033', '[', '4', '~', 0,
'\033', '[', '5', '~', 0,
'\033', '[', '6', '~', 0,
'\033', '[', 'M', 0,
'\033', '[', 'P', 0,
};
char *funcbufptr = func_buf;
int funcbufsize = sizeof(func_buf);
int funcbufleft = 0; /* space left */
char *func_table[MAX_NR_FUNC] = {
func_buf + 0,
func_buf + 5,
func_buf + 10,
func_buf + 15,
func_buf + 20,
func_buf + 25,
func_buf + 31,
func_buf + 37,
func_buf + 43,
func_buf + 49,
func_buf + 55,
func_buf + 61,
func_buf + 67,
func_buf + 73,
func_buf + 79,
func_buf + 85,
func_buf + 91,
func_buf + 97,
func_buf + 103,
func_buf + 109,
func_buf + 115,
func_buf + 120,
func_buf + 125,
func_buf + 130,
func_buf + 135,
func_buf + 140,
func_buf + 145,
NULL,
NULL,
func_buf + 149,
NULL,
};
struct kbdiacruc accent_table[MAX_DIACR] = {
{'`', 'A', 0300}, {'`', 'a', 0340},
{'\'', 'A', 0301}, {'\'', 'a', 0341},
{'^', 'A', 0302}, {'^', 'a', 0342},
{'~', 'A', 0303}, {'~', 'a', 0343},
{'"', 'A', 0304}, {'"', 'a', 0344},
{'O', 'A', 0305}, {'o', 'a', 0345},
{'0', 'A', 0305}, {'0', 'a', 0345},
{'A', 'A', 0305}, {'a', 'a', 0345},
{'A', 'E', 0306}, {'a', 'e', 0346},
{',', 'C', 0307}, {',', 'c', 0347},
{'`', 'E', 0310}, {'`', 'e', 0350},
{'\'', 'E', 0311}, {'\'', 'e', 0351},
{'^', 'E', 0312}, {'^', 'e', 0352},
{'"', 'E', 0313}, {'"', 'e', 0353},
{'`', 'I', 0314}, {'`', 'i', 0354},
{'\'', 'I', 0315}, {'\'', 'i', 0355},
{'^', 'I', 0316}, {'^', 'i', 0356},
{'"', 'I', 0317}, {'"', 'i', 0357},
{'-', 'D', 0320}, {'-', 'd', 0360},
{'~', 'N', 0321}, {'~', 'n', 0361},
{'`', 'O', 0322}, {'`', 'o', 0362},
{'\'', 'O', 0323}, {'\'', 'o', 0363},
{'^', 'O', 0324}, {'^', 'o', 0364},
{'~', 'O', 0325}, {'~', 'o', 0365},
{'"', 'O', 0326}, {'"', 'o', 0366},
{'/', 'O', 0330}, {'/', 'o', 0370},
{'`', 'U', 0331}, {'`', 'u', 0371},
{'\'', 'U', 0332}, {'\'', 'u', 0372},
{'^', 'U', 0333}, {'^', 'u', 0373},
{'"', 'U', 0334}, {'"', 'u', 0374},
{'\'', 'Y', 0335}, {'\'', 'y', 0375},
{'T', 'H', 0336}, {'t', 'h', 0376},
{'s', 's', 0337}, {'"', 'y', 0377},
{'s', 'z', 0337}, {'i', 'j', 0377},
};
unsigned int accent_table_size = 68;

View File

@ -0,0 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_MCST) += e1cp_e1cmt_tablet.dts
dtb-$(CONFIG_MCST) += e1cp_m2e-uvp.dts
dtb-$(CONFIG_MCST) += e1cp_mbe1c-pc.dts
dtb-$(CONFIG_MCST) += e1cp_p2p8-sip-s1.dts
dtb-$(CONFIG_MCST) += e2c_mono-pc.dts
dtb-$(CONFIG_MCST) += e4c_apk-pc4c.dts
dtb-$(CONFIG_MCST) += e4c_el-2s-4.dts
dtb-$(CONFIG_MCST) += e4c_mbe2s-pc.dts
dtb-$(CONFIG_MCST) += e8c2_uatx_se.dts
dtb-$(CONFIG_MCST) += e8c_mbe8c-pc.dts
dtb-$(CONFIG_MCST) += e8c_swtx.dts

View File

@ -0,0 +1,212 @@
/*
* E1CMT
* TVGI.469555.374
* (Tablet)
*/
/dts-v1/;
/*#include <dt-bindings/input/input.h>*/
/*#include <dt-bindings/interrupt-controller/irq.h>*/
/*#include <dt-bindings/gpio/gpio.h>*/
/ {
/* version = ""; */
model = "e1c+,mcst,e1cmt,tablet";
compatible = "mcst,e1cmt";
#address-cells = <1>;
#size-cells = <0>;
/* IOHUB2 I2C */
l_i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
compatible = "l_i2c";
label = "iohub2 i2c";
i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
lm96163@4c {
/* hwmon/lm63.ko (DD2:LM96163CISD) */
compatible = "lm63";
reg = <0x4c>;
label = "FAN Control (X1)";
temp1_label = "Internal Temp";
temp2_label = "IOHUB Temp";
};
};
i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
pca9534@20 {
/* gpio/gpio-pca953x.ko (DD20:PCA9534PW) */
compatible = "nxp,pca9534";
reg = <0x20>;
label = "spmc_gpio";
gpio-controller;
ngpios = <8>;
#gpio-cells = <2>;
gpio-line-names =
"SPMC_BATLOW_3V3#",
"SPMC_AC_PWR_PRSNT_3V3",
"none",
"none",
"none",
"none",
"none",
"none";
};
};
i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
/* Pressure Sensor */
bmp280@76 {
/* iio/pressure/bmp280.ko (DA14:BMP280) */
compatible = "bosch,bmp280";
reg = <0x76>;
label = "pressure sensor";
};
/* Light Sensor */
opt3001@44 {
/* iio/light/opt3001.ko (DD17:OPT3001DNPT) */
compatible = "ti,opt3001";
reg = <0x44>;
label = "light sensor";
};
/* (DA17:L96) - GPS @20, @21 */
};
i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
/* Battery Management unit */
bq40z60@b {
/* power/supply/sbs-batterypow.ko (DA11:BQ40Z60RHBT) */
compatible = "sbs,sbs-battery";
reg = <0xb>;
label = "battery management";
sbs,i2c-retry-count = <2>;
sbs,poll-retry-count = <10>;
/* sbs,battery-detect-gpios = <&gpio0 ? 0>; */
};
/* (X5:DF52-4S-0.8H(21)) */
};
};
/* PMBUS I2C */
pmc_i2c {
#address-cells = <1>;
#size-cells = <0>;
compatible = "pmc_i2c";
label = "pmbus i2c";
/* touchscreen sensor */
gt9110@14 {
/* input/touchscreen/goodix.ko (X2:DD???:) */
compatible = "goodix,gt9110";
reg = <0x14>;
label = "touchscreen";
interrupt-parent = <&gpio0>;
/*interrupts = <0 0>;*/
irq-gpios = <&gpio0 0 0>; /* TS_INT GPIO_ACTIVE_HIGH */
reset-gpios = <&gpio0 1 0>; /* TS_RST GPIO_ACTIVE_HIGH */
/*
touchscreen-inverted-x = 0;
touchscreen-inverted-y = 0;
touchscreen-swapped-x-y = 0;
*/
};
/* 9 Axis MEMS MotionTracking - is 2 in 1 package: */
icm20948@69 {
/* FIXME: use new driver */
/* 1) 3-axis accelerometer, 3-axis gyroscope */
/* iio/imu/inv_mpu6050/inv-mpu6050-i2c.ko (DD16:ICM-20948) */
compatible = "invensense,mpu9255"; /* mpu9250 ? */
reg = <0x69>;
label = "accelerometer, gyroscope";
interrupt-parent = <&gpio0>;
/* irq-gpios = <&gpio0 2 1>; /* INT_ICM GPIO_ACTIVE_LOW */
interrupts = <2 8>; /* INT_ICM IRQ_TYPE_LEVEL_LOW */
/*mount-matrix = x0, y0, z0, x1, y1, z1, x2, y2, z2;*/
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
akm8963@c {
/* ak8975.ko (DD16:ICM-20948) */
compatible = "ak,ak8975";
reg = <0x0c>;
label = "compass";
};
};
};
/* (DD29:IT6251FN) - LVDS to DisplayPort 1.1a Transmitter
* error!?! --> connect to I2C_GFX3_DDC_1V8 (TP11, TP12)
*/
};
/* IOHUB2 SPI */
l_spi@0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "l_spi";
reg = <0>;
label = "iohub2 spi";
boot@0 {
/* DD23:S25FL064P0XNFI001) */
compatible = "mcst,boot";
reg = <0>;
spi-max-frequency = <25000000>;
};
rtc-cy14b101p@1 {
/* (DD24:CY14B101PA-SFXI) */
compatible = "rtc-cy14b101p";
reg = <1>;
spi-max-frequency = <12500000>;
};
};
/* IOHUB2 GPIO */
gpio0:l_gpio@0 {
compatible = "mcst,gpio";
reg = <0x0>;
label = "L-GPIO";
gpio-controller;
ngpios = <32>;
#gpio-cells = <2>;
gpio-line-names =
/* 0.. 1 */ "TS_INT", "TS_RST", /* touchscreen */
/* 2.. 3 */ "INT_ICM", "nc", /* MotionTracking */
/* 4.. 7 */ "GPSPPS", "TP10", "S3", "S4",
/* 8..11 */ "nc", "nc", "nc", "nc",
/* 12..15 */ "nc", "nc", "nc", "nc",
/* 16..19 */ "nc", "nc", "nc", "nc",
/* 20..23 */ "nc", "nc", "nc", "nc",
/* 24..27 */ "nc", "nc", "nc", "nc",
/* 28..31 */ "nc", "nc", "nc", "nc";
};
};

View File

@ -0,0 +1,141 @@
/*
* M2E-UVP
* TVGI.469555.385 ver.1
* (UVM_KMI)
*/
/dts-v1/;
/*#include <dt-bindings/input/input.h>*/
/ {
/* version = ""; */
model = "e1c+,mcst,m2e-uvp";
compatible = "mcst,m2e-uvp";
#address-cells = <1>;
#size-cells = <0>;
/* IOHUB2 I2C */
l_i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
compatible = "l_i2c";
label = "iohub2 i2c";
i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
lm96163@4c {
/* hwmon/lm63.ko (DD19:LM96163CISD) */
compatible = "lm63";
reg = <0x4c>;
label = "IOHUB Temp Sensor";
temp1_label = "Internal Temp";
temp2_label = "IOHUB Temp";
/* no fan control */
};
};
i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
/* pndt006@38 from M1R:i2c@1 */
/* KSZ9896CTX@64 from PK-UVP:I2C_1 (M1R:i2c@1) */
};
i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
/* KSZ9896CTX@64 from PK-UVP:I2C_2 (M1R:i2c@2) */
};
i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
/* config SENSORS_PMBUS */
pndt006@10 {
/* hwmon/pmbus/pmbus.ko (DA7:PNDT006A0X3-SRZ) */
compatible = "pmbus";
reg = <0x10>;
label = "+1V0_P8 (in +3V3)";
};
pndt006@14 {
/* hwmon/pmbus/pmbus.ko (DA8:PNDT006A0X3-SRZ) */
compatible = "pmbus";
reg = <0x14>;
label = "+2V5_IOH (in +5V)";
};
};
};
/* PMBUS I2C */
pmc_i2c {
#address-cells = <1>;
#size-cells = <0>;
compatible = "pmc_i2c";
label = "pmbus i2c";
/* config SENSORS_PMBUS */
pndt012@10 {
/* hwmon/pmbus/pmbus.ko (DA2:PNDT012A0X3-SRZ) */
compatible = "pmbus";
reg = <0x10>;
label = "+0V9_CPU (in +3V3)";
};
pndt006@13 {
/* hwmon/pmbus/pmbus.ko (DA3:PNDT006A0X3-SRZ) */
compatible = "pmbus";
reg = <0x13>;
label = "+PWR_MC (in +5V)";
};
};
/* IOHUB2 SPI */
l_spi@0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "l_spi";
reg = <0>;
label = "iohub2 spi";
boot@0 {
/* DD13:S25FL128SAGNFI001) */
compatible = "mcst,boot";
reg = <0>;
spi-max-frequency = <25000000>;
};
rtc-cy14b101p@1 {
/* (DD14:CY14B101PA-SFXI) */
compatible = "rtc-cy14b101p";
reg = <1>;
spi-max-frequency = <12500000>;
};
};
/* IOHUB2 GPIO */
gpio0:l_gpio@0 {
compatible = "mcst,gpio";
reg = <0x0>;
label = "L-GPIO";
gpio-controller;
ngpios = <32>;
#gpio-cells = <2>;
gpio-line-names =
/* 0.. 3 */ "nc", "nc", "nc", "nc",
/* 4.. 7 */ "GA0", "GA1", "nc", "nc",
/* 8..11 */ "nc", "nc", "nc", "nc",
/* 12..15 */ "nc", "nc", "nc", "nc",
/* 16..19 */ "nc", "nc", "nc", "nc",
/* 20..23 */ "nc", "nc", "nc", "nc",
/* 24..27 */ "nc", "nc", "nc", "nc",
/* 28..31 */ "nc", "nc", "nc", "nc";
};
};

View File

@ -0,0 +1,124 @@
/*
* MBE1C-PC
* TVGI.469555.331
* (101-PC)
*/
/dts-v1/;
/*#include <dt-bindings/input/input.h>*/
/ {
/* version = ""; */
model = "e1c+,mcst,mbe1c-pc,101-pc";
compatible = "mcst,mbe1c-pc";
#address-cells = <1>;
#size-cells = <0>;
/* IOHUB2 I2C */
l_i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
compatible = "l_i2c";
label = "iohub2 i2c";
i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
lm96163@4c {
/* hwmon/lm63.ko (DD9:LM96163CISD) */
compatible = "lm63";
reg = <0x4c>;
label = "FAN Control (X29)";
temp1_label = "Internal Temp";
temp2_label = "IOHUB Temp";
};
/* (X32, X33) DIMMs: 0x18 0x1A */
};
i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
/* empty */
};
i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
/* empty */
};
i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
/* config SENSORS_PMBUS */
pdt012@10 {
/* hwmon/pmbus/pmbus.ko (DA3:PDT012A0X3) */
compatible = "pmbus";
reg = <0x10>;
label = "+1V0_P8";
};
pdt012@14 {
/* hwmon/pmbus/pmbus.ko (DA4:PDT012A0X3) */
compatible = "pmbus";
reg = <0x14>;
label = "+2V5_IOH";
};
};
};
/* PMBUS I2C */
pmc_i2c {
#address-cells = <1>;
#size-cells = <0>;
compatible = "pmc_i2c";
label = "pmbus i2c";
/* config SENSORS_PMBUS */
udt020@10 {
/* hwmon/pmbus/pmbus.ko (DA6:UDT020A0X3-SRZ) */
compatible = "pmbus";
reg = <0x10>;
label = "+0V9_CPU";
};
udt020@13 {
/* hwmon/pmbus/pmbus.ko (DA7:UDT020A0X3-SRZ) */
compatible = "pmbus";
reg = <0x13>;
label = "+PWR_MC";
};
pdt012@14 {
/* hwmon/pmbus/pmbus.ko (DA5:PDT012A0X3) */
compatible = "pmbus";
reg = <0x14>;
label = "+1V8_CPU";
};
};
/* IOHUB2 SPI */
l_spi@0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "l_spi";
reg = <0>;
label = "iohub2 spi";
boot@0 {
compatible = "mcst,boot";
reg = <0>;
spi-max-frequency = <25000000>;
};
rtc-cy14b101p@1 {
compatible = "rtc-cy14b101p";
reg = <1>;
spi-max-frequency = <12500000>;
};
};
};

View File

@ -0,0 +1,184 @@
/*
* P2P8-SIP-S1
* TVGI.469555.371 ver.1
* Razbrakovshik
*/
/dts-v1/;
/*#include <dt-bindings/input/input.h>*/
/ {
/* version = ""; */
model = "e1c+,mcst,p2p8-sip-s1,razbrakovshik";
compatible = "mcst,p2p8-sip-s1";
#address-cells = <1>;
#size-cells = <0>;
/* IOHUB2 I2C */
l_i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
compatible = "l_i2c";
label = "iohub2 i2c";
i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
lm96163@4c {
/* hwmon/lm63.ko (DD75:LM96163CISD) */
compatible = "lm63";
reg = <0x4c>;
label = "FAN Control (X27)";
temp1_label = "Internal Temp";
temp2_label = "IOHUB Temp";
};
};
i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
spmc_gpio:pca9534@20 {
/* gpio/gpio-pca953x.ko (DD74:PCA9534PW) */
compatible = "nxp,pca9534";
reg = <0x20>;
label = "spmc_gpio";
gpio-controller;
ngpios = <8>;
#gpio-cells = <2>;
gpio-line-names =
"SPMC_BATLOW_3V3#",
"SPMC_AC_PWR_PRSNT_3V3",
"none",
"none",
"none",
"none",
"none",
"none";
};
};
i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
pe1_p8_gpio:pca9534@21 {
/* gpio/gpio-pca953x.ko (DD112:PCA9534PW) */
compatible = "nxp,pca9534";
reg = <0x21>;
label = "PE1_P8_GPIO";
gpio-controller;
ngpios = <8>;
#gpio-cells = <2>;
gpio-line-names =
"CTRL_PE1_PRSNT0#",
"CTRL_PE1_PRSNT1#",
"CTRL_PE1_PRSNT2#",
"CTRL_PE1_PRSNT3#",
"CTRL_PCIE_X1_1_CONNECT",
"CTRL_PCIE_X1_23_CONNECT",
"none",
"none";
};
};
i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
/* config SENSORS_PMBUS */
pdt012@10 {
/* hwmon/pmbus/pmbus.ko (DA16:PDT012A0X3) */
compatible = "pmbus";
reg = <0x10>;
label = "+1V0_P8";
};
pdt012@12 {
/* hwmon/pmbus/pmbus.ko (DA33:PDT012A0X3) */
compatible = "pmbus";
reg = <0x12>;
label = "+3V0_P8";
};
pdt012@14 {
/* hwmon/pmbus/pmbus.ko (DA15:PDT012A0X3) */
compatible = "pmbus";
reg = <0x14>;
label = "+2V5_P8";
};
};
};
/* PMBUS I2C */
pmc_i2c {
#address-cells = <1>;
#size-cells = <0>;
compatible = "pmc_i2c";
label = "pmbus i2c";
/* config SENSORS_PMBUS */
pdt012@10 {
/* hwmon/pmbus/pmbus.ko (DA7:PDT012A0X3) */
compatible = "pmbus";
reg = <0x10>;
label = "+0V9_NB";
};
pdt012@11 {
/* hwmon/pmbus/pmbus.ko (DA8:PDT012A0X3) */
compatible = "pmbus";
reg = <0x11>;
label = "+PWR_3D";
};
pdt012@12 {
/* hwmon/pmbus/pmbus.ko (DA9:PDT012A0X3) */
compatible = "pmbus";
reg = <0x12>;
label = "+PWR_CORE";
};
udt020@13 {
/* hwmon/pmbus/pmbus.ko (DA1:UDT020A0X3) */
compatible = "pmbus";
reg = <0x13>;
label = "+PWR_MC";
};
pdt012@14 {
/* hwmon/pmbus/pmbus.ko (DA10:PDT012A0X3) */
compatible = "pmbus";
reg = <0x14>;
label = "+1V8_P2";
};
};
/* IOHUB2 SPI */
l_spi@0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "l_spi";
reg = <0>;
label = "iohub2 spi";
boot@0 {
compatible = "mcst,boot";
reg = <0>;
spi-max-frequency = <25000000>;
};
rtc-cy14b101p@1 {
compatible = "rtc-cy14b101p";
reg = <1>;
spi-max-frequency = <12500000>;
};
spidev@2 {
compatible = "mcst,boot"; // run spidev wo WARN
reg = <2>;
spi-max-frequency = <50000000>;
};
spidev@3 {
compatible = "mcst,boot"; // run spidev wo WARN
reg = <3>;
spi-max-frequency = <50000000>;
};
};
};

View File

@ -0,0 +1,87 @@
/*
* MONOCUBE
* TVGI.469555.253 ver.5
* (MONOCUBE-PC)
*/
/dts-v1/;
/ {
/* version = ""; */
model = "e2c+,mcst,mono-pc";
compatible = "mcst,mono-pc";
#address-cells = <1>;
#size-cells = <0>;
/* IOHUB I2C */
l_i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
compatible = "l_i2c";
label = "iohub i2c";
i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
lm95231@2b {
/* hwmon/lm95231.ko (DD12:LM95231CIMM) */
/* CIMM:0x57 / CIMM-1:0x19 / CIMM-2:0x2A */
compatible = "ti,lm95231";
reg = <0x2b>;
label = "CPU Temp Sensor";
temp1_label = "Board Temp";
temp2_label = "CPU Temp";
temp3_label = "not connected";
/* no fan control */
};
/* TODO: ???.ko (DD14:MAX3674ECM+) */
/* (X29, X30) DIMMs */
};
i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
/* empty */
};
i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
/* empty */
};
i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
/* empty */
};
};
/* IOHUB SPI */
l_spi@0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "l_spi";
reg = <0>;
label = "iohub spi";
boot@0 {
compatible = "mcst,boot";
reg = <0>;
spi-max-frequency = <25000000>;
};
rtc-cy14b101p@1 {
compatible = "rtc-cy14b101p";
reg = <1>;
spi-max-frequency = <12500000>;
};
};
};

View File

@ -0,0 +1,459 @@
/*
* support for the Mcst Pevm based board
*
*/
/dts-v1/;
/*#include <dt-bindings/input/input.h>*/
/ {
version = "apk-pc4c v1.0 2018-03-16";
model = "e4c, apk-pc4c, notebook";
compatible = "mcst,apk-pc4c";
#address-cells = <1>;
#size-cells = <0>;
l_i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
compatible = "l_i2c";
i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
lm96163@4c {
/* hwmon/lm63.ko (DD22:LM96163CISD) - CPU_TERM */
compatible = "lm63";
reg = <0x4c>;
label = "COM: CPU Temp Sensor";
temp1_label = "Internal Temp";
temp2_label = "CPU Temp";
/* no fan control */
};
ltm4676@40 {
/* hwmon/pmbus/ltc2978.ko (LTM4676IY) - +3V3out / +1V0out */
compatible = "lltc,ltm4676";
reg = <0x40>;
label = "COM: +3V3out / +1V0out";
regulators {
vout0 {
regulator-name = "COM:3V3";
};
vout1 {
regulator-name = "COM:1V0";
};
};
};
ltm4676@4f {
/* hwmon/pmbus/ltc2978.ko (LTM4676IY) - +1V5out / +1V2out */
compatible = "lltc,ltm4676";
reg = <0x4f>;
label = "COM: RAM-1V5 / IOHUB-1V2";
regulators {
vout0 {
regulator-name = "IOHUB-1V5";
};
vout1 {
regulator-name = "IOHUB-1V2";
};
};
};
ltc4151@6a {
/* hwmon/ltc4151.ko (LTC4551IDD) - TERM_LTM / +12V_CPU */
compatible = "lltc,ltc4151";
reg = <0x6a>;
shunt-resistor-micro-ohms = <20000>;
label = "COM: TERM_LTM / +12V_CPU";
};
/*
pca9534@20 {
compatible = "nxp,pca9534"; //driver: gpio/gpio-pca953x
reg = <0x20>;
};
pca9534@21 {
compatible = "nxp,pca9534"; //driver: gpio/gpio-pca953x
reg = <0x21>;
};
*/
};
i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
lm96163@4c {
/* hwmon/lm63.ko (DD24:LM96163CISD) - board temp */
compatible = "lm63";
reg = <0x4c>;
label = "COM: Board Temp Sensor";
temp1_label = "Internal Temp";
temp2_label = "not connected";
/* no fan control */
};
};
i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
/* (PEX8624-BB50BIF) - PCIe switch */
};
i2c@3 {
/* COMexpress:SMB */
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
i2c-mux@44 {
/* i2c/muxes/i2c-mux-ltc4306.ko (LTC4306) - I2C MUX */
#address-cells = <1>;
#size-cells = <0>;
compatible = "lltc,ltc4306";
reg = <0x44>;
/* i2c-mux-idle-disconnect; */
i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
/* E8860 MXM Radeon video */
};
i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
/* mPCI-E (WiFi+BT) */
};
i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
/* mPCI-E (Exp) */
};
i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
apkpwr@5a {
/* mcst/apkpwr.ko [X13:PowerIn] */
#address-cells = <1>;
#size-cells = <0>;
compatible = "mcst,apkpwr";
reg = <0x5a>;
label = "MPN power in";
};
};
};
i2c-mux@58 {
/* i2c/muxes/i2c-mux-ltc4306.ko (LTC4306) - I2C MUX */
#address-cells = <1>;
#size-cells = <0>;
compatible = "lltc,ltc4306";
reg = <0x58>;
/* i2c-mux-idle-disconnect; */
i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
gpi1:pca9534@20 {
/* gpio/gpio-pca953x.ko (DD14:PCA9534PW) - DiscretIn#1 */
compatible = "nxp,pca9534";
reg = <0x20>;
label = "DiscretIn#1";
gpio-controller;
/* FUTURE: (now interrupt support not compiled in)
interrupt-parent = <&gpio?>;
interrupts = <?? IRQ_TYPE_LEVEL_LOW>;
*/
ngpios = <8>;
#gpio-cells = <2>;
/* use gpio_keys to control lines 0..4 */
gpio-line-names = "wifi_btn", "avia_btn", "pwm_btn", "tpad_btn", "cover_down",
"PRSNT_L", "PRSNT_R", "NT_FLAG";
};
gpi2:pca9534@21 {
/* gpio/gpio-pca953x.ko (DD6:PCA9534PW) - DiscretIn#2 */
compatible = "nxp,pca9534";
reg = <0x21>;
label = "DiscretIn#2";
gpio-controller;
/* FUTURE: (now interrupt support not compiled in)
interrupt-parent = <&gpio?>;
interrupts = <?? IRQ_TYPE_LEVEL_LOW>;
*/
ngpios = <6>;
#gpio-cells = <2>;
gpio-line-names = "PWR_ALERT", "CASE_ALERT", "COVER_ALERT",
"CPU_OVERH", "TH_OVERH", "HDD_ALERT";
};
gpo1:pca9534@22 {
/* gpio/gpio-pca953x.ko (DD5:PCA9534) - DiscretOut#1 */
compatible = "nxp,pca9534";
reg = <0x22>;
label = "DiscretOut#1";
gpio-controller;
/* FUTURE: (now interrupt support not compiled in)
interrupt-parent = <&gpio?>;
interrupts = <?? IRQ_TYPE_LEVEL_LOW>;
*/
ngpios = <8>;
#gpio-cells = <2>;
/* use gpio_leds to control this lines */
gpio-line-names = "wifi_led", "bluetooth_led", "pwm_r_led", "pwm_g_led",
"tpad_off_led", "cam_act_led", "numlock_led", "capslock_led";
};
gpo2:pca9534@23 {
/* gpio/gpio-pca953x.ko (DD7:PCA9534) - DiscretOut#2 */
compatible = "nxp,pca9534";
reg = <0x23>;
label = "DiscretOut#2";
gpio-controller;
/* FUTURE: (now interrupt support not compiled in)
interrupt-parent = <&gpio?>;
interrupts = <?? IRQ_TYPE_LEVEL_LOW>;
*/
ngpios = <4>;
#gpio-cells = <2>;
/* use gpio_leds to control line 0 and gpio to other */
gpio-line-names = "sata_led",
"PWR_LEVEL", "RS_232_EN", "WIFI_DIS";
rs232_en {
gpio-hog;
gpios = <2 0>;
output-low;
line-name = "RS_232_EN";
/* use IOHUB-GPIO for this function */
};
};
};
i2c@1 {
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
lm95245@18 {
/* hwmon/lm95245.ko (DD54:LM95245CIMM) - TEMP_CASE + MXM */
compatible = "national,lm95245";
reg = <0x18>;
label = "MB: TEMP_CASE / MXM";
// TODO: in reg 0xBF clear bit 3 (lm95245.pdf, p.20)
};
lm95245@4c {
/* hwmon/lm95245.ko (DD55:LM95245CIMM) - TEMP_COVER */
compatible = "national,lm95245";
reg = <0x4c>;
label = "MB: TEMP_COVER";
// TODO: in reg 0xBF clear bit 3 (lm95245.pdf, p.20)
};
lm95245@29 {
/* hwmon/lm95245.ko (DD56:LM95245CIMM) - TEMP_HDD */
compatible = "national,lm95245";
reg = <0x29>;
label = "MB: TEMP_HDD";
// TODO: in reg 0xBF clear bit 3 (lm95245.pdf, p.20)
};
ltm4676@40 {
/* hwmon/pmbus/ltc2978.ko (DA1:LTM4676IY) - DC/DC 5V & 3V3 */
compatible = "lltc,ltm4676";
reg = <0x40>;
label = "MB: DC/DC 5V & 3V3";
regulators {
vout0 {
regulator-name = "MB-5V";
};
vout1 {
regulator-name = "MB-3V3";
};
};
};
};
i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
ptn3460@20 {
/* gpu/drm/bridge/nxp-ptn3460.ko (DD54:LM95245CIMM) - DP2LVDS */
compatible = "nxp,ptn3460";
reg = <0x20>;
label = "DP2LVDS";
powerdown-gpio = <&gpio 0 1 0 0>; /* PD_N pin */
reset-gpio = <&gpio 0 1 0 0>; /* RST_N pin */
edid-emulation = <1>;
/* edid-emulation:
| 0 | 1024x768 | NXP Generic |
| 1 | 1920x1080 | NXP Generic |
| 2 | 1920x1080 | NXP Generic |
| 3 | 1600x900 | Samsung LTM200KT |
| 4 | 1920x1080 | Samsung LTM230HT |
| 5 | 1366x768 | NXP Generic |
| 6 | 1600x900 | ChiMei M215HGE |
*/
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
bridge_out:endpoint {
remote-endpoint = <&panel_in>;
};
};
};
};
};
i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
};
};
};
};
l_spi@0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "l_spi";
reg = <0>;
boot@0 {
compatible = "mcst,boot";
reg = <0>;
spi-max-frequency = <16000000>;
};
rtc-cy14b101p@1 {
compatible = "rtc-cy14b101p";
reg = <1>;
spi-max-frequency = <16000000>;
};
};
gpio0:l_gpio@0 {
compatible = "mcst,gpio";
reg = <0x0>;
label = "L-GPIO";
gpio-controller;
ngpios = <16>;
#gpio-cells = <2>;
gpio-line-names = "nc", "nc", "nc", "nc", "nc",
"GPI0.PWR_NMI", "GPI1.I2C_INT",
"GPI2.TP14", "GPI3.TP15",
"GPO0.PWR_KILL", "GPO1.RS232_EN1",
"GPO2.TP16", "GPO3.TP17",
"nc", "nc", "nc";
};
gpio_leds {
compatible = "gpio-leds";
/* DiscretOut#1: */
wifi_led {
gpios = <&gpo1 0 0>; /* (F3) */
linux,default-trigger = "rfkill0";
label = "wifi:green";
};
avia_led {
gpios = <&gpo1 1 0>; /* (F1) */
linux,default-trigger = "rfkill1";
label = "bluetooth:green";
};
pwm_r_led {
gpios = <&gpo1 2 0>; /* (F4) */
linux,default-trigger = "none";
default-state = "on";
label = "pwm_r:yellow";
};
pwm_g_led {
gpios = <&gpo1 3 0>; /* (F4) */
linux,default-trigger = "none";
default-state = "off";
label = "pwm_g:green";
};
tpad_off_led {
gpios = <&gpo1 4 0>; /* (F2) */
linux,default-trigger = "none";
default-state = "off";
label = "tpad_off:red";
};
cam_act_led {
gpios = <&gpo1 5 0>;
linux,default-trigger = "none";
default-state = "off";
label = "cam_act:yellow";
};
numlock_led {
gpios = <&gpo1 6 0>;
linux,default-trigger = "kbd-numlock";
label = "numlock:green";
};
capslock_led {
gpios = <&gpo1 7 0>;
linux,default-trigger = "kbd-capslock";
label = "capslock:green";
};
/* DiscretOut#2: */
sata_led {
gpios = <&gpo2 0 0>;
linux,default-trigger = "disk-activity";
label = "sata:yellow";
};
};
gpio_keys_polled {
#address-cells = <1>;
#size-cells = <0>;
compatible = "gpio-keys-polled";
poll-interval = <250>;
/*autorepeat;*/
wifi_btn {
gpios = <&gpi1 0 0>; /* [F3] */
linux,code = <238>; /* KEY_WLAN */
debounce-interval = <10>;
label = "wifi_btn";
};
avia_btn {
gpios = <&gpi1 1 0>; /* [F1] */
linux,code = <247>; /* KEY_RFKILL */
debounce-interval = <10>;
label = "avia_btn";
};
pwm_btn {
gpios = <&gpi1 2 0>; /* [F4] */
linux,code = <243>; /* KEY_BRIGHTNESS_CYCLE */
debounce-interval = <10>;
label = "pwm_btn";
};
tpad_btn {
gpios = <&gpi1 3 0>; /* [F2] */
linux,code = <0x212>; /* KEY_TOUCHPAD_TOGGLE */
debounce-interval = <10>;
label = "tpad_btn";
};
cover_down {
gpios = <&gpi1 4 0>; /* case closed */
linux,code = <245>; /* KEY_DISPLAY_OFF */
debounce-interval = <10>;
label = "cover_down";
};
power {
gpios = <&gpio0 5 0>;
linux,code = <116>; /* KEY_POWER */
debounce-interval = <10>;
label = "Power-key";
};
};
/* stub */
gpio:gpio-controller {
gpio-controller;
ngpios = <2>;
#gpio-cells = <2>;
line_0 {
gpio-hog;
gpios = <0 0>;
output-low;
};
line_1 {
gpio-hog;
gpios = <1 0>;
output-high;
};
};
port {
panel_in: endpoint {
remote-endpoint = <&bridge_out>;
};
};
};

View File

@ -0,0 +1,272 @@
/*
* EL-2S-4
* LYUI.469555.052
* (Footballer / UEM-2U)
*/
/dts-v1/;
/ {
/* version = ""; */
model = "e4c,mcst,el-2s-4,uem-2u";
compatible = "mcst,el-2s-4";
#address-cells = <1>;
#size-cells = <0>;
/* IOHUB I2C */
l_i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
compatible = "l_i2c";
label = "iohub i2c";
i2c@0 {
/* I2C_*0 */
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
i2c-mux@8A {
/* i2c/muxes/i2c-mux-ltc4306.ko (DD48:LTC4306IUFD) */
#address-cells = <1>;
#size-cells = <0>;
compatible = "lltc,ltc4306";
reg = <0x8A>; /* LHH */
/* i2c-mux-idle-disconnect; */
i2c@0 {
/* I2C_*0_0 */
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
/* CPU0 */
lm96163@4c {
/* hwmon/lm63.ko (0_DD2:LM96163CISD) */
compatible = "lm63";
reg = <0x4c>;
label = "FAN_CPU0";
/* trivial-devices */
temp1_label = "Internal diode";
temp2_label = "CPU0_TERM";
};
/* 0xA0 (0_X1:DIMM) */
/* 0xA2 (0_X2:DIMM) */
/* 0xA3 (0_X3:DIMM) */
/* (0_X4:Power) */
};
i2c@1 {
/* I2C_*0_1 */
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
/* X35:PCIe */
};
i2c@2 {
/* I2C_*0_2 */
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
/* X36:PCIe */
};
i2c@3 {
/* I2C_*0_3 */
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
/* ???.ko (DD1:MAX3674ECM+)
* 0xB4? - 500MHz CPU IOHUB1,2
*/
/* ???.ko (DD2:MAX3674ECM+)
* 0xB6? - 500MHz IOL IOHUB1,2
*/
pdt003@1B {
/* hwmon/pmbus/pmbus.ko (DA7:PDT003A0X3-SRZ) */
compatible = "pmbus";
reg = <0x1B>; /* 033 */
label = "+3V3SB";
};
pdt012@2A {
/* hwmon/pmbus/pmbus.ko (DA1:PDT012A0X3-SRZ) */
compatible = "pmbus";
reg = <0x2A>; /* 052 */
label = "+2V5 IOHUB";
};
pdt012@11 {
/* hwmon/pmbus/pmbus.ko (DA2:PDT012A0X3-SRZ) */
compatible = "pmbus";
reg = <0x11>; /* 021 */
label = "+1V2 IOHUB";
};
service_gpio:pca9534@20 {
/* gpio/gpio-pca953x.ko (DD27:PCA9534PW) */
compatible = "nxp,pca9534";
reg = <0x20>; /* 0100 000 */
label = "Service Register";
gpio-controller;
ngpios = <8>;
#gpio-cells = <2>;
gpio-line-names =
"ModSel0",
"ModSel1",
"KCBB_SERVICE3",
"KCBB_SERVICE4",
"KCBB_CONF_DONE",
"KCBB_PWR_OK",
"SPEAKER",
"I2C_RESET#";
};
i2c-mux@B2 {
/* i2c/muxes/i2c-mux-ltc4306.ko (DD3:LTC4306IUFD) */
#address-cells = <1>;
#size-cells = <0>;
compatible = "lltc,ltc4306";
reg = <0xB2>; /* LHL */
/* i2c-mux-idle-disconnect; */
i2c@0 {
/* I2C00 */
#address-cells = <1>;
#size-cells = <0>;
reg = <0>;
lm96163@4c {
/* hwmon/lm63.ko (DD25:LM96163CISD) */
compatible = "lm63";
reg = <0x4c>;
label = "PWM2_FAN";
/* trivial-devices */
temp1_label = "Internal diode";
temp2_label = "not connected";
};
};
i2c@1 {
/* I2C10 */
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
lm96163@4c {
/* hwmon/lm63.ko (DD23:LM96163CISD) */
compatible = "lm63";
reg = <0x4c>;
label = "FAN_CPU0";
/* trivial-devices */
temp1_label = "Internal diode";
temp2_label = "not connected";
};
};
i2c@2 {
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
/* empty */
};
i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
/* empty */
};
};
/* X23:KCBB
* - 0xA0 - Trans
* - 0x12, 0x1A, 0x2A - Power
*/
};
};
};
i2c@1 {
/* I2C_*1 */
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
/* CPU1 */
lm96163@4c {
/* hwmon/lm63.ko (1_DD2:LM96163CISD) */
compatible = "lm63";
reg = <0x4c>;
label = "FAN_CPU1";
/* trivial-devices */
temp1_label = "Internal diode";
temp2_label = "CPU1_TERM";
};
/* 0xA0 (1_X1:DIMM) */
/* 0xA2 (1_X2:DIMM) */
/* 0xA3 (1_X3:DIMM) */
/* (1_X4:Power) */
};
i2c@2 {
/* I2C_*2 */
#address-cells = <1>;
#size-cells = <0>;
reg = <2>;
/* CPU2 */
lm96163@4c {
/* hwmon/lm63.ko (2_DD2:LM96163CISD) */
compatible = "lm63";
reg = <0x4c>;
label = "FAN_CPU2";
/* trivial-devices */
temp1_label = "Internal diode";
temp2_label = "CPU2_TERM";
};
/* 0xA0 (2_X1:DIMM) */
/* 0xA2 (2_X2:DIMM) */
/* 0xA3 (2_X3:DIMM) */
/* (2_X4:Power) */
};
i2c@3 {
/* I2C_*3 */
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
/* CPU3 */
lm96163@4c {
/* hwmon/lm63.ko (3_DD2:LM96163CISD) */
compatible = "lm63";
reg = <0x4c>;
label = "FAN_CPU3";
/* trivial-devices */
temp1_label = "Internal diode";
temp2_label = "CPU3_TERM";
};
/* 0xA0 (3_X1:DIMM) */
/* 0xA2 (3_X2:DIMM) */
/* 0xA3 (3_X3:DIMM) */
/* (3_X4:Power) */
};
};
/* IOHUB SPI */
l_spi@0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "l_spi";
reg = <0>;
label = "iohub spi";
boot@0 {
compatible = "mcst,boot";
reg = <0>;
spi-max-frequency = <25000000>;
};
rtc-cy14b101p@1 {
compatible = "rtc-cy14b101p";
reg = <1>;
spi-max-frequency = <12500000>;
};
};
};

Some files were not shown because too many files have changed in this diff Show More