summaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
authorPatrick Georgi <patrick@georgi-clan.de>2012-04-29 19:43:52 +0200
committerPatrick Georgi <patrick@georgi-clan.de>2012-04-29 19:43:52 +0200
commitf29d9c590acc2e2de14f292a30fcf865d4610f02 (patch)
tree22959dedd11aae7c9819d424d3a9cea0314e9cf2 /cpu
parent4e0c3ac0b0ce3d665783b511859931bdd9f6a76f (diff)
downloadblobs-f29d9c590acc2e2de14f292a30fcf865d4610f02.tar.gz
Add Geode LX VSA
license is proper, build environment not so, so distribute as binary.
Diffstat (limited to 'cpu')
-rw-r--r--cpu/amd/geode_lx/README9
-rw-r--r--cpu/amd/geode_lx/gpl_vsa_lx_102.binbin0 -> 57504 bytes
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/README.txt27
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/build/legacy.mak42
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/build/lxvg.mak40
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/build/makefile99
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/build/rules.mak138
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/build/setvars.mak65
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/build/sysmgr.mak42
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/build/vsainit.mak42
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/inc/acpi.h249
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/inc/chipset.h374
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/inc/cs5536.h230
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/inc/gx2.h443
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/inc/hce.h97
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/inc/isa.h183
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/inc/pci.h111
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/inc/vr.h485
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/inc/vsa2.h700
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/blockio.c88
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/cs5536.c479
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/events.c145
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/flash.bak174
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/flash.c174
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/header.asm53
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/ide.c158
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/init.c83
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/legacy.c92
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/legacy.h37
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/makefile165
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/msr.asm97
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/swapsif.c130
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/sysinfo.c78
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/uarts.c210
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/legacy/virtregs.c131
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/lxvg/decode.c194
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/lxvg/init.c74
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/lxvg/lxhwctl.c298
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/lxvg/lxvg.h915
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/lxvg/main.asm55
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/lxvg/makefile158
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/lxvg/msr.c305
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/lxvg/utils.asm271
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/lxvg/vgdata.c55
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/lxvg/vgdata.h36
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/lxvg/vsa2.c133
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/bugs.asm221
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/chip.asm262
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/chipset.c239
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/cpu.asm59
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/cpu_init.asm339
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/cs5536.c328
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/debug.asm220
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/descr.c521
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/descr.h47
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/errors.c371
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/events.c616
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/gpio.c62
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/gpio5536.c488
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/handlers.c645
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/history.c193
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/idt.asm697
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/image.asm37
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/init.asm1017
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/init.h39
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/io.c196
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/io_trap.c218
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/makefile222
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/mapper.c118
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/mapper.h48
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/mbiu.c135
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/mbus.c758
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.c367
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.h226
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/message.asm393
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/mfgpt.c500
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/msr.asm348
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/ohci.c164
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/pci_pm.c539
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/pci_rd.c177
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/pci_wr.c375
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/port92.asm387
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/protos.h91
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/smimac.mac209
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/smis.asm354
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/sw_int.asm502
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/swapsif.c316
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/syscalls.asm772
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/sysmgr.asm804
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/sysmgr.h207
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/timeout.c729
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/timer.c183
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/timer.h51
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/topology.c348
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/unregstr.c338
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/utils.asm642
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/virt_pci.c885
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/vpci.h174
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/vr.c356
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/vr_misc.asm1161
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/sysmgr/vsa_init.c111
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsabuild.txt52
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/critical.asm67
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/descr.asm182
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/hex.asm95
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/irq.asm82
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/makefile134
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/message.asm61
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/misc.asm62
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/msrs.asm98
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/pci.asm296
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/present.asm54
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/regs.asm368
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/resource.asm146
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/sw_int.asm87
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/sysinfo.asm83
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/utils.asm203
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/virtual.asm94
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/vsa2util.asm204
-rwxr-xr-xcpu/amd/geode_lx/gplvsa_ii/vsm_lib/yield.asm49
120 files changed, 30386 insertions, 0 deletions
diff --git a/cpu/amd/geode_lx/README b/cpu/amd/geode_lx/README
new file mode 100644
index 0000000..64a77ee
--- /dev/null
+++ b/cpu/amd/geode_lx/README
@@ -0,0 +1,9 @@
+This VSA is taken from
+http://marcjonesconsulting.com/gplvsa/gpl_vsa_lx_102.bin.gz
+
+and decompressed for simplicity. The original SHA1 was:
+96a6097331278d644230eac4fc39bcfebc3c9a16 gpl_vsa_lx_102.bin.gz
+
+While we have the source code (see gplvsa_ii), it requires a rather
+esoteric build system. Should this be fixed, we could consider adding
+VSA to the coreboot tree. Until then, source and binary can reside here.
diff --git a/cpu/amd/geode_lx/gpl_vsa_lx_102.bin b/cpu/amd/geode_lx/gpl_vsa_lx_102.bin
new file mode 100644
index 0000000..de9fd83
--- /dev/null
+++ b/cpu/amd/geode_lx/gpl_vsa_lx_102.bin
Binary files differ
diff --git a/cpu/amd/geode_lx/gplvsa_ii/README.txt b/cpu/amd/geode_lx/gplvsa_ii/README.txt
new file mode 100755
index 0000000..7c365d9
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/README.txt
@@ -0,0 +1,27 @@
+This is the VSA (Virtual Systems Architecture) code used on the AMD
+Geode series of processors. The Geode, rather than carrying lots of
+legacy hardware interfaces that are presumed to exist on x86 systems
+that might be painful to implement on a highly integrated, low power
+processor, the Geode often emulates such interfaces by use of software that is
+invoked by special traps that take place when the processor accesses
+these devices.
+
+Note that the code here is not currently buildable on open source
+systems, being only buildable using very obsolete and no longer
+commercially availble Windows based commercial toolchains. On the
+OLPC system, these "blobs" of binary code are concatenated together
+with LinuxBIOS and the bootloader, and set up to be executed by
+LinuxBIOS early in the Geode's initialization sequence (no linking is
+involved).
+
+If you are interested for some reason in making this code buildable on
+free systems, please let us know of your progress. It is under the
+GNU LGPL.
+
+Also note that VESA emulation is *not* included in this (nor does what
+we use on the OLPC machine use VESA at this date; we use frame
+buffer code for our console); that code was not owned by AMD and
+therefore not theirs to make available. Our thanks to AMD to making
+the VSA code available.
+
+ Jim Gettys, OLPC, September 27, 2006
diff --git a/cpu/amd/geode_lx/gplvsa_ii/build/legacy.mak b/cpu/amd/geode_lx/gplvsa_ii/build/legacy.mak
new file mode 100755
index 0000000..bbed202
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/build/legacy.mak
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2006 Advanced Micro Devices,Inc. ("AMD").
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# This code is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General
+# Public License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA
+#
+
+VSMNAME = legacy
+VSMDIR = $(VSA2ROOT)\$(VSMNAME)
+
+
+all:
+ cd $(VSMDIR)
+ $(MAKE) /nologo all "VSA2ROOT=$(VSA2ROOT)" "USER=$(USER)" "BUILDOBJ=$(OBJECT)" "CPU=$(CPU)"
+ cd $(MAKEDIR)
+
+clean:
+ cd $(VSMDIR)
+ $(MAKE) /nologo clean
+ cd $(MAKEDIR)
+
+cleanlocal:
+ cd $(VSMDIR)
+ $(MAKE) /nologo cleanlocal
+ cd $(MAKEDIR)
+
+cleanall:
+ cd $(VSMDIR)
+ $(MAKE) /nologo cleanall
+ cd $(MAKEDIR) \ No newline at end of file
diff --git a/cpu/amd/geode_lx/gplvsa_ii/build/lxvg.mak b/cpu/amd/geode_lx/gplvsa_ii/build/lxvg.mak
new file mode 100755
index 0000000..0791672
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/build/lxvg.mak
@@ -0,0 +1,40 @@
+# Copyright (c) 2007-2008 Advanced Micro Devices,Inc. ("AMD").
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# This code is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General
+# Public License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA
+
+VSMNAME = lxvg
+VSMDIR = $(VSA2ROOT)\$(VSMNAME)
+
+all:
+ cd $(VSMDIR)
+ $(MAKE) /nologo all "VSA2ROOT=$(VSA2ROOT)" "USER=$(USER)" "BUILDOBJ=$(OBJECT)" "CPU=$(CPU)"
+ cd $(MAKEDIR)
+
+
+clean:
+ cd $(VSMDIR)
+ $(MAKE) /nologo clean
+ cd $(MAKEDIR)
+
+cleanlocal:
+ cd $(VSMDIR)
+ $(MAKE) /nologo cleanlocal
+ cd $(MAKEDIR)
+
+cleanall:
+ cd $(VSMDIR)
+ $(MAKE) /nologo cleanall
+ cd $(MAKEDIR)
diff --git a/cpu/amd/geode_lx/gplvsa_ii/build/makefile b/cpu/amd/geode_lx/gplvsa_ii/build/makefile
new file mode 100755
index 0000000..168d399
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/build/makefile
@@ -0,0 +1,99 @@
+#
+# Copyright (c) 2006 Advanced Micro Devices,Inc. ("AMD").
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# This code is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General
+# Public License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA
+#
+# makefile for VSA2
+
+
+
+!ifndef VSA2ROOT
+VSA2ROOT = $(MAKEDIR)\..
+!endif
+
+USER = $(VSA2ROOT)
+
+OBJECT = $(MAKEDIR)\obj
+
+.SUFFIXES:
+.SUFFIXES : .exe .vsm .lib .bin .mak .cln
+
+!include setvars.mak
+
+VSMS = \
+ $(OBJECT)\sysmgr.vsm \
+ $(OBJECT)\vsainit.bin \
+ $(OBJECT)\legacy.vsm \
+ $(OBJECT)\lxvg.vsm
+
+VSM_CLN0 = $(VSMS:.vsm=.cln)
+VSM_CLN = $(VSM_CLN0:.bin=.cln)
+
+
+#######################################################################
+#
+# Targets
+#
+#######################################################################
+all: $(OBJECT) $(VSMS) basic
+
+basic: setenv
+ @$(ECHO) Make LX VSA Image
+ $(MAKE) /nologo vsa_lx.bin
+
+$(VSMS): setenv
+
+vsa_lx.bin $(OBJECT)\amd_vsa_lx.bin: $(OBJECT)\vsainit.bin $(OBJECT)\vsa2.bin
+ @$(ECHO) Concatenate for LX Image ...
+ -$(BINCOPY) $(OBJECT)\vsainit.bin+$(OBJECT)\vsa2.bin+$(OBJECT)\lxvg.vsm $(OBJECT)\amd_vsa_lx.bin
+
+vsa2.bin $(OBJECT)\vsa2.bin: $(OBJECT)\sysmgr.vsm $(OBJECT)\legacy.vsm
+ @$(ECHO) Concatenate for VSA2.BIN Image ...
+ -$(BINCOPY) $(OBJECT)\sysmgr.vsm+$(OBJECT)\legacy.vsm $(OBJECT)\vsa2.bin
+
+#This and only this clean target must exist as it is called by cleanall
+#cleanall and cleanlocal are defined in rules.mak
+
+clean: cleanlocal cleanlib $(VSM_CLN) tools_clean
+
+$(OBJECT):
+ -@md $(OBJECT)
+
+
+############################################
+# Tools.lib
+############################################
+tools_clean:
+ -@cd $(VSA2ROOT)\vsm_lib
+ -@$(MAKE) /nologo cleanall
+ -@cd $(MAKEDIR)
+
+
+###########################################################################
+# All VSMs
+###########################################################################
+{$(MAKEDIR)}.mak{$(OBJECT)}.vsm:
+ $(MAKE) /nologo -f $(MAKEDIR)\%|fF.mak "VSA2ROOT=$(VSA2ROOT)" "USER=$(VSA2ROOT)" "OBJECT=$(OBJECT)" "CPU=$(CPU)"
+
+{$(MAKEDIR)}.mak{$(OBJECT)}.bin:
+ $(MAKE) /nologo -f $(MAKEDIR)\%|fF.mak "VSA2ROOT=$(VSA2ROOT)" "USER=$(VSA2ROOT)" "OBJECT=$(OBJECT)" "CPU=$(CPU)"
+
+{$(MAKEDIR)}.mak{$(OBJECT)}.cln:
+ -@$(MAKE) /nologo -f $(MAKEDIR)\%|fF.mak cleanall "VSA2ROOT=$(VSA2ROOT)" "USER=$(VSA2ROOT)"
+
+
+!include rules.mak
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/build/rules.mak b/cpu/amd/geode_lx/gplvsa_ii/build/rules.mak
new file mode 100755
index 0000000..d177454
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/build/rules.mak
@@ -0,0 +1,138 @@
+#
+# Copyright (c) 2006 Advanced Micro Devices,Inc. ("AMD").
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# This code is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General
+# Public License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA
+#
+
+##############################################################################
+#
+# Common targets
+#
+##############################################################################
+
+
+
+setenv:
+!if "$(VARS_SET)" != "VSA_II"
+ @$(SETENV) PATH=.\;$(VSA2ROOT)\uti;$(PATH);
+ @$(SETENV) Lib=.\;$(VSA2ROOT)\lib;$(VSA2ROOT)\build;$(LIB);
+ @$(SETENV) VARS_SET=VSA_II
+!endif
+ @echo INCLUDE=$(INCLUDE)
+
+$(BUILD_DIR)\obj\$(TOOL_LIB):
+ cd $(VSA2ROOT)\vsm_lib
+ $(MAKE) /nologo all "BUILDOBJ=$(OBJECT)" "CPU=$(CPU)"
+ cd $(MAKEDIR)
+
+cleanlib:
+ cd $(VSA2ROOT)\vsm_lib
+ $(MAKE) /nologo cleanall
+ cd $(MAKEDIR)
+
+cleanlocal:
+ -@IF EXIST $(OBJECT)\*.def $(DEL) $(OBJECT)\*.def
+ -@IF EXIST $(OBJECT)\*.lnk $(DEL) $(OBJECT)\*.lnk
+ -@IF EXIST $(OBJECT)\*.map $(DEL) $(OBJECT)\*.map
+ -@IF EXIST $(OBJECT)\*.obj $(DEL) $(OBJECT)\*.obj
+ -@IF EXIST $(OBJECT)\*.exe $(DEL) $(OBJECT)\*.exe
+ -@IF EXIST $(OBJECT)\*.rom $(DEL) $(OBJECT)\*.rom
+ -@IF EXIST $(OBJECT)\*.cpu $(DEL) $(OBJECT)\*.cpu
+ -@IF EXIST $(OBJECT)\*.scc $(DEL) $(OBJECT)\*.scc
+ -@IF EXIST $(OBJECT)\*.inc $(DEL) $(OBJECT)\*.inc
+ -@IF EXIST $(OBJECT)\*.h $(DEL) $(OBJECT)\*.h
+ -@IF EXIST $(OBJECT)\*.lst $(DEL) $(OBJECT)\*.lst
+ -@IF EXIST $(OBJECT)\*.bak $(DEL) $(OBJECT)\*.bak
+ -@IF EXIST $(OBJECT)\*.mac $(DEL) $(OBJECT)\*.mac
+ -@IF EXIST $(OBJECT)\*.asm $(DEL) $(OBJECT)\*.asm
+ -@IF EXIST $(OBJECT)\*.cod $(DEL) $(OBJECT)\*.cod
+ -@IF EXIST $(MAKEDIR)\*.map $(DEL) $(MAKEDIR)\*.map
+ -@IF EXIST $(MAKEDIR)\arccode.h $(DEL) $(MAKEDIR)\arccode.h
+
+cleanall: clean
+ -@IF EXIST $(MAKEDIR)\*.vsm $(DEL) $(MAKEDIR)\*.vsm
+ -@IF EXIST $(OBJECT)\*.vsm $(DEL) $(OBJECT)\*.vsm
+ -@IF EXIST $(OBJECT)\*.bin $(DEL) $(OBJECT)\*.bin
+ -@IF EXIST $(OBJECT)\*.lib $(DEL) $(OBJECT)\*.lib
+ -@IF EXIST $(OBJECT) rd $(OBJECT)
+
+
+##############################################################################
+#
+# Common inference rules
+#
+##############################################################################
+
+{$(INC_DIR)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /C $<
+
+{$(INC_DIR)\$(CPU)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /C $<
+
+{$(SYSMGR_SRC)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /C $<
+
+{$(SYSMGR_SRC)\$(CPU)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /C $<
+
+{$(MAKEDIR)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /C $<
+
+{$(MAKEDIR)\$(CPU)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /C $<
+
+{$(INC_DIR)}.h{$(OBJECT)}.h:
+ $(COPY) $< $@
+
+{$(INC_DIR)\$(CPU)}.h{$(OBJECT)}.h:
+ $(COPY) $< $@
+
+{$(SYSMGR_SRC)}.h{$(OBJECT)}.h:
+ $(COPY) $< $@
+
+{$(SYSMGR_SRC)\$(CPU)}.h{$(OBJECT)}.h:
+ $(COPY) $< $@
+
+{$(MAKEDIR)}.h{$(OBJECT)}.h:
+ $(COPY) $< $@
+
+{$(MAKEDIR)\$(CPU)}.h{$(OBJECT)}.h:
+ $(COPY) $< $@
+
+{$(MAKEDIR)}.inc{$(OBJECT)}.inc:
+ $(COPY) $< $@
+
+{$(MAKEDIR)\$(CPU)}.inc{$(OBJECT)}.inc:
+ $(COPY) $< $@
+
+{$(MAKEDIR)}.c{$(OBJECT)}.obj:
+ $(CC) /nologo $(CC_OPTS) /Fo$@ $<
+
+{$(MAKEDIR)\$(CPU)}.c{$(OBJECT)}.obj:
+ $(CC) /nologo $(CC_OPTS) /Fo$@ $<
+
+{$(MAKEDIR)}.asm{$(OBJECT)}.obj:
+ $(AS) /nologo $(AS_OPTS) /Fo$@ $<
+
+{$(MAKEDIR)\$(CPU)}.asm{$(OBJECT)}.obj:
+ $(AS) /nologo $(AS_OPTS) /Fo$@ $<
+
+{$(SYSMGR_SRC)}.mac{$(OBJECT)}.mac:
+ $(COPY) $< $@
+
+{$(SYSMGR_SRC)\$(CPU)}.mac{$(OBJECT)}.mac:
+ $(COPY) $< $@
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/build/setvars.mak b/cpu/amd/geode_lx/gplvsa_ii/build/setvars.mak
new file mode 100755
index 0000000..cd06edd
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/build/setvars.mak
@@ -0,0 +1,65 @@
+#
+# Copyright (c) 2006 Advanced Micro Devices,Inc. ("AMD").
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# This code is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General
+# Public License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA
+#
+
+##############################################################################
+#
+# Directories
+#
+##############################################################################
+BUILD_DIR = $(VSA2ROOT)\build
+SYSMGR_SRC = $(VSA2ROOT)\sysmgr
+VSMUTILS_SRC = $(VSA2ROOT)\vsm_lib
+LEGACY_SRC = $(VSA2ROOT)\legacy
+INC_DIR = $(VSA2ROOT)\inc
+H_DIR = $(VSA2ROOT)\sysmgr
+
+SHELL =
+
+##############################################################################
+#
+# Tools / Options for tools
+#
+##############################################################################
+ECHO = echo
+COPY = copy
+BINCOPY = copy /b
+MOVE = move
+DEL = del
+REN = ren
+SETENV = set
+CD = cd
+AS = ml
+CC = cl
+H2 = h2inc
+LN = link
+LB = lib
+X2ROM = exe2bin
+
+AS_OPTS = /c /Cx /Sa /W3 $(ALIST) /I$(OBJECT)
+CC_OPTS = /c /AT /Gs /FPi87 /G3fsy /W3 /Fc$(OBJECT)\ /I$(OBJECT) $(COPTS_OPT) $(CLIST)
+
+COPTS_OPT = /Ow /W3
+LOPTS_OPT = /NONULLS /nologo /MAP
+LOPTS_SYS = /MAP /TINY /nologo
+LOPTS_VSM = /MAP /TINY /nologo
+
+TOOL_LIB = tools.lib
+HEAD_LIB = header.lib
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/build/sysmgr.mak b/cpu/amd/geode_lx/gplvsa_ii/build/sysmgr.mak
new file mode 100755
index 0000000..4d24f4b
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/build/sysmgr.mak
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2006 Advanced Micro Devices,Inc. ("AMD").
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# This code is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General
+# Public License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA
+#
+
+VSMNAME = sysmgr
+VSMDIR = $(VSA2ROOT)\$(VSMNAME)
+
+all:
+ cd $(VSMDIR)
+ $(MAKE) /nologo all "VSA2ROOT=$(VSA2ROOT)" "USER=$(USER)" "BUILDOBJ=$(OBJECT)" "CPU=$(CPU)"
+ cd $(MAKEDIR)
+
+
+clean:
+ cd $(VSMDIR)
+ $(MAKE) /nologo clean
+ cd $(MAKEDIR)
+
+cleanlocal:
+ cd $(VSMDIR)
+ $(MAKE) /nologo cleanlocal
+ cd $(MAKEDIR)
+
+cleanall:
+ cd $(VSMDIR)
+ $(MAKE) /nologo cleanall
+ cd $(MAKEDIR) \ No newline at end of file
diff --git a/cpu/amd/geode_lx/gplvsa_ii/build/vsainit.mak b/cpu/amd/geode_lx/gplvsa_ii/build/vsainit.mak
new file mode 100755
index 0000000..96a0720
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/build/vsainit.mak
@@ -0,0 +1,42 @@
+#
+# Copyright (c) 2006 Advanced Micro Devices,Inc. ("AMD").
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# This code is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General
+# Public License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA
+#
+
+VSMNAME = vsainit
+VSMDIR = $(VSA2ROOT)\sysmgr
+
+all:
+ cd $(VSMDIR)
+ $(MAKE) /nologo all "VSA2ROOT=$(VSA2ROOT)" "USER=$(USER)" "BUILDOBJ=$(OBJECT)" "CPU=$(CPU)"
+ cd $(MAKEDIR)
+
+
+clean:
+ cd $(VSMDIR)
+ $(MAKE) /nologo clean
+ cd $(MAKEDIR)
+
+cleanlocal:
+ cd $(VSMDIR)
+ $(MAKE) /nologo cleanlocal
+ cd $(MAKEDIR)
+
+cleanall:
+ cd $(VSMDIR)
+ $(MAKE) /nologo cleanall
+ cd $(MAKEDIR) \ No newline at end of file
diff --git a/cpu/amd/geode_lx/gplvsa_ii/inc/acpi.h b/cpu/amd/geode_lx/gplvsa_ii/inc/acpi.h
new file mode 100755
index 0000000..d7b85b4
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/inc/acpi.h
@@ -0,0 +1,249 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+
+
+//*********************************************************
+// Private messages used between ACPI VSM and PMCORE VSM **
+//*********************************************************
+#define PMSG_GOTO_SLEEP 0x70
+#define PMSG_BLINK_LED 0x71
+
+
+/* device power states */
+#define D0_STATE (0)
+#define D1_STATE (1)
+#define D2_STATE (2)
+#define D3_STATE (3)
+
+/**************************************************************
+* smi_cmd Definitions
+* These values must match the corresponding values in ACPI
+* FADT. OS writes these values to SMI_CMD I/O location.
+****************************************************************/
+#define ACPI_ENABLE (0xA1)
+#define ACPI_DISABLE (0xA2)
+#define S4BIOS_REQ (0xA3)
+
+
+// Bitmap of IRQ's PM VSM can map SCI to
+#define ALLOWED_SCI_IRQ (0x0E20) // 11,10,9,5
+#define DEFAULT_SCI_IRQ (9)
+
+/**************************************************************
+* PM1_STS bit definitions
+****************************************************************/
+#define WAKE_STS (0x8000)
+#define RTC_STS (0x0400)
+#define SLPBTN_STS (0x0200)
+#define PWRBTN_STS (0x0100)
+#define GBL_STS (0x0020)
+#define BM_STATUS (0x0010)
+#define TMR_STS (0x0001)
+#define PM1_STS_CLR (0x8731)
+
+/**************************************************************
+* PM1_EN bit definitions
+****************************************************************/
+#define RTC_EN (0x0400)
+#define SLPBTN_EN (0x0200)
+#define PWRBTN_EN (0x0100)
+#define GBL_EN (0x0020)
+#define TMR_EN (0x0001)
+
+/**************************************************************
+* PM1_CNT bit definitions
+****************************************************************/
+#define SLP_EN (0x2000)
+#define SLP_ENB (0x20)
+#define SLP_TYPx_MASK (0x1C00) // mask for setting SLP_TYPx
+#define SLP_TYPx_MASKB (0x1C)
+#define SLP_TYPx_SHFT (10)
+#define SLP_TYPx_SHFTB (2)
+#define GBL_RLS (0x0004)
+#define BM_RLD (0x0002)
+#define SCI_EN (0x0001)
+#define ACPI_S0 (0)
+#define ACPI_S1 (1)
+#define ACPI_S1_CLKOFF (0x81)
+#define ACPI_S2 (2)
+#define ACPI_S3 (3)
+#define ACPI_S4 (4)
+#define ACPI_S5 (5)
+
+/**************************************************************
+* PM2_CNT bit definitions
+**************************************************************/
+#define ARB_DIS (0x0001)
+
+
+/**************************************************************
+* P_CNT bit definitions
+****************************************************************/
+#define CLK_VAL_MASK (0x0000000F)
+#define CLK_VAL_OFFSET (0)
+#define CLK_VAL_WIDTH (4)
+#define THT_EN (0x00000010)
+
+
+/********************************************************************
+* FACS
+********************************************************************/
+#define FACS_SIG_OFS (0x00)
+#define FACS_LEN_OFS (0x04)
+#define FACS_HWSIG_OFS (0x08)
+#define FACS_OSWV_OFS (0x0C)
+#define FACS_GBLOCK_OFS (0x10)
+ #define FACS_GBL_OWNED (0x02)
+ #define FACS_GBL_PENDING (0x01)
+#define FACS_FLAGS_OFS (0x14)
+
+
+/********************************************************************
+* CS5536 PM stuff
+********************************************************************/
+#define YIG_SCI (5) // Y Interrupt Group 5 is all SCI sources
+#define MSR_SYS_RESET (0x0014) // 5536 GLCP SYS_RESET MSR
+
+// default location of PMC regs
+#define PMC5536_BASE (0x9D00)
+
+// default location of ACPI regs (32 bytes)
+#define ACPI5536_BASE (0x9C00)
+#define PM1_STS_OFS (0x00)
+#define PM1_EN_OFS (0x02)
+#define PM1_CNT_OFS (0x08)
+#define PM2_CNT_OFS (0x0C)
+#define PM_TMR_OFS (0x10)
+#define GPE0_STS_OFS (0x18)
+#define GPE0_EN_OFS (0x1C)
+
+// Virtualized ACPI registers, these offsets were picked to provide
+// minimal overlap of misaligned accesses.
+// Note: PM1_STS/EN and GPE0_STS/EN must be back-to-back AND
+// PM1_STS and PM1_EN must be 16-bit only.
+#define VACPI_TRAP_BASE 0x9C20
+#define VACPI_TRAP_LEN (32)
+#define VPM1_STS_OFS (0x00)
+#define VPM1_EN_OFS (0x02)
+#define VPM1_CNT_OFS (0x08)
+#define VGPE0_STS_OFS (0x10)
+#define VGPE0_EN_OFS (0x14)
+#define VACPI_ENABLE (0x1C)
+
+// 5536 GPIO13 AUX1_IN is dedicated to Sleep Button. It's controlled
+// by SLPB_STS in PM1_STS and SLPB_EN in PM1_EN.
+// Unfortunately, GPIO13 is in Working Power Domain so it is useless as
+// a wake event for anything other than S1.
+#define DFLT_5536_SLPB_GPIO (13)
+
+// Bit[9] of PM1_CNT, ignored bit in ACPI spec. On 5536 this bit indicates
+// software has written a 1 to GBL_RLS(bit[2]) of PM1_CNT. Bit[9] can be cleared
+// by writing a 1 to it.
+#define GBL_RLS_FLAG (0x0200)
+
+// Bit[11] of PM1_STS, ignored bit in ACPI spec. On 5536 writing this bit=1 causes
+// GBL_STS(bit[5]) to be set to 1. Bit[11] always reads as 0.
+#define SET_GBL_STS (0x0800)
+
+// 5536 specific bits in ACPI GPE0_STS & GPE0_EN
+#define GPE0_PIC_INT (0x00000001L)
+#define GPE0_PIC_ASMI (0x00000002L)
+#define GPE0_SMB (0x00000004L)
+#define GPE0_UART1 (0x00000008L)
+#define GPE0_UART2 (0x00000010L)
+#define GPE0_USB1 (0x00000020L)
+#define GPE0_USB2 (0x00000040L)
+#define GPE0_PME0 (0x00010000L)
+#define GPE0_PME1 (0x00020000L)
+#define GPE0_PME2 (0x00040000L)
+#define GPE0_PME3 (0x00080000L)
+#define GPE0_PME4 (0x00100000L)
+#define GPE0_PME5 (0x00200000L)
+#define GPE0_PME6 (0x40000000L)
+#define GPE0_PME7 (0x80000000L)
+
+
+
+/*##
+ *## ACPI Indicator Designations
+ *##
+ */
+#define LED_OFF 0x00 // LED turned off
+#define LED_SLOW 0x01 // 1/4Hz rate (4 second cycle time), 50% duty cycle
+#define LED_FAST 0x02 // 1Hz rate (1 second cycle time), 50% duty cycle
+#define LED_ON 0x03 // LED always on
+
+#define NO_LED 0x00 // No LEDs here
+//#define MB_LED0 0x01 // The motherboard LED 0 bit mask
+//#define MB_LED1 0x02 // The motherboard LED 1 bit mask
+//#define MB_LED2 0x04 // The motherboard LED 2 bit mask
+//#define MB_LED3 0x08 // The motherboard LED 3 bit mask
+#define MB_LEDALL 0x0F // The all motherboard LEDs bit mask
+//#define SIO_LED0 0x10 // The SIO LED 0 bit mask
+//#define SIO_LED1 0x20 // The SIO LED 1 bit mask
+//#define SIO_LED2 0x40 // The SIO LED 2 bit mask
+//#define SIO_LED3 0x80 // The SIO LED 3 bit mask
+#define SIO_LEDALL 0xF0 // The SIO LEDs are in the upper nibble
+//The LEDS used to indicate sleep/wake
+#define INDICATOR_SLEEP 0x11
+
+
+/*
+* table indexes for gx2/lx msrs
+* (This may be moved *)
+*/
+// Northbridge
+#define IDX_GLIU0 (0)
+#define IDX_MC (1)
+#define IDX_GLIU1 (2)
+#define IDX_VG (3)
+#define IDX_GP (4)
+#define IDX_DF (5)
+#define IDX_GLCP (6)
+#define IDX_GLPCI (7)
+#define IDX_FG (8)
+#define IDX_CPU (9)
+#define IDX_VIP (10)
+#define IDX_AES (11)
+
+// Southbridge
+#define IDX_SB_GLPCI (12)
+#define IDX_SB_GLIU (13)
+#define IDX_SB_USB2 (14)
+#define IDX_SB_ATA (15)
+#define IDX_SB_MDD (16)
+#define IDX_SB_AC97 (17)
+#define IDX_SB_USB1 (18)
+#define IDX_SB_GLCP (19)
+
+
+#define NUM_DEVS (IDX_SB_GLCP+1)
+
+// definitions for callbacks for PM functions
+#define PM_CALLBACK 0xBD50
+#define PM_CB_LED 0x00
+#define PM_CB_PME 0x01
+#define PM_CB_PME_DISARM 0x00
+#define PM_CB_PME_ARM 0x01
+#define PM_CB_SLEEP 0x02
+#define PM_CB_ENTER_S3 0x00
+#define PM_CB_ENTER_SLEEP 0x01
+#define PM_CB_LEAVE_SLEEP 0x02
+#define PM_CB_DONE_S3 0x03
diff --git a/cpu/amd/geode_lx/gplvsa_ii/inc/chipset.h b/cpu/amd/geode_lx/gplvsa_ii/inc/chipset.h
new file mode 100755
index 0000000..7a4f9ac
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/inc/chipset.h
@@ -0,0 +1,374 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+#define VENDOR_ID_COMPAQ 0x0E11
+#define VENDOR_ID_CYRIX 0x1078
+#define VENDOR_ID_NATIONAL 0x100B
+#define VENDOR_ID_AMD 0x1022
+
+#define DEVICE_ID_MEDIAGX 0x0001
+#define DEVICE_ID_5530 0x0100
+
+#define DEVICE_ID_GX2 0x0028
+#define DEVICE_ID_GFX2 0x0030
+
+#define DEVICE_ID_5535 0x002B
+#define DEVICE_ID_FLASH 0x002C
+#define DEVICE_ID_ATA 0x002D
+#define DEVICE_ID_AUDIO 0x002E
+#define DEVICE_ID_OHCI 0x002F
+
+#define DEVICE_ID_LX 0x2080
+#define DEVICE_ID_GFX3 0x2081
+#define DEVICE_ID_AES 0x2082
+
+#define DEVICE_ID_5536 0x2090
+#define DEVICE_ID_AMD_FLASH 0x2091
+#define DEVICE_ID_AMD_ATA 0x2092
+#define DEVICE_ID_AMD_AUDIO 0x2093
+#define DEVICE_ID_AMD_OHCI 0x2094
+#define DEVICE_ID_AMD_EHCI 0x2095
+#define DEVICE_ID_AMD_UDC 0x2096
+#define DEVICE_ID_AMD_OTG 0x2097
+#define DEVICE_ID_AMD_THOR 0x209A
+
+
+#define LEGACY_FUNCTION 0x0000
+#define PM_FUNCTION 0x0100
+#define IDE_FUNCTION 0x0200
+#define AUDIO_FUNCTION 0x0300
+#define VIDEO_FUNCTION 0x0400
+#define XBUS_FUNCTION 0x0500
+
+
+
+// SMI sources relative to Function 1 BAR0
+#define SMI_STATUS_RO 0x0000
+#define SMI_STATUS 0x0002
+#define SMI_SRC_PM (1L << 0)
+#define SMI_SRC_AUDIO_INDEX 1
+#define SMI_SRC_AUDIO (1L << SMI_SRC_AUDIO_INDEX)
+#define SMI_SRC_ACPI (1L << 2)
+#define SMI_SRC_VG (1L << 3)
+#define SMI_SRC_INT_MEMORY (1L << 4)
+#define SMI_SRC_RETRACE (1L << 5)
+#define SMI_SRC_VGA_TIMER (1L << 6)
+#define SMI_SRC_A20_INDEX 7
+#define SMI_SRC_A20 (1L << SMI_SRC_A20_INDEX)
+#define SMI_SRC_SW_INDEX 8
+#define SMI_SRC_SW (1L << SMI_SRC_SW_INDEX)
+#define GTT_INDEX 9
+#define SMI_SRC_GTT (1L << GTT_INDEX)
+#define SMI_SRC_DEBUG (1L << 10)
+#define SMI_SRC_MFGPT (1L << 11)
+#define SMI_SRC_NMI (1L << 12)
+#define SMI_SRC_RESET (1L << 13)
+#define SMI_SRC_USB1 (1L << 14)
+#define SMI_SRC_USB2 (1L << 15)
+#define SMI_IGNORE 0x7FFF
+
+
+#define GTT_STATUS 0x0006
+// NOTE: The following source definitions are shifted left 16 bits because
+// Get_SMI_Sources passes them that way in the SMI_Sources variable.
+ #define GTT_SRC_GT1 (1L << ( 0+16))
+ #define GTT_SRC_GT2 (1L << ( 1+16))
+ #define GTT_SRC_USR_DEF_TRAP1 (1L << ( 2+16))
+ #define GTT_SRC_USR_DEF_TRAP2 (1L << ( 3+16))
+ #define GTT_SRC_USR_DEF_TRAP3 (1L << ( 4+16))
+ #define SMI_SRC_PCI_TRAP (1L << ( 5+16))
+ #define GTT_SRC_1MS_TMR (1L << ( 6+16))
+ #define GTT_SRC_1SEC_TMR (1L << ( 7+16))
+ #define SMI_SRC_MPCI (1L << ( 8+16)) // Virtualized PCI access
+ #define SMI_SRC_DESCR_HIT (1L << ( 9+16)) // Hit on MBus descriptor
+ #define SMI_SRC_STAT (1L << (10+16)) // Hit on MBus statistics counter
+ #define SMI_SRC_PIC (1L << (11+16)) // PIC event
+ #define SMI_SRC_KEL (1L << (12+16)) // KEL event
+ #define SMI_SRC_PME (1L << (13+16)) // PME event
+ #define SMI_SRC_BLOCKIO (1L << (14+16)) // BLOCKIO event
+
+#define SMI_SPEEDUP_DISABLE 0x0008
+
+#define AUDIO_STATUS 0x0010 // relative to F3 BAR0
+
+
+
+//############################################################################################
+
+
+#define PCI_CFG_CONTROL 0x40
+ #define LEGACY_CFG_SMI (1L << 8)
+ #define PM_CFG_SMI (1L << 11)
+ #define IDE_CFG_SMI (1L << 14)
+ #define AUDIO_CFG_SMI (1L << 16)
+ #define VIDEO_CFG_SMI (1L << 17)
+ #define USB_PM_SMI (1L << 22)
+ #define USB_CFG_SMI (1L << 23)
+ #define USB_ENABLE (1L << 24)
+
+ #define PM_CFG_SMI_SCxxxx (1L << 9)
+ #define IDE_CFG_SMI_SCxxxx (1L << 10)
+ #define AUDIO_CFG_SMI_SCxxxx (1L << 11)
+ #define VIDEO_CFG_SMI_SCxxxx (1L << 12)
+ #define XBUS_CFG_SMI_SCxxxx (1L << 13)
+
+#define RESET_CONTROL 0x44
+ #define X_BUS_WARM_START (1L << 0)
+ #define PCI_RESET (1L << 1)
+ #define IDE_RESET (1L << 2)
+ #define IDE_CONTROLLER_RESET (1L << 3)
+ #define AC97_RESET (1L << 7)
+
+
+#define ROM_AT_LOGIC 0x52
+ #define LOWER_ROM_ENABLE (1 << 0)
+ #define ROM_WRITE_ENABLE (1 << 1)
+ #define ROM_1MB_WRITE_ENABLE (1 << 2)
+ #define PORT_92_ENABLE (1 << 3)
+ #define A20M_DEASSERT (1 << 4)
+ #define GAMEPORT_CS_ON_READS (1 << 5)
+ #define GAMEPORT_CS_ON_WRITES (1 << 6)
+ #define FAST_KEYBOARD_DISABLE (1 << 7)
+
+
+#define CPU_SUPPORT 0x53
+ #define A20M_ENABLE (1 << 0)
+ #define RTC_ENABLE (1 << 2)
+ #define GAMEPORT_ENABLE (1 << 3)
+
+#define DECODE_CONTROL 0x5A
+ #define RTC_POSITIVE_DECODE (1 << 0)
+ #define KBD_POSITIVE_DECODE (1 << 1)
+ #define COM1_POSITIVE_DECODE (1 << 2)
+ #define COM2_POSITIVE_DECODE (1 << 3)
+ #define COM3_POSITIVE_DECODE (1 << 4)
+ #define COM4_POSITIVE_DECODE (1 << 5)
+ #define FLPY1_POSITIVE_DECODE (1 << 6)
+ #define FLPY2_POSITIVE_DECODE (1 << 7)
+ #define LPT1_POSITIVE_DECODE (1 << 8)
+ #define LPT2_POSITIVE_DECODE (1 << 9)
+ #define LPT3_POSITIVE_DECODE (1 << 10)
+ #define IDE1_POSITIVE_DECODE (1 << 11)
+ #define IDE2_POSITIVE_DECODE (1 << 12)
+ #define ROM_POSITIVE_DECODE (1 << 13)
+ #define KBD_6X_DECODE (1 << 15)
+
+#define PCI_STEERING 0x5C
+
+
+// Top-level SMI enables (registers 0x80-0x83)
+#define ENABLE_TRAPS_TIMERS 0x80
+ #define ENABLE_PM (1L << 0)
+ #define ENABLE_TIMERS (1L << 1)
+ #define ENABLE_TRAPS (1L << 2)
+ #define ENABLE_IRQ_SPEEDUP (1L << 3)
+ #define ENABLE_VIDEO_SPEEDUP (1L << 4)
+ #define ENABLE_CODEC_SMI (1L << 5)
+ #define ENABLE_RESERVED1 (1L << 6)
+ #define ENABLE_RESERVED2 (1L << 7)
+ #define ENABLE_HDD0_TIMER (1L << 8)
+ #define ENABLE_FDD_TIMER (1L << 9)
+ #define ENABLE_PAR_SER_TIMER (1L << 10)
+ #define ENABLE_KYBD_MOUSE_TIMER (1L << 11)
+ #define ENABLE_USR_DEF_TIMER1 (1L << 12)
+ #define ENABLE_USR_DEF_TIMER2 (1L << 13)
+ #define ENABLE_USR_DEF_TIMER3 (1L << 14)
+ #define ENABLE_VIDEO_TIMER (1L << 15)
+ #define ENABLE_HDD0_TRAP (1L << 16)
+ #define ENABLE_FDD_TRAP (1L << 17)
+ #define ENABLE_PAR_SER_TRAP (1L << 18)
+ #define ENABLE_KYBD_MOUSE_TRAP (1L << 19)
+ #define ENABLE_USR_DEF_TRAP1 (1L << 20)
+ #define ENABLE_USR_DEF_TRAP2 (1L << 21)
+ #define ENABLE_USR_DEF_TRAP3 (1L << 22)
+ #define ENABLE_VIDEO_TRAP (1L << 23)
+ #define ENABLE_GT1 (1L << 24)
+ #define ENABLE_GT2 (1L << 25)
+ #define ENABLE_RETRACE (1L << 26)
+ #define ENABLE_VGA_TIMER (1L << 27)
+ #define ENABLE_THERMAL (1L << 28) // SCxxxx only
+ #define ENABLE_ACPI_TIMER (1L << 29)
+ #define ENABLE_HDD1_TRAP (1L << 30)
+ #define ENABLE_HDD1_TIMER (1L << 31)
+
+
+#define GT1_COUNT 0x88
+#define GT1_CONTROL 0x89
+ #define GT1_RESET_HDD (1 << 0)
+ #define GT1_RESET_FDD (1 << 1)
+ #define GT1_RESET_PARALLEL_SERIAL (1 << 2)
+ #define GT1_RESET_KEYBD_MOUSE (1 << 3)
+ #define GT1_RESET_USR_DEF1 (1 << 4)
+ #define GT1_RESET_USR_DEF2 (1 << 5)
+ #define GT1_RESET_USR_DEF3 (1 << 6)
+ #define GT1_TIMEBASE (1 << 7)
+
+
+#define GT2_COUNT 0x8A
+#define GT2_CONTROL 0x8B
+ #define GT2_RESET_GPIO7 (1 << 2)
+ #define GT2_TIMEBASE (1 << 3) // 0=second 1=ms
+ #define GT1_SHIFT (1 << 4) // 0=8 bit 1=16 bit
+ #define GT2_SHIFT (1 << 5) // 0=8 bit 1=16 bit
+ #define VGA_TIMEBASE (1 << 6) // 0=ms 1=32 us
+ #define GT1_RESET_SEC_HDD (1 << 7) // 0=disable 1=enable
+
+#define IRQ_SPEEDUP_COUNT 0x8C
+#define VIDEO_SPEEDUP_COUNT 0x8D
+#define VGA_TIMER_LOAD_COUNT 0x8E
+
+
+
+
+#define GPIO_DIRECTION 0x90
+#define GPIO_DATA 0x91
+#define GPIO_CONTROL 0x92
+ #define GPIO0_ENABLE (1 << 0)
+ #define GPIO1_ENABLE (1 << 1)
+ #define GPIO2_ENABLE (1 << 2)
+ #define GPIO0_EDGE (1 << 3)
+ #define GPIO1_EDGE (1 << 4)
+ #define GPIO2_EDGE (1 << 5)
+ #define GPIO6_ENABLE (1 << 6)
+ #define GPIO6_EDGE (0 << 6)
+ #define GPIO7_EDGE (1 << 7)
+
+
+
+#define MISCELLANEOUS 0x93
+ #define SERIAL_MOUSE_SELECT (1 << 0)
+ #define SERIAL_MOUSE (1 << 1)
+ #define HDD1_PARTIAL_DECODE (1 << 4)
+ #define HDD0_PARTIAL_DECODE (1 << 5)
+ #define HDD_SELECT (1 << 6)
+ #define FDD_SELECT (1 << 7)
+
+#define SUSPEND_MODULATION_OFF 0x94
+#define SUSPEND_MODULATION_ON 0x95
+#define SUSPEND_CONFIGURATION 0x96
+ #define SUSPEND_MOD_ENABLE (1 << 0)
+ #define SMI_SPEEDUP (1 << 1)
+ #define SUSPEND_MODE (1 << 2)
+
+
+#define GPIO_CONTROL2 0x97
+ #define GPIO3_ENABLE (1 << 0)
+ #define GPIO4_ENABLE (1 << 1)
+ #define GPIO5_ENABLE (1 << 2)
+ #define GPIO7_ENABLE (1 << 3)
+ #define GPIO3_EDGE (1 << 4)
+ #define GPIO4_EDGE (1 << 5)
+ #define GPIO5_EDGE (1 << 6)
+ #define GPIO7_EDGE (1 << 7)
+
+
+#define HDD_IDLE_TIMEOUT 0x98
+#define FDD_IDLE_TIMEOUT 0x9A
+#define PAR_SER_IDLE_TIMEOUT 0x9C
+#define KYBD_MOUSE_IDLE_TIMEOUT 0x9E
+#define USR_DEF1_IDLE_TIMEOUT 0xA0
+#define USR_DEF2_IDLE_TIMEOUT 0xA2
+#define USR_DEF3_IDLE_TIMEOUT 0xA4
+#define VIDEO_IDLE_TIMEOUT 0xA6
+
+#define SEC_HDD_TIMEOUT 0xAC
+#define CPU_SUSPEND_COMMAND 0xAE
+#define CPU_STOP_CLOCK_COMMAND 0xAF
+#define CPU_CACHE_MISS_ACTIVITY 0xB0
+#define CPU_CACHE_MISS_INACTIVITY 0xB1
+#define CPU_CACHE_MISS_THRESHOLD 0xB2
+
+#define FLOPPY_SHADOW 0xB4
+#define FLOPPY_3F2 0xB4
+#define FLOPPY_3F7 0xB5
+#define FLOPPY_372 0xB6
+#define FLOPPY_377 0xB7
+
+#define DMA_SHADOW 0xB8
+#define DMA_SHADOW_CNT 10
+
+#define PIC_SHADOW 0xB9
+#define PIC_SHADOW_CNT 12
+
+#define PIT_SHADOW 0xBA
+#define PIT_SHADOW_CNT 9
+
+#define RTC_SHADOW 0xBB
+#define RTC_SHADOW_CNT 1
+
+#define PIC_SHADOW 0xB9
+#define PIT_SHADOW 0xBA
+#define RTC_SHADOW 0xBB
+
+#define CLOCK_STOP_CONTROL 0xBC
+
+#define USR_DEF_1_BASE 0xC0
+#define USR_DEF_2_BASE 0xC4
+#define USR_DEF_3_BASE 0xC8
+#define USR_DEF_1_CONTROL 0xCC
+#define USR_DEF_2_CONTROL 0xCD
+#define USR_DEF_3_CONTROL 0xCE
+ #define USR_DEF_MEMORY (1 << 7) // Bit 7 = 1
+ #define USR_DEF_IO (0 << 7) // Bit 7 = 0
+ #define USR_DEF_WRITE (1 << 6) // Bit 6 = 1 (only for I/O)
+ #define USR_DEF_READ (1 << 5) // Bit 5 = 1 (only for I/O)
+
+
+#define SW_SMI 0xD0
+
+
+
+// Relative to PCI Function 0
+#define PM_STATUS 0xF4
+ #define PM_SRC_GPIO3 (1L << 0)
+ #define PM_SRC_GPIO4 (1L << 1)
+ #define PM_SRC_GPIO5 (1L << 2)
+ #define PM_SRC_GPIO7 (1L << 3)
+ #define PM_SRC_GAMEPORT (1L << 4)
+ #define PM_SRC_HDD_IDLE (1L << 8) // Primary
+ #define PM_SRC_FDD_IDLE (1L << 9)
+ #define PM_SRC_PARSER_IDLE (1L << 10)
+ #define PM_SRC_KEYBMS_IDLE (1L << 11)
+ #define PM_SRC_USER_DEF1_IDLE (1L << 12)
+ #define PM_SRC_USER_DEF2_IDLE (1L << 13)
+ #define PM_SRC_USER_DEF3_IDLE (1L << 14)
+ #define PM_SRC_VIDEO_IDLE (1L << 15)
+ #define PM_SRC_HDD_TRAP (1L << 16) // Primary
+ #define PM_SRC_FDD_TRAP (1L << 17)
+ #define PM_SRC_PAR_SER_TRAP (1L << 18)
+ #define PM_SRC_KYBD_MOUSE_TRAP (1L << 19)
+ #define PM_SRC_SECONDARY_IDLE (1L << 20)
+ #define PM_SRC_SECONDARY_TRAP (1L << 21)
+ #define PM_SRC_reserved (1L << 22)
+ #define PM_SRC_VIDEO_TRAP (1L << 23)
+ #define PM_SRC_ACPI_TIMER (1L << 24)
+ #define PM_SRC_RTC_ALARM (1L << 25)
+ #define PM_SRC_AC97_CODEC (1L << 26)
+ #define PM_SRC_LID_SWITCH (1L << 27)
+ #define PM_SRC_LID_POSITION (1L << 28) // Not an SMI source
+ #define PM_SRC_GPIO0 (1L << 29)
+ #define PM_SRC_GPIO1 (1L << 30) // CS55x0 only
+ #define PM_SRC_THERMAL (1L << 30) // SCxxxx only
+ #define PM_SRC_GPIO2 ((ULONG)(1L << 31))
+
+
+#define GPIO_PINS (PM_SRC_GPIO0 | PM_SRC_GPIO1 | PM_SRC_GPIO2 | PM_SRC_GPIO3 | PM_SRC_GPIO4 | PM_SRC_GPIO5 | PM_SRC_LID_SWITCH | PM_SRC_GPIO7)
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/inc/cs5536.h b/cpu/amd/geode_lx/gplvsa_ii/inc/cs5536.h
new file mode 100755
index 0000000..45981d7
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/inc/cs5536.h
@@ -0,0 +1,230 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//************************** CS5536 related defines ***************************
+
+
+
+// Southbridge MPCI CTRL:
+#define ME (1 << 0) // Enable in-bound memory accesses
+#define IE (1 << 1) // Enable in-bound I/O accesses
+#define CIS_MASK (3 << 3) // CIS Mode
+ #define CIS_A (1 << 3)
+ #define CIS_B (2 << 3)
+ #define CIS_C (3 << 3)
+
+
+
+#define MPCI_SOUTH 0x51000000 // 2.4.2.0
+
+#define MDD_PORT 4 // Port that MDD is at
+
+
+
+#define REGION_R0 0x20
+#define REGION_R15 (REGION_R0 + 15)
+
+
+
+
+/****** 5536 GPIO definitions ******/
+
+// offsets from GPIO base
+#define GPIO5536_BASE (0x6100)
+
+#define NUM_5536_GPIO (28)
+
+#define GPIOH_OFFSET (0x80)
+
+#define GPIO_OUT_VAL (0x00)
+#define GPIO_OUT_EN (0x04)
+#define GPIO_OUT_OD_EN (0x08)
+#define GPIO_OUT_INV_EN (0x0C)
+#define GPIO_OUT_AUX1_SEL (0x10)
+#define GPIO_OUT_AUX2_SEL (0x14)
+#define GPIO_PU_EN (0x18)
+#define GPIO_PD_EN (0x1C)
+#define GPIO_IN_EN (0x20)
+#define GPIO_IN_INV_EN (0x24)
+#define GPIO_IN_FIL_EN (0x28)
+#define GPIO_IN_EVC_EN (0x2C)
+#define GPIO_READBACK (0x30)
+#define GPIO_IN_AUX_SEL (0x34)
+#define GPIO_EVENT_EN (0x38)
+#define GPIO_LOCK_EN (0x3C)
+#define GPIO_IN_PEDG_EN (0x40)
+#define GPIO_IN_NEDG_EN (0x44)
+#define GPIO_IN_PEDG_STS (0x48)
+#define GPIO_IN_NEDG_STS (0x4C)
+
+#define GPIO00_FILA (0x50)
+#define GPIO00_FILC (0x52)
+#define GPIO00_EVCNT (0x54)
+#define GPIO00_EVCMP (0x56)
+#define GPIO01_FILA (0x58)
+#define GPIO01_FILC (0x5A)
+#define GPIO01_EVCNT (0x5C)
+#define GPIO01_EVCMP (0x5E)
+#define GPIO02_FILA (0x60)
+#define GPIO02_FILC (0x62)
+#define GPIO02_EVCNT (0x64)
+#define GPIO02_EVCMP (0x66)
+#define GPIO03_FILA (0x68)
+#define GPIO03_FILC (0x6A)
+#define GPIO03_EVCNT (0x6C)
+#define GPIO03_EVCMP (0x6E)
+#define GPIO04_FILA (0x70)
+#define GPIO04_FILC (0x72)
+#define GPIO04_EVCNT (0x74)
+#define GPIO04_EVCMP (0x76)
+#define GPIO05_FILA (0x78)
+#define GPIO05_FILC (0x7A)
+#define GPIO05_EVCNT (0x7C)
+#define GPIO05_EVCMP (0x7E)
+#define GPIO06_FILA (0xD0)
+#define GPIO06_FILC (0xD2)
+#define GPIO06_EVCNT (0xD4)
+#define GPIO06_EVCMP (0xD6)
+#define GPIO07_FILA (0xD8)
+#define GPIO07_FILC (0xDA)
+#define GPIO07_EVCNT (0xDC)
+#define GPIO07_EVCMP (0xDE)
+
+#define GPIO_MAPX (0xE0)
+#define GPIO_MAPY (0xE4)
+#define GPIO_MAPZ (0xE8)
+#define GPIO_MAPW (0xEC)
+
+#define GPIO_FE0 (0xF0)
+#define GPIO_FE1 (0xF1)
+#define GPIO_FE2 (0xF2)
+#define GPIO_FE3 (0xF3)
+#define GPIO_FE4 (0xF4)
+#define GPIO_FE5 (0xF5)
+#define GPIO_FE6 (0xF6)
+#define GPIO_FE7 (0xF7)
+
+#define GPIOL_IN_EVENT_DECR (0xF8)
+#define GPIOH_IN_EVENT_DECR (0xFC)
+
+// GPIO atomic register values
+#define GPIO00_SET (0x00000001L)
+#define GPIO00_CLR (0x00010000L)
+#define GPIO01_SET (0x00000002L)
+#define GPIO01_CLR (0x00020000L)
+#define GPIO02_SET (0x00000004L)
+#define GPIO02_CLR (0x00040000L)
+#define GPIO03_SET (0x00000008L)
+#define GPIO03_CLR (0x00080000L)
+#define GPIO04_SET (0x00000010L)
+#define GPIO04_CLR (0x00100000L)
+#define GPIO05_SET (0x00000020L)
+#define GPIO05_CLR (0x00200000L)
+#define GPIO06_SET (0x00000040L)
+#define GPIO06_CLR (0x00400000L)
+#define GPIO07_SET (0x00000080L)
+#define GPIO07_CLR (0x00800000L)
+#define GPIO08_SET (0x00000100L)
+#define GPIO08_CLR (0x01000000L)
+#define GPIO09_SET (0x00000200L)
+#define GPIO09_CLR (0x02000000L)
+#define GPIO10_SET (0x00000400L)
+#define GPIO10_CLR (0x04000000L)
+#define GPIO11_SET (0x00000800L)
+#define GPIO11_CLR (0x08000000L)
+#define GPIO12_SET (0x00001000L)
+#define GPIO12_CLR (0x10000000L)
+#define GPIO13_SET (0x00002000L)
+#define GPIO13_CLR (0x20000000L)
+#define GPIO14_SET (0x00004000L)
+#define GPIO14_CLR (0x40000000L)
+#define GPIO15_SET (0x00008000L)
+#define GPIO15_CLR (0x80000000L)
+
+#define GPIO16_SET (0x00000001L)
+#define GPIO16_CLR (0x00010000L)
+#define GPIO17_SET (0x00000002L)
+#define GPIO17_CLR (0x00020000L)
+#define GPIO18_SET (0x00000004L)
+#define GPIO18_CLR (0x00040000L)
+#define GPIO19_SET (0x00000008L)
+#define GPIO19_CLR (0x00080000L)
+#define GPIO20_SET (0x00000010L)
+#define GPIO20_CLR (0x00100000L)
+#define GPIO21_SET (0x00000020L)
+#define GPIO21_CLR (0x00200000L)
+#define GPIO22_SET (0x00000040L)
+#define GPIO22_CLR (0x00400000L)
+#define GPIO23_SET (0x00000080L)
+#define GPIO23_CLR (0x00800000L)
+#define GPIO24_SET (0x00000100L)
+#define GPIO24_CLR (0x01000000L)
+#define GPIO25_SET (0x00000200L)
+#define GPIO25_CLR (0x02000000L)
+#define GPIO26_SET (0x00000400L)
+#define GPIO26_CLR (0x04000000L)
+#define GPIO27_SET (0x00000800L)
+#define GPIO27_CLR (0x08000000L)
+#define GPIO28_SET (0x00001000L)
+#define GPIO28_CLR (0x10000000L)
+#define GPIO29_SET (0x00002000L)
+#define GPIO29_CLR (0x20000000L)
+#define GPIO30_SET (0x00004000L)
+#define GPIO30_CLR (0x40000000L)
+#define GPIO31_SET (0x00008000L)
+#define GPIO31_CLR (0x80000000L)
+
+// Hawk platform has Sleep Button connected to GPIO25
+#define DEFAULT_SLPB_GPIO (25)
+
+// GPIO13 AUX_IN is dedicated 5536 Sleep Button but it is only connected
+// to Working Power Domain and can't wake the system from Standby.
+// #define DEFAULT_SLPB_GPIO (13)
+
+
+// 5536 Power Management Controller
+
+// offsets from base PMC I/O address, all are 32-bit regs
+#define PM_SSD (0x00) // Sleep start delay
+#define PM_SCXA (0x04) // Sleep control X Assert Delay and Enable
+#define PM_SCYA (0x08) // Sleep control Y Assert Delay and Enable
+#define PM_SODA (0x0C) // Sleep Output Disable Assert Delay and Enable
+#define PM_SCLK (0x10) // Sleep Clock Delay and Enable
+#define PM_SED (0x14) // Sleep End Delay
+#define PM_SCXD (0x18) // Sleep Control X De-assert Delay and Enable
+#define PM_SCYD (0x1C) // Sleep Control Y De-assert Delay and Enable
+#define PM_SIDD (0x20) // Sleep Input Disable De-assert Delay and Enable
+#define PM_WKD (0x30) // Working De-assert Delay and Enable
+#define PM_WKXD (0x34) // Work_AUX De-assert Delay and Enable
+#define PM_RD (0x38) // De-assert Delay from Standby
+#define PM_WKXA (0x3C) // Work_AUX Assert Delay from Standby Wakeup
+#define PM_FSD (0x40) // Fail-Safe Delay and Enable
+#define PM_TSD (0x44) // Thermal-Safe Delay and Enable
+#define PM_PSD (0x48) // Power-Safe Delay and Enable
+#define PM_NWKD (0x4C) // Normal Work Delay and Enable
+#define PM_AWKD (0x50) // Abnormal Work Delay and Enable
+#define PM_SSC (0x54) // Standby Status and Control
+
+
+
+#define USBMSROHCB 0x0008
+#define USBMSREHCB 0x0009
+#define USBMSRUDCB 0x000A
+#define USBMSRUOCB 0x000B
+#define PMEEN (1L << 3)
diff --git a/cpu/amd/geode_lx/gplvsa_ii/inc/gx2.h b/cpu/amd/geode_lx/gplvsa_ii/inc/gx2.h
new file mode 100755
index 0000000..b9c66ae
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/inc/gx2.h
@@ -0,0 +1,443 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+
+// Vail MSRs
+#define MSR_SMM_CTRL 0x1301
+ #define SMM_NMI_EN (1L << 0) // Enables NMIs during SMM
+ #define SMM_SUSP_EN (1L << 1) // Enables SUSP# pin during SMM
+ #define NEST_SMI_EN (1L << 2) // Enables SSMIs during SMM
+ #define SMM_INST_EN (1L << 3) // Enables SMM instructions
+ #define INTL_SMI_EN (1L << 4) // Enables SSMIs
+ #define EXTL_SMI_EN (1L << 5) // Enables SMI# pin
+
+#define MSR_SMM_HDR 0x132B
+#define MSR_SMM_LOC 0x133B
+#define MSR_EFLAGS 0x1418
+#define MSR_CR0 0x1420
+#define MSR_DR7 0x1343
+
+
+//
+// Region Control Registers (see page 10-188 of Vail spec)
+//
+#define REGION_CD (1L << 0) // Cache disabled
+#define REGION_WA (1L << 1) // Write-allocate
+#define REGION_WP (1L << 2) // Write-protect
+#define REGION_WT (1L << 3) // Write-through
+#define REGION_WC (1L << 4) // Write-combine
+#define REGION_WS (1L << 5) // Write-serialize
+#define REGION_EN (1L << 8) // Region enable
+
+#define MSR_RCONF_DEFAULT 0x1808
+#define MSR_RCONF_BYPASS 0x180A
+#define MSR_RCONF_A0_BF 0x180B
+#define MSR_RCONF_C0_DF 0x180C
+#define MSR_RCONF_E0_FF 0x180D
+#define MSR_RCONF_SMM 0x180E
+#define MSR_RCONF_DMM 0x180F
+
+
+// Bit(s) Field
+// ------ -----------------------------------------------
+// 7:0 Region Properties
+// 8 Enable
+// 11:9 reserved
+// 31:12 Start of region (4 KB granularity; inclusive)
+// 43:32 reserved
+// 63:44 Top of region (4 KB granularity; inclusive)
+#define MSR_RCONF0 0x1810
+#define MSR_RCONF1 0x1811
+#define MSR_RCONF2 0x1812
+#define MSR_RCONF3 0x1813
+#define MSR_RCONF4 0x1814
+#define MSR_RCONF5 0x1815
+#define MSR_RCONF6 0x1816
+#define MSR_RCONF7 0x1817
+
+
+//========================================================================================
+#define BIZARRO (1L << 28)
+#define ROUTING 0xFFFFC000 // Mask for routing field
+
+
+
+// Ports under Redcloud MBIU0
+#define PORT_MBIU0 0x10000000L // By convention
+
+
+// Standard MBus Device MSRs:
+#define MBD_MSR_CAP 0x2000
+#define MBD_MSR_CONFIG 0x2001 // 3 LSBs = subtractive port
+ // MBIU0: 0x00000002
+ // MBIU1: 0x00000004
+ // MBIU2: 0x00000004
+
+#define MBD_MSR_SMI 0x2002
+#define MBD_MSR_ERROR 0x2003
+#define MBD_MSR_PM 0x2004
+#define MBD_MSR_DIAG 0x2005
+
+// Northbridge MPCI
+#define MPCI_CTRL 0x2010
+ #define LDE (1 << 9) // Enable latency disconnect timer
+#define MPCI_ARB 0x2011
+#define MPCI_PBUS 0x2012
+#define MPCI_REN 0x2014 // Fixed Region Enables
+#define MPCI_A0_BF 0x2015 // Fixed Regions Properties A0000-BFFFF
+#define MPCI_C0_DF 0x2016 // Fixed Regions Properties C0000-DFFFF
+#define MPCI_E0_FF 0x2017 // Fixed Regions Properties E0000-FFFFF
+#define MPCI_R0 0x2018 // Base memory
+#define MPCI_R1 0x2019 // Extended memory
+#define MPCI_R2 0x201A // SMM memory
+#define MPCI_R3 0x201B
+#define MPCI_R4 0x201C
+#define MPCI_R5 0x201D
+ // MPCI Region Control Registers (see page 89 of MPCI spec)
+ #define REGION_CD (1L << 0) // Cache disabled
+ #define REGION_DD (1L << 1) // Discard data
+ #define REGION_WP (1L << 2) // Write protect
+ #define REGION_WT (1L << 3) // Write through
+ #define REGION_WC (1L << 4) // Write combine
+ #define REGION_PF (1L << 5) // Prefetchable
+
+#define MPCI_ExtMSR 0x201E
+
+
+
+// Revision IDs
+#define CPU_REV_1_0 0x11
+#define CPU_REV_1_1 0x12
+#define CPU_REV_2_0 0x20
+
+
+// MBus Device IDs:
+#define ID_SHIFT 12
+#define ID_MBIU 0x01
+#define ID_MC 0x20
+#define ID_VAIL 0x86
+#define ID_AES 0x30
+#define ID_VIP 0x3C
+#define ID_GP 0x3D
+#define ID_VG 0x3E
+#define ID_DF 0x3F
+#define ID_MCP 0x02
+#define ID_MPCI 0x05
+#define ID_FG 0xF0
+#define ID_OHCI 0x42
+#define ID_USB_20 0x43
+#define ID_ATA 0x47
+#define ID_ATA100 0x48
+#define ID_MDD 0xDF
+#define ID_AC97 0x33
+
+
+
+/////////////////////////////////////////////////////////////
+// Northbridge
+/////////////////////////////////////////////////////////////
+// MBIU0
+//
+// Capabilities: 22711830 010C1086
+// P2D_BM = 6; 0x20-0x25
+// P2D_BMO = 2; 0x26-0x27
+// P2D_R = 1; 0x28
+// P2D_RO = 3; 0x29-0x2B
+// P2D_SC = 1; 0x2C
+// P2D_SCO = 0;
+// IOD_BM = 3; 0xE0-0xE2
+// IOD_SC = 6; 0xE3-0xE8
+// NPORTS = 5;
+// STATS = 2;
+//
+// Port Dev_ID Routing FS/2 Device Description
+// ----- -------- ------------------- -------- ------------------
+// 0 01h 10000000 0.1.0.0.0 20000000 MBIU0
+// 1 20h 20000000 1.0.0.0.0 24000000 Memory Controller
+// 2 01h 40000000 2.0.0.0.0 MBIU1 (subtractive)
+// 3 86h 60000000 3.0.0.0.0 2C000000 Vail (self-reference)
+// 4 3Eh 80000000 4.0.0.0.0 30000000 Video Generator
+// 5 3Dh A0000000 5.0.0.0.0 34000000 Graphics Processor
+// 6 3Fh C0000000 6.0.0.0.0 38000000 Display Filter
+// 7 <empty>
+
+#define VG_PORT 4L
+#define GP_PORT 5L
+#define VG_SMI_MSR (VG_PORT << 29) + MBD_MSR_SMI
+#define GP_SMI_MSR (GP_PORT << 29) + MBD_MSR_SMI
+
+
+//
+// MBIU1
+//
+// Capabilities: 20281830 01004009
+// P2D_BM = 9; 0x20-0x28
+// P2D_BMO = 0;
+// P2D_R = 4; 0x29-0x2C
+// P2D_RO = 0;
+// P2D_SC = 1; 0x2D
+// P2D_SCO = 0;
+// IOD_BM = 3; 0xE0-0xE2
+// IOD_SC = 6; 0xE3-0xE8
+// NPORTS = 5;
+// STATS = 2;
+//
+// Port Dev_ID Routing FS/2 Device Description
+// ----- -------- ------------------- -------- ------------------
+// 0 <empty>
+// 1 01h 44000000 2.1.0.0.0 01000000 MBIU1 (self-reference)
+// 2 <empty>
+// 3 02h 4C000000 2.3.0.0.0 00000000 MCP
+// 4 05h 50000000 2.4.0.0.0 80000000 MPCI Northbridge (subtractive)
+// 5 F0h 54000000 2.5.0.0.0 A0000000 FooGlue
+// 6 <empty>
+// 7 <empty>
+
+#define MBIU0_PORT 1 // From MBIU1's point of view
+
+
+/////////////////////////////////////////////////////////////
+// CS5535
+/////////////////////////////////////////////////////////////
+//
+// Capabilities: 327920A0 80000003 (simulator: 303820a0)
+// P2D_BM = 3; 0x20-0x22
+// P2D_BMK = 2; 0x23-0x24
+// IOD_BM = 10; 0xE0-0xE9
+// IOD_SC = 8; 0xEA-0xF1
+// NPORTS = 7;
+// STATS = 3;
+//
+//
+// Port Dev_ID Routing FS/2 Device Description
+// ----- -------- ------------------- -------- -----------------
+// 05h 51000000 2.4.2.0.0 88000000 MPCI Southbridge
+// 0 01h 51020000 2.4.2.0.1 88100000 MBIU2
+// 1 51100000 2.4.2.1.0 MPCI (self-reference)
+// 2 42h 51200000 2.4.2.2.0 89000000 OHCI #2
+// 3 47h 51300000 2.4.2.3.0 89800000 ATA-5
+// 4 DFh 51400000 2.4.2.4.0 8A000000 MDD (subtractive)
+// 5 33h 51500000 2.4.2.5.0 8A800000 AC97 codec
+// 6 42h 51600000 2.4.2.6.0 8B000000 OHCI #1
+// 7 02h 51700000 2.4.2.7.0 8B800000 MCP
+
+
+/////////////////////////////////////////////////////////////
+// CS5536
+/////////////////////////////////////////////////////////////
+//
+// Capabilities: 327920A0 80000003
+// P2D_BM = 3; 0x20-0x22
+// P2D_BMK = 2; 0x23-0x24
+// IOD_BM = 10; 0xE0-0xE9
+// IOD_SC = 8; 0xEA-0xF1
+// NPORTS = 7;
+// STATS = 3;
+//
+//
+// Port Dev_ID Routing FS/2 Device Description
+// ----- -------- ------------------- -------- -----------------
+// 05h 51000000 2.4.2.0.0 88000000 MPCI Southbridge
+// 0 01h 51020000 2.4.2.0.1 88100000 MBIU2
+// 1 51100000 2.4.2.1.0 MPCI (self-reference)
+// 2 42h 51200000 2.4.2.2.0 89000000 <empty>
+// 3 47h 51300000 2.4.2.3.0 89800000 ATA-5
+// 4 DFh 51400000 2.4.2.4.0 8A000000 MDD (subtractive)
+// 5 33h 51500000 2.4.2.5.0 8A800000 AC97 codec
+// 6 43h 51600000 2.4.2.6.0 8B000000 USB 2.0
+// 7 02h 51700000 2.4.2.7.0 8B800000 MCP
+
+
+//
+// Arcturus
+//
+// Device AD PIN Physical Device
+// ------ ------ ---------------------------------------------------
+// 13 23 MacPhyter
+// 14 24 PCI Slot 1
+// 15 25 PCI Slot 2
+// 16 26 Chipset Register Space - pin H26 High
+// 17 27 USB Register Space - pin H26 High
+// 18 28 Chipset Register Space - pin H26 Low
+// 19 29 USB Register Space - pin H26 Low
+
+
+//
+// MPCI
+//
+
+// Fields for both MPCI_MSR_SMI and MPCI_MSR_ERROR
+ #define MARM (1L << 0)
+ #define TARM (1L << 1)
+ #define BMM (1L << 2)
+ #define SSMM (1L << 2) // only in MPCI SB MSR_SMI
+ #define VPHM (1L << 3) // only in MPCI NB MSR_SMI
+ #define SYSM (1L << 4)
+ #define PARM (1L << 5)
+ #define MARE (1L << 16)
+ #define TARE (1L << 17)
+ #define BME (1L << 18) // Northbridge only ?
+ #define VPHE (1L << 19) // only in MPCI NB MSR_SMI
+ #define SYSE (1L << 20)
+ #define PARE (1L << 21)
+ #define TASE (1L << 22)
+
+
+
+// FooGlue MSRs:
+#define FG_IIOC 0x0010
+ #define MODE_5530 0
+ #define MODE_5535A 1
+ #define MODE_5535B 2
+#define FG_A20M 0x0011
+ #define A20M (1 << 0)
+#define FG_NMI 0x0012
+ #define NMI (1 << 0)
+
+#define FG_INIT 0x0013
+ #define INIT (1 << 0)
+
+
+
+#define MBIU_COH 0x0080
+#define MBIU_PAE 0x0081
+#define MBIU_ARB 0x0082
+#define MBIU_ASMI 0x0083
+#define MBIU_ERR 0x0084
+#define MBIU_DEBUG 0x0085
+#define MBIU_CAP 0x0086
+#define MBIU_NOUT_RESP 0x0087
+#define MBIU_NOUT_WDATA 0x0088
+#define MBIU_WHOAMI 0x008B
+ // MBIU_WHOAMI tells self-reference:
+ // MBIU0: 0x00000003
+ // MBIU1: 0x00000001
+ // MBIU2: 0x00000001
+#define MBIU_SLV 0x008C
+
+
+
+
+
+//
+// Descriptor MSRs
+//
+#define MSR_MEM_DESCR 0x0020
+#define MSR_IO_DESCR 0x00E0
+ // Defines for IOD_SC
+ #define REN (1L << 20)
+ #define WEN (1L << 21)
+
+
+
+
+
+
+
+//
+// Descriptor Statistics MSRs
+//
+#define MSR_STATISTICS_CNT 0x00A0 // and A4, A8, AC
+ // High dword is Load Value; Low dword is Count
+#define MSR_STATISTICS_MASK 0x00A1 // and A5, A9, AD
+ // High dword is IOD mask; Low dword is P2D mask
+#define MSR_STATISTICS_ACTION 0x00A2 // and A6, AA, AE
+ #define HIT_LDEN (1L << 0) // Load CNT on descriptor hit
+ #define HIT_DEC (1L << 1) // Decrement CNT on descriptor hit
+ #define HIT_SMI (1L << 2) // Assert ASMI on descriptor hit
+ #define HIT_ERR (1L << 3) // Assert AERR on descriptor hit
+ #define ALWAYS_DEC (1L << 4) // Always decrement CNT (unless loading or (CNT = 0 & !RELOAD))
+ #define ZERO_SMI (1L << 5) // Assert ASMI on CNT = 0
+ #define ZERO_ERR (1L << 6) // Assert AERR on CNT = 0
+ #define WRAP (1L << 7) // Reload CNT from LOAD_VAL on CNT = 0
+
+// Vail PM stuff
+#define BC_MSR0 0x1900
+ #define SUSP_EN (0x1000L)
+
+#define XC_CONFIG 0x1210
+ #define XC_CLK_SUSP (0x01L)
+
+// GX2 Memory Controller PM stuff
+
+// MC PMode1 Up Delay
+#define MC_CF1017_DATA 0x001A
+ #define PM1_UP_DLY_MASK (0xFF00L)
+ // 240ns delay, DDR spec. state minimum delay is 200ns
+ #define PM1_UP_DLY_VAL (0xF000L)
+
+// MC PMode Sensitivity
+// bits[63:32]=PMode1, bits[31:0]=PMode0
+#define MC_CF_PMCTR 0x0020
+ // number of MC clocks that MC must be inactive
+ // before entering PMode1
+ #define PM1_SENS_VAL (0x020L)
+
+
+// GX2 GLCP PM stuff
+
+// Clock Disable Delay
+#define MCP_CLK_DIS_DLY 0x0008
+ #define CLKDIS_MASK (0x00FFFFFFL)
+
+// PM Clock Disable
+#define MCP_PMCLKDISABLE (0x0009)
+
+#define MCP_PMCLKOFF (0x0010)
+
+// PM CLK4ACK MSR
+#define MCP_CLK4ACK 0x0013
+ #define S3_CLK4ACK (0x07BE7FC3L)
+ #define S1_CLK4ACK S3_CLK4ACK
+
+// Throttling PM I/O regs default location
+#define MCP_GLB_PM 0x000B
+ #define MCP_GLB_THEN (0x01L)
+
+#define MCP_DOTPLL 0x0015
+#define MCP_DBGCLKCTL 0x0016
+
+// default location to map GLCP P_CNT I/O space regs
+#define PMGX2_BASE (0x9E00)
+/* offset from PMGX2_BASE */
+#define P_CNT_OFS (0)
+#define P_LVL2_OFS (4)
+#define P_LVL3_OFS (8)
+
+// GLCP MSR offsets for clock throttling
+#define MCP_CNT (0x0018)
+ #define CNT_THEN (0x10L)
+ #define CNT_MASK (0x0FL)
+ #define CNT_MAX (0x01L)
+ #define CNT_NONE (0x0FL)
+#define MCP_LVL2 (0x0019)
+#define MCP_TH_SD (0x001C)
+ #define SD_MASK (0x0FFFL)
+ #define PLVL2_IN (0x1000L)
+#define MCP_TH_SF (0x001D)
+ #define SF_MASK (0x0FFL)
+#define MCP_TH_OD (0x001E)
+ #define OD_IRQ (0x8000L)
+ #define OD_SMI (0x4000L)
+ #define OD_MASK (0x3FFFL)
+
+
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/inc/hce.h b/cpu/amd/geode_lx/gplvsa_ii/inc/hce.h
new file mode 100755
index 0000000..e73a221
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/inc/hce.h
@@ -0,0 +1,97 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+typedef struct {
+ union {
+ unsigned long HceUlong;
+ unsigned short HceUshort;
+ struct {
+ unsigned short EmulationEnable: 1;
+ unsigned short EmulationInterrupt: 1;
+ unsigned short CharacterPending: 1;
+ unsigned short IRQEn: 1;
+ unsigned short ExternalIRQEn: 1;
+ unsigned short GateA20Sequence: 1;
+ unsigned short IRQ1Active: 1;
+ unsigned short IRQ12Active: 1;
+ unsigned short A20State: 1;
+ };
+ };
+} HCE_CONTROL;
+
+
+// Host Controller Operational Registers
+typedef struct {
+ unsigned long HcRevision;
+ unsigned long HcControl;
+ unsigned long HcCommandStatus;
+ unsigned long HcInterruptStatus;
+ unsigned long HcInterruptEnable;
+ unsigned long HcInterruptDisable;
+ unsigned long HcHCCA;
+ unsigned long HcPeriodCurrentED;
+ unsigned long HcControlHeadED;
+ unsigned long HcControlCurrentED;
+ unsigned long HcBulkHeadED;
+ unsigned long HcBulkCurrentED;
+ unsigned long HcDoneHead;
+ unsigned long HcFmInterval;
+ unsigned long HcFmRemaining;
+ unsigned long HcFmNumber;
+ unsigned long HcPeriodicStart;
+ unsigned long HcLSThreshold;
+ unsigned long HcRhDescriptorA;
+ unsigned long HcRhDescriptorB;
+ unsigned long HcRhStatus;
+ unsigned long HcRhPortStatus[2];
+
+ unsigned char Reserved[0x100-0x54-2*4]; // Reserved for use by HC
+ HCE_CONTROL HceControl; // 0x100
+ unsigned long HceInput; // 0x104
+ unsigned long HceOutput; // 0x108
+ unsigned long HceStatus; // 0x10C
+} HCOR;
+
+
+// HcInterruptStatus & HcInterruptDisable fields:
+#define SO 0x00000001L // Scheduling Overrun
+#define WDH 0x00000002L // HcDoneHead Writeback
+#define SF 0x00000004L // Start of Frame
+#define RD 0x00000008L // Resume Detect
+#define UE 0x00000010L // Unrecoverable Error
+#define FNO 0x00000020L // Frame Number Overflow
+#define RHSC 0x00000040L // Root Hub Status Change
+#define OC 0x40000000L // Ownership Change
+#define MIE 0x80000000L // Master Interrupt Enable
+
+
+// HceControl fields:
+#define EMULATION_ENABLE 0x01
+#define EMULATION_INTERRUPT 0x02
+#define CHARACTER_PENDING 0x04
+#define IRQ_ENABLE 0x08
+#define EXTERNAL_IRQ_ENABLE 0x10
+#define GATE_A20_SEQUENCE 0x20
+#define IRQ1_ACTIVE 0x40
+#define IRQ12_ACTIVE 0x80
+#define A20_STATE 0x100
+
+// HceStatus fields:
+#define CMD_DATA 0x08
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/inc/isa.h b/cpu/amd/geode_lx/gplvsa_ii/inc/isa.h
new file mode 100755
index 0000000..9ebad74
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/inc/isa.h
@@ -0,0 +1,183 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+// Real Time Clock (RTC) definitions
+#define CMOS_INDEX 0x70
+#define CMOS_DATA CMOS_INDEX+1
+#define CMOS_SECONDS 0x00
+#define CMOS_MINUTES 0x02
+#define CMOS_HOURS 0x04
+#define CMOS_DAY 0x07
+#define CMOS_MONTH 0x08
+#define CMOS_YEAR 0x09
+#define CMOS_STATUS_A 0x0A
+ #define UIP 0x80
+#define CMOS_STATUS_B 0x0B
+ #define SET 0x80
+ #define PI 0x40
+ #define AI 0x20
+ #define UI 0x10
+ #define SQUARE 0x08
+ #define DM 0x04
+ #define HOUR24 0x02
+ #define DLS 0x01
+#define CMOS_STATUS_C 0x0C
+ #define IRQ 0x80
+ #define PS 0x40
+ #define AS 0x20
+ #define US 0x10
+#define CMOS_CENTURY 0x32
+
+
+
+// Programmable Interrupt Controller (PIC) definitions
+#define PIC1_BASE 0x20
+#define PIC1_MASK PIC1_BASE+1
+#define PIC2_BASE 0xA0
+#define PIC2_MASK PIC2_BASE+1
+#define NONSPECIFIC_EOI 0x20
+#define SPECIFIC_EOI 0x60
+#define PIC1_EDGE 0x4D0
+#define PIC2_EDGE 0x4D1
+
+
+
+
+#define PIC1_ICW1 0x20
+#define PIC1_ICW2 0x21
+#define PIC1_ICW3 0x21
+#define PIC1_ICW4 0x21
+#define PIC1_OCW1 0x21
+#define PIC1_OCW2 0x20
+#define PIC1_OCW3 0x20
+#define PIC2_ICW1 0xA0
+#define PIC2_ICW2 0xA1
+#define PIC2_ICW3 0xA1
+#define PIC2_ICW4 0xA1
+#define PIC2_OCW1 0xA1
+#define PIC2_OCW2 0xA0
+#define PIC2_OCW3 0xA0
+
+
+// DMA definitions
+#define TRANSFER_MASK (0x0C)
+ #define DMA_VERIFY (0x00)
+ #define DMA_WRITE (0x04)
+ #define DMA_READ (0x08)
+#define MODE_MASK (0xC0)
+ #define MODE_DEMAND (0x00)
+ #define MODE_SINGLE (0x40)
+ #define MODE_BLOCK (0x80)
+ #define MODE_CASCADE (0xC0)
+
+#define DMA1_ADDR0 0x00
+#define DMA1_CNT0 0x01
+#define DMA1_ADDR1 0x02
+#define DMA1_CNT1 0x03
+#define DMA1_ADDR2 0x04
+#define DMA1_CNT2 0x05
+#define DMA1_ADDR3 0x06
+#define DMA1_CNT3 0x07
+#define DMA1_MODE 0x0B
+#define DMA1_CPTR 0x0C
+#define DMA1_MASK 0x0F
+#define DMA2_ADDR0 0xC0
+#define DMA2_CNT0 0xC2
+#define DMA2_ADDR1 0xC4
+#define DMA2_CNT1 0xC6
+#define DMA2_ADDR2 0xC8
+#define DMA2_CNT2 0xCA
+#define DMA2_ADDR3 0xCC
+#define DMA2_CNT3 0xCE
+#define DMA2_MODE 0xD6
+#define DMA2_CPTR 0xD8
+#define DMA2_MASK 0xDE
+#define DMA_PAGE 0x80
+#define DMA_HPAGE 0x480
+
+
+
+// Programmable Interval Timer (PIT) definitions
+#define PIT_CTR0 0x40
+#define PIT_CTR1 0x41
+#define PIT_CTR2 0x42
+#define PIT_CMD 0x43
+#define PIT_CMD_BOTH_BYTES 0x30 // Sets CMD word to read/write both bytes
+
+
+
+
+
+#define READ_IRR 0x0A
+#define READ_ISR 0x0B
+
+// Keyboard controller registers
+#define KYBD_DATA 0x60
+#define KYBD_STATUS 0x64
+ #define STAT_OBF 0x01
+ #define STAT_IBF 0x02
+ #define STAT_FLAG 0x04
+ #define STAT_CMD 0x08
+ #define STAT_INHIBIT 0x10
+ #define STAT_AUX_OBF 0x20
+ #define STAT_TIMEOUT 0x40
+ #define STAT_PARITY 0x80
+#define KYBD_COMMAND 0x64
+
+// Keyboard controller output port bits
+#define KYBD_SYSR 0x01 // Processor reset
+#define KYBD_GA20 0x02 // Gate A20 (1=on)
+#define KYBD_ADAT 0x04 // AUX data
+#define KYBD_ACLK 0x08 // AUX clock
+#define KYBD_KOBF 0x10 // Keyboard OBF
+#define KYBD_AOBF 0x20 // AUX OBF
+#define KYBD_KCLK 0x40 // Keyboard clock
+#define KYBD_KDAT 0x80 // Keyboard data
+
+// Keyboard controller commands
+#define KYBD_RD_OUT 0xD0
+#define KYBD_WR_OUT 0xD1
+
+// Keyboard controller command byte
+#define OBF_INTERRUPT 0x01
+#define AUX_INTERRUPT 0x02
+#define SYSTEM_STATUS 0x04
+#define KBD_DISABLED 0x10
+#define AUX_DISABLED 0x20
+#define XT_SCANSET 0x40
+
+
+#define PORT_B 0x92
+#define GAMEPORT 0x200
+#define PRIMARY_IDE 0x1F6
+#define SECONDARY_IDE 0x176
+#define PRIMARY_FLOPPY 0x3F5
+#define SECONDARY_FLOPPY 0x375
+
+#define COM1 0x3F8
+#define COM2 0x2F8
+#define COM3 0x3E8
+#define COM4 0x2E8
+
+#define LPT1 0x378
+#define LPT2 0x278
+
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/inc/pci.h b/cpu/amd/geode_lx/gplvsa_ii/inc/pci.h
new file mode 100755
index 0000000..f2a5c1f
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/inc/pci.h
@@ -0,0 +1,111 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+// PCI related definitions
+#define PCI_CONFIG_ADDRESS 0xCF8
+#define PCI_CONFIG_DATA 0xCFC
+
+#define VENDOR_ID 0x00
+#define COMMAND 0x04
+ #define IO_SPACE (1 << 0)
+ #define MEM_SPACE (1 << 1)
+ #define BUS_MASTER (1 << 2)
+ #define SPECIAL_CYCLES (1 << 3)
+ #define MEM_WR_INVALIDATE (1 << 4)
+ #define VGA_PALETTE_SNOOP (1 << 5)
+ #define PARITY_RESPONSE (1 << 6)
+ #define WAIT_CYCLE_CONTROL (1 << 7)
+ #define SERR_ENABLE (1 << 8)
+ #define FAST_BACK_TO_BACK (1 << 9)
+
+#define STATUS 0x06
+ #define CAPABILITIES_LIST (1L << 20)
+ #define PCI_66MHZ_CAPABLE (1L << 21)
+ #define BACK2BACK_CAPABLE (1L << 23)
+ #define MASTER_PARITY_ERROR (1L << 24)
+ #define DEVSEL_FAST (0L << 25)
+ #define DEVSEL_MEDIUM (1L << 25)
+ #define DEVSEL_SLOW (2L << 25)
+ #define SIGNALED_TARGET_ABORT (1L << 27)
+ #define RECEIVED_TARGET_ABORT (1L << 28)
+ #define RECEIVED_MASTER_ABORT (1L << 29)
+ #define SIGNALED_SYSTEM_ERROR (1L << 30)
+ #define DETECTED_PARITY_ERROR (1L << 31)
+
+
+
+#define REVISION_ID 0x08
+#define CACHE_LINE 0x0C
+#define LATENCY_TIMER 0x0D
+#define HEADER_TYPE 0x0E
+#define BIST 0x0F
+
+
+// Capability List IDs
+#define CAP_ID_PM 0x01
+#define CAP_ID_AGP 0x02
+#define CAP_ID_VPD 0x03
+#define CAP_ID_SLOT 0x04
+#define CAP_ID_MSI 0x05
+#define CAP_ID_HOT_SWAP 0x06
+
+
+#define SUBSYSTEM_VENDOR_ID 0x2C
+
+#define INTERRUPT_LINE 0x3C
+#define INTERRUPT_PIN 0x3D
+#define MIN_GNT 0x3E
+#define MAX_LAT 0x3F
+
+
+#define BAR0 0x10
+#define BAR1 0x14
+#define BAR2 0x18
+#define BAR3 0x1C
+#define BAR4 0x20
+#define BAR5 0x24
+
+// PCI Power Management:
+#define PCI_PM_REG 0x40
+
+// Graphics-specific registers:
+#define OEM_BAR0 0x50
+#define OEM_BAR1 0x54
+#define OEM_BAR2 0x58
+#define OEM_BAR3 0x5C
+
+// EHCI-specific registers
+#define EECP 0x50
+#define USBLEGSUP (EECP)
+ #define OS_OWNED_SEMAPHORE 0x01000000
+ #define BIOS_OWNED_SEMAPHORE 0x00010000
+#define USBLEGCTLSTS (EECP+4)
+ #define SMI_ON_BAR 0x80000000
+ #define SMI_ON_COMMAND 0x40000000
+ #define SMI_ON_OC 0x20000000
+
+#define SRBN_REG 0x60
+
+// 5536 B0 ATA-specific registers:
+#define IDE_CFG 0x40
+#define IDE_DTC 0x48
+#define IDE_CAST 0x4C
+#define IDE_ETC 0x50
+#define IDE_PM 0x54
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/inc/vr.h b/cpu/amd/geode_lx/gplvsa_ii/inc/vr.h
new file mode 100755
index 0000000..965efbe
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/inc/vr.h
@@ -0,0 +1,485 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+#define VRC_INDEX 0xAC1C // Index register
+#define VRC_DATA 0xAC1E // Data register
+#define VR_UNLOCK 0xFC53 // Virtual register unlock code
+#define NO_VR -1 // No virtual registers
+
+#define VRC_MISCELLANEOUS 0x00 // Miscellaneous Class
+ #define VSA_VERSION_NUM 0x00
+ #define HIGH_MEM_ACCESS 0x01
+ #define GET_VSM_INFO 0x02 // Used by INFO
+ #define GET_BASICS 0x00
+ #define GET_EVENT 0x01
+ #define GET_STATISTICS 0x02
+ #define GET_HISTORY 0x03
+ #define GET_HARDWARE 0x04
+ #define GET_ERROR 0x05
+ #define SET_VSM_TYPE 0x06
+ #define SIGNATURE 0x03
+ #define VSA2_SIGNATURE 0x56534132 // 'VSA2' returned in EAX
+
+ #define GET_HW_INFO 0x04
+ #define VSM_VERSION 0x05
+ #define CTRL_ALT_DEL 0x06
+ #define MSR_ACCESS 0x07
+ #define GET_DESCR_INFO 0x08
+ #define PCI_INT_AB 0x09 // GPIO pins for INTA# and INTB#
+ #define PCI_INT_CD 0x0A // GPIO pins for INTC# and INTD#
+ #define WATCHDOG 0x0B // Watchdog timer
+
+ #define MAX_MISC WATCHDOG
+
+
+// NOTE: Do not change the order of the following registers:
+#define VRC_AUDIO 0x01 // XpressAudio Class
+ #define AUDIO_VERSION 0x00
+ #define PM_STATE 0x01
+ #define SB_16_IO_BASE 0x02
+ #define MIDI_BASE 0x03
+ #define CPU_USAGE 0x04
+ #define CODEC_TYPE 0x05
+ #define STATE_INDEX 0x06
+ #define STATE_DATA 0x07
+ #define AUDIO_IRQ 0x08 // For use by native audio drivers
+ #define STATUS_PTR 0x09 // For use by native audio drivers
+ #define MAX_AUDIO STATUS_PTR
+
+#define VRC_VG 0x02 // SoftVG Class
+#define VRC_VGA 0x02 // SoftVGA Class
+ #define VG_MEM_SIZE 0x00 // bits 7:0 - 512K unit size, bit 8 controller priority
+ #define VG_CONFIG 0x00 // Main configuration register
+ #define VG_CFG_BYPASS 0x0001 // DOTPLL bypass bit
+ #define VG_MEM_MASK 0x00FE // Memory size mask bits, 2MB increment
+ #define VG_CFG_DSMASK 0x0700 // Active display mask bits
+ #define VG_CFG_DSCRT 0x0000 // Active display is CRT
+ #define VG_CFG_DSPAN 0x0100 // Active display is panel
+ #define VG_CFG_DSTV 0x0200 // Active display is TV
+ #define VG_CFG_DSSIM 0x0400 // Simultaneous CRT
+ #define VG_CFG_PRIORITY 0x0800 // Controller priority bit
+ #define VG_CFG_MONO 0x1000 // External monochrome card support bit
+ #define VG_CFG_DRIVER 0x2000 // Driver active bit
+ #define VG_CRTC_DIAG 0x8000 // Enable CRTC emulation
+
+ // Defined for LX/LXVG
+ #define VG_REFRESH 0x01 // Mode refresh, a mode switch without changing modes
+ #define VG_FRSH_REF_MASK 0xE000 // Refresh rate mask
+ #define VG_FRSH_REF_GO 0x1000 // Refresh rate GO bit
+ // Uses CFP_REF_xxx values from below
+ #define VG_FRSH_BPP_MASK 0x0E00 // Color depth mask
+ #define VG_FRSH_BPP_GO 0x0100 // Color depth GO bit
+ #define FRSH_BPP_8RGB 0x0200 // 8 bits per pixel, RGB
+ #define FRSH_BPP_16ARGB 0x0400 // 16BPP, ARGB (4:4:4:4)
+ #define FRSH_BPP_15RGB 0x0600 // 15BPP, RGB (1:5:5:5)
+ #define FRSH_BPP_16RGB 0x0800 // 16BPP, RGB (5:6:5)
+ #define FRSH_BPP_24RGB 0x0A00 // 24BPP, RGB (0:8:8:8)
+ #define FRSH_BPP_32ARGB 0x0C00 // 32BPP, ARGB (8:8:8:8)
+ #define VG_CFG_DPMS 0x00C0 // DPMS mask bits
+ #define VG_CFG_DPMS_H 0x0040 // HSYNC mask bit
+ #define VG_CFG_DPMS_V 0x0080 // VSYNC mask bit
+ #define VG_VESA_SV_RST 0x0020 // VESA Save/Restore state flag
+ #define VG_VESA_RST 0x0000 // VESA Restore state
+ #define VG_VESA_SV 0x0020 // VESA Save state
+ #define VG_FRSH_MODE 0x0002 // Mode refresh flag
+ #define VG_FRSH_TIMINGS 0x0001 // Timings only refresh flag
+
+ // Defined for GX2/SoftVG
+ #define VG_PLL_REF 0x01 // PLL reference frequency selection register
+ #define PLL_14MHZ 0x0000 // 14.31818MHz PLL reference frequency (Default)
+ #define PLL_48MHZ 0x0100 // 48MHz PLL reference frequency
+
+ // Defined for GX1/SoftVGA
+ #define VGA_MEM_SIZE 0x01 // bits 7:1 - 128K unit size, bit 0 controller enable
+
+ #define VG_FP_TYPE 0x02 // Flat panel type data
+ // VG_FP_TYPE definitions for GX2/SoftVG
+ #define FP_TYPE_SSTN 0x0000 // SSTN panel type value
+ #define FP_TYPE_DSTN 0x0001 // DSTN panel type value
+ #define FP_TYPE_TFT 0x0002 // TFT panel type value
+ #define FP_TYPE_LVDS 0x0003 // LVDS panel type value
+ #define FP_RES_6X4 0x0000 // 640x480 resolution value
+ #define FP_RES_8X6 0x0008 // 800x600 resolution value
+ #define FP_RES_10X7 0x0010 // 1024x768 resolution value
+ #define FP_RES_11X8 0x0018 // 1152x864 resolution value
+ #define FP_RES_12X10 0x0020 // 1280x1024 resolution value
+ #define FP_RES_16X12 0x0028 // 1600x1200 resolution value
+ #define FP_WIDTH_8 0x0000 // 8 bit data bus width
+ #define FP_WIDTH_9 0x0040 // 9 bit data bus width
+ #define FP_WIDTH_12 0x0080 // 12 bit data bus width
+ #define FP_WIDTH_18 0x00C0 // 18 bit data bus width
+ #define FP_WIDTH_24 0x0100 // 24 bit data bus width
+ #define FP_WIDTH_16 0x0140 // 16 bit data bus width - 16 bit Mono DSTN only
+ #define FP_COLOR_COLOR 0x0000 // Color panel
+ #define FP_COLOR_MONO 0x0200 // Mono Panel
+ #define FP_PPC_1PPC 0x0000 // One pixel per clock
+ #define FP_PPC_2PPC 0x0400 // Two pixels per clock
+ #define FP_H_POL_LGH 0x0000 // HSync at panel, normally low, active high
+ #define FP_H_POL_HGL 0x0800 // HSync at panel, normally high, active low
+ #define FP_V_POL_LGH 0x0000 // VSync at panel, normally low, active high
+ #define FP_V_POL_HGL 0x1000 // VSync at panel, normally high, active low
+ #define FP_REF_60 0x0000 // 60Hz refresh rate
+ #define FP_REF_65 0x2000 // 65Hz refresh rate
+ #define FP_REF_70 0x4000 // 70Hz refresh rate
+ #define FP_REF_72 0x6000 // 72Hz refresh rate
+ #define FP_REF_75 0x8000 // 75Hz refresh rate
+ #define FP_REF_85 0xA000 // 85Hz refresh rate
+
+ // VG_FP_TYPE definitions for LX/LXVG
+ #define FP_TYPE_TYPE 0x0003 // Flat panel type bits mask
+ #define CFP_TYPE_TFT 0x0000 // TFT panel type value
+ #define CFP_TYPE_LVDS 0x0001 // LVDS panel type value
+ #define FP_TYPE_RES 0x0038 // Panel resolution bits mask
+ #define CFP_RES_3X2 0x0000 // 320x240 resolution value
+ #define CFP_RES_6X4 0x0008 // 640x480 resolution value
+ #define CFP_RES_8X6 0x0010 // 800x600 resolution value
+ #define CFP_RES_10X7 0x0018 // 1024x768 resolution value
+ #define CFP_RES_11X8 0x0020 // 1152x864 resolution value
+ #define CFP_RES_12X10 0x0028 // 1280x1024 resolution value
+ #define CFP_RES_16X12 0x0030 // 1600x1200 resolution value
+ #define FP_TYPE_BUS 0x00C0 // Data bus width and pixels/clock mask
+ #define CFP_BUS_1PPC 0x0040 // 9, 12, 18 or 24 bit data bus, 1 pixel per clock
+ #define CFP_BUS_2PPC 0x0080 // 18 or 24 bit data bus, 2 pixels per clock
+ #define FP_TYPE_HPOL 0x0800 // HSYNC polarity into the panel
+ #define CFP_HPOL_HGL 0x0000 // HSync at panel, normally high, active low
+ #define CFP_HPOL_LGH 0x0800 // HSync at panel, normally low, active high
+ #define FP_TYPE_VPOL 0x1000 // VSYNC polarity into the panel
+ #define CFP_VPOL_HGL 0x0000 // VSync at panel, normally high, active low
+ #define CFP_VPOL_LGH 0x1000 // VSync at panel, normally low, active high
+ #define FP_TYPE_REF 0xE000 // Panel refresh rate
+ #define CFP_REF_60 0x0000 // 60Hz refresh rate
+ #define CFP_REF_70 0x2000 // 70Hz refresh rate
+ #define CFP_REF_75 0x4000 // 75Hz refresh rate
+ #define CFP_REF_85 0x6000 // 85Hz refresh rate
+ #define CFP_REF_100 0x8000 // 100Hz refresh rate
+
+ #define VG_FP_OPTION 0x03 // Flat panel option data
+ #define FP_OPT_SCLK_NORMAL 0x0000 // SHFTClk not inverted to panel
+ #define FP_OPT_SCLK_INVERTED 0x0010 // SHFTClk inverted to panel
+ #define FP_OPT_SCLK_ACT_ACTIVE 0x0000 // SHFTClk active during "active" only
+ #define FP_OPT_SCLK_ACT_FREE 0x0020 // SHFTClk free-running
+ #define FP_OPT_LP_ACT_FREE 0x0000 // LP free-running
+ #define FP_OPT_LP_ACT_ACTIVE 0x0040 // LP active during "active" only
+ #define FP_OPT_LDE_POL_LGH 0x0000 // LDE/MOD, normally low, active high
+ #define FP_OPT_LDE_POL_HGL 0x0080 // LDE/MOD, normally high, active low
+ #define FP_OPT_PWR_DLY_32MS 0x0000 // 32MS delay for each step of pwr seq.
+ #define FP_OPT_PWR_DLY_128MS 0x0100 // 128MS delay for each step of pwr seq.
+
+ #define VG_TV_CONFIG 0x04 // TV configuration register
+ #define VG_TV_ENC 0x000F // TV encoder select mask
+ #define VG_TV_ADV7171 0x0000 // ADV7171 Encoder
+ #define VG_TV_SAA7127 0x0001 // ADV7171 Encoder
+ #define VG_TV_ADV7300 0x0002 // ADV7300 Encoder
+ #define VG_TV_FS454 0x0003 // FS454 Encoder
+ #define VG_TV_FMT 0x0070 // TV encoder output format mask
+ #define VG_TV_FMT_SHIFT 0x0004 // Right shift value
+ #define VG_TV_NTSC 0x0000 // NTSC output format
+ #define VG_TV_PAL 0x0010 // PAL output format
+ #define VG_TV_HDTV 0x0020 // HDTV output format
+
+ // The meaning of the VG_TV_RES field is dependent on the selected
+ // encoder and output format. The translations are:
+ // ADV7171 - Not Used
+ // SAA7127 - Not Used
+ // ADV7300 - HDTV resolutions only
+ // LO -> 720x480p
+ // MED -> 1280x720p
+ // HI -> 1920x1080i
+ // FS454 - Both SD and HD resolutions
+ // SD Resolutions - NTSC and PAL
+ // LO -> 640x480
+ // MED -> 800x600
+ // HI -> 1024x768
+ // HD Resolutions
+ // LO -> 720x480p
+ // MED -> 1280x720p
+ // HI -> 1920x1080i
+ #define VG_TV_RES 0x0780 // TV resolution select mask
+ #define VG_TV_RES_SHIFT 0x0007 // Right shift value
+ #define VG_TV_RES_LO 0x0000 // Low resolution
+ #define VG_TV_RES_MED 0x0080 // Medium resolution
+ #define VG_TV_RES_HI 0x0100 // High resolution
+ #define VG_TV_PASSTHRU 0x0800 // TV passthru mode
+
+ #define VG_TV_SCALE_ADJ 0x05 // Modifies scaling factors for TV resolutions
+ #define VG_TV_HACT_ADJ 0x00FF // Horizontal active scale adjust value mask
+ #define VG_TV_VACT_ADJ 0xFF00 // Vertical active scale adjust value mask
+
+ #define VG_DEBUG 0x0F // A debug register
+
+ #define VG_FT_HTOT 0x10 // Fixed timings, horizontal total
+ #define VG_FT_HACT 0x11 // Fixed timings, horizontal active
+ #define VG_FT_HBST 0x12 // Fixed timings, horizontal blank start
+ #define VG_FT_HBND 0x13 // Fixed timings, horizontal blank end
+ #define VG_FT_HSST 0x14 // Fixed timings, horizontal sync start
+ #define VG_FT_HSND 0x15 // Fixed timings, horizontal sync end
+
+ #define VG_FT_VTOT 0x16 // Fixed timings, vertical total
+ #define VG_FT_VACT 0x17 // Fixed timings, vertical active
+ #define VG_FT_VBST 0x18 // Fixed timings, vertical blank start
+ #define VG_FT_VBND 0x19 // Fixed timings, vertical blank end
+ #define VG_FT_VSST 0x1A // Fixed timings, vertical sync start
+ #define VG_FT_VSND 0x1B // Fixed timings, vertical sync end
+
+ #define VG_START_OFFS_LO 0x20 // Framebuffer start offset bits 15:0
+ #define VG_START_OFFS_HI 0x21 // Framebuffer start offset bits 27:16
+
+ #define VG_FT_VEACT 0x28 // Fixed timings, vertical active
+ #define VG_FT_VETOT 0x29 // Fixed timings, vertical total
+ #define VG_FT_VEBST 0x2A // Fixed timings, vertical blank start
+ #define VG_FT_VEBND 0x2B // Fixed timings, vertical blank end
+ #define VG_FT_VESST 0x2C // Fixed timings, vertical sync start
+ #define VG_FT_VESND 0x2D // Fixed timings, vertical sync end
+
+ #define MAX_VGA VGA_MEM_SIZE
+// #define MAX_VG VG_FP_OPTION
+// #define MAX_VG VG_START_OFFS_HI
+ #define MAX_VG VG_FT_VESND
+
+#define VRC_APM 0x03
+ #define REPORT_EVENT 0x00
+ #define CAPABILITIES 0x01
+ #define APM_PRESENT 0x02
+ #define MAX_APM APM_PRESENT
+
+
+#define VRC_PM 0x04 // Legacy PM Class
+ #define POWER_MODE 0x00
+ #define POWER_STATE 0x01
+ #define DOZE_TIMEOUT 0x02
+ #define STANDBY_TIMEOUT 0x03
+ #define SUSPEND_TIMEOUT 0x04
+ #define PS2_TIMEOUT 0x05
+ #define RESUME_ON_RING 0x06
+ #define VIDEO_TIMEOUT 0x07
+ #define DISK_TIMEOUT 0x08
+ #define FLOPPY_TIMEOUT 0x09
+ #define SERIAL_TIMEOUT 0x0A
+ #define PARALLEL_TIMEOUT 0x0B
+ #define IRQ_WAKEUP_MASK 0x0C
+// #define SUSPEND_MODULATION 0x0D
+ #define SLEEP_PIN 0x0E
+ #define SLEEP_PIN_ATTR 0x0F
+// #define SMI_WAKEUP_MASK 0x10
+ #define INACTIVITY_CONTROL 0x11
+ #define PM_S1_CLOCKS 0x12
+ #define S1_CLOCKS_ON 0x00
+ #define S1_CLOCKS_OFF 0x01
+// #define PM_S2_CLOCKS 0x13
+// #define PM_S3_CLOCKS 0x14
+// #define PM_S4_CLOCKS 0x15
+// #define PM_S5_CLOCKS 0x16
+ #define PM_S0_LED 0x17
+ #define PM_S1_LED 0x18
+ #define PM_S2_LED 0x19
+ #define PM_S3_LED 0x1A
+ #define PM_S4_LED 0x1B
+ #define PM_S5_LED 0x1C
+ #define PM_LED_GPIO 0x1D
+ #define PM_IMM_LED 0x1E
+ #define PM_PWR_LEDS 0x1F
+ #define MB_LED0 0x01
+ #define MB_LED1 0x02
+ #define MB_LED2 0x04
+ #define MB_LED3 0x08
+ #define SIO_LED0 0x10
+ #define SIO_LED1 0x20
+ #define SIO_LED2 0x40
+ #define SIO_LED3 0x80
+ #define PM_PME_MASK 0x20
+ #define MAX_PM PM_PME_MASK
+
+#define VRC_INFRARED 0x05
+ #define MAX_INFRARED NO_VR
+
+#define VRC_TV 0x06 // TV Encoder Class
+ #define TV_ENCODER_TYPE 0x00
+ #define TV_CALLBACK_MASK 0x01
+ #define TV_MODE 0x02
+ #define TV_POSITION 0x03
+ #define TV_BRIGHTNESS 0x04
+ #define TV_CONTRAST 0x05
+ #define TV_OUTPUT 0x06
+ #define TV_TIMING 0x10 // 0x10...0x1D are all timings
+ #define MAX_TV TV_TIMING
+
+
+
+#define VRC_EXTERNAL_AMP 0x07
+ #define EAPD_VERSION 0x00
+ #define AMP_POWER 0x01
+ #define AMP_OFF 0x00
+ #define AMP_ON 0x01
+ #define AMP_TYPE 0x02
+ #define MAX_EXTERNAL_AMP AMP_TYPE
+
+
+#define VRC_ACPI 0x08
+ #define ENABLE_ACPI 0x00 // Enable ACPI Mode
+ #define SCI_IRQ 0x01 // Set the IRQ the SCI is mapped to, sysbios use.
+ #define ACPINVS_LO 0x02 // new calls to send 32bit physAddress of
+ #define ACPINVS_HI 0x03 // ACPI NVS region to VSA
+ #define GLOBAL_LOCK 0x04 // read requests semaphore, write clears
+ #define ACPI_UNUSED1 0x05
+ #define RW_PIRQ 0x06 // read/write PCI IRQ router regs in SB Func0 cfg space
+ #define SLPB_CLEAR 0x07 // clear sleep button GPIO status's
+ #define PIRQ_ROUTING 0x08 // read the PCI IRQ routing based on BIOS setup
+ #define ACPI_UNUSED2 0x09
+ #define ACPI_UNUSED3 0x0A
+ #define PIC_INTERRUPT 0x0B
+ #define ACPI_PRESENT 0x0C
+ #define ACPI_GEN_COMMAND 0x0D
+ #define ACPI_GEN_PARAM1 0x0E
+ #define ACPI_GEN_PARAM2 0x0F
+ #define ACPI_GEN_PARAM3 0x10
+ #define ACPI_GEN_RETVAL 0x11
+ #define MAX_ACPI ACPI_GEN_RETVAL
+
+#define VRC_ACPI_OEM 0x09
+ #define MAX_ACPI_OEM NO_VR
+
+#define VRC_POWER 0x0A
+ #define BATTERY_UNITS 0x00 // No. battery units
+ #define BATTERY_SELECT 0x01
+ #define AC_STATUS 0x02
+ #define BATTERY_STATUS 0x03
+ #define BATTERY_FLAG 0x04
+ #define BATTERY_PERCENTAGE 0x05
+ #define BATTERY_TIME 0x06
+ #define MAX_POWER BATTERY_TIME
+
+
+
+#define VRC_OHCI 0x0B // OHCI Class
+ #define SET_LED 0x00
+ #define INIT_OHCI 0x01
+ #define MAX_OHCI INIT_OHCI
+
+#define VRC_KEYBOARD 0x0C // Kbd Controller Class
+ #define KEYBOARD_PRESENT 0x00
+ #define SCANCODE 0x01
+ #define MOUSE_PRESENT 0x02
+ #define MOUSE_BUTTONS 0x03
+ #define MOUSE_XY 0x04
+ #define TYPEMATIC_DISABLE 0x05
+ #define MAX_KEYBOARD TYPEMATIC_DISABLE
+
+
+#define VRC_DDC 0x0D // Video DDC Class
+ #define VRC_DDC_ENABLE 0x00 // Enable/disable register
+ #define DDC_DISABLE 0x00
+ #define DDC_ENABLE 0x01
+ #define VRC_DDC_IO 0x01 // A non-zero value for safety
+ #define MAX_DDC VRC_DDC_IO
+
+#define VRC_DEBUGGER 0x0E
+ #define MAX_DEBUGGER NO_VR
+
+
+#define VRC_STR 0x0F // Virtual Register class
+ #define RESTORE_ADDR 0x00 // Physical address of MSR restore table
+
+
+#define VRC_COP8 0x10 // Virtual Register class
+ #define VRC_HIB_ENABLE 0x00 // HIB enable/disable index
+ #define HIB_ENABLE 0x00 // HIB enable command
+ #define HIB_DISABLE 0x01 // HIB disable command
+ #define VRC_HIB_SEND 0x01 // Send packet to COP8
+ #define VRC_HIB_READUART 0x02 // Read byte from COP8 UART
+ #define VRC_HIB_VERSION 0x03 // Read COP8 version
+ #define VRC_HIB_SERIAL 0x04 // Read 8 byte serial number
+ #define VRC_HIB_USRBTN 0x05 // Read POST button pressed status
+ #define MAX_COP8 NO_VR
+
+#define VRC_OWL 0x11 // Virtual Register class
+ #define VRC_OWL_DAC 0x00 // DAC (Backlight) Control
+ #define VRC_OWL_GPIO 0x01 // GPIO Control
+ #define MAX_OWL VRC_OWL_GPIO
+
+#define VRC_SYSINFO 0x12 // Virtual Register class
+ #define VRC_SI_VERSION 0x00 // Sysinfo VSM version
+ #define VRC_SI_CPU_MHZ 0x01 // CPU speed in MHZ
+ #define VRC_SI_CHIPSET_BASE_LOW 0x02
+ #define VRC_SI_CHIPSET_BASE_HI 0x03
+ #define VRC_SI_CHIPSET_ID 0x04
+ #define VRC_SI_CHIPSET_REV 0x05
+ #define VRC_SI_CPU_ID 0x06
+ #define VRC_SI_CPU_REV 0x07
+ #define MAX_SYSINFO VRC_SI_CPU_REV
+
+#define VRC_SUPERIO 0x13
+ #define VRC_SIO_CHIPID 0x00
+ #define VRC_SIO_NUMLD 0x01
+ #define VRC_SIO_FDCEN 0x02
+ #define VRC_SIO_FDCIO 0x03
+ #define VRC_SIO_FDCIRQ 0x04
+ #define VRC_SIO_FDCDMA 0x05
+ #define VRC_SIO_FDCCFG1 0x06
+ #define VRC_SIO_FDCCFG2 0x07
+ #define VRC_SIO_PP1EN 0x08
+ #define VRC_SIO_PP1IO 0x09
+ #define VRC_SIO_PP1IRQ 0x0A
+ #define VRC_SIO_PP1DMA 0x0B
+ #define VRC_SIO_PP1CFG1 0x0C
+ #define VRC_SIO_SP1EN 0x0D
+ #define VRC_SIO_SP1IO 0x0E
+ #define VRC_SIO_SP1IRQ 0x0F
+ #define VRC_SIO_SP1CFG1 0x10
+ #define VRC_SIO_SP2EN 0x11
+ #define VRC_SIO_SP2IO 0x12
+ #define VRC_SIO_SP2IRQ 0x13
+ #define VRC_SIO_SP2CFG1 0x14
+ #define VRC_SIO_KBEN 0x15
+ #define VRC_SIO_KBIO1 0x16
+ #define VRC_SIO_KBIO2 0x17
+ #define VRC_SIO_KBIRQ 0x18
+ #define VRC_SIO_KBCFG1 0x19
+ #define VRC_SIO_MSEN 0x1A
+ #define VRC_SIO_MSIO 0x1B
+ #define VRC_SIO_MSIRQ 0x1C
+ #define VRC_SIO_RTCEN 0x1D
+ #define VRC_SIO_RTCIO1 0x1E
+ #define VRC_SIO_RTCIO2 0x1F
+ #define VRC_SIO_RTCIRQ 0x20
+ #define VRC_SIO_RTCCFG1 0x21
+ #define VRC_SIO_RTCCFG2 0x22
+ #define VRC_SIO_RTCCFG3 0x23
+ #define VRC_SIO_RTCCFG4 0x24
+ #define MAX_SUPERIO VRC_SIO_RTCCFG4
+
+#define VRC_CHIPSET 0x14
+ #define VRC_CS_PWRBTN 0x00
+ #define VRC_CS_UART1 0x01
+ #define VRC_CS_UART2 0x02
+ #define MAX_CHIPSET VRC_CS_UART2
+
+#define VRC_THERMAL 0x15
+ #define VRC_THERMAL_CURR_RTEMP 0x00 // read only
+ #define VRC_THERMAL_CURR_LTEMP 0x01 // read only
+ #define VRC_THERMAL_FAN 0x02
+ #define VRC_THERMAL_LOW_THRESHOLD 0x03
+ #define VRC_THERMAL_HIGH_THRESHOLD 0x04
+ #define VRC_THERMAL_INDEX 0x05
+ #define VRC_THERMAL_DATA 0x06
+ #define VRC_THERMAL_SMB_ADDRESS 0x07
+ #define VRC_THERMAL_SMB_INDEX 0x08
+ #define VRC_THERMAL_SMB_DATA 0x09
+ #define MAX_THERMAL VRC_THERMAL_SMB_DATA
+
+#define MAX_VR_CLASS VRC_THERMAL
diff --git a/cpu/amd/geode_lx/gplvsa_ii/inc/vsa2.h b/cpu/amd/geode_lx/gplvsa_ii/inc/vsa2.h
new file mode 100755
index 0000000..79299d4
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/inc/vsa2.h
@@ -0,0 +1,700 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+#define VSM_SIGNATURE 0x204D5356 // 'VSM '
+#define VSA_VERSION 0x03B0 // SysMgr Version
+
+
+#define BYTE_IO 0x01
+#define WORD_IO 0x03
+#define DWORD_IO 0x0F
+#define IO_WRITE 0x80
+
+
+
+typedef unsigned char UCHAR;
+typedef unsigned long ULONG;
+typedef unsigned short USHORT;
+
+
+
+#define HIWORD(p) ((USHORT) ((p) >> 16))
+
+typedef struct {
+ unsigned short Alignment: 5; // 2^(n+5) (e.g. 00000 = 32-byte boundary)
+ unsigned short LoadHi: 1; // 1 = must load VSM above top of memory
+ unsigned short LoadLo: 1; // 1 = must load VSM below 1 MB
+ unsigned short SkipMe: 1; // 1 = Skip this VSM
+ unsigned short Reserved: 8;
+} Requirements;
+
+
+
+
+
+
+//*********************************************************************
+// Structures
+//*********************************************************************
+
+typedef struct {
+ union {
+ ULONG Reg_EAX;
+ USHORT Reg_AX;
+ struct {
+ UCHAR Reg_AL;
+ UCHAR Reg_AH;
+ };
+ };
+ union {
+ ULONG Reg_EBX;
+ USHORT Reg_BX;
+ struct {
+ UCHAR Reg_BL;
+ UCHAR Reg_BH;
+ };
+ };
+ union {
+ ULONG Reg_ECX;
+ USHORT Reg_CX;
+ struct {
+ UCHAR Reg_CL;
+ UCHAR Reg_CH;
+ };
+ };
+ union {
+ ULONG Reg_EDX;
+ USHORT Reg_DX;
+ struct {
+ UCHAR Reg_DL;
+ UCHAR Reg_DH;
+ };
+ };
+ union {
+ ULONG Reg_EBP;
+ USHORT Reg_BP;
+ };
+ union {
+ ULONG Reg_ESI;
+ USHORT Reg_SI;
+ };
+ union {
+ ULONG Reg_EDI;
+ USHORT Reg_DI;
+ };
+ USHORT Reg_DS;
+ USHORT Reg_ES;
+ USHORT Flags;
+ UCHAR PIC0_Mask;
+ UCHAR PIC1_Mask;
+} INT_REGS;
+
+
+
+typedef struct { // Used by SVDC & RSDC instructions
+ USHORT limit_15_0;
+ USHORT base_15_0;
+ UCHAR base_23_16;
+ UCHAR attr;
+#define G_BIT 0x80
+#define D_BIT 0x40
+
+ UCHAR limit_19_16;
+ UCHAR base_31_24;
+ USHORT selector;
+} Descriptor;
+
+
+typedef struct {
+ ULONG Reserved;
+ ULONG SMM_CTL_MSR;
+ ULONG write_data;
+ USHORT IO_addr;
+ USHORT data_size;
+ union {
+ struct {
+ USHORT CS_Writable: 1;
+ USHORT IO_Write: 1;
+ USHORT REP_Prefix: 1;
+ USHORT SMINT: 1;
+
+ USHORT HALT: 1;
+ USHORT Ext_IO_Trap: 1;
+ USHORT External: 1;
+ USHORT IO_Trap: 1;
+
+ USHORT Nested: 1;
+ USHORT Reserved: 6;
+ USHORT CS_Readable: 1;
+ } SMI_Flags;
+ USHORT SMI_Flags_Ushort;
+ };
+
+ USHORT SS_Flags;
+
+ struct {
+ ULONG limit;
+ ULONG base;
+ USHORT selector;
+ USHORT attr;
+ } _CS;
+
+ union {
+ USHORT Next_IP;
+ ULONG Next_EIP;
+ };
+ union {
+ USHORT Current_IP;
+ ULONG Current_EIP;
+ };
+ ULONG r_CR0;
+ ULONG EFLAGS;
+ ULONG r_DR7;
+} SmiHeader;
+
+
+
+
+
+
+typedef USHORT MSG;
+typedef USHORT PRIORITY;
+typedef USHORT EVENT;
+typedef ULONG VSM;
+
+
+
+
+
+#define MAX_MSG_PARAM 4 // Parameter count
+#define MAX_MSG_CNT 10 // # entries in message queue
+
+typedef struct {
+ MSG Msg; // Message code
+ PRIORITY Priority; // Priority
+ ULONG From_VSM; // VSM that sent the message
+ ULONG Param[MAX_MSG_PARAM]; // Parameters
+ ULONG Timestamp; // Timestamp when message was entered
+} Message;
+
+
+typedef struct {
+
+ // VSM's state
+ SmiHeader State; // SMM header for this VSM
+
+ // NOTE: Flink field must be immediately after State structure
+ ULONG Flink; // Forward link to next VSM
+ ULONG Blink; // Backward link to previous VSM
+ ULONG SavedESP; // VSM's stack pointer
+ ULONG SysMgr_Ptr; // Ptr to SysMgr's InfoStuff structure
+ ULONG Southbridge; // PCI address of Southbridge
+
+
+ // Statistics
+ ULONG Adjustment; // Clocks used by SMM entry/exit
+ ULONG Clocks[2]; // Total clocks used by this VSM
+ ULONG NumSMIs[2]; // Total SMI count for this VSM
+ ULONG FrozenClocks[2]; // Copied from Clocks[]
+ ULONG FrozenNumSMIs[2]; // Copied from NumSMIs[]
+ ULONG StartTime[2]; // Timestamp @ start of timeslice
+ ULONG StartClocks[2]; // Timestamp of last INFO /S
+
+ // Floating Point
+ UCHAR FPU_State[108]; // Saved FPU state
+ UCHAR FPU_Flag; // Non-zero if FPU in use
+
+ UCHAR RunFlag; // VSM's scheduler state
+
+ USHORT ResumeVector; // Used by SaveToRAM
+ USHORT Pad[5];
+
+ // Message Queue
+ USHORT EndMsgQ; // Offset of *end* of message queue
+ USHORT Qhead; // Message queue head offset
+ USHORT Qtail; // Message queue tail offset
+
+ // MsgQueue is variable length, so it must be the last field
+ Message MsgQueue[MAX_MSG_CNT]; // The VSM's message queue
+
+} System;
+
+
+
+//*********************************************************************
+// VSM Header
+//*********************************************************************
+
+typedef struct {
+ ULONG Signature; // 'VSM '
+ UCHAR VSM_Type; // Type of VSM
+ UCHAR ForCPU; // Required CPU (FFFFh for any)
+ USHORT ForChipset; // Required companion I/O (FFFFh for any)
+ USHORT VSM_Version; // Version of VSM
+ ULONG VSM_Length; // Length of VSM module in bytes
+ USHORT EntryPoint; // Offset of entry point
+ ULONG DS_Limit;
+ Requirements Flag; // Special requirements/capabilities
+ USHORT VSA_Version;
+ Descriptor _SS; // SS: descriptor for this VSM
+ Descriptor _DS; // DS: descriptor for this VSM
+ Descriptor _ES; // ES: descriptor for this VSM
+ USHORT AlignSystem; // SysStuff must be DWORD aligned
+ System SysStuff; // Reserved for use by System Manager
+
+} VSM_Header;
+
+
+
+
+
+
+//*********************************************************************
+// VSM Types
+//*********************************************************************
+#define VSM_SYS_MGR 0x00 // System Manager
+#define VSM_AUDIO 0x01 // Xpress Audio
+#define VSM_VGA 0x02 // SoftVGA
+#define VSM_LEGACY 0x03 // Standard AT peripherals
+#define VSM_PM 0x04 // Legacy Power Management
+#define VSM_OHCI 0x05 // OHCI
+#define VSM_i8042 0x06 // 8042 emulator
+#define VSM_DEBUGGER 0x07 // SMI based debugger
+#define VSM_ACPI 0x08 // Virtual ACPI
+#define VSM_APM 0x09 // APM 1.2
+#define VSM_OEM_ACPI 0x0A // OEM ACPI customizations
+#define VSM_SMB 0x0B // System Management Bus
+#define VSM_BATTERY 0x0C // Battery controller
+#define VSM_RTC 0x0D // Virtual RTC
+#define VSM_S2D 0x0E // SaveToDisk
+#define VSM_EXT_AMP 0x0F // External audio amplifier
+#define VSM_PCMCIA 0x10 // PCMCIA
+#define VSM_SPY 0x11 // Spy. Receives ALL messages first.
+#define VSM_NETWORK 0x12 // Network
+#define VSM_GPIO 0x13 // GPIO handler
+#define VSM_KEYBOARD 0x14 // USB keyboard to PC/AT emulation
+#define VSM_MOUSE 0x15 // USB mouse to PS/2 emulation
+#define VSM_USB 0x16 // Universal Serial Bus
+#define VSM_FLASH 0x17 // FLASH
+#define VSM_INFRARED 0x18 // Infrared
+#define VSM_THERMAL 0x19 // Thermal monitor
+#define VSM_NULL 0x1A // Unspecified
+#define VSM_MPEG 0x1B // MPEG video decoder (EMMA)
+#define VSM_VIP 0x1C // Video processor (VIDEC)
+#define VSM_LPC 0x1D // Low Pin Count bus
+#define VSM_VUART 0x1E // Virtual UART
+#define VSM_MICRO 0x1F // MicroController
+#define VSM_USER1 0x20 // USER 1
+#define VSM_USER2 0x21 // USER 2
+#define VSM_USER3 0x22 // USER 3
+#define VSM_SYSINFO 0x23 // System Information
+#define VSM_SUPERIO 0x24 // PM for SuperIO
+#define VSM_EHCI 0x25 // EHCI
+#define VSM_MAX_TYPE VSM_EHCI // Highest valid VSM type
+
+#define VSM_ANY 0xFF // Wildcard for SYS_BROADCAST
+#define VSM_NOT_SELF 0x4000 // Flag used by SYS_BROADCAST
+#define VSM_ALL_EXCEPT 0x8000 // Flag used by SYS_BROADCAST
+
+
+//*********************************************************************
+// SMINT codes used by non-VSA components (BIOS, INIT, etc.)
+//*********************************************************************
+#define SYS_BIOS_INIT 0x00F0 // VSA installation from POST
+#define SYS_DOS_INSTALL 0x00F2 // VSA installation from DOS prompt
+#define SYS_VSM_INSTALL 0x00F3 // Install VSM dynamically
+#define SYS_REMOVE 0x00F4 // Unregister events belonging to VSM
+#define SYS_INT_RETURN 0x00F5 // Return from call to INT vector
+#define SYS_RESUME_FROM_RAM 0x6789 // Resume from RAM
+#define SYS_END_OF_POST 0x5000 // Issued by GeodeROM at end of POST
+#define SYS_INT13_SMI 0x5001 // Issued by Int 13 module (USB floppy)
+#define SYS_INT13CDR_SMI 0x5003 // Issued by Int 13 module (USB CD-ROM)
+#define SYS_USB_DEVICE_SMI 0x7777 // Issued by USBBOOT.ROM to access device table
+
+//*********************************************************************
+// Event Priorities
+//*********************************************************************
+#define NORMAL_PRIORITY 0x0000
+#define MAX_PRIORITY 0x7FFF
+#define BROADCAST_PRIORITY 0x9000
+#define UNREGISTER_PRIORITY 0xFFF0
+
+//*********************************************************************
+// Messages
+//*********************************************************************
+
+#define MSG_INITIALIZE 0 // Perform VSM initialization
+ #define EARLY_INIT 0
+ #define END_OF_POST_INIT 1
+
+#define MSG_SHUTDOWN 1 // Prepare for system shutdown (cold boot)
+#define MSG_SAVE_STATE 2 // Save entire state of device(s) controlled by VSM
+#define MSG_RESTORE_STATE 3 // Restore saved state of device(s) controlled by VSM
+#define MSG_SET_POWER_STATE 4 // Set device(s) to specified power state
+#define MSG_EVENT 5 // A registered event has occurred
+#define MSG_QUEUE_OVERFLOW 6 // The message queue is full.
+#define MSG_WARM_BOOT 7 // Prepare for a warm boot
+#define MSG_SET_POWER_MODE 9 // Restore saved state of device(s) controlled by VSM
+#define MSG_ABORT_POWER_STATE 10 // Power state is to be aborted
+
+//*********************************************************************
+// Events
+//*********************************************************************
+
+#define EVENT_GRAPHICS 1 // Video event
+#define EVENT_AUDIO 2 // Audio event
+#define EVENT_USB 3 // USB event
+#define EVENT_ACPI 4 // ACPI register access
+#define EVENT_ACPI_TIMER 5 // The ACPI timer expired
+#define EVENT_IO_TRAP 6 // I/O trap
+#define EVENT_IO_TIMEOUT 7 // I/O timeout
+#define EVENT_PME 8 // Power Management
+#define EVENT_KEL 9 // KEL
+#define EVENT_VIDEO_INACTIVITY 0x0A // Not supported in GX2
+#define EVENT_GPIO 0x0B // GPIO transition
+ #define FALLING_EDGE (1 << 0)
+ #define RISING_EDGE (1 << 1)
+ #define BOTH_EDGES (FALLING_EDGE | RISING_EDGE)
+ #define PME (1 << 2)
+ #define DEBOUNCE (1 << 3)
+ #define PULLDOWN (1 << 4)
+ #define PULLUP (1 << 5)
+ #define INVERT (1 << 6)
+ #define OUTPUT (1 << 7)
+ #define OPEN_DRAIN (1 << 8)
+ // INPUT may be removed as if it is not OUTPUT it is assumed to be INPUT
+ // this will have almost no impact on the code
+ // Do Not use INPUT
+ #define INPUT (1 << 9)
+ #define AUX1 (1 << 10)
+ #define AUX2 (1 << 11)
+ #define NO_ASMI (1 << 12)
+ #define PM1 (1 << 13)
+ #define GPE (1 << 14)
+ #define NO_ENABLE (1L << 15) // do not enable in GPE0_EN or PM1_EN
+ // when using EVENT_PME
+#define EVENT_SOFTWARE_SMI 0x0C // Software SMI
+#define EVENT_PCI_TRAP 0x0D // PCI trap
+#define EVENT_VIRTUAL_REGISTER 0x0E // Virtual register access
+#define EVENT_NMI 0x0F // NMI
+#define EVENT_TIMER 0x10 // Millisecond timer
+#define EVENT_DEVICE_TIMEOUT 0x11 // Device timeout
+#define EVENT_SEMAPHORE 0x12 // ACPI global lock
+#define EVENT_VBLANK 0x13 // Vertical blank
+#define EVENT_A20 0x14 // A20 mask toggled
+#define EVENT_SMB 0x15 // SMB Controller
+#define EVENT_RTC 0x16 // RTC Alarm
+#define EVENT_THERMAL 0x17 // THRM pin
+#define EVENT_LPC 0x18 // Low Pin Count bus
+#define EVENT_UART 0x19
+#define EVENT_BLOCKIO 0x1A
+#define EVENT_PWM 0x1B
+#define MAX_EVENT EVENT_PWM
+
+// Flags for event registration
+#define WRITES_ONLY (1L << 16)
+#define READS_ONLY (1L << 17)
+#define GLIU_ID (1L << 19)
+#define NOT_GLIU0 (1L << 20)
+#define NOT_GLIU1 (1L << 21)
+#define NOT_GLIU2 (1L << 22)
+#define ALL_GLIUS (NOT_GLIU0 | NOT_GLIU1 | NOT_GLIU2)
+// Flags used for EVENT_TIMER must be >= bit 24
+#define ONE_SHOT (1L << 24)
+#define FOR_STANDBY (1L << 25)
+
+
+//*********************************************************************
+// Resources
+//*********************************************************************
+#define RESOURCE_MEMORY 0 // Physical Memory
+#define RESOURCE_MMIO 1 // Memory mapped I/O
+#define RESOURCE_IO 2 // I/O space
+#define RESOURCE_SCIO 3 // Swiss-cheese I/O
+#define RESOURCE_GPIO 4 // General-purpose I/O pin
+#define RESOURCE_IRQ 5 // IRQ
+
+
+
+//*********************************************************************
+// Macros
+//*********************************************************************
+
+#define SYS_GET_NEXT_MSG(p) sys_get_next_msg(p)
+#define SYS_QUERY_MSG_QUEUE(p) sys_query_msg_queue(p)
+#define SYS_UNREGISTER_EVENT(e, p1, p2) sys_register_event(e, p1, p2, UNREGISTER_PRIORITY)
+#define SYS_REGISTER_EVENT(e, p1, p2, p) sys_register_event(e, p1, p2, p)
+#define SYS_PASS_EVENT(e, p1, p2, p3) // no longer needed
+#define SYS_VSM_PRESENT(vsm) sys_vsm_present(vsm)
+#define SYS_YIELD_CONTROL(p1) sys_yield_control(p1)
+#define SYS_SW_INTERRUPT(interrupt, regs) sys_software_interrupt(interrupt, regs)
+#define SYS_BROADCAST_MSG(msg, p, vsm) sys_broadcast_msg(msg, p, vsm)
+#define SYS_GET_SYSTEM_INFO(buffer) sys_get_system_info(buffer)
+#define SYS_REPORT_ERROR(err, info1, info2) sys_report_error(err, info1, info2)
+#define SYS_GENERATE_IRQ(irq) sys_generate_IRQ(irq)
+#define SYS_UNLOAD_VSM() sys_unload_vsm()
+#define SYS_LOGICAL_TO_PHYSICAL(addr) sys_logical_to_physical(addr)
+#define SYS_ALLOCATE_RESOURCE(f,p,q,r,s) sys_resource(f, p, q, r, s)
+#define SYS_DEALLOCATE_RESOURCE(f,p,q,r,s) sys_resource((UCHAR)(f|0x80), p, q, r, s)
+#define SYS_MBUS_DESCRIPTOR(addr, p) sys_mbus_descriptor(addr, p, 0)
+#define SYS_IO_DESCRIPTOR(addr, p) sys_mbus_descriptor(addr, p, 3)
+#define SYS_LOOKUP_DEVICE(id, i) sys_lookup_device(id, i)
+#define SYS_SAVE_STATE(buffer) sys_state(0, buffer)
+#define SYS_RESTORE_STATE(buffer) sys_state(1, buffer)
+#define SYS_SET_DECODE(addr, flag) sys_address_decode(addr, flag)
+#define SYS_MAP_IRQ(Source, Irq) sys_map_irq(Source, Irq)
+#define SYS_RETURN_RESULT(Data) sys_return_result(Data)
+#define SYS_DUPLICATE_VSM(MemModel) sys_duplicate_vsm(MemModel)
+
+#define READ_PCI_BYTE(addr) read_PCI_byte(addr)
+#define READ_PCI_WORD(addr) read_PCI_word(addr)
+#define READ_PCI_DWORD(addr) read_PCI_dword(addr)
+#define WRITE_PCI_BYTE(addr, data) write_PCI_byte(addr, data)
+#define WRITE_PCI_WORD(addr, data) write_PCI_word(addr, data)
+#define WRITE_PCI_DWORD(addr, data) write_PCI_dword(addr, data)
+
+#define WRITE_PCI_BYTE_NO_TRAP(addr, data) write_PCI_no_trap(addr, (ULONG)data, BYTE_IO)
+#define WRITE_PCI_WORD_NO_TRAP(addr, data) write_PCI_no_trap(addr, (ULONG)data, WORD_IO)
+#define WRITE_PCI_DWORD_NO_TRAP(addr, data) write_PCI_no_trap(addr, data, DWORD_IO)
+#define READ_PCI_BYTE_NO_TRAP(addr) ((UCHAR)read_PCI_no_trap(addr, BYTE_IO))
+#define READ_PCI_WORD_NO_TRAP(addr) ((USHORT)read_PCI_no_trap(addr, WORD_IO))
+#define READ_PCI_DWORD_NO_TRAP(addr) read_PCI_no_trap(addr, DWORD_IO)
+
+#define WRITE_MEMORY(addr, data) write_flat(addr, data)
+#define READ_MEMORY(addr) read_flat(addr)
+
+#define ENTER_CRITICAL_SECTION EnterCriticalSection();
+#define EXIT_CRITICAL_SECTION ExitCriticalSection();
+
+
+
+void __pascal sys_register_event(EVENT, ULONG, ULONG, USHORT);
+void __pascal sys_software_interrupt(USHORT, INT_REGS *);
+void __pascal sys_broadcast_msg(MSG, void *, USHORT);
+void __pascal sys_yield_control(ULONG);
+void __pascal sys_get_system_info(void *);
+void __pascal sys_generate_IRQ(USHORT);
+void __pascal sys_state(USHORT, void *);
+void __pascal sys_address_decode(USHORT, USHORT);
+void __pascal sys_map_irq(UCHAR, UCHAR);
+void __pascal sys_return_result(ULONG);
+void __pascal sys_get_descriptor(USHORT, void *);
+void __pascal sys_set_descriptor(USHORT, void *);
+void __pascal sys_set_header_data(USHORT, ULONG);
+void __pascal sys_set_register(USHORT, ULONG);
+void __pascal sys_set_virtual_register(USHORT, USHORT);
+void __pascal sys_report_error(USHORT, ULONG, ULONG);
+
+void __pascal write_PCI_byte(ULONG, UCHAR);
+void __pascal write_PCI_word(ULONG, USHORT);
+void __pascal write_PCI_dword(ULONG, ULONG);
+void __pascal write_PCI_no_trap(ULONG, ULONG, USHORT);
+
+void EnterCriticalSection(void);
+void ExitCriticalSection(void);
+void sys_fast_path_return(void);
+void sys_unload_vsm(void);
+void __pascal sys_duplicate_vsm(USHORT);
+
+void __pascal write_flat(ULONG, ULONG);
+ULONG __pascal read_flat(ULONG);
+UCHAR __pascal sys_vsm_present(UCHAR);
+USHORT __pascal sys_get_virtual_register(USHORT);
+ULONG __pascal sys_get_header_data(USHORT);
+ULONG __pascal sys_get_register(USHORT);
+UCHAR __pascal read_PCI_byte(ULONG);
+USHORT __pascal read_PCI_word(ULONG);
+ULONG __pascal read_PCI_dword(ULONG);
+ULONG __pascal read_PCI_no_trap(ULONG, USHORT);
+ULONG __pascal sys_logical_to_physical(void *);
+ULONG __pascal sys_resource(UCHAR, USHORT, ULONG, USHORT, USHORT);
+ULONG __pascal sys_mbus_descriptor(USHORT, ULONG *, USHORT);
+ULONG __pascal sys_lookup_device(USHORT, USHORT);
+MSG sys_get_next_msg(void *);
+MSG sys_query_msg_queue(void *);
+
+// Macros for use by VSMs to access the non-SMM context
+#define SET_HEADER_DATA(reg, data) sys_set_header_data(reg, data)
+#define GET_HEADER_DATA(reg) (ULONG)sys_get_header_data(reg)
+#define GET_DESCRIPTOR(reg, buffer) sys_get_descriptor(reg, buffer);
+#define SET_DESCRIPTOR(reg, buffer) sys_set_descriptor(reg, buffer);
+#define GET_REGISTER(reg) (ULONG)sys_get_register(reg)
+#define SET_REGISTER(reg, data) sys_set_register(reg, data)
+#define SET_EAX(data) SET_REGISTER(R_EAX, (ULONG) (data))
+#define SET_AX(data) SET_REGISTER(R_AX, (USHORT)(data))
+#define SET_AL(data) SET_REGISTER(R_AL, (UCHAR) (data))
+#define SET_AH(data) SET_REGISTER(R_AH, (UCHAR) (data))
+#define SET_EFLAGS(data) SET_HEADER_DATA(R_EFLAGS, data)
+#define GET_EAX() ((ULONG) GET_REGISTER(R_EAX))
+#define GET_AX() ((USHORT)GET_REGISTER(R_AX))
+#define GET_AL() ((UCHAR) GET_REGISTER(R_AL))
+#define GET_AH() ((UCHAR) GET_REGISTER(R_AH))
+#define GET_EFLAGS() (GET_HEADER_DATA(R_EFLAGS))
+
+
+// Macros for accessing virtual registers
+#define GET_VIRTUAL_REGISTER(reg) (USHORT)sys_get_virtual_register(reg)
+#define SET_VIRTUAL_REGISTER(reg, data) sys_set_virtual_register(reg, data)
+
+
+//*********************************************************************
+// Error Codes
+//*********************************************************************
+
+#define ERR_UNDEF_EVENT 1 // Attempt to register an undefined event
+//#define ERR_SCHEDULER 2 // Scheduler error
+#define ERR_BAD_PARAMETER 3 // Illegal system call parameter
+#define ERR_RESOURCE_CONFLICT 4 // Multiple VSMs requested conflicting resources
+#define ERR_UNHANDLED_EVENT 5 // An event occurred that no VSM handled
+#define ERR_INVALID_EVENT 6 // SysMgr attempted to send an invalid event
+//#define ERR_TIME_LIMIT 7 // A VSM exceeded its allotted runtime
+#define ERR_REGISTRATION_LOST 8 // A registered event is lost due to too many event registrations
+#define ERR_HW_MISMATCH 9 // A VSM could not find the correct hardware (e.g. OHCI)
+#define ERR_BAD_DESCRIPTOR 0x0A // A descriptor in a VSM header is not valid
+//#define ERR_MSG_QUEUE_FULL 0x0B // A VSM's message queue is full
+//#define ERR_MULTIPLE_EVENT 0x0C // A VSM attempted to register the same event twice
+#define ERR_UNREGISTRATION 0x0D // A VSM attempted to unregister an event for which it was not registered
+#define ERR_UNREGISTERED_EVENT 0x0E // An event occurred for which no VSM is registered
+#define ERR_MISALIGNED_IO 0x0F // An misaligned I/O access occurred
+//#define ERR_UNEXPECTED_EVENT 0x10 // A handler routine was passed an unexpected SMI event
+//#define ERR_BAD_VSM 0x11 // A VSM header doesn't look right (no signature, etc.)
+#define ERR_NESTED_ACCESS 0x12 // A VSM directly accessed a ACPI or virtual register
+//#define ERR_BAD_MSG 0x13 // An attempt was made to send an illegal message code
+//#define ERR_UNHANDLED_VIRTUAL 0x14 // An access was made by a VSM to an unhandled virtual register
+#define ERR_BAD_INTERRUPT 0x15 // A VSM attempted to call an illegal INT vector
+#define ERR_ILLEGAL_MACRO 0x16 // Illegal use of GET/SET_REGISTER or GET/SET_HEADER_DATA macros
+#define ERR_UNDEF_SYS_CALL 0x17 // Undefined system call
+//#define ERR_BAD_POWER_STATE 0x18 // Invalid power state
+#define ERR_BAD_VR_ACCESS 0x19 // Access to undefined VR class by an application
+#define ERR_UNDEF_VIRTUAL_REG 0x1A // Access to undefined VR class by a VSM
+//#define ERR_UNSUPPORTED_CHIPSET 0x1B // This chipset is not supported
+#define ERR_PCI_TRAP 0x1C // A VSM requested an unsupported PCI trap
+#define ERR_RESOURCE_NOT_FOUND 0x1D // A VSM requested an unsupported resource
+#define ERR_NO_MORE_DESCRIPTORS 0x1E // Out of MBIU descriptors
+//#define ERR_INTERNAL_ERROR 0x1F // System error, e.g. inconsistent data structure
+#define ERR_DATA_STRUCTURE 0x20 // A system structure is too small
+
+
+
+
+
+
+// Used as 2nd parameter to SYS_SET_DECODE macro:
+#define POSITIVE_DECODE 1
+#define SUBTRACTIVE_DECODE 0
+
+
+
+
+//****************************************************************************************************
+#define FROM_HEADER 0x2000
+#define WORD_SIZE 0x4000
+#define DWORD_SIZE 0x8000
+
+
+
+
+// Field names for GET_REGISTER and SET_REGISTER macros
+// These offsets must match the register order on the stack (PUSHAD)
+
+#define R_DI 0 + WORD_SIZE
+#define R_EDI 0 + DWORD_SIZE
+
+#define R_SI 4 + WORD_SIZE
+#define R_ESI 4 + DWORD_SIZE
+
+#define R_BP 8 + WORD_SIZE
+#define R_EBP 8 + DWORD_SIZE
+
+#define R_BL 16
+#define R_BH R_BL + 1
+#define R_BX R_BL + WORD_SIZE
+#define R_EBX R_BL + DWORD_SIZE
+
+#define R_DL 20
+#define R_DH R_DL + 1
+#define R_DX R_DL + WORD_SIZE
+#define R_EDX R_DL + DWORD_SIZE
+
+#define R_CL 24
+#define R_CH R_CL + 1
+#define R_CX R_CL + WORD_SIZE
+#define R_ECX R_CL + DWORD_SIZE
+
+#define R_AL 28
+#define R_AH R_AL + 1
+#define R_AX R_AL + WORD_SIZE
+#define R_EAX R_AL + DWORD_SIZE
+
+#define R_SP 32 + WORD_SIZE
+#define R_ESP 32 + DWORD_SIZE
+
+
+// Segment registers
+// NOTE: offset points to .selector field
+#define DESCRIPTOR_SIZE 10 // sizeof(Descriptor)
+#define R_SS 36-2 + DESCRIPTOR_SIZE + WORD_SIZE
+#define R_DS R_SS + DESCRIPTOR_SIZE
+#define R_ES R_DS + DESCRIPTOR_SIZE
+#define R_FS R_ES + DESCRIPTOR_SIZE
+#define R_GS R_FS + DESCRIPTOR_SIZE
+
+// Fields from SMM header
+#define WRITE_DATA 0x08 + DWORD_SIZE + FROM_HEADER
+#define IO_ADDRESS 0x0C + WORD_SIZE + FROM_HEADER
+#define DATA_SIZE 0x0E + FROM_HEADER
+#define SMM_FLAGS 0x10 + WORD_SIZE + FROM_HEADER
+#define CS_LIMIT 0x14 + DWORD_SIZE + FROM_HEADER
+#define CS_BASE 0x18 + DWORD_SIZE + FROM_HEADER
+#define CS_SELECTOR 0x1C + WORD_SIZE + FROM_HEADER
+#define CS_ATTR 0x1E + WORD_SIZE + FROM_HEADER
+#define R_CS 0x1C + WORD_SIZE + FROM_HEADER
+#define R_IP 0x20 + WORD_SIZE + FROM_HEADER
+#define R_EIP 0x20 + DWORD_SIZE + FROM_HEADER
+#define CURRENT_EIP 0x24 + DWORD_SIZE + FROM_HEADER
+#define R_CR0 0x28 + DWORD_SIZE + FROM_HEADER
+#define R_EFLAGS 0x2C + DWORD_SIZE + FROM_HEADER
+ #define EFLAGS_CF 0x0001
+ #define EFLAGS_ZF 0x0040
+ #define EFLAGS_IF 0x0200
+ #define EFLAGS_DF 0x0400
+#define R_DR7 0x30 + DWORD_SIZE + FROM_HEADER
+
+
+
+
+
+
+typedef struct {
+ ULONG Chipset_Base;
+ USHORT Chipset_ID;
+ USHORT Chipset_Rev;
+ USHORT CPU_ID;
+ USHORT CPU_Revision;
+ USHORT CPU_MHz;
+ ULONG SystemMemory; // Units = bytes
+ ULONG VSA_Location; // Physical location
+ USHORT VSA_Size; // Units = KB
+ USHORT PCI_MHz;
+ USHORT DRAM_MHz;
+} Hardware;
+
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/blockio.c b/cpu/amd/geode_lx/gplvsa_ii/legacy/blockio.c
new file mode 100755
index 0000000..fca33aa
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/blockio.c
@@ -0,0 +1,88 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Function: *
+//* Handler for blocked PIO during UDMA
+
+#include "vsa2.h"
+#include "protos.h"
+
+
+#define RESET_DRIVE 0x08
+
+
+USHORT UDMA_IO_Base;
+
+
+//***********************************************************************
+// Enables/disables BLOCKIO
+//***********************************************************************
+void pascal BlockIO(UCHAR EnableFlag)
+{ USHORT Priority=UNREGISTER_PRIORITY;
+
+ if (EnableFlag) {
+ Priority = MAX_PRIORITY;
+ }
+
+ SYS_REGISTER_EVENT(EVENT_BLOCKIO, 0, 0, Priority);
+}
+
+
+
+
+
+//***********************************************************************
+// Handler for EVENT_BLOCKIO
+//***********************************************************************
+void Handle_BLOCKIO(USHORT IO_Address, ULONG Data, UCHAR DataSize)
+{ UCHAR Command;
+
+ switch (IO_Address) {
+
+ case 0x1F7:
+ // Check for drive reset command
+ if ((UCHAR)Data == RESET_DRIVE) {
+ break;
+ }
+ return;
+
+ case 0x3F6:
+ if ((UCHAR)Data & 4) {
+ break;
+ }
+
+ default:
+ // Ignore I/O to all other IDE registers
+ return;
+ }
+
+ // Disable BLOCKIO
+ BlockIO(0);
+
+ // Terminate bus mastering
+ Command = in_8(UDMA_IO_Base);
+ out_8(UDMA_IO_Base, (UCHAR)(Command & ~1));
+
+ // Re-issue the I/O
+ out_8(IO_Address, (UCHAR)Data);
+
+ // Re-enable BLOCKIO
+ BlockIO(1);
+
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/cs5536.c b/cpu/amd/geode_lx/gplvsa_ii/legacy/cs5536.c
new file mode 100755
index 0000000..9fbddec
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/cs5536.c
@@ -0,0 +1,479 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Function: *
+//* This file contains routines specific to the CS5536.
+
+#include "vsa2.h"
+#include "chipset.h"
+#include "pci.h"
+#include "vr.h"
+#include "mapper.h"
+#include "gx2.h"
+#include "legacy.h"
+#include "protos.h"
+#include "isa.h"
+
+
+
+// External Function prototypes
+extern void GetDrivesPresent(void);
+extern void Allocate_Flash_BARs(void);
+extern void pascal Flash_IDE_Switch(USHORT, ULONG);
+extern void BlockIO(UCHAR);
+extern void Register_DMA_Fix(void);
+extern UCHAR FlashIsEnabled(void);
+
+// Local function prototypes:
+void Handle_5536_PCI_Traps(USHORT, USHORT, ULONG);
+void Register_PCI_Trap(USHORT, UCHAR);
+
+// External variables:
+extern Hardware SystemInfo;
+extern ULONG ChipsetBase;
+extern ULONG Param[];
+extern USHORT UDMA_IO_Base;
+extern ULONG OHCI_Address[];
+
+// Local variables:
+typedef void (* PCI_HANDLER)(USHORT, USHORT, ULONG);
+extern PCI_HANDLER Handle_PCI_Traps;
+
+USHORT uart1 = 0;
+USHORT uart2 = 0;
+USHORT Flash_Function=0x00FF, IDE_Function = 0x00FF;
+USHORT PCI_Int_AB = ((USHORT)((INTB_PIN << 8) | INTA_PIN));
+USHORT PCI_Int_CD = ((USHORT)((INTD_PIN << 8) | INTC_PIN));
+USHORT Y_Sources[8];
+USHORT Flash_PME;
+USHORT Steering = 0x0000;
+USHORT Hidden_Function = 0x0000;
+UCHAR IDE_Allocated = 0;
+UCHAR Flash_Allocated = 0;
+ULONG MDD_Base;
+USHORT pmc_base = 0;
+USHORT gpio_base = 0;
+USHORT acpi_base = 0;
+
+typedef struct {
+ UCHAR Pin;
+ UCHAR Z_Source;
+ UCHAR Lbar;
+} PCI_INTERRUPT;
+
+PCI_INTERRUPT PCI_Interrupt[] = {
+// Pin Z_Source
+ {INTA_PIN, Z_IRQ_INTA},
+ {INTB_PIN, Z_IRQ_INTB},
+ {INTC_PIN, Z_IRQ_INTC},
+ {INTD_PIN, Z_IRQ_INTD}
+};
+
+
+//***********************************************************************
+// Hides the PCI header of the specified function
+//***********************************************************************
+void Hide_Hdr(USHORT Function)
+{
+
+ // If a function is currently being hidden, un-hide it
+ if (Hidden_Function) {
+ SYS_UNREGISTER_EVENT(EVENT_PCI_TRAP, ChipsetBase+Hidden_Function, 0x000000FF);
+ SYS_UNREGISTER_EVENT(EVENT_PCI_TRAP, ChipsetBase+Function+0x40, WRITES_ONLY);
+ }
+
+ // Register for IDE/Flash config space (to make invisible)
+ Register_PCI_Trap(Function, 0xFF);
+
+ // Record which function is hidden
+ Hidden_Function = Function;
+
+ // Get the 'other' function
+ if (Function == IDE_Function) {
+ Function = Flash_Function;
+ } else {
+ Function = IDE_Function;
+ }
+
+ // Trap IDE/Flash register 0x40 (used for Flash<->IDE switch)
+ SYS_REGISTER_EVENT(EVENT_PCI_TRAP, ChipsetBase+Function+0x40, WRITES_ONLY, 0);
+
+}
+
+
+//***********************************************************************
+// Maps the NAND Flash PMEs to the specified IRQ
+//***********************************************************************
+void Map_Flash_IRQ(UCHAR Irq)
+{
+ SYS_MAP_IRQ((UCHAR)(Flash_PME+0), Irq);
+ SYS_MAP_IRQ((UCHAR)(Flash_PME+1), Irq);
+}
+
+
+
+//***********************************************************************
+// Hides the IDE function and un-hides the Flash function
+//***********************************************************************
+void Hide_IDE_Hdr(void)
+{ UCHAR Shift, Irq;
+
+ // Map NAND Flash interrupts
+ Shift = (UCHAR)(((Flash_PME >> 8)-1) * 4);
+ Irq = (UCHAR)(Steering >> Shift) & 0x0F;
+ Map_Flash_IRQ(Irq);
+
+ // Hide the IDE header
+ Hide_Hdr(IDE_Function);
+}
+
+
+
+//***********************************************************************
+// Hides the Flash function and un-hides the IDE function
+//***********************************************************************
+void Hide_Flash_Hdr(void)
+{ USHORT Bar;
+
+ // Unmap NAND Flash interrupts
+ Map_Flash_IRQ(0);
+
+ // If Flash BARs have been allocated, then zero them to disable linked MSRs
+ if (Flash_Allocated) {
+ for (Bar = BAR0; Bar <= BAR3; Bar += 0x10) {
+ WRITE_PCI_DWORD(ChipsetBase+IDE_Function+Bar, 0x00000000);
+ }
+ }
+ Hide_Hdr(Flash_Function);
+
+ if (!IDE_Allocated) {
+
+ // Allocate UDMA BAR
+ SYS_ALLOCATE_RESOURCE(RESOURCE_IO, BAR4, 16, DEVICE_ID_AMD_THOR, ID_ATA);
+
+ IDE_Allocated = 1;
+ }
+}
+
+
+
+//***********************************************************************
+// Performs early initialization for CS5536
+//***********************************************************************
+void CS5536_Early_Init(void)
+{ USHORT Function;
+ ULONG PciAddr, PciData;
+
+ Handle_PCI_Traps = Handle_5536_PCI_Traps;
+
+ MDD_Base = SYS_LOOKUP_DEVICE(ID_MDD, 1);
+ // Get I/O base of PMC, ACPI & GPIO
+ pmc_base = READ_PCI_WORD(ChipsetBase + BAR4) & 0xFFFE;
+ gpio_base = READ_PCI_WORD(ChipsetBase + BAR1) & 0xFFFE;
+ acpi_base = READ_PCI_WORD(ChipsetBase + BAR5) & 0xFFFE;
+
+
+ // Scan Southbridge functions to:
+ // - Get Unrestricted Sources Y IRQ.
+ // - Find Flash & IDE functions.
+ for (Function = 0; Function < 8; Function++) {
+
+ // Generate PCI configuration address
+ PciAddr = ChipsetBase | (Function << 8);
+
+ // For functions that have PCI interrupts, Interrupt Line
+ // contains Y Sources field number.
+ (UCHAR)PciAddr = INTERRUPT_LINE;
+
+ // If PCI interrupt is defined, record linked Unrestricted Y Source
+ Y_Sources[Function] = READ_PCI_WORD(PciAddr);
+ if (Y_Sources[Function]) {
+ // clear Interrupt Line
+ WRITE_PCI_WORD(PciAddr, 0x0000);
+ }
+
+ // Read Class Code
+ (UCHAR)PciAddr = REVISION_ID;
+ PciData = READ_PCI_DWORD(PciAddr);
+ // Ignore Revision ID
+ PciData &= 0xFFFFFF00;
+
+ // Record function # of Flash header
+ if (PciData == 0x05010000) {
+ Flash_Function = (USHORT)PciAddr & 0x0700;
+ Flash_PME = Y_Sources[Function];
+ }
+ // Record function # of IDE header
+ if (PciData == 0x01018000) {
+ IDE_Function = (USHORT)PciAddr & 0x0700;
+ Y_Sources[Function] = Flash_PME+1;
+ }
+ }
+
+ switch (SystemInfo.Chipset_ID) {
+ case DEVICE_ID_5536:
+ SYS_REGISTER_EVENT(EVENT_PCI_TRAP, ChipsetBase+IDE_Function+BAR4, WRITES_ONLY, 0);
+ break;
+ }
+
+
+ // Is Flash controller enabled ?
+ if (FlashIsEnabled()) {
+
+ // Allocate Flash BARs
+ Allocate_Flash_BARs();
+
+ // Hide the IDE header
+ Hide_IDE_Hdr();
+
+ } else {
+
+ // Hide the Flash header
+ Hide_Flash_Hdr();
+ }
+
+ // Register for virtual registers VRC_MISCELLANEOUS::PCI_INT_AB->WATCHDOG
+ SYS_REGISTER_EVENT(EVENT_VIRTUAL_REGISTER, VRC_MISCELLANEOUS, (PCI_INT_AB<<8) | WATCHDOG, MAX_PRIORITY);
+
+ // Register for SB PCI register 0x5C-0x5D (emulation of 5530 PCI steering register)
+ Register_PCI_Trap(0x005C, 0x01);
+
+/*MEJ
+ // If Power Management VSM is present...
+ if (SYS_VSM_PRESENT(VSM_PM)) {
+ // Register for virtual register timeouts on legacy devices
+ SYS_REGISTER_EVENT(EVENT_VIRTUAL_REGISTER, VRC_PM, (DISK_TIMEOUT<<8) | PARALLEL_TIMEOUT, 0);
+ }
+*/
+
+ // Register for virtual register class VRC_CHIPSET
+ SYS_REGISTER_EVENT(EVENT_VIRTUAL_REGISTER, VRC_CHIPSET, 0, NORMAL_PRIORITY);
+
+
+}
+
+
+
+//***********************************************************************
+// Performs End-of-POST initialization for CS5536
+//***********************************************************************
+void CS5536_Late_Init(void)
+{
+ // Determine how many ATA drives are present
+ GetDrivesPresent();
+
+ // Set ISA bridge Latency Timer to 0x40
+ WRITE_PCI_BYTE(ChipsetBase + LATENCY_TIMER, 0x40);
+
+}
+
+
+//***********************************************************************
+// Handler for writes to VRC_MISCELLANEOUS PCI_INT_AB & PCI_INT_CD
+// These registers define what GPIOs are to be used for PCI interrupts.
+//***********************************************************************
+void Handle_Misc_VR(UCHAR Index, USHORT Data)
+{ int i, j;
+ ULONG Param2;
+ static UCHAR Flag = 0x00;
+
+
+ if (Index == PCI_INT_AB) {
+ // PCI interrupt GPIOs can only be allocated once
+ if (Flag & 1) {
+ return;
+ }
+ // Record data for readback
+ PCI_Int_AB = Data;
+ Flag |= 1;
+ i = 0;
+ } else {
+ // PCI interrupt GPIOs can only be allocated once
+ if (Flag & 2) {
+ return;
+ }
+ // Record data for readback
+ PCI_Int_CD = Data;
+ Flag |= 2;
+ i = 2;
+ }
+
+ // Set GPIOs as level-sensitive (no ASMI!), inverted inputs
+ j = i + 2;
+ while (i < j) {
+
+ // Record the GPIO pin
+ PCI_Interrupt[i].Pin = (UCHAR)Data;
+
+ if (PCI_Interrupt[i].Pin < 32) {
+ Param2 = ((ULONG)PCI_Interrupt[i].Z_Source << 16) | PCI_Interrupt[i].Pin;
+ SYS_REGISTER_EVENT(EVENT_GPIO, Param2, INVERT, MAX_PRIORITY);
+ }
+
+ // Shift the next pin # into the 8 LSBs
+ Data >>= 8;
+
+ i++;
+ }
+}
+
+
+
+
+//***********************************************************************
+// Emulates CS5530's PCI Interrupt steering registers 0x5C & 0x5D
+// Register 0x5C:
+// 3:0 INTA#
+// 7:4 INTB#
+// Register 0x5D:
+// 3:0 INTC#
+// 7:4 INTD#
+// Maps PCI INT pins to Unrestricted Z sources
+//***********************************************************************
+void PCI_Interrupt_Steering(USHORT Data)
+{ UCHAR i, j, Irq;
+
+ // Register for PCI interrupt GPIOs in case BIOS never wrote to the VR
+ Handle_Misc_VR(PCI_INT_AB, PCI_Int_AB);
+ Handle_Misc_VR(PCI_INT_CD, PCI_Int_CD);
+
+ for (i=0; i < 4; i++) {
+
+ // Extract IRQ from next nibble
+ Irq = (UCHAR)(Data & 0x0F);
+
+ // Don't allow IRQ2 (SMI)
+ if (Irq != 2) {
+ // Map the Unrestricted Z Source to the requested IRQ
+ SYS_MAP_IRQ((UCHAR)(PCI_Interrupt[i].Z_Source+16), Irq);
+
+ // Map the Unrestricted Y Source (if any) to the requested IRQ
+ for (j=0; j < 8; j++) {
+ UCHAR InterruptPin;
+
+ InterruptPin = (UCHAR)(Y_Sources[j] >> 8);
+ if (InterruptPin == i+1) {
+ SYS_MAP_IRQ((UCHAR)Y_Sources[j], Irq);
+ }
+ }
+ }
+
+ // Shift the next nibble into the 4 LSBs
+ Data >>= 4;
+ }
+}
+
+//***********************************************************************
+// Handler for emulation of 5530 PCI steering registers on a 5536 system
+//***********************************************************************
+void Handle_5536_PCI_Traps(USHORT PCI_Addr, USHORT IO_Params, ULONG Data)
+{ UCHAR PCI_Reg, Shift, IO_Size;
+ USHORT Function;
+
+
+ PCI_Reg = (UCHAR) PCI_Addr;
+ IO_Size = (UCHAR) IO_Params;
+ Function = PCI_Addr & 0x0700;
+ Shift = (PCI_Reg & 3) << 3;
+
+ // Record OHCI BAR values
+ if (PCI_Addr == 0x7C10 || PCI_Addr == 0x7D10) {
+ if (IO_Params & IO_WRITE) {
+ Function = (Function >> 8) - 4;
+ OHCI_Address[Function] = Data & 0xFFFFF000;
+ }
+ return;
+ }
+
+ // PCI Interrupt Steering register
+ if (Function == 0x0000) {
+
+ if (IO_Params & IO_WRITE) {
+ // Handle mis-aligned accesses
+ if (Shift) {
+ Steering &= 0x00FF;
+ Steering |= (USHORT)Data << 8;
+ } else {
+ Steering = (USHORT)Data;
+ }
+ PCI_Interrupt_Steering(Steering);
+ return;
+
+ } else {
+ if (PCI_Reg < 0x5C) {
+ Data = (ULONG)Steering << (32-Shift);
+ Shift = 0;
+ } else {
+ Data = Steering;
+ }
+ }
+
+ } else {
+
+ // Flash/IDE configuration space
+ if (Function == Flash_Function || Function == IDE_Function) {
+
+ if (IO_Params & IO_WRITE) {
+
+ // PCI writes to IDE/Flash function
+ switch (PCI_Reg) {
+ case BAR4:
+ if (Function == IDE_Function && (USHORT)Data != 0xFFFF) {
+ // Record UDMA I/O base for BLOCK_IO logic
+ UDMA_IO_Base = (USHORT)Data & 0xFFF0;
+ }
+ break;
+
+ // Write to IDE<->Flash switch
+ case 0x40:
+ if (Data == 0xDEADBEEF || Data == 0xBEEFDEAD) {
+ // Switch Flash<->IDE
+ Flash_IDE_Switch(Function, Data);
+ }
+ }
+ return;
+
+ } else {
+
+ // PCI reads of hidden function
+ if (Function == Hidden_Function) {
+ Data = 0xFFFFFFFF;
+ }
+ }
+ }
+ }
+
+
+ // Handle non-dword aligned accesses
+ Data >>= Shift;
+ Data |= 0xFFFFFFFFL << (32-Shift);
+
+ // Return the PCI register value
+ SYS_RETURN_RESULT(Data);
+
+}
+
+//***********************************************************************
+// Registers a PCI trap for the specified Addr/Mask
+//***********************************************************************
+void Register_PCI_Trap(USHORT Addr, UCHAR Mask)
+{
+ SYS_REGISTER_EVENT(EVENT_PCI_TRAP, ChipsetBase+Addr, (ULONG)Mask, 0);
+}
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/events.c b/cpu/amd/geode_lx/gplvsa_ii/legacy/events.c
new file mode 100755
index 0000000..6d80cbd
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/events.c
@@ -0,0 +1,145 @@
+/*
+* Copyright (c) 2006 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Function: *
+//* This file handles the Legacy VSM's event messages.
+
+#include "vsa2.h"
+#include "chipset.h"
+#include "vr.h"
+#include "legacy.h"
+#include "protos.h"
+#include "pci.h"
+#include "isa.h"
+
+// Function prototypes
+extern void Handle_BLOCKIO(USHORT, ULONG, UCHAR);
+extern void Handle_VirtualRegs(UCHAR, UCHAR, UCHAR, USHORT);
+extern void Do_OHCI_SWAPSiF(void);
+
+// External variables:
+extern ULONG ChipsetBase;
+extern USHORT DiskTimeout, SerialTimeout, ParallelTimeout, FloppyTimeout;
+
+// Local variables:
+USHORT IDE_Interface = MASTER_IDE; // Default to "bus master capable"
+
+typedef void (* PCI_HANDLER)(USHORT, USHORT, ULONG);
+PCI_HANDLER Handle_PCI_Traps;
+
+
+//***********************************************************************
+// Register I/O trap to fix 118.409 - Block/Demand mode fails
+//***********************************************************************
+void Register_DMA_Fix(void)
+{
+#define DMA_FLAGS (WRITES_ONLY | ONE_SHOT)
+
+ SYS_REGISTER_EVENT(EVENT_IO_TRAP, DMA1_MODE, DMA_FLAGS | 1, 0);
+}
+
+
+//***********************************************************************
+// Handler for MSG_EVENT
+//***********************************************************************
+void Handle_Events(ULONG * Param)
+{ USHORT Event, IO_Address;
+ ULONG Data;
+ UCHAR WrFlag, DataSize, Class, Index;
+
+ Event = (USHORT)Param[0];
+ IO_Address = (USHORT)Param[2];
+ DataSize = (UCHAR)(Param[2] >> 16);
+ Data = Param[3];
+
+ switch (Event) {
+
+ case EVENT_IO_TRAP:
+ // If it is an I/O to the 8237 DMA controller...
+ if (IO_Address == DMA1_MODE) {
+ static UCHAR Mode = 0x00;
+ UCHAR ByteData;
+
+ // and it is a I/O write...
+ if (Param[1] & 2) {
+ ByteData = (UCHAR)Data;
+ // and the Mode is either Block or Demand...
+ Mode = ByteData & MODE_MASK;
+ if (Mode == MODE_DEMAND || Mode == MODE_BLOCK) {
+ // then change the mode to Single
+ ByteData &= ~MODE_MASK;
+ ByteData |= MODE_SINGLE;
+ }
+
+ // Re-issue the I/O (trapping is disabled since it was a ONE_SHOT)
+ out_8(DMA1_MODE, ByteData);
+ }
+ // Re-register for the I/O trap
+ Register_DMA_Fix();
+ break;
+ }
+
+ // Handle PM traps here...
+ break;
+
+ case EVENT_IO_TIMEOUT:
+ // Handle PM timeout here...
+ break;
+
+ case EVENT_SOFTWARE_SMI:
+ if (Param[1] == SYS_DMA_DRIVER) {
+ // Allow the UDMA driver to see that IDE is bus master capable.
+ IDE_Interface = MASTER_IDE;
+ } else if (Param[1] == SYS_DMA_DRIVER+1) {
+ // Prevent the UDMA driver from seeing that IDE is bus master capable.
+ IDE_Interface = 0;
+ }
+ break;
+
+ case EVENT_PCI_TRAP:
+ Handle_PCI_Traps((USHORT)Param[1], (USHORT)Param[2], Data);
+ break;
+
+ case EVENT_VIRTUAL_REGISTER:
+ // Extract virtual register parameters from message
+ Class = (UCHAR)(Param[1] >> 8);
+ Index = (UCHAR)Param[1];
+ WrFlag = (UCHAR)Param[2];
+ Handle_VirtualRegs(Class, Index, WrFlag, (USHORT)Data);
+ break;
+
+ case EVENT_BLOCKIO:
+ Handle_BLOCKIO(IO_Address, Data, DataSize);
+ break;
+
+ case EVENT_TIMER:
+ // Fix for attach/detach hardware bug
+ if (Param[2] == USBF_HANDLE) {
+ Do_OHCI_SWAPSiF();
+ break;
+ }
+
+/*MEJ // Broadcast to all VSM's
+ Param[0] = S5_STATE;
+ Param[1] = CLASS_ALL;
+ SYS_BROADCAST_MSG(MSG_SET_POWER_STATE, &Param[0], VSM_ANY);
+*/
+ break;
+ }
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/flash.bak b/cpu/amd/geode_lx/gplvsa_ii/legacy/flash.bak
new file mode 100755
index 0000000..7cce28e
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/flash.bak
@@ -0,0 +1,174 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* Routines related to the Flash device.
+//******************************************************************************
+
+
+
+
+
+#include "VSA2.H"
+#include "CHIPSET.H"
+#include "SYSMGR.H"
+#include "MDD.H"
+#include "PCI.H"
+#include "GX2.H"
+#include "LEGACY.H"
+#include "PROTOS.H"
+
+// Function prototypes:
+extern void Hide_IDE_Hdr(void);
+extern void Hide_Flash_Hdr(void);
+
+
+// External variables:
+extern ULONG MDD_Base;
+extern USHORT Flash_Function, IDE_Function;
+extern UCHAR Flash_Allocated;
+
+
+
+//***********************************************************************
+// Returns non-zero if Flash device is enabled
+//***********************************************************************
+UCHAR FlashIsEnabled(void)
+{ UCHAR Pin;
+
+ Pin = (UCHAR)Read_MSR_LO(MDD_Base + MSR_PIN_OPTS) & PIN_OPT_IDE;
+ Pin ^= PIN_OPT_IDE;
+ return Pin;
+}
+
+
+//***********************************************************************
+// Allocates Flash BARs
+//***********************************************************************
+void Allocate_Flash_BARs(void)
+{ ULONG MsrAddr, MsrData[2], Size;
+ USHORT Bar;
+ UCHAR Resource;
+ static UCHAR Flash_LBARs[4] = {
+ MSR_LBAR_FLSH0,
+ MSR_LBAR_FLSH1,
+ MSR_LBAR_FLSH2,
+ MSR_LBAR_FLSH3,
+ };
+
+
+ // BARs are only to be allocated once
+ if (Flash_Allocated == 0) {
+
+ Flash_Allocated = 1;
+ // Determine type/size of PCI BAR for each Flash device
+ MsrAddr = MDD_Base;
+ for (Bar = BAR0; Bar <= BAR3; Bar += 4) {
+ // Read the Flash LBAR
+ (UCHAR)MsrAddr = Flash_LBARs[(Bar-BAR0)/4];
+ Read_MSR(MsrAddr, MsrData);
+
+ // If LBAR size has not been programmed, then don't configure the PCI BAR
+ Size = MsrData[1] & ~(MEM_IO | NOR_NAND | LBAR_EN);
+ if (Size == 0x00000000) {
+ continue;
+ }
+
+ // NAND or NOR Flash ?
+ if (MsrData[1] & NOR_NAND) {
+ // NAND Flash
+ // Required for proper byte count calculation
+ Size |= 0xFFFF0000;
+ Resource = RESOURCE_IO;
+ } else {
+ // NOR Flash
+ Size &= LBAR_MEM_MASK;
+ Resource = RESOURCE_MMIO;
+ }
+ // Convert mask to byte count
+ Size = ~Size + 1;
+ // Allocate BAR
+ SYS_ALLOCATE_RESOURCE(Resource, Bar, Size, DEVICE_ID_AMD_FLASH, ID_MDD);
+ }
+ }
+}
+
+
+
+//***********************************************************************
+// Switches between Flash and IDE headers
+//***********************************************************************
+void pascal Flash_IDE_Switch(USHORT Function, ULONG Data)
+{ ULONG PinOptions, PinMsr, FlashMsr, LBar[2], SavedLBar[2];
+
+ // Switch pins to Flash mode
+ PinMsr = MDD_Base + MSR_PIN_OPTS;
+ PinOptions = Read_MSR_LO(PinMsr);
+
+ if (Function == Flash_Function) {
+ // Currently in Flash mode
+
+ // Switching to IDE mode ?
+ if (Data == 0xBEEFDEAD) {
+
+ // Hide the Flash header
+ Hide_Flash_Hdr();
+
+ // Switch pins to IDE mode
+ PinOptions |= PIN_OPT_IDE;
+ Write_MSR_LO(PinMsr, PinOptions);
+
+ // Disconnect the ROM from the DMA pins
+ in_8(0x3F6);
+ }
+
+ } else {
+
+ // Currently in IDE mode
+
+ // Switching to Flash mode ?
+ if (Data == 0xDEADBEEF) {
+
+ // Hide the IDE header
+ Hide_IDE_Hdr();
+
+ // Allocate Flash BARs
+ Allocate_Flash_BARs();
+
+ // Enable Flash mode
+ PinOptions &= ~PIN_OPT_IDE;
+ Write_MSR_LO(PinMsr, PinOptions);
+
+ // Handle Canary circuit
+
+ // Set CS1# to respond to I/O address 22h
+ FlashMsr = MDD_Base + MSR_LBAR_FLSH1;
+ Read_MSR(FlashMsr, SavedLBar);
+ LBar[0] = 0x00000022;
+ LBar[1] = 0x0000FFF0 | LBAR_EN;
+ Write_MSR(FlashMsr, LBar);
+
+ // Turn Canary circuit on
+ in_8(0x22);
+
+ // Restore CS1 LBAR
+ Write_MSR(FlashMsr, SavedLBar);
+ }
+ }
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/flash.c b/cpu/amd/geode_lx/gplvsa_ii/legacy/flash.c
new file mode 100755
index 0000000..398a579
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/flash.c
@@ -0,0 +1,174 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* Routines related to the Flash device.
+//******************************************************************************
+
+
+
+
+
+#include "VSA2.H"
+#include "CHIPSET.H"
+#include "SYSMGR.H"
+#include "MDD.H"
+#include "PCI.H"
+#include "GX2.H"
+#include "LEGACY.H"
+#include "PROTOS.H"
+
+// Function prototypes:
+extern void Hide_IDE_Hdr(void);
+extern void Hide_Flash_Hdr(void);
+
+
+// External variables:
+extern ULONG MDD_Base;
+extern USHORT Flash_Function, IDE_Function;
+extern UCHAR Flash_Allocated;
+
+
+
+//***********************************************************************
+// Returns non-zero if Flash device is enabled
+//***********************************************************************
+UCHAR FlashIsEnabled(void)
+{ UCHAR Pin;
+
+ Pin = (UCHAR)Read_MSR_LO(MDD_Base + MSR_PIN_OPTS) & PIN_OPT_IDE;
+ Pin ^= PIN_OPT_IDE;
+ return Pin;
+}
+
+
+//***********************************************************************
+// Allocates Flash BARs
+//***********************************************************************
+void Allocate_Flash_BARs(void)
+{ ULONG MsrAddr, MsrData[2], Size;
+ USHORT Bar;
+ UCHAR Resource;
+ static UCHAR Flash_LBARs[4] = {
+ MSR_LBAR_FLSH0,
+ MSR_LBAR_FLSH1,
+ MSR_LBAR_FLSH2,
+ MSR_LBAR_FLSH3,
+ };
+
+
+ // BARs are only to be allocated once
+ if (Flash_Allocated == 0) {
+
+ Flash_Allocated = 1;
+ // Determine type/size of PCI BAR for each Flash device
+ MsrAddr = MDD_Base;
+ for (Bar = BAR0; Bar <= BAR3; Bar += 4) {
+ // Read the Flash LBAR
+ (UCHAR)MsrAddr = Flash_LBARs[(Bar-BAR0)/4];
+ Read_MSR(MsrAddr, MsrData);
+
+ // If LBAR size has not been programmed, then don't configure the PCI BAR
+ Size = MsrData[1] & ~(MEM_IO | NOR_NAND | LBAR_EN);
+ if (Size == 0x00000000) {
+ continue;
+ }
+
+ // MMIO or IO resource
+ if (MsrData[1] & MEM_IO ) {
+ // MMIO mode
+ Size &= LBAR_MEM_MASK;
+ Resource = RESOURCE_MMIO;
+ } else {
+ // IO mode
+ // Required for proper byte count calculation
+ Size |= 0xFFFF0000;
+ Resource = RESOURCE_IO;
+ }
+ // Convert mask to byte count
+ Size = ~Size + 1;
+ // Allocate BAR
+ SYS_ALLOCATE_RESOURCE(Resource, Bar, Size, DEVICE_ID_AMD_FLASH, ID_MDD);
+ }
+ }
+}
+
+
+
+//***********************************************************************
+// Switches between Flash and IDE headers
+//***********************************************************************
+void pascal Flash_IDE_Switch(USHORT Function, ULONG Data)
+{ ULONG PinOptions, PinMsr, FlashMsr, LBar[2], SavedLBar[2];
+
+ // Switch pins to Flash mode
+ PinMsr = MDD_Base + MSR_PIN_OPTS;
+ PinOptions = Read_MSR_LO(PinMsr);
+
+ if (Function == Flash_Function) {
+ // Currently in Flash mode
+
+ // Switching to IDE mode ?
+ if (Data == 0xBEEFDEAD) {
+
+ // Hide the Flash header
+ Hide_Flash_Hdr();
+
+ // Switch pins to IDE mode
+ PinOptions |= PIN_OPT_IDE;
+ Write_MSR_LO(PinMsr, PinOptions);
+
+ // Disconnect the ROM from the DMA pins
+ in_8(0x3F6);
+ }
+
+ } else {
+
+ // Currently in IDE mode
+
+ // Switching to Flash mode ?
+ if (Data == 0xDEADBEEF) {
+
+ // Hide the IDE header
+ Hide_IDE_Hdr();
+
+ // Allocate Flash BARs
+ Allocate_Flash_BARs();
+
+ // Enable Flash mode
+ PinOptions &= ~PIN_OPT_IDE;
+ Write_MSR_LO(PinMsr, PinOptions);
+
+ // Handle Canary circuit
+
+ // Set CS1# to respond to I/O address 22h
+ FlashMsr = MDD_Base + MSR_LBAR_FLSH1;
+ Read_MSR(FlashMsr, SavedLBar);
+ LBar[0] = 0x00000022;
+ LBar[1] = 0x0000FFF0 | LBAR_EN;
+ Write_MSR(FlashMsr, LBar);
+
+ // Turn Canary circuit on
+ in_8(0x22);
+
+ // Restore CS1 LBAR
+ Write_MSR(FlashMsr, SavedLBar);
+ }
+ }
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/header.asm b/cpu/amd/geode_lx/gplvsa_ii/legacy/header.asm
new file mode 100755
index 0000000..d2083c0
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/header.asm
@@ -0,0 +1,53 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+
+;* Function: *
+;* This file contains the VSM header for the legacy VSM
+
+
+.model tiny,c
+.586
+.CODE
+
+ include VSA2.INC
+
+externdef edata:proc
+externdef _end:proc
+externdef VSM_msg_loop:proc
+public VSM_Hdr
+
+
+
+VSM_Hdr:
+ dd VSM_SIGNATURE ; VSM signature
+ db VSM_LEGACY ; VSM type
+ db 0FFh ; Any CPU
+ dw 0FFFFh ; Any Chipset
+ dw 0106h ; VSM version
+ dd OFFSET edata ; Size of VSM module
+ dw OFFSET VSM_msg_loop ; EntryPoint
+ dd OFFSET _end ; DS Limit
+ dw 0000h ; Requirements
+ dw VSA_VERSION ; VSA version
+
+ db sizeof(VSM_Header) - ($-VSM_Hdr) dup (0)
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/ide.c b/cpu/amd/geode_lx/gplvsa_ii/legacy/ide.c
new file mode 100755
index 0000000..9e6d00c
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/ide.c
@@ -0,0 +1,158 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Function: *
+//* This file contains code for power-managing the ATA drives.
+
+
+#include "vsa2.h"
+#include "isa.h"
+
+extern UCHAR pascal in_8(USHORT);
+extern void pascal out_8(USHORT, UCHAR);
+
+
+// NOTE: Win95 touches CD-ROMs every 4.2 seconds for AutoDetect
+
+#define HDD0 1
+#define HDD1 2
+#define HDD2 4
+#define HDD3 8
+
+#define IDE_BSY 0x80 // Status register
+#define IDE_RDY 0x40 // Status register
+#define IDE_MSK IDE_BSY+IDE_RDY
+
+#define IDE_CMD_SPINDOWN 0xE0 // Spindown Command
+#define IDE_CMD_SPINUP 0xE1 // Spinup Command
+#define IDE_CMD_CHECK_POWER_MODE 0xE5 // Get Power Management State Command
+#define IDE_CMD_SLEEP 0xE6
+
+UCHAR DrivesPresent = 0, DrvHd;
+
+
+//*************************************************************************
+// Issues specified command to one or more drive units
+//*************************************************************************
+void pascal IDE_Command(UCHAR DriveUnit, UCHAR Command)
+{ UCHAR DriveSelect, Mask = 1;
+ USHORT IO_Port;
+ ULONG Timeout;
+
+ // Only spindown drives that are present
+ DriveUnit &= DrivesPresent;
+
+ while (DriveUnit) {
+
+ // Is drive present ?
+ if (DriveUnit & Mask) {
+
+ // Yes, determine I/O port
+ IO_Port = PRIMARY_IDE;
+ if (Mask & (HDD2+HDD3)) {
+ IO_Port = SECONDARY_IDE;
+ }
+
+ // Determine master/slave
+ DriveSelect = 0xA0; // Master drive
+ if (Mask & (HDD1+HDD3)) {
+ DriveSelect = 0xB0; // Slave drive
+ }
+
+ // Wait for IDE channel READY
+ for (Timeout=0xFFFFF; Timeout; Timeout--) {
+ if ((IDE_MSK & in_8(IO_Port+1)) == IDE_RDY)
+ break;
+ }
+
+ DrvHd = in_8(IO_Port); // Save Drive/Head register
+
+ out_8(IO_Port, DriveSelect); // Select drive to spin down
+ out_8(IO_Port+1, Command); // Issue command to the the drive
+
+ for (Timeout=0xFFFFF; Timeout; Timeout--) {
+ if (!(in_8(IO_Port+1) & IDE_BSY))
+ break;
+ }
+
+ in_8(IO_Port+1); // Clear IRQ
+
+ DriveUnit &= ~Mask;
+ }
+
+ // Next drive
+ Mask <<= 1;
+ }
+}
+
+//*************************************************************************
+// Spins down specified drive(s)
+//*************************************************************************
+void pascal SpinDownHardDrive(UCHAR DriveUnit)
+{
+ IDE_Command(DriveUnit, IDE_CMD_SPINDOWN);
+}
+
+
+//*************************************************************************
+// Puts drive(s) into sleep mode
+//*************************************************************************
+void pascal DriveSleep(UCHAR DriveUnit)
+{
+// IDE_Command(DriveUnit, IDE_CMD_SLEEP);
+}
+
+//*************************************************************************
+// Determines what hard drives are present
+// Input: I/O address of IDE Drive/Head register
+//*************************************************************************
+UCHAR Check_IDE_Channel(USHORT IDE_DrvHd)
+{ UCHAR HDD_Status, DrivesPresent=0;
+
+ DrvHd = in_8(IDE_DrvHd); // Save Drive/Head register
+
+ out_8(IDE_DrvHd, (UCHAR)(DrvHd & ~0x10)); // Select master drive
+ HDD_Status = in_8(IDE_DrvHd);
+ if (in_8(IDE_DrvHd+1) == 0x50) { // Is drive present ?
+ DrivesPresent |= HDD0;
+
+ out_8(IDE_DrvHd, (UCHAR)(DrvHd | 0x10)); // Select slave drive
+ HDD_Status = in_8(IDE_DrvHd);
+ if (in_8(IDE_DrvHd+1) == 0x50) { // Is drive present ?
+ DrivesPresent |= HDD1;
+ }
+ }
+
+ // Restore Drive/Head register
+ out_8(IDE_DrvHd, DrvHd);
+ return DrivesPresent;
+}
+
+
+//*************************************************************************
+// Determines what hard drives are present
+// Input: I/O address of IDE Drive/Head register
+//*************************************************************************
+UCHAR GetDrivesPresent(void)
+{
+ DrivesPresent = Check_IDE_Channel(PRIMARY_IDE);
+ DrivesPresent |= Check_IDE_Channel(SECONDARY_IDE) << 2;
+
+ return DrivesPresent;
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/init.c b/cpu/amd/geode_lx/gplvsa_ii/legacy/init.c
new file mode 100755
index 0000000..8d00d5b
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/init.c
@@ -0,0 +1,83 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//*****************************************************************************
+//* This file performs Legacy VSM initialization.
+//*****************************************************************************
+
+
+
+
+#include "vsa2.h"
+#include "chipset.h"
+#include "sysmgr.h"
+#include "vr.h"
+
+
+
+// External variables:
+extern Hardware SystemInfo;
+
+// Function prototypes:
+extern void pascal out_8(USHORT, UCHAR);
+extern void CS5536_Early_Init(void);
+extern void CS5536_Late_Init(void);
+extern void Init_OHCI_SWAPSiF(UCHAR);
+
+
+
+
+//***********************************************************************
+// Performs early initialization
+//***********************************************************************
+void Legacy_Early_Init(void)
+{
+
+ // Register for VRC_SYSINFO virtual registers
+ SYS_REGISTER_EVENT(EVENT_VIRTUAL_REGISTER, VRC_SYSINFO, 0, NORMAL_PRIORITY);
+
+
+ switch (SystemInfo.Chipset_ID) {
+
+ case DEVICE_ID_5536:
+ CS5536_Early_Init();
+ break;
+ }
+}
+
+
+
+//***********************************************************************
+// Performs End-of-POST initialization
+//***********************************************************************
+void Legacy_Late_Init(void)
+{
+
+ switch (SystemInfo.Chipset_ID) {
+
+ case DEVICE_ID_5536:
+ CS5536_Late_Init();
+ break;
+ }
+
+ // Initialize A20 to '1MB wrap'
+ // SDG - removed for OLPC
+ // out_8(0x92, 0);
+
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/legacy.c b/cpu/amd/geode_lx/gplvsa_ii/legacy/legacy.c
new file mode 100755
index 0000000..cf3f869
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/legacy.c
@@ -0,0 +1,92 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Function: *
+//* This file implements miscellaneous VSA functionality: *
+//* *
+//* All chipsets: *
+//* 1) SYSINFO virtual registers *
+//* *
+//* CS5536 : *
+//* 1) Emulation of CS5530 PCI interrupt steering registers. *
+//* 2) Flash-IDE switching *
+//* 3) Power management *
+
+
+#include "vsa2.h"
+#include "chipset.h"
+#include "protos.h"
+
+// Function prototypes
+extern void Legacy_Early_Init(void);
+extern void Legacy_Late_Init(void);
+extern void Handle_Events(ULONG *);
+
+
+// Local variables
+Hardware SystemInfo;
+ULONG ChipsetBase;
+ULONG Param[MAX_MSG_PARAM];
+
+
+
+//***********************************************************************
+// Message handler for the Legacy VSM
+//***********************************************************************
+void VSM_msg_loop()
+{ MSG Msg;
+
+ // Get information about the system I'm executing on.
+ SYS_GET_SYSTEM_INFO(&SystemInfo);
+ ChipsetBase = SystemInfo.Chipset_Base;
+
+ //
+ // Message Handling Loop
+ //
+ do {
+
+ // Get the next message
+ Msg = SYS_GET_NEXT_MSG(&Param);
+
+ switch (Msg) {
+
+ case MSG_INITIALIZE:
+ switch (Param[0]) {
+ case EARLY_INIT:
+ Legacy_Early_Init();
+ break;
+
+ case END_OF_POST_INIT:
+ Legacy_Late_Init();
+ break;
+ }
+ break;
+
+ case MSG_EVENT:
+ Handle_Events(Param);
+ break;
+
+ case MSG_SET_POWER_MODE:
+ case MSG_SET_POWER_STATE:
+ case MSG_SAVE_STATE:
+ case MSG_RESTORE_STATE:
+ break;
+ } // end switch(Msg)
+ } while (1);
+} \ No newline at end of file
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/legacy.h b/cpu/amd/geode_lx/gplvsa_ii/legacy/legacy.h
new file mode 100755
index 0000000..cbabf30
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/legacy.h
@@ -0,0 +1,37 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+#define SYS_DMA_DRIVER 0x5006
+#define MASTER_IDE 0x8000
+
+
+
+// Default GPIOs for PCI interrupts on the Hawk reference design
+#define INTA_PIN 0
+#define INTB_PIN 7
+#define INTC_PIN 12
+#define INTD_PIN 13
+
+
+
+#define USBF_PERIOD 2000 // 2 seconds
+#define USBF_HANDLE 0x3333
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/makefile b/cpu/amd/geode_lx/gplvsa_ii/legacy/makefile
new file mode 100755
index 0000000..c3d8391
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/makefile
@@ -0,0 +1,165 @@
+#
+# Copyright (c) 2006 Advanced Micro Devices,Inc. ("AMD").
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# This code is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General
+# Public License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA
+#
+#
+######################################################################
+#
+# Init variables
+#
+######################################################################
+.SUFFIXES: .asm .c .h .inc .map .obj .mac
+
+!ifndef VSA2ROOT
+VSA2ROOT = ..
+!endif
+
+BUILD_DIR = $(VSA2ROOT)\build
+OBJECT = obj
+!include $(BUILD_DIR)\setvars.mak
+
+INCLUDE = $(OBJECT);$(INCLUDE)
+
+VSMNAME = legacy
+
+
+######################################################################
+#
+# Build Macros
+#
+######################################################################
+
+LEGACY_ASM_OBJS = \
+ $(OBJECT)\header.obj \
+ $(OBJECT)\msr.obj \
+
+LEGACY_C_OBJS = \
+ $(OBJECT)\legacy.obj \
+ $(OBJECT)\init.obj \
+ $(OBJECT)\events.obj \
+ $(OBJECT)\flash.obj \
+ $(OBJECT)\cs5536.obj \
+ $(OBJECT)\ide.obj \
+ $(OBJECT)\blockio.obj \
+ $(OBJECT)\uarts.obj \
+ $(OBJECT)\virtregs.obj \
+ $(OBJECT)\swapsif.obj \
+ $(OBJECT)\sysinfo.obj \
+
+LEGACY_LNK_OBJS = \
+ header.obj \
+ legacy.obj \
+ msr.obj \
+ init.obj \
+ events.obj \
+ flash.obj \
+ cs5536.obj \
+ ide.obj \
+ blockio.obj \
+ uarts.obj \
+ virtregs.obj \
+ swapsif.obj \
+ sysinfo.obj \
+
+
+LEGACY_OBJS = $(LEGACY_ASM_OBJS) $(LEGACY_C_OBJS)
+LEGACY_VSM = legacy.vsm
+
+#######################################################################
+#
+# Targets
+#
+#######################################################################
+
+all: $(OBJECT) setenv legacy.vsm
+ $(COPY) $(LEGACY_VSM) $(BUILDOBJ)
+
+legacy.vsm: $(LEGACY_OBJS)
+ cd $(OBJECT)
+ $(LN) $(LOPTS_VSM) $(LEGACY_LNK_OBJS), ..\$(LEGACY_VSM),, ..\..\build\obj\$(TOOL_LIB);
+ cd ..
+
+#This and only this clean target must exist as it is called by cleanall
+#cleanall and cleanlocal are defined in rules.mak
+
+clean: cleanlocal cleanlib
+
+$(OBJECT):
+ -@md $(OBJECT)
+
+#######################################################################
+#
+# Dependencies
+#
+#######################################################################
+
+$(LEGACY_ASM_OBJS): $(MAKEDIR)\makefile \
+ $(OBJECT)\sysmgr.inc \
+ $(OBJECT)\smimac.mac \
+ $(OBJECT)\vsa2.inc \
+ $(OBJECT)\isa.inc \
+ $(OBJECT)\chipset.inc \
+ $(OBJECT)\vr.inc \
+ $(OBJECT)\pci.inc \
+ $(OBJECT)\acpi.inc \
+ $(OBJECT)\gx2.inc \
+ $(OBJECT)\cs5536.inc \
+ $(OBJECT)\pci.inc \
+ $(OBJECT)\mdd.inc \
+
+$(LEGACY_C_OBJS): $(MAKEDIR)\makefile \
+ $(BUILD_DIR)\obj\$(TOOL_LIB) \
+ $(OBJECT)\sysmgr.h \
+ $(OBJECT)\vsa2.h \
+ $(OBJECT)\isa.h \
+ $(OBJECT)\chipset.h \
+ $(OBJECT)\vr.h \
+ $(OBJECT)\pci.h \
+ $(OBJECT)\legacy.h \
+ $(OBJECT)\mapper.h \
+ $(OBJECT)\protos.h \
+ $(OBJECT)\mdd.h \
+ $(OBJECT)\acpi.h \
+ $(OBJECT)\gx2.h \
+ $(OBJECT)\cs5536.h \
+
+######################################################################
+#
+# Common Targets
+#
+######################################################################
+# include common targets and inference rules
+!include $(BUILD_DIR)\rules.mak
+
+######################################################################
+#
+# Inference Rules
+#
+######################################################################
+# Override common inference rules here
+
+{$(INC_DIR)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zni /C $<
+
+{$(INC_DIR)\$(CPU)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zni /C $<
+
+{$(SYSMGR_SRC)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zns /C $<
+
+{$(SYSMGR_SRC)\$(CPU)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zns /C $<
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/msr.asm b/cpu/amd/geode_lx/gplvsa_ii/legacy/msr.asm
new file mode 100755
index 0000000..a70c3d2
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/msr.asm
@@ -0,0 +1,97 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+
+.model tiny,c
+.586p
+.CODE
+
+;***********************************************************************
+; Returns the low DWORD of an MSR.
+; Usage: LowMsrValue = Read_MSR_LO(Msr_Address);
+;***********************************************************************
+Read_MSR_LO proc pascal \
+ Msr: dword
+
+ mov ecx, [Msr]
+ rdmsr
+ mov edx, eax
+ shr edx, 16
+ ret
+
+Read_MSR_LO endp
+
+;***********************************************************************
+; Writes the low DWORD of an MSR. The high DWORD is preserved.
+; Usage: Write_MSR_LO(Msr_Address, Data);
+;***********************************************************************
+Write_MSR_LO proc pascal \
+ Msr: dword, \
+ Data: dword
+
+ mov ecx, [Msr]
+ rdmsr ; Get high 32 bits
+ mov eax, [Data]
+ wrmsr
+ ret
+
+Write_MSR_LO endp
+
+
+
+;***********************************************************************
+; Returns an MSR value in a buffer.
+; Usage: Read_MSR(ULONG Msr, ULONG * Buffer);
+;***********************************************************************
+Read_MSR proc pascal \
+ Msr: dword, \
+ Buffer: PTR
+
+ mov ecx, [Msr]
+ rdmsr
+
+ mov bx, [Buffer]
+ mov [bx+0], eax
+ mov [bx+4], edx
+ ret
+
+Read_MSR endp
+
+
+;***********************************************************************
+; Writes an MSR.
+; Usage: Write_MSR(ULONG Msr, ULONG * Buffer);
+;***********************************************************************
+Write_MSR proc pascal \
+ Msr: dword, \
+ Buffer: PTR
+
+ mov ecx, [Msr]
+ mov bx, [Buffer]
+ mov eax, [bx+0]
+ mov edx, [bx+4]
+ wrmsr
+ ret
+
+Write_MSR endp
+
+
+ END
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/swapsif.c b/cpu/amd/geode_lx/gplvsa_ii/legacy/swapsif.c
new file mode 100755
index 0000000..93ad8dc
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/swapsif.c
@@ -0,0 +1,130 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* This file contains SWAPSiFs
+//******************************************************************************
+
+
+
+#include "vsa2.h"
+#include "protos.h"
+#include "chipset.h"
+#include "legacy.h"
+#include "pci.h"
+
+
+// External variables
+extern Hardware SystemInfo;
+
+// Local variables
+ULONG OHCI_Address[2];
+UCHAR WinCE_Flag = 1;
+
+
+//*****************************************************************
+// Fixes 118.438 - OHCI May Not Recognize Device Attach/Removal
+//*****************************************************************
+void pascal OHCI_SWAPSiF(UCHAR Flag)
+{ PRIORITY Priority = 0;
+ static PRIORITY LastPriority = 0x5555;
+
+ switch (SystemInfo.Chipset_ID) {
+ case DEVICE_ID_5536:
+ break;
+
+ default:
+ if (Flag == 0) {
+ Priority = UNREGISTER_PRIORITY;
+ }
+ if (Priority != LastPriority) {
+ LastPriority = Priority;
+ SYS_REGISTER_EVENT(EVENT_TIMER, USBF_PERIOD, USBF_HANDLE, Priority);
+ }
+ break;
+ }
+}
+
+
+#define HcControl 0x0004
+ #define HCFS 0x000000C0L
+ #define USB_RESET 0x00000000L
+ #define USB_RESUME 0x00000040L
+ #define USB_OPERATIONAL 0x00000080L
+ #define USB_SUSPEND 0x000000C0L
+ #define IR 0x00000100L
+#define HceControl 0x0100
+
+//***********************************************************************
+void Do_OHCI_SWAPSif(void)
+{ ULONG i, PCI_Addr, HC_Addr, OldValue;
+
+ for (i=0; i<=1; i++) {
+
+ // Get base of Host Controller's registers
+ HC_Addr = OHCI_Address[i];
+
+ // Ignore this tick if BAR is being sized
+ if (HC_Addr == 0xFFFFF000 || HC_Addr == 0x00000000) {
+ continue;
+ }
+
+ // Check if Host Controller registers are accessible
+ PCI_Addr = 0x80007C00L + (i<<8);
+ if (READ_PCI_BYTE(PCI_Addr + COMMAND) & MEM_SPACE) {
+
+ OldValue = READ_MEMORY(HC_Addr + HcControl);
+
+ // WinCE doesn't perform a valid Ownership Change.
+ // It disables MIE then performs the Ownership Change request.
+ // This code detects that situation and turns emulation off.
+ // Otherwise, neither the USB keyboard or PS/2 keyboard works.
+ if ((i == 0) && (OldValue & IR) == 0 && WinCE_Flag) {
+ WinCE_Flag = 0; // Only do this once
+ WRITE_MEMORY(HC_Addr + HceControl, 0x00);
+ }
+
+ // Transition through Operational to clear possible attach/detach glitch
+ if ((OldValue & USB_SUSPEND) == USB_SUSPEND) {
+ WRITE_MEMORY(HC_Addr + HcControl, USB_OPERATIONAL);
+ WRITE_MEMORY(HC_Addr + HcControl, OldValue);
+ }
+ }
+ }
+}
+
+
+
+//***********************************************************************
+// Initialization for the OHCI attach/detach hardware bug
+//***********************************************************************
+void Init_OHCI_SWAPSiF(UCHAR InitStage)
+{
+ switch (InitStage) {
+ case EARLY_INIT:
+ // Trap writes to SB F4 & F5 BAR0 in order keep current OHCI BAR values
+ SYS_REGISTER_EVENT(EVENT_PCI_TRAP, 0x7C10, WRITES_ONLY | 0x100, 0);
+ break;
+
+ case END_OF_POST_INIT:
+ // Turn on the timer
+ OHCI_SWAPSiF(1);
+ break;
+ }
+} \ No newline at end of file
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/sysinfo.c b/cpu/amd/geode_lx/gplvsa_ii/legacy/sysinfo.c
new file mode 100755
index 0000000..0cd7843
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/sysinfo.c
@@ -0,0 +1,78 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Function: *
+//* This file implementes the SYSINFO virtual registers.
+
+#include "vsa2.h"
+#include "vr.h"
+
+void pascal Hex_8(UCHAR);
+void pascal Hex_16(USHORT);
+void pascal Hex_32(ULONG);
+
+
+// Local variables
+extern Hardware SystemInfo;
+
+
+void Handle_SysInfo_VR(UCHAR i)
+{ USHORT Data;
+
+
+ switch (i) {
+ case VRC_SI_VERSION:
+ Data = 0x100; // Version 1.0
+ break;
+
+ case VRC_SI_CPU_MHZ:
+ Data = SystemInfo.CPU_MHz;
+ break;
+
+ case VRC_SI_CHIPSET_BASE_LOW:
+ Data = (USHORT) SystemInfo.Chipset_Base;
+ break;
+
+ case VRC_SI_CHIPSET_BASE_HI:
+ Data = (USHORT) (SystemInfo.Chipset_Base >> 16);
+ break;
+
+ case VRC_SI_CHIPSET_ID:
+ Data = SystemInfo.Chipset_ID;
+ break;
+
+ case VRC_SI_CHIPSET_REV:
+ Data = SystemInfo.Chipset_Rev;
+ break;
+
+ case VRC_SI_CPU_ID:
+ Data = SystemInfo.CPU_ID;
+ break;
+
+ case VRC_SI_CPU_REV:
+ Data = SystemInfo.CPU_Revision;
+ break;
+
+ default:
+ Data = 0xFFFF;
+ break;
+ }
+
+ SET_AX(Data);
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/uarts.c b/cpu/amd/geode_lx/gplvsa_ii/legacy/uarts.c
new file mode 100755
index 0000000..d04be7b
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/uarts.c
@@ -0,0 +1,210 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+//* Function: *
+//* This file contains routines specific to the CS5536 UARTs.
+
+#include "vsa2.h"
+#include "vr.h"
+#include "mdd.h"
+#include "protos.h"
+
+
+// Function prototypes:
+void Handle_5536_UART(UCHAR, UCHAR, USHORT);
+USHORT Get_5536_UART(USHORT);
+void Prog_5536_UART(USHORT, USHORT);
+
+// External variables:
+extern ULONG MDD_Base;
+extern USHORT gpio_base;
+
+
+// 5536 implements two UART's. The resources for both are controlled
+// by MDD MSR_LEG_IO, MSR_IRQM_YHIGH.
+// IRQ Enable, Clock freeze and soft reset controlled by MSR_UARTx_CONF
+//
+// One Virtual Register is implemented for each UART.
+// bit15 = 1 Soft-Reset
+// bits[14:13] = unused
+// bit12 = 1 UART GPIO's have been setup by BIOS, RO bit
+// bit11 = 1 enable UART I/O space extended register banks
+// bit10 = 1 enable test mode
+// bit9 = 1 Freeze device clocks, IRQ still enabled
+// bit8 = 1 enable interrupt & functionality, doesn't affect I/O
+// bits[7:4] = IRQ number
+// bit3 = unused
+// bit2 = 1 I/O decode enabled
+// bits[1:0] = I/O location
+//
+void Handle_5536_UART(UCHAR vrIndex, UCHAR wFlag, USHORT wData)
+{
+ if (wFlag) { // write
+ Prog_5536_UART(vrIndex, wData);
+ } else {
+ SYS_RETURN_RESULT((ULONG)Get_5536_UART(vrIndex));
+ }
+}
+
+USHORT Get_5536_UART(USHORT vri)
+{
+ ULONG d;
+ USHORT u;
+
+ u = 0;
+
+ (USHORT)MDD_Base = MSR_LEG_IO;
+ d = Read_MSR_LO(MDD_Base);
+ switch (vri) {
+ case VRC_CS_UART1:
+ d >>= UART1_SHIFT;
+ break;
+
+ case VRC_CS_UART2:
+ d >>= UART2_SHIFT;
+ break;
+
+ default:
+ return 0;
+ }
+
+ u = (USHORT)d & UART_MASK;
+
+ // get the IRQ number
+ (USHORT)MDD_Base = MSR_IRQM_YHIGH;
+ d = Read_MSR_LO(MDD_Base);
+ if (vri == VRC_CS_UART1) {
+ d >>= 20;
+ } else {
+ d >>= 24;
+ }
+ u |= ((USHORT)d & 0x00F0);
+
+ // fill in the other flags from MSR_UARTx_CONF
+ if (vri == VRC_CS_UART1) {
+ (USHORT)MDD_Base = MSR_UART1_CONF;
+ } else {
+ (USHORT)MDD_Base = MSR_UART2_CONF;
+ }
+ d = Read_MSR_LO(MDD_Base);
+ // MSR bit0 = soft-reset -> bit15
+ // MSR bit1 = deven -> bit8
+ // MSR bit2 = freeze -> bit9
+ // MSR bit3 = test mode -> bit10
+ // MSR bit4 = upper banks -> bit11
+ if ((USHORT)d & 0x0001) {
+ u |= 0x8000;
+ }
+ d <<= 7;
+ u |= ((USHORT)d & 0x0F00);
+
+ // check if GPIO's for this UART have been setup
+ // This is used as an indicator the UART is 'hidden' from OS
+ d = in_32(gpio_base + GPIO_IN_AUX1_SELECT);
+ if (vri == VRC_CS_UART1) {
+ // UART1 GPIO9 should be IN_AUX
+ if (d & 0x0200L) {
+ u |= 0x1000; // set bit12
+ }
+ } else {
+ // UART2 GPIO3 should be IN_AUX
+ if (d & 0x0008L) {
+ u |= 0x1000; // set bit12
+ }
+ }
+
+ return u;
+}
+
+
+void Prog_5536_UART(USHORT vri, USHORT vrval)
+{
+ ULONG d, r;
+ USHORT curval, uartmsr, shift, irqshift;
+
+ r = 0L;
+
+ // clear reserved/unused bits
+ vrval &= 0x8FF7;
+
+ switch (vri) {
+ case VRC_CS_UART1:
+ uartmsr = MSR_UART1_CONF;
+ shift = UART1_SHIFT;
+ irqshift = 24;
+ break;
+
+ case VRC_CS_UART2:
+ uartmsr = MSR_UART2_CONF;
+ shift = UART2_SHIFT;
+ irqshift = 28;
+ break;
+
+ default:
+ return;
+ }
+
+ // get current settings
+ curval = Get_5536_UART(vri);
+
+ // change?
+ if (curval ^ vrval) { // Yes
+ // I/O change?
+ if ((curval & 0x0007) ^ (vrval & 0x0007)) {
+ // Program I/O
+ (USHORT)MDD_Base = MSR_LEG_IO;
+ d = Read_MSR_LO(MDD_Base);
+ // don't trust C compiler when expanding a 'define' to
+ // long unless 'define' is a long constant.
+ (USHORT)r = UART_MASK;
+ d &= ~(r << shift);
+ d |= ((ULONG)(vrval & 0x0007)) << shift;
+ Write_MSR_LO(MDD_Base, d);
+ }
+
+ // IRQ change?
+ if ((curval & 0x00F0) ^ (vrval & 0x00F0)) {
+ // Program IRQ
+ (USHORT)MDD_Base = MSR_IRQM_YHIGH;
+ d = Read_MSR_LO(MDD_Base);
+ d &= ~(0x0FL << irqshift);
+ d |= ((ULONG)(vrval & 0x00F0)) << (irqshift-4);
+ Write_MSR_LO(MDD_Base, d);
+ }
+
+ // control bit(s) changed?
+ if ((curval & 0x8F00) ^ (vrval & 0x8F00)) {
+ // Program control bits in MSR_UARTx_CONF
+ // bits[11:8] of vr map to bits[4:1] of MSR
+ // bit[15] of vr maps to bit[0] of MSR
+ (USHORT)MDD_Base = uartmsr;
+ d = Read_MSR_LO(MDD_Base);
+ // clear bits[4:0]
+ d &= ~(0x1FL);
+ (USHORT)d |= ((vrval & 0x0F00) >> 7);
+ if (vrval & 0x8000) {
+ (USHORT)d |= 0x0001;
+ }
+ Write_MSR_LO(MDD_Base, d);
+ }
+ }
+
+}
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/legacy/virtregs.c b/cpu/amd/geode_lx/gplvsa_ii/legacy/virtregs.c
new file mode 100755
index 0000000..04ee363
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/legacy/virtregs.c
@@ -0,0 +1,131 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Function: *
+//* This file handles virtual registers.
+
+#include "vsa2.h"
+#include "chipset.h"
+#include "vr.h"
+#include "protos.h"
+#include "acpi.h"
+
+extern void Handle_Misc_VR(UCHAR, USHORT);
+extern void Handle_SysInfo_VR(UCHAR);
+extern void Handle_5536_UART(UCHAR, UCHAR, USHORT);
+
+extern USHORT PCI_Int_AB, PCI_Int_CD;
+extern USHORT DiskTimeout, SerialTimeout, ParallelTimeout, FloppyTimeout;
+USHORT WatchDogDelay;
+
+void Handle_VirtualRegs(UCHAR Class, UCHAR Index, UCHAR WrFlag, USHORT Data)
+{
+ ULONG Param[MAX_MSG_PARAM]; // Select on virtual register class
+ switch (Class) {
+
+ case VRC_MISCELLANEOUS:
+ if (WrFlag) {
+ if (Index == WATCHDOG) {
+ static ULONG WatchDogKey=0;
+ ULONG Key;
+
+ Key = GET_REGISTER(R_ECX);
+ if (WatchDogKey) {
+ // The key has already been set...check it
+ if (WatchDogKey != Key) {
+/*MEJ // Broadcast to all VSM's
+ Param[0] = S5_STATE;
+ Param[1] = CLASS_ALL;
+ SYS_BROADCAST_MSG(MSG_SET_POWER_STATE, &Param[0], VSM_ANY);
+*/
+ }
+ } else {
+ // Set the key (only once)
+ WatchDogKey = Key;
+ }
+ WatchDogDelay = Data;
+ SYS_REGISTER_EVENT(EVENT_TIMER, WatchDogDelay*1000L, ONE_SHOT, 0);
+ break;
+ }
+ Handle_Misc_VR(Index, Data);
+ } else {
+ switch (Index) {
+ case PCI_INT_AB:
+ SET_AX(PCI_Int_AB);
+ break;
+
+ case PCI_INT_CD:
+ SET_AX(PCI_Int_CD);
+ break;
+
+ case WATCHDOG:
+ SET_AX(WatchDogDelay);
+ break;
+ }
+ }
+ break;
+
+ case VRC_PM:
+ // Ignore READs
+ if (WrFlag) {
+/*MEJ switch (Index) {
+ case DISK_TIMEOUT:
+ DiskTimeout = Data;
+ break;
+
+ case SERIAL_TIMEOUT:
+ SerialTimeout = Data;
+ break;
+
+ case PARALLEL_TIMEOUT:
+ ParallelTimeout = Data;
+ break;
+
+ case FLOPPY_TIMEOUT:
+ FloppyTimeout = Data;
+ break;
+ }
+*/
+ }
+ break;
+
+ case VRC_SYSINFO:
+ if (!WrFlag) {
+ Handle_SysInfo_VR(Index);
+ }
+ break;
+
+
+ case VRC_CHIPSET:
+ switch (Index) {
+ case VRC_CS_UART1:
+ case VRC_CS_UART2:
+ Handle_5536_UART(Index, WrFlag, Data);
+ break;
+
+ }
+ break;
+ }
+}
+
+
+
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/lxvg/decode.c b/cpu/amd/geode_lx/gplvsa_ii/lxvg/decode.c
new file mode 100755
index 0000000..5fa8918
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/lxvg/decode.c
@@ -0,0 +1,194 @@
+/*
+* Copyright (c) 2007-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+// This module decodes the SoftVG SMI sources.
+
+
+#include "lxvg.h"
+#include "vsa2.h"
+#include "vr.h"
+#include "pci.h"
+
+extern void pascal out_8(USHORT, UCHAR);
+extern void pascal out_16(USHORT, USHORT);
+extern UCHAR pascal in_8(USHORT);
+extern USHORT pascal in_16(USHORT);
+
+//---------------------------------------------------------------------------
+// virtual_register_event
+//
+// This routine is called when LXVG receives a VRC_VG virtual register
+// access event.
+//
+//---------------------------------------------------------------------------
+
+void virtual_register_event(unsigned char reg, unsigned long rwFlag, unsigned long vrData)
+{
+
+ // Look for virtual register read case first
+ if (!(rwFlag & SMM_VR_WRITE))
+ {
+ // Determine if we are initialized
+ if (!(VGState & SF_SECONDARY))
+ {
+ SET_AX(0xFFFF);
+ }else{
+ SET_AX(vReg[reg]);
+ }
+ return;
+ }
+
+ // If we get here, we know its a write, so handle the requests
+ switch (reg)
+ {
+ case VG_CONFIG:
+ // We only need to initialize once!
+ if (!(VGState & SF_SECONDARY))
+ {
+ // Initialize the secondary controller portion of the engine.
+ lxvg_initialize((unsigned short)vrData);
+
+ // REGISTER PCI EVENTS - DO NOT ENABLE PCI EVENTS IF DISABLED.
+
+ if (VGState & SF_SECONDARY)
+ {
+ // If we've initialized to the secondary state, we need to support
+ // PCI config accesses. If we are disabled, the SysMgr will handle
+ // the support. We may be initialized to the primary state, but the
+ // minimum level is secondary.
+ SYS_REGISTER_EVENT(EVENT_PCI_TRAP, vga_config_addr, 0xFF, NORMAL_PRIORITY);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // Finally, store the data...
+ vReg[reg] = (unsigned short)vrData;
+
+ return;
+}
+
+//---------------------------------------------------------------------------
+// pci_trap_event
+//
+// This routine is called when the VSA2 system manager receives an SMI for
+// a PCI configuration cycle that we have registered for.
+//
+// The "flags" parameter indicates the size in bits [3:0] (0x1 = byte,
+// 0x3 = word, and 0xF = dword). Bit 7 indicates a write.
+//---------------------------------------------------------------------------
+
+void pci_trap_event(unsigned long address, unsigned long flags, unsigned long data)
+{
+ unsigned char reg = (unsigned char) address & 0x000000FF;
+ unsigned char size = (unsigned char) flags & 0x0000000F;
+ unsigned long pciSave;
+
+ if ((address & PCI_CONFIG_MASK) == vga_config_addr)
+ {
+
+ // CHECK IF PCI WRITE
+ if (flags & PCI_TRAP_WRITE)
+ {
+ // Handle the trapped register writes
+ if (reg == PCI_CMD_REG)
+ {
+ if ((unsigned char)data & PCI_MEM_SPACE)
+ // Change the frame buffer base realated stuff.
+ hw_fb_map_init(framebuffer_base);
+ }
+ else if ((reg >= BAR0) && (reg <= BAR4))
+ {
+ // NOTE: SysMgr now delivers DWORD aligned values with all reserved bits zeroed.
+ if ((data < VGdata.pci_fb_mask) && (data != 0L))
+ {
+ // We have to assume that the changing agent won't put the framebuffer
+ // on top of program memory. The check for zero above was added when
+ // Windows was observed clearing out the BARS by writing 0's to them.
+ // This is still susceptible to failure due to bad address choices by
+ // the changing agent.
+ switch (reg)
+ {
+ case BAR0:
+ if ((data != framebuffer_base) && (data >= 0x1000000))
+ {
+ // Set the frame buffer base.
+ framebuffer_base = data;
+
+ // If the PCI memory is on, change the framebuffer base
+ // related stuff.
+ pciSave = READ_PCI_DWORD_NO_TRAP(PCI_CMD_REG);
+ if (pciSave & PCI_MEM_SPACE)
+ // Change the frame buffer base realated stuff.
+ hw_fb_map_init(framebuffer_base);
+ }
+ break;
+
+ case BAR1:
+ // Set the GP register base
+ GPregister_base = data;
+ break;
+
+ case BAR2:
+ // Set the VG register base
+ VGregister_base = data;
+ break;
+
+ case BAR3:
+ // Set the DF register base
+ DFregister_base = data;
+ break;
+
+ case BAR4:
+ // Set the VIP register base
+ VIPregister_base = data;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Always mask off the invalid bits, but preserve the
+ // bottom 4 bits.
+ if (size == DWORD_IO)
+ {
+ pciSave = GET_EAX();
+ switch (reg)
+ {
+ case BAR0:
+ pciSave &= VGdata.pci_fb_mask | 0x0000000F;
+ break;
+
+ case BAR1:
+ case BAR2:
+ case BAR3:
+ case BAR4:
+ pciSave &= MASK16K;
+ break;
+ }
+ SET_EAX(pciSave);
+ }
+ }
+ }
+}
+
+// END OF FILE
diff --git a/cpu/amd/geode_lx/gplvsa_ii/lxvg/init.c b/cpu/amd/geode_lx/gplvsa_ii/lxvg/init.c
new file mode 100755
index 0000000..ad00a0a
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/lxvg/init.c
@@ -0,0 +1,74 @@
+/*
+* Copyright (c) 2007-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+// This module performs LXVG initialization.
+
+
+#include "lxvg.h"
+#include "vsa2.h"
+#include "pci.h"
+#include "vr.h"
+
+
+//---------------------------------------------------------------------------
+// lxvg_initialize
+//
+// This routine initializes LXVG. This is the routine called when
+// VG_CONFIG virtual register is written the first time.
+//---------------------------------------------------------------------------
+
+void lxvg_initialize(unsigned short init_parms)
+{
+ int index;
+ unsigned char *ptr;
+
+ // CLEAR THE ENTIRE LXVG DATA STRUCTURE TO ZERO - This is a tedious loop
+
+ ptr = (unsigned char *) &VGdata;
+ for (index = 0; index < sizeof(VGdata); index++)
+ *ptr++ = 0;
+
+ // Start with virtual registers = 0
+ for (index = 0; index < MAX_VG+1; index++)
+ {
+ if (index != VG_CONFIG)
+ {
+ vReg[index] = 0;
+ }
+ }
+
+ // DEVICE DEPENDENT INITIALIZATION
+ // -------------------------------
+ // This MUST be done first. The routine handles all of the MBUS related
+ // initialization and determines various register and base address values
+ // that get used during later initialization.
+ hw_initialize(init_parms);
+
+ // If we haven't initialized because of error, just leave...
+ if (VGState & SF_DISABLED) return;
+
+
+ // LXVG is operating strictly as a secondary controller
+ VGState |= SF_DRIVER_ENABLED;
+
+ // Disable the graphics system in the PCI header command register
+ WRITE_PCI_BYTE(vga_config_addr+0x04, 0);
+ return;
+}
+
+// END OF FILE
diff --git a/cpu/amd/geode_lx/gplvsa_ii/lxvg/lxhwctl.c b/cpu/amd/geode_lx/gplvsa_ii/lxvg/lxhwctl.c
new file mode 100755
index 0000000..3b5ab6e
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/lxvg/lxhwctl.c
@@ -0,0 +1,298 @@
+/*
+* Copyright (c) 2007-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+// This module contains the routines that access the LX hardware.
+
+
+#include "lxvg.h"
+#include "vsa2.h"
+#include "vr.h"
+#include "pci.h"
+
+// This is required here because of inclusion problems in LXVG.h
+extern Hardware SystemInfo;
+
+
+//---------------------------------------------------------------------------
+// hw_initialize
+//
+// This routine performs the device dependent initialization.
+//---------------------------------------------------------------------------
+
+void hw_initialize(unsigned short config)
+{
+ unsigned long base,tbase;
+ struct mValue mVal;
+ unsigned short i;
+
+ // Find the list of devices so we can get to their MSRs. If any one
+ // device is missing, bail out because we don't know how to handle
+ // partial systems.
+
+ if (FALSE == msrInit())
+ {
+ VGState = SF_DISABLED;
+ return;
+ }
+
+
+ // Initialize the MSRs for the graphics processor
+ hw_gp_msr_init();
+
+ // Initialize the MSRs for the video generator
+ hw_vg_msr_init();
+
+ // Initialize the MSRs for the display filter
+ hw_df_msr_init();
+
+ // Initialize the MSRs for the display filter
+ hw_vip_msr_init();
+
+ // Initialize the DOT PLL MSR in the MCP
+ hw_mcp_msr_init();
+
+ // Compute graphics memory requirement from config. The following strips
+ // off the PLL bypass bit and shifts the number of 1MB hunks up
+ // to the point where it is a size in bytes. Base is used as a temp.
+ base = (unsigned long)(config & MEM_SIZE_MASK) << 20;
+
+ // Now compute the memory size mask we will use when we return the contents of
+ // BAR0
+ VGdata.pci_fb_mask = 0;
+ tbase = base;
+ for (i=0;i<32,tbase!=0L;i++)
+ {
+ VGdata.pci_fb_mask |= (1L << i);
+ tbase = tbase >> 1;
+ }
+ VGdata.pci_fb_mask = ~(VGdata.pci_fb_mask);
+
+ // ALLOCATE DESCRIPTORS
+ vga_config_addr = SYS_ALLOCATE_RESOURCE(RESOURCE_MEMORY, BAR0, base, PCI_DEV_ID, ID_MC); // Graphics memory
+ SYS_ALLOCATE_RESOURCE(RESOURCE_MMIO, BAR1, SIZE16K, PCI_DEV_ID, ID_GP); // GP registers
+ SYS_ALLOCATE_RESOURCE(RESOURCE_MMIO, BAR2, SIZE16K, PCI_DEV_ID, ID_VG); // VG registers
+ SYS_ALLOCATE_RESOURCE(RESOURCE_MMIO, BAR3, SIZE16K, PCI_DEV_ID, ID_DF); // DF registers
+ SYS_ALLOCATE_RESOURCE(RESOURCE_MMIO, BAR4, SIZE16K, PCI_DEV_ID, ID_VIP); // VIP registers
+
+ // Modify vga_config_addr to point to the beginning of the header, because all the accesses
+ // to the header are based on the beginning of the header rather than BAR0.
+ vga_config_addr -= BAR0;
+
+ // SET BASE ADDRESS VALUES.
+
+ // The base addresses are all relative to the framebuffer base address which
+ // is defined to be on the next 256MB boundary above the SYSMGR. Initially,
+ // it was hard coded to be at 0x50000000, and now it should show up at 0x90000000.
+ framebuffer_base = (SYS_LOGICAL_TO_PHYSICAL(0) & 0xF0000000) + 0x10000000;
+ WRITE_PCI_DWORD_NO_TRAP(vga_config_addr+BAR0, framebuffer_base); // Frame buffer address
+
+ GPregister_base = framebuffer_base - 0x00004000;
+ WRITE_PCI_DWORD_NO_TRAP(vga_config_addr+BAR1, GPregister_base); // Graphics processor register space
+
+ VGregister_base = GPregister_base - 0x00004000;
+ WRITE_PCI_DWORD_NO_TRAP(vga_config_addr+BAR2, VGregister_base); // Video generator register space
+
+ DFregister_base = VGregister_base - 0x00004000;
+ WRITE_PCI_DWORD_NO_TRAP(vga_config_addr+BAR3, DFregister_base); // Display filter register space
+
+ VIPregister_base = DFregister_base - 0x00004000;
+ WRITE_PCI_DWORD_NO_TRAP(vga_config_addr+BAR4, VIPregister_base); // Display filter register space
+
+ // Turn on the descriptors
+ WRITE_PCI_BYTE(vga_config_addr+0x04,PCI_MEM_SPACE);
+
+ // Unlock the display controller registers
+ saveLock = read_vg_32(DC_UNLOCK);
+ write_vg_32(DC_UNLOCK, DC_UNLOCK_VALUE);
+
+ // Set up the DV Address offset in the DC_DV_CTL register to the offset from frame
+ // buffer descriptor. First, get the frame buffer descriptor so we can set the
+ // DV Address Offset in the DV_CTL register. Because this is a pointer to real
+ // silicon memory, we don't need to do this whenever we change the framebuffer BAR,
+ // so it isn't included in the hw_fb_map_init routine.
+ SYS_MBUS_DESCRIPTOR((unsigned short)(vga_config_addr+BAR0),(void *)&mVal);
+ mVal.high &= DESC_OFFSET_MASK;
+ mVal.high <<= 4;
+ mVal.high += framebuffer_base; // Watch for overflow issues here...
+ write_vg_32(DC_DV_CTL, mVal.high);
+
+ // Initialize the frame buffer base realated stuff.
+ hw_fb_map_init(framebuffer_base);
+
+ // CLEAR Video Generator START ADDRESS VALUES
+ write_vg_32(DC_FB_ST_OFFSET, 0L);
+ write_vg_32(DC_CB_ST_OFFSET, 0L);
+ write_vg_32(DC_CURS_ST_OFFSET, 0L);
+ write_vg_32(DC_UNLOCK, saveLock);
+
+
+ // Put VIP input and output sections into reset state with default values.
+ write_vip_32(VIP_CTRL1, 0x42000001);
+
+ // Set flags indicating the hardware registers are available and that we are not
+ // disabled. Among other things, the SF_SECONDARY flag controls the hardware
+ // register locking and unlocking at the top of the message handling loop.
+ VGState |= SF_SECONDARY;
+ VGState &= ~SF_DISABLED;
+
+ return;
+}
+
+
+// Initialize the graphics processor MSR registers.
+void hw_gp_msr_init(void)
+{
+ // Initialize the configuration MSR - 0x00000000 00000010
+ msrModify(msrIdx_GP, MBD_MSR_CONFIG, MSR_CLR_ALL, MSR_CLR_ALL_BUT_PID, 0, GP_DEF_PRI);
+
+ // Initialize the SMI MSR. Clear and disable all SMIs - 0x00000001 00000001
+ msrModify(msrIdx_GP, MBD_MSR_SMI, MSR_CLR_ALL, MSR_CLR_ALL, GP_SMI_CLR, GP_SMI_DIS);
+
+ return;
+}
+
+// Initialize the video input port MSR registers.
+void hw_vip_msr_init(void)
+{
+ msrModify(msrIdx_VIP, MBD_MSR_CONFIG, MSR_CLR_ALL, MSR_CLR_ALL_BUT_PID, 0L, VIP_DEF_PRI);
+
+ // Initialize the SMI MSR. Clear and disable all SMIs - 0x00000000 7FFF7FFF
+ msrModify(msrIdx_VIP, MBD_MSR_SMI, MSR_CLR_ALL, MSR_CLR_ALL, 0L, 0x7FFF7FFF);
+
+ return;
+}
+
+// Initialize the video generator MSR registers.
+void hw_vg_msr_init(void)
+{
+ // Initialize the configuration MSR - 0x00000000 00000320
+ msrModify(msrIdx_VG, MBD_MSR_CONFIG, MSR_CLR_ALL, MSR_CLR_ALL_BUT_PID, 0, VG_DEF_PRI);
+
+ // Initialize the SMI MSR. Clear and disable all SMIs - 0x0000001f 0000001f
+ msrModify(msrIdx_VG, MBD_MSR_SMI, MSR_CLR_ALL, MSR_CLR_ALL, VG_SMI_DIS, VG_SMI_DIS);
+
+ // Initialize the DELAY MSR.
+ msrModify(msrIdx_VG, MBD_MSR_DELAY, MSR_CLR_ALL, MSR_CLR_ALL, 0L, 0x00000302);
+
+ // Turn off the bad VG fetch state machine hardware fix and the video FIFO watermarks
+ msrModify(msrIdx_VG, MBD_MSR_SPARE, MSR_CLR_ALL, MSR_CLR_ALL, 0L, 0x00000042);
+
+ return;
+}
+
+// Initialize the display filter MSR registers.
+void hw_mcp_msr_init(void)
+{
+ unsigned long orValLo, orValHi;
+ struct mValue mVal;
+ unsigned char i;
+
+ // Initialize the DOT PLL MSR. We need to default to a known clock so
+ // the PLL doesn't exceed its limits, and if the bypass bit is set, we
+ // need to also set the power down bit.
+ if (vReg[VG_CONFIG] & VG_CFG_BYPASS)
+ {
+ // Bypassed, so just set the bypass and power down bits.
+ orValLo = DOTPLL_BYPASS | DOTPLL_PDBIT;
+ orValHi = 0L;
+ }
+ else
+ {
+ orValLo = DOTPLL_RESET;
+ orValHi = 0x0000216C; // 28.322MHz
+ }
+
+ msrModify(msrIdx_MCP, MCP_DOTPLL, MSR_CLR_ALL, MSR_CLR_ALL, orValHi, orValLo);
+
+ // LEDA has indicated that there may be up to a 42 clock delay from the time the
+ // DOTPLL comes out of powerdown until the lock bit is guaranteed to go low. In
+ // order to make sure we don't read an errant value, we need to delay a bit.
+ for (i=0;i<8;i++)
+ outp(0xed,0xf5);
+
+ // Wait for lock (maybe)
+ msrRead(msrIdx_MCP, MCP_DOTPLL, &mVal);
+ while (!(mVal.low & DOTPLL_LOCKBIT))
+ {
+ // Read the current contents...
+ msrRead(msrIdx_MCP, MCP_DOTPLL, &mVal);
+ };
+
+ msrModify(msrIdx_MCP, MCP_DOTPLL, 0, MSR_CLR_ALL, 0, 0); // Clear the reset bit
+
+ return;
+}
+
+// Initialize the display filter MSR registers.
+void hw_df_msr_init(void)
+{
+ unsigned long orVal;
+ unsigned long mDiv, mMul, pSpd, mSpd, mbClk;
+ struct mValue mVal;
+
+ // Get a colletion of information necessary to compute the divisor for the
+ // CONFIG MSR. This includes the processor speed, the CPU multiplier and
+ // divisor and the MBus multiplier and divisor. There are two different
+ // versions of the computation. The commented out version doesn't depend
+ // on the bootstrap pin, and the other starts with a known PCI speed based
+ // on that pin.
+ msrRead(msrIdx_MCP, MCP_SYSPLL, &mVal); // Returns the divisors...
+
+ pSpd = (mVal.low & 0x00000008)?66:33;
+
+ mDiv = ((mVal.high & 0x00000040) >> 6) + 1;
+ mMul = ((mVal.high & 0x00000F80) >> 7) + 1;
+
+ mbClk = (pSpd * mMul) / mDiv;
+
+ mSpd = (mbClk / 14) & 0x0000003F;
+
+ // Initialize the configuration MSR
+ orVal = DF_DEF_PRI;
+ orVal |= (mSpd << 8);
+ msrModify(msrIdx_DF, MBD_MSR_CONFIG, MSR_CLR_ALL, MSR_CLR_ALL_BUT_PID, 0, orVal);
+
+ return;
+}
+
+
+
+//---------------------------------------------------------------------------
+// hw_fb_map_init
+//
+// This routine initializes the hardware pointers that are specifically
+// related to the framebuffer address.
+//---------------------------------------------------------------------------
+void hw_fb_map_init(unsigned long fbLoc)
+{
+ unsigned long ltemp;
+
+ // Insist upon a certain alignment...
+ fbLoc &= VGdata.pci_fb_mask;
+
+ // Set the MBus Memory Offset register.
+ write_vg_32(PHY_MEM_OFFSET, fbLoc);
+
+ // Set GP2 base offset - different from Redcloud. There are both source
+ // and destination fields the need to be set.
+ ltemp = fbLoc | (fbLoc >> 10);
+ write_gp_32(GP2_BASE_OFFSET, ltemp);
+
+ return;
+}
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/lxvg/lxvg.h b/cpu/amd/geode_lx/gplvsa_ii/lxvg/lxvg.h
new file mode 100755
index 0000000..eaa6304
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/lxvg/lxvg.h
@@ -0,0 +1,915 @@
+/*
+* Copyright (c) 2007-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+// This is the main header file for LXVG.
+
+// VERSION NUMBERS
+
+#define LXVG_MAJOR_VER 0x00
+#define LXVG_MINOR_VER 0x11
+
+// PROCESSOR IDS
+// Keep as bitwise flags to make "either" comparisons easier.
+
+#define PROCESSOR_GXM 0x01
+#define PROCESSOR_REDC 0x02
+#define PROCESSOR_CSTL 0x03
+
+// A pair of LONG generic masks
+#define CLR_HIWORD 0x0000FFFF
+#define CLR_LOWORD 0xFFFF0000
+
+
+// Some LXVG configuration flags and masks
+#define MEM_SIZE_MASK 0x00FE // Bits 7:1 (size in 2MB hunks)
+#define ADAPTER_PRIMARY 0x0100 // Bit 8
+
+#define PLL_REF_MASK 0x0600 // Bits 10:9
+#define PLL_BYPASS 0x0800 // Bit 11
+#define VGDATA_PLL_14MHZ 0x00 // VGdata PLL reference frequency flag value
+#define VGDATA_PLL_48MHZ 0x01 // VGdata PLL reference frequency flag value
+#define VGDATA_PLL_ERROR 0xFF // Bad PLL or hardware error
+#define MONOCHROME_CARD 0x1000 // Bit 12
+
+// SOME REDCLOUD DEFINITIONS
+
+#define FAKE_ADDRESS 0xFFFFFFFF
+#define CLASS_MASK 0x000FF000
+#define DEVID_MASK 0x00FFFF00
+
+// A memory space enable value for the PCI command register
+#define PCI_CMD_REG 0x04
+#define PCI_IO_SPACE (1 << 0)
+#define PCI_MEM_SPACE (1 << 1)
+
+// Some commonly used size definitions
+#define SIZE4K 0x00001000 // A 4K range indicator
+#define SIZE16K 0x00004000 // A 16K range indicator
+#define MASK16K 0xFFFFC00F // A 16K range mask
+#define SIZE32K 0x00008000 // A 32K range indicator
+#define SIZE64K 0x00010000 // A 64K range indicator
+#define SIZE128K 0x00020000 // A 128K range indicator
+
+// PCI device ID assigned to LX graphics system
+#define PCI_DEV_ID 0x2081
+
+// MBus device IDs. These IDs will have to be shifted into place by the System
+// manager when it goes to access the devices.
+#define ID_MBIU 0x01 // Default MBIU device ID
+#define ID_MCP 0x02 // MBus Control Processor device ID
+#define ID_MC 0x20 // Default Memory Controller device ID
+#define ID_GP 0x3D // Graphics Processor device ID
+#define ID_VG 0x3E // Video Generator device ID
+#define ID_DF 0x3F // Display Filter device ID
+#define ID_VIP 0x3C // Display Filter device ID
+
+// MSR Register Offsets
+#define MBD_MSR_CAP 0x2000
+#define MBD_MSR_CONFIG 0x2001
+#define MBD_MSR_SMI 0x2002
+#define MBD_MSR_ERROR 0x2003
+#define MBD_MSR_PM 0x2004
+#define MBD_MSR_DIAG 0x2005
+#define MBD_MSR_SPARE 0x2011
+#define MBD_MSR_DELAY 0x2012
+
+// DF specific MSRs
+#define DF_MSR_DIAG_DF 0x2010
+#define DF_MSR_PAD_SEL 0x2011
+
+// MSR stuff specific to the MCP_DOTPLL
+#define MCP_SYSPLL 0x0014
+#define MCP_DOTPLL 0x0015
+#define DOTPLL_DIV_MASK 0x00007FFF
+#define DOTPLL_DIV4 0x00010000
+
+#define DOTPLL_RESET 0x00000001
+#define DOTPLL_CAPEN 0x00002000
+#define DOTPLL_PDBIT 0x00004000
+#define DOTPLL_BYPASS 0x00008000
+#define DOTPLL_HALFPIX 0x01000000
+#define DOTPLL_LOCKBIT 0x02000000
+
+// MCP Error and SMI MSR error bits related to the DOTPLL reset during power-on bug PBz#3344.
+#define MCP_SMI_ERRBIT 0x00010000
+#define MCP_DOTPLL_ERRBIT 0x00000004
+
+#define MCP_CHIPREV 0x0017
+
+//
+// msrDev indices for the devices that we care about/know about
+//
+#define msrIdx_MCP 0
+#define msrIdx_MC 1
+#define msrIdx_GP 2
+#define msrIdx_VG 3
+#define msrIdx_DF 4
+#define msrIdx_VIP 5
+#define msrIdx_MBIU 6
+
+// A mask to isolate the offset field of the frame buffer descriptor.
+#define DESC_OFFSET_MASK 0x0FFFFF00
+#define DV_OFFSET_MASK 0xFFFFF000
+#define DV_LINE_1K 0x00000000
+#define DV_LINE_2K 0x00000400
+#define DV_LINE_4K 0x00000800
+#define DV_LINE_8K 0x00000C00
+
+// Structures of MSRs.
+//
+// Proper usage is as follows:
+//
+// MSR access routines (MSRAR) should first check the 'Present' field and :
+//
+// 1) If the field is set to 'REQ_NOT_FOUND' :
+// - The device was not detected on the MBUS but a request was made to
+// find it at some point since/during initization [ see msrInit() ].
+// Therefore, MSRAR should not attempt to access the device.
+//
+// 2) If the field is set to 'FOUND' :
+// - The device was detected on the MBUS, the rest of the structure
+// has been filled in and MSRAR should use the address provided.
+//
+// 3) If the field is set to 'UNKNOWN' :
+// - There has never been a request to find this device. MSRAR returns
+// to caller. Caller should first call msrInit().
+//
+// The address field is set to FAKE_ADDRESS just in case "renegade software" doesn't
+// check the 'Present' field and just grabs the 'address' field.
+// FAKE_ADDRESS has been set to a value that should never appear in
+// a real system. It is only meant to protect the system 99%
+// of the time from badly written software....
+
+typedef struct tagMSR {
+ unsigned short Present; // Present - Read above under "Structures of MSRs"
+ unsigned short Id; // Id - Device ID number (from MSR specs)
+ unsigned long Routing; // Routing - 32-bit address at which 'Id' was found
+} MSR;
+
+//
+// mValue is used to hold the 64-bit msr data value.
+//
+typedef struct mValue {
+ unsigned long low;
+ unsigned long high;
+};
+
+// Capabilities bits
+#define DF_BOND_MASK 0x000000C0 // CRT bond value
+#define BOND_CRT 0x00 // CRT bond value
+#define BOND_FP 0x40 // flat panel bond value
+
+#define HALF_MEG 0x00080000 // 512K
+#define QRTR_MEG 0x00040000 // 256K
+#define MAX_ICON 0x4C00 // 19K
+
+// MSR AND masks used by rc_msrModify. These masks define bits that are
+// always cleared in the register.
+#define MSR_CLR_ALL 0xFFFFFFFF // Clear all bits
+#define MSR_CLR_NONE 0L // Clear no bits
+#define MSR_CLR_OUT 0x00008038 // Clear bits 15, 5:3
+#define MSR_CLR_ALL_BUT_PID 0xFFFFFFF8 // Clear all bits except [2:0]
+
+
+// GP
+#define GP_SMI_MSK_HI 0xFFFFFFFF // SMI MSR
+#define GP_SMI_MSK_LO 0xFFE0FFE0
+#define GP_ERR_MSK_HI 0xFFFFFFFF // Error MSR
+#define GP_ERR_MSK_LO 0xFFF0FFF0
+#define GP_PM_MSK_HI 0xFFFFFFFC // PM MSR
+#define GP_PM_MSK_LO 0xFFFFFFF0
+
+// VG
+#define VG_SMI_MSK_HI 0xFFFFFFFF // SMI MSR
+#define VG_SMI_MSK_LO 0xFFE0FFE0
+#define VG_ERR_MSK_HI 0xFFFFFFFF // Error MSR
+#define VG_ERR_MSK_LO 0xFFF0FFF0
+#define VG_PM_MSK_HI 0xFFFFFFFC // PM MSR
+#define VG_PM_MSK_LO 0xFFFFFFF0
+
+// DF
+#define DF_SMI_MSK_HI 0xFFFFFFFF // SMI MSR
+#define DF_SMI_MSK_LO 0xFFFCFFFC
+#define DF_ERR_MSK_HI 0xFFFFFFFE // Error MSR
+#define DF_ERR_MSK_LO 0xFFFFFFFE
+#define DF_PM_MSK_HI 0xFFFFFFE0 // PM MSR
+#define DF_PM_MSK_LO 0xF0FFFC00
+
+
+// MSR bit field AND masks. These are added to the above masks to
+// clear particular fields
+
+// GP
+#define GP_CFG_PRI 0x00000070 // Both priority fields
+#define GP_CFG_PID 0x00000007 // PID field
+#define GP_DEF_PRI 0x00000010 // Default priorities
+
+#define GP_SMI_CLR 0x00000001 // SMI clear bits
+#define GP_SMI_DIS 0x00000001 // SMI disable bits
+
+#define GP_CLK_RQ 0x00000001 // Software clock PM request bits field
+#define GP_PM_MODE 0x00000003 // Clock PM mode fields
+#define GP_CLK_ON 0x00000000 // Both clocks always on
+#define GP_CLK_HW 0x00000001 // Both clocks hardware gated
+#define GP_CLK_SW 0x00000002 // Both clocks software gated
+#define GP_CLK_BOTH 0x00000003 // Both clocks software and hardware gated
+
+// VG
+#define VG_CFG_PRI 0x00000770 // Both priority fields
+#define VG_CFG_PID 0x00000007 // PID field
+#define VG_DEF_PRI 0x00000720 // Default priorities
+#define VG_DEF_PRI_10 0x00000620 // Default priorities for 1.0 parts
+
+// LX 2.0 changes
+#define VG_SMI_DIS 0x1001FFFF // SMI disable and clear bits
+#define VG_SMI_ALLNB 0x10000016 // All "Standard" SMIs but VBLANKs
+
+#define VG_SMI_INV_CRTC 0x00000010 // Invalid CRTC SMI disable mask
+#define VG_SMI_VBLANK 0x00000009 // Vertical blanks SMI disable mask
+#define VG_SMI_ISR0 0x00000004 // Input status register SMI disable mask
+#define VG_SMI_MISC_W 0x00000002 // Miscellaneous output register SMI disable mask
+
+#define VG_SMI_ALLCRTC 0x00000060 // All CRTC reads and writes
+#define VG_SMI_ALLSEQ 0x00000180 // All SEQ reads and writes
+#define VG_SMI_ALLGDC 0x00000600 // All GFX reads and writes
+#define VG_SMI_ALLATC 0x00001800 // All ATC reads and writes
+#define VG_SMI_ALLDAC 0x00006000 // All DAC reads and writes
+
+#define VG_SMI_CRTC_W 0x00000020 // All CRTC writes
+#define VG_SMI_CRTC_R 0x00000040 // All CRTC reads
+#define VG_SMI_SEQ_W 0x00000080 // All SEQ writes
+#define VG_SMI_SEQ_R 0x00000100 // All SEQ reads
+#define VG_SMI_GDC_W 0x00000200 // All GDC writes
+#define VG_SMI_GDC_R 0x00000400 // All GDC reads
+#define VG_SMI_ATC_W 0x00000800 // All ATC writes
+#define VG_SMI_ATC_R 0x00001000 // All ATC reads
+#define VG_SMI_DAC_W 0x00002000 // All DAC writes
+#define VG_SMI_DAC_R 0x00004000 // All DAC reads
+#define VG_SMI_MISC_R 0x00008000 // Miscellaneous output register reads
+#define VG_SMI_ISR1_R 0x00010000 // Input status register 1 reads
+
+// VG_DEBUG trap request bits
+#define TRAP_ALL_CRTC 0x0100
+#define TRAP_ALL_SEQ 0x0200
+#define TRAP_ALL_GDC 0x0400
+#define TRAP_ALL_ATC 0x0800
+#define TRAP_ALL_DAC 0x1000
+#define TRAP_MISC_RDS 0x2000
+#define TRAP_ISR1_RDS 0x4000
+// LX 2.0 changes
+
+#define VG_CLK_RQ 0x00000003 // Software clock PM request bits field
+#define VG_PM_MODE 0x0000000F // Clock PM mode fields
+#define VG_CLK_ON 0x00000000 // Both clocks always on
+#define VG_CLK_HW 0x00000005 // Both clocks hardware gated
+#define VG_CLK_SW 0x0000000A // Both clocks software gated
+#define VG_CLK_BOTH 0x0000000F // Both clocks software and hardware gated
+
+
+// DF
+#define DF_CFG_PID 0x00000007 // PID field
+#define DF_CFG_FMT 0x00000038 // Output format select field
+#define DF_CFG_FMBO 0x000000C0 // Output format byte order field
+#define DF_CFG_DIV 0x00003F00 // Clock divider field
+#define DF_CFG_IUV 0x00004000 // Interchange UV field
+#define DF_CFG_FPC 0x00008000 // Simultaneous CRT and panel/VOP bit
+#define DF_CFG_PRI 0x00070000 // MBus master priority field
+#define DF_DEF_PRI 0x00040000 // Default priority
+#define DF_DEF_DIV 0x00003F00 // Default clock divider
+
+//#define DF_SMI_CLR 0x00030000 // SMI clear bits
+#define DF_SMI_CLR 0x00000000 // SMI clear bits
+#define DF_SMI_DIS 0x00000003 // SMI disable bits
+
+#define DF_CLK_RQ 0x0000001F // Software clock PM request bits field
+#define DF_PM_MODE 0x000003FF // Clock PM mode fields
+#define DF_CLK_ON 0x00000000 // All clocks always on
+#define DF_CLK_HW 0x00000155 // All clocks hardware gated
+#define DF_CLK_SW 0x000002AA // All clocks software gated
+#define DF_CLK_BOTH 0x000003FF // All clocks software and hardware gated
+
+#define DF_CLR_CRC 0x80000000 // Clear the CRC select bit
+
+// VIP
+#define VIP_CFG_PID 0x00000007 // PID field
+#define VIP_PRI_PRI 0x00000070 // MBus master priority field
+#define VIP_SEC_PRI 0x00000700 // Default priority
+#define VIP_DEF_PRI_10 0x00000630 // Default priority
+#define VIP_DEF_PRI 0x00000620 // Default priority
+
+#define VIP_SMI_CLR 0x3FFF0000 // SMI clear bits
+#define VIP_SMI_DIS 0x00003FFF // SMI disable bits
+
+#define VIP_CLK_RQ 0x0000001F // Software clock PM request bits field
+#define VIP_PM_MODE 0x000003FF // Clock PM mode fields
+#define VIP_CLK_ON 0x00000000 // All clocks always on
+#define VIP_CLK_HW 0x00000155 // All clocks hardware gated
+#define VIP_CLK_SW 0x000002AA // All clocks software gated
+#define VIP_CLK_BOTH 0x000003FF // All clocks software and hardware gated
+
+//
+// SMI event id bits
+//
+#define EVT_VG_VBLANK 0x00000001
+#define EVT_VG_MISC_WR 0x00000002
+#define EVT_VG_ISR0_RD 0x00000004
+#define EVT_VGA_VBLANK 0x00000008
+#define EVT_VG_INV_CRTC 0x00000010
+#define EVT_VG_CRTC_W 0x00000020
+#define EVT_VG_CRTC_R 0x00000040
+#define EVT_VG_SEQ_W 0x00000080
+#define EVT_VG_SEQ_R 0x00000100
+#define EVT_VG_GFX_W 0x00000200
+#define EVT_VG_GFX_R 0x00000400
+#define EVT_VG_ATC_W 0x00000800
+#define EVT_VG_ATC_R 0x00001000
+#define EVT_VG_DAC_W 0x00002000
+#define EVT_VG_DAC_R 0x00004000
+#define EVT_VG_MISC_R 0x00008000
+#define EVT_VG_ISR1_R 0x00010000
+#define EVT_VGA_RES_CHG 0x10000000
+
+#define EVT_WRITES 0x00000AB2 // The register write bits
+#define EVT_READS 0x0001D554 // The register read bits + ISR0 & Inv CRTC
+//#define EVT_GP_SMI0 0x20000000
+//#define EVT_DF_SMI0 0x40000000
+//#define EVT_DF_SMI1 0x80000000
+// Castle 2.0 Defs
+
+
+//
+// GP2 Memory Mapped Register Set
+//
+#define GP2_DST_OFFSET 0x0000
+#define GP2_SRC_OFFSET 0x0004
+#define GP2_VEC_ERR 0x0004
+#define GP2_STRIDE 0x0008
+#define GP2_WID_HEIGHT 0x000C
+#define GP2_SRC_COLOR_FG 0x0010
+#define GP2_SRC_COLOR_BG 0x0014
+#define GP2_PAT_COLOR_0 0x0018
+#define GP2_PAT_COLOR_1 0x001C
+#define GP2_PAT_COLOR_2 0x0020
+#define GP2_PAT_COLOR_3 0x0024
+#define GP2_PAT_COLOR_4 0x0028
+#define GP2_PAT_COLOR_5 0x002C
+#define GP2_PAT_DATA_0 0x0030
+#define GP2_PAT_DATA_1 0x0034
+#define GP2_RASTER_MODE 0x0038
+#define GP2_VECTOR_MODE 0x003C
+#define GP2_BLT_MODE 0x0040
+#define GP2_BLT_STATUS 0x0044
+#define GP2_RESET 0x0044
+#define GP2_HST_SRC 0x0048
+#define GP2_BASE_OFFSET 0x004C
+
+//
+// VG Memory Mapped Register Set
+//
+#define DC_UNLOCK 0x0000
+#define DC_GENERAL_CFG 0x0004
+#define DC_DISPLAY_CFG 0x0008
+#define DC_ARB_CFG 0x000C
+//#define DC_GFX_SCL 0x000C
+#define DC_FB_ST_OFFSET 0x0010
+#define DC_CB_ST_OFFSET 0x0014
+#define DC_CURS_ST_OFFSET 0x0018
+//#define DC_ICON_ST_OFFSET 0x001C
+#define DC_VID_Y_ST_OFFSET 0x0020
+#define DC_VID_U_ST_OFFSET 0x0024
+#define DC_VID_V_ST_OFFSET 0x0028
+#define DC_DV_TOP 0x002C
+//#define DC_VID_SP_ST_OFFSET 0x002C
+#define DC_LINE_SIZE 0x0030
+#define DC_GFX_PITCH 0x0034
+#define DC_VID_YUV_PITCH 0x0038
+//#define DC_VID_SP_PITCH 0x003C
+#define DC_H_ACTIVE_TIMING 0x0040
+#define DC_H_BLANK_TIMING 0x0044
+#define DC_H_SYNC_TIMING 0x0048
+//#define DC_FP_HSYNC_TIMING 0x004C
+#define DC_V_ACTIVE_TIMING 0x0050
+#define DC_V_BLANK_TIMING 0x0054
+#define DC_V_SYNC_TIMING 0x0058
+#define DC_FB_ACTIVE 0x005C
+//#define DC_FP_VSYNC_TIMING 0x005C
+#define DC_CURSOR_X 0x0060
+#define DC_CURSOR_Y 0x0064
+//#define DC_ICON_X 0x0068
+#define DC_LINE_CNT 0x006C
+#define DC_PAL_ADDRESS 0x0070
+#define DC_PAL_DATA 0x0074
+#define DC_DFIFO_DIAG 0x0078
+#define DC_CFIFO_DIAG 0x007C
+#define DC_VID_DS_DELTA 0x0080
+#define PHY_MEM_OFFSET 0x0084
+#define DC_DV_CTL 0x0088
+#define DC_ACCESS 0x008C
+
+#define DC_GFX_SCALE 0x0090
+#define DC_IRQ_FLT_CTL 0x0094
+#define DC_FLT_COEFF1 0x0098
+#define DC_FLT_COEFF2 0x009C
+
+#define DC_VBI_EVN_CTL 0x00A0
+#define DC_VBI_ODD_CTL 0x00A4
+#define DC_VBI_HOR_CTL 0x00A8
+#define DC_VBI_LN_ODD 0x00AC
+#define DC_VBI_LN_EVN 0x00B0
+#define DC_VBI_PITCH 0x00B4
+#define DC_VBI_CLR_KEY 0x00B8
+#define DC_VBI_CK_MASK 0x00BC
+#define DC_VBI_CK_X 0x00C0
+#define DC_VBI_CK_Y 0x00C4
+
+#define DC_IRQ 0x00C8
+#define DC_GENLK_CTL 0x00D4
+
+#define DC_VID_EVN_Y_ST 0x00D8
+#define DC_VID_EVN_U_ST 0x00DC
+#define DC_VID_EVN_V_ST 0x00E0
+
+#define DC_VID_EVN_ACT 0x00E4
+#define DC_VID_EVN_BLANK 0x00E8
+#define DC_VID_EVN_SYNC 0x00EC
+
+#define DC_VGA_CONFIG 0x0100
+#define DC_VGA_STATUS 0x0104
+//#define DC_VGA_EXTADDR 0x0108
+
+#define DC_UNLOCK_VALUE 0x00004758
+#define DC_LOCK_VALUE 0x00000000
+
+//-----------------------------------//
+// DC_GENERAL_CFG Bit Definitions //
+//-----------------------------------//
+// DC_GCFG_CLR_MASK turns off everything but VGA fixed timing enable, VGA enable,
+// compression and decompression enables and Display-FIFO Load Enable
+#define DC_GCFG_CLR_MASK 0x0004FF00
+
+#define DC_GCFG_DFLE 0x00000001
+#define DC_GCFG_CURE 0x00000002
+#define DC_GCFG_ICNE 0x00000004
+#define DC_GCFG_VIDE 0x00000008
+//#define DC_GCFG_VSPE 0x00000010
+#define DC_GCFG_FSSEL 0x00000010
+#define DC_GCFG_CMPE 0x00000020
+#define DC_GCFG_DECE 0x00000040
+#define DC_GCFG_VGAE 0x00000080
+
+#define DC_GCFG_DFIFO_ST 0x00000F00
+#define DC_GCFG_DFIFO_END 0x0000F000
+#define DC_GCFG_WATERMARKS 0x00007200
+#define DC_GCFG_STFM 0x00010000
+#define DC_GCFG_FDTY 0x00020000
+#define DC_GCFG_VGAFT 0x00040000
+#define DC_GCFG_VDSE 0x00080000
+#define DC_GCFG_YUVM 0x00100000
+//#define DC_GCFG_FTSTR 0x00200000
+#define DC_GCFG_FRC8PIX 0x00400000
+#define DC_GCFG_SIGSEL 0x00800000
+#define DC_GCFG_CLR_CRC 0xF8FFFFFF
+//#define DC_GCFG_CLR_CRC_ALL 0xF07FFFFF
+#define DC_GCFG_CLR_CRC_ALL 0xF07FFFEF
+#define DC_GCFG_SIGE 0x01000000
+#define DC_GCFG_SGRE 0x02000000
+#define DC_GCFG_SGFR 0x04000000
+#define DC_GCFG_CRCMODE 0x08000000
+//#define DC_GCFG_GXRFS4 0x08000000
+
+
+//-----------------------------------//
+// DC_DISPLAY_CFG Bit Definitions //
+//-----------------------------------//
+// DC_DCFG_CLR_MASK turns off everything but display center, color depth fields,
+// and scale enable.
+#define DC_DCFG_CLR_MASK 0xC0000F00
+#define DC_DCFG_BLANK_MASK 0xFFFFFFC0
+
+#define DC_DCFG_TGEN 0x00000001
+//#define DC_DCFG_PCKE 0x00000002
+//#define DC_DCFG_VCKE 0x00000004
+#define DC_DCFG_GDEN 0x00000008
+//#define DC_DCFG_VDEN 0x00000010
+#define DC_DCFG_VIEN 0x00000020
+#define DC_DCFG_TRUP 0x00000040
+#define DC_DCFG_SCLE 0x00000080
+
+// Color depth related masks and values
+#define DC_DCFG_MODE_MASK 0x00000F00
+#define DC_DCFG_16BPP_MODE 0x00000C00
+#define DC_DCFG_DISP_MODE 0x00000300
+
+#define DC_DCFG_BPP16 0x00000100
+#define DC_DCFG_BPP15 0x00000500
+#define DC_DCFG_BPP12 0x00000900
+#define DC_DCFG_BPP32 0x00000200
+
+#define DC_DCFG_VFHPSL 0x0000F000
+//#define DC_DCFG_PLNR 0x00001000
+//#define DC_DCFG_SSLC 0x00002000
+//#define DC_DCFG_PXDB 0x00004000
+//#define DC_DCFG_LNDB 0x00008000
+
+#define DC_DCFG_VFHPEL 0x000F0000
+//#define DC_DCFG_BLNK 0x00010000
+//#define DC_DCFG_BKRT 0x00020000
+//#define DC_DCFG_RFS4 0x00040000
+//#define DC_DCFG_DCEN 0x00080000
+
+//#define DC_DCFG_PIX_PAN 0x00F00000
+//#define DC_DCFG_PPC 0x01000000
+#define DC_DCFG_DCEN 0x01000000
+#define DC_DCFG_PALB 0x02000000
+//#define DC_DCFG_FRLK 0x04000000
+#define DC_DCFG_VISL 0x08000000
+//#define DC_DCFG_A18M 0x40000000
+//#define DC_DCFG_A20M 0x80000000
+
+//-----------------------------------//
+// DC_IRQ_FLT_CTL Bit Definitions //
+//-----------------------------------//
+#define IF_FLT_ADDR_MASK 0x000000FF
+#define IF_HFILT_SEL 0x00000400
+#define IF_INTL_EN 0x00000800
+#define IF_HFILT_EN 0x00001000
+#define IF_VFILT_EN 0x00002000
+#define IF_HALPH_FILT_EN 0x00004000
+#define IF_VALPH_FILT_EN 0x00008000
+#define IF_LIN_CNT_MASK 0x07FF0000
+#define IF_IRQ_EN 0x08000000
+#define IF_INTL_ADDR 0x10000000
+
+
+
+//
+// DF Memory Mapped Register Set
+//
+#define DF_VCFG 0x0000
+#define DF_DCFG 0x0008
+#define DF_VID_X 0x0010
+#define DF_VID_Y 0x0018
+#define DF_VID_SCL 0x0020
+#define DF_VID_CK 0x0028
+#define DF_VID_CM 0x0030
+#define DF_PAL_ADDR 0x0038
+#define DF_PAL_DATA 0x0040
+
+#define DF_SLR 0x0048
+
+#define DF_MISC 0x0050
+#define DF_CRT_CS 0x0058
+
+#define DF_VYS 0x0060
+#define DF_VXS 0x0068
+
+#define DF_VID_DSC 0x0078
+//#define DF_VID_DCO 0x0080
+
+#define DF_CRC_SIG 0x0088
+#define DF_CRCS_CLR_CRC 0xFFFFFFF8
+#define DF_CRCS_SIGE 0x00000001
+#define DF_CRCS_SGFR 0x00000004
+#define DF_CRC32_SIG 0x0090
+
+#define DF_VID_VDE 0x0098
+#define DF_VID_CCK 0x00A0
+#define DF_VID_CCM 0x00A8
+#define DF_VID_CC1 0x00B0
+#define DF_VID_CC2 0x00B8
+#define DF_VID_A1X 0x00C0
+#define DF_VID_A1Y 0x00C8
+#define DF_VID_A1C 0x00D0
+#define DF_VID_A1T 0x00D8
+#define DF_VID_A2X 0x00E0
+#define DF_VID_A2Y 0x00E8
+#define DF_VID_A2C 0x00F0
+#define DF_VID_A2T 0x00F8
+#define DF_VID_A3X 0x0100
+#define DF_VID_A3Y 0x0108
+#define DF_VID_A3C 0x0110
+#define DF_VID_A3T 0x0118
+#define DF_VID_VRR 0x0120
+#define DF_VID_AWT 0x0128
+
+// Flat panel specific
+#define DF_FP_PT1 0x0400
+#define DF_FP_PT2 0x0408
+#define DF_FP_PM 0x0410
+#define DF_FP_DFC 0x0418
+#define DF_DFC_NO_DITHER 0x00000070
+//#define DF_FP_BLFSR 0x0420
+//#define DF_FP_RLFSR 0x0428
+//#define DF_FP_FMI 0x0430
+//#define DF_FP_FMD 0x0438
+//#define DF_FP_RSVD 0x0440
+#define DF_FP_DCA 0x0448
+#define DF_FP_DMD 0x0450
+#define DF_FP_CRC 0x0458
+//#define DF_FP_FBB 0x0460
+#define DF_FP_CRC32 0x0468
+
+// VOP specific
+#define DF_VOP_CFG 0x0800
+#define DF_VOP_SIG 0x0808
+
+#define DF_VID_VCR 0x1000
+
+#define DF_DCFG_VID_EN 0x00000001
+
+//-----------------------------------//
+// DF_DCFG Bit Definitions //
+//-----------------------------------//
+// DF_DCFG_CLR_MASK turns off everything but CRT sync skew. The blank mask turns off
+// CRT DACs, the CRT sync enables and resets the display logic.
+#define DF_DCFG_CLR_MASK 0x0001C000
+#define DF_DCFG_BLANK_MASK 0xFFFFFFF0 // 0xF431FF30
+#define DF_DCFG_ENABLE_MASK 0x0000000F
+#define DF_DCFG_DPMS_STBY 0x00000005
+#define DF_DCFG_DPMS_SUSP 0x00000003
+
+#define DF_DCFG_DIS_EN 0x00000001
+#define DF_DCFG_HSYNC_EN 0x00000002
+#define DF_DCFG_VSYNC_EN 0x00000004
+#define DF_DCFG_DAC_BL_EN 0x00000008
+//#define DF_DCFG_DAC_PWDNX 0x00000020
+//#define DF_DCFG_FP_PWR_EN 0x00000040
+//#define DF_DCFG_FP_DATA_EN 0x00000080
+#define DF_DCFG_CRT_HSYNC_POL 0x00000100
+#define DF_DCFG_CRT_VSYNC_POL 0x00000200
+//#define DF_DCFG_FP_HSYNC_POL 0x00000400
+//#define DF_DCFG_FP_VSYNC_POL 0x00000800
+//#define DF_DCFG_XGA_FP 0x00001000
+//#define DF_DCFG_FP_DITH_EN 0x00002000
+#define DF_DCFG_CRT_SYNC_SKW_MASK 0x0001C000
+#define DF_DCFG_CRT_SYNC_SKW_POS 14
+//#define DF_DCFG_PWR_SEQ_DLY_MASK 0x000E0000
+//#define DF_DCFG_PWR_SEQ_DLY_POS 17
+//#define DF_DCFG_PWR_SEQ_DLY_VAL 0x00080000
+#define DF_DCFG_VG_CK 0x00100000
+#define DF_DCFG_GV_PAL_BYP 0x00200000
+//#define DF_DCFG_DDC_SCL 0x00400000
+//#define DF_DCFG_DDC_SDA 0x00800000
+//#define DF_DCFG_DDC_OE 0x01000000
+#define DF_DCFG_DAC_VREF 0x04000000
+//#define DF_DCFG_FP_PWR_ON 0x08000000
+
+
+//-----------------------------------//
+// DF_FP_PT1 Bit Definitions //
+//-----------------------------------//
+#define DF_PT1_HPULSE_MASK 0x0000001F
+#define DF_PT1_HDELAY_MASK 0x000000E0 // Not used in LXVG
+#define DF_PT1_HDELAY_SHIFT 5
+#define DF_PT1_O 0x00004000
+#define DF_PT1_U 0x00008000
+#define DF_PT1_VSIZE_MASK 0x07FF0000
+#define DF_PT1_VSIZE_SHIFT 16
+#define DF_PT1_HSRC 0x08000000
+#define DF_PT1_HSIP 0x20000000
+#define DF_PT1_VSIP 0x40000000
+
+
+//-----------------------------------//
+// DF_FP_PT2 Bit Definitions //
+//-----------------------------------//
+#define DF_PT2_CLP 0x00002000
+#define DF_PT2_PIXF_MASK 0x00070000
+#define DF_PT2_PIXF_SHIFT 16
+#define DF_PT2_PIXF_000 0x00000000
+#define DF_PT2_PIXF_001 0x00010000
+#define DF_PT2_PIXF_002 0x00020000
+#define DF_PT2_PIXF_003 0x00030000
+#define DF_PT2_MCS 0x00080000
+#define DF_PT2_PSEL_MASK 0x00300000
+#define DF_PT2_PSEL_STN 0x00000000
+#define DF_PT2_PSEL_TFT 0x00100000
+#define DF_PT2_HSP 0x00400000
+#define DF_PT2_VSP 0x00800000
+#define DF_PT2_VFS 0x01000000
+#define DF_PT2_LMS 0x02000000
+#define DF_PT2_LHS 0x04000000
+#define DF_PT2_SCRC 0x08000000
+#define DF_PT2_LPOL 0x20000000
+#define DF_PT2_TPASS 0x40000000
+
+//-----------------------------------//
+// DF_FP_PM Bit Definitions //
+//-----------------------------------//
+#define DF_PM_SINV 0x00002000
+#define DF_PM_VDEL_MASK 0x0000C000
+#define DF_PM_VDEL_SHIFT 14
+#define DF_PM_HDEL_MASK 0x00030000
+#define DF_PM_HDEL_SHIFT 16
+#define DF_PM_PD0 0x00040000
+#define DF_PM_PD1 0x00080000
+#define DF_PM_PD2 0x00100000
+#define DF_PM_PUB0 0x00200000
+#define DF_PM_PUB1 0x00400000
+#define DF_PM_PUB2 0x00800000
+#define DF_PM_P 0x01000000
+#define DF_PM_D 0x02000000
+#define DF_PM_PWR_SEQ 0x08000000
+
+//-----------------------------------//
+// DF_VOP_CFG Bit Definitions //
+//-----------------------------------//
+#define DF_VOP_ENABLE_MASK 0x00000003
+#define DF_VOP_VIP11 0x00000001
+#define DF_VOP_VIP2 0x00000002
+#define DF_VOP_CCIR656 0x00000003
+#define DF_VOP_LVL2 0x00000004
+#define DF_VOP_EXTSAV 0x00000008
+#define DF_VOP_422CO 0x00000000
+#define DF_VOP_422RCO 0x00000010
+#define DF_VOP_422ASS 0x00000020
+#define DF_VOP_SC120X 0x00000040
+#define DF_VOP_SIGE 0x00000080
+#define DF_VOP_SIGFR 0x00000100
+
+
+//
+// VIP Memory Mapped Register Set
+//
+#define VIP_CTRL1 0x0000
+#define VIP_CTRL2 0x0004
+#define VIP_STATUS 0x0008
+#define VIP_INTS 0x000C
+#define VIP_CURTGT 0x0010
+#define VIP_MAX_ADDR 0x0014
+
+#define VIP_AVID_EBASE 0x0018
+#define VIP_AVID_OBASE 0x001C
+#define VIP_AVBI_EBASE 0x0020
+#define VIP_AVBI_OBASE 0x0024
+#define VIP_A_PITCH 0x0028
+#define VIP_CTRL3 0x002C
+#define VIP_A_VOBUF 0x0030
+#define VIP_A_UOBUF 0x0034
+
+#define VIP_BVID_EBASE 0x0038
+#define VIP_BVID_OBASE 0x003C
+#define VIP_BVBI_EBASE 0x0040
+#define VIP_BVBI_OBASE 0x0044
+#define VIP_B_PITCH 0x0048
+#define VIP_B_VBUF 0x0050
+#define VIP_B_UBUF 0x0054
+
+#define VIP_AMSG_1BASE 0x0058
+#define VIP_AMSG_2BASE 0x005C
+#define VIP_AMSG_SIZE 0x0060
+
+#define VIP_PAGE_OFFS 0x0068
+#define VIP_VERT_ST 0x006C
+#define VIP_FIFO_ADDR 0x0070
+#define VIP_FIFO_RW 0x0074
+#define VIP_FRM_DCNT 0x0078
+#define VIP_A_VEBUF 0x007C
+#define VIP_A_UEBUF 0x0080
+
+
+
+// CHIPSET IDS
+// Keep as bitwise flags to make "either" comparisons easier.
+
+#define CHIPSET_CX5530 0x01
+#define CHIPSET_REDC 0x02
+#define CHIPSET_DHRUVA 0x10
+#define CHIPSET_BHARGAVA 0x20
+#define CX5530_DISPLAY_CONFIG 0x00000004
+
+// TRAPPED PCI DEVICES
+
+#define PCI_CONFIG_MASK 0xFFFFFF00 // bits for comparison
+#define PCI_NSM_FLAGS_REG0 0x44 // register for flags
+#define PCI_NSM_FLAGS_REG1 0x45 // register for flags
+#define PCI_NSM_FLAGS_REG2 0x46 // register for flags
+#define PCI_NSM_FLAGS_REG3 0x47 // register for flags
+#define PCI_NSM_FLAG_DISABLE 0x01 // flag to disable LXVG
+
+// SYSTEM FLAGS (stored in VGState)
+
+#define SF_DISABLED 0x00000001 // LXVG is disabled
+#define SF_SECONDARY 0x00000002 // Init to secondary controller capability
+#define SF_PRIMARY 0x00000004 // Init to primary controller capability
+// The next flag indicates a mode switch has occurred. Generally only the first mode
+// switch is interesting.
+#define SF_MODE_SET 0x00000008
+#define SF_END_POST 0x00000010 // POST is complete
+#define SF_DRIVER_ENABLED 0x00000020 // Graphics driver is controlling system
+#define SF_DIAG_SMI 0x00000040 // Use diagnostic SMI settings
+
+#define SF_MONOCHROME 0x00000100 // monochrome mode
+#define SF_3D0_RANGE 0x00000200 // remembers state of ioaddr bit in misc output
+#define SF_SCALE_DISABLED 0x00000400 // Disable graphics scaling during fixed timings
+#define SF_FORCE_VALIDATION 0x00000800 // force all HW validation
+
+
+// SMM HEADER FLAGS
+
+#define SMM_IO_WRITE 0x0002
+#define SMM_VR_WRITE 0x0001
+
+// FLAGS FOR PCI TRAP EVENTS
+
+#define PCI_TRAP_WRITE 0x80
+
+#include "VGdata.h"
+
+#define TRUE 1
+#define FALSE 0
+
+
+extern VGDATA VGdata;
+extern unsigned long VGState;
+extern unsigned long lockNest; // Nested SMI recognition scheme
+extern unsigned long saveLock; // Nested SMI recognition scheme
+extern unsigned short vReg[];
+extern unsigned long vga_config_addr;
+extern unsigned long GPregister_base;
+extern unsigned long VGregister_base;
+extern unsigned long DFregister_base;
+extern unsigned long VIPregister_base;
+extern unsigned long framebuffer_base;
+extern unsigned long VG_SMI_Mask;
+extern unsigned char crc_time;
+
+
+//------------//
+// ROUTINES //
+//------------//
+
+// ROUTINES IN MSR.C
+
+unsigned char msrInit(void);
+unsigned short msrFindDevice(struct tagMSR *);
+unsigned short msrIdDevice(unsigned long);
+unsigned short msrRead(unsigned short msrIdx, unsigned short msrReg, struct mValue *);
+unsigned short msrWrite(unsigned short msrIdx, unsigned short msrReg, unsigned long outHi, unsigned long outLo);
+void msrModify(unsigned short msrIdx, unsigned short msrReg,
+ unsigned long andHi, unsigned long andLo, unsigned long orHi, unsigned long orLo);
+void msrSave(unsigned short msrIdx, unsigned short *, struct mValue *);
+void msrRestore(unsigned short msrIdx, unsigned short *, struct mValue *);
+void msrDump(unsigned short msrIdx, unsigned short msrReg);
+
+
+// ROUTINES IN VSA2.C
+
+void decode_vsa2_event(void);
+void vsa2_io_read(unsigned short size, unsigned long data);
+
+
+// ROUTINES IN DECODE.C
+
+void virtual_register_event(unsigned char reg, unsigned long rwFlag, unsigned long vrData);
+void pci_trap_event(unsigned long address, unsigned long size, unsigned long data);
+
+
+// ROUTINES IN GXHWCTL.C
+
+void hw_initialize(unsigned short config);
+void hw_gp_msr_init(void);
+void hw_vip_msr_init(void);
+void hw_vg_msr_init(void);
+void hw_df_msr_init(void);
+void hw_mcp_msr_init(void);
+void hw_fb_map_init(unsigned long fbLoc);
+
+// ROUTINES IN INIT.C
+
+void lxvg_initialize(unsigned short init_parms);
+
+
+// ROUTINES IN UTILS.ASM
+
+unsigned long read_fb_32(unsigned long offset);
+void write_fb_32(unsigned long offset, unsigned long data);
+unsigned long read_gp_32(unsigned long offset);
+void write_gp_32(unsigned long offset, unsigned long data);
+unsigned char read_vg_8(unsigned long offset);
+void write_vg_8(unsigned long offset, unsigned char data);
+unsigned long read_vg_32(unsigned long offset);
+void write_vg_32(unsigned long offset, unsigned long data);
+unsigned long read_df_32(unsigned long offset);
+void write_df_32(unsigned long offset, unsigned long data);
+unsigned long read_vip_32(unsigned long offset);
+void write_vip_32(unsigned long offset, unsigned long data);
+void asmRead(unsigned short msrReg, unsigned long msrAddr, unsigned long *ptrHigh, unsigned long *ptrLow);
+void asmWrite(unsigned short msrReg, unsigned long msrAddr, unsigned long *ptrHigh, unsigned long *ptrLow);
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/lxvg/main.asm b/cpu/amd/geode_lx/gplvsa_ii/lxvg/main.asm
new file mode 100755
index 0000000..0f3b267
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/lxvg/main.asm
@@ -0,0 +1,55 @@
+;/*
+;* Copyright (c) 2007-2008 Advanced Micro Devices,Inc. ("AMD").
+;*
+;* This library is free software; you can redistribute it and/or modify
+;* it under the terms of the GNU Lesser General Public License as
+;* published by the Free Software Foundation; either version 2.1 of the
+;* License, or (at your option) any later version.
+;*
+;* This code is distributed in the hope that it will be useful,
+;* but WITHOUT ANY WARRANTY; without even the implied warranty of
+;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;* Lesser General Public License for more details.
+;
+;* You should have received a copy of the GNU Lesser General
+;* Public License along with this library; if not, write to the
+;* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+;* Boston, MA 02111-1307 USA
+;*/
+
+;* This file contains the VSM header for the LXVG VSM
+
+
+.model tiny,c
+.486
+.CODE
+
+include VSA2.INC
+
+externdef edata:proc
+externdef _end:proc
+externdef vsa2_message_loop:proc
+
+public VSM_Hdr
+
+
+VSM_Hdr:
+
+ dd VSM_SIGNATURE ; VSM signature
+ db VSM_VGA ; VSM type
+ db 0FFh ; Any CPU
+ dw 0FFFFh ; Any Chipset
+ dw 0101h ; VSM version 01.01
+ dd OFFSET edata ; Size of VSM module
+ dw OFFSET vsa2_message_loop; EntryPoint
+ dd OFFSET _end ; DS Limit
+ dw 0000h ; Requirements
+ dw VSA_VERSION ; VSA version
+ db sizeof(VSM_Header) - ($-VSM_Hdr) dup (0)
+
+
+ END VSM_Hdr
+
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/lxvg/makefile b/cpu/amd/geode_lx/gplvsa_ii/lxvg/makefile
new file mode 100755
index 0000000..8d5faba
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/lxvg/makefile
@@ -0,0 +1,158 @@
+# Copyright (c) 2007-2008 Advanced Micro Devices,Inc. ("AMD").
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# This code is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+
+# You should have received a copy of the GNU Lesser General
+# Public License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA
+
+######################################################################
+#
+# Init variables
+#
+######################################################################
+!ifndef VSA2ROOT
+VSA2ROOT = ..
+!endif
+
+BUILD_DIR = $(VSA2ROOT)\build
+OBJECT = obj
+!include $(BUILD_DIR)\setvars.mak
+
+.SUFFIXES: .asm .c .h .inc .map .obj .mac
+
+INCLUDE = $(OBJECT)
+
+
+######################################################################
+#
+# Build Macros
+#
+######################################################################
+
+VGA_C_OBJS = \
+ $(OBJECT)\vsa2.obj \
+ $(OBJECT)\init.obj \
+ $(OBJECT)\msr.obj \
+ $(OBJECT)\decode.obj \
+ $(OBJECT)\vgdata.obj \
+ $(OBJECT)\lxhwctl.obj \
+
+VGA_ASM_OBJS = \
+ $(OBJECT)\main.obj \
+ $(OBJECT)\utils.obj \
+
+
+VGA_OBJS = $(VGA_ASM_OBJS) $(VGA_C_OBJS)
+
+VGA_VSM = $(OBJECT)\lxvg.vsm
+
+#######################################################################
+#
+# Targets
+#
+#######################################################################
+
+
+all: setenv
+ $(MAKE) lxvga.vsm "CPU=lx"
+
+lxvga.vsm: $(OBJECT) $(VGA_OBJS)
+ $(LN) $(LOPTS_VSM) @<<
+$(VGA_OBJS: =+^
+)
+$(VGA_VSM)
+lxvg.map
+$(BUILD_DIR)\obj\$(TOOL_LIB) ;
+<<NOKEEP
+ $(COPY) $(VGA_VSM) $(BUILDOBJ)
+
+#This and only this clean target must exist as it is called by cleanall
+#cleanall and cleanlocal are defined in rules.mak
+
+clean: cleanlocal cleanlib
+
+$(OBJECT):
+ -@md $(OBJECT)
+
+#######################################################################
+#
+# Dependencies
+#
+#######################################################################
+
+$(VGA_ASM_OBJS): $(MAKEDIR)\makefile \
+ $(OBJECT)\vsa2.inc \
+
+$(VGA_C_OBJS): $(MAKEDIR)\makefile \
+ $(BUILD_DIR)\obj\$(TOOL_LIB) \
+ $(OBJECT)\vsa2.h \
+ $(OBJECT)\isa.h \
+ $(OBJECT)\chipset.h \
+ $(OBJECT)\vr.h \
+ $(OBJECT)\pci.h \
+ $(OBJECT)\lxvg.h \
+ $(OBJECT)\vgdata.h \
+
+######################################################################
+#
+# Common Targets
+#
+######################################################################
+# include common targets and inference rules
+!include $(BUILD_DIR)\rules.mak
+
+######################################################################
+#
+# Inference Rules
+#
+######################################################################
+# Override common inference rules here
+
+{$(INC_DIR)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zni /C $<
+
+{$(INC_DIR)\$(CPU)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zni /C $<
+
+{$(SYSMGR_SRC)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zns /C $<
+
+{$(SYSMGR_SRC)\$(CPU)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zns /C $<
+
+{$(MAKEDIR)}.c{$(OBJECT)}.obj:
+ $(CC) /AT /W3 /G3s /Gx /Oi /c /I$(OBJECT) $(CDEFS) /Fo$@ $<
+
+{$(MAKEDIR)\$(CPU)}.c{$(OBJECT)}.obj:
+ $(CC) /AT /W3 /G3s /Gx /Oi /c /I$(OBJECT) $(CDEFS) /Fo$@ $<
+
+{$(MAKEDIR)}.asm{$(OBJECT)}.obj:
+ $(AS) /nologo $(AS_OPTS) $(CDEFS) /Fo$@ $<
+
+{$(MAKEDIR)\$(CPU)}.asm{$(OBJECT)}.obj:
+ $(AS) /nologo $(AS_OPTS) $(CDEFS) /Fo$@ $<
+
+{$(MAKEDIR)}.h{$(OBJECT)}.h:
+ copy $< $@
+
+{$(USER)\lxvg}.h{$(OBJECT)}.h:
+ copy $< $@
+
+{$(USER)\lxvg}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zns /C $<
+
+{$(USER)\lxvg}.asm{$(OBJECT)}.obj:
+ $(AS) /nologo $(AS_OPTS) $(CDEFS) /Fo$@ $<
+
+{$(USER)\lxvg}.c{$(OBJECT)}.obj:
+ $(CC) /AT /W3 /G3s /Gx /Oi /c /I$(OBJECT) $(CDEFS) /Fo$@ $<
diff --git a/cpu/amd/geode_lx/gplvsa_ii/lxvg/msr.c b/cpu/amd/geode_lx/gplvsa_ii/lxvg/msr.c
new file mode 100755
index 0000000..65c40d9
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/lxvg/msr.c
@@ -0,0 +1,305 @@
+/*
+* Copyright (c) 2007-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+
+
+
+#include "lxvg.h"
+#include "vsa2.h"
+
+#define FOUND 0
+#define UNKNOWN 1
+#define REQ_NOT_FOUND 2
+
+struct tagMSR msrDev[] = {
+ { UNKNOWN, ID_MCP, FAKE_ADDRESS },
+ { UNKNOWN, ID_MC, FAKE_ADDRESS },
+ { UNKNOWN, ID_GP, FAKE_ADDRESS },
+ { UNKNOWN, ID_VG, FAKE_ADDRESS },
+ { UNKNOWN, ID_DF, FAKE_ADDRESS },
+ { UNKNOWN, ID_VIP, FAKE_ADDRESS } };
+// DEBUG
+// { UNKNOWN, ID_MBIU, FAKE_ADDRESS } };
+// DEBUG
+
+#define NUM_DEVS sizeof(msrDev) / sizeof(struct tagMSR)
+
+
+//=================================================================
+// BOOL msrInit(void)
+//
+// Handles the details of finding each possible device on the MBUS.
+// If a given device is not found, its structure is left inited at default.
+// If a given device is found, its structure is updated.
+//
+// This init routine only checks for devices already in the structure.
+//
+// Returns:
+// TRUE - If, for every device, its address was found.
+// FALSE - If, for any device, an error was encountered.
+//
+
+unsigned char msrInit(void)
+{
+ unsigned short issues=0, i;
+
+ //
+ // For each item in the list, try to find its address
+ //
+ for (i=0; i < NUM_DEVS; i++)
+ {
+ msrDev[i].Present = msrFindDevice(&msrDev[i]);
+ if (msrDev[i].Present != FOUND) issues++;
+ }
+
+ if (issues) return(FALSE);
+
+/*
+ //
+ // For each item in the list, get its real device ID
+ //
+ for (i=0; i < NUM_DEVS; i++)
+ msrDev[i].Id = msrIdDevice(msrDev[i].Address);
+*/
+ return(TRUE);
+
+}
+
+
+//=================================================================
+// unsigned short msrFindDevice(struct msr *pDev)
+//
+// Returns:
+// FOUND - if no errors were detected. msrAddress has been updated.
+// REQ_NOT_FOUND - Address for 'devId' is unknown. Caller should
+// call msrInit() first. ptr->Address is not updated.
+//
+// NOTE: The structure default for the 'Present' field is "UNKNOWN".
+// Therefore, if a given id is passed to msrFindDevice, the 'Present'
+// field will be updated with either 'FOUND' or 'REQ_NOT_FOUND'. If
+// a given ID is not passed to msrFindDevice, the 'Present' field will
+// be left as 'UNKNOWN'.
+//
+
+unsigned short msrFindDevice(struct tagMSR *pDev)
+{
+ unsigned long msrAdr;
+ msrAdr = SYS_LOOKUP_DEVICE(pDev->Id,1);
+ if (0 != msrAdr)
+ {
+ pDev->Routing = msrAdr;
+ return(FOUND);
+ }
+
+ // All done...
+ return(REQ_NOT_FOUND);
+}
+
+
+//=================================================================
+// unsigned short msrIdDevice(unsigned long address)
+//
+// Reads the capabilities MSR register (typically 0x2000)
+// and returns the 'id' field (bits 23:8)
+//
+// Returns:
+// Bits 23:8 of MSR low DWORD
+//
+
+unsigned short msrIdDevice(unsigned long address)
+{
+ struct mValue msrValue;
+
+ asmRead(MBD_MSR_CAP, address, &msrValue.high, &msrValue.low);
+
+ return((unsigned short)((msrValue.low & DEVID_MASK) >> 8));
+
+}
+
+
+//=================================================================
+// unsigned short msrRead(unsigned short msrIdx, unsigned short msrReg, struct mValue msrValue)
+//
+// Performs a 64-bit read from 'msrReg' in device 'devID'.
+//
+// Returns:
+// FOUND - if no errors were detected and msrValue has been updated.
+// UNKNOWN - an error was detected. msrValue is not updated.
+// REQ_NOT_FOUND - 'msrAddress' for 'devID' is unknown. Caller
+// should call msrInit() first. msrValue is not updated.
+//
+
+unsigned short msrRead(unsigned short msrIdx, unsigned short msrReg, struct mValue *msrValue)
+{
+
+ if (msrDev[msrIdx].Present == FOUND) {
+ asmRead(msrReg, msrDev[msrIdx].Routing, &msrValue->high, &msrValue->low);
+ }
+
+ return (msrDev[msrIdx].Present);
+
+}
+
+
+//=================================================================
+// unsigned short msrWrite(unsigned short msrIdx, unsigned short msrReg, unsigned long outHi, unsigned long outLo)
+//
+// Performs a 64-bit write to 'msrReg' in device 'devID'.
+//
+// Returns:
+// FOUND - if no errors were detected and msrValue has been updated.
+// UNKNOWN - an error was detected. msrValue is not updated.
+// REQ_NOT_FOUND - 'msrAddress' for 'devID' is unknown. Caller
+// should call msrInit() first. msrValue is not updated.
+//
+
+unsigned short msrWrite(unsigned short msrIdx, unsigned short msrReg, unsigned long outHi, unsigned long outLo)
+{
+ struct mValue mVal;
+
+ if (msrDev[msrIdx].Present == FOUND) {
+ // Incorporate the OR values
+ mVal.high = outHi;
+ mVal.low = outLo;
+
+ asmWrite(msrReg, msrDev[msrIdx].Routing, &mVal.high, &mVal.low);
+ }
+
+ return (msrDev[msrIdx].Present);
+
+}
+
+
+//=================================================================
+// void msrModify(unsigned short msrIdx, unsigned short msrReg, unsigned long maskHi, unsigned long maskLo,
+// unsigned long orHi, unsigned long orLo)
+//
+// Performs a 64-bit read-modify-write of 'msrReg' in device 'msrIdx'.
+// The mask values indicate the bits that are to be changed, so the
+// register values are ANDed with the NOT of the mask values to clear
+// out the affected bits.
+//
+// Returns:
+// NONE
+//
+
+void msrModify(unsigned short msrIdx, unsigned short msrReg, unsigned long maskHi, unsigned long maskLo, unsigned long orHi, unsigned long orLo)
+{
+ struct mValue mVal;
+
+ if (msrDev[msrIdx].Present == FOUND) {
+ asmRead(msrReg, msrDev[msrIdx].Routing, &mVal.high, &mVal.low);
+
+ // Incorporate the AND values
+ mVal.high &= ~maskHi;
+ mVal.low &= ~maskLo;
+
+ // Incorporate the OR values
+ mVal.high |= orHi;
+ mVal.low |= orLo;
+
+ asmWrite(msrReg, msrDev[msrIdx].Routing, &mVal.high, &mVal.low);
+ }
+
+ return;
+
+}
+
+
+//=================================================================
+// void msrSave(unsigned short msrIdx, unsigned short *msrList[], struct mValue *msrValue[])
+//
+// Saves a list of MSRs limited by an index value of 0xFFFF.
+//
+//
+
+void msrSave(unsigned short msrIdx, unsigned short *msrList, struct mValue *msrValue)
+{
+ unsigned char finished = FALSE;
+ unsigned char i = 0;
+
+ if (msrDev[msrIdx].Present == FOUND)
+ {
+ while (FALSE == finished)
+ {
+ if (0xFFFF == msrList[i])
+ finished = TRUE;
+ else
+ {
+ asmRead(msrList[i], msrDev[msrIdx].Routing, &msrValue[i].high, &msrValue[i].low);
+ i++;
+ }
+ }
+ }
+
+ return;
+
+}
+
+
+//=================================================================
+// void msrRestore(unsigned short msrIdx, unsigned short *msrList[], struct mValue *msrValue[])
+//
+// Restores a previously saved list of MSRs limited by an index value of 0xFFFF.
+//
+//
+
+void msrRestore(unsigned short msrIdx, unsigned short *msrList, struct mValue *msrValue)
+{
+ unsigned char finished = FALSE;
+ unsigned char i = 0;
+
+ if (msrDev[msrIdx].Present == FOUND)
+ {
+ while (FALSE == finished)
+ {
+ if (0xFFFF == msrList[i])
+ finished = TRUE;
+ else
+ {
+ asmWrite(msrList[i], msrDev[msrIdx].Routing, &msrValue[i].high, &msrValue[i].low);
+ i++;
+ }
+ }
+ }
+
+ return;
+
+}
+
+
+//=================================================================
+// void msrDump(unsigned short msrIdx, unsigned short msrReg)
+//
+// Performs a 64-bit read of 'msrReg' in device 'msrIdx' for debug.
+//
+// Returns:
+// NONE
+//
+
+void msrDump(unsigned short msrIdx, unsigned short msrReg)
+{
+ struct mValue mVal;
+
+ asmRead(msrReg, msrDev[msrIdx].Routing, &mVal.high, &mVal.low);
+
+ return;
+
+}
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/lxvg/utils.asm b/cpu/amd/geode_lx/gplvsa_ii/lxvg/utils.asm
new file mode 100755
index 0000000..88579a0
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/lxvg/utils.asm
@@ -0,0 +1,271 @@
+;/*
+;* Copyright (c) 2007-2008 Advanced Micro Devices,Inc. ("AMD").
+;*
+;* This library is free software; you can redistribute it and/or modify
+;* it under the terms of the GNU Lesser General Public License as
+;* published by the Free Software Foundation; either version 2.1 of the
+;* License, or (at your option) any later version.
+;*
+;* This code is distributed in the hope that it will be useful,
+;* but WITHOUT ANY WARRANTY; without even the implied warranty of
+;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;* Lesser General Public License for more details.
+;
+;* You should have received a copy of the GNU Lesser General
+;* Public License along with this library; if not, write to the
+;* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+;* Boston, MA 02111-1307 USA
+;*/
+
+
+.MODEL TINY,c
+.CODE
+.586p
+
+;----------------------------------------------------------------------------
+; BASE ADDRESSES
+; These global variables are used to access the memory mapped regions.
+; VSA II maintains a flat 4 Gig selector in FS.
+;----------------------------------------------------------------------------
+
+extrn framebuffer_base:dword
+extrn GPregister_base:dword
+extrn VGregister_base:dword
+extrn DFregister_base:dword
+extrn VIPregister_base:dword
+
+
+
+;----------------------------------------------------------------------------
+; READ_FB_32: Returns a 32-bit value from the frame buffer.
+;
+; Parameter specifies 32-bit offset.
+;----------------------------------------------------------------------------
+
+read_fb_32 proc c address: dword
+
+ mov ebx, [address]
+ add ebx, [framebuffer_base]
+ mov eax, fs:[ebx]
+ mov edx, eax
+ shr edx, 16
+ ret
+
+read_fb_32 endp
+
+;----------------------------------------------------------------------------
+; WRITE_FB_32: Writes a 32-bit value to the frame buffer.
+;
+; Parameters specify 32-bit offset and 32-bit data value.
+;----------------------------------------------------------------------------
+
+write_fb_32 proc c address: dword, data: dword
+
+ mov ebx, [address]
+ add ebx, [framebuffer_base]
+ mov eax, [data]
+ mov fs:[ebx], eax
+ ret
+
+write_fb_32 endp
+
+
+;----------------------------------------------------------------------------
+; READ_GP_32: Returns 32-bit value from the graphics processor register space.
+;
+; Parameter specifies 32-bit offset.
+;----------------------------------------------------------------------------
+
+read_gp_32 proc c address: dword
+
+ mov ebx, [address]
+ add ebx, [GPregister_base]
+ mov eax, fs:[ebx]
+ mov edx, eax
+ shr edx, 16
+ ret
+
+read_gp_32 endp
+
+;----------------------------------------------------------------------------
+; WRITE_GP_32: Writes 32-bit value to graphics processor register space.
+;
+; Parameters specify 32-bit offset and 32-bit data value.
+;----------------------------------------------------------------------------
+
+write_gp_32 proc c address: dword, data: dword
+
+ mov ebx, [address]
+ add ebx, [GPregister_base]
+ mov eax, [data]
+ mov fs:[ebx], eax
+ ret
+
+write_gp_32 endp
+
+
+;----------------------------------------------------------------------------
+; READ_VG_8: Returns 8-bit value from the video generator register space.
+;
+; Parameter specifies 32-bit offset.
+;----------------------------------------------------------------------------
+
+read_vg_8 proc c address: dword
+
+ mov ebx, [address]
+ add ebx, [VGregister_base]
+ mov al, fs:[ebx]
+ ret
+
+read_vg_8 endp
+
+;----------------------------------------------------------------------------
+; WRITE_VG_8: Writes 8-bit value to video generator register space.
+;
+; Parameters specify 32-bit offset and 8-bit data value.
+;----------------------------------------------------------------------------
+
+write_vg_8 proc c address: dword, data: byte
+
+ mov ebx, [address]
+ add ebx, [VGregister_base]
+ mov al, [data]
+ mov fs:[ebx], al
+ ret
+
+write_vg_8 endp
+
+
+;----------------------------------------------------------------------------
+; READ_VG_32: Returns 32-bit value from the video generator register space.
+;
+; Parameter specifies 32-bit offset.
+;----------------------------------------------------------------------------
+
+read_vg_32 proc c address: dword
+
+ mov ebx, [address]
+ add ebx, [VGregister_base]
+ mov eax, fs:[ebx]
+ mov edx, eax
+ shr edx, 16
+ ret
+
+read_vg_32 endp
+
+;----------------------------------------------------------------------------
+; WRITE_VG_32: Writes 32-bit value to video generator register space.
+;
+; Parameters specify 32-bit offset and 32-bit data value.
+;----------------------------------------------------------------------------
+
+write_vg_32 proc c address: dword, data: dword
+
+ mov ebx, [address]
+ add ebx, [VGregister_base]
+ mov eax, [data]
+ mov fs:[ebx], eax
+ ret
+
+write_vg_32 endp
+
+
+;----------------------------------------------------------------------------
+; READ_DF_32: Returns 32-bit value from the display filter register space.
+;
+; Parameter specifies 32-bit offset.
+;----------------------------------------------------------------------------
+
+read_df_32 proc c address: dword
+
+ mov ebx, [address]
+ add ebx, [DFregister_base]
+ mov eax, fs:[ebx]
+ mov edx, eax
+ shr edx, 16
+ ret
+
+read_df_32 endp
+
+;----------------------------------------------------------------------------
+; WRITE_DF_32: Writes 32-bit value to display filter register space.
+;
+; Parameters specify 32-bit offset and 32-bit data value.
+;----------------------------------------------------------------------------
+
+write_df_32 proc c address: dword, data: dword
+
+ mov ebx, [address]
+ add ebx, [DFregister_base]
+ mov eax, [data]
+ mov fs:[ebx], eax
+ ret
+
+write_df_32 endp
+
+
+;----------------------------------------------------------------------------
+; READ_VIP_32: Returns 32-bit value from the video input port register space.
+;
+; Parameter specifies 32-bit offset.
+;----------------------------------------------------------------------------
+
+read_vip_32 proc c address: dword
+
+ mov ebx, [address]
+ add ebx, [VIPregister_base]
+ mov eax, fs:[ebx]
+ mov edx, eax
+ shr edx, 16
+ ret
+
+read_vip_32 endp
+
+;----------------------------------------------------------------------------
+; WRITE_VIP_32: Writes 32-bit value to video input port register space.
+;
+; Parameters specify 32-bit offset and 32-bit data value.
+;----------------------------------------------------------------------------
+
+write_vip_32 proc c address: dword, data: dword
+
+ mov ebx, [address]
+ add ebx, [VIPregister_base]
+ mov eax, [data]
+ mov fs:[ebx], eax
+ ret
+
+write_vip_32 endp
+
+
+asmRead proc public uses bx eax ecx edx, msrReg:word, msrAddr:dword, ptrHigh:word, ptrLow:word
+ mov ecx, msrAddr
+ mov cx, msrReg
+ RDMSR
+
+ mov bx, ptrHigh
+ mov [bx], edx
+ mov bx, ptrLow
+ mov [bx], eax
+
+ ret
+
+asmRead endp
+
+
+asmWrite proc public uses bx eax ecx edx, msrReg:word, msrAddr:dword, ptrHigh:word, ptrLow:word
+
+ mov ecx, msrAddr
+ mov cx, msrReg
+
+ mov bx, ptrHigh
+ mov edx, [bx]
+ mov bx, ptrLow
+ mov eax, [bx]
+
+ WRMSR
+ ret
+
+asmWrite endp
+
+END
diff --git a/cpu/amd/geode_lx/gplvsa_ii/lxvg/vgdata.c b/cpu/amd/geode_lx/gplvsa_ii/lxvg/vgdata.c
new file mode 100755
index 0000000..df33fd8
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/lxvg/vgdata.c
@@ -0,0 +1,55 @@
+/*
+* Copyright (c) 2007-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+// This file declares the data structures and arrays used by lxvg.
+
+
+
+#include "lxvg.h"
+#include "vsa2.h"
+#include "vr.h"
+
+//---------------------------------------------------------------------------
+// MAIN lxvg DATA STRUCTURE
+// This data structure maintains the current lxvg state.
+//---------------------------------------------------------------------------
+
+VGDATA VGdata;
+
+unsigned long vga_config_addr;
+
+unsigned long GPregister_base;
+unsigned long VGregister_base;
+unsigned long DFregister_base;
+unsigned long VIPregister_base;
+unsigned long framebuffer_base;
+
+unsigned long VG_SMI_Mask;
+
+// General system information...
+Hardware SystemInfo;
+
+// The main VG state information flag.
+unsigned long VGState = SF_DISABLED;
+unsigned long lockNest = 0; // Nested SMI recognition scheme
+unsigned long saveLock; // Locking
+
+// The virtual registers
+unsigned short vReg[MAX_VG+1];
+
+// END OF FILE
diff --git a/cpu/amd/geode_lx/gplvsa_ii/lxvg/vgdata.h b/cpu/amd/geode_lx/gplvsa_ii/lxvg/vgdata.h
new file mode 100755
index 0000000..6dd9ead
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/lxvg/vgdata.h
@@ -0,0 +1,36 @@
+/*
+* Copyright (c) 2007-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+// This file defines the main data structure for LXVG.
+
+
+
+#define SIZE_PCI_HEADER 0x50
+
+typedef struct tagVGDATA
+{
+
+ // PCI HEADER
+
+ unsigned char pci_header[SIZE_PCI_HEADER]; // PCI header data
+ unsigned long pci_fb_mask;
+
+} VGDATA;
+
+// END OF FILE
diff --git a/cpu/amd/geode_lx/gplvsa_ii/lxvg/vsa2.c b/cpu/amd/geode_lx/gplvsa_ii/lxvg/vsa2.c
new file mode 100755
index 0000000..91cfb98
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/lxvg/vsa2.c
@@ -0,0 +1,133 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+// Function:
+// This module contains the main code to handle the VSA II interface.
+
+
+#include "vsa2.h"
+#include "vr.h"
+#include "lxvg.h"
+
+// This is required here because of inclusion problems in LXVG.h
+extern Hardware SystemInfo;
+
+// ARRAY TO STORE VSA II MESSAGE PARAMETERS
+unsigned long VSAparam[MAX_MSG_PARAM];
+
+
+//---------------------------------------------------------------------------
+// vsa2_message_loop
+//
+// This is the main routine that handles the VSA II message interface.
+//---------------------------------------------------------------------------
+
+void vsa2_message_loop(void)
+{
+ MSG Msg;
+
+ // SPIN FOREVER ON MESSAGE LOOP
+ // The VSA system manager branches here after loading the VSM. Control
+ // is returned to the system manager using an SMI.
+
+ do {
+
+ // GET THE NEXT MESSAGE
+ // If a message is available, the macro reads the parameter data
+ // from the VSM header and copies it to the VSAparam global array.
+ // If a message is not available, control returns to the main VSA
+ // dispatcher.
+ Msg = SYS_GET_NEXT_MSG(&VSAparam);
+
+ // DECODE THE MESSAGE
+ switch(Msg)
+ {
+ case MSG_INITIALIZE:
+
+ // CHECK IF NORMAL INITIALIZATION
+ // Currently there is no "end of post" initialization.
+ if (VSAparam[0] == EARLY_INIT) {
+
+ // Get information about the system I'm executing on.
+ SYS_GET_SYSTEM_INFO(&SystemInfo);
+
+ // REGISTER FOR VGA VIRTUAL REGISTER EVENTS
+ SYS_REGISTER_EVENT(EVENT_VIRTUAL_REGISTER, VRC_VG, 0, NORMAL_PRIORITY);
+
+ }
+ else
+ {
+ // Now we can handle DPMS and driver active
+ VGState |= SF_END_POST;
+ }
+ break;
+
+ case MSG_EVENT:
+
+ // DECODE THE EVENT
+ decode_vsa2_event();
+ break;
+
+ case MSG_WARM_BOOT:
+ break;
+
+
+ default:
+ break;
+ }
+
+
+ } while(1);
+}
+
+//---------------------------------------------------------------------------
+// decode_vsa2_event
+//
+// This routine is called when the message loop receives an event. For
+// LXVG, this is either a Virtual Rgister event or a pci event
+// (trapping PCI config cycles to our device).
+//---------------------------------------------------------------------------
+
+void decode_vsa2_event(void)
+{
+ // PARSE EVENT
+
+ switch((unsigned short)VSAparam[0])
+ {
+ case EVENT_VIRTUAL_REGISTER:
+ if (VRC_VG == (unsigned char)(VSAparam[1] >> 8))
+ virtual_register_event((unsigned char)VSAparam[1], VSAparam[2], VSAparam[3]);
+
+ break;
+
+ case EVENT_PCI_TRAP:
+ // If LXVG isn't enabled, just leave
+ if (VGState & SF_DISABLED) break;
+
+ // CALL LXVG TO DECODE THE PCI TRAP EVENT
+ // address = VSAparam[1]
+ // size = VSAparam[2], bit 7 indicates write.
+ // data = VSAparam[3]
+
+ pci_trap_event(VSAparam[1], VSAparam[2], VSAparam[3]);
+ break;
+
+ default:
+ break;
+ }
+} \ No newline at end of file
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/bugs.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/bugs.asm
new file mode 100755
index 0000000..a7ec293
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/bugs.asm
@@ -0,0 +1,221 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file contains hardware bug fixes.
+
+include VSA2.INC
+include ISA.INC
+include GX2.INC
+include CHIPSET.INC
+
+.model tiny,c
+.586p
+.CODE
+
+externdef Nested_SMI: proc
+externdef SysMgr_Entry: proc
+externdef Restore_IDT: proc
+externdef Install_IDT: proc
+externdef Sample_SMI_Pin: proc
+externdef Clear_SMI_Pin: proc
+externdef Header_Addr: dword
+externdef HC_Status: dword
+externdef SMI_Sources: dword
+externdef HardwareInfo: Hardware
+
+
+;*******************************************************************************
+; Remove the RTC fix if an RTC VSM is installed.
+;*******************************************************************************
+Remove_RTC_Fix proc
+
+ mov word ptr [Fix_RTC], 0C3F8h ; CLC RET
+ ret
+
+Remove_RTC_Fix endp
+
+
+; *******************************************************************************
+; This routine is called upon entry to a non-nested SMI.
+; *******************************************************************************
+VSA_Entry proc
+
+ ; Patch a "jmp Nested_SMI" at Start
+ mov word ptr ds:[1], OFFSET Nested_SMI-3
+
+ ; Install exception handlers
+ call Install_IDT
+ ret
+
+VSA_Entry endp
+
+
+
+
+
+; *******************************************************************************
+; This routine is called upon exit from a non-nested SMI.
+; It performs:
+; 1) RTC fix
+; 2) USB fix
+; 3) IDT restore
+; 4) Re-enable Suspend Modulation
+;
+; If CF=1 is returned, then loop back to SMI handlers.
+; *******************************************************************************
+VSA_Exit proc
+
+ mov eax, [Header_Addr] ; Restore the original SMM header
+ mov ecx, MSR_SMM_HDR
+ wrmsr
+
+ call Fix_RTC
+ jc short Exit ; Don't exit from VSA
+
+ ; Restore "JMP SysMgr_Entry" at Start
+ mov word ptr ds:[1], OFFSET SysMgr_Entry-3
+
+
+ call Restore_IDT ; Restore IDT
+
+ clc
+
+Exit: ret
+
+VSA_Exit endp
+
+
+
+
+
+
+
+
+
+
+; *******************************************************************************
+; Handle the case where the RTC UIP bit was clear, application code was about to
+; read the RTC, but an SMI occurs. When VSA returns, the RTC is updating, so the
+; application reads a bad value.
+;
+; The Solution:
+;
+; The Time Stamp Counter is read upon entry to VSA. On exit, if UIP is low or
+; it is determined that the SMI has taken < 250 us, then just exit. This leaves
+; 44 us for the application to finish reading the RTC safely. If the SMI has
+; taken > 250 us, then spin for 500 us minus the time spent servicing the SMI.
+; This guarantees the RTC has finished updating. Then set the SET bit, wait for
+; UIP to go low, then clear the SET bit.
+;
+; *******************************************************************************
+RTC_TIME equ 250
+
+Fix_RTC proc
+
+ in al, CMOS_INDEX ; Get RTC index
+ cmp al, 9 ; Only RTC indices 0-9 are UIP sensitive
+ ja Exit
+
+ mov bl, al ; Save RTC index
+ push si
+ mov al, CMOS_STATUS_A ; Read RTC Status A
+ out CMOS_INDEX, al
+ in al, CMOS_DATA
+ test al, UIP
+ jz Restore_RTC_Index
+
+
+ mov al, CMOS_STATUS_B ; Exit if StatusB[SET] = 1
+ out CMOS_INDEX, al
+ in al, CMOS_DATA
+ test al, SET
+ jz Restore_RTC_Index
+
+
+
+ ASSUME SI: PTR System ; Compute time servicing SMI in us
+ mov si, OFFSET VSM_Header.SysStuff
+ rdtsc
+ sub eax, [si+0].StartTime
+ sbb edx, [si+4].StartTime
+ movzx ecx, [HardwareInfo].CPU_MHz
+ cmp edx, ecx ; If sitting in Dowser or Standby too long,
+ jae Restore_RTC_Index ; the divide could overflow.
+ div ecx
+
+ cmp eax, RTC_TIME ; If < RTC_TIME us, exit
+ jb Restore_RTC_Index
+
+
+ call Clear_SMI_Pin
+WaitForUpdate:
+ call Sample_SMI_Pin
+ stc
+ jnz short SMI_Abort ; Yes, go process it
+
+
+ rdtsc ; Wait for additional 300 us
+ sub eax, [si+0].StartTime
+ sbb edx, [si+4].StartTime
+ div ecx
+ cmp eax, RTC_TIME + 300
+ jb WaitForUpdate
+
+ ASSUME SI: NOTHING
+
+
+ ; StatusB[SET] = 1;
+ mov al, CMOS_STATUS_B ; Read RTC StatusB
+ out CMOS_INDEX, al
+ in al, CMOS_DATA
+ test al, SET ; If (SET == 1)
+ jnz short Restore_RTC_Index ; bail
+ or al, SET ; else
+ out CMOS_DATA, al ; SET = 1
+
+ ; Wait for StatusA[UIP] to go inactive
+ mov cx, 0FFFFh ; RTC timeout
+SpinUIP:
+ mov al, CMOS_STATUS_A ; Yes, spin until UIP is clear
+ out CMOS_INDEX, al
+ in al, CMOS_DATA
+ test al, UIP
+ loopnz SpinUIP
+
+ mov al, CMOS_STATUS_B ; SET = 0
+ out CMOS_INDEX, al
+ in al, CMOS_DATA
+ and al, NOT SET
+ out CMOS_DATA, al
+
+Restore_RTC_Index:
+ clc
+SMI_Abort:
+ pop si
+ mov al, bl ; Restore CMOS index
+ out CMOS_INDEX, al
+Exit: ret
+
+
+Fix_RTC endp
+
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/chip.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/chip.asm
new file mode 100755
index 0000000..1630d75
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/chip.asm
@@ -0,0 +1,262 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;********************************************************************************
+;* This file contains the Southbridge specific code.
+;********************************************************************************
+
+
+
+
+include smimac.mac
+include chipset.inc
+include pci.inc
+include sysmgr.inc
+include init.inc
+include cs5536.inc
+
+
+.model small,c
+.586
+.CODE
+
+
+externdef Errors: word
+externdef Device_ID: word
+externdef Chipset_Base: dword
+
+;***********************************************************************
+; Clear all SMI source registers
+;***********************************************************************
+Clear_SMIs proc
+
+ mov ax, [Device_ID] ; Get Southbridge Device ID
+ cmp ax, DEVICE_ID_5536 ; If CS5536, exit
+ clc
+ je Exit
+
+ or [Errors], ERR_NO_CHIPSET
+ stc
+ jmp Exit
+
+Exit: ret
+
+Clear_SMIs endp
+
+
+
+
+;****************************************************************
+; Returns information about the Southbridge
+;
+; On Exit, if CF clear:
+; EBX = PCI address of Southbridge
+; CL = Chipset Revision
+; DX = Device ID
+;****************************************************************
+Get_Sbridge_Info proc
+
+ mov ebx, 80000000h+(15 SHL 11) ; Start at Bus 0; DevNum 15
+SouthbridgeLoop:
+ call Read_PCI32
+ cmp ax, VENDOR_ID_CYRIX ; Is it a Cyrix chipset ?
+ je short CorrectVendorID
+ cmp ax, VENDOR_ID_NATIONAL ; Is it a National Semiconductor chipset ?
+ je short CorrectVendorID
+ cmp ax, VENDOR_ID_AMD ; Is it an AMD chipset ?
+ jne short NextDevice
+CorrectVendorID:
+ shr eax, 16
+ push ax ; Save device ID
+
+ mov bl, 8 ; Read Class Code & Rev ID
+ call Read_PCI32
+ mov cl, al ; Save revision in CL
+ shr eax, 16
+ cmp ax, 0601h ; Is it an ISA bridge ?
+ pop dx
+ mov bl, 0 ; Vendor & Device ID
+ je Exit ; CF is cleared
+
+
+ ; Check the DeviceID
+ cmp dx, DEVICE_ID_5536-1 ; Hardware CS5536 Device ID
+ jne NextDevice
+FoundSB:
+ ; On CS5536, the virtualized Device ID is h/w Device ID + 1
+ inc dx
+ push cx
+ push dx
+ mov ecx, 5100002Fh ; Write-post I/O to port 84h for debug
+ mov edx, 00084001h
+ mov eax, edx
+ or al, 8
+ wrmsr
+ pop dx
+ pop cx
+ jmp Exit
+
+NextDevice:
+ add bh, 8 ; Next device
+ cmp bh, (19 SHL 3) ; Last possible DevNum ?
+ jbe SouthbridgeLoop
+
+ ; Can't find supported Southbridge chipset
+ or [Errors], ERR_NO_CHIPSET
+ stc
+
+Exit: ret
+
+Get_Sbridge_Info endp
+
+
+;****************************************************************
+; Generates a s/w SMI
+;****************************************************************
+Software_SMI proc
+
+ smint
+ ret
+
+Software_SMI endp
+
+
+;*********************************************************************************
+; Reads 32-bit PCI config register specified by EBX
+;*********************************************************************************
+Read_PCI32 proc
+
+ mov dx, PCI_CONFIG_ADDRESS
+ mov eax, ebx
+ out dx, eax
+ mov dx, PCI_CONFIG_DATA
+ in eax, dx
+ ret
+
+Read_PCI32 endp
+
+
+
+
+;*********************************************************************************
+; Writes a 32 bit Southbridge register
+; Input:
+; DL - register offset
+; EAX - value to write
+;*********************************************************************************
+SetReg_32 proc uses bx
+
+ push eax
+ mov bl, dl
+ call Address8
+ pop eax
+ out dx, eax
+ ret
+
+SetReg_32 endp
+
+
+;*********************************************************************************
+; Writes an 8 bit register
+; Input:
+; BL = register #
+; BH = Data
+;*********************************************************************************
+SetReg_8 proc
+
+ call Address8
+ mov al, bh
+ out dx, al
+ ret
+
+SetReg_8 endp
+
+
+
+;*********************************************************************************
+; Reads an 8 bit register
+; Input:
+; BL = register #
+; Output:
+; AL = Data
+;*********************************************************************************
+GetReg_8 proc
+
+ call Address8
+ in al, dx
+ ret
+
+GetReg_8 endp
+
+;*********************************************************************************
+; Helper routine for SetReg_32, SetReg_8 & GetReg_8
+;*********************************************************************************
+Address8 proc
+
+ mov dx, PCI_CONFIG_ADDRESS
+ mov eax, [Chipset_Base]
+ mov al, bl
+ and al, NOT 3
+ out dx, eax
+ mov dx, PCI_CONFIG_DATA
+ and bl, 3
+ add dl, bl
+ ret
+
+Address8 endp
+
+
+
+
+
+;*********************************************************************************
+; Determines the base address of the top-level SMI status register
+; On Exit:
+; EAX = address
+;*********************************************************************************
+Get_SMI_Base proc
+
+ mov ebx, [Chipset_Base] ; Patch SMI_Base
+ add bx, PM_FUNCTION + BAR0
+ call Read_PCI32
+ mov al, SMI_STATUS
+ ret
+
+Get_SMI_Base endp
+
+
+
+;*********************************************************************************
+; Determines the base address of the internal IRQ register
+; On Exit:
+; EAX = address
+;*********************************************************************************
+Get_IRQ_Base proc
+
+ mov ebx, [Chipset_Base] ; Patch SMI_Base
+ add bx, AUDIO_FUNCTION + BAR0 ; Patch IRQ_Base
+ call Read_PCI32
+ mov al, 1Ah
+ ret
+
+Get_IRQ_Base endp
+
+
+
+ END
+ \ No newline at end of file
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/chipset.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/chipset.c
new file mode 100755
index 0000000..9d3e695
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/chipset.c
@@ -0,0 +1,239 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+/*****************************************************************************
+ * The routines in this file translate requests for hardware
+ * support to Southbridge-specific function calls.
+ *****************************************************************************/
+
+
+#include "VSA2.H"
+#include "CHIPSET.H"
+#include "CS5536.H"
+#include "ISA.H"
+#include "SYSMGR.H"
+#include "PROTOS.H"
+#include "GX2.H"
+
+
+// External function prototypes
+extern void MillisecondTimer(UCHAR, EVENT_ENTRY *);
+extern void InitTimers(void);
+extern void Init_CS5536(void);
+extern void pascal Enable_USB_5536(UCHAR, USHORT);
+extern void pascal Address_Decode_5536(UCHAR, USHORT);
+extern void pascal MBus_IO_Trap(ULONG, ULONG, UCHAR);
+extern void pascal MBus_IO_Timeout(ULONG, ULONG, UCHAR);
+extern void pascal A20_Init(UCHAR);
+extern void pascal InactivityTimer(UCHAR, USHORT, UCHAR);
+extern void pascal Program_PWM(UCHAR, UCHAR, USHORT, UCHAR);
+
+// External variables
+extern EVENT_ENTRY Events[];
+extern Hardware HardwareInfo;
+extern ULONG MPCI_NB;
+extern ULONG ATA_Error;
+
+// Local variables:
+typedef void (pascal * CHIPSET_DEPENDENT)(unsigned char, unsigned short);
+CHIPSET_DEPENDENT Address_Decode;
+CHIPSET_DEPENDENT Enable_USB;
+GPIO_FUNCTION GPIO_Control;
+ULONG ClocksPerMs;
+
+
+//*****************************************************************************
+// Initializes the Southbridge
+//*****************************************************************************
+void InitChipset(void)
+{
+
+ ClocksPerMs = HardwareInfo.CPU_MHz * 1000L;
+
+ InitTimers();
+
+ switch (HardwareInfo.Chipset_ID) {
+
+ case DEVICE_ID_5536:
+
+ Address_Decode = Address_Decode_5536;
+ Enable_USB = Enable_USB_5536;
+
+ // Initialize the CS5536
+ Init_CS5536();
+ break;
+
+ }
+}
+
+
+
+//*****************************************************************************
+// Enables trapping of a PCI function
+// Return value:
+// 0 = not supported
+// 1 = already enabled
+// 2 = previously disabled
+//*****************************************************************************
+UCHAR pascal Enable_PCI_Trapping(USHORT PCI_Address, UCHAR EnableFlag)
+{ UCHAR ReturnValue = 0;
+
+
+ // Call the appropriate chipset routine
+ switch (HardwareInfo.Chipset_ID) {
+
+ default:
+ // Use PBUS MSR to trap this address
+ Trap_PCI_IDSEL(PCI_Address, EnableFlag);
+ ReturnValue = 1;
+ break;
+ }
+
+ return ReturnValue;
+
+}
+
+
+//*****************************************************************************
+// Diables an event
+//*****************************************************************************
+void pascal Disable_Event(EVENT Event, USHORT Index)
+{
+ Enable_Event(Event, Index, 0);
+}
+
+//*****************************************************************************
+// Enables an event
+//
+// EnableFlag:
+// 0 = Disable event
+// 1 = Enable event
+// 2 = Reset event logic (e.g. timer, GPIO)
+//*****************************************************************************
+void pascal Enable_Event(EVENT Event, USHORT Index, UCHAR EnableFlag)
+{ USHORT Device_ID;
+ UCHAR Error = 0;
+ ULONG Param1, Param2;
+ EVENT_ENTRY * EventPtr;
+
+ Device_ID = HardwareInfo.Chipset_ID;
+
+ EventPtr = &Events[Index];
+ Param1 = EventPtr->Param1;
+ Param2 = EventPtr->Param2;
+
+
+ switch (Event) {
+
+ case EVENT_USB:
+ Enable_USB(EnableFlag, (USHORT)Param1);
+ case EVENT_KEL:
+ break;
+
+ case EVENT_TIMER:
+ // Initialize RemainingInterval field to Interval
+ if (EnableFlag == 1) {
+ EventPtr->RemainingInterval = EventPtr->Param1;
+ }
+ MillisecondTimer(EnableFlag, EventPtr);
+ break;
+
+ case EVENT_IO_TRAP:
+ MBus_IO_Trap(Param1, Param2, EnableFlag);
+ break;
+
+ case EVENT_DEVICE_TIMEOUT:
+ // If programmer forgot to specify Instance, assume 1st instance
+ if ((USHORT)Param2 == 0x0000) {
+ (USHORT)Param2 = 1;
+ }
+ Param2 |= GLIU_ID;
+ case EVENT_IO_TIMEOUT:
+ MBus_IO_Timeout(Param1, Param2, EnableFlag);
+ break;
+
+ case EVENT_PME:
+ (USHORT)Param2 |= PME;
+ case EVENT_GPIO:
+ GPIO_Control(Param1, Param2, EnableFlag);
+ break;
+
+ case EVENT_PCI_TRAP:
+ if (Enable_PCI_Trapping((USHORT)Param1, EnableFlag) == 0) {
+ // Companion I/O can't trap requested PCI function.
+ Error = ERR_PCI_TRAP;
+ }
+ break;
+
+ case EVENT_ACPI:
+ switch (Device_ID) {
+ case DEVICE_ID_5536:
+ Enable_ACPI_5536(EnableFlag);
+ break;
+ }
+ break;
+
+ case EVENT_PWM:
+ // GPIO pin Duty cycle (%) Rate (ms)
+ Program_PWM((UCHAR)Param1, (UCHAR)(Param2 >> 16), (USHORT)(Param1 >> 16), EnableFlag);
+
+ // 8 LSBs are GPIO pin number
+ Param1 &= 0x000000FF;
+ // Mask all except valid flags
+ Param2 &= OPEN_DRAIN | PULLDOWN | PULLUP | INVERT;
+ // Insert flags appropriate to PWM
+ Param2 |= OUTPUT | NO_ASMI;
+ if (EnableFlag) {
+ Param2 |= AUX1;
+ }
+ GPIO_Control(Param1, Param2, EnableFlag);
+ break;
+
+ } // end switch (Event)
+
+ if (Error) {
+ Report_VSM_Error(Error, Event, Param1);
+ }
+}
+
+
+
+void pascal Set_Address_Decode(USHORT Address, UCHAR Decode)
+{
+ Address_Decode(Decode, Address);
+}
+
+
+
+
+void pascal Allocate_Resource(USHORT Resource, ULONG Param)
+{
+
+ switch ((UCHAR)Resource) {
+
+ case RESOURCE_IRQ:
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/cpu.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/cpu.asm
new file mode 100755
index 0000000..52b5ec0
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/cpu.asm
@@ -0,0 +1,59 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* Implementation of routines specific to the Vail core.
+
+
+.model tiny,c
+.586p
+.ALPHA
+DGROUP GROUP _CODE, _TEXT
+_CODE SEGMENT PUBLIC use16 'CODE'
+ ASSUME DS:_CODE
+
+
+
+
+
+
+
+
+
+;************************************************************************
+;************************************************************************
+Sample_SMI_Pin proc
+ ret
+Sample_SMI_Pin endp
+
+
+
+;************************************************************************
+;************************************************************************
+Clear_SMI_Pin proc
+
+ ret
+Clear_SMI_Pin endp
+
+
+
+
+_CODE ENDS
+
+
+ END
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/cpu_init.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/cpu_init.asm
new file mode 100755
index 0000000..21e6c9b
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/cpu_init.asm
@@ -0,0 +1,339 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file contains code specific to the processor core.
+
+include vsa2.inc
+include gx2.inc
+include sysmgr.inc
+include init.inc
+include chipset.inc
+
+.model small,c
+.586
+
+.CODE
+
+
+externdef BIOS_ECX: dword
+externdef BIOS_EDX: dword
+externdef VSA_Image:byte
+
+SMM_Size dd 0
+FooGlue dd 54000000h
+
+;***********************************************************************
+; Sets CPU dependent fields in the SMM header
+; On entry:
+; SI = pointer to VSM header
+;***********************************************************************
+Set_CPU_Fields proc
+
+SMM_CONTROL equ EXTL_SMI_EN + INTL_SMI_EN + SMM_INST_EN + NEST_SMI_EN
+
+ mov (VSM_Header PTR [si]).SysStuff.State.SMM_CTL_MSR, SMM_CONTROL
+ ret
+
+Set_CPU_Fields endp
+
+
+
+
+
+;***********************************************************************
+; - Sets the SMM entry point to the location in EBX
+; - Sets the SMM header location
+; - Write protects the SMM regions
+;***********************************************************************
+Init_SMM_Region proc
+
+ ; Set the SMM entry point
+ mov ecx, MSR_SMM_LOC
+ mov eax, ebx
+ mov edx, [SMM_Size] ; SMM Code Limit
+ wrmsr
+
+ ; Set the SMM header location
+ lea eax, (VSM_Header PTR [eax]).SysStuff.State + sizeof(SmiHeader)
+ mov ecx, MSR_SMM_HDR
+ xor edx, edx
+ wrmsr
+
+
+ ; Write protect the SMM memory
+ mov ecx, MSR_RCONF_SMM
+ rdmsr
+ or al, REGION_WP
+ wrmsr
+
+ ret
+
+Init_SMM_Region endp
+
+
+
+
+
+
+;***********************************************************************
+; Returns information about the LX CPU
+; On exit:
+; AX = CPU Revision
+; SI = CPU ID
+; BX = PCI MHz
+; CX = CPU MHz
+; DX = DRAM MHz
+;***********************************************************************
+Get_CPU_Info proc
+
+ mov ecx, 4C000014h ; GLCP_SYS_RSTPLL
+ rdmsr
+
+ ; PCI Speed
+ mov bx, 33
+ test al, 1 SHL 7 ; RSTPPL_LOWER_PCISPEED_SHIFT
+ jz not66
+ mov bx, 66
+not66:
+ push bx ; save PCI speed
+
+ ; CPU Speed
+ mov ax, 333 ; 33.3MHZ * 10
+
+ ror dx, 1 ; RSTPLL_UPPER_CPUMULT_SHIFT
+ mov bx, dx
+ rol dx, 1 ; RSTPLL_UPPER_CPUMULT_SHIFT
+ push dx ; save RSTPLL
+ and bx, 1Fh
+ inc bx ; 0 = multiply by 1....
+ mul bx ; ax=PCI * bl=Mul
+
+ ; Rounding divide
+ mov bx, 10
+ xor dx, dx
+ div bx ; ax= quotent and dx=remainder
+ cmp dx, 5
+ jb NoRound ; can round because of /10
+ inc ax ; round up
+NoRound:
+ pop dx ; restore RSTPLL
+ pop bx ; restore PCI * 10
+ push ax ; save CPU speed
+
+
+ ; DRAM speed
+ mov ax, 333 ; 33.3MHZ * 10
+
+ ror dx, 7 ; RSTPLL_UPPER_GLMULT_SHIFT
+ mov bx, dx
+ rol dx, 7 ; RSTPLL_UPPER_GLMULT_SHIFT
+ push dx ; save RSTPLL
+ and bx, 1Fh
+ inc bx ; 0 = multiply by 1....
+ mul bx ; ax=PCI * bl=Mul
+
+ ; Rounding divide
+ mov bx, 10
+ xor dx, dx
+ div bx ; ax= quotent and dx=remainder
+ cmp dx, 5
+ jb NoRoundmem ; can round because of /10
+ inc ax ; round up
+NoRoundmem:
+
+ ; DDR is 1/2 GeodeLink speed.
+ xor dx, dx
+ mov bx, 2
+ div bx
+ push ax ; save mem speed
+
+ ; Get CPU Revision
+ mov cx, 0017h
+ rdmsr
+ push ax
+
+ mov ecx, 10002000h ; Read MBIU0 Capabilities MSR
+ rdmsr
+ and ah, 0Fh ; Extract 4 LSBs of DEVID
+ cmp ah, 04h ; Is it LX ?
+ mov si, DEVICE_ID_GX2
+ jne RestoreInfo
+ mov si, DEVICE_ID_LX ; Yes
+ mov [FooGlue], 4C000020h ; FooGlue is at Northbridge MCP + 20h
+RestoreInfo:
+ pop ax ; Restore CPU Revision
+ pop dx ; Restore DRAM MHz
+ pop cx ; Restore CPU MHz
+ pop bx ; Restore PCI MHz
+ ret
+
+Get_CPU_Info endp
+
+
+
+;***********************************************************************
+; Returns the SMM information
+; On Exit:
+; EAX = SMM entry point
+; BX = Size of SMM memory in KB
+;***********************************************************************
+Get_SMM_Region proc
+ Local Attributes: byte
+
+ mov ecx, MSR_RCONF_DEFAULT
+ rdmsr
+ mov [Attributes], al
+
+
+ mov ecx, [BIOS_ECX] ; Descriptor for SMM memory
+ rdmsr
+ cmp cl, 27h ; P2D_BMO or P2D_RO ?
+ jbe BaseMaskOffset
+ mov ebx, eax ; P2D_RO
+ shl eax, 12 ; EAX = SMM base
+ shrd ebx, edx, 8 ; EBX = end of SMM range
+ and bx, 0F000h
+ sub ebx, eax ; Compute length of range
+ add ebx, 1000h ; Adjust for 4KB granularity
+ shr ebx, 10 ; Convert to KB
+ jmp short Save_SMM_Base
+
+BaseMaskOffset:
+ mov ebx, eax ; BX = length of SMM memory in KB
+ shrd eax, edx, 8 ; EAX = Base
+ and ax, 0F000h
+
+ or ebx, 0FFF00000h
+ neg ebx
+ shl ebx, 2 ; Adjust for 4KB granularity
+
+Save_SMM_Base:
+ push eax ; Save SMM base
+ push bx ; Save SMM size in KB
+
+ shl ebx, 10 ; Convert KB to bytes
+ dec ebx
+ mov [SMM_Size], ebx ; Save size for MSR_SMM_LOC
+
+ ; Set SMM RCONF
+ and bx, 0F000h
+ mov edx, ebx ; SMM_TOP = SMM_BASE + sizeof(SMM region)
+ add edx, eax
+ mov dl, [Attributes] ; SMM active properties mirror RCONF_DEFAULT
+ or ah, 1 ; Set Enable
+ mov al, dl ; SMM inactive properties (R/W for now)
+ and al, NOT REGION_WP
+ mov ecx, MSR_RCONF_SMM
+ wrmsr
+
+ pop bx ; BX = size of SMM region in KB
+ pop eax ; EAX = base of SMM region
+
+ ret
+
+Get_SMM_Region endp
+
+
+;****************************************************************
+; Enables SMIs
+;****************************************************************
+Enable_SMIs proc
+
+ ; Enable internal and external SMIs
+ mov ecx, MSR_SMM_CTRL
+ rdmsr
+ or eax, INTL_SMI_EN + EXTL_SMI_EN
+ wrmsr
+
+ ret
+
+Enable_SMIs endp
+
+
+
+
+;***********************************************************************
+; Enables the SMM instructions
+;***********************************************************************
+Enable_SMM_Instr proc
+
+ mov ecx, MSR_SMM_CTRL
+ rdmsr
+ or eax, SMM_INST_EN
+ wrmsr
+ ret
+
+Enable_SMM_Instr endp
+
+
+
+
+;***********************************************************************
+; Disables the A20 masking at the processor.
+;***********************************************************************
+Disable_A20 proc
+
+ mov ecx, [FooGlue]
+ add cx, FG_A20M
+ rdmsr
+ and al, NOT A20M ; A20M = 0
+ wrmsr
+ ret
+
+Disable_A20 endp
+
+
+
+
+
+;***********************************************************************
+; Gets the size of physical memory
+; On Exit:
+; EAX = physical memory size in bytes
+;***********************************************************************
+Get_Memory_Size proc
+
+ mov ecx, [BIOS_EDX] ; P2D_R descriptor of physical memory
+ jecxz Exit
+ rdmsr
+; EDX = 2000001F
+; EAX = FDF00100
+; 1MB thru <512MB-192K)
+
+ shrd eax, edx, 20 ; Extract PMAX field
+ shl eax, 12 ; Convert units from 4KB to bytes
+Exit: ret
+
+Get_Memory_Size endp
+
+
+
+
+
+
+; The linker won't allow code to be put in a PARA aligned segment.
+; The following will align the next module to a paragraph boundary.
+TEXT SEGMENT PARA 'CODE'
+
+ db 16 dup (0)
+
+TEXT ENDS
+
+ END
+ \ No newline at end of file
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/cs5536.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/cs5536.c
new file mode 100755
index 0000000..25e1321
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/cs5536.c
@@ -0,0 +1,328 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//*****************************************************************************
+//* Routines related to the CS5536
+//*****************************************************************************
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "PROTOS.H"
+#include "GX2.H"
+#include "VPCI.H"
+#include "DESCR.H"
+#include "PCI.H"
+#include "CHIPSET.H"
+#include "CS5536.H"
+#include "MDD.H"
+
+ULONG Mbiu2 = MPCI_SOUTH + 0x00020000; // 2.4.2.0.1
+ULONG MPCI_SB = MPCI_SOUTH; // 2.4.2.0.0
+ULONG MCP_SB = MPCI_SOUTH + 0x00700000; // 2.4.2.7.0
+ULONG OHCI1_Smi=0, OHCI2_Smi=0;
+CAPABILITIES Southbridge_MBIU;
+ULONG ATA_Error;
+
+// External Functions:
+extern void CS5536_GPIO_Init(void);
+extern void Init_MDD(void);
+extern ULONG Write_EPCI(UCHAR, ULONG);
+extern void ACPI_PMS_SWAPSiF(void);
+extern PCI_HEADER_ENTRY * Get_Structure(USHORT);
+extern void pascal Handle_EHCI_Wr(PCI_HEADER_ENTRY *);
+extern PCI_HEADER_ENTRY * pascal Find_Register(PCI_HEADER_ENTRY *, UCHAR);
+
+// External Variables:
+extern ULONG MPCI_NB, MDD_Base;
+extern Hardware HardwareInfo;
+extern PCI_HEADER_ENTRY ISA_Hdr[];
+extern PCI_HEADER_ENTRY Audio_Hdr[];
+extern VIRTUAL_DEVICE * SouthBridge;
+extern PCI_HEADER_ENTRY * Virtual_5536[];
+
+//***********************************************************************
+// Enables USB SMIs on CS5536
+//***********************************************************************
+void pascal Enable_USB_5536(UCHAR EnableFlag, USHORT Instance)
+{ ULONG MsrData;
+ UCHAR Mask;
+
+ // OHCI is the only valid setting for now
+ if (Instance == 1) {
+
+ MsrData = Read_MSR_LO(OHCI1_Smi);
+ Mask = 0x10 << (Instance-1);
+ if (EnableFlag) {
+ (UCHAR)MsrData &= ~Mask;
+ } else {
+ (UCHAR)MsrData |= Mask;
+ }
+ Write_MSR_LO(OHCI1_Smi, MsrData);
+
+ } else {
+ static UCHAR * Msg_Enable = "enable";
+ static UCHAR * Msg_Disable = "disable";
+ UCHAR * OnOff;
+
+ if (EnableFlag) {
+ OnOff = Msg_Enable;
+ } else {
+ OnOff = Msg_Disable;
+ }
+ Log_Error("Attempt to %s invalid USB instance: 0x%04X", OnOff, Instance);
+ }
+}
+
+
+//***********************************************************************
+// Enables/disables writes to PM1_CNT register
+//***********************************************************************
+void Enable_ACPI_5536(UCHAR EnableFlag)
+{ ULONG MsrAddr, MsrData;
+
+ // Get address to MDDs SMI MSR
+ MsrAddr = MDD_Base;
+ (USHORT)MsrAddr = MBD_MSR_SMI;
+
+ // Get current value
+ MsrData = Read_MSR_LO(MsrAddr);
+
+ // Set/clear enable for trapping of writes to PM1_CNT
+ if (EnableFlag) {
+ MsrData |= PM1_CNT_SSMI_EN;
+
+ } else {
+ MsrData &= ~PM1_CNT_SSMI_EN;
+ }
+
+ // Update the MSR
+ Write_MSR_LO(MsrAddr, MsrData);
+
+}
+
+
+//***********************************************************************
+// Sets positive/subtractive decode
+//***********************************************************************
+void pascal Address_Decode_5536(UCHAR Decode, USHORT Address)
+{
+ // Not yet implemented
+}
+
+//***********************************************************************
+// Initializes BARs in the Southbridge virtual headers
+//***********************************************************************
+void Init_SB_Headers(void)
+{ ULONG MsrAddr, BAR_Value;
+ USHORT PCI_Addr, Bar;
+
+
+ //*********************************************
+ // Allocate BARs for CS5536's F0 header
+ //*********************************************
+ MsrAddr = MDD_Base;
+ for (Bar = BAR0; Bar <= BAR5; Bar += 4) {
+ ULONG BAR_Length;
+
+ (UCHAR)MsrAddr = ISA_Hdr[Bar/4].LBar;
+
+ // Get current LBAR value
+ BAR_Value = Read_MSR_LO(MsrAddr);
+
+ // Determine the length of the I/O range
+ BAR_Length = ISA_Hdr[Bar/4].Mask;
+
+ // Allocate a PCI BAR corresponding to the LBAR
+ PCI_Addr = Allocate_BAR(RESOURCE_IO, Bar, BAR_Length, ID_MDD, ISA_Hdr[0].Device_ID);
+
+ // Synchronize with any LBARs that have already been initialized by the BIOS
+ Virtual_PCI_Write_Handler(PCI_Addr, DWORD_IO, BAR_Value);
+
+ }
+
+ // Initialize Southbridge's COMMAND register
+ (UCHAR)PCI_Addr = COMMAND;
+ Virtual_PCI_Write_Handler(PCI_Addr, BYTE_IO, SPECIAL_CYCLES | IO_SPACE);
+
+
+ //*********************************************
+ // Allocate Audio BAR
+ //*********************************************
+ Allocate_BAR(RESOURCE_IO, BAR0, 128, ID_AC97, Audio_Hdr[0].Device_ID);
+}
+
+
+//***********************************************************************
+// Initializes the CS5536 chipset
+//***********************************************************************
+void Init_CS5536(void)
+{ register PCI_HEADER_ENTRY * Header;
+ ULONG MsrAddr, USB20_Msr, MsrData[2];
+ UCHAR i, CS5536_DevNum;
+
+
+
+ //*********************************************
+ // Get routing address of CS5536's MPCI
+ //*********************************************
+ MPCI_SB = MPCI_NB;
+ CS5536_DevNum = (UCHAR)((USHORT)HardwareInfo.Chipset_Base >> 11);
+ MsrData[0] = Read_MSR_LO(MPCI_NB + MPCI_ExtMSR);
+ while (MsrData[0]) {
+ MPCI_SB += 1L << 23;
+ if ((UCHAR)MsrData[0] == CS5536_DevNum) {
+ break;
+ }
+ MsrData[0] >>= 8;
+ }
+
+ //*********************************************
+ // Get routing address to Southbridge's GLIU
+ //*********************************************
+ Mbiu2 = MPCI_SB + 0x00020000;
+
+
+ // Read Southbridge's GLIU capabilities
+ Read_MSR(Mbiu2 + MBIU_CAP, &MsrData[0]);
+
+
+ //*********************************************
+ // Initialize GLIU2
+ //*********************************************
+ Parse_Capabilities(MsrData, &Southbridge_MBIU);
+ // The NP2D_SCO field is actually the NP2D_BMK field
+ Southbridge_MBIU.NP2D_BMK = Southbridge_MBIU.NP2D_SCO;
+ Southbridge_MBIU.NP2D_SCO = 0;
+
+ // SWAPSiF for erroneous P2D_BM/BMK numbering
+ if (HardwareInfo.Chipset_ID == DEVICE_ID_5536) {
+ Southbridge_MBIU.NP2D_BM = 3;
+ }
+
+ // Find address of MCP in Southbridge
+ MCP_SB = Find_MBus_ID(ID_MCP, 2) & 0xFFFF0000;
+
+ // Default range for IDE P2D_BM descriptor is 16 bytes.
+ // Change range to 8 bytes.
+ MsrAddr = Mbiu2 + MSR_IO_DESCR;
+ Write_MSR_LO(MsrAddr, Read_MSR_LO(MsrAddr) | 0x00000008);
+
+ // Initialize the descriptor structure for Southbridge's GLIU
+ Init_MBIU((UCHAR *)&Southbridge_MBIU, Mbiu2);
+
+ // Get Southbridge's Revision ID from MCP
+ ISA_Hdr[REVISION_ID/4].Revision_ID = (UCHAR)Read_MSR_LO(MCP_SB + 0x0017);
+
+
+ //*********************************************
+ // Initialize the MDD
+ //*********************************************
+ Init_MDD();
+
+ //*********************************************
+ // Add MPCI R0-R15 to available descriptor list
+ //*********************************************
+ MsrAddr = MPCI_SB;
+ // REGION_R15 is reserved for port 84h
+ for ((USHORT)MsrAddr = REGION_R0; (UCHAR)MsrAddr <= REGION_R15-1; MsrAddr++) {
+ if (Init_Descr(MPCI_RCONF, MsrAddr)) {
+ break;
+ }
+ }
+
+ // Enable SSMI Received event
+ (USHORT)MsrAddr = MBD_MSR_SMI;
+ Write_MSR_LO(MsrAddr, Read_MSR_LO(MsrAddr) | SSMM);
+
+ // Add ATA LBAR to available descriptor list
+ // NOTE: Not really part of MDD (just leveraging MDD logic)
+ MsrAddr = Find_MBus_ID(ID_ATA, 1);
+ ATA_Error = MsrAddr;
+ (USHORT)ATA_Error = MBD_MSR_ERROR;
+
+#if 1
+ // Enable SSMI Received event
+ (USHORT)MsrAddr = MBD_MSR_SMI;
+ Write_MSR_LO(MsrAddr, Read_MSR_LO(MsrAddr) | SSMM);
+#endif
+
+ (USHORT)MsrAddr = MSR_LBAR_ATA;
+ Init_Descr(MDD_LBAR, MsrAddr);
+
+
+ //*********************************************
+ // Initialize the virtual Southbridge headers
+ //*********************************************
+ Init_SB_Headers();
+
+ //*********************************************
+ // Initialize the GPIO logic
+ //*********************************************
+ CS5536_GPIO_Init();
+
+ //*********************************************
+ // Install workaround for ACPI & PMS bugs
+ //*********************************************
+ ACPI_PMS_SWAPSiF();
+
+
+ // Find address of USB 2.0
+ OHCI1_Smi = USB20_Msr = Find_MBus_ID(ID_USB_20, 1);
+
+ if (OHCI1_Smi == 0) {
+ return;
+ }
+ (USHORT)OHCI1_Smi = MBD_MSR_SMI;
+
+ // Set PMEEN for each USB 2.0 controller
+ for (i=USBMSROHCB; i<=USBMSRUOCB; i++) {
+ (UCHAR)USB20_Msr = i;
+ Read_MSR(USB20_Msr, MsrData);
+ MsrData[1] |= PMEEN;
+ Write_MSR(USB20_Msr, MsrData);
+ }
+
+
+
+ // Initialize the USB 2.0 devices
+ for (i=0; i <= 7; i++) {
+
+ // If the header exists...
+ if (Header = Virtual_5536[i]) {
+ // Read Class Code to see it is USB class
+ if ((Header+REVISION_ID/4)->Class == 0x0C03) {
+ // Initialize USB LBAR
+ (UCHAR)USB20_Msr = (Header+BAR0/4)->LBar;
+ Init_Descr(USB_LBAR, USB20_Msr);
+
+ // Allocate the PCI BAR
+ Allocate_BAR(RESOURCE_MMIO, BAR0, (Header+BAR0/4)->Mask, ID_USB_20, Header->Device_ID);
+
+ // If EHCI, initialize FLADJ
+ if (Header->Device_ID == DEVICE_ID_AMD_EHCI) {
+ Header = Find_Register(Header, SRBN_REG);
+ if ((USHORT)Header != UNIMPLEMENTED_REGISTER) {
+ Header->FLADJ = 0x20;
+ Handle_EHCI_Wr(Header);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/debug.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/debug.asm
new file mode 100755
index 0000000..9856d5c
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/debug.asm
@@ -0,0 +1,220 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* Debug routines for GX2-based systems
+
+
+include vsa2.inc
+include vr.inc
+include sysmgr.inc
+
+.model tiny,c
+.586p
+.CODE
+
+
+CR equ 0Dh
+LF equ 0Ah
+
+externdef SMM_Header: SmiHeader
+
+;***********************************************************************
+; Hex dump routines
+;***********************************************************************
+Hex_32 proc pascal Num:dword
+
+ pushad
+ mov ebx, Num
+ mov cx, 8
+@@: rol ebx, 4
+ call Hex_4
+ loop @b
+ call Space
+ popad
+ ret
+
+Hex_32 endp
+
+
+
+Hex_16 proc pascal Num:word
+
+ pusha
+ mov cx, 4
+ mov bx, Num
+@@: rol bx, 4
+ call Hex_4
+ loop @b
+ call Space
+ popa
+ ret
+
+Hex_16 endp
+
+
+Hex_8 proc pascal Num:byte
+
+ pusha
+ mov cx, 2
+ mov bl, Num
+@@: rol bl, 4
+ call Hex_4
+ loop @b
+ call Space
+ popa
+ ret
+
+Hex_8 endp
+
+
+Hex_4: mov al, bl
+ and al, 0Fh
+ add al, '0' ; Convert to ASCII
+ cmp al, '9'
+ jbe @f
+ add al, 7 ; 'A'-'F'
+@@: mov dx, DBG_PORT
+ jmp Char
+
+Space: mov al, ' '
+Char: out dx, al
+ in al, 80h
+ ret
+
+
+
+
+
+;***********************************************************************
+; Displays SMI source(s)
+;
+; On Entry:
+; ECX = SMI source(s)
+;***********************************************************************
+Show_SMI_Source proc
+
+ pushad
+ cld
+
+ mov dx, DBG_PORT
+ lea bx, SMI_Source_Strings-2
+MsgLoop:jecxz Exit
+ add bx, 2
+ shr ecx, 1
+ jnc MsgLoop
+
+ mov si, [bx] ; Get message ptr
+ cmp si, OFFSET Msg_DescrHit
+ jne short CharLoop
+ mov ax, [SMM_Header].IO_addr
+ cmp ax, VRC_INDEX
+ je IsVirtualReg
+ cmp ax, VRC_DATA
+ jne CharLoop
+IsVirtualReg:
+ lea si, [Msg_VirtReg]
+CharLoop:
+ lodsb
+ or al, al ; End of string ?
+ jz Blank
+ out dx, al ; No, display next character
+ jmp CharLoop
+
+Blank: mov al, ' ' ; Yes, display trailing blank
+ out dx, al
+ jmp MsgLoop
+
+Exit: popad
+ ret
+
+
+Show_SMI_Source endp
+
+
+SMI_Source_Strings:
+ dw OFFSET Msg_PM
+ dw OFFSET Msg_Audio
+ dw OFFSET Msg_ACPI
+ dw OFFSET Msg_VG
+ dw OFFSET Msg_Reserved
+ dw OFFSET Msg_Retrace
+ dw OFFSET Msg_VGA_Timer
+ dw OFFSET Msg_A20
+ dw OFFSET Msg_SW_SMI
+ dw OFFSET Msg_GTT
+ dw OFFSET Msg_Reserved
+ dw OFFSET Msg_MFGPT
+ dw OFFSET Msg_NMI
+ dw OFFSET Msg_Reset
+ dw OFFSET Msg_USB
+ dw OFFSET Msg_Graphics
+
+ dw OFFSET Msg_GT1
+ dw OFFSET Msg_GT2
+ dw OFFSET Msg_USR_DEF_1
+ dw OFFSET Msg_VirtReg
+ dw OFFSET Msg_USR_DEF_3
+ dw OFFSET Msg_PCI_Trap
+ dw OFFSET Msg_Reserved
+ dw OFFSET Msg_Reserved
+ dw OFFSET Msg_MPCI
+ dw OFFSET Msg_DescrHit
+ dw OFFSET Msg_Stat_Hit
+ dw OFFSET Msg_PIC
+ dw OFFSET Msg_KEL
+ dw OFFSET Msg_PME
+ dw OFFSET Msg_BlockIO
+ dw OFFSET Msg_Reserved
+
+
+Msg_Reserved db '???',0
+Msg_VG db 'VG',0
+Msg_PM db 'PM',0
+Msg_Audio db 'Audio',0
+Msg_ACPI db 'ACPI',0
+Msg_Retrace db 'Vsync',0
+Msg_VGA_Timer db 'Vga',0
+Msg_SW_SMI db 'S/W',0
+Msg_A20 db 'A20',0
+Msg_GTT db 'GTT',0
+Msg_MFGPT db 'MFGPT',0
+Msg_NMI db 'NMI',0
+Msg_GT1 db 'GT1',0
+Msg_GT2 db 'Timer',0
+Msg_USB db 'USB',0
+Msg_Reset db 'Reset',0
+Msg_Graphics db 'VGA',0
+Msg_USR_DEF_1 db 'PIC',0
+Msg_VirtReg db 'VR',0
+Msg_USR_DEF_3 db 'UDef3',0
+Msg_PCI_Trap db 'PCI',0
+Msg_MPCI db 'MPCI',0
+Msg_DescrHit db 'I/O',0
+Msg_Stat_Hit db 'StatHit',0
+Msg_PIC db 'PIC',0
+Msg_KEL db 'KEL',0
+Msg_PME db 'PME',0
+Msg_BlockIO db 'BlockIO',0
+
+
+
+
+
+ end
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/descr.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/descr.c
new file mode 100755
index 0000000..c08da73
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/descr.c
@@ -0,0 +1,521 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* Utility routines for managing descriptors
+//******************************************************************************
+
+
+
+#include "VSA2.H"
+#include "PROTOS.H"
+#include "GX2.H"
+#include "VPCI.H"
+#include "DESCR.H"
+#include "SYSMGR.H"
+
+
+
+// External variables:
+extern UCHAR NumMbius;
+extern UCHAR MBIU1_SelfReference;
+
+// Local variables:
+UCHAR NumDescriptors = 1;
+DESCRIPTOR MSRs[MAX_DESCR]={0};
+UCHAR DynamicVSALoad=0;
+
+
+//***********************************************************************
+// Computes the 32 LSBs of an IOD_SC descriptor from Address/Range
+//***********************************************************************
+ULONG pascal Compute_IOD_SC(ULONG * AddressPtr, USHORT * RangePtr, UCHAR Flag)
+{ ULONG IO_Mask, Address;
+ USHORT Range;
+ UCHAR Addr_LSBs, Bit_Mask, Max_Bits;
+
+ Address = * AddressPtr;
+ Range = * RangePtr;
+
+ // Set IOD_SC Base field
+ IO_Mask = Address & 0x0000FFF8;
+
+ // Compute the R/W attributes
+ if (!(Address & WRITES_ONLY)) {
+ IO_Mask |= REN;
+ }
+ if (!(Address & READS_ONLY)) {
+ IO_Mask |= WEN;
+ }
+
+ // Initialize bit mask
+ Addr_LSBs = (UCHAR)Address & 0x7;
+ Max_Bits = 8 - Addr_LSBs;
+ if (Range > Max_Bits) {
+ Range = Max_Bits;
+ }
+ Bit_Mask = (UCHAR)(0x01 << Range) - 1;
+ Bit_Mask <<= Addr_LSBs;
+
+ // Insert byte enables
+ IO_Mask |= (ULONG)Bit_Mask << 24;
+
+
+ // Adjust Address & Range parameters by # bytes handled by this descriptor
+ if (Flag) {
+ * AddressPtr += (ULONG)Range;
+ * RangePtr -= (USHORT)Range;
+ }
+ return IO_Mask;
+}
+
+
+//***********************************************************************
+// Returns the default value for the given descriptor Type
+//***********************************************************************
+void pascal Get_Descriptor_Default(UCHAR Type, ULONG * Msr)
+{
+
+ *Msr = *(Msr+1) = 0x00000000;
+
+ switch (Type) {
+
+ case IOD_BM:
+ case P2D_BM:
+ case P2D_BMO:
+ case P2D_BMK:
+ *Msr = 0xFFF00000;
+ *(Msr+1) = 0x000000FF;
+ break;
+
+ case P2D_R:
+ case P2D_RO:
+ *(Msr) = 0x000FFFFF;
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+//***********************************************************************
+// Initializes a MSRs[] entry
+//***********************************************************************
+UCHAR pascal Init_Descr(UCHAR Type, ULONG MsrAddr)
+{ register DESCRIPTOR * Descr;
+
+ // Keep count of total # descriptors
+ if (NumDescriptors >= MAX_DESCR) {
+ // Log an error: Not enough descriptor entries.
+ Report_VSM_Error(ERR_NO_MORE_DESCRIPTORS, MAX_DESCR, 0x77 );
+ return 0x01;
+ }
+
+
+
+ Descr = &MSRs[NumDescriptors++];
+
+ // Initialize the descriptor entry
+ Descr->Mbiu = NumMbius;
+ Descr->Split = 0x00;
+ Descr->Flag = AVAILABLE;
+ Descr->Type = Type;
+ Descr->Link = 0x00;
+ Descr->Owner = 0x0000;
+ Descr->MsrAddr = MsrAddr;
+ Descr->Physical = 0x00000000;
+
+ return 0x00;
+}
+
+
+//***********************************************************************
+// Returns a descriptor to the available pool
+//***********************************************************************
+void Deallocate_Descriptor(DESCRIPTOR * Descr)
+{
+ // Mark MSR available
+ Descr->Flag = AVAILABLE;
+ Descr->Link = 0x00;
+ Descr->Owner = 0x0000;
+ // Set MSR to default value
+ Get_Descriptor_Default(Descr->Type, Descr->MsrData);
+ Write_MSR(Descr->MsrAddr, Descr->MsrData);
+
+}
+
+
+
+
+//***********************************************************************
+// Restores all descriptors owned by VSA to their default values.
+// Used when VSA is installed from DOS.
+//***********************************************************************
+void ReInit_Descriptors(void)
+{ register USHORT Index;
+ register DESCRIPTOR * Descr;
+ ULONG MDD_Msr;
+
+ DynamicVSALoad = 1;
+
+ Descr = &MSRs[1];
+
+ MDD_Msr = Find_MBus_ID(ID_MDD, 1) & ROUTING;
+
+ // Restore VSA-owned MSRs to their default values
+ for (Index = 1; Index < NumDescriptors; Index++) {
+ // Don't zero MDD LBARs
+ if ((Descr->MsrAddr & ROUTING) == MDD_Msr) {
+ Descr->Flag = AVAILABLE;
+ } else {
+ if (Descr->MsrAddr == 0x5100002F) {
+ continue;
+ }
+ Deallocate_Descriptor(Descr);
+ }
+ Descr++;
+ }
+
+ NumDescriptors = 1;
+
+}
+
+
+
+
+
+
+//***********************************************************************
+// Searches for an unused descriptor of the specified type(s) on the
+// specified MBIU.
+// NOTE: This implementation makes multiple passes through the table, but
+// this removes the requirement that they be in a particular order.
+//***********************************************************************
+UCHAR pascal Allocate_Descriptor(UCHAR Type, UCHAR EndType, ULONG Msr)
+{ register DESCRIPTOR * Descr;
+ register UCHAR Index;
+ ULONG Mask;
+ UCHAR Incr = 1;
+
+ if (EndType < Type) {
+ Incr = 0xFF;
+ }
+ EndType += Incr;
+
+ do {
+
+ // Find an available descriptor of the right type
+ Index = 1;
+ do {
+
+ Descr = &MSRs[Index];
+
+ if ((Descr->Flag & AVAILABLE) && (Type == Descr->Type)) {
+
+ switch (Type) {
+
+ case MPCI_RCONF:
+ case GX2_RCONF:
+ // Any register will do
+ Mask = 0x00000000;
+ break;
+
+ case USB_LBAR:
+ case MDD_LBAR:
+ // Entire MSR must match
+ Mask = 0xFFFFFFFF;
+ break;
+
+ case EPCI:
+ // Entire routing field must match
+ Mask = ROUTING;
+ break;
+
+ default:
+ // MSR must match in 1st 3 routing fields
+ Mask = 0xFF800000;
+ break;
+
+ }
+
+ if ((Descr->MsrAddr & Mask) == (Msr & Mask)) {
+ // Mark descriptor in-use
+ Descr->Flag &= ~AVAILABLE;
+ return Index;
+ }
+ }
+
+ Index++;
+ } while (Index != NumDescriptors);
+ Type += Incr;
+ } while (Type != EndType);
+
+ return DESCRIPTOR_NOT_FOUND;
+}
+
+
+
+
+//***********************************************************************
+// Searches existing descriptors for the specified address range.
+// If possible, a descriptor is updated to add/remove the new range.
+// Parameter Enable:
+// = 0, the range is removed
+// = 1, the range is added for I/O timeout
+// = 2, the range is added for I/O trap
+// = 3, the range is being searched (SYS_IO_DESCRIPTOR)
+//***********************************************************************
+UCHAR pascal Find_Matching_IO_Descriptor(ULONG * AddressPtr, USHORT * RangePtr, UCHAR Enable)
+{ UCHAR Index, HitFlag, DescrFlag;
+ ULONG Attributes, Mask;
+ USHORT Address, StartRange, EndRange, Length, Range;
+ register DESCRIPTOR * Descr;
+ static ULONG GLIU_Masks[3] = {NOT_GLIU0, NOT_GLIU1, NOT_GLIU2};
+
+ Range = * RangePtr;
+ Address = (USHORT) * AddressPtr;
+ Attributes = * AddressPtr;
+
+
+ // Scan descriptors for those used for I/O trap or timeout
+ // NOTE: We must be careful about mixing I/O traps with I/O address that
+ // are directed to Northbridge devices. This may cause multiple
+ // MBUI descriptors set to the same address.
+ for (Index = 1; Index < NumDescriptors; Index++) {
+
+ Descr = &MSRs[Index];
+ DescrFlag = Descr->Flag;
+
+ // Only examine allocated descriptors
+ if (DescrFlag & AVAILABLE) {
+ continue;
+ }
+
+ // Ignore descriptors that route transactions Northbound
+ if (Descr->MsrData[1] >> 29 == MBIU1_SelfReference) {
+ continue;
+ }
+
+ // If an MBIU is to be excluded, don't allow a match on that MBIU
+ if (Attributes & GLIU_Masks[Descr->Mbiu]) {
+ continue;
+ }
+
+
+
+ // Check if this descriptor matches the requested address range.
+ // Cases:
+ // - Descriptor needs to be split, since I/O ranges are not compatible.
+ // - Subtractive port: timeout is set for this I/O range
+ // - It is currently routed to an MBus device: change Port to 0
+ // - Address ranges need to be merged
+ switch (Descr->Type) {
+
+ case IOD_SC:
+ HitFlag = 1;
+ // Does the I/O range overlap an existing Swiss-cheese descriptor ?
+ if ((USHORT)Descr->MsrData[0] == (Address & 0xFFF8)) {
+ UCHAR CurrentByteEnables, NewByteEnables, CommonByteEnables;
+
+ // Yes, compute the byte enables
+ Mask = Compute_IOD_SC(AddressPtr, RangePtr, 1);
+ CurrentByteEnables = (UCHAR)(Descr->MsrData[0] >> 24);
+ NewByteEnables = (UCHAR)(Mask >> 24);
+
+ // Compute # bytes of overlap
+ CommonByteEnables = CurrentByteEnables & NewByteEnables;
+ Length = 0;
+ while (CommonByteEnables) {
+ if (CommonByteEnables & 1) {
+ Length++;
+ }
+ CommonByteEnables >>= 1;
+ }
+
+ switch (Enable) {
+
+ case 0:
+ if (CurrentByteEnables == NewByteEnables) {
+ if (Descr->MsrData[0] == Mask) {
+ // Entire range is being disabled
+ Deallocate_Descriptor(Descr);
+ } else {
+ // Only change REN/WEN, not byte enables
+ Mask &= 0x00FFFFFF;
+ }
+ } else {
+ // Only subset of range is being disabled
+ // Don't change REN/WEN
+ Mask &= ~(WEN | REN);
+ }
+ if (Length) {
+ // Don't change base address
+ (USHORT)Mask = 0x0000;
+ Descr->MsrData[0] &= ~Mask;
+ } else {
+ HitFlag = 0;
+ }
+ break;
+
+ case 1:
+ if ((Descr->MsrData[0] & (WEN | REN)) != (Mask & (WEN | REN))) {
+ // R/W attributes mismatch; descriptor is not compatible
+ HitFlag = 0;
+ } else {
+ // Descriptors are compatible: set additional byte enables
+ Descr->MsrData[0] |= Mask;
+ }
+ break;
+
+ case 2:
+ if ((Descr->MsrData[0] & (WEN | REN)) != (Mask & (WEN | REN))) {
+ // R/W attributes mismatch.
+ // Descriptor is not compatible unless byte enables are the same.
+ if (CurrentByteEnables != NewByteEnables) {
+ HitFlag = 0;
+ break;
+ }
+ }
+
+ // Descriptors are compatible: set additional byte enables
+ Descr->MsrData[0] |= Mask;
+
+ // If the descriptors overlap but not exactly (disjoint enables)
+ // then Address & Range need to be handled according to special cases
+ if (CurrentByteEnables != NewByteEnables) {
+ // Restore Address & Range (modified above by Compute_IOD_SC)
+ * (USHORT *)AddressPtr = Address;
+ * RangePtr = Range;
+
+ if (NewByteEnables > CurrentByteEnables) {
+ // For example: 01110000 - NewByteEnables
+ // 00011100 - CurrentByteEnables
+ // Increment Address by overlapped range
+ * (USHORT *)AddressPtr += Length;
+ }
+
+ // Decrement Range by overlapped range
+ * RangePtr -= Length;
+ }
+ break;
+
+ case 3:
+ if (CurrentByteEnables & NewByteEnables) {
+ return Index;
+ }
+ continue;
+
+ } // end switch(Enable)
+
+ Write_MSR(Descr->MsrAddr, Descr->MsrData);
+
+ if (HitFlag == 0) {
+ // Restore Address/Range.
+ * (USHORT *)AddressPtr = Address;
+ * RangePtr = Range;
+ continue;
+ } else {
+ return Index;
+ }
+ }
+ break;
+
+ case IOD_BM:
+ HitFlag = 0;
+ Mask = ~((USHORT)Descr->MsrData[0])+1;
+ Length = 1 << BitScanForward(Mask);
+ StartRange = Descr->Address;
+ EndRange = StartRange + Length;
+
+ // Check if the requested range is covered by the existing descriptor
+ if ((Address >= StartRange) && (Address < EndRange)) {
+ if (Enable == 3) {
+ return Index;
+ }
+ HitFlag = 1;
+ Range -= Address - StartRange;
+ }
+
+
+ Mask = Address ^ StartRange;
+
+ if (Enable) {
+ if (HitFlag) {
+ Length = Range;
+ break; //??????????????????????????
+ }
+ } else {
+
+ // Range is being disabled
+ if (HitFlag) {
+ if (Length <= Range) {
+ Deallocate_Descriptor(Descr);
+ } else {
+ // Descriptor must be trimmed
+ if (Address == StartRange) {
+ // I/O Base needs to be adjusted up
+ Descr->MsrData[0] += (ULONG)Range << 20;
+ Mask = (1L << Range) - 1;
+ Length = Range;
+ } else {
+ // Adjust IO_MASK to trim range down
+ (USHORT)Descr->MsrData[0] &= ~(Range-1);
+ }
+
+ // Adjust IO_MASK
+ (USHORT)Descr->MsrData[0] |= Mask;
+ HitFlag = 2;
+ }
+ }
+ }
+
+ // Recompute start address of descriptor
+ if (HitFlag == 2) {
+ Descr->Address = (USHORT)(Descr->MsrData[0] >> 20);
+ Descr->Address |= (USHORT)(Descr->MsrData[1] << 12);
+ }
+
+ if (HitFlag) {
+ if (Length > Range) {
+ Length = Range;
+ }
+ * AddressPtr += Length;
+ * RangePtr -= Length;
+
+ // Write descriptor if matching descriptor was modified
+ if (HitFlag == 2) {
+ Write_MSR(Descr->MsrAddr, Descr->MsrData);
+ }
+ return Index;
+ }
+ break;
+
+
+ } // end switch(Descr->Type)
+ }
+
+ // If a descriptor gets deallocated, need to clean up any possible links to a BAR
+ return DESCRIPTOR_NOT_FOUND;
+}
+
+
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/descr.h b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/descr.h
new file mode 100755
index 0000000..c13f51e
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/descr.h
@@ -0,0 +1,47 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+// Descriptor types: (don't use 0)
+
+
+#define P2D_BM 1
+#define P2D_BMO 2
+#define P2D_R 3
+#define P2D_RO 4
+#define P2D_SC 5
+#define P2D_SCO 6
+#define P2D_BMK 7
+#define IOD_BM 8
+#define IOD_SC 9
+#define MDD_LBAR 10
+#define GX2_RCONF 11
+#define MPCI_RCONF 12
+#define EPCI 13
+#define USB_LBAR 14
+
+
+typedef struct {
+ unsigned long Mbiu;
+ unsigned long SubtrPid;
+ unsigned long ClockGating;
+ unsigned char NumCounters; // Number of statistic counters on this MBIU
+ unsigned char ActiveCounters; // Count of # active statistic counters in use
+} MBIU_INFO;
+
+#define MAX_MBIU 3
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/errors.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/errors.c
new file mode 100755
index 0000000..7d23c22
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/errors.c
@@ -0,0 +1,371 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//*****************************************************************************
+//* Implements the error reporting code.
+//*****************************************************************************
+
+
+
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "PROTOS.H"
+
+extern void pascal write_flat_size(ULONG, ULONG, UCHAR);
+extern ULONG pascal Get_SysCall_Address(ULONG, UCHAR);
+extern ULONG VSMs_EAX;
+extern ULONG Saved_EAX, Saved_EBX, Saved_ECX, Saved_EDX, Saved_ESI, Saved_EDI;
+extern ULONG Current_VSM;
+
+
+#define MAX_ERROR_BUFFER 500
+UCHAR ErrorStrings[MAX_ERROR_BUFFER];
+UCHAR * ErrorBuffer = ErrorStrings;
+UCHAR * CurrentError;
+UCHAR * PreviousError = ErrorStrings;
+UCHAR DuplicateFlag;
+
+int letbase;
+
+
+//***************************************************************************
+// Input:
+// BH - 1 to clear error log
+// CL - Error number (0 for 1st)
+// Exit:
+// AL - 0 if last error
+//***************************************************************************
+void Get_Errors()
+{ USHORT ErrorNumber, Flag;
+ ULONG Destination;
+
+ // Get parameters passed in from INFO
+ Flag = (UCHAR)(Saved_EBX >> 8);
+ ErrorNumber = (UCHAR)Saved_ECX;
+ Destination = Saved_EDI;
+
+ (UCHAR)Saved_EAX = 0x00;
+
+ // If no errors, return AL = 0;
+ if (ErrorBuffer == ErrorStrings) {
+ return;
+ }
+
+ // If request for 1st error, initialize buffer ptr
+ if (ErrorNumber == 0) {
+ CurrentError = ErrorStrings;
+ }
+
+
+ // Copy next message to EDI
+ while (CurrentError < ErrorBuffer) {
+ // Copy 1 byte of error message
+ write_flat_size(Destination++, (ULONG)*CurrentError, BYTE_IO);
+ // If end of this message, return
+ if (*CurrentError++ == 0) {
+
+ write_flat_size(Destination-1, '$', BYTE_IO);
+
+ (UCHAR)Saved_EAX = 1;
+
+ // Is this the last message ?
+ if (*CurrentError == 0) {
+ // Clear error log ? (/E flag)
+ if (Flag == 1) {
+ PreviousError = ErrorBuffer = ErrorStrings;
+ }
+ }
+ return;
+ }
+ }
+}
+
+
+
+
+
+
+//*****************************************************************************
+//*****************************************************************************
+static void printchar(char **str, int c)
+{
+ out_8(DBG_PORT, (UCHAR)c);
+ in_8(0x80);
+ if (ErrorBuffer < &ErrorStrings[MAX_ERROR_BUFFER-2]) {
+ *ErrorBuffer = c;
+ if (*ErrorBuffer++ != *PreviousError++) {
+ DuplicateFlag = 0;
+ }
+ }
+}
+
+#define PAD_RIGHT 1
+#define PAD_ZERO 2
+
+//*****************************************************************************
+//*****************************************************************************
+static int prints(char **out, const char *string, int width, int pad)
+{ register int pc = 0, padchar = ' ';
+
+ if (width > 0) {
+ register int len = 0;
+ register const char *ptr;
+
+ for (ptr = string; *ptr; ++ptr) {
+ ++len;
+ }
+
+ if (len >= width) {
+ width = 0;
+ } else {
+ width -= len;
+ }
+
+ if (pad & PAD_ZERO) {
+ padchar = '0';
+ }
+ }
+
+
+ if (!(pad & PAD_RIGHT)) {
+ for ( ; width > 0; --width) {
+ printchar(out, padchar);
+ ++pc;
+ }
+ }
+
+ for ( ; *string ; ++string) {
+ printchar(out, *string);
+ ++pc;
+ }
+
+ for ( ; width > 0; --width) {
+ printchar(out, padchar);
+ ++pc;
+ }
+
+ return pc;
+}
+
+/* the following should be enough for 32 bit int */
+#define PRINT_BUF_LEN 12
+
+//*****************************************************************************
+// Prints an integer with the specified formatting
+//*****************************************************************************
+static int printi(char **out, unsigned long u, int base, int sg, int width, int pad)
+{ char print_buf[PRINT_BUF_LEN];
+ register char *s;
+ register int t, neg = 0, pc = 0;
+
+ if (u == 0) {
+ print_buf[0] = '0';
+ print_buf[1] = '\0';
+ return prints (out, print_buf, width, pad);
+ }
+ if (sg && (base == 10) && (u & 0x8000)) {
+ neg = 1;
+ u = ~u;
+ u++;
+ }
+
+ s = print_buf + PRINT_BUF_LEN-1;
+ *s = '\0';
+
+ while (u) {
+ t = (int)(u % base);
+ if (t >= 10 ) {
+ t += letbase - '0' - 10;
+ }
+ *--s = t + '0';
+ u /= base;
+ }
+
+ if (neg) {
+ if (width && (pad & PAD_ZERO) ) {
+ printchar(out, '-');
+ ++pc;
+ --width;
+ } else {
+ *--s = '-';
+ }
+ }
+
+ return pc + prints(out, s, width, pad);
+}
+
+//*****************************************************************************
+//*****************************************************************************
+static int print(char **out, int *varg)
+{ register int width, pad;
+ register int pc = 0;
+ register char *format = (char *)(*varg++);
+ char scr[2];
+ unsigned long number;
+ char *s;
+
+
+ for (; *format != 0; ++format) {
+ if (*format == '%') {
+ ++format;
+ pad = 0;
+ if (*format == '\0') {
+ break;
+ }
+
+ switch (*format) {
+ case '%':
+ printchar(out, *format);
+ ++pc;
+ continue;
+
+ case '-':
+ ++format;
+ pad = PAD_RIGHT;
+ break;
+ }
+
+ while (*format == '0') {
+ ++format;
+ pad |= PAD_ZERO;
+ }
+
+ for (width = 0; *format >= '0' && *format <= '9'; ++format) {
+ width *= 10;
+ width += *format - '0';
+ }
+
+ letbase = 'a';
+ switch (*format) {
+
+ case 's':
+ s = *((char **)varg++);
+ pc += prints (out, s ? s :"(null)", width, pad);
+ break;
+
+ case 'u':
+ number = *varg++;
+ pc += printi (out, number, 10, 0, width, pad);
+ break;
+
+ case 'd':
+ number = *varg++;
+ pc += printi (out, number, 10, 1, width, pad);
+ break;
+
+ case 'x':
+// pc += printi (out, number, 16, 0, width, pad);
+// break;
+
+ case 'X':
+ letbase = 'A';
+ number = (USHORT)*varg++;
+ if (width > 4) {
+ number |= (ULONG)(*varg++) << 16;
+ }
+ pc += printi (out, number, 16, 0, width, pad);
+ break;
+
+ case 'c':
+ // char are converted to int then pushed on the stack
+ scr[0] = *varg++;
+ scr[1] = '\0';
+ pc += prints (out, scr, width, pad);
+ break;
+
+ } // end switch
+
+ } else {
+ printchar(out, *format);
+ ++pc;
+ }
+ } // end for
+
+ if (out) {
+ **out = '\0';
+ }
+ return pc;
+}
+
+//*****************************************************************************
+//*****************************************************************************
+void Log_Error(const char *format, ...)
+{ register int *varg = (int *)(&format);
+ UCHAR * SavedErrorBuffer;
+ UCHAR * SavedPrevious;
+
+ SavedErrorBuffer = ErrorBuffer;
+ SavedPrevious = PreviousError;
+ if (PreviousError == ErrorStrings) {
+ DuplicateFlag = 0;
+ } else {
+ DuplicateFlag = 1;
+ }
+
+ // Store a formatted error message
+ print(0, varg);
+
+ // Terminate the error buffer
+ if (ErrorBuffer < &ErrorStrings[MAX_ERROR_BUFFER]) {
+ *(ErrorBuffer++) = 0;
+ }
+
+ // Same error as previous?
+ if (DuplicateFlag) {
+ // Yes, then restore ptrs
+ PreviousError = SavedPrevious;
+ ErrorBuffer = SavedErrorBuffer;
+ *(ErrorBuffer) = 0;
+ } else {
+ // No, then advance previous error buffer ptr
+ PreviousError = SavedErrorBuffer;
+ }
+
+}
+
+
+
+//*****************************************************************************
+// Inserts an error entry into the error log.
+//*****************************************************************************
+void pascal Error_Report(UCHAR ErrorCode, ULONG Info1, ULONG Info2, ULONG Vsm, UCHAR Depth)
+{ ULONG CallingAddress;
+ static UCHAR ErrorString[50];
+
+ CallingAddress = Get_SysCall_Address(Vsm, Depth);
+
+ Log_Error("Error code 0x%02X reported at %08X. Parameters: 0x%08X and 0x%08X.", \
+ ErrorCode, CallingAddress, Info1, Info2);
+}
+
+
+//*****************************************************************************
+// Reports an error from a VSM.
+//*****************************************************************************
+void pascal Report_VSM_Error(UCHAR ErrorCode, ULONG Info1, ULONG Info2)
+{
+ if (Current_VSM == 0) {
+ Error_Report(ErrorCode, Info1, Info2, SysMgr_VSM, 0);
+ } else {
+ Error_Report(ErrorCode, Info1, Info2, Current_VSM, 1);
+ }
+}
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/events.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/events.c
new file mode 100755
index 0000000..3dbbc16
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/events.c
@@ -0,0 +1,616 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* This file contains code for:
+//* 1) Initialization of the Events[] array
+//* 2) Registering events
+//* 3) Sending event messages
+//******************************************************************************
+
+
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "PROTOS.H"
+
+
+#define MAX_HIT 10 // Max. # of hits on any single event
+
+// External function prototypes:
+extern USHORT FilterTimer(EVENT_ENTRY *, EVENT);
+extern UCHAR VSM_Is_Yielded(VSM);
+
+// External variables:
+extern ULONG VSM_Ptrs[];
+
+// Local variables:
+//*****************************************************************************
+// The first MAX_EVENT entries are indexed by the EVENT code.
+// The Link field contains the index of the next VSM registered for that event.
+// A link of 00h terminates the list.
+//*****************************************************************************
+EVENT_ENTRY Events[MAX_REGISTRATIONS];
+UCHAR FreeEvent; // Head of available Events[] entries
+ULONG MsgPacket[MAX_MSG_PARAM+1];
+ULONG MsgParams[MAX_HIT][4];
+
+UCHAR * VsmNames[] = {
+ "SYS_MGR",
+ "AUDIO",
+ "VGA",
+ "LEGACY",
+ "PM",
+ "OHCI",
+ "i8042",
+ "DEBUGGER",
+ "ACPI",
+ "APM",
+ "OEM_ACPI",
+ "SMB",
+ "BATTERY",
+ "RTC",
+ "S2D",
+ "EXT_AMP",
+ "PCMCIA",
+ "SPY",
+ "NETWORK",
+ "GPIO",
+ "KEYBOARD",
+ "MOUSE",
+ "USB",
+ "FLASH",
+ "INFRARED",
+ "THERMAL",
+ "NULL",
+ "MPEG",
+ "VIP",
+ "LPC",
+ "VUART",
+ "MICRO",
+ "USER1",
+ "USER2",
+ "USER3",
+ "SYSINFO",
+ "SUPERIO",
+ "EHCI",
+};
+
+UCHAR * EventNames[] = {
+ "????",
+ "GRAPHICS",
+ "AUDIO",
+ "USB",
+ "ACPI",
+ "ACPI_TIMER",
+ "IO_TRAP",
+ "IO_TIMEOUT",
+ "PME",
+ "KEL",
+ "VIDEO_INACTIVITY",
+ "GPIO",
+ "SOFTWARE_SMI",
+ "PCI_TRAP",
+ "VIRTUAL_REGISTER",
+ "NMI",
+ "TIMER",
+ "DEVICE_TIMEOUT",
+ "SEMAPHORE",
+ "VBLANK",
+ "A20",
+ "SMB",
+ "RTC",
+ "THERMAL",
+ "LPC",
+ "UART",
+ "BLOCKIO",
+};
+
+
+//*****************************************************************************
+// Copies an Events[] entry
+//*****************************************************************************
+void pascal Copy_Event(USHORT From, USHORT To)
+{
+ Events[To].Vsm = Events[From].Vsm;
+ Events[To].Param1 = Events[From].Param1;
+ Events[To].Param2 = Events[From].Param2;
+ Events[To].Param3 = Events[From].Param3;
+ Events[To].Link = Events[From].Link;
+ Events[To].Priority = Events[From].Priority;
+}
+
+
+
+//*****************************************************************************
+// Initializes the Events[] array
+//*****************************************************************************
+void Initialize_Events(void)
+{ int i;
+
+ Events[0].RemainingInterval = 0xFFFFFFFF;
+
+ for (i = 0; i < MAX_REGISTRATIONS ; i++) {
+ Events[i].Priority = 0xffff;
+ Events[i].Index = i;
+ }
+
+ // Initialize the list of free event entries
+ for (i = MAX_REGISTRATIONS-2; i > MAX_EVENT ; i--) {
+ Events[i].Link = i+1;
+ }
+ FreeEvent = MAX_EVENT+1;
+}
+
+//*****************************************************************************
+// Checks Events[EventIndex] for parameters matching those in MsgPacket[].
+// Return value is EventIndex if the parameters match else 0x00.
+//*****************************************************************************
+USHORT pascal FilterEvent(EVENT Event, EVENT EventIndex)
+{ USHORT IO_Hit, IO_Base, IO_Range, ClassIndex, RdWrAttribute;
+ UCHAR Size;
+ ULONG Vsm;
+ register EVENT_ENTRY * EventPtr;
+ USHORT PCI_Hit;
+ static ULONG PCI_Data;
+ static USHORT PCI_Addr;
+ static UCHAR PCI_Size;
+
+ EventPtr = &Events[EventIndex];
+ Vsm = EventPtr->Vsm;
+
+ switch (Event) {
+
+ case EVENT_USB:
+ if ((UCHAR)MsgPacket[2] == (UCHAR)EventPtr->Param1) {
+ return EventIndex;
+ }
+ break;
+
+ case EVENT_TIMER:
+ // Check if the registered interval has expired
+ return FilterTimer(EventPtr, EventIndex);
+
+ case EVENT_GPIO:
+ // Verify the pin & edge match the event registration
+ if (MsgPacket[1] == EventPtr->Pin && (MsgPacket[2] & EventPtr->Attributes)) {
+ // If GPIO is Sleep button being used to wake system, don't send event
+ return EventIndex;
+ }
+ break;
+
+ case EVENT_PME:
+ // MsgPacket[1] = ACPI GPE0_STS
+ // MsgPacket[2] = ACPI PM1_STS
+ if (EventPtr->Attributes & GPE) {
+ if ((1L << EventPtr->Pme) & MsgPacket[1]) {
+ return EventIndex;
+ }
+ }
+ if (EventPtr->Attributes & PM1) {
+ if ((1L << EventPtr->Pm1) & MsgPacket[2]) {
+ return EventIndex;
+ }
+ }
+ break;
+
+ case EVENT_IO_TRAP:
+ case EVENT_IO_TIMEOUT:
+ IO_Base = EventPtr->IO_Base;
+ IO_Range = EventPtr->IO_Range;
+ IO_Hit = (USHORT)MsgPacket[2];
+ // Check address range
+ if ((IO_Hit >= IO_Base) && (IO_Hit <= (IO_Base+IO_Range-1))) {
+
+ if (Event == EVENT_IO_TIMEOUT) {
+ return EventIndex;
+ }
+
+ // Filter reads/writes
+ if (MsgPacket[1] & 2) {
+ RdWrAttribute = READS_ONLY >> 16;
+ } else {
+ RdWrAttribute = WRITES_ONLY >> 16;
+ }
+ if (!(EventPtr->Flags & RdWrAttribute)) {
+ return EventIndex;
+ }
+ }
+ break;
+
+ case EVENT_VIRTUAL_REGISTER:
+ // Check for correct Class::Index
+ ClassIndex = (USHORT)MsgPacket[1];
+ if ((ClassIndex >= EventPtr->ClassLow) && (ClassIndex <= EventPtr->ClassHigh)) {
+ return EventIndex;
+ }
+ break;
+
+ case EVENT_PCI_TRAP:
+ if (EventIndex == EVENT_PCI_TRAP) {
+ // Save original parameters
+ PCI_Addr = (USHORT)MsgPacket[1];
+ PCI_Size = (UCHAR)MsgPacket[2];
+ PCI_Data = MsgPacket[3];
+ } else {
+ // Restore original parameters
+ (USHORT)MsgPacket[1] = PCI_Addr;
+ (UCHAR)MsgPacket[2] = PCI_Size;
+ MsgPacket[3] = PCI_Data;
+ }
+
+ // Ignore SysMgr's virtualization
+ if (Vsm == SysMgr_VSM) {
+ break;
+ }
+
+ if (MsgPacket[2] & 0x20000) {
+ RdWrAttribute = READS_ONLY >> 16;
+ } else {
+ RdWrAttribute = WRITES_ONLY >> 16;
+ }
+
+
+ PCI_Hit = PCI_Addr;
+ Size = PCI_Size & DWORD_IO;
+
+ while (Size) {
+
+ // Check for PCI address match after applying mask
+ if (EventPtr->PCI_Addr == (PCI_Hit & ~(EventPtr->PCI_Mask))) {
+
+ // Filter reads/writes
+ if (!(EventPtr->Flags & RdWrAttribute)) {
+ // Limit Size to correct boundaries
+ Size = PCI_Size & DWORD_IO;
+ switch (PCI_Hit & 0x3) {
+ case 2:
+ if (Size == DWORD_IO) {
+ Size = WORD_IO;
+ }
+ break;
+ case 3:
+ Size = BYTE_IO;
+ break;
+ }
+ MsgPacket[2] &= ~DWORD_IO;
+ MsgPacket[2] |= Size;
+ (USHORT)MsgPacket[1] = PCI_Hit;
+ return EventIndex;
+ }
+ }
+
+ // Don't cross DWORD boundaries
+ if ((++PCI_Hit & 0x3) == 0) {
+ break;
+ }
+ MsgPacket[3] >>= 8;
+ if (!(PCI_Size & IO_WRITE)) {
+ MsgPacket[3] |= 0xFF000000;
+ }
+ Size >>= 1;
+ }
+ break;
+
+ case EVENT_SOFTWARE_SMI:
+ // Check for code match after applying mask
+ if (EventPtr->Param1 == (MsgPacket[1] & ~EventPtr->Param2)) {
+ return EventIndex;
+ }
+ break;
+
+ default:
+ return EventIndex;
+ }
+
+ return 0;
+}
+
+
+//*****************************************************************************
+//
+// Sends a MSG_EVENT to all VSMs registered for the specified event.
+//
+//*****************************************************************************
+EVENT pascal Send_Event(EVENT Event, VSM From_VSM)
+{ ULONG To_VSM, ErrorParam = Event;
+ UCHAR HitCount = 0;
+ EVENT Hits[MAX_HIT], EventIndex;
+ USHORT i;
+ register EVENT_ENTRY * EventPtr;
+
+ // Perform sanity checks
+ if (Event == 0 || Event > MAX_EVENT) {
+ Log_Error("Invalid event 0x%04X", Event);
+ return 0;
+ }
+
+ if (Events[Event].Vsm == 0) {
+ // No VSM has registered this event.
+ Log_Error("EVENT_%s[0x%08X;0x%08X] is not registered to a VSM", EventNames[Event], MsgPacket[1], MsgPacket[2]);
+ return 0;
+ }
+
+ EventIndex = Event;
+
+#if HISTORY
+ Keep_History(Event, EventIndex);
+#endif
+
+ // Store Event code as message parameter[0]
+ MsgPacket[0] = Event;
+
+ // Walk the entire event chain looking for parameter matches
+ while (EventIndex) {
+
+ EventPtr = &Events[EventIndex];
+
+ // Check if the parameters for the current event match this event registration
+ if (FilterEvent(Event, EventIndex)) {
+ if (HitCount < MAX_HIT-1) {
+ // Record the hit
+ Hits[++HitCount] = EventIndex;
+ MsgParams[HitCount][1] = MsgPacket[1];
+ MsgParams[HitCount][2] = MsgPacket[2];
+ MsgParams[HitCount][3] = MsgPacket[3];
+ } else {
+ // ERROR: MAX_HIT is too small
+ Log_Error("Hits[] array is too small");
+ break;
+ }
+ }
+
+ // Point to the next registered VSM
+ EventIndex = EventPtr->Link;
+ }
+
+ // Send messages in priority order
+ for (i = HitCount; i > 0; i--) {
+ EventPtr = &Events[Hits[i]];
+ To_VSM = EventPtr->Vsm;
+
+ // Is the VSM being awakened prematurely from SYS_YIELD_CONTROL?
+ if (VSM_Is_Yielded(To_VSM)) {
+ EVENT_ENTRY * TimerPtr;
+
+ // Find the wakeup timer being used
+ EventIndex = EVENT_TIMER;
+ while (EventIndex) {
+ TimerPtr = &Events[EventIndex];
+
+ if ((TimerPtr->Vsm == To_VSM) && (TimerPtr->Param2 & SYS_YIELD)) {
+ Unregister_Event(EVENT_TIMER, To_VSM, TimerPtr->Param1, TimerPtr->Param2);
+ break;
+ }
+ EventIndex = TimerPtr->Link;
+ }
+ }
+
+ // Send a message to the VSM
+ if (!(EventPtr->Param2 & SYS_YIELD)) {
+ MsgPacket[1] = MsgParams[i][1];
+ MsgPacket[2] = MsgParams[i][2];
+ MsgPacket[3] = MsgParams[i][3];
+ Send_Message(From_VSM, To_VSM, MSG_EVENT);
+ }
+
+ // Unregister one-shot events
+ if (EventPtr->Param2 & ONE_SHOT) {
+ Unregister_Event(Event, To_VSM, EventPtr->Param1, EventPtr->Param2);
+ }
+ }
+
+ // Send message to Spy VSM, if present
+ if (HitCount && VSM_Ptrs[VSM_SPY]) {
+ Send_Message(From_VSM, VSM_Ptrs[VSM_SPY], MSG_EVENT);
+ }
+
+
+ return HitCount;
+}
+
+
+
+
+
+//*****************************************************************************
+// Associates a VSM with an Event and associated Parameters.
+// The System Manager maintains a table indexed by the Event. Each entry
+// contains a Link (array index) to the next VSM registered as a handler for
+// that Event. Entries are ordered by Priority (high to low). Unused array
+// elements are denoted by the Vsm field == 0000.
+//*****************************************************************************
+void pascal Register_Event(EVENT Event, PRIORITY Priority, VSM Vsm, ULONG Param1, ULONG Param2)
+{ UCHAR index, previous, next, Match=0;
+ register EVENT_ENTRY * EventPtr;
+
+ if (Event > MAX_EVENT) {
+ // Illegal Event
+ Log_Error("Attempt to register invalid event 0x%04X by the %s VSM", Event, VsmNames[Get_VSM_Type(Vsm)]);
+ return;
+ }
+
+ // Handle special cases
+ switch (Event) {
+
+ case EVENT_VIRTUAL_REGISTER:
+ // Param2[15:8] = low index Param2[7:0] = high index
+ // If index == 0x00, then any index is valid
+ Param1 <<= 8; // Shift class to bits 15:8
+ index = 0xFF; // Default upper index
+ if (Param2) {
+ index = (UCHAR)Param2; // Get upper index
+ (UCHAR)Param1 = (UCHAR)(Param2 >> 8); // Get lower index
+ }
+ Param2 = Param1;
+ (UCHAR)Param2 = index;
+ break;
+
+ case EVENT_IO_TRAP:
+ // 16 MSBs of Param1 are reserved
+ Param1 &= 0x0000FFFF;
+ // Don't allow PCI config cycles to be trapped
+ if (Param1 >= 0xCF8 && Param1 <= 0xCFF) {
+ Log_Error("Attempt to trap I/O 0xCF8-0xCFF by the %s VSM", VsmNames[Get_VSM_Type(Vsm)]);
+ return;
+ }
+ break;
+
+ case EVENT_TIMER:
+ // Mask all except Handle and valid flags
+ Param2 &= FOR_STANDBY | ONE_SHOT | SYS_YIELD | 0xFFFF;
+ if (Param1 == 0) {
+ Priority = UNREGISTER_PRIORITY;
+ }
+ break;
+ }
+
+ // If unregistering event(s)...
+ if (Priority >= UNREGISTER_PRIORITY) {
+ Unregister_Event(Event, Vsm, Param1, Param2);
+ return;
+ }
+
+ index = (UCHAR)Event;
+ next = 0;
+
+ if (Events[Event].Vsm) {
+
+ // Ensure a VSM doesn't register for the same event twice
+ do {
+ EventPtr = &Events[index];
+
+ // If it is the same VSM...
+ if (EventPtr->Vsm == Vsm) {
+
+ switch (Event) {
+
+ // If existing timer handle, assign new interval and/or priority
+ case EVENT_TIMER:
+ if (EventPtr->Handle == (USHORT)Param2) {
+ Match = 2;
+ }
+ break;
+
+ case EVENT_PWM:
+ // If existing pin, change rate and/or duty cycle
+ if (EventPtr->Pin == (USHORT)Param1) {
+ Match = 3;
+ }
+ break;
+
+ // If existing pin, accumulate attributes
+ case EVENT_GPIO:
+ if (EventPtr->Pin == Param1 && EventPtr->Priority == Priority) {
+ EventPtr->Attributes |= Param2;
+ Match = 1;
+ }
+ break;
+
+
+ default:
+ // If params match, then just update the event priority
+ if (EventPtr->Param1 == Param1 && EventPtr->Param2 == Param2) {
+#if SUPPORT_PRIORITY
+ // Sort list again according to priority
+#endif
+ Match = 1;
+ break;
+ }
+ }
+ }
+
+ // Early out
+ if (Match) {
+ break;
+ }
+ // Get link to next event
+ index = EventPtr->Link;
+
+ } while (index);
+
+
+
+ if (Match == 0) {
+
+ // Report error if no more Events[] entries
+ if (FreeEvent == 0) {
+ Log_Error("Failed attempt to register EVENT_%s[0x%08X;0x%08X] by the %s VSM", EventNames[Event], Param1, Param2, VsmNames[Get_VSM_Type(Vsm)]);
+ return;
+ }
+
+ // Get an unused Events[] entry
+ index = FreeEvent;
+ FreeEvent = Events[index].Link;
+
+ //
+ // Find the insertion point. There are two cases:
+ // 1) The new entry is higher priority than the current 1st entry
+ // 2) The new entry belongs somewhere down the chain.
+ //
+ previous = next = (UCHAR)Event;
+ while (next = Events[next].Link) {
+
+ if (Priority > Events[next].Priority) {
+ break;
+ }
+ previous = next;
+ }
+
+ if (Priority > Events[Event].Priority) {
+ // case 1: Need to copy 1st entry to Events[index]
+ Copy_Event(Event, index);
+ next = index;
+ index = (UCHAR)Event;
+
+ } else {
+ // case 2:
+ // Insert new event into linked list
+ Events[previous].Link = index;
+ }
+ }
+ }
+
+ // Create new Events[] entry
+ EventPtr = &Events[index];
+
+
+ switch (Match) {
+
+ // New registration
+ case 0:
+ EventPtr->Link = next;
+ EventPtr->Vsm = Vsm;
+ case 3:
+ EventPtr->Param2 = Param2;
+
+ // Update of Priority
+ case 1:
+ EventPtr->Priority = Priority;
+
+ // Update of Parameter (e.g. timer interval)
+ case 2:
+ EventPtr->Param1 = Param1;
+
+ }
+
+ // Enable the appropriate hardware
+ Enable_Event(Event, index, 1);
+
+} \ No newline at end of file
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/gpio.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/gpio.c
new file mode 100755
index 0000000..a04e2ef
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/gpio.c
@@ -0,0 +1,62 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Function: *
+//* This file contains non-chipset specific GPIO code.
+
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "PROTOS.H"
+
+
+extern ULONG MsgPacket[];
+extern Hardware HardwareInfo;
+
+
+
+//************************************************************************************
+// Reports invalid GPIO pin
+//************************************************************************************
+void Report_GPIO_Error(USHORT Pin)
+{
+ Report_VSM_Error(ERR_HW_MISMATCH, EVENT_GPIO, Pin);
+}
+
+
+
+//************************************************************************************
+// Sends the EVENT_GPIO message
+//************************************************************************************
+void Send_GPIO_Event(USHORT Pin, USHORT Edge)
+{
+
+ MsgPacket[1] = Pin;
+ MsgPacket[2] = Edge;
+ Send_Event(EVENT_GPIO, 0);
+
+}
+
+
+
+
+
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/gpio5536.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/gpio5536.c
new file mode 100755
index 0000000..ac3cf41
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/gpio5536.c
@@ -0,0 +1,488 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* This file contains code specific to CS5536 GPIOs
+//******************************************************************************
+
+
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "PROTOS.H"
+#include "VPCI.H"
+#include "PCI.H"
+#include "MDD.H"
+#include "MAPPER.H"
+
+
+#define POWER_BUTTON_PIN 28
+
+// External Functions:
+extern void Send_GPIO_Event(USHORT Pin, USHORT Edge);
+extern void Enable_PME_Event(UCHAR, UCHAR, UCHAR, USHORT);
+extern UCHAR pascal BitScanReverse(ULONG);
+
+// External Variables:
+extern PCI_HEADER_ENTRY ISA_Hdr[];
+extern GPIO_FUNCTION GPIO_Control;
+
+// Local Variables:
+ULONG Enable_Mask;
+USHORT Lock_Port, Lock_Data;
+USHORT GPIO_Port;
+UCHAR Bank=0;
+UCHAR ShiftCount;
+
+
+
+typedef struct {
+ UCHAR SelectOffset; // Offset to filter select register
+ UCHAR FilterOffset; // Offset to filter amount register
+ UCHAR Pin; // Pin this filter is associated to
+ UCHAR FilterRestore;
+} FILTERS;
+
+FILTERS FilterInfo[8] = {
+ {GPIO_FILTER_SELECT0, GPIO_FILTER_AMOUNT+0*8, 0xFF, 0},
+ {GPIO_FILTER_SELECT1, GPIO_FILTER_AMOUNT+1*8, 0xFF, 0},
+ {GPIO_FILTER_SELECT2, GPIO_FILTER_AMOUNT+2*8, 0xFF, 0},
+ {GPIO_FILTER_SELECT3, GPIO_FILTER_AMOUNT+3*8, 0xFF, 0},
+ {GPIO_FILTER_SELECT4, GPIO_FILTER_AMOUNT+4*8, 0xFF, 0},
+ {GPIO_FILTER_SELECT5, GPIO_FILTER_AMOUNT+5*8, 0xFF, 0},
+ {GPIO_FILTER_SELECT6, GPIO6_FILTER_AMOUNT, 28, 1}, // power button pre-defined
+ {GPIO_FILTER_SELECT7, GPIO7_FILTER_AMOUNT, 0xFF, 0},
+};
+
+
+
+
+//*****************************************************************************
+// Sends EVENT_GPIO messages for pins that have the specified edge status pending
+//*****************************************************************************
+void GPIO_Helper(UCHAR Edge, UCHAR PinBase)
+{ ULONG PinMask;
+ UCHAR Pin;
+
+ if (Edge == RISING_EDGE) {
+ (UCHAR)GPIO_Port = GPIO_POSEDGE_STATUS;
+ } else {
+ (UCHAR)GPIO_Port = GPIO_NEGEDGE_STATUS;
+ }
+ if (PinBase) {
+ (UCHAR)GPIO_Port |= GPIO_HIGH_BANK_SELECT;
+ }
+
+ // Get edge status
+ PinMask = in_32(GPIO_Port);
+
+ // Clear the edge status
+ out_32(GPIO_Port, PinMask);
+
+ // Ignore transitions that are not enabled
+ GPIO_Port -= GPIO_POSEDGE_STATUS;
+ GPIO_Port += GPIO_POSEDGE_ENABLE;
+ PinMask &= in_32(GPIO_Port) & 0x0000FFFFL;
+
+ // Loop through all pending GPIO edges
+ while (PinMask) {
+
+ // Determine next pending GPIO pin
+ Pin = BitScanReverse(PinMask);
+ PinMask &= ~(1L << Pin);
+
+ // Send the event to the VSM(s)
+ Send_GPIO_Event(PinBase+Pin, Edge);
+ }
+}
+
+//*****************************************************************************
+// Handles GPIO SMIs
+//*****************************************************************************
+void CS5536_GPIO_Handler(ULONG Active_GPIOs)
+{
+ // Get the current GPIO address
+ GPIO_Port = ISA_Hdr[BAR1/4].Value_LO;
+ Bank = GPIO_LOW_BANK_SELECT;
+ GPIO_Helper( RISING_EDGE, 0); // Handle GPIO[15:00] rising edges
+ GPIO_Helper(FALLING_EDGE, 0); // Handle GPIO[15:00] falling edges
+ Bank = GPIO_HIGH_BANK_SELECT;
+ GPIO_Helper( RISING_EDGE, 16); // Handle GPIO[31:16] rising edges
+ GPIO_Helper(FALLING_EDGE, 16); // Handle GPIO[31:16] falling edges
+}
+
+
+
+
+//*****************************************************************************
+// Unlocks specified GPIO register(s).
+// After GPIO registers are accessed, Relock_GPIO_Regs() should be invoked.
+//*****************************************************************************
+void Unlock_GPIO_Regs(USHORT UnlockMask)
+{
+ // Get current Lock register
+ Lock_Port = ISA_Hdr[BAR1/4].Value_LO;
+ (UCHAR)Lock_Port = Bank + GPIO_LOCK_ENABLE;
+ Lock_Data = in_16(Lock_Port);
+
+ // Unlock required registers
+ out_16(Lock_Port, Lock_Data & ~UnlockMask);
+
+}
+
+//*****************************************************************************
+// Restores GPIO register lock
+//*****************************************************************************
+void Relock_GPIO_Regs(void)
+{
+ out_16(Lock_Port, Lock_Data);
+}
+
+
+
+//*****************************************************************************
+// Writes a 32-bit value to a GPIO register
+//*****************************************************************************
+void Write_GPIO_Register(UCHAR Register, ULONG Data)
+{
+ // Write register
+ (UCHAR)GPIO_Port = Bank + Register;
+ out_32(GPIO_Port, Data);
+
+ // Handle registers that are slow due to being in the Standby power domain
+ if (Bank == GPIO_HIGH_BANK_SELECT) {
+ in_32(GPIO_Port);
+ }
+}
+
+//*****************************************************************************
+// Writes Enable_Mask to a GPIO register
+//*****************************************************************************
+void Configure_GPIO(UCHAR Reg)
+{
+ Write_GPIO_Register(Reg, Enable_Mask);
+}
+
+
+//*****************************************************************************
+// Maps the specified GPIO pin to the specified GPIO Interrupt
+//*****************************************************************************
+void GPIO_Mapper(UCHAR Pin, UCHAR Irq)
+{ ULONG Data;
+
+ // Unlock GPIO register(s)
+ Unlock_GPIO_Regs(LKIE | LKOE | LKPU | LKPD);
+
+ // Configure pin as Input
+ if (Pin != POWER_BUTTON_PIN) { // Keeps sleep pin from generating SMI
+ Configure_GPIO(GPIO_INPUT_ENABLE);
+ }
+
+ // Disable Output, Pullup & Pulldown
+ Data = Enable_Mask << 16;
+ Write_GPIO_Register(GPIO_OUTPUT_ENABLE, Data);
+ Write_GPIO_Register(GPIO_PULLDOWN_ENABLE, Data);
+ Write_GPIO_Register(GPIO_PULLUP_ENABLE, Data);
+
+ // Restore Lock register
+ Relock_GPIO_Regs();
+
+
+ // Program GPIO Mapper
+ (UCHAR)GPIO_Port = (UCHAR)(GPIO_MAPPER_X + ((Pin >> 1) & 0x0C));
+ ShiftCount = (Pin % 8) * 4;
+ Data = in_32(GPIO_Port);
+
+ Data &= ~(0x0000000FL << ShiftCount);
+ Data |= (ULONG)Irq << ShiftCount;
+ out_32(GPIO_Port, Data);
+
+}
+
+
+
+
+//*****************************************************************************
+// Clears the positive & negative edge status registers for the specified GPIOs
+//*****************************************************************************
+void ClearEdgeStatus(ULONG Mask)
+{
+ Write_GPIO_Register(GPIO_POSEDGE_STATUS, Mask);
+ Write_GPIO_Register(GPIO_NEGEDGE_STATUS, Mask);
+}
+
+
+
+//*****************************************************************************
+// Enables/Disables generation of SMI on GPIO edge(s) for the CS5536 chipset
+//*****************************************************************************
+void CS5536_GPIO_Control(ULONG Param1, ULONG Param2, UCHAR EnableFlag)
+{ ULONG Attributes;
+ UCHAR Pin, Pme, Pm1, i, PinToMatch, FilterAmount, filter_to_use;
+ ULONG Clear_Mask;
+
+
+ // Unpack parameters
+ Pin = (UCHAR)Param1;
+ Pme = (UCHAR)(Param1 >> 16);
+ Pm1 = (UCHAR)(Param2 >> 16);
+ Attributes = Param2 & 0xff00ffff;
+
+ GPIO_Port = ISA_Hdr[BAR1/4].Value_LO;
+
+// Log_Error("GPIO %d (%d) %d %d 0x%08X 0x%08X 0x%08X\r\n",Pin,EnableFlag,Pme,Pm1,Attributes,Param1,Param2);
+ // Validate parameters
+ if (Pin >= 32) {
+ Log_Error("Invalid GPIO pin # = 0x%02X\r\n", Pin);
+ return;
+ }
+ if ((Pme > 7) && (Attributes & PME)) {
+ Log_Error("Invalid PME # = 0x%02X\r\n", Pme);
+ return;
+ }
+ if ((Pm1 > 10) && (Attributes & PM1)) {
+ Log_Error("Invalid PM1 # = 0x%02X\r\n", Pm1);
+ return;
+ }
+
+ // Select Low/High bank
+ ShiftCount = Pin;
+ Bank = GPIO_LOW_BANK_SELECT;
+ if (Pin >= 16) {
+ ShiftCount -= 16;
+ Bank = GPIO_HIGH_BANK_SELECT;
+ }
+ // Generate masks
+ Clear_Mask = Enable_Mask = 1L << ShiftCount;
+
+ // Clear possible false edge events
+ ClearEdgeStatus(Clear_Mask);
+
+ // If disable, set 16 MSBs of Enable_Mask
+ if (!EnableFlag) {
+ Enable_Mask <<= 16;
+ }
+
+ // Set GPIO Interrupt/PME Mapper to generate an ASMI or PME
+ if (Attributes & PME) {
+ // Map the GPIO as a PME
+ GPIO_Mapper(Pin, (UCHAR)(Pme | 0x08));
+ } else {
+ // Route to ASMI unless PCI interrupt is specified
+ if (Pme) {
+ // Map the GPIO to a GPIO Interrupt
+ GPIO_Mapper(Pin, (UCHAR)(Pme & 0x07));
+ } else {
+ if (!(Attributes & NO_ASMI)) {
+ // Map the GPIO to an ASMI
+ GPIO_Mapper(Pin, (Z_IRQ_SMI & 0x07));
+ }
+ }
+ }
+
+
+
+ // This will set the MDD MSR_SMI bit for SMI on any PM event
+ // and program the appropriate ACPI PM1_EN or GPE0_EN bit.
+ // Additionally, it will clear the corresponding ACPI PM1_STS or GPE0_STS bit.
+ Enable_PME_Event(EnableFlag, Pm1, Pme, (USHORT)Attributes);
+
+ // If power button, don't touch any GPIO regs!
+ if (Pin == POWER_BUTTON_PIN) {
+ return;
+ }
+
+
+ // Unlock GPIO registers
+ Unlock_GPIO_Regs(LKPE | LKNE | LKFE | LKEE);
+
+ // Configure as Output ?
+ if (Attributes & OUTPUT) {
+
+ Configure_GPIO(GPIO_OUTPUT_ENABLE);
+
+ // Configure output pin inversion
+ if (Attributes & INVERT) {
+ Configure_GPIO(GPIO_OUTPUT_INVERT);
+ }
+
+ // Configure open drain
+ if (Attributes & OPEN_DRAIN) {
+ Configure_GPIO(GPIO_OUTPUT_OPENDRAIN);
+ }
+
+ // Configure AUX output selects
+ if (Attributes & AUX1) {
+ Configure_GPIO(GPIO_OUT_AUX1_SELECT);
+ } else {
+ if (Attributes & AUX2) {
+ Configure_GPIO(GPIO_OUT_AUX2_SELECT);
+ }
+ }
+ }
+
+
+ // Configure as Input ?
+ if ((Attributes & INPUT) || !(Attributes & OUTPUT)) {
+ // Configure input pin inversion
+ if (Attributes & INVERT) {
+ Configure_GPIO(GPIO_INPUT_INVERT);
+ }
+
+ if (Attributes & AUX1) {
+ Configure_GPIO(GPIO_IN_AUX1_SELECT);
+ }
+
+
+
+ // Configure input for correct edge(s)
+ switch (Attributes & BOTH_EDGES) {
+
+ case BOTH_EDGES:
+ case RISING_EDGE:
+ // Enable/Disable the RISING edge
+ Configure_GPIO(GPIO_POSEDGE_ENABLE);
+ if ((Attributes & BOTH_EDGES) == RISING_EDGE) {
+ break;
+ }
+ // fall through intended
+
+ case FALLING_EDGE:
+ // Enable/Disable the FALLING edge
+ Configure_GPIO(GPIO_NEGEDGE_ENABLE);
+ break;
+
+ default:
+ // If neither edge is enabled, an event is 'active' as long
+ // as the input is high (or low if inverted).
+ break;
+ }
+ }
+
+
+ // NOTE: If pullup is enabled, pulldown is automatically disabled
+ // Configure pullup
+ if (Attributes & PULLUP) {
+ Configure_GPIO(GPIO_PULLUP_ENABLE);
+ } else {
+ // Configure pulldown
+ if (Attributes & PULLDOWN) {
+ Configure_GPIO(GPIO_PULLDOWN_ENABLE);
+ }
+ }
+
+
+ // Configure debounce filter
+ if (Attributes & DEBOUNCE) {
+ PinToMatch = (UCHAR)Pin;
+
+ if (EnableFlag) {
+ FilterAmount = 1; // Units = ~30 usec
+ } else {
+ FilterAmount = 0;
+ }
+
+ // Find a filter
+ i=0;
+ if (Attributes & FOR_STANDBY ) {
+ i=6; // if pme 6/7 set for filter 6/7 (in standby domain)
+ }
+ filter_to_use=0xff;
+
+ for (; i < 8; i++) {
+ if (FilterInfo[i].Pin == PinToMatch) {
+ filter_to_use=i;
+ break;
+ }
+ // see if we have found an open filter - use only for enable
+ if ((filter_to_use == 0xff) && (FilterInfo[i].Pin == 0xff) && (EnableFlag)) {
+ filter_to_use=i;
+ }
+ }
+// Log_Error("GPIO %d using filter %d\r\n",Pin,filter_to_use);
+ // found an matching pin for filter or an open one
+ if (filter_to_use != 0xff) { // found one
+ i=filter_to_use; // use this filter
+ if (EnableFlag) {
+ // Mark filter in-use
+ FilterInfo[i].Pin = (UCHAR)Pin;
+
+ // Save the filter select register
+ (UCHAR)GPIO_Port = FilterInfo[i].SelectOffset;
+ FilterInfo[i].FilterRestore = in_8(GPIO_Port);
+
+ // Select the filter
+ out_8(GPIO_Port, (UCHAR)Pin);
+ }
+
+ // Program filter Amount & Count
+ (UCHAR)GPIO_Port = FilterInfo[i].FilterOffset;
+ out_32(GPIO_Port, (ULONG)FilterAmount);
+
+ if (!EnableFlag) {
+ // Mark filter as available
+ FilterInfo[i].Pin = 0xFF;
+
+ // Restore the filter select register
+ (UCHAR)GPIO_Port = FilterInfo[i].SelectOffset;
+ out_8(GPIO_Port, FilterInfo[i].FilterRestore);
+ }
+ // Enable/Disable filter
+ Configure_GPIO(GPIO_IN_FILTER_ENABLE);
+ }
+ else {
+ // no filter found
+ Log_Error("No filter found for GPIO %d\r\n",Pin);
+ }
+ }
+
+ // Enable/Disable GPIO as an event unless it is EVENT_PWM
+ if ((Attributes & (OUTPUT | NO_ASMI)) != (OUTPUT | NO_ASMI)) {
+ Configure_GPIO(GPIO_EVENTS_ENABLE);
+ }
+
+
+ // Clear possible false edge events
+ ClearEdgeStatus(Clear_Mask);
+
+
+ // Restore Lock register
+ Relock_GPIO_Regs();
+
+}
+
+
+
+
+//*****************************************************************************
+// Initialized CS5536 GPIO logic
+//*****************************************************************************
+void CS5536_GPIO_Init(void)
+{
+
+ // Point GPIO_Control to correct GPIO routine for CS5536
+ GPIO_Control = CS5536_GPIO_Control;
+
+ // Clear pending GPIOs
+ CS5536_GPIO_Handler(0);
+
+ // Map the GPIO SMI source
+ IRQZ_Mapper(Z_IRQ_SMI, 2);
+
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/handlers.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/handlers.c
new file mode 100755
index 0000000..277edfd
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/handlers.c
@@ -0,0 +1,645 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//*****************************************************************************
+//* Implements the handlers for top-level SMI source
+//*****************************************************************************
+
+
+#include "VSA2.H"
+#include "CHIPSET.H"
+#include "PROTOS.H"
+#include "SYSMGR.H"
+#include "VPCI.H"
+#include "PCI.H"
+
+// External variables
+extern SmiHeader SMM_Header;
+extern SmiHeader Nested_Header;
+extern ULONG Saved_EAX, Saved_EBX, Saved_ECX;
+extern ULONG MsgPacket[];
+extern ULONG VSM_ListHead;
+extern ULONG Virtualized_PCI_Devices;
+extern ULONG Stats_Sources;
+extern ULONG IRQ_Mask;
+extern ULONG MPCI_NB;
+extern ULONG VSM_Buffer;
+extern ULONG Nested_Flag;
+extern ULONG Video_Sources;
+extern USHORT Audio_Sources;
+extern Hardware HardwareInfo;
+extern EVENT_ENTRY Events[];
+extern PCI_HEADER_ENTRY ISA_Hdr[];
+extern PCI_HEADER_ENTRY HostBridge_Hdr[];
+
+
+// External function prototypes
+extern void pascal Timer_Handler(USHORT);
+extern void CS5536_GPIO_Handler(ULONG);
+extern void INT_Return(void);
+extern void Send_OHCI_Event(UCHAR);
+extern void VR_Handler(SmiHeader *);
+extern void ACPI_Workaround(SmiHeader *, USHORT);
+extern void Remove_RTC_Fix(void);
+extern void set_reset_state(void);
+extern void pascal Unblock_VSM(ULONG);
+extern void pascal Return_Virtual_Value(SmiHeader *, ULONG);
+extern SmiHeader * pascal Get_Header_Params(ULONG);
+extern ULONG Get_ACPI_Status(ULONG *);
+extern USHORT Get_Timeout(ULONG, UCHAR *);
+extern USHORT CS5536_MFGPT_Handler(void);
+extern void ReInit_Descriptors(void);
+extern void Init_SysMgr();
+extern void A20_Sync(void);
+extern void Update_VSMs_CR0(void);
+
+
+ULONG INT_Vectors[MAX_INT] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xF000F859};
+ULONG VSM_Ptrs[VSM_MAX_TYPE+1];
+ULONG Audio_IRQ = 0;
+ULONG NativeAudioStatus = 0x4F0; // Defaults to 0040:00F0
+UCHAR End_of_POST = 0;
+
+
+
+
+
+
+
+
+void Broadcast_SysMgr_Msg (MSG Message, UCHAR Param1)
+{
+ MsgPacket[0] = (ULONG)Param1;
+ MsgPacket[1] = MsgPacket[2] = 0;
+ Broadcast_Message(Message, VSM_ANY, 0x00000000);
+}
+
+
+//***********************************************************************
+// Sends a message for an asynchronous event
+//***********************************************************************
+void pascal Send_Asynchronous_Event(EVENT Event)
+{
+ MsgPacket[1] = MsgPacket[3] = MsgPacket[4] = 00000000;
+ if (Event != EVENT_IO_TIMEOUT) {
+ MsgPacket[2] = 00000000;
+ }
+ Send_Event(Event, 0x00000000);
+}
+
+
+
+//***********************************************************************
+// Sends a message for a synchronous event
+// Returns TRUE if the event was registered.
+//***********************************************************************
+USHORT pascal Send_Synchronous_Event(EVENT Event, SmiHeader * SmiHdr)
+{ ULONG Vsm;
+ USHORT EventRegistered;
+
+ if ((USHORT)SmiHdr == 0x0000 || (USHORT)SmiHdr == (USHORT)&SMM_Header) {
+ Vsm = SysMgr_VSM;
+ } else {
+ Vsm = Current_VSM;
+ }
+ EventRegistered = Send_Event(Event, Vsm);
+ if (!EventRegistered) {
+
+ // No VSM is registered for this event
+ // If nested event, change the VSM's state from 'Blocked' to 'Ready'
+ if (Nested_Flag) {
+ Unblock_VSM(Vsm);
+ }
+ }
+
+ return EventRegistered;
+}
+
+
+
+//***********************************************************************
+// This routine walks the VSM linked list, recording ptrs to VSMs that
+// have special requirements.
+//***********************************************************************
+void Record_VSM_Locations(void)
+{ ULONG VSM_Ptr;
+ UCHAR VSM_Type;
+
+ for (VSM_Type=0; VSM_Type<=VSM_MAX_TYPE; VSM_Type++) {
+ VSM_Ptrs[VSM_Type] = 0x00000000;
+ }
+ VSM_Ptr = VSM_ListHead;
+
+ while (VSM_Ptr) {
+
+ VSM_Type = Get_VSM_Type(VSM_Ptr);
+
+ if (VSM_Type < sizeof(VSM_Ptrs)/4) {
+ VSM_Ptrs[VSM_Type] = VSM_Ptr;
+ }
+ if (VSM_Type == VSM_RTC) {
+ Remove_RTC_Fix();
+ }
+ VSM_Ptr = GetFlink(VSM_Ptr);
+ }
+}
+
+
+
+//***********************************************************************
+// This routine handles software SMI events.
+//***********************************************************************
+void pascal SMINT_Handler(USHORT Code)
+{ int i;
+
+ // Handle return from INT callback
+ if (VSM_Buffer) {
+ INT_Return();
+ return;
+ }
+
+ switch (Code) {
+
+ case SYS_BIOS_INIT:
+
+ // If installing VSA from DOS, restore descriptors to default state
+ if (Saved_EBX != 0) {
+ ReInit_Descriptors();
+ }
+
+ // VSA Initialization
+ Init_SysMgr();
+ if (Saved_EBX == 0) {
+ break;
+ }
+
+ case SYS_END_OF_POST:
+ Current_VSM = 0;
+
+ End_of_POST = 1;
+ //
+ // Take a snapshot of the interrupt vectors
+ //
+ for (i = 0; i < MAX_INT; i++) {
+ if (INT_Vectors[i] == 0) {
+ INT_Vectors[i] = read_flat((ULONG) i << 2 );
+ }
+ }
+
+ // Entry point to video ROM
+ INT_Vectors[1] = 0xC0000003;
+
+ //
+ // The BIOS may have enabled the changed the cache setting
+ // since early init, so update each VSM's CR0 field
+ //
+ Update_VSMs_CR0();
+
+ // Send a phase 1 initialization message to each VSM
+ Broadcast_SysMgr_Msg(MSG_INITIALIZE, END_OF_POST_INIT);
+ break;
+
+
+ case SYS_REMOVE:
+ Unregister_VSM_Events(Saved_ECX);
+ break;
+
+ case SYS_VSM_INSTALL:
+
+ // EBX points to the new VSM
+ // ECX points to the old VSM
+ Unregister_VSM_Events(Saved_ECX);
+
+ Record_VSM_Locations();
+
+
+ //
+ // Send both phase 0 & 1 initialization messages to the new VSM
+ //
+ MsgPacket[0] = EARLY_INIT;
+ MsgPacket[1] = 1;
+ Send_Message(SysMgr_VSM, Saved_EBX, MSG_INITIALIZE);
+
+ MsgPacket[0] = END_OF_POST_INIT;
+ MsgPacket[1] = 1;
+ Send_Message(SysMgr_VSM, Saved_EBX, MSG_INITIALIZE);
+ break;
+
+ default:
+ //
+ // Send event to appropriate VSM
+ //
+ MsgPacket[1] = (ULONG)Code;
+ MsgPacket[2] = Saved_EBX;
+ MsgPacket[3] = Saved_ECX;
+ Send_Synchronous_Event(EVENT_SOFTWARE_SMI, 0);
+ break;
+
+ } // end switch
+}
+
+
+//***********************************************************************
+// This routine handles graphics events.
+//***********************************************************************
+void VG_Handler(void)
+{ register SmiHeader * SmiHdr;
+
+ SmiHdr = Get_Header_Params(0);
+
+ // Set bit 24 of MsgPacket[2] if I/O write
+ if (SmiHdr->SMI_Flags.IO_Write) {
+ MsgPacket[2] |= 0x01000000L;
+ }
+ MsgPacket[1] = Video_Sources;
+ Send_Synchronous_Event(EVENT_GRAPHICS, SmiHdr);
+
+ // Reset video event flags
+ Video_Sources = 0;
+}
+
+
+
+//***********************************************************************
+// This routine handles A20
+//***********************************************************************
+void A20_Handler(void)
+{
+
+ A20_Sync();
+
+ // Send event so it will be recorded in the history buffer
+ // Send_Synchronous_Event(EVENT_A20, SMM_Header);
+
+}
+
+//***********************************************************************
+// This routine handles reset
+//***********************************************************************
+void Reset_Handler(void)
+{
+
+
+ // Schedule reset routine after VSMs have processes MSG_SHUTDOWN
+ Schedule_VSM((ULONG)((USHORT)set_reset_state));
+
+ // Tell each VSM to get ready for cold boot
+ // No VSMs use this message at this time, so don't broadcast message
+ // (to keep overhead down)
+ // Broadcast_SysMgr_Msg(MSG_SHUTDOWN, 0);
+
+
+}
+
+//***********************************************************************
+// This routine handles NMI
+//***********************************************************************
+void NMI_Handler(void)
+{
+ Send_Asynchronous_Event(EVENT_NMI);
+}
+
+
+
+
+
+//***********************************************************************
+// This routine handles trapped PCI events.
+// The event may come from an SSMI (CPU) or an external SMI (chipset)
+//***********************************************************************
+void PCI_Handler(void)
+{ ULONG ID_Select, Data;
+ USHORT Address;
+ UCHAR Size;
+ register SmiHeader * SmiHdr;
+
+
+ SmiHdr = Get_Header_Params(SMI_SRC_PCI_TRAP);
+ Address = (USHORT)MsgPacket[2];
+
+ Size = (UCHAR)SmiHdr->data_size;
+ ID_Select = 1L << ((Address >> 11) & 0x1F);
+
+
+ if (SmiHdr->SMI_Flags.IO_Write) {
+
+ //
+ // Trapped PCI header WRITE
+ //
+ Data = MsgPacket[3];
+
+ // Is it is a totally virtual PCI header ?
+ if (ID_Select & Virtualized_PCI_Devices) {
+ MsgPacket[3] = Virtual_PCI_Write_Handler(Address, Size, Data);
+ Address &= 0xFFFC;
+ Size = DWORD_IO;
+ }
+
+ // Set the write flag
+ Size |= IO_WRITE;
+
+ } else {
+
+ //
+ // Trapped PCI header READ
+ //
+
+ // Is it is a totally virtual PCI header ?
+ if (ID_Select & Virtualized_PCI_Devices) {
+
+ Data = Virtual_PCI_Read_Handler(Address);
+
+ } else {
+ Trap_PCI_IDSEL(Address, 0);
+ out_32(PCI_CONFIG_ADDRESS, 0x80000000 | Address);
+ Data = in_32(PCI_CONFIG_DATA);
+ Trap_PCI_IDSEL(Address, 1);
+ }
+ // Return virtualized PCI device value to the right environment
+ Return_Virtual_Value(SmiHdr, Data);
+ MsgPacket[3] = Data;
+ }
+
+ // Repackage the parameters
+ MsgPacket[2] = MsgPacket[1] << 16;
+ MsgPacket[1] = 0x80000000 + (USHORT)Address;
+ (USHORT)MsgPacket[2] = Size;
+
+ // Send EVENT_PCI_TRAP message
+ if (!Send_Synchronous_Event(EVENT_PCI_TRAP, SmiHdr)) {
+ // This PCI register was not trapped.
+ // Re-issue configuration writes to real PCI hardware devices.
+ if (Size & IO_WRITE) {
+ if (!(ID_Select & Virtualized_PCI_Devices)) {
+ USHORT PCI_Data_Reg;
+ // Disable trapping for this device
+ Trap_PCI_IDSEL(Address, 0);
+
+ // Re-issue the configuration write to the h/w device
+ out_32(PCI_CONFIG_ADDRESS, 0x80000000 | Address);
+ PCI_Data_Reg = PCI_CONFIG_DATA + (Address & 3);
+ switch (Size & ~IO_WRITE) {
+
+ case BYTE_IO:
+ out_8(PCI_Data_Reg, (UCHAR)Data);
+ break;
+
+ case WORD_IO:
+ out_16(PCI_Data_Reg, (USHORT)Data);
+ break;
+
+ case DWORD_IO:
+ out_32(PCI_Data_Reg, Data);
+ break;
+ }
+
+ // Re-enable trapping for this device
+ Trap_PCI_IDSEL(Address, 1);
+ }
+ }
+ }
+
+}
+
+
+
+
+//***********************************************************************
+// This routine handles USB1 events.
+//***********************************************************************
+void USB1_Handler(void)
+{
+ Send_OHCI_Event(1);
+
+}
+
+//***********************************************************************
+// This routine handles USB2 events.
+//***********************************************************************
+void USB2_Handler(void)
+{
+ Send_OHCI_Event(2);
+}
+
+
+//***********************************************************************
+// This routine handles the CS5536's KEL events
+//***********************************************************************
+void KEL_Handler(void)
+{
+ Send_OHCI_Event(1);
+}
+
+
+
+//***********************************************************************
+// This routine handles a BLOCKIO event (PIO to ATA during UDMA).
+//***********************************************************************
+void BLOCKIO_Handler(void)
+{ SmiHeader * SmiHdr;
+
+ SmiHdr = Get_Header_Params(SMI_SRC_BLOCKIO);
+ Send_Synchronous_Event(EVENT_BLOCKIO, SmiHdr);
+}
+
+//***********************************************************************
+// This routine handles hits on MBus descriptors.
+//***********************************************************************
+void Descr_Hit_Handler(void)
+{ USHORT Address;
+ SmiHeader * SmiHdr;
+
+ SmiHdr = Get_Header_Params(SMI_SRC_DESCR_HIT);
+
+ // Ignore if one of the other sources of SSMI_FLAGS
+ if (!SmiHdr->SMI_Flags.Ext_IO_Trap && !SmiHdr->SMI_Flags.IO_Trap) {
+ return;
+ }
+
+ Address = (USHORT)SmiHdr->IO_addr;
+
+ // Handle virtual registers
+ if ((Address & 0xFFFC) == (HostBridge_Hdr[BAR0/4].Value_LO)) {
+ if (SmiHdr == &SMM_Header) {
+ // Handle virtual register
+ VR_Handler(SmiHdr);
+ } else {
+ Report_VSM_Error(ERR_NESTED_ACCESS, 0, 0);
+ }
+ return;
+ }
+
+ // Handle workaround for PM Support registers
+ if ((Address & (USHORT)ISA_Hdr[BAR4/4].Mask) == (ISA_Hdr[BAR4/4].Value_LO)) {
+ ACPI_Workaround(SmiHdr, 0);
+ }
+
+ // Handle workaround for ACPI registers
+ if ((Address & 0xFFE0) == (ISA_Hdr[BAR5/4].Value_LO)) {
+ ACPI_Workaround(SmiHdr, 1);
+ }
+ // Send the event
+ Send_Synchronous_Event(EVENT_IO_TRAP, SmiHdr);
+}
+
+
+
+//***********************************************************************
+// This routine handles statistic counter ASMIs
+//***********************************************************************
+void StatCntr_Handler(void)
+{ UCHAR StartIndex = 0;
+ USHORT Address;
+ ULONG SFlag;
+
+
+ while (Stats_Sources) {
+ SFlag = 1L << BitScanForward(Stats_Sources);
+
+ Address = Get_Timeout(SFlag, &StartIndex);
+ if (Address) {
+ (USHORT)MsgPacket[2] = Address;
+ Send_Asynchronous_Event(EVENT_IO_TIMEOUT);
+ } else {
+ // Clear status bit
+ Stats_Sources &= ~SFlag;
+ }
+ }
+}
+
+
+//***********************************************************************
+// This routine handles the Southbridge's PIC events
+//***********************************************************************
+void PIC_Handler(void)
+{ USHORT ExpiredTimerMask, Timer;
+
+ // Need to read PIC registers to determine if one of:
+ // USB1, USB2, S/W Generated, RTC Alarm, Audio, PM, NAND Flash,
+ // SMB, KEL, UART1, UART2, MFGPT comparator, or GPIO.
+ CS5536_GPIO_Handler(0);
+
+
+ // Check if any MFGPT events occurred
+ ExpiredTimerMask = CS5536_MFGPT_Handler();
+ Timer = 0;
+ while (ExpiredTimerMask) {
+ if (ExpiredTimerMask & 1) {
+ Timer_Handler(Timer);
+ }
+ Timer++;
+ ExpiredTimerMask >>= 1;
+ }
+}
+
+
+
+//***********************************************************************
+// This routine handles the CS5536's ACPI events
+//***********************************************************************
+void ACPI_Handler(void)
+{ SmiHeader * SmiHdr;
+
+ SmiHdr = Get_Header_Params(0);
+
+ // Handle mis-aligned access to the PM1_CNT register
+ while ((UCHAR)SmiHdr->IO_addr != 0x08) {
+ (UCHAR)SmiHdr->IO_addr++;
+ (UCHAR)SmiHdr->data_size >>= 1;
+ SmiHdr->write_data >>= 8;
+ }
+ if ((UCHAR)SmiHdr->data_size == 0x07) {
+ (UCHAR)SmiHdr->data_size = WORD_IO;
+ }
+
+
+ Send_Synchronous_Event(EVENT_ACPI, SmiHdr);
+
+}
+
+
+//***********************************************************************
+// This routine handles the CS5536's Power Management Events
+//***********************************************************************
+void PME_Handler(void)
+{
+
+ // Handle GPIOs that are routed to PM logic
+ CS5536_GPIO_Handler(0);
+
+ // Filter any false event caused by enabling PME
+ if (Get_ACPI_Status(MsgPacket)) {
+ Send_Synchronous_Event(EVENT_PME, 0);
+ }
+}
+
+
+//***********************************************************************
+// This routine handles events for which no other handler applies.
+//***********************************************************************
+void Leftover_Handler(void)
+{
+
+ // Report that the event was not handled.
+ Log_Error("Unhandled event");
+
+}
+
+
+
+
+
+//*************************************************************************
+//
+// The SMI_Sources table is used for determining the proper handler for
+// a top-level SMI source. Note that a single handler may process multiple
+// SMI sources. The order of entries in this table governs the order that
+// the handlers will be invoked. This is NOT the order that the VSMs will
+// be given control. Therefore, the order of entries is unimportant with
+// respect to controlling priority. However, in terms of finding a match
+// more quickly, the more frequent SMI events should be placed earlier in
+// the table.
+//
+//*************************************************************************
+
+SMI_ENTRY Handler_Table[] = {
+ PCI_Handler, SMI_SRC_PCI_TRAP,
+ VG_Handler, SMI_SRC_VG,
+ USB1_Handler, SMI_SRC_USB1,
+ USB2_Handler, SMI_SRC_USB2,
+ A20_Handler, SMI_SRC_A20,
+ Reset_Handler, SMI_SRC_RESET,
+ NMI_Handler, SMI_SRC_NMI,
+
+
+ Descr_Hit_Handler, SMI_SRC_DESCR_HIT,
+ PIC_Handler, SMI_SRC_PIC,
+ StatCntr_Handler, SMI_SRC_STAT,
+ KEL_Handler, SMI_SRC_KEL,
+ ACPI_Handler, SMI_SRC_ACPI,
+ PME_Handler, SMI_SRC_PME,
+ BLOCKIO_Handler, SMI_SRC_BLOCKIO,
+
+ Leftover_Handler, 0xFFFFFFFF,
+};
+
+
+
+
+ \ No newline at end of file
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/history.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/history.c
new file mode 100755
index 0000000..85a3d2c
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/history.c
@@ -0,0 +1,193 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Function: *
+//* This file contains the code for recording event history.
+
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "PROTOS.H"
+
+
+extern EVENT_ENTRY Events[];
+extern ULONG MsgPacket[];
+
+extern UCHAR VSM_Filter;
+
+#if HISTORY
+EVENT NonReportableEvents[] = {
+ EVENT_A20,
+ EVENT_GRAPHICS,
+ EVENT_ACPI_TIMER
+};
+#define UNREPORT_COUNT (sizeof(NonReportableEvents)/sizeof(EVENT))
+
+//
+// Event history
+//
+EVENT_HISTORY History[HISTORY];
+int HistoryWrap = 0;
+int HistoryStart = 0;
+int HistoryEnd = 0;
+
+
+
+//*****************************************************************************
+//
+// Record the event history
+//
+//*****************************************************************************
+void Keep_History(EVENT Event, EVENT EventIndex)
+{ int i;
+ ULONG ParamMask, Param2;
+ UCHAR VSM_Type;
+ register EVENT_ENTRY * EventPtr;
+
+ EventPtr = &Events[EventIndex];
+
+ VSM_Type = Get_VSM_Type(EventPtr->Vsm);
+
+
+ // Filter out VSM(s)
+ if (VSM_Filter != VSM_ANY && VSM_Type != VSM_Filter)
+ return;
+
+ //
+ // Filter events from reporting
+ //
+
+ for (i=0; i < UNREPORT_COUNT; i++) {
+ if (Event == NonReportableEvents[i])
+ return;
+ }
+
+ // Generate mask for Param1
+ ParamMask = 0xFFFFFFFF;
+ Param2 = EventPtr->Param2;
+ switch (Event) {
+
+ case EVENT_PCI_TRAP:
+ // Report all PCI events together by PCI function
+ ParamMask = ~Param2;
+ break;
+
+ case EVENT_GPIO:
+ // Get current edge
+ Param2 = EventPtr->CurrentEdge;
+ break;
+
+ case EVENT_SOFTWARE_SMI:
+ // Don't report APM calls CPU_Busy or CPU_Idle
+ if ((EventPtr->Param1 & 0xFF00) == 0x5300) {
+ switch (EventPtr->Param1 & 0x00FF) {
+ case 0x05:
+ case 0x06:
+ return;
+ }
+ break;
+ }
+ break;
+
+ case EVENT_VIRTUAL_REGISTER:
+ // Report all VR events together by classes
+ ParamMask = 0x0000FF00;
+ break;
+
+ }
+
+ // If it's the same event for the same VSM...
+ if ((History[HistoryEnd].Event == Event) &&
+ (History[HistoryEnd].Vsm == EventPtr->Vsm) ) {
+
+ switch (Event) {
+
+ case EVENT_IO_TRAP:
+ if (History[HistoryEnd].Param1 != (MsgPacket[2] & 0x0000FFFFL)) {
+ break;
+ }
+
+
+ // Events to be recorded together if (Param1 & ParamMask) matches
+ case EVENT_PCI_TRAP:
+ case EVENT_SOFTWARE_SMI:
+ case EVENT_VIRTUAL_REGISTER:
+ if (History[HistoryEnd].Param1 != (MsgPacket[1] & ParamMask)) {
+ break;
+ }
+
+
+ default:
+ // Record together if 1st two parameters match
+ if (History[HistoryEnd].Param1 == EventPtr->Param1 &&
+ History[HistoryEnd].Param2 == EventPtr->Param2 ) {
+ History[HistoryEnd].Count++;
+ Store_Timestamp(&History[HistoryEnd].TimeStamp);
+ return;
+ }
+
+ } // end switch
+ }
+
+ //
+ // Report event in a new history entry.
+ //
+ // Increment HistoryEnd unless it's the 1st event
+ if (History[HistoryEnd].Vsm) {
+ HistoryEnd++;
+ if (HistoryEnd >= HISTORY) {
+ HistoryEnd = 0;
+ HistoryWrap = 1;
+ }
+
+ // Increment HistoryStart index too if HistoryEnd has wrapped
+ if (HistoryWrap) {
+ HistoryStart++;
+ if (HistoryStart >= HISTORY)
+ HistoryStart = 0;
+ }
+ }
+
+
+ History[HistoryEnd].Vsm = EventPtr->Vsm;
+ History[HistoryEnd].Event = Event;
+ History[HistoryEnd].Param1 = MsgPacket[1] & ParamMask;
+ History[HistoryEnd].Param2 = Param2;
+ History[HistoryEnd].Count = 1;
+ Store_Timestamp(&History[HistoryEnd].TimeStamp);
+}
+
+
+
+void Initialize_History(void)
+{
+
+ // Initialize timestamp field of history buffer entry "previous" to 1st entry
+ Store_Timestamp(&History[HISTORY-1].TimeStamp);
+ HistoryWrap = 0;
+ HistoryStart = 0;
+ HistoryEnd = 0;
+}
+
+#else
+
+void Initialize_History(void) { }
+
+
+#endif
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/idt.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/idt.asm
new file mode 100755
index 0000000..44609c4
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/idt.asm
@@ -0,0 +1,697 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;********************************************************************************
+; Routines to:
+; -set up an SMM-based IDT
+; -save/restore of FPU state only as needed
+;********************************************************************************
+
+
+
+include sysmgr.inc
+include vsa2.inc
+include gx2.inc
+
+.model tiny,c
+.586p
+.CODE
+
+
+CR equ 0Dh
+LF equ 0Ah
+
+
+public Saved_INTs
+public Trap_Common
+externdef Trap_Code: dword
+externdef SysMgr_VSM: dword
+externdef Current_VSM: dword
+externdef IDT_Base: dword
+externdef IDT_Limit: dword
+externdef IDT_Selector:dword
+externdef pascal Parse_Capabilities: proc
+externdef pascal Read_MSR_HI: proc
+
+FPU_Owner dd 0
+FPU_State db 108 dup (0)
+CR0_PE equ 1
+CR0_EM equ 4
+
+
+;***********************************************************************
+; Saves the non-SMM IDT and installs VSA's exception vectors
+;***********************************************************************
+Install_IDT proc
+
+ ; Save IDT of interrupted thread
+ mov ecx, 1329h
+ rdmsr
+ mov [IDT_Selector], eax
+ mov eax, IDT_SIZE-1
+ wrmsr
+
+ mov cl, 39h
+ rdmsr
+ mov [IDT_Base], eax
+ mov [IDT_Limit], edx
+ mov eax, [SysMgr_VSM]
+ add eax, OFFSET Saved_INTs
+ mov dx, IDT_SIZE
+ wrmsr
+
+
+ nop
+ mov byte ptr [$-1], 0C3h ; Patch a RET at the NOP above
+
+ mov eax, [SysMgr_VSM] ; Initialize FPU owner
+ mov [FPU_Owner], eax
+
+; The following code is only necessary if SysMgr starts on a non-MB boundary.
+; HandlerBase = {SMM_base[31:20], CS_selector[15:0], 4'b0}
+; lea di, [Saved_INTs+2] ; Patch SysMgr's CS into vector table
+; mov cx, IDT_SIZE/4
+; shr eax, 4 ; Compute SysMgr's CS
+;InsertCS:
+; mov [di], ax ; Store SysMgr's CS into vector table
+; add di, 4
+; loop InsertCS
+
+ ret
+
+
+Install_IDT endp
+
+
+
+;***********************************************************************
+; Restores the IDT ptr and FPU state (if modified)
+;***********************************************************************
+Restore_IDT proc
+
+ ; Restore the IDT of interrupted thread
+ mov ecx, 1329h
+ mov eax, [IDT_Selector]
+ wrmsr
+ mov cl, 39h
+ mov eax, [IDT_Base]
+ mov edx, [IDT_Limit]
+ wrmsr
+
+
+ ; The RET will be patched with a NOP if FPU usage occurs
+RestoreRET::
+ ret
+
+ ; Restore the RET at RestoreRET
+ mov byte ptr [RestoreRET], 0C3h
+
+ ; Get last VSM to use FPU
+ mov esi, [SysMgr_VSM]
+ xchg [FPU_Owner], esi
+
+ ; Set VSM's CR0.EM
+ or fs:(VSM_Header PTR [esi]).SysStuff.State.r_CR0, CR0_EM
+
+ ; Save VSM's FPU state
+ ; NOTE: This can be done in real-mode
+ fnsave fs:(VSM_Header PTR [esi]).SysStuff.FPU_State
+
+ ; Restore non-SMM FPU state
+ ; NOTE: This must be done in 32-bit protected mode
+ mov eax, CR0 ; Enter protected mode for FPU save
+ or al, CR0_PE
+ mov CR0, eax
+ jmp $+2
+
+ db 66h
+ frstor byte ptr cs:[FPU_State]
+
+ and al, NOT CR0_PE ; Return to real mode
+ mov CR0, eax
+
+ ret
+
+Restore_IDT endp
+
+
+
+
+
+
+
+
+
+
+
+;***********************************************************************
+; Handler for Trap 7 (Device Not Available)
+;***********************************************************************
+Trap7 proc
+
+ push eax
+
+ ; Clear interrupted VSM's CR0.EM (so it will own the FPU)
+ mov eax, CR0
+ and al, NOT CR0_EM
+ mov CR0, eax
+
+
+ ; Get current owner of FPU
+ mov eax, cs:[FPU_Owner]
+
+ ; Is it non-SMM thread ?
+ cmp eax, cs:[SysMgr_VSM]
+ jne Set_EM
+
+
+ ; Yes, enable FPU restore code in Restore_IDT
+ mov byte ptr cs:[RestoreRET], 90h
+
+ ; Save non-SMM FPU state
+ ; NOTE: This must be done in 32-bit protected mode
+ mov eax, CR0 ; Enter protected mode for FPU save
+ or al, CR0_PE
+ mov CR0, eax
+ jmp $+2
+
+ db 66h
+ fnsave byte ptr cs:[FPU_State]
+
+ and al, NOT CR0_PE ; Return to real mode
+ mov CR0, eax
+
+ jmp short Record_FPU_Owner
+
+
+
+
+Set_EM:
+ ; Set previous owner's CR0.EM
+ or fs:(VSM_Header PTR [eax]).SysStuff.State.r_CR0, CR0_EM
+
+ ; Save the FPU state of the previous owner
+ ; NOTE: This can be done in 16-bit real-mode
+ fnsave byte ptr fs:(VSM_Header PTR [eax]).SysStuff.FPU_State
+
+ ; Set FPU flag
+ mov fs:(VSM_Header PTR [eax]).SysStuff.FPU_Flag, 1
+
+
+Record_FPU_Owner:
+ ; Record the new owner of the FPU
+ mov eax, cs:[Current_VSM]
+ mov cs:[FPU_Owner], eax
+
+ ; Has this VSM used the FPU previously ?
+ cmp fs:(VSM_Header PTR [eax]).SysStuff.FPU_Flag, 0
+ je short Exit
+
+ ; Yes, restore its FPU state
+ ; NOTE: This can be done in 16-bit real-mode
+ lea eax, (VSM_Header PTR [eax]).SysStuff.FPU_State
+ frstor byte ptr fs:[eax]
+
+Exit: pop eax
+ iret ; Return to the interrupted VSM
+
+Trap7 endp
+
+
+
+
+
+;***********************************************************************
+; Exception vectors (segments will be patched)
+;***********************************************************************
+Saved_INTs:
+ dd OFFSET Trap_Code + 8*0
+ dd OFFSET Trap_Code + 8*1
+ dd OFFSET Trap_Code + 8*2
+ dd OFFSET Trap_Code + 8*3
+ dd OFFSET Trap_Code + 8*4
+ dd OFFSET Trap_Code + 8*5
+ dd OFFSET Trap_Code + 8*6
+ dd OFFSET Trap_Code + 8*7
+ dd OFFSET Trap_Code + 8*8
+ dd OFFSET Trap_Code + 8*9
+ dd OFFSET Trap_Code + 8*0Ah
+ dd OFFSET Trap_Code + 8*0Bh
+ dd OFFSET Trap_Code + 8*0Ch
+ dd OFFSET Trap_Code + 8*0Dh
+ dd OFFSET Trap_Code + 8*0Eh
+ dd OFFSET Trap_Code + 8*0Fh
+IDT_SIZE equ ($-Saved_INTs)
+
+
+
+
+
+
+
+
+;***********************************************************************
+; Macros for performing stackless CALLs & RETs
+;***********************************************************************
+ROM_CALL macro Subr
+ local RetAddr
+ mov dx, RetAddr ; Put return addr in BP
+ jmp Subr
+RetAddr:
+ endm
+
+
+
+ROM_RET macro
+ jmp dx ; Return to caller
+ endm
+
+
+
+;***********************************************************************
+; BX = Exception #
+;***********************************************************************
+Trap_Common:
+ mov cs:[TrapNum], bx
+ mov cs:[Reg_ECX], ecx
+
+
+ ; Disable SMIs
+ mov ecx, MSR_SMM_CTRL
+ xor eax, eax
+ wrmsr
+
+ ROM_CALL NewLine
+
+ cmp bl, LastTrap
+ jbe @f
+ mov bl, LastTrap
+@@:
+ add bx, bx
+ mov bx, cs:[bx+TrapMsgTbl]
+ ROM_CALL String
+
+ lea bx, [Msg_in]
+ ROM_CALL String
+
+ ;
+ ; Display the VSM which generated the exception
+ ;
+ pop ecx ; Get SEG:OFFSET of faulting code
+ mov cs:[SegOff], ecx
+ mov esi, cs:[Current_VSM]
+ mov ah, fs:(VSM_Header PTR [esi]).VSM_Type
+ lea si, [VSM_Table]
+ ASSUME SI: PTR TableItem
+ test ecx, 0FFFF0000h ; Is it System Manager ?
+ jnz ScanVSM
+ mov eax, cs:[SysMgr_VSM]
+ mov cs:[Current_VSM], eax
+ jmp ShowVSM
+ScanVSM:
+ mov al, cs:[si].Vsm ; Get VSM Type from table
+ cmp ah, al
+ je ShowVSM
+ cmp al, VSM_ANY ; End of table ?
+ je ShowVSM
+ add si, sizeof(TableItem) ; Advance to next table entry
+ jmp ScanVSM
+
+ShowVSM:
+ mov bx, cs:[si].MsgStr
+ ROM_CALL String
+
+ lea bx, Msg_VSM ; VSM
+ ROM_CALL String
+
+ ROM_CALL NewLine
+ lea bx, Msg_IP ; IP = xxxx
+ ROM_CALL String
+
+ cmp cs:[TrapNum], 000Dh ; Is it Trap 0Dh ?
+ jne ShowIP
+ mov ebx, cs:[Current_VSM] ; Yes, check for bad MSR address
+ test ecx, 0FFFF0000h ; Did SysMgr cause it ?
+ jnz ComputeAddr
+ mov ebx, cs:[SysMgr_VSM] ; Yes
+ComputeAddr:
+ movzx esi, cx
+ add esi, ebx
+ mov eax, dword ptr fs:[esi]
+ cmp al, 0Fh
+ jne short ShowIP
+ cmp ah, 30h ; WRMSR ?
+ je short BadMSR
+ cmp ah, 32h ; RDMSR ?
+ jne ShowIP
+BadMSR:
+ mov cs:[MSR_Access], ah
+ mov si, sp ; Show caller
+ mov cx, ss:[si+4]
+ sub cx, 3
+
+ ; If one of the MSR routines, show caller
+ cmp si, OFFSET Read_MSR_HI
+ jb short ShowIP
+ cmp si, OFFSET Parse_Capabilities
+ jae short ShowIP
+ mov cx, ss:[si+2]
+ShowIP:
+
+
+ mov ax, cx
+ ROM_CALL Hex16
+
+ mov al, '/'
+ out dx, al
+ movzx eax, cx
+ add eax, cs:[Current_VSM]
+ ROM_CALL Hex32
+
+
+ lea bx, Msg_SP ; SP = xxxx
+ ROM_CALL String
+ mov ax, sp
+ ROM_CALL Hex16
+
+ lea bx, Msg_BP ; BP = xxxx
+ ROM_CALL String
+ mov ax, bp
+ ROM_CALL Hex16
+
+ cmp cs:[MSR_Access], 0 ; Was it an MSR access ?
+ je Beep
+ ROM_CALL NewLine ; Yes
+ lea bx, [Msg_MSR]
+ ROM_CALL String
+ lea bx, [Msg_MSR_Wr]
+ cmp cs:[MSR_Access], 30h
+ je short ShowMSR
+ lea bx, [Msg_MSR_Rd]
+ShowMSR:
+ ROM_CALL String
+ mov eax, cs:[Reg_ECX] ; Display invalid MSR address
+ ROM_CALL Hex32
+
+
+HI_TONE equ 1193180/3000 ; 3 KHz
+LO_TONE equ 1193180/750 ; 750 Hz
+INTERVAL equ 100000/15 ; .10 second
+BEEP_LOOPS equ 10
+
+Beep:
+ mov bx, BEEP_LOOPS
+ in al, 61h
+ or al, 3 ; connect speaker to timer 2
+ out 61h, al
+BeepLoop:
+ mov dx, HI_TONE ; Start frequency
+TwoTone:
+ mov al, 0B6h ; timer 2 mode set
+ out 43h, al ; set mode
+ mov ax, dx
+ out 42h, al ; set LSB of counter
+ mov al, ah
+ out 42h, al ; set MSB of counter
+
+ mov cx, INTERVAL ; # 15 usec intervals
+Interval:
+ in al, 61h ; Wait for 15 usec
+ xor al, ah
+ test al, 10h
+ jz Interval
+ xor ah, 10h
+ loop Interval
+
+ shl dx, 1 ; Divide frequency by 2
+ cmp dx, LO_TONE ; End frequency
+ jb TwoTone
+ dec bx ; Decrement loop counter
+ jnz BeepLoop ; Start tones over
+
+ in al, 61h ; Turn off speaker
+ and al, NOT 3
+ out 61h, al
+
+Halt: hlt
+ jmp Halt
+
+
+
+;***********************************************************************
+; VSM strings for display of VSM causing the exception
+;***********************************************************************
+TableItem struc
+ Vsm db ?
+ MsgStr dw ?
+TableItem ends
+
+
+VSM_Table:
+ TableItem {VSM_SYS_MGR, Sys_Mgr_VSM}
+ TableItem {VSM_AUDIO, XpressAudio}
+ TableItem {VSM_VGA, SoftVGA}
+ TableItem {VSM_LEGACY, Legacy_VSM}
+ TableItem {VSM_PM, PM_VSM}
+ TableItem {VSM_OHCI, OHCI_VSM}
+ TableItem {VSM_i8042, i8042_VSM}
+ TableItem {VSM_ACPI, ACPI_VSM}
+ TableItem {VSM_APM, APM_VSM}
+ TableItem {VSM_SMB, SMB_VSM}
+ TableItem {VSM_BATTERY, Battery_VSM}
+ TableItem {VSM_RTC, RTC_VSM}
+ TableItem {VSM_S2D, S2D_VSM}
+ TableItem {VSM_SPY, Spy_VSM}
+ TableItem {VSM_NETWORK, Network_VSM}
+ TableItem {VSM_GPIO, GPIO_VSM}
+ TableItem {VSM_USB, USB_VSM}
+ TableItem {VSM_FLASH, Flash_VSM}
+ TableItem {VSM_INFRARED,Infrared_VSM}
+ TableItem {VSM_THERMAL, Thermal_VSM}
+ TableItem {VSM_NULL, Null_VSM}
+ TableItem {VSM_VIP, VIP_VSM}
+ TableItem {VSM_LPC, LPC_VSM}
+ TableItem {VSM_VUART, VUART_VSM}
+ TableItem {VSM_MICRO, Micro_VSM}
+ TableItem {VSM_USER1, User1_VSM}
+ TableItem {VSM_USER2, User2_VSM}
+ TableItem {VSM_USER3, User3_VSM}
+ TableItem {VSM_SUPERIO, SuperIO_VSM}
+ TableItem {VSM_ANY, Unknown_VSM} ; Catch-all
+
+
+Msg macro TrapString
+ db TrapString
+ db 0
+ endm
+
+XpressAudio: Msg "Audio"
+SoftVGA: Msg "SoftVG"
+Legacy_VSM: Msg "Legacy"
+USB_VSM: Msg "USB"
+GPIO_VSM: Msg "GPIO"
+ACPI_VSM: Msg "ACPI"
+Sample_VSM: Msg "Sample"
+APM_VSM: Msg "APM"
+Battery_VSM: Msg "Battery"
+PM_VSM: Msg "PM"
+S2D_VSM: Msg "SaveToRAM"
+Sys_Mgr_VSM: Msg "SysMgr"
+i8042_VSM: Msg "i8042"
+OHCI_VSM: Msg "OHCI"
+SuperIO_VSM: Msg "SuperIO"
+Null_VSM: Msg "Null"
+Spy_VSM: Msg "Spy"
+RTC_VSM: Msg "RTC"
+SPY_VSM: Msg "Spy"
+Network_VSM: Msg "Network"
+Infrared_VSM: Msg "Infrared"
+Thermal_VSM: Msg "Thermal"
+VIP_VSM: Msg "VIP"
+LPC_VSM: Msg "LPC"
+User1_VSM: Msg "User1"
+User2_VSM: Msg "User2"
+User3_VSM: Msg "User3"
+SMB_VSM: Msg "SMB"
+Flash_VSM: Msg "Flash"
+VUART_VSM: Msg "VUART"
+Micro_VSM: Msg "Micro"
+Unknown_VSM: Msg "VSM???"
+
+
+;***********************************************************************
+; Strings describing the type of exception
+;***********************************************************************
+TrapMsgTbl:
+ dw OFFSET Trap00
+ dw OFFSET Trap01
+ dw OFFSET Trap02
+ dw OFFSET Trap03
+ dw OFFSET Trap04
+ dw OFFSET Trap05
+ dw OFFSET Trap06
+ dw OFFSET Trap07
+ dw OFFSET Trap08
+ dw OFFSET Trap09
+ dw OFFSET Trap0A
+ dw OFFSET Trap0B
+ dw OFFSET Trap0C
+ dw OFFSET Trap0D
+ dw OFFSET Trap0E
+ dw OFFSET Trap0F
+ dw OFFSET Trap10
+ dw OFFSET Trap11
+ dw OFFSET Trapnn
+LastTrap equ ($-TrapMsgTbl)/2
+
+
+
+Trap00: Msg "Divide by Zero"
+Trap01: Msg "Debug"
+Trap02: Msg "NMI/INT 02h"
+Trap03: Msg "Breakpoint"
+Trap04: Msg "Overflow"
+Trap05: Msg "Bounds Check"
+Trap06: Msg "Invalid Opcode"
+Trap07: Msg "Device Not Available"
+Trap08: Msg "Double Fault"
+Trap09: Msg "Invalid TSS"
+Trap0A: Msg "INT 0Ah"
+Trap0B: Msg "Segment Not Present"
+Trap0C: Msg "Stack Fault"
+Trap0D: Msg "General Protection"
+Trap0E: Msg "Page Fault"
+Trap0F: Msg "INT 0Fh"
+Trap10: Msg "INT 10h"
+Trap11: Msg "Aligment Check"
+Trapnn: Msg "Trap ??"
+
+
+
+;***********************************************************************
+; Miscellaneous strings
+;***********************************************************************
+Msg_in: Msg " in "
+Msg_VSM: Msg " VSM"
+Msg_SP: Msg " SP="
+Msg_BP: Msg " BP="
+Msg_IP: Msg "IP="
+Msg_MSR: Msg "Invalid MSR "
+Msg_MSR_Rd: Msg "read: "
+Msg_MSR_Wr: Msg "write: "
+
+;***********************************************************************
+; Stackless display routines
+;***********************************************************************
+NewLine:
+ mov al, CR
+ out DBG_PORT, al
+ ROM_RET
+
+String:
+ mov al, cs:[bx]
+ or al, al
+ jz StringExit
+ out DBG_PORT, al
+ in al, 80h
+ inc bx ; Advance ptr
+ jmp String
+StringExit:
+ ROM_RET
+
+
+Seg_Addr:
+ mov si, bp
+ rol eax, 16
+ xchg ah, al
+ ROM_CALL Hex8
+ xchg ah, al
+ ROM_CALL Hex8
+ mov al, ':'
+ out DBG_PORT, al
+
+ rol eax, 16
+ xchg ah, al
+ ROM_CALL Hex8
+ xchg ah, al
+ ROM_CALL Hex8
+
+ mov bp, si ; Restore ret addr
+ ROM_RET
+
+
+Hex32: rol edx, 16 ; Save return address in upper EDX
+
+ rol eax, 8
+ ROM_CALL Hex8
+ rol eax, 8
+ ROM_CALL Hex8
+ rol eax, 8
+ ROM_CALL Hex8
+ rol eax, 8
+ ROM_CALL Hex8
+ mov al, ' '
+ out DBG_PORT, al
+ rol edx, 16 ; Restore return address
+ ROM_RET
+
+
+
+Hex16: rol edx, 16 ; Save return address in upper EDX
+ xchg ah, al
+ ROM_CALL Hex8
+ xchg ah, al
+ ROM_CALL Hex8
+ rol edx, 16 ; Restore return address
+ mov al, ' '
+ out DBG_PORT, al
+ ROM_RET
+
+
+Hex8:
+ ; Display 4 MSBs
+ mov di, ax
+ rol al, 4
+ and al, 0Fh
+ add al, '0' ; Convert to ASCII
+ cmp al, '9'
+ jbe @f
+ add al, 7 ; 'A'-'F'
+@@: out DBG_PORT, al
+ in al, 80h
+ mov ax, di
+
+
+ ; Display 4 LSBs
+ and al, 0Fh
+ add al, '0' ; Convert to ASCII
+ cmp al, '9'
+ jbe Char
+ add al, 7 ; 'A'-'F'
+Char: out DBG_PORT, al
+ in al, 80h
+ ROM_RET
+
+SegOff dd 0
+Reg_ECX dd 0
+TrapNum dw 0
+MSR_Access db 0
+
+
+ end
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/image.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/image.asm
new file mode 100755
index 0000000..6445839
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/image.asm
@@ -0,0 +1,37 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file contains the label for the beginning of the VSA image *
+;* It MUST be the last .OBJ file in the link
+
+
+.model small,c
+.586
+.CODE
+
+public VSA_Image
+
+TEXT SEGMENT PARA 'CODE'
+
+VSA_Image:
+
+TEXT ENDS
+
+ END
+ \ No newline at end of file
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/init.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/init.asm
new file mode 100755
index 0000000..34b6742
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/init.asm
@@ -0,0 +1,1017 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;*******************************************************************************
+;* This file contains the installation code for VSA II.
+;*
+;* BIOS Usage:
+;* CALL far ptr [VSA_Entry]
+;* where VSA_Entry: dw 0020h, <segment>
+;*
+;*******************************************************************************
+
+
+include vsa2.inc
+include sysmgr.inc
+include init.inc
+include smimac.mac
+include chipset.inc
+;include vpci.inc
+DESCRIPTOR struc
+DescrType BYTE ? ; Type of MSR
+Flag BYTE ? ; See definitions below
+Link BYTE ? ; Link to next MSR
+Split BYTE ? ; Index of descriptor that was split
+
+Owner WORD ? ; PCI Address this descriptor belongs to
+Mbiu BYTE ? ; MBUI on which this descriptor is located
+Port BYTE ? ; Port this descriptor routes to
+
+MsrAddr DWORD ? ; Routing address of MSR (descriptor/LBAR/RCONF)
+MsrData0 DWORD ? ; MSR data low
+MsrData1 DWORD ? ; MSR data high
+Physical DWORD ? ; Physical memory assigned (00000000 if none)
+Range DWORD ? ; Actual I/O range for IOD_SC
+Address WORD ? ; Address of I/O Trap or Timeout
+DESCRIPTOR ENDS
+
+
+.model small,c
+.586
+.CODE
+
+VERIFY_VSM_COPY equ 1 ; 0=skip verify
+
+
+SW_SMI equ 0D0h
+
+
+; VSA loader debug codes:
+VSA_ENTERED equ 10h ; VSA installation has been entered
+VSA_INIT1 equ 11h ; Returned from Setup
+VSA_SYSMGR equ 12h ; Image of SysMgr was found
+VSA_VSM_FOUND equ 13h ; A VSM has been found (followed by VSM type)
+VSA_COPY_START equ 14h ; Start of module copy
+VSA_COPY_END equ 15h ; End of module copy
+VSA_VRFY_START equ 1Ch ; Start of verifying module copy
+VSA_VRFY_END equ 1Dh ; End of verifying module copy
+VSA_FILL_START equ 1Eh ; Start of filling BSS
+VSA_FILL_END equ 1Fh ; End of filling BSS
+VSA_INIT2 equ 16h ; Returned from copying VSA image
+VSA_INIT3 equ 17h ; Performing VSA initialization SMI
+VSA_INIT4 equ 18h ; Returned from s/w SMI
+VSA_INIT5 equ 19h ; Returned from initializing statistics
+VSA_INIT6 equ 1Ah ; Returning to BIOS
+VSA_ERROR equ 0EEh ; Installation error. EBX contains error mask
+
+
+
+; NOTES:
+; 1) A VSM's CS segment must be writeable since the message queue is
+; stored there and the VSM must be able to update the pointers.
+; 2) The nested flag must be set so when the System Manager RSMs
+; to a VSM, the processor remains in SMM.
+VSM_FLAGS equ SMI_FLAGS_CS_WRITABLE + SMI_FLAGS_NESTED + SMI_FLAGS_CS_READABLE
+
+
+
+
+
+POST macro Code
+
+ mov al, Code
+ out 80h, al
+
+ endm
+
+public Device_ID
+public Chipset_Base
+public Errors
+public BIOS_ECX
+public BIOS_EDX
+
+
+externdef Software_SMI: proc
+externdef Get_Sbridge_Info: proc
+externdef Get_IRQ_Base: proc
+externdef Get_SMI_Base: proc
+externdef Get_CPU_Info: proc
+externdef Clear_SMIs: proc
+externdef Get_SMM_Region: proc
+externdef Init_SMM_Region: proc
+externdef Enable_SMIs: proc
+externdef Enable_SMM_Instr: proc
+externdef Disable_A20: proc
+externdef Get_Memory_Size: proc
+externdef Set_CPU_Fields: proc
+externdef VSA_Image: byte
+
+
+
+
+ ORG 0000h
+;***********************************************************************
+; Entry Point for DOS installer
+;***********************************************************************
+VSA_Installation:
+
+ mov dx, offset Msg_Not_DOS_BUILD
+ push cs ; DS <= CS
+ pop ds
+ mov ah, 9 ; Call DOS PrintString
+ int 21h
+
+
+ReturnToDOS:
+ sti
+ mov ah, 4Ch ; Return to DOS
+ int 21h
+
+
+ org 001Eh ; Used by INFO to skip over init code
+ dw offset VSA_Image
+
+
+;***********************************************************************
+; Entry point for BIOS installer
+;***********************************************************************
+ org 0020h
+
+VSA_Install proc far
+
+ POST VSA_ENTERED
+
+ pushf
+ push cs ; DS <- CS
+ pop ds
+ ASSUME DS:_TEXT
+ mov [BIOS_ECX], ecx ; MSR address of SMM memory descriptor (P2D_BMO)
+ mov [BIOS_EDX], edx ; MSR address of system memory descriptor (P2D_R)
+
+
+;
+; Make sure VSM's SmiHeader is DWORD aligned
+;
+ mov si, VSM_Header.SysStuff.State
+ test si, 3
+ jz AlignmentOK
+ mov bx, [Errors]
+ or bx, ERR_INTERNAL
+ jmp DisplayErrors
+
+AlignmentOK:
+
+
+ ; Set up for SMM
+ call Setup
+ jc DisplayErrors
+
+ ; Load System Manager and VSMs into memory
+ POST VSA_INIT1
+ call ProcessModules
+ POST VSA_INIT2
+
+ push cs
+ pop ds
+
+ mov bx, [Errors] ; Any errors detected ?
+ test bx, bx
+ jz Init_VSA
+DisplayErrors:
+ POST VSA_ERROR
+
+ jmp Exit
+
+
+Init_VSA:
+ cli
+
+ ; Set SMM MSRs
+ mov ebx, [SysMgrEntry]
+ call Init_SMM_Region
+
+
+ ; Generate s/w SMI to initialize VSA
+ POST VSA_INIT3 ; POST 17h
+
+
+ call Enable_SMIs ; Enable SMIs
+ movzx eax, [SysCall_Code]
+ mov ebx, [InitParam1]
+ mov ecx, [InitParam2]
+ call Software_SMI
+
+ POST VSA_INIT4 ; POST 18h
+
+
+ call InitStatistics ; Initialize VSA statistics
+
+ POST VSA_INIT5 ; POST 19h
+
+
+Exit:
+ POST VSA_INIT6 ; POST 1Ah
+ popf
+ ret
+
+VSA_Install endp
+
+ ASSUME DS:NOTHING
+
+
+;***********************************************************************
+;***********************************************************************
+;***********************************************************************
+;***********************************************************************
+
+
+
+
+
+;***********************************************************************
+;
+; Some of the time in SMM cannot be recorded by VSA.
+; This unaccounted time consists of:
+; 1) the cycles used to write the SMM header.
+; 2) the cycles for the SMM entry code before RDTSC is executed.
+; 3) the cycles between the exit RDTSC through the RSM instruction.
+;
+; The following code calculates how many clocks this time consists
+; of and stores it in a VSA structure. It is used as an adjustment
+; to the statistics calculations.
+;
+;***********************************************************************
+InitStatistics proc
+
+ in al, 92h ; Save A20 mask
+ push ax
+
+ mov si, 0 ; Don't toggle A20 (no SMI)
+ call DeltaSMI
+ mov edi, eax ; EDI = overhead of DeltaSMI()
+
+ mov ebx, [SysMgrEntry] ; Get ptr to SysMgr's header
+ add ebx, VSM_Header.SysStuff
+ mov es:(System PTR [ebx]).Clocks, 0
+ mov si, 2 ; Generate an SMI by toggling A20
+ call DeltaSMI
+
+ mov ecx, es:(System PTR [ebx]).Clocks
+ sub eax, ecx ; Subtract clocks VSA determined
+ sub eax, edi ; Subtract DeltaSMI() overhead
+ mov es:(System PTR [ebx]).Adjustment, eax
+
+ pop ax ; Restore A20 mask
+ out 92h, al
+
+ ; Initialize statistics structure
+ RDTSC ; Record VSA start time
+ mov es:(System PTR [ebx+0]).StartClocks, eax
+ mov es:(System PTR [ebx+4]).StartClocks, edx
+ xor eax, eax
+ mov es:(System PTR [ebx+0]).Clocks, eax
+ mov es:(System PTR [ebx+4]).Clocks, eax
+ mov es:(System PTR [ebx+0]).NumSMIs, eax
+ mov es:(System PTR [ebx+4]).NumSMIs, eax
+ ret
+
+InitStatistics endp
+
+;***********************************************************************
+; Helper routine for InitStatistics()
+; Input: SI = XOR mask for port 92h
+;***********************************************************************
+DeltaSMI proc
+
+ RDTSC ; Record VSA start time
+ mov ecx, eax
+
+ in al, 92h ; Generate an SMI by toggling A20 mask
+ xor ax, si
+ out 92h, al
+
+ RDTSC ; Compute actual delta clocks
+ sub eax, ecx
+ jnc Exit
+ neg eax ; TSC rolled over
+Exit: ret
+
+DeltaSMI endp
+
+
+
+
+;***********************************************************************
+; Setup for VSA installation:
+; - Gets information about the system: CPU, Southbridge, memory, PCI
+; - Sets ES to be 4 GB descriptor
+; - Clears pending SMIs
+;***********************************************************************
+Setup proc near
+
+ ASSUME DS:_TEXT
+
+ cli
+
+ call Get_CPU_Info ; Get information about the CPU
+ mov [Cpu_Revision], ax
+ mov [Cpu_ID], si
+ mov [PCI_MHz], bx
+ mov [CPU_MHz], cx
+ mov [DRAM_MHz], dx
+
+ call Get_Sbridge_Info ; Get information about the Southbridge
+ jc short SetupExit
+ mov [Chipset_Base], ebx
+ mov [Device_ID], dx
+ mov [Chipset_Rev], cl
+
+ call Get_SMM_Region ; Get SMM entry point
+ mov [ModuleBase], eax
+ mov [SysMgr_Location], eax
+ mov [VSA_Size], bx
+ movzx ebx, bx ; Get end of VSA memory
+ shl ebx, 10
+ add eax, ebx
+ mov [VSA_End], eax
+
+ call Enable_SMM_Instr ; Enable SMM instructions
+
+
+ rsdc es, [Flat_Descriptor] ; Setup ES as a 4 GB flat descriptor
+
+
+ call Disable_A20 ; Turn off A20 masking
+
+
+ call Get_Memory_Size ; Get physical memory size
+ mov [TotalMemory], eax
+
+
+ call Clear_SMIs ; Clear all pending SMIs
+
+SetupExit:
+ mov [SetupComplete], 0FFh
+ clc
+ ret
+
+
+ ASSUME DS: NOTHING
+
+Setup endp
+
+
+
+
+
+
+
+
+
+
+
+;*****************************************************************************
+;
+; Loads the VSA II image into memory
+; NOTE: The System Manager must be the first module of the VSA image.
+;
+;*****************************************************************************
+ProcessModules proc
+
+ ; Point DS:ESI to loaded VSA image
+ lea bx, [VSA_Image] ; Point DS to start of file image
+ movzx esi, bx
+ and si, 000Fh
+ shr bx, 4
+ mov ax, cs
+ add ax, bx
+ mov ds, ax
+
+ ; Point EDI to where System Manager will be loaded
+ mov edi, cs:[ModuleBase] ; Get last ptr value
+ call AlignVSM
+ mov cs:[SysMgrEntry], edi ; Record entry point of System Manager
+
+
+ ; Ensure the System Manager is the first module unless loading from DOS
+ mov ax, ERR_NO_SYS_MGR
+ cmp (VSM_Header PTR [si]).Signature, VSM_SIGNATURE
+ jne ErrExit
+ cmp (VSM_Header PTR [si]).VSM_Type, VSM_SYS_MGR
+ je LoadSysMgr
+
+
+LoadSysMgr:
+ POST VSA_SYSMGR
+ call PatchSysMgr ; Apply patches to the System Manager
+
+ ; EDI = flat ptr of System Manager base
+ ; DS:SI = near ptr to System Manager image
+ call CopyModule ; Install System Manager
+ jc ErrExit
+
+
+
+ ; Sequence through each VSM and install it.
+VSM_Loop:
+ mov eax, VSM_SIGNATURE ; Check for a VSM signature
+ cmp eax, (VSM_Header PTR [si]).Signature
+ jne short Return
+ call Load_VSM ; Load the VSM
+ jnc VSM_Loop
+
+
+ErrExit:or cs:[Errors], ax
+Return: ret
+
+ProcessModules endp
+
+
+
+
+
+
+;*****************************************************************************
+; Copies INT vector table to VSA. If installing VSA from DOS, copies the
+; INT_Vector[] from current System Manager to the VSA image being installed.
+;*****************************************************************************
+SnagInterruptVectors proc
+
+Exit: ret
+
+SnagInterruptVectors endp
+
+
+
+
+
+
+;*******************************************************************
+;
+; Aligns a VSM ptr according to requirements flag
+; Input:
+; EDI = ptr to be aligned
+; Output:
+; EDI = aligned ptr
+;
+;*******************************************************************
+AlignVSM proc uses eax
+
+ mov cx, cs:[Requirments] ; Compute alignment
+ and cl, MASK Alignment@@tag_i0 ; Compute mask from 2^(n+4)
+ add cl, 4
+ xor eax, eax
+ mov al, 1
+ shl eax, cl
+ dec eax
+
+ add edi, eax ; Align the next VSM load address
+ not eax ; to requested boundary
+ and edi, eax
+ ret
+
+AlignVSM endp
+
+
+
+
+;*******************************************************************
+; Patches various fields within System Manager
+; INPUT:
+; SI = ptr to System Manager
+; EDI = ptr to where System Manager will reside
+;*******************************************************************
+PatchSysMgr proc
+
+ pushad
+
+ ;
+ ; Patch "jmp <EntryPoint>" over System Manager's VSM signature
+ ;
+ mov ax, (VSM_Header PTR [si]).EntryPoint
+ sub ax, 3
+ shl eax, 8
+ mov al, 0E9h ; JMP opcode
+ mov (VSM_Header PTR [si]).Signature, eax
+
+ ;
+ ; Patch SysMgr's Hardware structure
+ ;
+ lea bx, [si+SPECIAL_LOC]
+ mov bx, (InfoStuff PTR [bx]).HardwareInfo
+ ASSUME BX: PTR Hardware
+
+ mov ax, cs:[Device_ID]
+ mov [bx].Chipset_ID, ax
+
+ mov ax, cs:[PCI_MHz]
+ mov [bx].PCI_MHz, ax
+
+ movzx ax, cs:[Chipset_Rev]
+ mov [bx].Chipset_Rev, ax
+
+ mov eax, cs:[Chipset_Base]
+ mov [bx].Chipset_Base, eax
+
+ mov ax, cs:[Cpu_ID]
+ mov [bx].CPU_ID, ax
+
+ mov ax, cs:[Cpu_Revision]
+ mov [bx].CPU_Revision, ax
+
+ mov ax, cs:[CPU_MHz]
+ mov [bx].CPU_MHz, ax
+
+ mov ax, cs:[DRAM_MHz]
+ mov [bx].DRAM_MHz, ax
+
+ mov eax, cs:[TotalMemory]
+ mov [bx].SystemMemory, eax
+
+ mov eax, cs:[SysMgr_Location]
+ mov [bx].VSA_Location, eax
+ mov [si].SysStuff.SysMgr_Ptr, eax
+
+ mov ax, cs:[VSA_Size]
+ mov [bx].VSA_Size, ax
+ ASSUME BX:NOTHING
+
+ ;
+ ; Patch SysMgr's descriptors
+ ;
+ mov eax, (VSM_Header PTR [si]).DS_Limit
+ mov [SysMgrSize], ax
+ lea bx, (VSM_Header PTR [si])._DS
+ call Init_Descr
+
+ mov eax, SYSMGRS_STACK + VSM_STACK_FRAME
+ lea bx, (VSM_Header PTR [si])._SS
+ call Init_Descr
+
+ ;
+ ; Initialize the SysMgr's message queue
+ ;
+ call Init_Msg_Q
+
+ ;
+ ; Patch variables in SysMgr
+ ;
+ mov eax, cs:[Chipset_Base]
+ mov [si].SysStuff.Southbridge, eax
+
+ mov bx, si
+ add si, SPECIAL_LOC
+ ASSUME SI: PTR InfoStuff
+
+ movzx eax, [si].SysMgr_Stack
+ mov (VSM_Header PTR [bx]).SysStuff.SavedESP, eax
+
+ mov [si].SysMgr_VSM, edi
+
+ lea eax, (VSM_Header PTR [edi]).SysStuff.State + sizeof(SmiHeader)
+ add bx, [si].Header_Addr
+ mov [bx], eax
+
+ call Get_SMI_Base
+ mov [si].SMI_Base, eax
+
+ call Get_IRQ_Base
+ mov [si].IRQ_Base, eax
+
+
+Exit:
+
+ call SnagInterruptVectors ; Snapshot INT vectors from current VSA
+
+ popad
+ ret
+
+
+PatchSysMgr endp
+
+
+
+
+;*******************************************************************
+;
+; Loads a VSM into memory
+; Input:
+; DS:SI = ptr to VSM to load
+;
+;*******************************************************************
+Load_VSM proc
+
+ POST VSA_VSM_FOUND
+
+
+ ; Initialize the VSM's Header
+ ASSUME si:PTR VSM_Header
+
+ mov ax, [si].Flag
+ mov cs:[Requirments], ax
+ test ax, MASK SkipMe@@tag_i0
+ jz LoadIt
+
+Skip_VSM:
+ add esi, [si].VSM_Length ; Point to end of this VSM
+ call Flat_ESI
+ jmp Next_VSM
+LoadIt:
+
+ ; Initialize CPU dependent fields in the VSM's SMM header
+ call Set_CPU_Fields
+
+
+ ; Initialize EIP to VSM's entry point
+ movzx ecx, [si].EntryPoint
+ mov [si].SysStuff.State.Next_EIP, ecx
+
+ or [si].SysStuff.State.SMI_Flags, VSM_FLAGS
+
+
+ ; Store ptrs to certain System Manager structures for fast access
+ mov eax, cs:[SysMgrEntry]
+ add eax, SPECIAL_LOC
+ mov [si].SysStuff.SysMgr_Ptr, eax
+
+ mov eax, cs:[Chipset_Base]
+ mov al, SW_SMI
+ mov [si].SysStuff.Southbridge, eax
+
+
+
+ ; Initialize the VSM's resume header
+ ; Get size of DS segment
+ mov eax, [si].DS_Limit ; _DS.limit_15_0
+
+
+ inc eax ; Round to WORD boundary
+ and al, NOT 1
+ mov ecx, eax
+
+ ; Initialize the CS descriptor fields
+ ; NOTE: CS descriptor fields in SMM header are in "linear" format.
+ mov [si].SysStuff.State._CS.limit, ecx
+ mov [si].SysStuff.State._CS.attr, CODE_ATTR
+
+ mov [si].SysStuff.State.EFLAGS, VSM_EFLAGS
+ mov ecx, CR0 ; Preserve the CD & NW bit
+ and ecx, 60000000h
+ or ecx, VSM_CR0
+ mov [si].SysStuff.State.r_CR0, ecx
+ mov [si].SysStuff.State.r_DR7, VSM_DR7
+
+
+ ; Determine size of VSM's stack
+ movzx ecx, [si]._SS.limit_15_0 ; Get SS limit
+ or cx, cx ; Did VSM specify a stack size ?
+ jnz CheckMemSize
+ mov cx, VSM_STACK_SIZE ; No, use default stack size
+
+;*******************************************************************
+; SI = ptr to VSM image to be loaded
+; EAX = DS limit
+; ECX = stack size
+;*******************************************************************
+CheckMemSize:
+ add eax, ecx ; Compute descriptor limits
+ add ax, 15 ; Round up to next paragraph
+ and al, NOT 15
+ mov [si].DS_Limit,eax ; Update for use by BIOS scan
+
+ lea ebx, [edi+eax] ; If not enough memory, skip this VSM
+ cmp ebx, [VSA_End]
+ jae Skip_VSM
+ call AlignVSM
+ mov cs:[ModuleBase], edi ; Save the VSM module pointer in EDI
+
+
+;*******************************************************************
+;
+; Initialize VSM's descriptors
+;
+; SI = ptr to VSM image to be loaded
+; EAX = DS limit
+; EDI = Runtime address for this VSM
+;
+;*******************************************************************
+
+
+ ; Set VSM's CS selector to <load address> & 0xFFFFF
+ mov ecx, edi
+ and ecx, 000FFFFFh
+ shr ecx, 4
+ mov [si].SysStuff.State._CS.selector, cx
+
+ mov [si].SysStuff.State._CS.base, edi
+
+
+ ; Initialize the VSM's stack ptr
+ mov ebx, eax
+ and bl, 0FCh ; Round DOWN to nearest DWORD
+ sub bx, VSM_STACK_FRAME
+ mov [si].SysStuff.SavedESP, ebx
+
+ lea bx, [si]._DS ; Init DS
+ call Init_Descr
+
+ lea bx, [si]._ES ; Init ES
+ call Init_Descr
+
+ lea bx, [si]._SS ; Init SS
+ call Init_Descr
+
+
+ ; Initialize the VSM's message queue
+ call Init_Msg_Q
+
+
+ ; Update the doubly linked list of VSMs
+ mov ebx, edi
+ xchg ebx, cs:[Blink]
+ or ebx, ebx ; 1st VSM other than System Manager ?
+ jnz SetFlink
+
+ ; Store ptr to 1st VSM in the System Manager
+ mov eax, cs:[SysMgrEntry]
+ mov es:(VSM_Header PTR [eax]).SysStuff.Flink, edi
+
+ jmp Setlinks
+
+ ; EBX points to previous VSM
+SetFlink:
+ mov (VSM_Header PTR es:[ebx]).SysStuff.Flink, edi
+Setlinks:
+ mov [si].SysStuff.Blink, ebx
+
+ mov eax, cs:[Flink]
+ mov [si].SysStuff.Flink, eax
+
+ call CopyModule
+ ret
+
+
+Load_VSM endp
+
+
+END_MSG_QUEUE equ (MAX_MSG_CNT)*sizeof(Message)
+
+
+Init_Msg_Q proc
+
+ mov bx, offset VSM_Header.SysStuff.MsgQueue
+ mov [si].SysStuff.Qhead, bx ; Store queue head ptr
+ mov [si].SysStuff.Qtail, bx ; Store queue tail ptr
+ add bx, END_MSG_QUEUE ; End of queue
+ mov [si].SysStuff.EndMsgQ, bx
+ ret
+
+Init_Msg_Q endp
+
+
+
+
+
+
+
+;*******************************************************************
+;
+; Initializes a descriptor
+; On entry:
+; BX = ptr to descriptor
+; EAX = limit
+; EDI = base
+;
+;*******************************************************************
+Init_Descr proc
+ ASSUME bx: PTR Descriptor
+
+ push eax
+ push edi
+ mov [bx].limit_15_0, ax ; limit
+ shr eax, 16
+ mov [bx].limit_19_16, al
+ mov [bx].base_15_0, di ; base[15:00]
+ shr edi, 16
+ mov ax, di
+ mov [bx].base_23_16, al ; base[31:16]
+ mov [bx].base_31_24, ah
+ mov [bx].attr, DATA_ATTR ; attribute
+ pop edi
+ pop eax
+ ret
+
+ ASSUME bx: NOTHING
+
+Init_Descr endp
+
+
+;*******************************************************************
+;
+; Copies a module to its runtime location.
+; On Entry:
+; DS:SI - ptr to source
+; ES:EDI - ptr to destination
+; On Exit:
+; CF - set if error. AX = error code
+;*******************************************************************
+CopyModule proc
+
+
+
+ ; Get length of segment & compute size of BSS
+ mov ecx, [si].VSM_Length
+ movzx edx, [si]._DS.limit_15_0
+ sub edx, ecx
+
+
+ call Flat_ESI
+
+
+ ;
+ ; Copy the VSM image to its runtime location
+ ;
+
+if VERIFY_VSM_COPY
+ push ecx ; Save byte count & ptrs
+ push esi
+ push edi
+endif
+
+ POST VSA_COPY_START ; 14h
+
+ mov ah, cl
+ shr ecx, 2 ; Convert BYTE count to DWORD count
+ cld
+ rep movsd [edi], es:[esi]
+
+ and ah, 3 ; Copy remaining bytes
+ mov cl, ah
+ rep movsb [edi], es:[esi]
+
+ POST VSA_COPY_END ; 15h
+
+if VERIFY_VSM_COPY
+
+ pop edi ; Restore original ptrs and byte count
+ pop esi
+ pop ecx
+
+ ;
+ ; Verify the VSM image copy
+ ;
+ mov ebx, edi ; Save ptr to start of VSM
+ shr ecx, 2 ; Convert byte count to dword count
+
+ POST VSA_VRFY_START ; 1Ch
+
+ repe cmpsd es:[esi], [edi]
+ jne VerifyError
+
+ mov cl, ah ; Compare leftover byte(s)
+ repe cmpsb es:[esi], [edi]
+ je Verify_Passed
+
+VerifyError:
+
+ mov ax, ERR_VERIFY
+ stc
+ jmp Exit
+
+Verify_Passed:
+ POST VSA_VRFY_END ; 1Dh
+
+endif ; VERIFY_VSM_COPY
+
+
+
+
+ POST VSA_FILL_START
+
+ ;
+ ; Clear the uninitialized data space
+ ;
+ mov ecx, edx ; Fill BSS with zeros
+ shr ecx, 2
+ xor eax, eax
+ rep stosd [edi]
+ mov cl, dl
+ and cl, 3
+ je BSS_Cleared
+ rep stosb [edi]
+BSS_Cleared:
+
+
+ POST VSA_FILL_END
+
+
+
+
+ ; Search the image for the next VSM.
+ ; Some VSMs lie about their size. Search a byte at a time
+ ; for 'VSM ', first backward, then forward.
+Next_VSM::
+ mov edx, -1 ; Start search backwards
+MAX_SEARCH equ 16
+Search:
+ mov cx, MAX_SEARCH ; Range in bytes to scan for VSM
+
+SearchNext:
+ cmp dword ptr es:[esi], VSM_SIGNATURE
+ je NextVSMfound
+ add esi, edx
+ loop SearchNext
+
+ add esi, MAX_SEARCH
+ neg edx ; Look the other direction
+ cmp dl, 1 ; Have we already looked in that direction ?
+ je Search
+ jmp OK_Exit ; No more VSMs found
+
+
+NextVSMfound:
+
+ ; Convert ESI into DS:SI format
+ mov edx, esi
+ shr edx, 4
+ mov ds, dx
+ and esi, 0000000Fh
+OK_Exit:
+ clc
+Exit: ret
+
+
+
+CopyModule endp
+
+
+;*******************************************************************
+; Converts DS:SI to a flat ptr in ESI.
+;*******************************************************************
+Flat_ESI proc
+
+ push eax
+ mov ax, ds ; Convert DS:SI to a flat ptr
+ movzx eax, ax
+ shl eax, 4
+ movzx esi, si
+ add esi, eax
+ pop eax
+ ret
+
+Flat_ESI endp
+
+
+BIOS_ECX dd 0
+BIOS_EDX dd 0
+TotalMemory dd 0
+SysMgr_Location dd 0
+VSA_End dd 0
+Chipset_Base dd 0
+SysMgrEntry dd 00000000h
+ModuleBase dd 00000000h
+Blink dd 00000000h
+Flink dd 00000000h
+InitParam1 dd 0
+InitParam2 dd 0
+
+SysMgrSize dw 0
+VSA_Size dw 0
+Errors dw 0
+Device_ID dw 0
+Cpu_ID dw 0
+Cpu_Revision dw 0
+SysCall_Code dw SYS_BIOS_INIT
+Requirments dw 0
+CPU_MHz dw 0
+PCI_MHz dw 0
+DRAM_MHz dw 0
+Chipset_Rev db 0
+SetupComplete db 0
+LoadFlag db 0
+
+Flat_Descriptor Descriptor {0FFFFh, 0000h, 00h, DATA_ATTR, 8Fh, 00h, 0}
+
+Msg_CompareError db "...compare error at 0x$"
+Msg_Not_DOS_BUILD db CR,LF, "This version of INIT doesn't support DOS install.$"
+
+
+ END VSA_Installation
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/init.h b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/init.h
new file mode 100755
index 0000000..6040cde
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/init.h
@@ -0,0 +1,39 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+#define CR 0x0D
+#define LF 0x0A
+
+#define ERR_NO_FIT (1 << 0)
+#define ERR_NO_SYS_MGR (1 << 1)
+#define ERR_BAD_TYPE (1 << 2)
+#define ERR_SMI_STATUS (1 << 3)
+#define ERR_BAD_CPU (1 << 4)
+#define ERR_NO_CHIPSET (1 << 5)
+#define ERR_NOT_CPL0 (1 << 6)
+#define ERR_VERIFY (1 << 7)
+#define ERR_VERSION (1 << 8)
+#define ERR_INTERNAL (1 << 9)
+#define ERR_INVALID_VSM (1 << 10)
+
+
+
+#define DOS_LOAD (1 << 0)
+#define VSM_LOAD (1 << 1)
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/io.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/io.c
new file mode 100755
index 0000000..6335923
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/io.c
@@ -0,0 +1,196 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Function: *
+//* Handles trapped and virtualized I/O
+
+
+
+
+#include "VSA2.H"
+#include "PROTOS.H"
+#include "SYSMGR.H"
+
+
+// External variables
+extern ULONG Saved_EAX, Saved_EDI;
+extern ULONG Nested_EAX, Nested_EDI;
+extern Descriptor Saved_ES, Flat_Descriptor;
+extern SmiHeader SMM_Header;
+
+// External routines
+extern void pascal write_flat_size(ULONG, ULONG, UCHAR);
+extern ULONG pascal Convert_To_Physical_Addr(ULONG);
+
+#define PAGING_ENABLED 0x80000001
+
+#define ADDR32 1
+#define DATA32 2
+
+
+typedef struct {
+ union {
+ ULONG Ulong;
+ struct {
+ USHORT LowAddr;
+ UCHAR MidAddr;
+ UCHAR HiAddr;
+ };
+ };
+} DESCR;
+
+
+
+//***********************************************************************
+// Returns the physical address of the location to return the value
+//***********************************************************************
+ULONG pascal Get_Logical_Address(SmiHeader * SmiHdr, ULONG * CR0_Ptr)
+{ UCHAR Override = 0, Size, Instruction;
+ static UCHAR SizeToIncr[16] = {0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,4};
+ ULONG EDI, Logical_Addr, Incr, Phys_Addr, Reg_Ptr;
+ register Descriptor * Callers_ES;
+ DESCR Mem_Ptr;
+
+
+ Size = (UCHAR)SmiHdr->data_size;
+
+ if (SmiHdr == &SMM_Header) {
+ Reg_Ptr = SysMgr_VSM + (ULONG)((USHORT)&Saved_EAX);
+ // Get ES:EDI in case it's INSW
+ Callers_ES = &Saved_ES;
+ EDI = Saved_EDI;
+ } else {
+ // Nested_EAX is a flat ptr to EAX on the VSM's stack
+ Reg_Ptr = Nested_EAX;
+ // Get ES:EDI in case it's INSW
+ Callers_ES = &Flat_Descriptor;
+ EDI = Nested_EDI;
+ }
+
+
+ // Determine default operand and address size
+ if (Callers_ES->attr & D_BIT) {
+ Override = DATA32 | ADDR32;
+ }
+
+
+ // Get address of trapped code
+ Logical_Addr = SmiHdr->Current_EIP + SmiHdr->_CS.base;
+
+ do {
+
+ // If paging is enabled...
+ if ((SmiHdr->r_CR0 & PAGING_ENABLED) == PAGING_ENABLED){
+ // translate logical to physical address via the page tables
+ Phys_Addr = Convert_To_Physical_Addr(Logical_Addr);
+ } else {
+ Phys_Addr = Logical_Addr;
+ }
+
+
+ // Get opcode
+ Instruction = (UCHAR)read_flat(Phys_Addr);
+
+ switch (Instruction) {
+
+ case 0xE4: // IN AL, <nn>
+ case 0xE5: // IN AX, <nn>
+ case 0xEC: // IN AL, DX
+ case 0xED: // IN AX, DX
+ *CR0_Ptr = 0x00000000;
+ return Reg_Ptr;
+
+ case 0x67: // Address Size
+ Override ^= ADDR32;
+ break;
+
+ case 0x66: // Data Size
+ // Override ^= DATA32;
+ case 0xF2: // REPNE
+ case 0xF3: // REPE
+ break;
+
+ case 0x6C: // INSB
+ case 0x6D: // INSW/INSD
+ Mem_Ptr.LowAddr = Callers_ES->base_15_0;
+ Mem_Ptr.MidAddr = Callers_ES->base_23_16;
+ Mem_Ptr.HiAddr = Callers_ES->base_31_24;
+
+ // (E)DI has already been inc'd/dec'd
+ Incr = SizeToIncr[Size];
+ if (SmiHdr->EFLAGS & EFLAGS_DF) {
+ EDI += Incr;
+ } else {
+ EDI -= Incr;
+ }
+
+ // If 16-bit mode, mask 16 MSBs of ptr
+ if (!(Override & ADDR32)) {
+ EDI &= 0x0000FFFF;
+ }
+ Mem_Ptr.Ulong += EDI;
+ *CR0_Ptr = SmiHdr->r_CR0;
+ return Mem_Ptr.Ulong;
+
+ default:
+ // Unexpected opcode
+ Log_Error("Unexpected opcode at 0x%08X = 0x%08X", Phys_Addr, read_flat(Phys_Addr));
+ return 0xFFFFFFFF;
+ }
+
+ // Increment code ptr
+ Logical_Addr++;
+
+ } while (1);
+
+}
+
+
+
+
+//***********************************************************************
+// Returns an I/O value to AL/AX/EAX or ES:(E)DI
+//***********************************************************************
+void pascal Return_Virtual_Value(SmiHeader * SmiHdr, ULONG Data)
+{ ULONG PhysicalAddr, LogicalAddr, CR0;
+ UCHAR Size;
+
+ LogicalAddr = Get_Logical_Address(SmiHdr, &CR0);
+
+ if (LogicalAddr == 0xFFFFFFFF)
+ return;
+
+ Size = (UCHAR)SmiHdr->data_size;
+
+
+ if ((CR0 & PAGING_ENABLED) == PAGING_ENABLED){
+ // If paging is enabled, translate logical to physical address and
+ // write one byte at a time since buffer could cross page boundary.
+ do {
+ PhysicalAddr = Convert_To_Physical_Addr(LogicalAddr++);
+ write_flat_size(PhysicalAddr, Data, BYTE_IO);
+ Data >>= 8;
+ Size >>= 1;
+ } while (Size);
+
+ } else {
+ // Write the data to memory
+ write_flat_size(LogicalAddr, Data, Size);
+ }
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/io_trap.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/io_trap.c
new file mode 100755
index 0000000..57c2fa5
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/io_trap.c
@@ -0,0 +1,218 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* Routines for setting I/O traps
+//******************************************************************************
+
+
+
+#include "VSA2.H"
+#include "PROTOS.H"
+#include "GX2.H"
+#include "VPCI.H"
+#include "DESCR.H"
+#include "CHIPSET.H"
+
+ULONG pascal Compute_IOD_SC(ULONG *, USHORT *, UCHAR);
+
+// External variables:
+extern DESCRIPTOR MSRs[];
+extern UCHAR NumMbius;
+extern MBIU_INFO MbiuInfo[MAX_MBIU];
+extern Hardware HardwareInfo;
+extern UCHAR * VsmNames[];
+extern ULONG Current_VSM;
+
+
+// Local variables:
+UCHAR MbiuSearchOrder[MAX_MBIU] = {2,1,0};
+ULONG MbiuSkipFlags[] = {NOT_GLIU0, NOT_GLIU1, NOT_GLIU2};
+
+//***********************************************************************
+// Creates an I/O descriptor for the specified Address/Range.
+// UsePID:
+// 0 = set PID to zero (generate SMI)
+// 1 = set PID to MBIU's subtractive port
+//***********************************************************************
+UCHAR pascal Setup_IO_Descriptor(ULONG * AddressPtr, USHORT * RangePtr, UCHAR UsePID)
+{ UCHAR i, j, Index, FirstChoice, SecondChoice;
+ USHORT Range, MaxRange;
+ ULONG Address, Flags;
+ MBIU_INFO * MbiuPtr;
+ register DESCRIPTOR * Descr;
+
+
+ Range = * RangePtr;
+ Flags = Address = * AddressPtr;
+
+ // Determine type(s) of I/O descriptor to use
+ FirstChoice = IOD_BM;
+ SecondChoice = IOD_SC;
+ if (Flags & (READS_ONLY | WRITES_ONLY)) {
+ FirstChoice = IOD_SC;
+ } else {
+ // Check if we should try to use a swiss-cheese descriptor
+ if (Address & 7 || Range < 8) {
+ FirstChoice = IOD_SC;
+ SecondChoice = IOD_BM;
+ }
+ }
+
+
+ // Find an appropriate descriptor
+ for (i = 0; i < NumMbius; i++) {
+ j = MbiuSearchOrder[i];
+
+ // Skip this MBIU ?
+ if (Flags & MbiuSkipFlags[j]) {
+ continue;
+ }
+
+
+ MbiuPtr = &MbiuInfo[j];
+ Index = Allocate_Descriptor(FirstChoice, SecondChoice, MbiuPtr->Mbiu);
+ if (Index != DESCRIPTOR_NOT_FOUND) {
+ break;
+ }
+ }
+ if (Index == DESCRIPTOR_NOT_FOUND) {
+ return Index;
+ }
+
+ Descr = &MSRs[Index];
+ Descr->Address = (USHORT)Address;
+
+ // Set appropriate port
+ if (UsePID) {
+ Descr->MsrData[1] = MbiuPtr->SubtrPid;
+ }
+
+ switch (Descr->Type) {
+
+ case IOD_BM:
+ // Mask must not include any valid address bits
+ MaxRange = 1 << BitScanForward(Address);
+ if (Range > MaxRange) {
+ Range = MaxRange;
+ } else {
+ while (!IsPowerOfTwo(Range)) {
+ Range--;
+ }
+ }
+ (USHORT)Descr->MsrData[1] = (USHORT)Address >> 12;
+ Descr->MsrData[0] = ~(Range-1) | 0x000F0000;
+ Descr->MsrData[0] |= Address << 20;
+ Descr->Range = Range;
+ * AddressPtr += Range;
+ * RangePtr -= Range;
+ break;
+
+ case IOD_SC:
+ Descr->MsrData[0] = Compute_IOD_SC(AddressPtr, RangePtr, 1);
+ Descr->Range = Range - * RangePtr;
+ break;
+
+ default:
+ return DESCRIPTOR_NOT_FOUND;
+
+ }
+
+ Write_MSR(Descr->MsrAddr, Descr->MsrData);
+ return Index;
+}
+
+
+
+//***********************************************************************
+// Clears an I/O trap on the specified I/O Range
+//***********************************************************************
+void pascal Clr_MBus_IO_Trap(ULONG Address, USHORT Range)
+{ UCHAR Index;
+
+ while (Range) {
+
+ // Find an existing descriptor that matches Address
+ Index = Find_Matching_IO_Descriptor(&Address, &Range, 0);
+
+ if (Index == DESCRIPTOR_NOT_FOUND) {
+ // Report error
+ Log_Error("Unregistration of I/O 0x%04X by the %s VSM", Address, VsmNames[Get_VSM_Type(Current_VSM)]);
+ return;
+ }
+ }
+}
+
+
+//***********************************************************************
+// Sets an I/O trap on the specified I/O Range
+//***********************************************************************
+void pascal Set_MBus_IO_Trap(ULONG Address, USHORT Range)
+{ UCHAR Index;
+
+
+ // If the range is > 8 bytes and/or is not a power of 2,
+ // multiple descriptors may be required.
+ while (Range) {
+ // Find an existing descriptor that matches Address
+ Index = Find_Matching_IO_Descriptor(&Address, &Range, 2);
+
+ if (Index == DESCRIPTOR_NOT_FOUND) {
+ // An existing descriptor does not match the range.
+ // Allocate a new descriptor
+ Index = Setup_IO_Descriptor(&Address, &Range, 0);
+ if (Index == DESCRIPTOR_NOT_FOUND) {
+ // Report resource error
+ Log_Error("No descriptors for I/O trap of 0x%04X by the %s VSM", Address, VsmNames[Get_VSM_Type(Current_VSM)]);
+ break;
+ }
+ } else {
+ // An existing descriptor was modified for the new Addr/Range
+ }
+ MSRs[Index].Flag |= IO_TRAP;
+ }
+}
+
+
+//***********************************************************************
+// Enable/Disable I/O trap
+//***********************************************************************
+void pascal MBus_IO_Trap(ULONG Param1, ULONG Param2, UCHAR EnableFlag)
+{ ULONG Address;
+ USHORT Range;
+
+ // Repackage parameters
+ Address = Param2;
+ (USHORT)Address = (USHORT)Param1;
+ Range = (USHORT)Param2;
+
+
+ // Check for illegal combination of flags
+ if ((Address & ALL_GLIUS) == ALL_GLIUS) {
+ // Report error
+ Log_Error("Illegal combination of flags for I/O 0x%04X by the %s VSM", Address, VsmNames[Get_VSM_Type(Current_VSM)]);
+ return;
+ }
+
+ if (EnableFlag) {
+ Set_MBus_IO_Trap(Address, Range);
+ } else {
+ Clr_MBus_IO_Trap(Address, Range);
+ }
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/makefile b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/makefile
new file mode 100755
index 0000000..c9ae416
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/makefile
@@ -0,0 +1,222 @@
+
+#
+# Copyright (c) 2006 Advanced Micro Devices,Inc. ("AMD").
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# This code is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General
+# Public License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA
+#
+
+######################################################################
+#
+# Init variables
+#
+######################################################################
+
+!ifndef VSA2ROOT
+VSA2ROOT = ..
+!endif
+
+BUILD_DIR = $(VSA2ROOT)\build
+OBJECT = obj
+!include $(BUILD_DIR)\setvars.mak
+.SUFFIXES: .asm .c .h .inc .map .obj .mac
+
+INCLUDE = $(OBJECT);$(INCLUDE)
+
+VSMNAME = sysmgr
+
+
+######################################################################
+#
+# Build Macros
+#
+######################################################################
+
+INIT_ASM_OBJS = \
+ $(OBJECT)\init.obj \
+ $(OBJECT)\cpu_init.obj \
+ $(OBJECT)\chip.obj \
+ $(OBJECT)\image.obj \
+
+SYSMGR_ASM_OBJS = \
+ $(OBJECT)\sysmgr.obj \
+ $(OBJECT)\bugs.obj \
+ $(OBJECT)\utils.obj \
+ $(OBJECT)\syscalls.obj \
+ $(OBJECT)\smis.obj \
+ $(OBJECT)\port92.obj \
+ $(OBJECT)\sw_int.obj \
+ $(OBJECT)\debug.obj \
+ $(OBJECT)\vr_misc.obj \
+ $(OBJECT)\cpu.obj \
+ $(OBJECT)\idt.obj \
+ $(OBJECT)\message.obj \
+ $(OBJECT)\msr.obj \
+
+SYSMGR_C_OBJS = \
+ $(OBJECT)\events.obj \
+ $(OBJECT)\handlers.obj \
+ $(OBJECT)\chipset.obj \
+ $(OBJECT)\gpio.obj \
+ $(OBJECT)\errors.obj \
+ $(OBJECT)\history.obj \
+ $(OBJECT)\io.obj \
+ $(OBJECT)\virt_pci.obj \
+ $(OBJECT)\mbus.obj \
+ $(OBJECT)\vsa_init.obj \
+ $(OBJECT)\descr.obj \
+ $(OBJECT)\vr.obj \
+ $(OBJECT)\topology.obj \
+ $(OBJECT)\pci_rd.obj \
+ $(OBJECT)\pci_wr.obj \
+ $(OBJECT)\cs5536.obj \
+ $(OBJECT)\swapsif.obj \
+ $(OBJECT)\unregstr.obj \
+ $(OBJECT)\mdd.obj \
+ $(OBJECT)\pci_pm.obj \
+ $(OBJECT)\gpio5536.obj \
+ $(OBJECT)\mfgpt.obj \
+ $(OBJECT)\mapper.obj \
+ $(OBJECT)\timeout.obj \
+ $(OBJECT)\io_trap.obj \
+ $(OBJECT)\mbiu.obj \
+ $(OBJECT)\timer.obj \
+ $(OBJECT)\ohci.obj \
+
+SYSMGR_C_CODS = $(SYSMGR_C_SRCS:.obj=.cod)
+
+SYSMGR_OBJS = $(SYSMGR_ASM_OBJS) $(SYSMGR_C_OBJS)
+
+SYSMGR_VSM = $(OBJECT)\sysmgr.vsm
+
+#######################################################################
+#
+# Targets
+#
+#######################################################################
+
+
+all: $(OBJECT) setenv sysmgr.vsm vsainit.bin
+!ifdef BUILDOBJ
+ $(COPY) $(OBJECT)\sysmgr.vsm $(BUILDOBJ)
+ $(COPY) $(OBJECT)\vsainit.bin $(BUILDOBJ)
+!endif
+
+sysmgr.vsm: $(SYSMGR_OBJS)
+ $(LN) /MAP $(LOPTS_VSM) @<<sysmgr.lnk
+ $(SYSMGR_OBJS: =+^
+ )
+$(SYSMGR_VSM)
+
+;
+<<NOKEEP
+
+vsainit.bin init.exe: $(INIT_ASM_OBJS)
+ $(LN) $(LD_OPTS) /MAP $**,$(OBJECT)\init.exe,$(OBJECT)\init.map;
+ $(X2ROM) $(OBJECT)\init.exe $(OBJECT)\vsainit.bin
+# $(COPY) $(OBJECT)\init.rom $(OBJECT)\vsainit.bin
+
+#This and only this clean target must exist as it is called by cleanall
+#cleanall and cleanlocal are defined in rules.mak
+
+clean: cleanlocal
+
+$(OBJECT):
+ -@md $(OBJECT)
+
+#######################################################################
+#
+# Dependencies
+#
+#######################################################################
+
+$(SYSMGR_ASM_OBJS): $(MAKEDIR)\makefile \
+ $(OBJECT)\sysmgr.inc \
+ $(OBJECT)\smimac.mac \
+ $(OBJECT)\vsa2.inc \
+ $(OBJECT)\isa.inc \
+ $(OBJECT)\chipset.inc \
+ $(OBJECT)\vr.inc \
+ $(OBJECT)\pci.inc \
+ $(OBJECT)\hce.inc \
+ $(OBJECT)\gx2.inc \
+ $(OBJECT)\protos.inc \
+ $(OBJECT)\descr.inc \
+ $(OBJECT)\mdd.inc \
+ $(OBJECT)\cs5536.inc \
+
+$(SYSMGR_C_OBJS): $(MAKEDIR)\makefile \
+ $(OBJECT)\sysmgr.h \
+ $(OBJECT)\vsa2.h \
+ $(OBJECT)\isa.h \
+ $(OBJECT)\chipset.h \
+ $(OBJECT)\vr.h \
+ $(OBJECT)\pci.h \
+ $(OBJECT)\vpci.h \
+ $(OBJECT)\protos.h \
+ $(OBJECT)\mdd.h \
+ $(OBJECT)\timer.h \
+ $(OBJECT)\mapper.h \
+ $(OBJECT)\gx2.h \
+ $(OBJECT)\hce.h \
+ $(OBJECT)\acpi.h \
+ $(OBJECT)\cs5536.h \
+
+$(INIT_ASM_OBJS): $(MAKEDIR)\makefile \
+ $(OBJECT)\sysmgr.inc \
+ $(OBJECT)\smimac.mac \
+ $(OBJECT)\vsa2.inc \
+ $(OBJECT)\isa.inc \
+ $(OBJECT)\chipset.inc \
+ $(OBJECT)\vr.inc \
+ $(OBJECT)\pci.inc \
+ $(OBJECT)\init.inc \
+ $(OBJECT)\mdd.inc \
+ $(OBJECT)\gx2.inc \
+ $(OBJECT)\cs5536.inc \
+
+######################################################################
+#
+# Common Targets
+#
+######################################################################
+# include common targets and inference rules
+!include $(BUILD_DIR)\rules.mak
+
+######################################################################
+#
+# Inference Rules
+#
+######################################################################
+# Override common inference rules here
+
+{$(INC_DIR)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zni /C $<
+
+{$(INC_DIR)\$(CPU)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zni /C $<
+
+{$(SYSMGR_SRC)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zns /C $<
+
+{$(SYSMGR_SRC)\$(CPU)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zns /C $<
+
+$(OBJECT)\hce.inc:
+ $(H2) /Fa$(OBJECT)\hce.inc /Znh /C $(INC_DIR)\hce.h
+
+$(OBJECT)\protos.inc:
+ $(H2) /Fa$(OBJECT)\protos.inc /Zn"q" /C $(SYSMGR_SRC)\protos.h
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mapper.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mapper.c
new file mode 100755
index 0000000..bc1e9bc
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mapper.c
@@ -0,0 +1,118 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* This file contains code specific to the IRQ Mapper
+//******************************************************************************
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "PROTOS.H"
+#include "VPCI.H"
+#include "PCI.H"
+#include "MDD.H"
+#include "MAPPER.H"
+#include "ISA.H"
+
+// Local Variables:
+UCHAR PCI_INTs[4] = {0,0,0,0}; // Current PCI INT mappings
+UCHAR Max_PCI_Interrupt=4;
+
+// External Variables:
+extern ULONG MDD_Base;
+extern USHORT Saved_AX;
+
+
+
+
+// External Functions:
+void PCI_Interrupts(void);
+
+
+
+//************************************************************************************
+// Maps an Unrestricted Source to a PIC IRQ via the IRQ Mapper logic
+//************************************************************************************
+void pascal IRQ_Mapper(UCHAR Reg, UCHAR Source, UCHAR Irq)
+{ ULONG MsrAddr, MsrData;
+ UCHAR ShiftCount;
+
+ // 8 sources per MSR
+ Reg += Source/8;
+
+ MsrAddr = MDD_Base + Reg;
+
+ // 4 bits per field
+ ShiftCount = (Source % 8) * 4;
+
+ // Map Unrestricted Source[Source] to Irq via IRQ Mapper
+ MsrData = Read_MSR_LO(MsrAddr);
+ MsrData &= ~(0x0000000FL << ShiftCount);
+ MsrData |= (ULONG)Irq << ShiftCount;
+ Write_MSR_LO(MsrAddr, MsrData);
+}
+
+//************************************************************************************
+// Maps an Unrestricted Source Y to a PIC IRQ
+//************************************************************************************
+void pascal IRQY_Mapper(UCHAR Y_Source, UCHAR Irq)
+{
+ IRQ_Mapper(MSR_IRQM_YLOW, Y_Source, Irq);
+}
+
+
+//************************************************************************************
+// Maps an Unrestricted Source Z to a PIC IRQ
+//************************************************************************************
+void pascal IRQZ_Mapper(UCHAR Z_Source, UCHAR Irq)
+{
+ IRQ_Mapper(MSR_IRQM_ZLOW, Z_Source, Irq);
+}
+
+
+
+//************************************************************************************
+// Implements the SYS_GENERATE_IRQ macro for CS5536
+//************************************************************************************
+void pascal Generate_IRQ_5536(USHORT IRQ_Mask)
+{ UCHAR Irq=0;
+ USHORT Level;
+
+ Level = in_16(PIC1_EDGE);
+
+ // Don't attempt to generate a level-sensitive interrupt
+ if (IRQ_Mask & Level) {
+ Log_Error("Attempt to generate a level-sensitive IRQ. Mask= 0x%04X", IRQ_Mask);
+ return;
+ }
+
+ while (IRQ_Mask) {
+ if (IRQ_Mask & 1) {
+ // Map the software IRQ to the requested IRQ
+ IRQY_Mapper(Y_IRQ_SW, Irq);
+
+ // Generate an edge to the PIC
+ Write_MSR_LO(MDD_Base + MSR_SOFT_IRQ, 0L);
+ Write_MSR_LO(MDD_Base + MSR_SOFT_IRQ, 1L);
+ }
+ IRQ_Mask >>= 1;
+ Irq++;
+ }
+}
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mapper.h b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mapper.h
new file mode 100755
index 0000000..f4737b6
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mapper.h
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+
+// Unrestricted Y usage:
+#define Y_IRQ_SW 0
+#define Y_IRQ_USB1 1
+#define Y_IRQ_USB2 2
+#define Y_IRQ_RTC 3
+#define Y_IRQ_AUDIO 4
+#define Y_IRQ_PME 5
+#define Y_IRQ_FLASH 6
+#define Y_IRQ_SMB 12
+#define Y_IRQ_KEL 13
+#define Y_IRQ_UART1 14
+#define Y_IRQ_UART2 15
+
+
+
+// Unrestricted Z usage:
+#define Z_IRQ_MFGPT_04 0
+#define Z_IRQ_MFGPT_15 1
+#define Z_IRQ_MFGPT_26 2
+#define Z_IRQ_MFGPT_37 3
+
+#define Z_IRQ_SMI 8
+#define Z_IRQ_INTA 9
+#define Z_IRQ_INTB 10
+#define Z_IRQ_INTC 11
+#define Z_IRQ_INTD 12
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mbiu.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mbiu.c
new file mode 100755
index 0000000..4a35388
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mbiu.c
@@ -0,0 +1,135 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Function: *
+//* Utility routines for managing MBIUs
+
+
+#include "VSA2.H"
+#include "PROTOS.H"
+#include "GX2.H"
+#include "VPCI.H"
+#include "DESCR.H"
+#include "SYSMGR.H"
+
+
+extern void InitStatCounters(ULONG, UCHAR);
+
+
+// External variables:
+extern ULONG Mbiu0;
+
+// Local variables:
+ULONG ExtendedMemoryDescr0, ExtendedMemoryDescr1 = 0;
+MBIU_INFO MbiuInfo[MAX_MBIU];
+UCHAR NumMbius=0;
+
+
+
+
+
+//***********************************************************************
+// Called once for each MBIU:
+// - Initializes statistic counters
+// - Records all available descriptors
+//***********************************************************************
+void pascal Init_MBIU(UCHAR * CountPtr, ULONG Msr)
+{ UCHAR Type, i;
+ ULONG Default[2], MsrData[2];
+
+
+ // Record info about MBIU
+ MbiuInfo[NumMbius].Mbiu = Msr;
+ MbiuInfo[NumMbius].SubtrPid = Read_MSR_LO(Msr + MBD_MSR_CONFIG) << 29;
+ MbiuInfo[NumMbius].NumCounters = ((CAPABILITIES *)CountPtr)->NSTATS;
+ MbiuInfo[NumMbius].ActiveCounters = 0x00;
+ MbiuInfo[NumMbius].ClockGating = Read_MSR_LO(Msr + MBD_MSR_PM);
+
+ // Clear SMIs on this MBIU & disable all events except HW Emulation
+ MsrData[0] = 0x0000000E;
+ MsrData[1] = 0x0000000F;
+ (USHORT)Msr = MBD_MSR_SMI;
+ Write_MSR(Msr, MsrData);
+
+ //*********************************************
+ // Initialize Statistics MSRs
+ //*********************************************
+ InitStatCounters(Msr, ((CAPABILITIES *)CountPtr)->NSTATS);
+
+ //*********************************************
+ // Begin with P2D_BM descriptors
+ //*********************************************
+ Type = P2D_BM;
+ (USHORT)Msr = MSR_MEM_DESCR;
+
+ do {
+
+ // Get number of next type of descriptor
+ if (i = *(CountPtr++)) {
+
+ // Get the default value for this descriptor type
+ Get_Descriptor_Default(Type, Default);
+
+ // Loop through all descriptors of a given type
+ do {
+
+ // If descriptor is already in use by the BIOS, skip it
+ Read_MSR(Msr, MsrData);
+ if ((MsrData[0] == Default[0]) && (MsrData[1] == Default[1])) {
+
+ // Initialize Descriptor[] entry
+ if (Init_Descr(Type, Msr)) {
+ // Not enough table entries...abort
+ Type = 0x99;
+ break;
+ }
+
+ } else {
+ // Descriptor is in use.
+ // If it's an extended memory descriptor, record the routing address.
+ if (Type == P2D_R) {
+ if ((Msr & ROUTING) == Mbiu0) {
+ ExtendedMemoryDescr0 = Msr;
+ } else {
+ ExtendedMemoryDescr1 = Msr;
+ }
+ }
+ }
+ Msr++;
+ } while (--i);
+ }
+
+ // Check next descriptor type.
+ // If transitioning from P2D to IOD descriptors...
+ if (++Type == IOD_BM) {
+ // change MSR offset to 0xE0
+ (USHORT)Msr = MSR_IO_DESCR;
+ }
+ } while (Type <= IOD_SC);
+
+ // Increment number of MBIUs
+ NumMbius++;
+}
+
+
+
+
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mbus.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mbus.c
new file mode 100755
index 0000000..d03d2ee
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mbus.c
@@ -0,0 +1,758 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* Routines related to the MBus
+//******************************************************************************
+
+
+#include "VSA2.H"
+#include "PROTOS.H"
+#include "PCI.H"
+#include "GX2.H"
+#include "VPCI.H"
+#include "CHIPSET.H"
+#include "DESCR.H"
+#include "MDD.H"
+#include "SYSMGR.H"
+
+// Externals:
+extern void InitLogicalCounters(void);
+extern UCHAR GetPortID(ULONG);
+extern void pascal ClearMbiu(ULONG);
+extern UCHAR pascal Get_MBus_Status(ULONG, USHORT);
+extern UCHAR pascal Is_LBAR_Enabled(PCI_HEADER_ENTRY * Pci);
+extern ULONG pascal Compute_IOD_SC(ULONG *, USHORT *, UCHAR);
+extern PCI_HEADER_ENTRY * pascal Get_Structure(USHORT);
+
+extern USHORT Class;
+extern CAPABILITIES Southbridge_MBIU;
+extern ULONG Mbiu2, MPCI_SB;
+extern ULONG ACPI_Timer_MSR;
+extern Hardware HardwareInfo;
+extern MBIU_INFO MbiuInfo[];
+extern DESCRIPTOR MSRs[];
+
+// Local Variables:
+static ULONG PCI_Value;
+ULONG Mbiu0 = PORT_MBIU0;
+ULONG Mbiu1;
+ULONG LookupMbiu;
+ULONG MPCI_NB=0;
+ULONG MCP_NB =0;
+ULONG FooGlue=0;
+UCHAR MBIU1_SelfReference;
+UCHAR VG_Port;
+UCHAR MC_Port;
+CAPABILITIES Northbridge_MBIU0, Northbridge_MBIU1;
+
+typedef struct {
+ ULONG Routing;
+ USHORT MBus_ID;
+ UCHAR Instance;
+} SCAN_RESULTS;
+
+#define MAX_HITS (3*8) // Num-GLIUs * Max-Ports-per-GLIU
+SCAN_RESULTS PriorScans[MAX_HITS];
+int j;
+
+
+//***********************************************************************
+// Scans an MBIU for the specified MBus_ID.
+// Returns MBIU routing address (LSB = MBIU port)
+//***********************************************************************
+ULONG pascal Scan_MBIU(ULONG Mbiu, USHORT Port_ID, UCHAR * Instance, UCHAR Shift)
+{ USHORT Port;
+ ULONG RoutingMask;
+
+ RoutingMask = 1L << Shift;
+
+ LookupMbiu = Mbiu;
+
+ // Adjustment for Southbridge MPCI
+ if (Port_ID == ID_MPCI && Mbiu == Mbiu2) {
+ Mbiu &= ~(RoutingMask - 1);
+ }
+
+ // Scan MBIU's ports for specified ID
+ for (Port = 0; Port <= 7; Port++) {
+
+ // If correct ID...
+ if (GetPortID(Mbiu) == Port_ID) {
+
+ // and correct instance...
+ if (--(* Instance) == 0) {
+
+ // return the routing address and port # (in 3 LSBs)
+ return (Mbiu | Port);
+ }
+ }
+
+ // Get MSR address to next device
+ Mbiu &= ~(RoutingMask - 1);
+ Mbiu += RoutingMask;
+
+ }
+
+ return 0x00000000;
+}
+
+// Port = 1
+// Mbiu = Southbridge = 0x51000000
+// Port_ID = 0x47
+// RoutingMask = 1 << 20 = 0x00100000
+
+
+
+
+//***********************************************************************
+// Finds an MBUS ID and returns the routing address.
+// The port number is also returned in the 3 LSBs.
+//***********************************************************************
+ULONG pascal Find_MBus_ID(USHORT MBus_ID, UCHAR Instance)
+{ ULONG DeviceAddr;
+ int i, SavedInstance=Instance;
+
+ // Check results of previous scans for a match
+ for (i=0; i<j; i++) {
+ if (PriorScans[i].MBus_ID == MBus_ID && PriorScans[i].Instance == Instance) {
+ return PriorScans[i].Routing;
+ }
+ }
+
+ // Filter out MBIU1 self-reference
+ if (MBus_ID == ID_MBIU) {
+ if (Instance > 2) {
+ Instance++;
+ }
+ }
+
+ // MBus_ID = 0x47
+ // Instance = 1
+ if (!(DeviceAddr = Scan_MBIU(Mbiu0, MBus_ID, &Instance, 29))) {
+ if (!(DeviceAddr = Scan_MBIU(Mbiu1, MBus_ID, &Instance, 26))) {
+ if (!(DeviceAddr = Scan_MBIU(Mbiu2, MBus_ID, &Instance, 20)) && MBus_ID == ID_ATA) {
+ DeviceAddr = Scan_MBIU(Mbiu2, ID_ATA100, &Instance, 20);
+ }
+ }
+ }
+
+ // Clear h/w emulation events generated by scanning empty ports
+ ClearMbiu(Mbiu0);
+ ClearMbiu(Mbiu1);
+
+ // SDG: if Mbiu2 is 0x51020000, then the folliwng call
+ // sets bit 32 (EDX[0]) in 0x51022002. Does this actually talk
+ // MSR 0x51000002? If so... BUG!
+
+ ClearMbiu(Mbiu2);
+
+ // Record this scan for future reference
+ if (DeviceAddr && j < MAX_HITS-1) {
+ PriorScans[j].Instance = SavedInstance;
+ PriorScans[j].MBus_ID = MBus_ID;
+ PriorScans[j].Routing = DeviceAddr;
+ j++;
+ }
+
+ return DeviceAddr;
+}
+
+
+//***********************************************************************
+// Returns the MSR address of the MPCI associated with the current device
+//***********************************************************************
+ULONG pascal GetMSR(void)
+{
+ switch (Class) {
+
+ case 0x0600: // Bridge: Host
+ return MPCI_NB;
+
+ case 0x0601: // Bridge: ISA
+ return MPCI_SB;
+
+ default:
+ return 0x00000000;
+ }
+}
+
+
+//***********************************************************************
+// Gets the PCI Latency Timer
+//***********************************************************************
+UCHAR pascal Get_Latency(PCI_HEADER_ENTRY * Pci)
+{ ULONG MsrAddr, MPCI_Ctrl[2];
+ UCHAR LatencyTimer=Pci->LatencyTimer;
+
+ // If bridge device, get MSR address of its MPCI
+ if (MsrAddr = GetMSR()) {
+ // Read Latency timer from MPCI_CTRL.LAT
+ Read_MSR(MsrAddr + MPCI_CTRL, MPCI_Ctrl);
+ LatencyTimer = (UCHAR)MPCI_Ctrl[1];
+ }
+ return LatencyTimer;
+}
+
+//***********************************************************************
+// Sets the PCI Latency timer
+//***********************************************************************
+void pascal Set_Latency(UCHAR Latency)
+{ ULONG MsrAddr=0, MPCI_Ctrl[2];
+
+ // If bridge device, get MSR address of its MPCI
+ if (MsrAddr = GetMSR()) {
+
+ // Set the PCI Latency timer
+ Read_MSR(MsrAddr + MPCI_CTRL, MPCI_Ctrl);
+ (UCHAR)MPCI_Ctrl[1] = Latency;
+
+ // LDE is only defined in Northbridge MPCI
+ if (MsrAddr == MPCI_NB) {
+ if (Latency) {
+ // Issues 118.176 & 118.197 require LDE to be set unless Latency Timer == 0
+ (USHORT)MPCI_Ctrl[0] |= LDE;
+ } else {
+ // Clear MPCI_CTRL[LDE] if Latency Timer = 0x00
+ (USHORT)MPCI_Ctrl[0] &= ~LDE;
+ }
+ }
+ Write_MSR(MsrAddr + MPCI_CTRL, MPCI_Ctrl);
+ }
+}
+
+
+//***********************************************************************
+// Enables/Disables a trap on a PCI Address
+//***********************************************************************
+void pascal Trap_PCI_IDSEL(USHORT PCI_Address, UCHAR EnableFlag)
+{ ULONG Pbus, IDSEL_Mask;
+
+ IDSEL_Mask = 1L << (UCHAR)(PCI_Address >> 11);
+ Pbus = Read_MSR_LO(MPCI_NB + MPCI_PBUS);
+
+ if (EnableFlag) {
+ Pbus |= IDSEL_Mask;
+ } else {
+ Pbus &= ~IDSEL_Mask;
+ }
+
+ Write_MSR_LO(MPCI_NB + MPCI_PBUS, Pbus);
+}
+
+
+
+
+
+//***********************************************************************
+// Initializes MBus related structures and MSRs
+// Input:
+// IDSEL_Mask = Mask of IDSELs to be virtualized
+//***********************************************************************
+void Init_MBus(void)
+{ ULONG MsrAddr, MsrData[2];
+
+
+ //*********************************************
+ // Add RCONF0-RCONF7 to available descriptor list
+ //*********************************************
+ for (MsrAddr = MSR_RCONF0; MsrAddr <= MSR_RCONF7; MsrAddr++) {
+ if (Init_Descr(GX2_RCONF, MsrAddr)) {
+ break;
+ }
+ }
+
+
+ //*********************************************
+ // Initialize MBIU0
+ //*********************************************
+ Read_MSR(Mbiu0 + MBIU_CAP, &MsrData[0]);
+ Parse_Capabilities(&MsrData[0], &Northbridge_MBIU0);
+ Init_MBIU((UCHAR *)&Northbridge_MBIU0, Mbiu0);
+
+
+
+
+ //*********************************************
+ // Initialize MBIU1
+ //*********************************************
+ // MBIU1 is MBIU0's subtractive port
+ Mbiu1 = MbiuInfo[0].SubtrPid;
+ // Determine MBIU1 self-reference
+ MBIU1_SelfReference = (UCHAR)Read_MSR_LO(Mbiu1 + MBIU_WHOAMI);
+
+ Read_MSR(Mbiu1 + MBIU_CAP, &MsrData[0]);
+ Parse_Capabilities(&MsrData[0], &Northbridge_MBIU1);
+ Init_MBIU((UCHAR *)&Northbridge_MBIU1, Mbiu1);
+
+ // Find address of MPCI_NB
+ MPCI_NB = Find_MBus_ID(ID_MPCI, 1) & 0xFFFF0000;
+
+ // Find address of MCP
+ MCP_NB = Find_MBus_ID(ID_MCP, 1) & 0xFFFF0000;
+
+ // Enable SMIs from the companion I/O
+ MsrAddr = MCP_NB | MBD_MSR_SMI;
+ Write_MSR_LO(MsrAddr, Read_MSR_LO(MsrAddr) & ~0x00000010L);
+
+ PriorScans[j].Routing = 0x00000000;
+ PriorScans[j].MBus_ID = ID_VAIL;
+ PriorScans[j].Instance = 1;
+ j++;
+
+ // On LX, FooGlue MSRs == MCP_NB+0x20
+ if (HardwareInfo.CPU_ID == DEVICE_ID_LX) {
+ PriorScans[j].Routing = MCP_NB+0x20;
+ PriorScans[j].MBus_ID = ID_FG;
+ PriorScans[j].Instance = 1;
+ j++;
+ }
+
+ // Find address of FooGlue
+ FooGlue = Find_MBus_ID(ID_FG, 1) & 0xFFFFFFF0;
+
+ // Find port of Video Generator
+ VG_Port = (UCHAR)Find_MBus_ID(ID_VG, 1);
+
+
+ // Find port of Memory Controller
+ MC_Port = (UCHAR)Find_MBus_ID(ID_MC, 1);
+
+
+ // Enable MPCI error masks
+ MsrAddr = MPCI_NB | MBD_MSR_ERROR;
+ Write_MSR_LO(MsrAddr, Read_MSR_LO(MsrAddr) & ~(MARM | TARM | BMM | SYSM | PARM));
+
+
+
+ // Initialize logical timeout counters
+ InitLogicalCounters();
+
+}
+
+
+
+
+
+//***********************************************************************
+// Computes the MSR data corresponding to an enabled PCI BAR
+//***********************************************************************
+void Compute_Msr_Value(register DESCRIPTOR * Descr, register PCI_HEADER_ENTRY * Pci)
+{ ULONG PBase, PMask, POffset=0;
+
+
+ Descr->MsrData[0] = Pci->Value;
+
+ if (Pci->Flag & IO_BAR) {
+ if (Descr->MsrAddr == ACPI_Timer_MSR) {
+ PCI_Value += 4; // Skip over ACPI timer
+ }
+ Descr->Address = (USHORT)PCI_Value;
+ }
+
+ switch (Descr->Type) {
+
+ case USB_LBAR:
+ Descr->MsrData[1] |= MEM_SPACE;
+ return;
+
+ case MDD_LBAR:
+ Descr->MsrData[1] |= Pci->Mask | LBAR_EN;
+
+ // If Memory LBAR, set MEM_IO
+ if (!(Pci->Flag & IO_BAR)) {
+ Descr->MsrData[1] |= MEM_IO;
+ } else {
+ Descr->MsrData[1] &= 0x0000FFFF;
+ Descr->MsrData[0] &= 0x0000FFFF;
+ }
+ return;
+
+ case MPCI_RCONF:
+ Descr->MsrData[1] = Pci->Value;
+
+ // If I/O BAR, set SPACE bit & shift BASE & TOP
+ if (Pci->Flag & IO_BAR) {
+ Descr->MsrData[0] <<= 12; // Move BASE to MSR[31:14]
+ Descr->MsrData[1] += ~(Pci->Mask | 3);
+ Descr->MsrData[1] <<= 12; // Move TOP to MSR[63:46]
+ Descr->MsrData[1] |= 1; // Set SPACE bit
+ } else {
+ Descr->MsrData[1] += ~Pci->Mask & 0xFFFFF000;
+ }
+ Descr->MsrData[0] |= 1; // Enable region
+ return;
+
+ case EPCI:
+ return;
+
+ case GX2_RCONF:
+ // Mark region non-cacheable and write-combined
+ Descr->MsrData[0] |= REGION_CD | REGION_EN;
+ Descr->MsrData[1] = Pci->Value + ~Pci->Mask & 0xFFFFF000;
+
+ if (Pci->Flag & MMIO_BAR) {
+ // Memory-mapped I/O must be write-serialized to avoid deadlocks
+ // They are also marked write-burstable
+ // Descr->MsrData[0] |= REGION_WS | REGION_WT;
+ }
+ if (Pci->Flag & MEM_BAR) {
+ // Mark frame buffers write-combined
+ Descr->MsrData[0] |= REGION_WC;
+ }
+ return;
+
+ case IOD_SC:
+ PMask = Descr->Range;
+ Descr->MsrData[0] = Compute_IOD_SC(&PCI_Value, &(USHORT)PMask, 1);
+ break;
+
+ case IOD_BM:
+ PMask = ~(Descr->Range-1) | 0xF0000;
+ PBase = PCI_Value & PMask;
+ PCI_Value += Descr->Range;
+ break;
+
+ case P2D_BMK:
+ case P2D_BMO:
+ case P2D_BM:
+ PMask = Pci->Mask >> 12;
+ PBase = Pci->Value >> 12;
+ break;
+
+ case P2D_RO:
+ // Fixup for VG alias bug
+ if (Descr->Physical) {
+ POffset = (~Pci->Value + 1) >> 12;
+ }
+ case P2D_R:
+ PMask = Pci->Value >> 12;
+ PBase = PMask + ((Descr->Range-1) >> 12);
+ break;
+
+ // These descriptor types are not used for PCI BARs
+ case P2D_SCO:
+ case P2D_SC:
+ default:
+ Log_Error("Compute_Msr_Value() was called with an invalid descriptor type: 0x%0x", Descr->Type);
+ return;
+
+ } // end switch()
+
+ if (Descr->Type != IOD_SC) {
+ if (Pci->Flag & MEM_BAR) {
+ POffset = (Descr->Physical - Pci->Value) >> 12;
+ }
+ // Assemble fields into MSR value
+ MergeFields(Descr->MsrData, PMask, PBase, POffset);
+ }
+
+ // Set PID field
+ Descr->MsrData[1] |= (ULONG)Descr->Port << 29;
+
+ // Set Bizarro bit, if necessary
+ if (Pci->Flag & USE_BMK) {
+ Descr->MsrData[1] |= BIZARRO;
+ }
+}
+
+
+
+//***********************************************************************
+// Updates all descriptors/LBARs/RCONF associated with a PCI BAR
+//***********************************************************************
+void pascal Update_BAR(register PCI_HEADER_ENTRY * Pci, UCHAR Enable)
+{ register DESCRIPTOR * Descr;
+ UCHAR Link;
+
+ PCI_Value = Pci->Value;
+ Link = Pci->Link;
+
+
+ // For each linked item, update the associated MSR
+ while (Link) {
+
+ Descr = &MSRs[Link];
+
+ // Get link to next MSR
+ Link = Descr->Link;
+
+ // Section 3.2.2 of PCI Spec 2.1: A BAR of zero is not a valid address.
+ // If the BAR value is zero, the corresponding MSR will be disabled.
+ if (Enable && Pci->Value != 0) {
+
+ // Don't update MSRs if querying resource requirements
+ if (Pci->Value == Pci->Mask) {
+ continue;
+ }
+
+ // BAR is being enabled
+ Compute_Msr_Value(Descr, Pci);
+
+ } else {
+
+ // Graphics device ignores disabling Command[1] (Issue 118.181)
+ if (Class == 0x0300) {
+ if (!(Pci->Flag & IO_BAR)) {
+ continue;
+ }
+ }
+
+ // BAR is being disabled
+ Read_MSR(Descr->MsrAddr, Descr->MsrData);
+
+ switch (Descr->Type) {
+
+ case USB_LBAR:
+ Descr->MsrData[1] &= ~2;
+ break;
+
+ case MDD_LBAR:
+ Descr->MsrData[1] &= ~LBAR_EN;
+ break;
+
+ case EPCI:
+ break;
+
+ case GX2_RCONF:
+ Descr->MsrData[0] &= ~REGION_EN;
+ break;
+
+ case MPCI_RCONF:
+ Descr->MsrData[0] &= ~1;
+ break;
+
+ case IOD_SC:
+ Descr->MsrData[0] &= ~(WEN | REN);
+ break;
+
+ default:
+ Get_Descriptor_Default(Descr->Type, Descr->MsrData);
+ break;
+ }
+ }
+
+ // Write the MSR
+ Write_MSR(Descr->MsrAddr, Descr->MsrData);
+
+ }
+}
+
+
+
+//***********************************************************************
+// Parses a MBD_MSR_ERROR & returns the Status register equivalent.
+// NOTE:
+// PERR# is not implemented, so MASTER_PARITY_ERROR always reads 0.
+//***********************************************************************
+ULONG pascal Get_Device_Status(PCI_HEADER_ENTRY * Pci)
+{ ULONG MsrAddr, MsrData, Status=0;
+
+ // Read MBD_MSR_ERROR
+ if (MsrAddr = GetMSR()) {
+ (USHORT)MsrAddr = MBD_MSR_ERROR;
+
+ MsrData = Read_MSR_LO(MsrAddr);
+
+ if (MsrData & (BME | TASE))
+ Status |= SIGNALED_TARGET_ABORT; // Status[11]
+
+ if (MsrData & TARE)
+ Status |= RECEIVED_TARGET_ABORT; // Status[12]
+
+ if (MsrData & MARE)
+ Status |= RECEIVED_MASTER_ABORT; // Status[13]
+
+ if (MsrData & SYSE)
+ Status |= SIGNALED_SYSTEM_ERROR; // Status[14]
+
+ if (MsrData & PARE)
+ Status |= DETECTED_PARITY_ERROR; // Status[15]
+ }
+ return Status;
+}
+
+
+
+//***********************************************************************
+// Clears error(s) pending on a device according to the Status mask
+//***********************************************************************
+void pascal Clear_MBus_Error(PCI_HEADER_ENTRY * Pci, ULONG Status)
+{ ULONG MsrAddr, MsrData;
+
+ // Read MBD_MSR_ERROR
+ if (MsrAddr = GetMSR()) {
+
+ (USHORT)MsrAddr = MBD_MSR_ERROR;
+
+ MsrData = Read_MSR_LO(MsrAddr);
+
+
+ // Status[15:11] write-1-to-clear.
+ // Only clear the MSR bits corresponding to Status[15:11]
+ MsrData &= ~(TASE | BME | TARE | MARE | SYSE | PARE);
+
+ if (Status & SIGNALED_TARGET_ABORT) // Status[11]
+ MsrData |= TASE | BME;
+
+ if (Status & RECEIVED_TARGET_ABORT) // Status[12]
+ MsrData |= TARE;
+
+ if (Status & RECEIVED_MASTER_ABORT) // Status[13]
+ MsrData |= MARE;
+
+ if (Status & SIGNALED_SYSTEM_ERROR) // Status[14]
+ MsrData |= SYSE;
+
+ if (Status & DETECTED_PARITY_ERROR) // Status[15]
+ MsrData |= PARE;
+
+ Write_MSR_LO(MsrAddr, MsrData);
+ }
+}
+
+
+
+
+
+//***********************************************************************
+// Enables/disables bus mastering on a GLIU device
+// Returns non-zero if no more bus-master MSRs for this device
+//***********************************************************************
+UCHAR pascal Update_BusMaster(PCI_HEADER_ENTRY * Pci, UCHAR EnableFlag)
+{ register DESCRIPTOR * Descr;
+ ULONG MsrAddr, MsrData[2];
+ USHORT Mask;
+ UCHAR Link, Shift;
+
+ switch (Class) {
+
+ // Filter out devices that don't affect PAE when Command[2] is changed
+ case 0x0600: // Bridge: Host
+ case 0x0601: // Bridge: ISA
+ case 0x0300: // Graphics
+ case 0x1010: // AES
+ return 1;
+
+ default:
+
+ Link = Pci->Link;
+
+ // For each linked item, update the associated MSR
+ while (Link) {
+
+ Descr = &MSRs[Link];
+
+ // Get link to next MSR
+ Link = Descr->Link;
+
+
+ MsrAddr = Descr->MsrAddr;
+ // Each USB 2.0 device on port 2 has its own bus-master control
+ if (Descr->Type == USB_LBAR) {
+ // Modify bus-master control
+ Read_MSR(MsrAddr, MsrData);
+ (UCHAR)MsrData[1] &= ~BUS_MASTER;
+ if (EnableFlag) {
+ (UCHAR)MsrData[1] |= BUS_MASTER;
+ }
+ Write_MSR(MsrAddr, MsrData);
+ Descr->MsrData[1] = MsrData[1];
+ return 1;
+ }
+ // Only change PAE in MBIU0 & MBIU2
+ MsrAddr &= ROUTING;
+ if (MsrAddr == Mbiu0 || MsrAddr == Mbiu2) {
+ (USHORT)MsrAddr = MBIU_PAE;
+
+ // Generate shift count from port #
+ Shift = 14; // Port 0 is in 8th position (bits 15:14)
+ if (Descr->Port) {
+ Shift = (Descr->Port-1) * 2;
+ }
+
+ // Generate mask for PAE MSR. 2 bits/field.
+ Mask = 3 << Shift;
+
+ // Modify bus-master control
+ Read_MSR(MsrAddr, MsrData);
+ (USHORT)MsrData[0] &= ~Mask;
+ if (EnableFlag) {
+ (USHORT)MsrData[0] |= Mask;
+ }
+ Write_MSR(MsrAddr, MsrData);
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+
+
+
+//***********************************************************************
+// Supports macro SYS_MBUS_DESCRIPTOR.
+// Returns the MSR address associated with a virtualized PCI resource.
+//***********************************************************************
+ULONG pascal Lookup_PCI(USHORT Address)
+{ register PCI_HEADER_ENTRY * Pci;
+ register DESCRIPTOR * Descr;
+ UCHAR LO_Address, Index=0;
+
+ LO_Address = (UCHAR)Address;
+
+ // Limit search to PCI BARs and OEM registers
+ if (((LO_Address >= BAR0) && (LO_Address <= BAR5)) || (LO_Address >= 0x40)) {
+
+ Pci = Get_Structure(Address);
+
+ if ((USHORT)Pci > UNIMPLEMENTED_REGISTER) {
+ if (Index = Pci->Link) {
+ // For OHCI devices, return embedded PCI address
+ if (Pci->Flag & EPCI_RW ) {
+ do {
+ Descr = &MSRs[Index];
+ if (Descr->Type == EPCI) {
+ break;
+ }
+ } while (Index = Descr->Link);
+ }
+ }
+ }
+ }
+
+ Descr = &MSRs[Index];
+ return Descr->MsrAddr;
+}
+
+//***********************************************************************
+// Supports macro SYS_IO_DESCRIPTOR.
+// Returns the MSR address associated with an I/O address.
+//***********************************************************************
+ULONG pascal Lookup_IO(USHORT Address)
+{ USHORT Range;
+ ULONG Addr;
+ UCHAR Index=0;
+
+ Range = 1;
+ Addr = (ULONG)Address;
+ Index = Find_Matching_IO_Descriptor(&Addr, &Range, 3);
+ return MSRs[Index].MsrAddr;
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.c
new file mode 100755
index 0000000..8a7cdf4
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.c
@@ -0,0 +1,367 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* Routines related to the MBus Diverse Device
+//******************************************************************************
+
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "GX2.H"
+#include "MDD.H"
+#include "PROTOS.H"
+#include "DESCR.H"
+#include "ACPI.H"
+#include "VPCI.H"
+#include "PCI.H"
+#include "ACPI.H"
+#include "CHIPSET.H"
+
+#define A20_EN (A20_P_EN | A20_K_EN)
+#define INIT_EN (INIT_K_EN | INIT_P_EN)
+
+
+// External function prototypes:
+void Init_MFGPT(void);
+UCHAR pascal ACPI_Trapping(USHORT);
+
+// Local function prototypes:
+void pascal Control_MDD_SMI(USHORT, ULONG);
+
+
+// Local variables:
+ULONG MDD_Base;
+
+// External variables:
+extern PCI_HEADER_ENTRY ISA_Hdr[];
+extern Hardware HardwareInfo;
+
+
+//***********************************************************************
+// Enables/disables KEL SMIs
+//***********************************************************************
+void pascal Control_KEL_SMI(USHORT EnableFlag)
+{
+ Control_MDD_SMI(EnableFlag, KEL_ASMI_EN);
+}
+
+//***********************************************************************
+// Enable/disable keyboard command snooping by KEL
+//***********************************************************************
+void pascal Control_KEL_Snoop(USHORT EnableFlag)
+{ ULONG MsrAddr, MsrData;
+
+ MsrAddr = MDD_Base;
+ (USHORT)MsrAddr = MSR_KEL_CNTRL;
+ MsrData = Read_MSR_LO(MsrAddr);
+
+ if (EnableFlag) {
+ MsrData |= KEL_SNOOP;
+ } else {
+ MsrData &= ~KEL_SNOOP;
+ }
+ Write_MSR_LO(MsrAddr, MsrData);
+
+}
+
+//***********************************************************************
+// Initializes the MBus Diverse Device
+//***********************************************************************
+void Init_MDD(void)
+{ ULONG MsrAddr;
+ USHORT ACPI_Bar;
+ UCHAR i;
+
+
+ // Find address of MBus Diverse Device
+ MsrAddr = MDD_Base = Find_MBus_ID(ID_MDD, 1) & 0xFFFF0000;
+
+ //*********************************************
+ // Record MDD's LBARs in MSRs[]
+ //*********************************************
+ for (i = MSR_LBAR_IRQ; i <= MSR_LBAR_FLSH3; i++) {
+
+ (UCHAR)MsrAddr = i;
+
+ if (Init_Descr(MDD_LBAR, MsrAddr)) {
+ break;
+ }
+ }
+
+ // Clear PM1_STS
+ (UCHAR)MsrAddr = ISA_Hdr[BAR5/4].LBar;
+ ACPI_Bar = (USHORT)Read_MSR_LO(MsrAddr);
+ out_16(ACPI_Bar, in_16(ACPI_Bar));
+
+
+ // Initialize KEL
+
+ // Enable keyboard snooping by KEL
+ Control_KEL_Snoop(1);
+
+ // Enable SMIs from:
+ // - A20 & Init (keyboard and port 92h)
+ // - KEL
+ // - Extended PIC Mapper
+ Control_MDD_SMI(1, A20_EN | INIT_EN | PIC_ASMI_EN | KEL_ASMI_EN);
+
+
+ // Initialize the MFGPT
+ Init_MFGPT();
+
+ // Clear any pending PIC events
+ (USHORT)MsrAddr = MBD_MSR_SMI;
+ Write_MSR_HI(MsrAddr, PIC_ASMI_EN);
+
+}
+
+
+
+
+//***********************************************************************
+// Implements CS5536's F0 Special Cycles.
+// Linked to MDD's MSR_LEG_IO[31].
+//
+// When set, a Shutdown special cycle causes a reset. When the Special
+// Cycles bit is cleared, a Shutdown special cycle is ignored. Before
+// updating MSR_LEG_IO, VSA will check MSR_ERR[15] and MSR_SMI[1]. If
+// either of these MSR bits are set, then no action is taken. It will
+// be assumed that a debugger is in use and VSA will not interfere.
+//***********************************************************************
+void pascal Update_Special_Cycles(USHORT EnableFlag)
+{ ULONG MSR_Addr, MSR_Data;
+
+
+ // If either MSR_ERR[15] and MSR_SMI[1] is set, then bail.
+ if (Read_MSR_LO(MDD_Base + MBD_MSR_SMI) & 2) {
+ return;
+ }
+ if (Read_MSR_LO(MDD_Base + MBD_MSR_ERROR) & 0x8000) {
+ return;
+ }
+
+ // Link MSR_LEG_IO[RESET_SHUT_EN] to COMMAND[3]
+ MSR_Addr = MDD_Base + MSR_LEG_IO;
+ MSR_Data = Read_MSR_LO(MSR_Addr);
+
+ if (EnableFlag) {
+ MSR_Data |= RESET_SHUT_EN;
+ } else {
+ MSR_Data &= ~RESET_SHUT_EN;
+ }
+
+ Write_MSR_LO(MSR_Addr, MSR_Data);
+}
+
+
+//***********************************************************************
+// Enable/disable of MDD ASMI(s)
+//***********************************************************************
+void pascal Control_MDD_SMI(USHORT EnableFlag, ULONG EnableMask)
+{ ULONG MsrAddr, MsrData;
+
+ MsrAddr = MDD_Base;
+ (USHORT)MsrAddr = MBD_MSR_SMI;
+
+ MsrData = Read_MSR_LO(MsrAddr);
+ if (EnableFlag) {
+ MsrData |= EnableMask;
+ } else {
+ MsrData &= ~EnableMask;
+ }
+ Write_MSR_LO(MsrAddr, MsrData);
+}
+
+
+//***********************************************************************
+// Clears the ACPI Status register
+// This routine fills in MsgPacket[0] = ACPI GPE0_STS
+// and MsgPacket[1] bits[15:0] = ACPI PM1_STS
+//***********************************************************************
+USHORT Get_ACPI_Status(ULONG *msgp)
+{ USHORT ACPI_Bar, PM1_Status;
+ ULONG GPE_Status;
+ UCHAR Flag;
+
+ // Disable ACPI trapping
+ Flag = ACPI_Trapping(0);
+
+ // Get ACPI Status
+ ACPI_Bar = ISA_Hdr[BAR5/4].Value_LO;
+
+ (UCHAR)ACPI_Bar = GPE0_STS_OFS;
+ GPE_Status = in_32(ACPI_Bar);
+
+ // Don't clear PIC status
+ GPE_Status &= ~1;
+
+
+ msgp[1] = GPE_Status;
+
+
+ (UCHAR)ACPI_Bar = PM1_STS_OFS;
+ PM1_Status = in_16(ACPI_Bar);
+
+
+ // Enable ACPI trapping
+ if (Flag) {
+ ACPI_Trapping(1);
+ }
+
+ msgp[2] = (ULONG)PM1_Status;
+
+ return (PM1_Status || GPE_Status);
+}
+
+//***********************************************************************
+// Enable PM logic
+//***********************************************************************
+void Enable_PME_Event(UCHAR EnableFlag, UCHAR Pm1Bit, UCHAR PmeBit, USHORT Attributes)
+{ ULONG Gpe, Pm1, bmGPE0;
+ USHORT ACPI_Bar, bmPM1;
+ UCHAR Flag;
+ static UCHAR pme_instance = 0;
+ static UCHAR PM1_Instance[11] = {0,0,0,0,0,0,0,0,0,0,0};
+ static UCHAR PME_Instance[8] = {0,0,0,0,0,0,0,0};
+ static ULONG GPE0_Masks[] = { // Maps PME # to GPE0 bits
+ 0x00010000,
+ 0x00020000,
+ 0x00040000,
+ 0x00080000,
+ 0x00100000,
+ 0x00200000,
+ 0x40000000,
+ 0x80000000,
+ };
+
+ bmPM1 = 0;
+ bmGPE0 = 0L;
+ if (Attributes & PM1) {
+ bmPM1 = 1 << Pm1Bit;
+
+ if (EnableFlag) {
+ PM1_Instance[Pm1Bit]++;
+ } else {
+ if (PM1_Instance[Pm1Bit]) {
+ // If there are still registrations for this PM1 bit...
+ if (--PM1_Instance[Pm1Bit]) {
+ // then don't turn disable it
+ return;
+ }
+ } else {
+ // Error:
+ return;
+ }
+ }
+ }
+ if (Attributes & GPE) {
+ bmGPE0 = GPE0_Masks[PmeBit];
+ if (EnableFlag) {
+ PME_Instance[PmeBit]++;
+ } else {
+ if (PME_Instance[PmeBit]) {
+ // If there are still registrations for this GEP0 bit...
+ if (--PME_Instance[PmeBit]) {
+ // then don't turn disable it
+ return;
+ }
+ } else {
+ // Error:
+ return;
+ }
+ }
+ }
+
+
+ if (!(Attributes & NO_ASMI)) {
+ // Keep a count of PME events.
+ // Once all have been de-registered, turn off PM_ASMI bit.
+ if (EnableFlag) {
+ if (Attributes & PME) {
+ pme_instance++;
+ }
+ // Enable ASMIs from Power Management logic
+ Control_MDD_SMI(EnableFlag, PM_ASMI_EN);
+ } else {
+ if (Attributes & PME) {
+ if (pme_instance != 0) {
+ if (--pme_instance == 0) {
+ // Disable ASMIs from Power Management logic
+ Control_MDD_SMI(0, PM_ASMI_EN);
+ }
+ }
+ }
+ }
+ }
+
+ // See if we want to enable the approriate bits in PM1_EN and GPE0_EN
+ // if set to NO_ENALE we don't enable (Used by ACPI as the OS controls)
+ if (!(Attributes & NO_ENABLE)) {
+ // Disable ACPI trapping
+ Flag = ACPI_Trapping(0);
+
+ // Get ACPI base address
+ ACPI_Bar = ISA_Hdr[BAR5/4].Value_LO;
+
+ if (bmPM1) {
+ // Must do 32-bit I/O to avoid shadow register bug (IAeng00003062)
+ (UCHAR)ACPI_Bar = 0x00;
+ Pm1 = in_32(ACPI_Bar);
+ if (EnableFlag) {
+ Pm1 |= (ULONG)bmPM1 << 16;
+ } else {
+ Pm1 &= ~((ULONG)bmPM1 << 16);
+ }
+ out_32(ACPI_Bar, Pm1);
+
+ // Serialize the previous I/O write
+ in_16(ACPI_Bar);
+
+ // Clear spurious status
+ (UCHAR)ACPI_Bar = PM1_STS_OFS;
+ out_32(ACPI_Bar, (ULONG)Pm1);
+ }
+
+ if (bmGPE0) {
+ (UCHAR)ACPI_Bar = GPE0_EN_OFS;
+ Gpe = in_32(ACPI_Bar);
+ if (EnableFlag) {
+ Gpe |= bmGPE0;
+ } else {
+ Gpe &= ~bmGPE0;
+ }
+ out_32(ACPI_Bar, Gpe);
+ // Serialize the previous I/O write
+ in_32(ACPI_Bar);
+
+ // Clear spurious status
+ (UCHAR)ACPI_Bar = GPE0_STS_OFS;
+ out_32(ACPI_Bar, Gpe);
+ }
+
+ // Serialize the previous I/O write
+ in_32(ACPI_Bar);
+
+ // Re-enable ACPI trapping
+ if (Flag) {
+ ACPI_Trapping(1);
+ }
+ }
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.h b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.h
new file mode 100755
index 0000000..9c7df22
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mdd.h
@@ -0,0 +1,226 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+// ATA
+#define MSR_LBAR_ATA 0x0008
+
+
+// Diverse Integration Logic
+
+#define MSR_MAST_CONF 0x0001
+ #define NON_COH_RD (1L << 12)
+ #define NON_COH_WR (1L << 13)
+
+#define LBAR_EN (1 << 0)
+#define NOR_NAND (1 << 1)
+#define MEM_IO (1 << 2)
+#define LBAR_IO_MASK 0x0001FFF0
+#define LBAR_MEM_MASK 0xFFFFF000
+
+
+#define MSR_LBAR_IRQ 0x0008
+#define MSR_LBAR_KEL1 0x0009
+#define MSR_LBAR_KEL2 0x000A
+#define MSR_LBAR_SMB 0x000B
+
+#define MSR_LBAR_GPIO 0x000C
+ #define GPIO_LOW_BANK_SELECT 0x00
+ #define GPIO_HIGH_BANK_SELECT 0x80
+ #define GPIO_OUTPUT_VALUE 0x00
+ #define GPIO_OUTPUT_ENABLE 0x04
+ #define GPIO_OUTPUT_OPENDRAIN 0x08
+ #define GPIO_OUTPUT_INVERT 0x0C
+ #define GPIO_OUT_AUX1_SELECT 0x10
+ #define GPIO_OUT_AUX2_SELECT 0x14
+ #define GPIO_PULLUP_ENABLE 0x18
+ #define GPIO_PULLDOWN_ENABLE 0x1C
+ #define GPIO_INPUT_ENABLE 0x20
+ #define GPIO_INPUT_INVERT 0x24
+ #define GPIO_IN_FILTER_ENABLE 0x28
+ #define GPIO_IN_EVENTCOUNT 0x2C
+ #define GPIO_READ_BACK 0x30
+ #define GPIO_IN_AUX1_SELECT 0x34
+ #define GPIO_EVENTS_ENABLE 0x38
+ #define GPIO_LOCK_ENABLE 0x3C
+ #define LKOV (1 < 0)
+ #define LKOE (1 < 1)
+ #define LKOD (1 < 2)
+ #define LKOI (1 < 3)
+ #define LKA1 (1 < 4)
+ #define LKA2 (1 < 5)
+ #define LKPU (1 < 6)
+ #define LKPD (1 < 7)
+ #define LKIE (1 < 8)
+ #define LKII (1 < 9)
+ #define LKFE (1 < 10)
+ #define LKEE (1 < 11)
+ #define LKIA (1 < 12)
+ #define LKIP (1 < 13)
+ #define LKPE (1 < 14)
+ #define LKNE (1 < 15)
+ #define GPIO_POSEDGE_ENABLE 0x40
+ #define GPIO_NEGEDGE_ENABLE 0x44
+ #define GPIO_POSEDGE_STATUS 0x48
+ #define GPIO_NEGEDGE_STATUS 0x4C
+
+ // GPIO IRQ Mapper
+ #define GPIO_MAPPER_X 0xE0
+ #define GPIO_MAPPER_Y 0xE4
+ #define GPIO_MAPPER_Z 0xE8
+ #define GPIO_MAPPER_W 0xEC
+
+ // Digital Filter
+ #define GPIO_FILTER_AMOUNT 0x50
+ #define GPIO_FILTER_COUNT 0x52
+ #define GPIO_EVENT_COUNT 0x54
+ #define GPIO_EVENT_COMPARE 0x56
+
+ #define GPIO6_FILTER_AMOUNT 0xD0
+ #define GPIO7_FILTER_AMOUNT 0xD8
+
+ #define GPIO_FILTER_SELECT0 0xF0
+ #define GPIO_FILTER_SELECT1 0xF1
+ #define GPIO_FILTER_SELECT2 0xF2
+ #define GPIO_FILTER_SELECT3 0xF3
+ #define GPIO_FILTER_SELECT4 0xF4
+ #define GPIO_FILTER_SELECT5 0xF5
+ #define GPIO_FILTER_SELECT6 0xF6
+ #define GPIO_FILTER_SELECT7 0xF7
+
+
+
+
+#define MSR_LBAR_MFGPT 0x000D
+ // I/O offsets relative to MFGPT LBAR
+ #define MFGPT_CMP1 0x00
+ #define MFGPT_CMP2 0x02
+ #define MFGPT_COUNTER 0x04
+ #define MFGPT_SETUP 0x06
+
+ #define MFGPT_OFFSET 8
+
+#define MSR_LBAR_ACPI 0x000E
+#define MSR_LBAR_PMS 0x000F
+#define MSR_LBAR_FLSH0 0x0010
+#define MSR_LBAR_FLSH1 0x0011
+#define MSR_LBAR_FLSH2 0x0012
+#define MSR_LBAR_FLSH3 0x0013
+#define MSR_LEG_IO 0x0014
+ #define RESET_SHUT_EN (0x80000000L)
+ #define UART1_SHIFT (16)
+ #define UART2_SHIFT (20)
+ #define UART_MASK (0x07)
+ #define UART_IO_MASK (0x03)
+ #define UART_EN (0x04)
+#define MSR_PIN_OPTS 0x0015
+ #define PIN_OPT_IDE (1 << 0)
+#define MSR_SOFT_IRQ 0x0016
+#define MSR_SOFT_RESET 0x0017
+#define MSR_AC_DMA 0x0019
+
+#define MSR_KEL_CNTRL 0x001F
+ #define KEL_SNOOP (1 << 0)
+ #define KEL_EER (1 << 1)
+ #define KEL_PRTA_EN (1 << 4)
+
+
+// IRQ Mask & Mapper (from MDD Specification)
+#define MSR_IRQM_YLOW 0x0020
+#define MSR_IRQM_YHIGH 0x0021
+#define MSR_IRQM_ZLOW 0x0022
+#define MSR_IRQM_ZHIGH 0x0023
+#define MSR_IRQM_PRIM 0x0024
+#define MSR_IRQM_LPC 0x0025
+#define MSR_IRQM_LXIRR 0x0026
+#define MSR_IRQM_HXIRR 0x0027
+#define MSR_MFGPT_IRQ 0x0028
+#define MSR_MFGPT_NR 0x0029
+#define MSR_MFGPT_CLR_SETUP 0x002B
+
+#define MSR_FLOP_S3F2 0x0030
+#define MSR_FLOP_S3F7 0x0031
+#define MSR_FLOP_S372 0x0032
+#define MSR_FLOP_S377 0x0033
+#define MSR_PIC_SHADOW 0x0034
+#define MSR_PIT_SHADOW 0x0036
+
+// UART's
+#define MSR_UART1_MOD 0x0038
+#define MSR_UART1_DONG 0x0039
+#define MSR_UART1_CONF 0x003A
+ #define UART_SOFT_RESET (0x01L)
+ #define UART_DEVEN (0x02L)
+ #define UART_FREEZE (0x04L)
+ #define UART_TEST (0x08L)
+ #define UART_EXT_BANKS (0x10L)
+#define MSR_UART2_MOD 0x003C
+#define MSR_UART2_DONG 0x003D
+#define MSR_UART2_CONF 0x003E
+
+#define MSR_DMA_MAP 0x0040
+#define MSR_DMA_SHAD0 0x0041
+#define MSR_DMA_SHAD1 0x0042
+#define MSR_DMA_SHAD2 0x0043
+#define MSR_DMA_SHAD3 0x0044
+#define MSR_DMA_SHAD4 0x0045
+#define MSR_DMA_SHAD5 0x0046
+#define MSR_DMA_SHAD6 0x0047
+#define MSR_DMA_SHAD7 0x0048
+#define MSR_DMA_MSK_SHAD 0x0049
+
+// LPC
+#define MSR_LPC_SIRQ 0x004E
+
+
+
+// MSR_SMI
+#define HLT_ASMI_EN (1L << 0)
+#define SHUTDOWN_ASMI_EN (1L << 1)
+#define KEL_ASMI_EN (1L << 2)
+#define PIC_ASMI_EN (1L << 3)
+#define PM_ASMI_EN (1L << 4)
+#define INIT_K_EN (1L << 5)
+#define A20_P_EN (1L << 6)
+#define INIT_P_EN (1L << 7)
+#define UART1_SSMI_EN (1L << 8)
+#define UART2_SSMI_EN (1L << 9)
+#define RESERVED_EN (1L << 10)
+#define LPC_SSMI_EN (1L << 11)
+#define DMA_SSMI_EN (1L << 12)
+#define A20_K_EN (1L << 13)
+#define PM2_CNT_SSMI_EN (1L << 14)
+#define PM1_CNT_SSMI_EN (1L << 15)
+
+#define HLT_ASMI_STAT (1L << 32)
+#define SHUTDOWN_ASMI_STAT (1L << 33)
+#define KEL_ASMI_STAT (1L << 34)
+#define PIC_ASMI_STAT (1L << 35)
+#define PM_ASMI_STAT (1L << 36)
+#define INIT_K_STAT (1L << 37)
+#define A20_P_STAT (1L << 38)
+#define INIT_P_STAT (1L << 39)
+#define UART1_SSMI_STAT (1L << 40)
+#define UART2_SSMI_STAT (1L << 41)
+#define RESERVED_STAT (1L << 42)
+#define LPC_SSMI_STAT (1L << 43)
+#define DMA_SSMI_STAT (1L << 44)
+#define A20_K_STAT (1L << 45)
+#define PM2_CNT_SSMI_STAT (1L << 46)
+#define PM1_CNT_SSMI_STAT (1L << 47)
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/message.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/message.asm
new file mode 100755
index 0000000..10fe571
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/message.asm
@@ -0,0 +1,393 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* Implements message handling routines
+
+include SYSMGR.INC
+include VSA2.INC
+
+
+
+.model tiny,c
+.586p
+.CODE
+
+externdef SysMgr_VSM: dword
+externdef MsgPacket: dword
+externdef VSM_ListHead: dword
+externdef Current_VSM: dword
+
+externdef Events: EVENT_ENTRY
+externdef Sys_Exit: proc
+externdef pascal Schedule_VSM: proc
+
+
+
+;***********************************************************************
+; This routine is called from the System Manager to enter a message
+; packet into a VSM's message queue.
+;
+; Input:
+; To_VSM = Flat ptr to VSM to which message is to be sent
+; MsgCode = Priority::Message
+; From_VSM = value to be put in Async_VSM field
+; MsgPacket contains the message parameters
+;***********************************************************************
+Send_Message proc pascal uses di si \
+ From_VSM: dword, \
+ To_VSM: dword, \
+ MsgCode: dword
+
+ mov edi, [To_VSM]
+ cmp edi, [SysMgr_VSM] ; Don't send messages to SysMgr
+ je short Exit
+
+ mov eax, [MsgCode]
+ lea si, [MsgPacket]
+ mov ebx, [From_VSM]
+ call Insert_Msg
+Exit: ret
+
+Send_Message endp
+
+
+
+
+
+
+
+
+;***********************************************************************
+; This routine enters a message packet into a VSM's message queue.
+;
+; Input:
+; EAX = Priority::Message
+; EBX = From_VSM
+; EDI = To_VSM
+; SI = Ptr to message packet
+;***********************************************************************
+Insert_Msg proc
+
+ cld
+
+ push ebx ; Save From_VSM
+
+ ; Get ptr to the head of the message queue
+ movzx ebx, fs:(VSM_Header PTR [edi]).SysStuff.Qhead
+
+ ; Compute ptr to the next available message queue entry
+ lea dx, [bx+sizeof(Message)]
+ cmp dx, fs:(VSM_Header PTR [edi]).SysStuff.EndMsgQ
+ jb short Check_Q_Overflow
+ mov dx, OFFSET VSM_Header.SysStuff.MsgQueue
+Check_Q_Overflow:
+
+ ; Is Qhead == Qtail ?
+ cmp dx, fs:(VSM_Header PTR [edi]).SysStuff.Qtail
+ jne short UpdateQueueHead
+
+ ; Yes, then message queue has overflowed
+ mov [si+8], eax ; Store previous message into Param2
+ mov ax, MSG_QUEUE_OVERFLOW ; Replace previous message
+ mov dx, bx ; Qhead = old Qhead
+UpdateQueueHead:
+ mov fs:(VSM_Header PTR [edi]).SysStuff.Qhead, dx
+
+ pop edx ; From_VSM
+ push edi ; Parameter to Schedule_VSM() below
+
+ ; Store the message into the VSM's message queue.
+ ; NOTE: This code is dependent on "#typedef Message"
+ add edi, ebx
+ stosd [edi] ; Priority::Message
+
+ mov eax, edx ; From_VSM
+ stosd [edi]
+
+REPEAT MAX_MSG_PARAM
+ lodsd ; Copy parameters to message queue
+ stosd [edi]
+ENDM
+
+
+
+ ; Sort messages by Priority
+if SUPPORT_PRIORITY
+
+ pop ebx ; To_VSM
+ push ebx
+
+ push fs:(VSM_Header PTR [ebx]).SysStuff.Qhead
+BubbleSort:
+
+ ; Get ptr to latest queue entry
+ movzx esi, fs:(VSM_Header PTR [ebx]).SysStuff.Qhead
+ sub esi, sizeof(Message)
+ cmp si, OFFSET VSM_Header.SysStuff.MsgQueue
+ jae short @f
+ mov si, fs:(VSM_Header PTR [ebx]).SysStuff.EndMsgQ
+ sub si, sizeof(Message)
+@@:
+ cmp si, fs:(VSM_Header PTR [ebx]).SysStuff.Qtail
+ je Bail
+
+ ; Get ptr to previous queue entry
+ lea edi, [esi-sizeof(Message)]
+ cmp di, OFFSET VSM_Header.SysStuff.MsgQueue
+ jae short @f
+ mov di, fs:(VSM_Header PTR [ebx]).SysStuff.EndMsgQ
+ sub di, sizeof(Message)
+@@:
+
+ mov fs:(VSM_Header PTR [ebx]).SysStuff.Qhead, di
+
+ ; Add VSM base to ptrs
+ add edi, ebx
+ add esi, ebx
+
+ ; Compare their priorities
+ mov ax, fs:(Message PTR [esi]).Priority
+ cmp ax, fs:(Message PTR [edi]).Priority
+ jbe short Bail
+
+
+
+ ; Swap the entries in the message queue
+ mov cx, sizeof(Message)/4 ; Assumes entry is multiple of dword
+Interchange:
+ mov eax, fs:[edi]
+ xchg fs:[esi], eax
+ stosd [edi]
+ add esi, 4
+ loop Interchange
+
+ jmp BubbleSort
+
+
+Bail:
+ pop fs:(VSM_Header PTR [ebx]).SysStuff.Qhead
+
+endif
+
+
+ ; Schedule the VSM to execute
+ pop eax
+ cmp eax, [SysMgr_VSM]
+ je short Exit
+ push eax
+ call Schedule_VSM
+Exit:
+ ret
+
+
+Insert_Msg endp
+
+
+
+
+
+
+
+
+
+
+;************************************************************************
+;
+; Sends a message to each VSM of type VSM_Type (or all if VSM_ANY).
+; Called from HANDLERS.C
+;
+;************************************************************************
+Broadcast_Message proc pascal uses si di \
+ MsgCode: word, \
+ VSM_Type: word, \
+ From_VSM: dword
+
+ mov edi, [VSM_ListHead] ; Get ptr to list of VSMs
+VSM_Loop:
+ or edi, edi ; End of VSM list ?
+ jz Exit_Broadcast
+
+ mov dx, [VSM_Type]
+ mov ah, fs:(VSM_Header PTR [edi]).VSM_Type
+
+ cmp dl, VSM_ANY ; Schedule all VSMs ?
+ je Schedule_It
+
+ test dh, (VSM_ALL_EXCEPT SHR 8)
+ jz CheckType
+
+ cmp dl, ah ; Skip the one that matches
+ je Skip_VSM
+ jmp Schedule_It
+
+CheckType:
+ cmp dl, ah ; Is it the correct VSM ?
+ jne Skip_VSM
+
+Schedule_It:
+
+ cmp edi, [From_VSM] ; Is it the requesting VSM ?
+ je Skip_VSM ; Yes, don't send to sender
+
+ push edi
+
+ movzx eax, [MsgCode] ; Send the message
+ xor ebx, ebx
+ lea si, [MsgPacket]
+
+; EAX = Priority::Message
+; EBX = 00000000h (a broadcast is not a synchronous event)
+; SI = Ptr to message packet
+; EDI = Ptr to VSM header where message is to be sent
+ call Insert_Msg
+ pop edi
+
+
+Skip_VSM:
+ mov edi, fs:(VSM_Header PTR [edi]).SysStuff.Flink
+ jmp VSM_Loop
+
+Exit_Broadcast:
+ ret
+
+Broadcast_Message endp
+
+
+
+;************************************************************************
+; Broadcasts a message to one or more VSMs.
+;
+; Input:
+; EBX = message code (16 MSBs)
+; BH = Flags
+; BL = VSM_Type
+; ECX = Param1
+; ESI = Param2
+; EDI = Param3
+;************************************************************************
+Sys_Broadcast proc
+
+ mov dx, bx ; Put VSM_Type::Flags into DX
+ shr ebx, 16 ; Put message into BX
+
+ mov eax, esi
+ lea si, [MsgPacket]
+ mov [si+0], ecx
+ mov [si+4], eax
+ mov [si+8], edi
+
+ ; Re-schedule the broadcasting VSM
+ ; RunFlag will be changed from RUN_FLAG_ACTIVE to RUN_FLAG_READY
+ mov edi, [Current_VSM]
+ push edi
+ call Schedule_VSM
+ ; If RunFlag == RUN_FLAG_READY, Insert_Msg() won't schedule it again
+ mov fs:(VSM_Header PTR [edi]).SysStuff.RunFlag, RUN_FLAG_BLOCKED
+
+ ; Push parameters for call to Broadcast_Message()
+ push bx ; Message code
+ push dx ; VSM type
+ push edi ; From_VSM
+
+ ; Normally, the message is sent to the broadcasting VSM
+ ; after all VSMs have handled the broadcasted message.
+ ; There are two exceptions to this rule:
+ ; 1) VSM_NOT_SELF | <VSM type>
+ ; 2) VSM_ALL_EXCEPT | <self>
+ test dh, (VSM_NOT_SELF SHR 8)
+ jnz short Broadcast
+
+ test dh, (VSM_ALL_EXCEPT SHR 8)
+ jz short SendToSelf
+ cmp dl, fs:(VSM_Header PTR [edi]).VSM_Type
+ je short Broadcast
+
+SendToSelf:
+ ; Put callback address onto the scheduler stack
+ mov eax, OFFSET BroadcastCallback
+ push eax
+ call Schedule_VSM
+
+ mov ax, BROADCAST_PRIORITY ; EAX = Priority::Message
+ shl eax, 16
+ mov ax, bx
+
+ mov edi, [SysMgr_VSM] ; EDI = To_VSM
+ mov ebx, [Current_VSM] ; EBX = From_VSM
+ call Insert_Msg
+
+Broadcast:
+ call Broadcast_Message
+
+ jmp Sys_Exit ; Exit w/o scheduling current VSM
+
+Sys_Broadcast endp
+
+
+;************************************************************************
+; Control comes here when all VSMs have processed the broadcasted message.
+; Copies the broadcasted message from SysMgr's message queue to the
+; broadcasting VSM's message queue.
+;************************************************************************
+BroadcastCallback proc
+ ASSUME DI: PTR VSM_Header
+ ASSUME BX: PTR Message
+
+ ; Point BX to parameters in SysMgr's message queue head
+ xor di, di
+ mov bx, [di].SysStuff.Qhead
+ sub bx, sizeof(Message)
+ cmp bx, OFFSET VSM_Header.SysStuff.MsgQueue
+ jb short BadMsgStack
+ mov [di].SysStuff.Qhead, bx
+
+ mov eax, dword ptr [bx].Msg ; Get Priority::Message
+ mov edi, [bx].From_VSM ; To_VSM (the VSM it was originally from)
+
+ lea si, [bx].Param
+ xor ebx, ebx ; From_VSM (asynchronous)
+ call Insert_Msg
+BadMsgStack:
+ ret
+
+ ASSUME BX: NOTHING
+ ASSUME DI: NOTHING
+
+BroadcastCallback endp
+
+
+
+;***********************************************************************
+; Passes an event to the next VSM registered for this event
+; NOTE: This system call is now obsolete.
+;***********************************************************************
+Sys_PassEvent proc
+
+ jmp Sys_Exit ; Exit to VSM dispatcher
+
+Sys_PassEvent endp
+
+
+
+
+
+ END
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mfgpt.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mfgpt.c
new file mode 100755
index 0000000..27b3cdf
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/mfgpt.c
@@ -0,0 +1,500 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//*****************************************************************************
+//* This file contains code specific to CS5536 MFGPTs
+//*****************************************************************************
+
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "PROTOS.H"
+#include "MDD.H"
+#include "MAPPER.H"
+#include "TIMER.H"
+
+// External variables:
+extern ULONG MDD_Base;
+
+// Local variables:
+USHORT MFGPT_Base=0;
+ULONG MFGPT_LBAR[2];
+
+
+
+// NOTE: Timers that use the 32KHz clock interfere with LPC DMA (see PBZ 709)
+
+ // Clock Prescalar Period
+#define TIMER_SETUP (MFGPT_SCALE_1K | MFGPT_CMP1MODE | MFGPT_CLK_SEL) // 14 MHz 1024 71 us
+#define STDBY_SETUP (MFGPT_SCALE_32 | MFGPT_CMP1MODE) // 32 KHz 32 1 ms
+#define PWM_SETUP (MFGPT_SCALE_32 | MFGPT_CMP1GE) // 32 KHz 32 1 ms
+TIMERS TimerInfo[] = {
+// # Z Mapper Setup
+// Save for OS (Linux) use { 0, Z_IRQ_MFGPT_04, PWM_SETUP},
+ { 1, Z_IRQ_MFGPT_15, PWM_SETUP},
+ { 2, Z_IRQ_MFGPT_26, PWM_SETUP},
+ { 3, Z_IRQ_MFGPT_37, TIMER_SETUP},
+// Save for OS (Linux) use { 4, Z_IRQ_MFGPT_04, TIMER_SETUP},
+ { 5, Z_IRQ_MFGPT_15, TIMER_SETUP},
+ { 6, Z_IRQ_MFGPT_26, STDBY_SETUP},
+ { 7, Z_IRQ_MFGPT_37, PWM_SETUP},
+};
+#define NUM_MFGPTS (sizeof(TimerInfo)/sizeof(TIMERS)) // Number of MFGPTs available
+
+//************************************************************************************
+// Saves the MFGPT LBAR setting and enables the LBAR
+//************************************************************************************
+void Enable_MFGPT_LBAR()
+{ ULONG Tmp;
+ int i;
+
+ // Get MFGPT LBAR
+ Read_MSR(MDD_Base + MSR_LBAR_MFGPT, MFGPT_LBAR);
+
+ // Has the MFGPT base address changed?
+ if (MFGPT_Base != (USHORT)MFGPT_LBAR[0]) {
+ // Yes, record the new base address of MFGPT
+ MFGPT_Base = (USHORT)MFGPT_LBAR[0];
+
+ // Update the individual timer base addresses
+ for (i = 0; i < NUM_MFGPTS; i++) {
+ TimerInfo[i].TimerBase = MFGPT_Base + TimerInfo[i].Timer*MFGPT_OFFSET;
+ }
+ }
+
+ // Save the current LBAR enable
+ Tmp = MFGPT_LBAR[1];
+
+ // Enable the LBAR
+ MFGPT_LBAR[1] |= LBAR_EN;
+ Write_MSR(MDD_Base + MSR_LBAR_MFGPT, MFGPT_LBAR);
+ MFGPT_LBAR[1] = Tmp;
+
+}
+
+
+//************************************************************************************
+// Restores the MFGPT LBAR
+//************************************************************************************
+void Restore_MFGPT_LBAR()
+{
+ // Restore MFGPT LBAR
+ Write_MSR(MDD_Base + MSR_LBAR_MFGPT, MFGPT_LBAR);
+}
+
+
+//************************************************************************************
+// Checks for MFGPT events
+// Returns a mask of which timer(s) have expired
+//************************************************************************************
+USHORT CS5536_MFGPT_Handler(void)
+{ USHORT Setup, Status, Accum_Status=0, i;
+ register TIMERS * TimerPtr;
+
+ Enable_MFGPT_LBAR();
+
+ for (i = 0; i < NUM_MFGPTS; i++) {
+
+ TimerPtr = &TimerInfo[i];
+
+ // Get timer status
+ Setup = TimerPtr->TimerBase + MFGPT_SETUP;
+ Status = in_16(Setup);
+ if (Status & MFGPT_INITED) {
+ out_16(Setup, Status);
+ }
+
+ // Check if MFGPT is reserved for EVENT_PWM
+ if(TimerPtr->Setup == PWM_SETUP) {
+ continue;
+ }
+
+ // If timer is enabled and expired...
+ Status &= MFGPT_ENABLE | MFGPT_COMPARE1;
+ if (Status == (MFGPT_ENABLE | MFGPT_COMPARE1)) {
+ // disable the timer
+ out_16(Setup, Status & (~MFGPT_ENABLE));
+ // record timer event
+ Accum_Status |= TimerPtr->Mask;
+ }
+ }
+
+ // Restore the MFGPT LBAR
+ Restore_MFGPT_LBAR();
+
+ return Accum_Status;
+}
+
+//************************************************************************************
+// Initializes a single MFGPT
+//************************************************************************************
+void Init_Timer(TIMERS * TimerPtr)
+{ USHORT Setup, TimerKHz;
+ ULONG MicrosPerCount;
+
+ TimerPtr->TimerBase = MFGPT_Base + TimerPtr->Timer*MFGPT_OFFSET;
+
+ TimerPtr->Mask = 1 << TimerPtr->Timer;
+
+ Setup = TimerPtr->Setup;
+
+ // Compute microseconds / tick
+ MicrosPerCount = 1000L << (Setup & 0xF);
+ TimerKHz = 32;
+ if (Setup & MFGPT_CLK_SEL) {
+ TimerKHz = 14318;
+ }
+ TimerPtr->Period = (USHORT)(MicrosPerCount / TimerKHz);
+
+ // Initialize the timer
+ out_16(TimerPtr->TimerBase + MFGPT_SETUP, Setup);
+
+ // NOTE: Counter resets to 0 when Counter == Comparator2 register
+ out_32(TimerPtr->TimerBase + MFGPT_CMP1, 0xFFFFFFFF);
+
+}
+
+//***********************************************************************
+// Marks a MFGPT as available
+//***********************************************************************
+void pascal MarkTimerAvailable(USHORT Timer)
+{ USHORT i;
+
+ for (i = 0; i < NUM_MFGPTS; i++) {
+ if (TimerInfo[i].Timer == Timer) {
+ TimerInfo[i].Interval = 0x00000000;
+ return;
+ }
+ }
+
+ Log_Error("Invalid timer: %d.", Timer);
+}
+
+
+//************************************************************************************
+// Initializes the MFGPT timers to be used for EVENT_TIMER
+//************************************************************************************
+void Init_MFGPT(void)
+{ ULONG MsrAddr, IRQ_Enables;
+ USHORT i;
+ register TIMERS * TimerPtr;
+
+ Enable_MFGPT_LBAR();
+
+ // Get current MFGPT IRQ mask
+ MsrAddr = MDD_Base;
+ (USHORT)MsrAddr = MSR_MFGPT_IRQ;
+ IRQ_Enables = Read_MSR_LO(MsrAddr);
+
+ for (i = 0; i < NUM_MFGPTS; i++) {
+
+ TimerPtr = &TimerInfo[i];
+
+ // Initialize a MFGPT
+ Init_Timer(TimerPtr);
+
+ // Mark timer as available
+ MarkTimerAvailable(TimerPtr->Timer);
+
+ // Route Compare 1 events to SMI
+ IRQZ_Mapper(TimerPtr->Mapper, 2);
+
+ // Enable timer event
+ IRQ_Enables |= TimerPtr->Mask;
+
+ }
+
+
+ // Restore the MFGPT LBAR
+ Restore_MFGPT_LBAR();
+
+
+ // Enable MFGPT SMIs
+ Write_MSR_LO(MsrAddr, IRQ_Enables);
+
+}
+
+
+
+//***********************************************************************
+// Disables a millisecond timer
+//***********************************************************************
+void DisableMsTimer_5536(USHORT Timer)
+{ USHORT Setup, i;
+
+ Enable_MFGPT_LBAR();
+
+
+ for (i = 0; i < NUM_MFGPTS; i++) {
+ if (TimerInfo[i].Timer == Timer) {
+ // Mark timer as available
+ MarkTimerAvailable(Timer);
+
+ // Clear timer event and disable timer
+ Setup = TimerInfo[i].TimerBase + MFGPT_SETUP;
+ out_16(Setup, MFGPT_COMPARE1 | MFGPT_COMPARE2);
+ break;
+ }
+ }
+
+ // Restore the MFGPT LBAR
+ Restore_MFGPT_LBAR();
+
+}
+
+
+
+//***********************************************************************
+// Allocates a h/w timer for the specified interval
+// Returns the timer # allocated else 0xFFFF
+//***********************************************************************
+USHORT AllocateTimer_5536(ULONG Interval, UCHAR Attributes)
+{ UCHAR i, Exact = 0, Unused=0, Compat=0, Mask;
+ register TIMERS * TimerPtr;
+
+ // Find the MFGPT whose timebase is the best-match
+ for (i = 0; i < NUM_MFGPTS; i++) {
+ TimerPtr = &TimerInfo[i];
+
+ // Don't use timers reserved for EVENT_PWM
+ if (TimerPtr->Setup == PWM_SETUP) {
+ continue;
+ }
+
+ if (Attributes & (FOR_STANDBY >> 24)) {
+ // Timers used for PM must be in the 32 KHz domain
+ if (TimerPtr->Setup & MFGPT_CLK_SEL) {
+ continue;
+ }
+ } else {
+ if (TimerPtr->Timer >= 6) {
+ // Timers 6 & 7 are reserved for PM
+ continue;
+ }
+ }
+ Mask = (UCHAR)TimerPtr->Mask;
+
+ // Is timer unused?
+ if (TimerPtr->Interval == 0x00000000) {
+ Unused |= Mask;
+ }
+
+ // Is timebase a perfect match?
+ if ((Interval*1000 % TimerPtr->Period) == 0) {
+ Exact |= Mask;
+ }
+
+ // Is timebase compatible?
+ if (Interval*1000 >= TimerPtr->Period) {
+ Compat |= Mask;
+ }
+ }
+
+ // Is there an UNUSED timer whose timebase is an exact match?
+ if (!(Mask = (Unused & Exact))) {
+ // No, is there an UNUSED timer that is compatible?
+ if (!(Mask = (Unused & Compat))) {
+ // No, is there ANY timer whose timebase is an exact match?
+ if (!(Mask = Exact)) {
+ // No, is there ANY timer that is compatible?
+ if (!(Mask = Compat)) {
+ // No timers are available
+ return 0xFFFF;
+ }
+ }
+ }
+ }
+
+ // Return the MFGPT index
+ Mask = 1 << BitScanReverse(Mask);
+ for (i = 0; i < NUM_MFGPTS; i++) {
+ if (TimerInfo[i].Mask == Mask) {
+ return i;
+ }
+ }
+ return 0xFFFF;
+}
+
+
+//***********************************************************************
+// Enables a millisecond timer
+//***********************************************************************
+UCHAR EnableMsTimer_5536(ULONG Interval, UCHAR Attributes)
+{ USHORT i, Count, TimerBase;
+ ULONG MsrAddr, IRQ_Enables, TotalCounts, Roundoff;
+ register TIMERS * TimerPtr;
+
+ // Get current MFGPT IRQ mask
+ MsrAddr = MDD_Base;
+ (USHORT)MsrAddr = MSR_MFGPT_IRQ;
+ IRQ_Enables = Read_MSR_LO(MsrAddr);
+
+ // Allocate a h/w timer
+ i = AllocateTimer_5536(Interval, Attributes);
+ if (i == 0xFFFF) {
+ Log_Error("Attempt to enable %d ms timer interval failed", Interval);
+ return 0;
+ }
+
+ TimerPtr = &TimerInfo[i];
+
+ // A timer was allocated, is it already in use?
+ if (TimerPtr->Interval) {
+ // Yes, does it need to be reprogrammed?
+ if (Interval > TimerPtr->Interval) {
+ // No, but since the timer has already been running for an
+ // indeterminate period, the 1st interval will be shortened.
+ return (UCHAR)TimerPtr->Timer;
+ }
+ }
+
+
+ if (Interval) {
+
+ Enable_MFGPT_LBAR();
+
+ // Get I/O address of this timer
+ TimerBase = TimerPtr->TimerBase;
+
+ // The MFGPT document specifies the following sequence in order
+ // to prevent any spurious resets, interrupt, or output events:
+ // - Set Counter Enable bit to 0.
+ // - Clear SMI enable in MSR_MFGPT_IRQ
+ // - Update Count as desired
+ // - When updates are completed, clear event bits
+ // - Set SMI enable in MSR_MFGPT_IRQ
+ // - Set Counter Enable bit to 1
+
+ // Does this timer need to be initialized again (e.g. after S3) ?
+ if (!(in_16(TimerBase + MFGPT_SETUP) & MFGPT_INITED)) {
+ // Initialize the timer
+ Init_Timer(TimerPtr);
+ }
+
+ // Set Counter Enable to 0
+ out_16(TimerBase + MFGPT_SETUP, 0);
+
+ // Disable SMIs
+ Write_MSR_LO(MsrAddr, 0x00000000);
+
+ // Scale the interval appropriately
+ Roundoff = 0;
+ if (TimerPtr->Period < 1000) {
+ Roundoff = TimerPtr->Period;
+ }
+ TotalCounts = (Interval*1000 + Roundoff)/TimerPtr->Period;
+ Count = (USHORT)TotalCounts;
+ if (TotalCounts & 0xFFFF0000) {
+ Count = 0xFFFF;
+ }
+
+ // Record the timer's interval
+ TimerPtr->Interval = ((ULONG)Count * TimerPtr->Period)/1000;
+
+ // Zero the counter
+ out_16(TimerBase + MFGPT_COUNTER, 0x0000);
+
+ // Set Comparator1 to Count and Comparator2 to 0xFFFF
+ out_32(TimerBase + MFGPT_CMP1, 0xFFFF0000L | Count);
+
+ // Clear timer event(s)
+ out_16(TimerBase + MFGPT_SETUP, MFGPT_COMPARE1 | MFGPT_COMPARE2);
+
+ // Re-enable SMIs
+ Write_MSR_LO(MsrAddr, IRQ_Enables);
+
+ // Set Counter Enable to 1
+ out_16(TimerBase + MFGPT_SETUP, MFGPT_ENABLE);
+
+ // Restore the MFGPT LBAR
+ Restore_MFGPT_LBAR();
+ }
+
+ return (UCHAR)TimerPtr->Timer;
+}
+
+
+//***********************************************************************
+// Configures a MFGPT as a PWM signal generator
+//***********************************************************************
+void pascal Program_PWM(UCHAR Gpio, UCHAR Duty, USHORT Rate, UCHAR EnableFlag)
+{ USHORT i, Timer;
+ register TIMERS * TimerPtr;
+
+ // Determine the MFGPT associated with the specified GPIO
+ switch (Gpio) {
+ case 5:
+ Timer = 0;
+ break;
+ case 6:
+ Timer = 1;
+ break;
+ case 7:
+ Timer = 2;
+ break;
+ case 27:
+ Timer = 7;
+ break;
+ default:
+ Log_Error("EVENT_PWM is not supported on GPIO%d", Gpio);
+ return;
+ }
+
+ // Program the MFGPT to the specified rate and duty cycle
+ for (i = 0; i < NUM_MFGPTS; i++) {
+
+ TimerPtr = &TimerInfo[i];
+
+ if (TimerPtr->Timer == Timer) {
+
+ // Check if MFGPT is reserved for EVENT_PWM
+ if(TimerPtr->Setup != PWM_SETUP) {
+ continue;
+ }
+
+ // Enable the MFGPT LBAR
+ Enable_MFGPT_LBAR();
+
+ // Clear this timer's SETUP register in case it has been used previously as a timer
+ // Write_MSR_LO(MDD_Base + MSR_MFGPT_CLR_SETUP, TimerPtr->Mask);
+ // out_16(TimerPtr->TimerBase + MFGPT_SETUP, PWM_SETUP);
+
+
+ // Clamp duty cycle to 100%
+ if (Duty > 100) {
+ Duty = 100;
+ }
+
+ // Program the Count registers
+ out_16(TimerPtr->TimerBase + MFGPT_COUNTER, 0x0000);
+ out_16(TimerPtr->TimerBase + MFGPT_CMP1, (USHORT)(((ULONG)Rate * Duty)/100));
+ out_16(TimerPtr->TimerBase + MFGPT_CMP2, Rate);
+
+ // Enable the counter
+ out_16(TimerPtr->TimerBase + MFGPT_SETUP, EnableFlag ? MFGPT_ENABLE: 0);
+
+ Restore_MFGPT_LBAR();
+
+ return;
+ }
+ }
+
+ Log_Error("EVENT_PWM on GPIO%d failed because MFGPT%d is reserved.", Gpio, Timer);
+}
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/msr.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/msr.asm
new file mode 100755
index 0000000..97cc583
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/msr.asm
@@ -0,0 +1,348 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* Routines related to MSRs.
+
+include VSA2.INC
+include DESCR.INC
+
+
+.model tiny,c
+.586p
+.CODE
+
+extern SMM_Header: SmiHeader
+
+;***********************************************************************
+; Returns the high DWORD of an MSR.
+; Usage: HighMsrValue = Read_MSR_HI(Msr_Address);
+;***********************************************************************
+Read_MSR_HI proc pascal \
+ Msr: dword
+
+ mov ecx, [Msr]
+ rdmsr
+ mov ax, dx
+ shr edx, 16
+ ret
+
+Read_MSR_HI endp
+
+;***********************************************************************
+; Writes the high DWORD of an MSR. The low DWORD is preserved.
+; Usage: Write_MSR_HI(Msr_Address, Data);
+;***********************************************************************
+Write_MSR_HI proc pascal \
+ Msr: dword, \
+ Data: dword
+
+ mov ecx, [Msr]
+ rdmsr ; Get low 32 bits
+ mov edx, [Data]
+ wrmsr
+ ret
+
+Write_MSR_HI endp
+
+;***********************************************************************
+; Returns the low DWORD of an MSR.
+; Usage: LowMsrValue = Read_MSR_LO(Msr_Address);
+;***********************************************************************
+Read_MSR_LO proc pascal \
+ Msr: dword
+
+ mov ecx, [Msr]
+ rdmsr
+ mov edx, eax
+ shr edx, 16
+ ret
+
+Read_MSR_LO endp
+
+;***********************************************************************
+; Writes the low DWORD of an MSR. The high DWORD is preserved.
+; Usage: Write_MSR_LO(Msr_Address, Data);
+;***********************************************************************
+Write_MSR_LO proc pascal \
+ Msr: dword, \
+ Data: dword
+
+ mov ecx, [Msr]
+ rdmsr ; Get high 32 bits
+ mov eax, [Data]
+ wrmsr
+ ret
+
+Write_MSR_LO endp
+
+
+
+
+;***********************************************************************
+; Returns an MSR value in a buffer.
+; Usage: Read_MSR(ULONG Msr, ULONG * Buffer);
+;***********************************************************************
+Read_MSR proc pascal \
+ Msr: dword, \
+ Buffer: PTR
+
+ mov ecx, [Msr]
+ rdmsr
+
+ mov bx, [Buffer]
+ mov [bx+0], eax
+ mov [bx+4], edx
+ ret
+
+Read_MSR endp
+
+
+;***********************************************************************
+; Writes an MSR.
+; Usage: Write_MSR(ULONG Msr, ULONG * Buffer);
+;***********************************************************************
+Write_MSR proc pascal \
+ Msr: dword, \
+ Buffer: PTR
+
+ mov ecx, [Msr]
+ mov bx, [Buffer]
+ mov eax, [bx+0]
+ mov edx, [bx+4]
+ wrmsr
+ ret
+
+Write_MSR endp
+
+
+
+
+;***********************************************************************
+; Parses MSR_MBIU_CAP of an MBIU and returns descriptor counts in
+; a byte buffer.
+;***********************************************************************
+Parse_Capabilities proc pascal \
+ Msr: PTR, \
+ Buffer: PTR
+
+ mov bx, [Msr]
+ mov eax, [bx+0] ; Get 1st dword of CAPABILITIES
+ mov edx, [bx+4] ; Get 2nd dword of CAPABILITIES
+ mov bx, [Buffer]
+ mov cl, 6 ; Number of P2D descriptors
+NxtCount:
+ mov ch, al
+ and ch, 3Fh ; 6 bits per field
+ mov [bx], ch
+ inc bx
+
+ shrd eax, edx, 6 ; Shift next field into LSBs
+ shr edx, 6
+ dec cl
+ jnz NxtCount
+
+ mov ch, al ; Get NIOD_BM
+ and ch, 3Fh
+ mov [bx+1], ch
+
+ shr eax, 6 ; Get NIOD_SC
+ mov ch, al
+ and ch, 3Fh
+ mov [bx+2], ch
+
+ shr eax, 9 ; Skip NCOH field
+ mov ch, al
+ and ch, 07h ; Get NPORTS
+ mov [bx+3], ch
+
+ shr ax, 9 ; Get NSTAT_CNT
+ and al, 07h
+ mov [bx+4], al
+ ret
+
+Parse_Capabilities endp
+
+
+;***********************************************************************
+; Extract the 3 main fields from a P2D descriptor
+;***********************************************************************
+Parse_Descriptor proc pascal uses edi \
+ P2D_Type: byte, \
+ Source: ptr, \
+ Dest: ptr
+
+ mov bx, [Source]
+
+ mov ecx, [bx] ; Get low MSR
+ mov eax, ecx
+ mov edx, [bx+4] ; Get high MSR
+
+ cmp bl, IOD_BM
+ je Descr_IO_BM
+
+ shl ecx, 12 ; Extract 1st field
+ shrd eax, edx, 20 ; Extract 2nd field
+ shl eax, 12
+
+ xor dl, dl ; Extract 3rd field
+ shl edx, 12-8
+ mov edi, edx ; EDI = Offset
+
+ mov bl, [P2D_Type] ; Dispatch to correct descriptor parser
+ cmp bl, P2D_BM
+ je Descr_BM
+ cmp bl, P2D_BMO
+ je Descr_BMO
+ cmp bl, P2D_BMK
+ je Descr_BMK
+ cmp bl, P2D_R
+ je Descr_R
+ cmp bl, P2D_RO
+ je Descr_RO
+ jmp Exit
+
+
+Descr_IO_BM:
+ and ecx, 000FFFFFh ; ECX = IMASK
+ shrd eax, edx, 20 ; EAX = IBASE
+ xor edi, edi ; EDI = 00000000
+
+Descr_BMO: ; Assume OFFSET == 0
+Descr_BM:
+Descr_BMK:
+ ; ECX = PMASK
+ ; EAX = PBASE
+ and eax, ecx ; Start = PBASE & PMASK
+ mov edx, eax ; End = Start + ~PMASK
+ not ecx
+ add edx, ecx
+ jmp StoreResult
+
+
+Descr_RO: ; Assume OFFSET == 0
+Descr_R:
+ ; ECX = PMIN
+ ; EAX = PMAX
+ xchg eax, ecx ; Start = PMIN
+ mov edx, ecx ; End = PMAX
+ or dx, 0FFFh
+
+StoreResult:
+ mov bx, [Dest]
+ mov [bx], eax ; Start
+ mov [bx+4], edx ; End
+ add edi, eax ; Physical = Start + Offset
+ mov [bx+8], edi
+
+Exit: ret
+
+
+Parse_Descriptor endp
+
+
+
+
+;***********************************************************************
+;***********************************************************************
+MergeFields proc pascal \
+ Dest: PTR, \
+ Field1: DWORD, \
+ Field2: DWORD, \
+ Field3: DWORD
+
+ mov bx, [Dest]
+
+;// Descr->MsrData[0] = (PBase << 20) | (PMask & 0xFFFFF);
+;// Descr->MsrData[1] = (PBase >> 12) | (POffset << 8);
+ mov eax, [Field2]
+ mov edx, eax
+ shl eax, 20
+ mov ecx, [Field1]
+ and ecx, 0FFFFFh
+ or eax, ecx
+ mov [bx], eax
+
+ shr edx, 12
+ mov eax, [Field3]
+ shl eax, 8
+ or eax, edx
+ mov [bx+4], eax
+ ret
+
+MergeFields endp
+
+
+
+
+;***********************************************************************
+; Returns TRUE if Range is a power of 2
+;***********************************************************************
+IsPowerOfTwo proc pascal \
+ Range: dword
+
+ mov ebx, [Range]
+ bsf eax, ebx ; Scan LSB to MSB
+ bsr edx, ebx ; Scan MSB to LSB
+ cmp al, dl ; Same bit found ?
+ mov al, 0 ; No, return FALSE
+ jne Exit
+ mov al, 1 ; else return TRUE
+Exit: ret
+
+IsPowerOfTwo endp
+
+
+
+;***********************************************************************
+; Returns index of first bit set when scanning from MSB to LSB
+;***********************************************************************
+BitScanReverse proc pascal \
+ Range: dword
+
+ mov ebx, [Range]
+ bsr eax, ebx ; Scan MSB to LSB
+ ret
+
+BitScanReverse endp
+
+
+;***********************************************************************
+; Returns index of first bit set when scanning from LSB to MSB
+;***********************************************************************
+BitScanForward proc pascal \
+ Range: dword
+
+ mov ebx, [Range]
+ bsf eax, ebx ; Scan LSB to MSB
+ ret
+
+BitScanForward endp
+
+
+
+
+
+
+
+
+
+
+
+
+ end
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/ohci.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/ohci.c
new file mode 100755
index 0000000..db19956
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/ohci.c
@@ -0,0 +1,164 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//*****************************************************************************
+//* Handler for EVENT_USB and EVENT_KEL
+//*****************************************************************************
+
+
+
+
+#include "VSA2.H"
+#include "PROTOS.H"
+#include "CHIPSET.H"
+#include "VPCI.H"
+#include "PCI.H"
+#include "HCE.H"
+
+extern ULONG MsgPacket[];
+extern SmiHeader SMM_Header;
+extern Hardware HardwareInfo;
+extern VIRTUAL_DEVICE * SouthBridge;
+extern void pascal write_flat_size(ULONG, ULONG, UCHAR);
+
+USHORT OHCI_Address;
+ULONG OHCI_Command;
+ULONG HC_Status;
+#define HC ((ULONG)(&((HCOR *)0)
+
+
+//***********************************************************************
+// Restores the OHCI COMMAND register to the original value
+//***********************************************************************
+void Restore_OHCI_Command()
+{
+ Virtual_PCI_Write_Handler(OHCI_Address, BYTE_IO, OHCI_Command & ~MEM_SPACE);
+}
+
+//***********************************************************************
+// Sends EVENT_USB or EVENT_KEL
+//***********************************************************************
+void Send_OHCI_Event(UCHAR HC_Number)
+{ USHORT Hce_Status;
+ HCE_CONTROL Hce_Control;
+ ULONG HC_Enable, HC_Address;
+ ULONG Timeout;
+ PCI_HEADER_ENTRY * OHCI_Hdr;
+
+ // Get ptr to virtualized PCI header
+ OHCI_Hdr = *(SouthBridge+3 + HC_Number);
+ if (!OHCI_Hdr) {
+ Log_Error("Invalid HC number 0x%02X", HC_Number);
+ return;
+ }
+
+ // Get HC address from BAR0
+ if (!(HC_Address = (OHCI_Hdr+(BAR0/4))->Value)) {
+ return;
+ }
+
+ OHCI_Address = 0x7C00 + (((USHORT)HC_Number-1) << 8) + COMMAND;
+ // Are memory-mapped registers enabled?
+ if (!((OHCI_Hdr+(COMMAND/4))->Value & MEM_SPACE)) {
+
+ OHCI_Command = (OHCI_Hdr+(COMMAND/4))->Value;
+ // No, temporarily enable access to them
+ Virtual_PCI_Write_Handler(OHCI_Address, BYTE_IO, OHCI_Command | MEM_SPACE);
+
+ // Schedule a routine to restore the original COMMAND value
+ // after the VSM has processed the EVENT_USB or EVENT_KEL.
+ Schedule_VSM((USHORT)Restore_OHCI_Command);
+ }
+
+
+ // Get HC's Hce_Control register
+ Hce_Control.HceUshort = (USHORT)read_flat(HC_Address + HC->HceControl)));
+
+ // Prepare message packet
+ MsgPacket[1] = HC_Address;
+ MsgPacket[2] = HC_Number;
+ MsgPacket[3] = 0;
+
+ // Is it an emulation event ?
+ if (Hce_Control.EmulationInterrupt) {
+
+ // SiBZ 3069/3370: HceStatus[3] is not updated properly
+ if (SMM_Header.SMI_Flags.Ext_IO_Trap) {
+ if (SMM_Header.SMI_Flags.IO_Write) {
+
+ Hce_Status = (USHORT)read_flat(HC_Address + HC->HceStatus)));
+ switch ((USHORT)SMM_Header.IO_addr) {
+ case 0x60:
+ Hce_Status &= ~CMD_DATA;
+ break;
+ case 0x64:
+ Hce_Status |= CMD_DATA;
+ break;
+ }
+ write_flat_size(HC_Address + HC->HceStatus)), Hce_Status, BYTE_IO);
+ }
+ }
+
+ // SiBZ 3509/3571: KEL SMIs are level instead of edge-triggered
+ MsgPacket[3] = Hce_Control.HceUshort;
+ Timeout = 1000;
+ while (Timeout--) {
+
+ Hce_Control.HceUshort = (USHORT)read_flat(HC_Address + HC->HceControl)));
+ if (Hce_Control.IRQ1Active || Hce_Control.IRQ12Active) {
+ // Clear the active IRQ & disable emulation
+ Hce_Control.EmulationEnable = 0;
+ write_flat_size(HC_Address + HC->HceControl)), Hce_Control.HceUshort , WORD_IO);
+
+ // Read a byte from the data port to dismiss the 8042 interrupt
+ in_8(0x60);
+
+ // Re-enable emulation
+ Hce_Control.EmulationEnable = 1;
+ write_flat_size(HC_Address + HC->HceControl)), Hce_Control.HceUshort, WORD_IO);
+ } else {
+ break;
+ }
+ }
+
+ // Report if SiBZ 3571 workaround failed
+ if (Timeout == 0) {
+ Log_Error("IRQx_ACTIVE won't clear");
+ }
+
+ // Send emulation event to the i8042 VSM
+ Send_Event(EVENT_KEL, SysMgr_VSM);
+ }
+
+ // Any unmasked events pending ?
+ HC_Status |= read_flat(HC_Address + HC->HcInterruptStatus)));
+
+
+ HC_Enable = read_flat(HC_Address + HC->HcInterruptEnable)));
+ if (HC_Status & HC_Enable) {
+ // SWAPSiF for PBZ 2300:
+ MsgPacket[3] = HC_Status;
+ write_flat(HC_Address + HC->HcInterruptStatus)), HC_Status);
+
+ // Send Host Controller event to the OHCI VSM
+ Send_Event(EVENT_USB, 0x00000000);
+ }
+
+ HC_Status = 0;
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/pci_pm.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/pci_pm.c
new file mode 100755
index 0000000..8e7f041
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/pci_pm.c
@@ -0,0 +1,539 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Routines related to PCI power management.
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "VPCI.H"
+#include "PROTOS.H"
+#include "PCI.H"
+#include "CHIPSET.H"
+#include "GX2.H"
+#include "ACPI.H"
+#include "DESCR.H"
+
+
+
+#if SUPPORT_CAPABILITIES
+
+extern DESCRIPTOR MSRs[];
+extern PCI_HEADER_ENTRY * HdrPtr;
+extern PCI_HEADER_ENTRY * CommandPtr;
+extern UCHAR End_of_POST;
+extern ULONG OHCI1_Smi;
+extern ULONG MCP_SB;
+
+#define OHC_IN_D3 1
+#define EHC_IN_D3 2
+#define UDC_IN_D3 4
+#define UOC_IN_D3 8
+#define ALL_IN_D3 (OHC_IN_D3 | EHC_IN_D3 | UDC_IN_D3 | UOC_IN_D3)
+
+typedef struct { // All bits are Read-Only
+ union {
+ ULONG AsDword;
+ struct {
+ ULONG CompatibilityID: 8;
+ ULONG NextItemPtr: 8;
+ ULONG Version: 3;
+ ULONG PME_Clock: 1;
+ ULONG Reserved: 1;
+ ULONG DSI: 1;
+ ULONG Aux_Current: 3;
+ ULONG D1_Support: 1;
+ ULONG D2_Support: 1;
+ ULONG PME_D0: 1;
+ ULONG PME_D1: 1;
+ ULONG PME_D2: 1;
+ ULONG PME_D3_Hot: 1;
+ ULONG PME_D3_Cold: 1;
+ };
+ };
+} PMC;
+
+typedef struct {
+ union {
+ ULONG AsDword;
+ struct {
+ union {
+ USHORT AsWord;
+ struct {
+ USHORT PowerState: 2; // Read-write
+ USHORT Reserved: 6; // Read-only
+ USHORT PME_En: 1; // Read-write
+ USHORT Data_Select: 4; // Read-write
+ USHORT Data_Scale: 2; // Read-only
+ USHORT PME_Status: 1; // Read/Write-Clear
+ };
+ };
+ UCHAR PMCSR_BSE; // Bridge Support Extensions
+ UCHAR Data;
+ };
+ };
+} PMCR;
+// R/W Mask = 1001_1111_0000_0011
+#define PMCR_MASK 0x9F03
+
+
+
+// Fields in USBMSROHCB, USBMSREHCB, USBMSRUDCB, USBMSRUOCB:
+typedef struct {
+ union {
+ struct {
+ ULONG Reserved: 1;
+ ULONG MEMEN: 1;
+ ULONG BMEN: 1;
+ ULONG PMEEN: 1;
+ ULONG PMESTS: 1;
+ };
+ struct {
+ UCHAR Enables;
+ // NOTE: the next 3 fields are actually 6 bits, but the compiler
+ // generates crappy code if defined as such
+ UCHAR FLADJ;
+ UCHAR LEGSMIEN;
+ UCHAR LEGSMISTS;
+ };
+ };
+} USBMSR;
+
+
+// Fields in 32-MSBs of GLCP's PMCLKACTIVE, PMCLKOFF, PMCLKDISABLE, PMCLK4ACK, PMCLKDISABLE:
+typedef struct {
+ union {
+ ULONG AsDword;
+ struct {
+ ULONG GL0_0: 1;
+ ULONG GL0_1: 1;
+ ULONG GLPCI_GLIU: 1;
+ ULONG GLPCI_PCI: 1;
+ ULONG GLPCI_PCIF: 1;
+ ULONG RSVD: 6;
+ ULONG ATAC_GLIU: 1;
+ ULONG ATAC_LB: 1;
+ ULONG ACC_GLIU: 1;
+ ULONG ACC_LB: 1;
+ ULONG ACC_BIT: 1;
+ ULONG DIVIL_GLIU: 1;
+ ULONG DIVIL_LB: 1;
+ ULONG DIVIL_LPC: 1;
+ ULONG DIVIL_DMA: 1;
+ ULONG DIVIL_SMB: 1;
+ ULONG DIVIL_PIT: 1;
+ ULONG DIVIL_UART1: 1;
+ ULONG DIVIL_UART2: 1;
+ ULONG DIVIL_PMC: 1;
+ ULONG DIVIL_PMC_STD: 1;
+ ULONG DIVIL_GPIO: 1;
+ ULONG DIVIL_GPIO_STD: 1;
+ ULONG DIVIL_MFGPT_32K: 1;
+ ULONG DIVIL_MFGPT_14M: 1;
+ ULONG DIVIL_32K_STD: 1;
+ ULONG GLCP_GLIU: 1;
+ };
+ };
+ union {
+ ULONG AsDword_HI;
+ struct {
+ ULONG GLCP_DBG: 1;
+ ULONG GLCP_PCI: 1;
+ ULONG OHC_CLK48: 1;
+ ULONG UDC_HCLK: 1;
+ ULONG EHC_HCLK: 1;
+ ULONG OHC_HCLK: 1;
+ ULONG EHC_CLK60: 1;
+ ULONG UDC_CLK60: 1;
+ ULONG USBP1_CLK60: 1;
+ ULONG USBP2_CLK60: 1;
+ ULONG USBP3_CLK60: 1;
+ ULONG USBP4_CLK60: 1;
+ ULONG OTC_HCLK: 1;
+ ULONG USB_GLIU: 1; // aka M2A_HCLK in USB 2.0 IDS
+ ULONG USBPHYPLLEN: 1;
+ };
+ };
+} GLCP_CLKS;
+
+// Local variables:
+ULONG MsrAddr, MsrData[2];
+USBMSR * UsbMsr = (USBMSR *)&MsrData[1];
+GLCP_CLKS Clocks;
+USHORT D3_Flag = 0;
+ULONG EHCI_BAR;
+
+//***********************************************************************
+// Returns TRUE if the specified EHCI port is suspended
+// NOTE: Port is 1-based
+//***********************************************************************
+UCHAR pascal EHCI_Port_Suspended(UCHAR Port)
+{
+ if ((UCHAR)READ_MEMORY(EHCI_BAR + 0x50 + Port*4) & 0x80) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+//***********************************************************************
+// Reads the MSR corresponding to the current USB 2.0 function
+//***********************************************************************
+void Get_USB_MSR(void)
+{
+ MsrAddr = OHCI1_Smi;
+ (UCHAR)MsrAddr = (HdrPtr+BAR0/4)->LBar;
+
+ // Get current MSR value
+ Read_MSR(MsrAddr, MsrData);
+}
+
+
+//***********************************************************************
+// Returns value of the EHCI Power Management register USBLEGCTLSTS
+//***********************************************************************
+ULONG pascal Handle_EHCI_Rd(PCI_HEADER_ENTRY * Pci)
+{
+
+ // Filter out non-EHCI functions
+ if (((HdrPtr+REVISION_ID/4)->Value & 0xFFFFFF00) == 0x0C032000) {
+
+ // Read USBMSREHCB MSR
+ Get_USB_MSR();
+
+ Pci->EHCI_Errors = (UCHAR)UsbMsr->LEGSMISTS;
+
+ // Sync PCI register with MSR (optional):
+ Pci->EHCI_SMI_Enables = (UCHAR)UsbMsr->LEGSMIEN;
+
+ }
+ return Pci->Value;
+}
+
+//***********************************************************************
+// Handles writes to the EHCI PCI registers:
+// COMMAND
+// BAR0
+// USBLEGSUP
+// USBLEGCTLSTS
+// FLADJ
+//***********************************************************************
+void pascal Handle_EHCI_Wr(PCI_HEADER_ENTRY * Pci)
+{ ULONG SMI_Status = SMI_ON_COMMAND;
+
+ // Read USBMSREHCB MSR
+ Get_USB_MSR();
+
+ switch (Pci->Reg & 0xFC) {
+ case BAR0:
+ EHCI_BAR = Pci->Value;
+ SMI_Status = SMI_ON_BAR;
+ case COMMAND:
+ if (End_of_POST) {
+ // Set USBLEGCTLSTS[31/30]
+ (HdrPtr+9)->Value |= SMI_Status;
+ }
+ return;
+
+ case USBLEGSUP: // EECP
+ // If ownership changing, set USBLEGCTLSTS[29]
+ if (Pci->Value & (OS_OWNED_SEMAPHORE | BIOS_OWNED_SEMAPHORE)) {
+ // Set USBLEGCTLSTS[29]
+ (Pci+1)->Value |= SMI_ON_OC;
+ }
+ // If system software is requesting ownership...
+ if (Pci->Value & OS_OWNED_SEMAPHORE) {
+ // Clear BIOS Owned Semaphore
+ Pci->Value &= ~BIOS_OWNED_SEMAPHORE;
+ // Clear SMI enables
+ UsbMsr->LEGSMIEN = 0x00;
+ }
+ // If BIOS is requesting ownership...
+ if (Pci->Value & BIOS_OWNED_SEMAPHORE) {
+ // Clear system software Owned Semaphore
+ Pci->Value &= ~OS_OWNED_SEMAPHORE;
+ }
+ break;
+
+ case USBLEGCTLSTS: // EECP+4
+ UsbMsr->LEGSMIEN = Pci->EHCI_SMI_Enables;
+ break;
+
+ case SRBN_REG:
+ UsbMsr->FLADJ = Pci->FLADJ;
+ break;
+ }
+
+ // Update USBMSREHCB
+ Write_MSR(MsrAddr, MsrData);
+}
+
+
+
+
+//***********************************************************************
+// Handles reads from a PCI Power Management register
+// Returns value of PCI register
+//***********************************************************************
+ULONG pascal Handle_PCI_PM_Rd(PCI_HEADER_ENTRY * Pci)
+{ PMCR * PMCR_Ptr;
+
+ // Get PME status from MSR
+ Get_USB_MSR();
+
+ // Cast register ptr
+ PMCR_Ptr = (PMCR *)&Pci->Value;
+ PMCR_Ptr->PME_Status = UsbMsr->PMESTS ? 1: 0;
+
+ return Pci->Value;
+}
+
+//***********************************************************************
+// Handles writes to the PCI Power Management register
+//***********************************************************************
+void pascal Handle_PCI_PM_Wr(PCI_HEADER_ENTRY * Pci, USHORT PreviousData)
+{ PMCR Delta;
+ PMCR * PMCR_Ptr;
+ PMC * PMC_Ptr;
+ USHORT Value;
+
+ // Cast register ptrs
+ PMCR_Ptr = (PMCR *)&Pci->Value;
+ PMC_Ptr = (PMC *)&(Pci-1)->Value;
+
+ Value = (USHORT)Pci->Value;
+
+ // Mask read-only bits
+ Value &= PMCR_MASK;
+
+
+ // Compute changes
+ Delta.AsWord = (USHORT)PreviousData ^ PMCR_Ptr->AsWord;
+
+
+ // Select data to be reported through the Data register
+ // Return as "not implemented"
+ PMCR_Ptr->Data = 0; //Power[PMCR_Ptr->Data_Select].Data;
+ PMCR_Ptr->Data_Scale = 0; //Power[PMCR_Ptr->Data_Select].Scale;
+
+ Get_USB_MSR();
+
+ // PME# status write-to-clear
+ if (PMCR_Ptr->PME_Status) {
+ UsbMsr->PMESTS = 1;
+ }
+
+ // PME# enable
+ if (Delta.PME_En) {
+ // Check if PME# is supported
+ if (PMC_Ptr->PME_D3_Cold || PMC_Ptr->PME_D3_Hot ||
+ PMC_Ptr->PME_D0 || PMC_Ptr->PME_D1 || PMC_Ptr->PME_D2) {
+ if (PMCR_Ptr->PME_En) {
+ // Enable PME# assertion
+ UsbMsr->PMEEN = 1;
+ } else {
+ // Disable PME# assertion
+ UsbMsr->PMEEN = 0;
+ }
+ } else {
+ // PME# not supported
+ PMCR_Ptr->PME_En = 0;
+ }
+ }
+ // Update USBMSRxxCB
+ Write_MSR(MsrAddr, MsrData);
+
+ // Power state
+ if (Delta.PowerState) {
+ UCHAR SupportedState=0;
+ ULONG ClocksMsr;
+ register USHORT USB_20_D3_Flag = D3_Flag;
+
+ ClocksMsr = MCP_SB + MCP_PMCLKOFF;
+ Read_MSR(ClocksMsr, &Clocks.AsDword);
+
+ switch (PMCR_Ptr->PowerState) {
+ case D0_STATE:
+ // If D0 is supported...
+ if (PMC_Ptr->PME_D0) {
+ switch (HdrPtr->Device_ID) {
+ case DEVICE_ID_AMD_OHCI:
+ Clocks.OHC_HCLK = 0;
+ Clocks.OHC_CLK48 = 0;
+ USB_20_D3_Flag &= ~OHC_IN_D3;
+ break;
+
+ case DEVICE_ID_AMD_EHCI:
+ Clocks.EHC_HCLK = 0;
+ Clocks.EHC_CLK60 = 0;
+ Clocks.USBP1_CLK60 = 0;
+ Clocks.USBP2_CLK60 = 0;
+ Clocks.USBP3_CLK60 = 0;
+ Clocks.USBP4_CLK60 = 0;
+ Clocks.USBPHYPLLEN = 0;
+ USB_20_D3_Flag &= ~EHC_IN_D3;
+ break;
+
+ case DEVICE_ID_AMD_UDC:
+ Clocks.UDC_HCLK = 0;
+ Clocks.UDC_CLK60 = 0;
+ USB_20_D3_Flag &= ~UDC_IN_D3;
+ break;
+
+ case DEVICE_ID_AMD_OTG:
+ Clocks.OTC_HCLK = 0;
+ USB_20_D3_Flag &= ~UOC_IN_D3;
+ break;
+ }
+ SupportedState = 1;
+ }
+ break;
+
+ case D1_STATE:
+ case D2_STATE:
+ // D1 & D2 are not supported
+ switch (HdrPtr->Device_ID) {
+ case DEVICE_ID_AMD_OHCI:
+ USB_20_D3_Flag &= ~OHC_IN_D3;
+ break;
+
+ case DEVICE_ID_AMD_EHCI:
+ USB_20_D3_Flag &= ~EHC_IN_D3;
+ break;
+
+ case DEVICE_ID_AMD_UDC:
+ USB_20_D3_Flag &= ~UDC_IN_D3;
+ break;
+
+ case DEVICE_ID_AMD_OTG:
+ USB_20_D3_Flag &= ~UOC_IN_D3;
+ break;
+ }
+ break;
+
+ case D3_STATE: // D3hot
+ // If D3hot is supported...
+ if (PMC_Ptr->PME_D3_Hot) {
+ switch (HdrPtr->Device_ID) {
+ case DEVICE_ID_AMD_OHCI:
+ Clocks.OHC_HCLK = 0;
+ Clocks.OHC_CLK48 = 0;
+ USB_20_D3_Flag |= OHC_IN_D3;
+ break;
+
+ case DEVICE_ID_AMD_EHCI:
+ Clocks.EHC_HCLK = 0;
+ Clocks.EHC_CLK60 = 0;
+ Clocks.USBP1_CLK60 = 0;
+ Clocks.USBP2_CLK60 = 0;
+ Clocks.USBP3_CLK60 = 0;
+ Clocks.USBP4_CLK60 = 0;
+ Clocks.USBPHYPLLEN = 1;
+
+ // In D3 *only* USBPHYPLLEN should be gated (Phy Clock switched off).
+ // This guarantees max. power saving during S1 and proper USB Remote WakeUp functionality and Resume from S1
+ // If all EHC ports are suspended USBPHYPLLEN should not be gated, because USBPHYPLL is switched off by Phy-HW
+ if (EHCI_Port_Suspended(1) & EHCI_Port_Suspended(2) & EHCI_Port_Suspended(3) & EHCI_Port_Suspended(4)) {
+ Clocks.USBPHYPLLEN = 0;
+ }
+ USB_20_D3_Flag |= EHC_IN_D3;
+ break;
+
+ case DEVICE_ID_AMD_UDC:
+ USB_20_D3_Flag |= UDC_IN_D3;
+ break;
+
+ case DEVICE_ID_AMD_OTG:
+ USB_20_D3_Flag |= UOC_IN_D3;
+ break;
+ }
+
+ SupportedState = 1;
+ }
+ break;
+ } // end switch (PMCR_Ptr->PowerState)
+
+ if (SupportedState) {
+ PCI_HEADER_ENTRY * Bar;
+ DESCRIPTOR * Descr;
+ ULONG MsrData[2];
+ UCHAR Index;
+
+ // If going to D3, turn off P2D_BM descriptor so accesses will master-abort.
+ // Otherwise, the system hangs when the device registers are accessed since
+ // the clocks have been turned off. Restore the descriptor when going to D0.
+ Bar = HdrPtr+BAR0/4;
+ while ((Bar->Reg >= BAR0) && (Bar->Reg <= BAR5)) {
+ if (Bar->Flag & (MMIO_BAR | MEM_BAR)) {
+
+ // For each linked item, update the associated MSR
+ // Get the P2D_BM descriptor linked to this BAR
+ Index = Bar->Link;
+ do {
+ Descr = &MSRs[Index];
+ if (Descr->Type == P2D_BM || Descr->Type == P2D_BMK) {
+ if (PMCR_Ptr->PowerState == D3_STATE) {
+ Get_Descriptor_Default(Descr->Type, MsrData);
+ } else {
+ MsrData[0] = Descr->MsrData[0];
+ MsrData[1] = Descr->MsrData[1];
+ }
+ Write_MSR(Descr->MsrAddr, MsrData);
+ break;
+ }
+ } while (Index = Descr->Link);
+ }
+ if (Pci->Flag & EOL) {
+ break;
+ }
+ Bar++;
+ }
+
+
+
+// PBZ 2292 - Can't turn off USB_GLIU else MSR read of USB 2.0 hangs
+#if 0
+ // Are all USB 2.0 functions are in D3?
+ if (USB_20_D3_Flag == ALL_IN_D3) {
+ // Yes, then turn off USB_GLIU
+ Clocks.USB_GLIU = 1;
+ } else {
+ Clocks.USB_GLIU = 0;
+ }
+#endif
+ // Update D3 state for each function
+ D3_Flag = USB_20_D3_Flag;
+ // Update clock settings
+ Write_MSR(ClocksMsr, &Clocks.AsDword);
+
+ } else {
+ PMCR Previous;
+
+ // PCI PM Specification (page 29; Table 7):
+ // Writes of an unsupported state should discard the data
+ Previous.AsWord = PreviousData;
+ PMCR_Ptr->PowerState = Previous.PowerState;
+ }
+ } // end if (Delta.PowerState)
+
+ // Record current value
+ Pci->Value = PMCR_Ptr->AsDword;
+}
+
+
+#endif
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/pci_rd.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/pci_rd.c
new file mode 100755
index 0000000..d1d29ed
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/pci_rd.c
@@ -0,0 +1,177 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//*****************************************************************************
+//* Implements reads of virtualized PCI configuration headers
+//*****************************************************************************
+
+
+#include "VSA2.H"
+#include "PCI.H"
+#include "VPCI.H"
+#include "PROTOS.H"
+#include "SYSMGR.H"
+#include "CHIPSET.H"
+
+
+// External function declarations:
+ULONG pascal Get_Device_Status(PCI_HEADER_ENTRY *);
+ULONG pascal Handle_PCI_PM_Rd(PCI_HEADER_ENTRY *);
+ULONG pascal Handle_EHCI_Rd(PCI_HEADER_ENTRY *);
+ULONG pascal Read_MSR_LO(ULONG);
+UCHAR pascal Get_Latency(PCI_HEADER_ENTRY *);
+PCI_HEADER_ENTRY * pascal Get_Structure(USHORT);
+extern Hardware HardwareInfo;
+
+
+
+// External variable declarations:
+extern DESCRIPTOR MSRs[];
+extern UCHAR Shift, AlignedReg, Function;
+extern PCI_HEADER_ENTRY * CommandPtr;
+extern ULONG ATA_Error;
+
+
+
+//***********************************************************************
+// Reads an embedded PCI register
+//***********************************************************************
+ULONG pascal Read_EPCI(UCHAR AlignedReg)
+{ ULONG MsrAddr;
+
+ MsrAddr = MSRs[CommandPtr->Link].MsrAddr;
+ if (MsrAddr) {
+ (UCHAR)MsrAddr = AlignedReg/4;
+ return Read_MSR_LO(MsrAddr);
+ } else {
+ return 0;
+ }
+}
+
+
+//***********************************************************************
+//
+// This routine implements reads to virtualized configuration space.
+//
+// NOTES:
+// 1) Misaligned accesses are handled. If an access crosses a DWORD
+// boundary, only the bytes within the addressed DWORD are read.
+// The remaining bytes return FFs.
+// 2) The variable Pci points to a PCI_HEADER_ENTRY entry that defines
+// the state and characteristics of the register being read.
+//***********************************************************************
+ULONG pascal Virtual_PCI_Read_Handler(USHORT PCI_Address)
+{ ULONG Data;
+ register PCI_HEADER_ENTRY * Pci;
+
+
+ // Get ptr to virtualized table entry
+ Pci = Get_Structure(PCI_Address);
+
+
+ switch ((USHORT)Pci) {
+
+ case UNIMPLEMENTED_FUNCTION:
+ Data = 0xFFFFFFFF;
+ break;
+
+ case UNIMPLEMENTED_REGISTER:
+ Data = 0x00000000;
+ break;
+
+ default:
+ // Handle special cases
+ if (Pci->Flag & EPCI_R && AlignedReg < 0x40) {
+
+ // Embedded PCI device: read its h/w PCI configuration space
+ Data = Read_EPCI(AlignedReg);
+
+ if (AlignedReg == COMMAND) {
+ // Mark device '66 MHz capable'
+ Data |= PCI_66MHZ_CAPABLE;
+ }
+ break;
+ }
+
+ Data = Pci->Value;
+
+ switch (AlignedReg) {
+
+ case COMMAND:
+ // Get device's Status
+ Data |= Get_Device_Status(Pci);
+ break;
+
+ case BAR0:
+ case BAR1:
+ case BAR2:
+ case BAR3:
+ case BAR4:
+ case BAR5:
+ // If I/O BAR, set bit 0
+ if (Pci->Flag & IO_BAR) {
+ Data |= 1;
+ }
+ break;
+
+ case CACHE_LINE:
+ Pci->LatencyTimer = Get_Latency(Pci);
+ Data = Pci->Value;
+ break;
+
+#if SUPPORT_CAPABILITIES
+ case (PCI_PM_REG+4): // 0x44
+ if (Pci->Flag & PCI_PM) {
+ Data = Handle_PCI_PM_Rd(Pci);
+ break;
+ }
+
+ case USBLEGCTLSTS:
+ if (Pci->Flag & PCI_EHCI) {
+ Data = Handle_EHCI_Rd(Pci);
+ break;
+ }
+#endif
+
+ // Thor ATA vendor-specific registers:
+ case IDE_CFG: // 0x40
+ case IDE_DTC: // 0x48
+ case IDE_CAST: // 0x4C
+ case IDE_ETC: // 0x50
+ if (Pci->LBar) {
+ ULONG MsrAddr = ATA_Error;
+
+ (USHORT)MsrAddr = (USHORT)Pci->LBar;
+ Data = Read_MSR_LO(MsrAddr);
+ }
+ break;
+
+ }
+ }
+
+
+ // Handle non-dword aligned accesses
+ Data >>= Shift;
+ Data |= 0xFFFFFFFFL << (32-Shift);
+
+ return Data;
+}
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/pci_wr.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/pci_wr.c
new file mode 100755
index 0000000..b731778
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/pci_wr.c
@@ -0,0 +1,375 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//*****************************************************************************
+//* Implements writes of virtualized PCI configuration headers
+//*****************************************************************************
+
+
+#include "VSA2.H"
+#include "PCI.H"
+#include "GX2.H"
+#include "VPCI.H"
+#include "SYSMGR.H"
+#include "CHIPSET.H"
+#include "PROTOS.H"
+#include "MAPPER.H"
+
+
+// External function declarations:
+PCI_HEADER_ENTRY * pascal Get_Structure(USHORT);
+UCHAR pascal Update_BusMaster(PCI_HEADER_ENTRY *, UCHAR);
+void pascal Set_Latency(UCHAR);
+void pascal Clear_MBus_Error(PCI_HEADER_ENTRY *, ULONG);
+void pascal SMINT_Handler(USHORT);
+void pascal PCI_Interrupt_Steering(USHORT);
+void pascal Handle_EHCI_Wr(PCI_HEADER_ENTRY *);
+void pascal Handle_PCI_PM_Wr(PCI_HEADER_ENTRY *, USHORT);
+void pascal Update_Special_Cycles(USHORT);
+void Deallocate_Descriptor(DESCRIPTOR *);
+
+// External variable declarations:
+extern DESCRIPTOR MSRs[];
+extern ULONG ATA_Error;
+extern UCHAR Shift, AlignedReg, Function;
+extern PCI_HEADER_ENTRY * CommandPtr;
+extern PCI_HEADER_ENTRY * HdrPtr;
+extern VIRTUAL_DEVICE * IDSELs;
+extern Hardware HardwareInfo;
+
+
+//***********************************************************************
+// Writes an embedded PCI register
+//***********************************************************************
+void pascal Write_EPCI(UCHAR AlignedReg, ULONG Data)
+{ ULONG MsrAddr;
+
+ MsrAddr = MSRs[CommandPtr->Link].MsrAddr;
+ if (MsrAddr) {
+ (UCHAR)MsrAddr = AlignedReg/4;
+ Write_MSR_LO(MsrAddr, Data);
+ }
+}
+
+
+//***********************************************************************
+//
+// Handle changes to the COMMAND register
+//
+//***********************************************************************
+void pascal Update_Command(USHORT PreviousValue, USHORT NewValue)
+{ UCHAR Changes, EnableFlag;
+ register PCI_HEADER_ENTRY * Pci;
+ ULONG OldValue;
+
+ Changes = (UCHAR)(PreviousValue ^ NewValue);
+
+ //
+ // Handle changes to Special Cycles
+ //
+ if (Changes & SPECIAL_CYCLES) {
+ Update_Special_Cycles((UCHAR)NewValue & SPECIAL_CYCLES);
+ }
+
+
+ //
+ // Handle changes to bus master & address space enables
+ //
+ if (Changes & (IO_SPACE | MEM_SPACE | BUS_MASTER)) {
+
+ Pci = CommandPtr + 2;
+
+ // Walk through BAR entries & enable/disable corresponding descriptors/LBARs
+ do {
+
+ // Advance ptr to next implemented register
+ Pci++;
+
+ // Only concerned with allocated BARs
+ if (Pci->Flag & (MMIO_BAR | MEM_BAR | IO_BAR)) {
+
+ // Only write descriptors for BARs that have had resources allocated
+ // and have a non-zero value.
+ if ((Pci->Link) && Pci->Value) {
+
+ // Check correct Command bit according to BAR type
+ EnableFlag = (Pci->Flag & IO_BAR) ? IO_SPACE : MEM_SPACE;
+
+ // Handle changes to address space enable
+ if (Changes & EnableFlag) {
+ EnableFlag &= (UCHAR)NewValue;
+
+ // Update the descriptor(s)
+ OldValue = Pci->Value;
+ Update_BAR(Pci, EnableFlag);
+ Pci->Value = OldValue;
+ }
+
+
+ //
+ // Handle changes to bus master enable
+ //
+ if (Changes & BUS_MASTER) {
+ EnableFlag = (UCHAR)NewValue & BUS_MASTER;
+ if (Update_BusMaster(Pci, EnableFlag)) {
+ // Early-out (e.g. bridge)
+ Changes &= ~BUS_MASTER;
+ }
+ }
+ }
+ }
+
+ } while (!(Pci->Flag & EOL));
+ }
+
+}
+
+
+
+
+//***********************************************************************
+//
+// This routine implements writes to virtualized configuration space.
+//
+// NOTES:
+// 1) Misaligned accesses are handled. If an access crosses a DWORD
+// boundary, only the bytes within the addressed DWORD are written.
+// 2) The variable Pci points to a PCI_HEADER_ENTRY entry that defines
+// the state and behavior of the accessed register.
+//
+//***********************************************************************
+ULONG pascal Virtual_PCI_Write_Handler(USHORT PCI_Address, UCHAR Size, ULONG NewData)
+{ UCHAR EnableFlag;
+ ULONG Mask, Data, PreviousData;
+ register PCI_HEADER_ENTRY * Pci;
+
+
+ // Get ptr to virtualized table entry
+ Pci = Get_Structure(PCI_Address);
+
+ // Unimplemented function ?
+ if ((USHORT)Pci == UNIMPLEMENTED_FUNCTION) {
+ return NewData;
+ }
+
+ // Unimplemented register ?
+ if ((USHORT)Pci == UNIMPLEMENTED_REGISTER) {
+ // Removing an entire PCI function ?
+ if (AlignedReg == 0x7C && NewData == 0xDEADBEEF) {
+ UCHAR i, Link;
+ DESCRIPTOR * Descr;
+
+
+#if SUPPORT_CAPABILITIES
+ Pci = HdrPtr + BAR0/4;
+ do {
+ Pci++;
+ // If this device is PCI PM-aware...
+ if (Pci->Flag & PCI_PM) {
+ // then set device to D3
+ (UCHAR)PCI_Address = 0x44;
+ Virtual_PCI_Write_Handler(PCI_Address, BYTE_IO, 0x03);
+ break;
+ }
+ } while (!(Pci->Flag & EOL));
+#endif
+ // Make function unimplemented
+ IDSELs[Function] = 0x0000;
+
+ // Walk through all BARs and deallocate associated MSRs
+ Pci = HdrPtr + BAR0/4;
+ if (Pci->Reg != BAR0) {
+ return NewData;
+ }
+
+ for (i = BAR0; i <= BAR5; i += 4) {
+ if (Pci->Flag & (MMIO_BAR | MEM_BAR | IO_BAR)) {
+ Link = Pci->Link;
+
+ // For each linked item, update the associated MSR
+ while (Link) {
+ Descr = &MSRs[Link];
+
+ // Get link to next MSR
+ Link = Descr->Link;
+
+ // Deallocate the descriptor & set MSR to default value
+ Deallocate_Descriptor(Descr);
+ }
+ }
+ if (Pci->Flag & EOL) {
+ break;
+ }
+ Pci++;
+ }
+ }
+ return NewData;
+ }
+
+ // Save a copy of original value
+ PreviousData = Pci->Value;
+
+ //
+ // Generate mask to preserve read-only fields
+ //
+ switch (Size) {
+
+ case BYTE_IO:
+ Mask = 0x000000FF;
+ break;
+
+ case WORD_IO:
+ Mask = 0x0000FFFF;
+ break;
+
+ case DWORD_IO:
+ Mask = 0xFFFFFFFF;
+ break;
+
+ default:
+ Mask = 0x00000000;
+ break;
+ }
+ Mask = Pci->Mask & (Mask << Shift);
+
+
+ //
+ // Compute new register value
+ // - preserves R/O fields
+ // - handles misaligned accesses
+ // - handles accesses smaller than dword
+ //
+ NewData <<= Shift;
+ Data = (NewData & Mask) | (PreviousData & ~Mask);
+
+
+ //
+ // Record the new register value
+ //
+ Pci->Value = Data;
+
+
+ // Handle Write-to-Clear bits
+ if (NewData & Pci->WriteToClear) {
+ Pci->Value &= ~(NewData & Pci->WriteToClear);
+ }
+
+
+ //
+ // Update the MBus hardware
+ //
+ switch (AlignedReg) {
+
+ case COMMAND:
+
+ // Handle writes to Command register
+ if ((USHORT)PreviousData != (USHORT)Data) {
+ // If the Command register has changed, update the h/w
+ Update_Command((USHORT)PreviousData, (USHORT)Data);
+ }
+
+ // Handle writes to Status[15:11] (write-to-clear);
+ if (NewData &= Pci->WriteToClear) {
+ // Clear status bits in device's MSR
+ Clear_MBus_Error(Pci, NewData);
+ }
+
+ // Handle SMI on EHCI COMMAND write
+ if (Pci->Flag & PCI_EHCI) {
+ Handle_EHCI_Wr(Pci);
+ break;
+ }
+ break;
+
+ case CACHE_LINE:
+ // PCI Spec: if an unsupported Cache Line value is written, treat as 0x00
+ if ((UCHAR)Data ^ (UCHAR)Pci->Mask) {
+ Pci->CacheLineSize = 0x00;
+ }
+ Set_Latency((UCHAR)(Data >> 8));
+ break;
+
+
+
+ // Emulation of CS5530 software SMI mechanism
+ case SW_SMI: // 0xD0
+ SMINT_Handler((USHORT)Data);
+ break;
+
+ case (PCI_PM_REG+4): // 0x44
+#if SUPPORT_CAPABILITIES
+ if (Pci->Flag & PCI_PM) {
+ Handle_PCI_PM_Wr(Pci, (USHORT)PreviousData);
+ break;
+ }
+#endif
+ case IDE_CFG:
+ // Don't write IDE_CFG if this is a IDE-to-Flash switch
+ if (NewData == 0xDEADBEEF && Pci->LBar) {
+ return NewData;
+ }
+ case IDE_DTC: // 0x48
+ case IDE_CAST: // 0x4C
+ case IDE_ETC: // 0x50
+ // Thor ATA vendor-specific registers:
+ if (Pci->LBar) {
+ ULONG MsrAddr = ATA_Error;
+
+ (USHORT)MsrAddr = (USHORT)Pci->LBar;
+
+ // Sync with the current MSR value
+ PreviousData = Read_MSR_LO(MsrAddr);
+
+ // Update Thor ATA MSR with the new value
+ Pci->Value = (NewData & Mask) | (PreviousData & ~Mask);
+ Write_MSR_LO(MsrAddr, Pci->Value);
+ break;
+ }
+
+
+#if SUPPORT_CAPABILITIES
+ case BAR0:
+ case USBLEGCTLSTS:
+ case SRBN_REG:
+ if (Pci->Flag & PCI_EHCI) {
+ Handle_EHCI_Wr(Pci);
+ }
+#endif
+
+
+ default:
+ // Is it a BAR ?
+ if (Pci->Flag & (MMIO_BAR | MEM_BAR | IO_BAR)) {
+ // If value has changed, update the MBus descriptor
+ if (PreviousData != Data) {
+ // I/O BAR and Memory BAR ?
+ EnableFlag = (Pci->Flag & IO_BAR) ? IO_SPACE : MEM_SPACE;
+ EnableFlag &= (UCHAR)CommandPtr->Value;
+ Update_BAR(Pci, EnableFlag);
+ }
+ }
+ break;
+
+ } // end switch(AlignedReg)
+
+ return Pci->Value;
+}
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/port92.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/port92.asm
new file mode 100755
index 0000000..0fb9d74
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/port92.asm
@@ -0,0 +1,387 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+
+;*******************************************************************************
+;* Port 92h routines
+;*******************************************************************************
+
+
+include SYSMGR.INC
+include VSA2.INC
+include GX2.INC
+include CHIPSET.INC
+include CS5536.INC
+include ISA.INC
+include PCI.INC
+include MDD.INC
+include HCE.INC
+include SMIMAC.MAC
+
+.model tiny,c
+.586p
+.CODE
+
+
+externdef VSA_Exit: proc
+externdef MDD_Base: dword
+externdef FooGlue: dword
+externdef OHCI1_Smi: dword
+externdef OHCI2_Smi: dword
+externdef Nested_Flag: dword
+externdef Saved_EAX: dword
+externdef Saved_EBX: dword
+externdef Saved_ECX: dword
+externdef Saved_EDX: dword
+externdef Saved_ESI: dword
+externdef Saved_EDI: dword
+externdef Saved_EBP: dword
+externdef Saved_ESP: dword
+externdef IDT_Base: dword
+externdef IDT_Limit: dword
+externdef IDT_Selector: dword
+externdef SMI_Sources: dword
+externdef SMM_Header: SmiHeader
+externdef Saved_SS: Descriptor
+externdef Data_Descriptor: Descriptor
+externdef HardwareInfo: Hardware
+
+
+
+
+
+;***********************************************************************
+;
+; A20_Sync - synchronize port 92h and virtual A20 pin
+;
+;***********************************************************************
+A20_Sync proc uses si edi
+
+ ; Determine if it is a nested access to port 92h
+ btr word ptr [Nested_Flag], SMI_SRC_A20_INDEX
+ jc short Get_A20_Data
+ rsdc gs, cs:[Data_Descriptor]
+Get_A20_Data:
+ ASSUME SI: ptr SmiHeader
+ mov si, OFFSET VSM_Header.SysStuff.State
+ mov bl, byte ptr gs:[si].write_data ; Get I/O data
+ mov si, gs:[si].IO_addr ; Get I/O address
+ ASSUME SI:NOTHING
+
+ ; Set A20M in FooGlue appropriately
+ mov ecx, [FooGlue]
+ add cx, FG_A20M
+ rdmsr
+ and al, NOT A20M ; A20M = 0
+
+ and bl, 02h ; Check A20M setting
+ jnz short Set_A20
+ or al, A20M ; Force A20 low
+Set_A20:
+ wrmsr
+
+ cmp si, 0092h ; If port 92h, no update necessary
+ je short SyncHceControl
+
+ cmp si, KYBD_DATA ; If not 8042 data port, ignore
+ jne Return
+
+ ; Sync Port 92h to keyboard controller
+ mov ecx, [MDD_Base] ; Disable Port 92h trapping
+ mov cx, MBD_MSR_SMI
+ rdmsr
+ push ax
+ and al, NOT A20_P_EN
+ wrmsr
+
+ mov al, bl ; Update Port 92h A20 state
+ out 92h, al
+
+ pop ax ; Restore Port 92h trapping
+ wrmsr
+
+ ; Synchronize HceControl[A20State] with port 92h
+SyncHceControl:
+ mov ecx, [OHCI1_Smi] ; Read OHCI1 h/w BAR0
+ test ecx, 0FFF00000h
+ jnz short Get_HC_Base
+ mov ecx, [OHCI2_Smi] ; Use OHCI2 if OHCI1 not used
+ test ecx, 0FFF00000h
+ jz Return
+Get_HC_Base:
+ mov cx, 1000h + BAR0/4 ; 5536 Embedded PCI MSR
+ cmp [HardwareInfo].Chipset_ID, DEVICE_ID_5536
+ je short ReadBAR
+ mov cx, USBMSROHCB ; 5536 OHCI MSR
+ReadBAR:
+ rdmsr
+
+ mov bh, 0 ; Clear MSR restore flag
+ or eax, eax ; Is BAR initialized ?
+ jnz short SyncA20State
+ mov bh, 1 ; Set MSR restore flag
+
+ push eax ; Save current OHCI MSR
+ push edx
+ push ecx
+
+ ; OHCI BAR is not initialized or OHCI header is hidden.
+ ; Temporarily map the OHCI register set just above VSA
+ ; This range has been declared as OS-reserved in INT 15h E820h
+ mov ecx, MSR_RCONF_SMM
+ rdmsr
+ lea edi, [edx+1000h]
+ pop ecx
+ push ecx
+
+ mov edx, 00000000Eh
+ mov eax, edi
+ wrmsr
+
+ mov ecx, [MDD_Base]
+ mov cx, MSR_LBAR_KEL1
+ rdmsr
+ push eax ; Save current KEL LBAR
+ push edx
+ push ecx
+ mov eax, edi
+ mov edx, 0FFFFF001h
+ wrmsr
+
+ ; Synchronize HceControl.A20State
+SyncA20State:
+ or ax, OFFSET (HCOR Ptr ds:[0]).HceControl
+ mov dx, fs:[eax]
+ cmp dx, 0FFFFh ; Is Memory Space enabled ?
+ je short Exit
+CLEAR_A20 equ (A20_STATE OR IRQ1_ACTIVE OR IRQ12_ACTIVE)
+ ; SWAPSiF for SiBZ 3509/3571: KEL SMIs are level instead of edge-triggered
+ ; Manifests itself as PBZ 3878: PS/2 keyboard hangs after running PCIDIAG
+ test dx, (IRQ1_ACTIVE OR IRQ12_ACTIVE)
+ jz short NoIRQ
+ or [SMI_Sources], SMI_SRC_KEL ; Fake another KEL SMI
+NoIRQ:
+ and dx, NOT CLEAR_A20 ; Clear A20State
+ test bl, 02h
+ jz Update_HceControl
+ or dx, A20_STATE ; Set A20State
+Update_HceControl:
+ mov fs:[eax], dx
+
+Exit:
+ or bh, bh ; Do OHCI MSRs need to be restored?
+ je short Return
+
+ pop ecx ; Restore KEL LBAR
+ pop edx
+ pop eax
+ wrmsr
+
+ pop ecx ; Restore OHCI MSR
+ pop edx
+ pop eax
+ wrmsr
+Return:
+ ret
+
+A20_Sync endp
+
+
+
+
+
+
+
+;***********************************************************************
+; Sets the top-level RSM state to the reset state:
+; 1) Real-mode IDT
+; 2) Real-mode descriptors; segment regisers = 0000
+; 3) CS:EIP = F000:FFF0
+; 4) CS base = FFFF0000
+; 5) CS limit = 64K
+; 6) DX = CPU ID
+;***********************************************************************
+set_reset_state proc uses si
+
+ ; Check if user code is doing a 286-style shutdown
+ in al, CMOS_INDEX ; Preserve CMOS index
+ mov ah, al
+
+ mov al, 0Fh
+ out CMOS_INDEX, al
+ in al, CMOS_DATA
+
+ xchg al, ah
+ out CMOS_INDEX, al ; Restore CMOS index
+
+ cmp ah, 09H
+ je UserShutdown
+
+ cmp ah, 05H
+ je UserShutdown
+
+ cmp ah, 0AH
+ je UserShutdown
+
+ cmp ah, 0FFH ; JMP if no CMOS present
+ je UserShutdown
+
+
+
+
+
+CACHE_LINE_SIZE equ 32
+
+ ; If cache is disabled, there is no way to guarantee that
+ ; the entire code sequence from DisableCKE to Pre_Fetch
+ ; will be fetched before CKE is disabled. It was decided
+ ; we'd rather see the original POST 0xBF hang rather than
+ ; a hang in SMM.
+ mov ebp, [MDD_Base] ; Prepare reset MSR
+ mov bp, MSR_SOFT_RESET
+ mov eax, CR0 ; Is cache disabled ?
+ test eax, 40000000h
+ jnz Reset
+
+ lea si, [DisableCKE] ; Move code to start of a cache line
+ mov di, si
+ and di, NOT (CACHE_LINE_SIZE-1)
+ mov bx, di ; Remember where we moved it to
+ cld
+@@: lodsd
+ mov [di], eax
+ add di, 4
+ cmp si, OFFSET Pre_Fetch
+ jb @b
+
+ mov ecx, 2000001Dh ; Memory controller
+ rdmsr
+ or ah, 3 ; Set CKE Mask = 11b
+
+ jmp Pre_Fetch
+
+
+
+ ; Bug #118.226 - Some DIMMs hang at POST 0xBF on a reboot
+ ;
+ ; Need to de-assert CKE off before command signals are tri-stated.
+ ; There can be no memory accesses after the following WRMSR.
+ ; If cache is disabled, there is no way to satisfy this condition,
+ ; so some DIMMs with cache disabled is not supported with
+ ; respect to resets.
+ db CACHE_LINE_SIZE dup (90h)
+DisableCKE:
+ wrmsr
+
+ ; Reset the CPU via MDD MSR_SOFT_RESET
+Reset: mov ecx, ebp
+ mov al, 1
+ wrmsr
+ jmp $
+Pre_Fetch:
+ ; Prefetch 4 cache lines of NOPs so there won't be any
+ ; prefetching to memory after the MC MSR is written.
+ db 4*CACHE_LINE_SIZE dup (90h) ; 4 cache lines
+ jmp bx
+
+UserShutdown:
+
+ mov ecx, [FooGlue] ; Disable A20 mask
+ add cx, FG_A20M
+ rdmsr
+ and al, NOT A20M ; A20M = 0
+ wrmsr
+
+ ; Disable the cache & flush it
+ mov eax, CR0
+ or eax, 60000000h
+ mov CR0, eax
+ wbinvd
+
+ ; Set real-mode IDT
+ mov [IDT_Limit], 0FFFFh ; Limit
+ mov [IDT_Base], 00000000h ; Base
+ mov [IDT_Selector], 00920000h ; Selector & Attributes
+
+
+ ; INIT is broken on LX 2.x and 3.0
+ cmp [HardwareInfo].CPU_ID, DEVICE_ID_LX
+ jne short Set_INIT
+ mov ax, [HardwareInfo].CPU_Revision
+ cmp al, 30h ; Is it 3.0?
+ jae short FakeInit
+ and al, 0F0h ; Is it 2.x?
+ cmp al, 20h
+ je short FakeInit
+
+ call VSA_Exit
+
+ ; Reset via INIT MSR
+Set_INIT:
+ mov ecx, [FooGlue] ; Reset the CPU
+ add cx, FG_INIT
+ xor eax, eax
+ wrmsr
+ mov al, INIT
+ wrmsr
+
+ ; Fake an INIT by setting up initial CPU state
+FakeInit:
+ lea si, [Saved_SS] ; Set descriptors to 64K real-mode
+ mov cx, 5 ; # descriptors to fill
+ mov eax, 0000FFFFh ; limit_15_0 & base_15_0
+DescrLoop:
+ mov [si+0], eax ; limit_15_0 & base_15_0
+ mov dword ptr [si+4], 00009200h ; base_23_16, attr, limit_19_16 & base_31_24
+ mov word ptr [si+8], 0000h ; selector
+ add si, sizeof (Descriptor) ; Advance ptr to next descriptor
+ loop DescrLoop
+
+
+ ; Set top-level SMM header to reset state
+ mov bx, OFFSET SMM_Header
+ ASSUME BX: PTR SmiHeader
+ mov [bx]._CS.limit, eax
+ mov [bx]._CS.base, 0FFFF0000h
+ mov [bx]._CS.selector, 0F000h
+ mov [bx]._CS.attr, 92h
+
+ mov [bx].Next_EIP, 0000FFF0h
+ mov [bx].r_CR0, 60000010h ; Real-mode; cache disabled
+ mov [bx].r_DR7, 00000400h
+ mov [bx].EFLAGS, 00000002h
+ mov [bx].SMI_Flags, 8001h ; CS is R/W
+
+ mov [bx].SS_Flags, DATA_ATTR
+
+ ; Initialize general purpose register
+ mov [Saved_EDX], 00000540h ; CPU ID
+ xor eax, eax
+ mov [Saved_EAX], eax
+ mov [Saved_EBX], eax
+ mov [Saved_ECX], eax
+ mov [Saved_EDI], eax
+ mov [Saved_ESI], eax
+ mov [Saved_EBP], eax
+ mov [Saved_ESP], eax
+
+ ret
+
+set_reset_state endp
+
+ end
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/protos.h b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/protos.h
new file mode 100755
index 0000000..a463a07
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/protos.h
@@ -0,0 +1,91 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+typedef unsigned short EVENT;
+typedef unsigned short MSG;
+typedef unsigned short PRIORITY;
+typedef unsigned long VSM;
+typedef void (* GPIO_FUNCTION)(unsigned long, unsigned long, unsigned char);
+
+
+
+void pascal out_8(unsigned short, unsigned char);
+void pascal out_16(unsigned short, unsigned short);
+void pascal out_32(unsigned short, unsigned long);
+unsigned char pascal in_8(unsigned short);
+unsigned short pascal in_16(unsigned short);
+unsigned long pascal in_32(unsigned short);
+
+void pascal Hex_8(unsigned char);
+void pascal Hex_16(unsigned short);
+void pascal Hex_32(unsigned long);
+
+
+
+extern void pascal Trap_PCI_IDSEL(unsigned short, unsigned char);
+extern unsigned char pascal Init_Descr(unsigned char, unsigned long);
+extern unsigned char pascal BitScanReverse(unsigned long);
+extern unsigned char pascal BitScanForward(unsigned long);
+extern unsigned long pascal read_flat(unsigned long);
+extern unsigned long pascal Read_MSR_LO(unsigned long);
+extern unsigned long pascal Read_MSR_HI(unsigned long);
+extern unsigned long pascal Virtual_PCI_Read_Handler(unsigned short);
+extern unsigned long pascal GetFlink(unsigned long);
+extern unsigned char pascal Get_VSM_Type(unsigned long);
+extern unsigned char pascal IsPowerOfTwo(unsigned long);
+extern unsigned short pascal Send_Event(EVENT, VSM);
+extern unsigned char pascal Find_Matching_IO_Descriptor(unsigned long *, unsigned short *, unsigned char);
+extern unsigned char pascal Setup_IO_Descriptor(unsigned long *, unsigned short *, unsigned char);
+extern void pascal Init_MBIU(unsigned char *, unsigned long);
+extern void pascal Get_Descriptor_Default(unsigned char, unsigned long *);
+extern unsigned long pascal Virtual_PCI_Write_Handler(unsigned short, unsigned char, unsigned long);
+extern void pascal write_flat(unsigned long, unsigned long);
+extern void pascal Read_MSR(unsigned long, unsigned long *);
+extern void pascal Write_MSR(unsigned long, unsigned long *);
+extern void pascal Write_MSR_LO(unsigned long, unsigned long);
+extern void pascal Write_MSR_HI(unsigned long, unsigned long);
+extern void pascal Store_Timestamp(void *);
+extern void pascal Schedule_VSM(unsigned long);
+extern void pascal Report_Error(unsigned char, unsigned long, unsigned long);
+extern void pascal Report_VSM_Error(unsigned char, unsigned long, unsigned long);
+extern void pascal Send_Message(VSM, VSM, unsigned long);
+extern void pascal Broadcast_Message(MSG, unsigned short, unsigned long);
+extern void pascal Register_Event(EVENT, PRIORITY, VSM, unsigned long, unsigned long);
+extern void pascal Enable_Event(EVENT, unsigned short, unsigned char);
+extern void pascal Disable_Event(EVENT, unsigned short);
+extern void pascal Unregister_VSM_Events(VSM);
+
+extern void pascal IRQY_Mapper(unsigned char, unsigned char);
+extern void pascal IRQZ_Mapper(unsigned char, unsigned char);
+
+
+extern void Keep_History(EVENT, EVENT);
+extern unsigned short pascal Unregister_Event(EVENT, VSM, unsigned long, unsigned long);
+extern unsigned short pascal Allocate_BAR(unsigned char, unsigned short, unsigned long, unsigned short, unsigned short);
+
+extern unsigned long Current_VSM;
+extern unsigned long SysMgr_VSM;
+
+
+extern void Log_Error(const char *format, ...);
+extern unsigned long pascal Compute_IOD_SC(unsigned long *, unsigned short *, unsigned char);
+extern void pascal MBus_IO_Trap(unsigned long, unsigned long, unsigned char);
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/smimac.mac b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/smimac.mac
new file mode 100755
index 0000000..7d73bc6
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/smimac.mac
@@ -0,0 +1,209 @@
+;
+; Copyright (c) 2006 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+
+
+smint macro
+ db 0Fh, 38h
+ endm
+
+
+
+EREG macro Reg
+ ifidni <Reg>, <eax>
+ db 0C8h
+ elseifidni <Reg>, <ecx>
+ db 0C9h
+ elseifidni <Reg>, <edx>
+ db 0CAh
+ elseifidni <Reg>, <ebx>
+ db 0CBh
+ elseifidni <Reg>, <esp>
+ db 0CCh
+ elseifidni <Reg>, <ebp>
+ db 0CDh
+ elseifidni <Reg>, <esi>
+ db 0CEh
+ elseifidni <Reg>, <edi>
+ db 0CFh
+ else
+ .err
+
+ endif
+
+ endm
+
+
+RDSHR macro Reg
+ db 0Fh, 36h
+ EREG Reg
+ endm
+
+WRSHR macro Reg
+ db 0Fh, 37h
+ EREG Reg
+ endm
+
+
+
+
+
+MOV_EAX_CR4 macro
+ db 0Fh, 20h, 0E0h ; mov eax, CR4
+ENDM
+
+MOV_CR4_EAX macro
+ db 0Fh, 22h, 0E0h ; mov CR4, eax
+ENDM
+
+
+
+
+
+
+
+
+
+
+
+SMM_Instr macro Reg:REQ, Addr:REQ, Opcode:REQ
+ Local Place1, Place2, Attr, InstrLen
+
+
+
+Place1:
+
+
+ ifidni <Reg>, <ES>
+ LFS ax, dword ptr Addr
+ elseifidni <Reg>, <SS>
+ LFS dx, dword ptr Addr
+ elseifidni <Reg>, <DS>
+ LFS bx, dword ptr Addr
+ elseifidni <Reg>, <FS>
+ LFS sp, dword ptr Addr
+ elseifidni <Reg>, <GS>
+ LFS bp, dword ptr Addr
+ elseifidni <Reg>, <CS>
+ LFS cx, dword ptr Addr
+ else
+ .err "Error in RSDC macro"
+ endif
+
+Place2:
+
+Extras = 1
+SegOverride INSTR <Addr>, <:>
+if SegOverride
+ Extras = Extras + 1
+endif
+
+AddrOverride INSTR <Addr>, <eax>
+if AddrOverride
+ Extras = Extras + 1
+else
+ AddrOverride INSTR <Addr>, <EAX>
+ if AddrOverride
+ Extras = Extras + 1
+ else
+ AddrOverride INSTR <Addr>, <ebx>
+ if AddrOverride
+ Extras = Extras + 1
+ else
+ AddrOverride INSTR <Addr>, <EBX>
+ if AddrOverride
+ Extras = Extras + 1
+ else
+ AddrOverride INSTR <Addr>, <ecx>
+ if AddrOverride
+ Extras = Extras + 1
+ else
+ AddrOverride INSTR <Addr>, <ECX>
+ if AddrOverride
+ Extras = Extras + 1
+ else
+ AddrOverride INSTR <Addr>, <edx>
+ if AddrOverride
+ Extras = Extras + 1
+ else
+ AddrOverride INSTR <Addr>, <EDX>
+ if AddrOverride
+ Extras = Extras + 1
+ else
+ AddrOverride INSTR <Addr>, <esi>
+ if AddrOverride
+ Extras = Extras + 1
+ else
+ AddrOverride INSTR <Addr>, <ESI>
+ if AddrOverride
+ Extras = Extras + 1
+ else
+ AddrOverride INSTR <Addr>, <edi>
+ if AddrOverride
+ Extras = Extras + 1
+ else
+ AddrOverride INSTR <Addr>, <EDI>
+ if AddrOverride
+ Extras = Extras + 1
+ endif
+ endif
+ endif
+ endif
+ endif
+ endif
+ endif
+ endif
+ endif
+ endif
+ endif
+endif
+
+ ORG Place1 + Extras
+ db Opcode
+ ORG Place2
+
+ endm
+
+svdc macro Addr:REQ, Reg:REQ
+ SMM_Instr Reg, Addr, 78h
+ endm
+
+rsdc macro Reg:REQ, Addr:REQ
+ SMM_Instr Reg, Addr, 79h
+ endm
+
+
+svldt macro Addr:REQ
+ SMM_Instr <ES>, Addr, 7Ah
+ endm
+
+
+rsldt macro Addr:REQ
+ SMM_Instr <ES>, Addr, 7Bh
+ endm
+
+svts macro Addr:REQ
+ SMM_Instr <ES>, Addr, 7Ch
+ endm
+
+
+rsts macro Addr:REQ
+ SMM_Instr <ES>, Addr, 7Dh
+ endm
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/smis.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/smis.asm
new file mode 100755
index 0000000..007f6a6
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/smis.asm
@@ -0,0 +1,354 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;********************************************************************************
+;* This file contains the code for reading the source of SMIs.
+;********************************************************************************
+
+
+include GX2.INC
+include VSA2.INC
+include SYSMGR.INC
+include CS5536.INC
+include CHIPSET.INC
+include MDD.INC
+include PCI.INC
+
+.model tiny,c
+.586p
+.CODE
+ASSUME DS:_TEXT
+
+SYNCHRONOUS equ (SMI_SRC_PCI_TRAP OR SMI_SRC_DESCR_HIT OR SMI_SRC_PM OR SMI_SRC_RESET OR SMI_SRC_BLOCKIO OR SMI_SRC_A20)
+SMI_Sources dd 0
+Video_Sources dd 0
+Audio_Sources dw 0
+Stats_Sources dd 0
+SynchEvents dd SYNCHRONOUS
+HiPrioritySMIs dd SMI_SRC_AUDIO OR SMI_SRC_USB1 OR SMI_SRC_USB2
+
+public SynchEvents, HiPrioritySMIs
+public SMI_Sources, Audio_Sources, Stats_Sources, Video_Sources
+
+externdef pascal Hex_8:proc
+externdef pascal Hex_16:proc
+externdef pascal Hex_32:proc
+externdef pascal Generate_IRQ_5536: proc
+
+externdef SMI_Base: dword
+externdef Mbiu0: dword
+externdef Mbiu1: dword
+externdef Mbiu2: dword
+externdef MPCI_NB: dword
+externdef MPCI_SB: dword
+externdef MDD_Base: dword
+externdef MCP_NB: dword
+externdef ATA_Error: dword
+externdef OHCI1_Smi: dword
+externdef OHCI2_Smi: dword
+externdef HardwareInfo: Hardware
+
+
+
+;*************************************************************************
+; Installs the SMI routine(s) appropriate to the chipset.
+; The default routine(s) are for CS5536.
+;*************************************************************************
+Install_SMI_Routines proc
+
+ ;5536 already set, do nothing. mov [OHCI_SMI], OHCSSTAT
+Exit: ret
+
+Install_SMI_Routines endp
+
+
+
+
+;************************************************************************
+; Asserts/deasserts internal IRQs
+; On Entry:
+; ECX = IRQ mask
+; 16 LSBs - enable
+; 16 MSBs - disable
+;************************************************************************
+Generate_IRQ proc
+
+ push cx
+ call word ptr [IRQ_Routine]
+ ret
+
+IRQ_Routine::
+ dw OFFSET Generate_IRQ_5536
+
+Generate_IRQ endp
+
+
+
+
+;*************************************************************************
+; Reads & clears all SMI source registers (MSRs & Southbridge)
+; On Exit:
+; EBX = SMI sources
+; All other registers may be destroyed
+;*************************************************************************
+Get_SMI_Sources proc
+
+ mov ebx, [SMI_Sources] ; Get SMIs that have not yet been handled
+ call Get_Northbridge_SMIs
+ or ebx, ebx ; If any NB SMIs, handle them quickly
+ jz short Get_SB_SMIs
+ ret
+Get_SB_SMIs:
+
+ jmp word ptr [SMI_Routine] ; Get Southbridge SMI(s)
+
+SMI_Routine::
+ dw OFFSET Get_5536_SMIs
+
+Get_SMI_Sources endp
+
+
+
+
+
+
+
+
+
+
+
+;***********************************************************************
+; Gets SMI sources from Northbridge
+; On Entry:
+; EBX = pending SMI sources
+; NOTES:
+; - May set SMI source bits in EBX.
+;***********************************************************************
+MPCI_ERROR equ (MARE + TARE + PARE + BME + SYSE)
+VGA_BLANK equ 08h
+VG_BLANK equ 01h
+VERT_BLANK equ (VGA_BLANK OR VG_BLANK)
+
+Get_Northbridge_SMIs proc
+
+ mov ecx, [MPCI_NB] ; MBIU1.MPCI.0.0.0.0
+ mov cx, MBD_MSR_SMI
+ rdmsr
+ wrmsr ; Clear the MPCI SMI event(s)
+
+ mov dl, al ; Only record enabled events
+ not dl
+ shr eax, 16
+ and al, dl ; Only consider unmasked events
+ jz short Graphics_SMIs ; Jmp if no MPCI SMI is pending
+
+ test al, VPHE SHR 16 ; Is it a virtualized PCI header ?
+ jz short CheckMPCI
+ or ebx, SMI_SRC_PCI_TRAP ; Yes, record the event
+
+ cmp al, VPHE SHR 16 ; Is VPHE the only SMI pending ?
+ je short Exit ; Yes, do a quick exit
+
+
+CheckMPCI:
+ test ax, MPCI_ERROR SHR 16 ; Is it an MPCI error ?
+ jz short Graphics_SMIs
+ or ebx, SMI_SRC_MPCI ; Yes
+
+ mov cx, MBD_MSR_ERROR ; Clear the MPCI error(s)
+ rdmsr
+ wrmsr
+
+
+
+
+
+ ;*******************************************
+ ; Check for graphics SMIs
+ ;*******************************************
+
+; Value in Video_Sources:
+;
+; Bit Description
+; ----- -----------------------------------
+; 0 DF: SMI #1 (TBD)
+; 1 DF: SMI #2 (TBD)
+; 2 GP: SMI (address or type violation)
+; 3 reserved
+; 4 VG: Miscellaneous Output SMI
+; 5 VG: Input Status register SMI
+; 6 reserved
+; 7 VG: CRTC invalid I/O SMI
+Graphics_SMIs:
+ ; Video Generator
+ mov ecx, VG_SMI_MSR
+ rdmsr
+ wrmsr ; Clear SMI(s)
+
+ ; Because the VG records all events that occur in the upper half of the MSR
+ ; regardless of whether or not they generate SMIs, we need to clear out the
+ ; events that aren't generating SMIs and only look for valid ones.
+ not eax ; NOT the SMI mask
+ and edx,eax ; Clear out untrapped events
+
+ test dl, VERT_BLANK ; Is a vertical blank pending ?
+ jz short SaveVideoSources
+ and dl, NOT (VERT_BLANK)
+ or ebx, SMI_SRC_RETRACE ; Yes, record EVENT_VBLANK
+SaveVideoSources:
+ or [Video_Sources], edx
+ jz short Statistic_SMIs
+ or ebx, SMI_SRC_VG ; Yes, then record EVENT_GRAPHICS
+
+
+ ;*******************************************
+ ; Check for Statistic Counter SMI(s)
+ ;*******************************************
+Statistic_SMIs:
+ mov ecx, [Mbiu0] ; Check MBIU0 Statistics Counters
+ call Get_MBD_SMIs
+ or byte ptr [Stats_Sources+0], dl
+
+ mov ecx, [Mbiu1] ; Check MBIU1 Statistics Counters
+ call Get_MBD_SMIs
+ or byte ptr [Stats_Sources+1], dl
+Exit:
+ ret
+
+Get_Northbridge_SMIs endp
+
+
+
+
+;***********************************************************************
+; Checks for events in MBD_MSR_SMI:
+; - descriptor traps
+; - statistic counters
+; On entry: ECX = base address of GLIU
+; Returns: DL = statistic event mask
+;***********************************************************************
+Get_MBD_SMIs proc
+
+ mov cx, MBD_MSR_ERROR ; Clear errors
+ rdmsr
+ wrmsr
+
+ mov cx, MBD_MSR_SMI
+ rdmsr
+
+ and dl, 1Fh ; Any SMIs pending ?
+ jz short Exit ; No, just exit
+ wrmsr
+
+ btr dx, 0 ; Is it a MBIU descriptor hit ?
+ jnc short StatCntrs
+ or ebx, SMI_SRC_DESCR_HIT ; Yes
+
+StatCntrs:
+ or dl, dl ; Any hits on statistic counters ?
+ jz short Exit
+ or ebx, SMI_SRC_STAT ; Yes, record the event
+ or al, dl ; Disable further events
+
+ wrmsr
+
+ shr dl, 1
+Exit:
+ ret
+
+Get_MBD_SMIs endp
+
+
+
+
+
+
+
+;*************************************************************************
+; Reads and clears CS5536 SMI source registers
+;*************************************************************************
+Get_5536_SMIs proc
+
+ mov ecx, [MDD_Base] ; Check for MDD SMIs
+ mov cx, MBD_MSR_SMI
+ rdmsr
+ wrmsr ; Clear any pending SMI(s)
+ or dx, dx ; Any MDD SMIs pending ?
+ jz short Get_MPCI_SB ; No
+
+ xor eax, eax
+MDD_Loop:
+ bsf ax, dx ; Determine next pending event
+ jz Exit
+ btr dx, ax ; Clear the status bit
+ or ebx, dword ptr [eax*4+MDD_Sources]
+ jmp short MDD_Loop
+
+
+ ; MDD SMI sources
+MDD_Sources:
+ dd 0 ; HLT_ASMI_STAT
+ dd 0 ; SHUTDOWN_ASMI_STAT
+ dd SMI_SRC_KEL ; KEL_ASMI_STAT
+ dd SMI_SRC_PIC ; PIC_ASMI_STAT
+ dd SMI_SRC_PME ; PM_ASMI_STAT
+ dd SMI_SRC_RESET ; INIT_K_STAT
+ dd SMI_SRC_A20 ; A20_P_STAT
+ dd SMI_SRC_RESET ; INIT_P_STAT
+ dd 0 ; UART1_SSMI_STAT
+ dd 0 ; UART2_SSMI_STAT
+ dd 0 ; RESERVED_STAT
+ dd 0 ; LPC_SSMI_STAT
+ dd 0 ; DMA_SSMI_STAT
+ dd SMI_SRC_A20 ; A20_K_STAT
+ dd SMI_SRC_ACPI ; PM2_CNT_SSMI_STAT
+ dd SMI_SRC_ACPI ; PM1_CNT_SSMI_STAT
+
+
+
+Get_MPCI_SB:
+ mov ecx, [MPCI_SB] ; Get Southbridge MPCI events
+ mov cx, MBD_MSR_SMI
+ rdmsr
+ wrmsr ; Clear any pending SMI(s)
+
+ mov ecx, [Mbiu2] ; Check for MBIU2 SMIs
+ call Get_MBD_SMIs
+ or byte ptr [Stats_Sources+2], dl
+
+ mov ecx, [OHCI1_Smi] ; Check for USB #1 SMIs
+ jcxz short Exit
+ rdmsr
+ test dl, [OHCI_SMI] ; OHCI SMI pending ?
+ jz short Exit ; JMP if not
+ wrmsr ; Yes, clear the SMI
+ or ebx, SMI_SRC_USB1 ; Record the SMI event
+
+Exit: ret
+
+Get_5536_SMIs endp
+
+
+OHCSSTAT equ 10h ; 5536
+OHCI_SMI db OHCSSTAT ; Assume 5536; could patched by Install_SMI_Routines() if other
+
+
+
+
+ end
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/sw_int.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/sw_int.asm
new file mode 100755
index 0000000..33d113c
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/sw_int.asm
@@ -0,0 +1,502 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;********************************************************************************
+;* Implementation of BIOS callbacks
+;********************************************************************************
+
+
+include SYSMGR.INC
+include VSA2.INC
+include SMIMAC.MAC
+include GX2.INC
+include ISA.INC
+
+.model tiny,c
+.586p
+.ALPHA
+DGROUP GROUP _CODE, _TEXT
+_CODE SEGMENT PUBLIC use16 'CODE'
+ ASSUME DS:_CODE
+
+public VSM_Buffer
+
+SMINT_SEGMENT equ 0E000h ; Segment to store SMINT instruction & ISR stack
+ALLOW_SMM_SEGMENTS equ 0 ; 1 = ES segment allowed to point to SMM memory
+
+
+externdef pascal Report_VSM_Error: proc
+externdef pascal Schedule_VSM: proc
+externdef Sys_Exit: proc
+externdef pascal Hex_8: proc
+externdef pascal Hex_16: proc
+externdef pascal Hex_32: proc
+
+externdef BracketFlag: byte
+externdef SchedulerStack: word
+externdef INT_Vectors: dword
+externdef Current_VSM: dword
+externdef StartSaveArea: dword
+externdef EndSaveArea: dword
+externdef SysMgr_VSM: dword
+externdef Header_Addr: dword
+externdef SMM_Header: SmiHeader
+
+;************************************************************************
+; Implements the SYS_STATE macro
+;
+; Input:
+; CX = Flag: 0 = Save 1 = Restore
+; EDI = Offset to VSM's register buffer
+; DS = System Manager's data segment
+;************************************************************************
+Sys_State proc
+
+ cld
+ mov eax, [Current_VSM] ; Create flat ptr to calling VSM
+ add edi, eax
+
+ push eax ; Re-schedule the calling VSM
+ call Schedule_VSM
+
+
+ lea esi, [StartSaveArea]
+ add esi, [SysMgr_VSM]
+
+ jcxz CopyState ; Save or Restore ?
+
+ xchg esi, edi ; Restore
+
+ ; Copy the non-SMM state
+CopyState:
+ mov ecx, OFFSET EndSaveArea
+ sub cx, OFFSET StartSaveArea
+ shr cx, 1
+
+ rep movsw [edi], fs:[esi]
+ jmp Sys_Exit
+
+Sys_State endp
+
+
+
+
+;************************************************************************
+; Implements the SYS_SW_INTERRUPT macro
+;
+; Input:
+; EBX = 4 * INT number
+; ECX = Offset to VSM's register buffer
+;************************************************************************
+Sys_SW_INT proc
+
+ cld
+ mov esi, [Current_VSM]
+ push esi ; Re-schedule the calling VSM
+ call Schedule_VSM
+
+ cmp bx, 4*MAX_INT ; Validate INT vector
+ ja Unsupported_INT
+ mov edx, [INT_Vectors+bx]
+ or edx, edx
+ jz Illegal_INT
+
+ mov [Saved_INT], ebx ; Save current vector &
+ mov edi, edx ; patch with the original vector
+ xchg fs:[ebx], edi
+ mov [Saved_Vector], edi
+
+ xor edi, edi ; Don't allow calling VSM to execute
+ push edi
+ call Schedule_VSM
+
+ ASSUME di:PTR VSM_Header ; Mark the requesting VSM blocked
+ mov gs:[di].SysStuff.RunFlag, RUN_FLAG_BLOCKED
+
+
+ ; Handle PIC masks
+ in al, PIC1_MASK ; Save PIC masks & set user-defined masks
+ mov ah, al
+ in al, PIC2_MASK
+ mov [Saved_PIC], ax
+
+ ASSUME di:PTR INT_REGS
+ mov di, cx
+ mov ax, word ptr gs:[di].PIC0_Mask
+ not ax ; PIC masks are 0=enable
+ cmp ah, 0FFh ; Any PIC1 IRQs enabled ?
+ je short SetPIC
+ and al, NOT 04h ; Yes, enable IRQ2
+SetPIC:
+ or al, 01h ; Always disable IRQ0
+ out PIC1_MASK, al
+ mov al, ah
+ out PIC2_MASK, al
+
+ cmp ax, 0FFFFh ; Are any IRQs enabled ?
+ je short RealMode
+ or gs:[di].Flags, EFLAGS_IF ; Yes, enable interrupts
+
+ ;
+ ; Initialize real-mode state
+ ;
+RealMode:
+ mov ax, gs:[di].Reg_ES ; Set up ES descriptor
+ push OFFSET BIOS_ES
+ call Set_Descriptor
+
+ mov ax, gs:[di].Reg_DS ; Set up DS descriptor
+ push OFFSET BIOS_DS
+ call Set_Descriptor
+
+ add esi, ecx ; Create flat ptr to calling VSM's registers
+ mov [VSM_Buffer], esi
+
+
+ ASSUME di:PTR SmiHeader
+
+ lea edi, [BIOS_Header] ; Set up CS descriptor & Next_EIP
+ mov word ptr [di].SS_Flags, DATA_ATTR
+ mov [di].SMI_Flags, SMI_FLAGS_CS_WRITABLE + SMI_FLAGS_CS_READABLE
+ mov word ptr [di].Next_EIP, dx ; IP
+ shr edx, 16 ; Convert segment to linear address
+ mov [di]._CS.selector, dx ; CS selector
+ shl edx, 4
+ mov [di]._CS.base, edx ; CS descriptor
+ mov [di]._CS.limit, 0FFFFh
+ mov [di]._CS.attr, CODE_ATTR ; CS attribute
+ mov eax, CR0 ; Preserve the CD & NW bits
+ and eax, 60000000h
+ or eax, VSM_CR0
+ mov [di].r_CR0, eax
+
+if ALLOW_SMM_SEGMENTS
+ mov ecx, MSR_RCONF_SMM ; Make SMM memory writeable by interrupt code
+ rdmsr
+ mov [OldRCONF], al
+ and al, NOT REGION_WP
+ wrmsr
+endif
+
+ ASSUME DI: NOTHING
+
+
+
+ mov ecx, 1000002Ch ; Save P2D_SC value & make UMBs R/W
+ rdmsr
+ mov [ShadowMSR], dx
+ or dx, 0FFFFh
+ wrmsr
+
+ mov ebx, SMINT_SEGMENT ; Patch SS descriptor
+ mov word ptr [BIOS_SS+8], bx
+ shl ebx, 4
+ mov dword ptr [BIOS_SS+2], ebx
+ mov byte ptr [BIOS_SS+5], DATA_ATTR
+ add ebx, 0FFF0h
+ mov [ShadowAddr], ebx
+ mov word ptr [BIOS_ESP], bx
+
+ ; Build a stack frame:
+ ; SMINT_SEGMENT:FFF0 SMINT_SEGMENT:FFF6 - return addresss
+ ; SMINT_SEGMENT:FFF4 Flags
+ ; SMINT_SEGMENT:FFF6 SMINT instruction
+ mov eax, SMINT_SEGMENT SHL 16 ; Segment
+ lea ax, [bx+6] ; Offset (SP+6)
+ xchg eax, dword ptr fs:[ebx]
+ mov [ShadowMemory], eax
+ mov eax, 380F0000h ; FLAGS & SMINT
+ xchg eax, fs:[ebx+4]
+ mov [ShadowMemory+4], eax
+
+ mov eax, [Header_Addr] ; Copy top-level header address
+ mov [Hdr_Address], eax
+
+
+ call VSM_Registers ; Get registers for ISR
+
+
+ call Swap_States ; S wap top-level state with BIOS state
+
+Exit: jmp Sys_Exit
+
+
+
+Unsupported_INT:
+Illegal_INT:
+
+
+ mov ax, ERR_BAD_INTERRUPT
+ push ax ; Push error code
+ shr ebx, 2
+ push ebx ; Info1 = Interrupt #
+ push dword ptr 0 ; Info2 = 0x00000000
+ call Report_VSM_Error
+ jmp Exit
+
+Sys_SW_INT endp
+
+
+
+
+
+
+
+
+
+
+;********************************************************************************
+; Returns here from INT callback
+;********************************************************************************
+INT_Return proc
+
+ mov ebx, [Saved_INT] ; Restore the INT vector
+ mov edx, [Saved_Vector]
+ mov fs:[ebx], edx
+
+
+if ALLOW_SMM_SEGMENTS
+ mov ecx, MSR_RCONF_SMM ; Restore SMM region properties
+ rdmsr
+ mov al, [OldRCONF]
+ wrmsr
+endif
+
+ mov esi, [Current_VSM] ; Mark the requesting VSM ready to run
+ mov fs:(VSM_Header PTR [esi]).SysStuff.RunFlag, RUN_FLAG_READY
+
+ call Swap_States ; Restore the original non-SMM state
+
+ call VSM_Registers ; Return register values & flags
+
+
+ xor eax, eax
+ mov [VSM_Buffer], eax
+
+ sub [SchedulerStack], 4 ; Pop the scheduler sentinel
+
+ mov ebx, [ShadowAddr] ; Restore shadow memory
+ mov eax, [ShadowMemory]
+ mov fs:[ebx], eax
+ mov eax, [ShadowMemory+4]
+ mov fs:[ebx+4], eax
+
+ mov ecx, 1000002Ch ; Restore R/W attributes of UMBs
+ rdmsr
+ mov dx, [ShadowMSR]
+ wrmsr
+
+ mov ax, [Saved_PIC] ; Restore PIC masks
+ out PIC2_MASK, al
+ mov al, ah
+ out PIC1_MASK, al
+ ret
+
+INT_Return endp
+
+
+
+;************************************************************************
+; Swaps the top-level state with the BIOS callback state.
+; Info to be saved:
+; - SMM header & pointer
+; - Descriptors
+; - GP registers
+; - IDT ptr
+; - PCI config address
+;************************************************************************
+Swap_States proc
+
+ lea si, [StartSaveArea] ; Swap thread states
+ lea di, [Saved_State]
+ mov cx, OFFSET EndSaveArea ; Compute # dwords of state
+ sub cx, si
+ shr cx, 2
+StateLoop:
+ lodsd ; Exchange a dword
+ xchg [di], eax
+ mov dword ptr [si-4], eax
+ add di, 4
+ loop StateLoop
+
+ lea si, [SMM_Header] ; Now do the top-level SMM header
+ lea di, [BIOS_Header]
+ mov cl, sizeof(SmiHeader)/4
+Hdr_Loop:
+ lodsd
+ xchg [di], eax
+ mov [si-4], eax
+ add di, 4
+ loop Hdr_Loop
+
+ ret
+
+Swap_States endp
+
+
+;************************************************************************
+; Swaps the VSM's registers with the local state
+;************************************************************************
+VSM_Registers proc
+
+ mov esi, [VSM_Buffer] ; Caller's register buffer
+ mov ax, word ptr [BIOS_Header].EFLAGS
+ xchg fs:(INT_REGS PTR [esi]).Flags, ax
+ mov word ptr [BIOS_Header].EFLAGS, ax
+
+ lea bx, [Reg_Table]
+ mov cx, (End_Reg_Table-Reg_Table)/2
+Reg_Loop:
+ mov di, [bx] ; Get offset of register
+ mov eax, [di] ; Swap with register structure
+ xchg eax, fs:[esi]
+ mov [di], eax
+ add bx, 2 ; Increment ptrs
+ add esi, 4
+ loop Reg_Loop
+
+ ret
+
+; This table translates between a INT_REGS structure and the PUSHA/POPA ordering
+Reg_Table:
+ dw OFFSET BIOS_EAX
+ dw OFFSET BIOS_EBX
+ dw OFFSET BIOS_ECX
+ dw OFFSET BIOS_EDX
+ dw OFFSET BIOS_EBP
+ dw OFFSET BIOS_ESI
+ dw OFFSET BIOS_EDI
+End_Reg_Table:
+
+VSM_Registers endp
+
+
+;************************************************************************
+; Sets a descriptor to a real-mode descriptor
+; Input:
+; AX = selector
+; If selector = 0x0000, a 4 GB descriptor (big-real) is used
+; If selector = 0xFFFF, the calling VSM's base/limit is used
+; DI = ptr to descriptor
+;************************************************************************
+Set_Descriptor proc pascal uses di \
+ DescrPtr: PTR Descriptor
+
+ ASSUME di: PTR Descriptor
+ mov di, [DescrPtr]
+
+ mov ebx, 0FFFFh ; 64K limit
+
+ or ax, ax ; Selector = 0000h?
+ jnz short SetSelector
+ mov ebx, 008FFFFFh ; Yes, then use 4 GB limit (big-real mode)
+SetSelector:
+
+ movzx eax, ax
+ mov [di].selector, ax
+ shl eax, 4
+
+
+if ALLOW_SMM_SEGMENTS
+ ; If ES == 0xFFFF, use VSM's base
+ cmp ax, bx
+ jne short Set_Limit
+ mov eax, [Current_VSM] ; No, use VSM's base & limit
+ mov bx, ax
+ shr bx, 4
+ mov [di].selector, bx
+ mov ebx, (VSM_Header PTR fs:[eax]).DS_Limit
+endif
+
+Set_Limit:
+ ; EAX = base
+ ; EBX = limit
+ mov [di].limit_15_0, bx ; Store 24-bit limit
+ shr ebx, 16
+ mov [di].limit_19_16, bl
+
+ mov [di].base_15_0, ax ; Store 32-bit base
+ shr eax, 16
+ mov [di].base_23_16, al
+ mov [di].base_31_24, ah
+ ret
+
+ ASSUME di: NOTHING
+
+Set_Descriptor endp
+
+
+
+
+
+
+
+
+
+ align 4
+Saved_State:
+;******************************************************************************
+; The following must match the structure at StartSaveArea in SYSMGR.ASM
+BIOS_PCI dd 80000000h
+BIOS_EDI dd 0
+BIOS_ESI dd 0
+BIOS_EBP dd 0
+ dd 0 ; ESP (not used)
+BIOS_EBX dd 0
+BIOS_EDX dd 0
+BIOS_ECX dd 0
+BIOS_EAX dd 0
+
+BIOS_ESP dd 0
+
+BIOS_SS Descriptor {0FFFFh, 0, 0, DATA_ATTR, 0, 0, 0}
+BIOS_DS Descriptor {0FFFFh, 0, 0, DATA_ATTR, 0, 0, 0}
+BIOS_ES Descriptor {0FFFFh, 0, 0, DATA_ATTR, 0, 0, 0}
+BIOS_FS Descriptor {0FFFFh, 0, 0, DATA_ATTR, 0, 0, 0}
+BIOS_GS Descriptor {0FFFFh, 0, 0, DATA_ATTR, 0, 0, 0}
+
+Hdr_Address dd 0
+
+IDT_Selector dd 00920000h
+IDT_Base dd 00000000h
+IDT_Limit dd 0000FFFFh
+
+
+ dw 0 ; Pad
+
+;******************************************************************************
+SMM_CONTROL equ EXTL_SMI_EN + INTL_SMI_EN + SMM_INST_EN + NEST_SMI_EN
+
+BIOS_Header SmiHeader {,SMM_CONTROL,,,,,,,,,VSM_CR0, VSM_EFLAGS, VSM_DR7}
+
+ShadowMemory dd 0, 0
+ShadowAddr dd 0
+ShadowMSR dw 0
+
+VSM_Buffer dd 0
+
+
+Saved_PIC dw 0
+Saved_INT dd 0
+Saved_Vector dd 0
+OldRCONF db 0
+
+_CODE ENDS
+
+
+ END
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/swapsif.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/swapsif.c
new file mode 100755
index 0000000..c46409d
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/swapsif.c
@@ -0,0 +1,316 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//*****************************************************************************
+//* SWAPSiFs routines
+//*****************************************************************************
+
+
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "PROTOS.H"
+#include "VPCI.H"
+#include "PCI.H"
+
+
+// External Functions:
+extern void pascal Return_Virtual_Value(SmiHeader *, ULONG);
+
+
+// External Variables:
+extern PCI_HEADER_ENTRY ISA_Hdr[];
+extern DESCRIPTOR MSRs[];
+
+
+
+#define ACPI_FLAGS (0)
+#define ACPI_RANGE 0x20
+#define PMS_RANGE 0x80
+#define PMS_FLAGS (NOT_GLIU1)
+
+ULONG ACPI_Timer_MSR;
+
+
+//***********************************************************************
+// Enables/disables trapping of PMS or ACPI registers
+//***********************************************************************
+UCHAR pascal PM_Trapping(USHORT EnableFlag, USHORT Bar)
+{ ULONG DescrDefault[2];
+ UCHAR Link, i=0;
+ register DESCRIPTOR * Descr;
+
+ // For each linked item, update the associated MSR
+ Link = ISA_Hdr[Bar/4].Link;
+ while (Link) {
+ Descr = &MSRs[Link];
+
+ // Get link to next MSR
+ Link = Descr->Link;
+
+ // Ignore this MSR if not an I/O trap
+ if ((Descr->Flag & IO_TRAP) != IO_TRAP) {
+ continue;
+ }
+
+ if (EnableFlag) {
+ // Restore descriptor to original value (re-enable trapping)
+ Write_MSR(Descr->MsrAddr, Descr->MsrData);
+ } else {
+ i++;
+ // Set descriptor to default (disable trapping)
+ Get_Descriptor_Default(Descr->Type, DescrDefault);
+ Write_MSR(Descr->MsrAddr, DescrDefault);
+ }
+ }
+
+ return i;
+}
+
+
+//***********************************************************************
+// Enables/disables trapping of PM Support registers
+//***********************************************************************
+UCHAR pascal PMS_Trapping(USHORT EnableFlag)
+{
+ return PM_Trapping(EnableFlag, BAR4);
+}
+
+
+
+//***********************************************************************
+// Enables/disables trapping of ACPI registers
+//***********************************************************************
+UCHAR pascal ACPI_Trapping(USHORT EnableFlag)
+{
+ return PM_Trapping(EnableFlag, BAR5);
+}
+
+
+
+
+//***********************************************************************
+// Workaround for ACPI issues with A3 parts:
+// 1) Hang on byte accesses to ACPI registers 0x00-0x03
+// 2) Improper sharing of shadow register
+// Flag:
+// = 0 if PM Support registers
+// = 1 if ACPI registers
+//***********************************************************************
+void ACPI_Workaround(SmiHeader * SmiHdr, USHORT Flag)
+{ USHORT Address;
+ UCHAR Alignment, Size;
+ ULONG WriteToClearMask, Mask, Data, SrcData;
+ static ULONG WriteToClearMasks[] = {
+ 0xFFFF0000, // 00 PM1_STS
+ 0xFFFFFFFF, // 04 PM1_EN
+ 0xFFFFFDFF, // 08 PM1_CNT
+ 0xFFFFFFFF, // 0C PM2_CNT
+ 0xFFFFFFFF, // 10 PM_TMR
+ 0xFFFFFFFF, // 14 Reserved
+ 0x00000000, // 18 GPE0_STS
+ 0xFFFFFFFF, // 1C GPE0_EN
+ };
+
+
+ // Get info about the I/O from the SMM header
+ Data = SmiHdr->write_data;
+ Address = SmiHdr->IO_addr;
+ Size = (UCHAR)SmiHdr->data_size;
+
+ Alignment = (UCHAR)((Address & 3) << 3);
+ // Make Address dword-aligned
+ Address &= ~3;
+
+ if (Flag) {
+
+ // Get write-to-clear mask for ACPI registers
+ WriteToClearMask = WriteToClearMasks[(Address & 0x1F) >> 2];
+
+ // Disable I/O trapping
+ ACPI_Trapping(0);
+
+ } else {
+
+ // Get write-to-clear mask for PM Support registers
+ switch ((UCHAR)Address) {
+
+ case 0x00:
+ WriteToClearMask = 0xFFFF7FFF;
+ break;
+
+ case 0x54:
+ WriteToClearMask = 0xFFFF0000;
+ break;
+
+ default:
+ WriteToClearMask = 0xFFFFFFFF;
+ break;
+ }
+ // Disable I/O trapping
+ PMS_Trapping(0);
+
+ }
+
+
+ // Read initial value
+ SrcData = in_32(Address);
+
+ if (SmiHdr->SMI_Flags.IO_Write) {
+ // I/O WRITE
+
+ // Get mask appropriate to I/O size
+ switch (Size) {
+ case BYTE_IO:
+ Mask = 0x000000FF;
+ break;
+
+ case WORD_IO:
+ Mask = 0x0000FFFF;
+ break;
+
+ case DWORD_IO:
+ Mask = 0xFFFFFFFF;
+ break;
+ }
+
+
+ Data &= Mask;
+ Data <<= Alignment;
+ SrcData &= ~(Mask << Alignment);
+
+ // Write final data out; Don't rewrite write-to-clear bits
+ Data |= (SrcData & WriteToClearMask);
+ out_32(Address, Data);
+
+ } else {
+
+ // I/O READ
+ Data = (SrcData >> Alignment);
+
+ // Return value to the right environment
+ Return_Virtual_Value(SmiHdr, Data);
+ }
+
+ // Re-enable I/O trapping
+ if (Flag) {
+ ACPI_Trapping(1);
+ } else {
+ PMS_Trapping(1);
+ }
+}
+
+
+//***********************************************************************
+// An I/O BAR for devices in the MDD (e.g. PMS and ACPI) doesn't require
+// a GLIU descriptor since the MDD is the subtractive decode. Therefore,
+// if these registers are trapped, they are not linked to the BARs.
+// This function adds the linkages so when the BAR is changed, the
+// descriptor(s) generating the I/O trap are also changed.
+// NOTES:
+// 1) The descriptors must be linked in order of increasing address.
+// Increasing address does not imply increasing MSRs[] index, so the
+// search index starts over at 1 on an address hit.
+// 2) This function must handle the case where the BAR is of one size but
+// the trapped range is another (either longer or shorter).
+//***********************************************************************
+void pascal FixupLinkages(USHORT Bar)
+{ USHORT IO_Address;
+ UCHAR First = 0, Previous=0, Index;
+ register DESCRIPTOR * Descr;
+
+ IO_Address = ISA_Hdr[Bar/4].Value_LO;
+
+ // Walk through all the descriptors
+ for (Index=1; Index<MAX_DESCR ; Index++ ) {
+ Descr = &MSRs[Index];
+
+ // Only examine descriptors used for I/O traps
+ if ((Descr->Flag & (AVAILABLE | IO_TRAP)) != IO_TRAP) {
+ continue;
+ }
+ // Does this descriptor map the region covered by the BAR?
+ if (Descr->Address == IO_Address) {
+ // Yes
+ if (Previous) {
+ // Link it
+ MSRs[Previous].Link = Index;
+ } else {
+ First = Index;
+ }
+ Previous = Index;
+
+ // Mark it unavailable so we don't 'hit' again
+ Descr->Flag &= ~AVAILABLE;
+
+ // Advance the address
+ IO_Address += (USHORT)Descr->Range;
+
+ // Skip the ACPI timer register
+ if (Bar == BAR5) {
+ switch (IO_Address & (ACPI_RANGE-1)) {
+ case 0x10:
+ (UCHAR)IO_Address += 4;
+ break;
+ case 0x18:
+ // Record descriptor that skips ACPI timer
+ ACPI_Timer_MSR = Descr->MsrAddr;
+ break;
+ }
+ }
+ // Re-start search at beginning of MSR array
+ Index = 1;
+ }
+ }
+
+ if (First) {
+ // Re-link the 'expanded' list to the BAR's linkages
+ MSRs[Previous].Link = ISA_Hdr[Bar/4].Link;
+ ISA_Hdr[Bar/4].Link = First;
+ } else {
+ Log_Error("No links found by FixupLinkages()");
+ }
+}
+
+
+
+//***********************************************************************
+// Installs the trapping for ACPI and PMS register SWAPSiF
+//***********************************************************************
+void ACPI_PMS_SWAPSiF(void)
+{ USHORT IO_Address;
+
+ // Trap PMC registers (F0 BAR4)
+ IO_Address = ISA_Hdr[BAR4/4].IO_Base;
+ if (IO_Address) {
+ Register_Event(EVENT_IO_TRAP, 0, SysMgr_VSM, IO_Address, PMS_FLAGS | PMS_RANGE);
+ // Link the descriptors used for trapping the PMS registers
+ FixupLinkages(BAR4);
+ }
+
+ // Trap ACPI registers (F0 BAR5)
+ IO_Address = ISA_Hdr[BAR5/4].IO_Base;
+ if (IO_Address) {
+ Register_Event(EVENT_IO_TRAP, 0, SysMgr_VSM, IO_Address, ACPI_FLAGS | 0x10);
+ // Skip the ACPI Timer register
+ Register_Event(EVENT_IO_TRAP, 0, SysMgr_VSM, IO_Address+0x14, ACPI_FLAGS | 0x0C);
+ // Link the descriptors used for trapping the ACPI registers
+ FixupLinkages(BAR5);
+ }
+} \ No newline at end of file
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/syscalls.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/syscalls.asm
new file mode 100755
index 0000000..ebf8004
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/syscalls.asm
@@ -0,0 +1,772 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;*******************************************************************************
+;* Implements several system calls
+;*******************************************************************************
+
+
+include SYSMGR.INC
+include VSA2.INC
+include PCI.INC
+include SMIMAC.MAC
+include CHIPSET.INC
+include VR.INC
+
+
+
+
+.model tiny,c
+.586p
+.CODE
+
+public SysCall_Table
+public ReturnULONG
+
+
+externdef Sys_SW_INT: proc
+externdef Sys_Broadcast: proc
+externdef Sys_PassEvent: proc
+externdef Sys_State: proc
+externdef EmptyMsgQueue: proc
+externdef ExitSysCall: proc
+externdef Dispatcher: proc
+externdef Sys_Exit: proc
+externdef Record_VSM_Locations: proc
+externdef pascal Lookup_PCI: proc
+externdef pascal Lookup_IO: proc
+externdef pascal Find_MBus_ID: proc
+externdef pascal Send_Event: proc
+externdef pascal Schedule_VSM: proc
+externdef pascal Allocate_BAR: proc
+externdef pascal Register_Event: proc
+externdef pascal Report_VSM_Error: proc
+externdef pascal Allocate_Resource: proc
+externdef pascal Set_Address_Decode: proc
+externdef pascal Enable_PCI_Trapping: proc
+externdef pascal Unregister_VSM_Events: proc
+externdef pascal IRQY_Mapper: proc
+externdef pascal Return_Virtual_Value: proc
+
+externdef SysMgr_VSM: dword
+externdef VSM_ListHead: dword
+externdef Current_VSM: dword
+externdef MsgPacket: dword
+externdef SMI_Base: dword
+externdef IRQ_Base: dword
+externdef VSM_Ptrs: dword
+externdef Events: EVENT_ENTRY
+externdef HardwareInfo: Hardware
+
+
+
+
+
+ align 2
+SysCall_Table:
+ dw OFFSET Sys_Register ; 00 - SYS_CODE_EVENT
+ dw OFFSET Sys_Yield ; 01 - SYS_CODE_YIELD
+ dw OFFSET Sys_SW_INT ; 02 - SYS_CODE_SW_INT
+ dw OFFSET Sys_PassEvent ; 03 - SYS_CODE_PASS_EVENT
+ dw OFFSET Sys_Unload ; 04 - SYS_CODE_UNLOAD
+ dw OFFSET Sys_Registers ; 05 - SYS_CODE_REGISTER
+ dw OFFSET Sys_RdWrPCI ; 06 - SYS_CODE_PCI_ACCESS
+ dw OFFSET Sys_SetVirtual ; 07 - SYS_CODE_SET_VIRTUAL
+ dw OFFSET Sys_GetVirtual ; 08 - SYS_CODE_GET_VIRTUAL
+ dw OFFSET Sys_Broadcast ; 09 - SYS_CODE_BROADCAST
+ dw OFFSET Sys_State ; 0A - SYS_CODE_STATE
+ dw OFFSET Sys_Report_Error ; 0B - SYS_CODE_ERROR
+ dw OFFSET Sys_Resource ; 0C - SYS_CODE_RESOURCE
+ dw OFFSET Sys_Decode ; 0D - SYS_CODE_DECODE
+ dw OFFSET Sys_GetDescr ; 0E - SYS_CODE_DESCRIPTOR
+ dw OFFSET Sys_Lookup ; 0F - SYS_CODE_LOOKUP
+ dw OFFSET Sys_IRQ_Mapper ; 10 - SYS_CODE_IRQ_MAPPER
+ dw OFFSET Sys_Result ; 11 - SYS_CODE_RESULT
+ dw OFFSET Sys_Duplicate ; 12 - SYS_CODE_DUPLICATE
+ dw OFFSET EmptyMsgQueue ; 13 - SYS_CODE_EXIT
+
+
+;************************************************************************
+; Implements the WRITE_PCI_NO_TRAP macros
+;
+; On Entry:
+; SI = data size (bit 7 = 1 if I/O write);
+; EBX = PCI configuration address
+; ECX = data (if write)
+;************************************************************************
+Sys_RdWrPCI proc
+
+ push ebx ; Save PCI address
+ push ecx ; Save data
+
+ ; Disable trapping of PCI address
+ push bx ; PCI_Address
+ push word ptr 0000
+ call Enable_PCI_Trapping
+
+ movzx bp, al ; Save previous trap setting
+
+ pop ecx ; Restore data
+ pop ebx ; Restore PCI address
+
+ ; Write the PCI address
+ mov dx, PCI_CONFIG_ADDRESS
+ mov eax, ebx
+ out dx, eax
+ add dl, 4
+ and al, 3
+ add dl, al
+
+ btr si, 7 ; Read or write ?
+ jc PCI_Write ; Jmp if write
+
+ cmp si, BYTE_IO ; Byte, Word, or Dword ?
+ je Read_Byte
+ cmp si, WORD_IO
+ je Read_Word
+
+
+Read_Dword:
+ db 66h ; Force next instruction to be IN EAX,DX
+Read_Word:
+ in ax, dx
+ jmp short ReturnValue
+
+
+Read_Byte:
+ in al, dx
+ReturnValue:
+
+ push eax ; Save return value
+
+ call Restore_Trapping ; Re-enable PCI trapping
+
+ pop ax ; Restore return value
+ pop dx
+
+ReturnULONG::
+ mov bx, word ptr gs:(VSM_Header).SysStuff.SavedESP
+ mov word ptr gs:[bx+8*4], ax
+ mov word ptr gs:[bx+6*4], dx
+ jmp ExitSysCall
+
+
+
+;************************************************************************
+PCI_Write:
+
+ mov eax, ecx ; Get data to be written
+ cmp si, WORD_IO ; Byte, Word, or Dword ?
+ je short Write_Word
+ cmp si, DWORD_IO
+ je short Write_Dword
+ cmp si, BYTE_IO
+ jne short Ignore ; Ignore if error in parameter
+
+Write_Byte:
+ out dx, al
+ jmp short Restore_PCI_Trap
+
+
+Write_Dword:
+ db 66h ; Force next instruction to be OUT DX,EAX
+Write_Word:
+ out dx, ax
+
+Restore_PCI_Trap:
+ call Restore_Trapping ; Re-enable PCI trapping
+
+Ignore:
+ jmp ExitSysCall
+
+
+Sys_RdWrPCI endp
+
+
+;***********************************************************************
+; Restores PCI trapping
+; On entry:
+; BP = 1 means re-enable PCI trapping
+;***********************************************************************
+Restore_Trapping proc
+
+ ; Is trapping to be re-enabled ?
+ cmp bp, 1
+ jne short Exit
+
+ ; Yes, restore PCI trapping on this address
+ ; Enable_PCI_Trapping(PCI_Address, EnableFlag);
+ push bx ; PCI address
+ push bp ; EnableFlag
+ call Enable_PCI_Trapping
+Exit: ret
+
+Restore_Trapping endp
+
+
+
+
+;***********************************************************************
+;
+; Register an event to the calling VSM
+;
+; On entry:
+; EBX = Event::Priority
+; ECX = Parameter 1
+; EDI = Parameter 2
+;***********************************************************************
+Sys_Register proc
+
+ ; Register_Event(Event, Priority, VSM, Param1, Param2);
+ push ebx ; Event::Priority
+ push [Current_VSM] ; VSM ptr
+ push ecx ; Param1
+ push edi ; Param2
+ call Register_Event
+ jmp ExitSysCall
+
+Sys_Register endp
+
+
+;***********************************************************************
+; Input:
+; BX = Virtual register index
+; Output:
+; AX = returned data
+;***********************************************************************
+Sys_GetVirtual proc
+
+ xor cx, cx ; Data = 0000
+ xor di, di ; 0 = read
+ jmp VirtualCommon
+
+Sys_GetVirtual endp
+
+
+
+;***********************************************************************
+; Input:
+; BX = Virtual register index
+; CX = Data
+;***********************************************************************
+Sys_SetVirtual proc
+
+ call Handle_PM
+
+ mov di, 1 ; 1 = write
+VirtualCommon::
+ cmp bh, VRC_KEYBOARD ; Allow VRC_KEYBOARD to pass 32-bits
+ je Reschedule
+ movzx ecx, cx
+Reschedule:
+ mov edx, [Current_VSM] ; Re-schedule calling VSM
+ push edx
+ call Schedule_VSM
+
+ call VirtualRegisterEvent
+
+ mov ax, 0FFFFh ; Value of an undefined virtual register
+ mov bx, word ptr gs:(VSM_Header).SysStuff.SavedESP
+ mov word ptr gs:[bx+8*4], ax
+ jmp Dispatcher
+
+
+
+
+Sys_SetVirtual endp
+
+
+Handle_PM proc
+
+if 0;SUPPORT_PM ; requires 78 bytes
+ ; If OHCI VSM is sending a USB event to KBD VSM, send an EVENT_IO_TRAP
+ ; to the PM VSM so system will exit DOZE mode.
+ cmp bh, VRC_KEYBOARD
+ jne short Exit
+ mov eax, [VSM_Ptrs+4*VSM_PM]; Is PM installed ?
+ or eax, eax
+ jz short Exit
+
+
+ ; Is PM VSM registered for the I/O trap ?
+ mov al, EVENT_IO_TRAP
+FindPM:
+ mov ah, sizeof(EVENT_ENTRY)
+ mul ah
+ mov si, ax
+ mov eax, (EVENT_ENTRY PTR [Events+si]).Vsm
+ or eax, eax
+ jz short Exit
+ cmp eax, edi ; Is it the PM VSM ?
+ jne short Next_VSM
+ cmp (EVENT_ENTRY PTR [Events+si]).Param1, 0060h
+ je short PM_Is_Dozing
+Next_VSM:
+ mov al, (EVENT_ENTRY PTR [Events+si]).Link
+ or al, al
+ jnz FindPM
+ jmp short Exit
+
+
+PM_Is_Dozing:
+ push bx ; Yes, save virtual register info
+ push cx
+
+ mov eax, MSG_EVENT ; Send the PM VSM an EVENT_IO_TRAP[0x60] message
+ mov ebx, [SysMgr_VSM]
+ lea si, [PM_Packet]
+ call Insert_Msg
+
+ pop cx ; Restore virtual register info
+ pop bx
+
+endif
+
+Exit: ret
+
+PM_Packet dd EVENT_IO_TRAP, 0, 0060h
+
+Handle_PM endp
+
+
+
+;***********************************************************************
+; Sends an EVENT_VIRTUAL_REGISTER to VSM(s)
+; On entry:
+; BX = Class::Index
+; CX = write data
+; DI = 0 (read) or 1 (write)
+; EDX = From_VSM
+;***********************************************************************
+VirtualRegisterEvent proc
+
+ lea si, [MsgPacket] ; Fill the message packet
+ movzx eax, bx
+ mov [si+1*4], eax ; MsgPacket[1] : virtual register index
+ mov ax, di
+ mov [si+2*4], eax ; MsgPacket[2] : 0=read 1=write
+ mov [si+3*4], ecx ; MsgPacket[3] : write data
+
+ mov ax, EVENT_VIRTUAL_REGISTER ; No, so it's a VR access
+ push ax ; Event
+ push edx ; From_VSM
+ call Send_Event
+ ret
+
+VirtualRegisterEvent endp
+
+
+
+
+
+
+;***********************************************************************
+; Implements the SYS_UNLOAD_VSM macro
+;***********************************************************************
+Sys_Unload proc
+
+ ; Find prior VSM to current VSM
+ mov eax, [Current_VSM]
+ or eax, eax
+ jz short Exit
+
+ ; Remove current VSM from linked list
+ mov ebx, (VSM_Header PTR fs:[eax]).SysStuff.Blink
+ mov ecx, (VSM_Header PTR fs:[eax]).SysStuff.Flink
+ or ebx, ebx ; Is there a previous VSM ?
+ jnz short IsBackLink
+ mov [VSM_ListHead], ecx ; No, update VSM_ListHead with VSM at Flink
+ jmp short FixupBlink
+IsBackLink:
+ mov (VSM_Header PTR fs:[ebx]).SysStuff.Flink, ecx
+FixupBlink:
+ or ecx, ecx
+ jz short Unregister
+ mov (VSM_Header PTR fs:[ecx]).SysStuff.Blink, ebx
+
+ ; Unregister events registered to this VSM
+Unregister:
+ push eax
+ call Unregister_VSM_Events
+
+ call Record_VSM_Locations
+Exit: jmp Sys_Exit ; Exit to SysMgr
+
+Sys_Unload endp
+
+
+
+
+
+;***********************************************************************
+; Implements the SYS_ALLOCATE_RESOURCE macro
+; Input:
+; BL - Resource type
+; Other registers - various parameters
+;***********************************************************************
+Sys_Resource proc
+
+ ; Only BAR types are implemented at this time
+ cmp bl, RESOURCE_MEMORY
+ je short BAR_Resource
+ cmp bl, RESOURCE_MMIO
+ je short BAR_Resource
+ cmp bl, RESOURCE_IO
+ je short BAR_Resource
+ cmp bl, RESOURCE_SCIO
+ je short BAR_Resource
+
+ ; Not a BAR resource
+ push bx ; Resource
+ push ecx ; Param
+ call Allocate_Resource
+ jmp ExitSysCall
+
+
+BAR_Resource:
+ push bx ; BAR type
+ push si ; BAR offset
+ push ecx ; Range
+
+ ror edi, 16
+ push di ; MBus_ID
+ ror edi, 16
+ push di ; PCI Device_ID
+ call Allocate_BAR
+
+ jmp ReturnULONG
+
+Sys_Resource endp
+
+
+
+;***********************************************************************
+; Implements the SYS_REPORT_ERROR macro
+; DI = Error code
+; EBX = Info1
+; ECX = Info2
+;***********************************************************************
+Sys_Report_Error proc
+
+ push di
+ push ebx
+ push ecx
+ call Report_VSM_Error
+
+ jmp ExitSysCall
+
+
+Sys_Report_Error endp
+
+
+YIELD_HANDLE equ (ONE_SHOT OR SYS_YIELD OR 0000BEEFh)
+
+;***********************************************************************
+; Implements the SYS_YIELD macro
+;
+; Input:
+; ECX = milliseconds to suspend the VSM
+;***********************************************************************
+Sys_Yield proc
+
+ mov eax, [Current_VSM] ; VSM that is yielding control
+ mov fs:(VSM_Header PTR [eax]).SysStuff.RunFlag, RUN_FLAG_WAITING
+
+ push word ptr EVENT_TIMER ; Event
+ push word ptr 0000 ; Priority
+ push eax ; Vsm
+ push ecx ; Param1 (ms)
+ push dword ptr YIELD_HANDLE ; Param2 (handle)
+ call Register_Event
+
+ jmp Sys_Exit ; Exit to SysMgr. Don't return to VSM
+
+Sys_Yield endp
+
+
+;***********************************************************************
+; This system call is obsolete
+; Input:
+; BH = 0 for Set, 1 for Get
+; BL = register definition
+; ECX = data if Set
+;***********************************************************************
+Sys_Registers proc
+
+ jmp ExitSysCall
+
+Sys_Registers endp
+
+
+;***********************************************************************
+; Implements the SYS_MAP_IRQ macro
+; Maps IRQ source to specified IRQ
+; Input:
+; BL = Unrestricted Y source (0x00-0x0F)
+; CL = IRQ setting
+;***********************************************************************
+Sys_IRQ_Mapper proc
+
+ push bx
+ push cx
+ call IRQY_Mapper
+ jmp ExitSysCall
+
+Sys_IRQ_Mapper endp
+
+
+
+;***********************************************************************
+; Input:
+; BX = Address
+; CX = Decode flag
+;***********************************************************************
+Sys_Decode proc
+
+ push bx ; Address
+ push cx ; Decode (POSITIVE_DECODE or SUBTRACTIVE_DECODE)
+ call Set_Address_Decode
+
+ jmp ExitSysCall
+
+Sys_Decode endp
+
+
+
+
+
+;***********************************************************************
+; Implements the SYS_MBUS_DESCRIPTOR & SYS_IO_DESCRIPTOR macros
+;
+; On entry:
+; BX = Address
+; CX = 0 if PCI else I/O
+; Returns:
+; MSR address of corresponding resource
+;***********************************************************************
+Sys_GetDescr proc
+
+ jcxz PCI
+
+ ; MSR_Address = Lookup_IO(Address);
+ push bx
+ call Lookup_IO
+
+ mov bl, 2 ; Restore IO_Flag
+ jmp Common
+
+ ; MSR_Address = Lookup_PCI(Address);
+PCI: push bx
+ call Lookup_PCI
+
+ xor bx, bx
+Common:
+ mov cx, dx ; Was resource found ?
+ shl ecx, 16
+ mov cx, ax
+ xor eax, eax ; EDX:EAX = 00000000:00000000
+ xor edx, edx
+ jecxz ReturnMSRInfo
+
+ rdmsr ; Yes, read MSR
+
+ test bl, 2 ; Set MSR to default ?
+ jz ReturnMSRInfo
+ push edx ; Yes, save current value
+ push eax
+
+ test eax, 000F0000h ; IOD_BM or IOD_SC ?
+ mov eax, 00000000h ; Default for IOD_SC
+ mov edx, eax
+ jz SetDefault
+ mov eax, 0FFF00000h ; Default for IOD_BM
+ mov edx, 0000000FFh
+SetDefault:
+ wrmsr ; Set MSR to default value
+
+ pop eax ; Restore original MSR value
+ pop edx
+
+ ; Return MSR address in ECX and MSR value in EDX:EAX
+ReturnMSRInfo:
+ mov bx, word ptr gs:(VSM_Header).SysStuff.SavedESP
+ mov gs:[bx+7*4], ecx ; Return MSR address in ECX
+ mov gs:[bx+8*4], eax ; Return MSR value in EDX:EAX
+ mov gs:[bx+6*4], edx
+ jmp ExitSysCall
+
+Sys_GetDescr endp
+
+
+
+
+;***********************************************************************
+; Implements the SYS_LOOKUP_DEVICE macro
+;
+; On entry:
+; BX = MBus Device_ID
+; CX = Instance
+; Returns:
+; DX:AX = MSR routing address to MBus device
+;***********************************************************************
+Sys_Lookup proc
+
+ ; Find_MBus_ID(USHORT MBus_ID, UCHAR Instance);
+ push bx
+ push cx
+ call Find_MBus_ID
+ xor ax, ax
+
+ jmp ReturnULONG
+
+Sys_Lookup endp
+
+
+
+
+
+
+;***********************************************************************
+; Implements the SYS_RETURN_RESULT macro
+; Returns a byte/word/dword result to the correct context.
+; Input:
+; EBX = Result to be returned
+;***********************************************************************
+Sys_Result proc
+
+ push OFFSET VSM_Header.SysStuff.State
+ push ebx ; Value
+ call Return_Virtual_Value
+
+ jmp ExitSysCall
+
+Sys_Result endp
+
+
+;***********************************************************************
+; Implements the SYS_DUPLICATE_VSM macro
+; On entry: BX = memory model
+; Legend: (C=copy of parent VSM) (N=new copy)
+; CS DS SS
+; 0: N N N
+; 1: C N N
+;***********************************************************************
+Sys_Duplicate proc
+
+; mov [MemoryModel], bx ; Ignore parameter for new
+
+ ; Find end of VSMs in memory
+ mov esi, [Current_VSM]
+ mov ebx, esi
+FindLastVSM:
+ mov edi, ebx
+ mov ebx, (VSM_Header PTR fs:[ebx]).SysStuff.Flink
+ or ebx, ebx
+ jnz FindLastVSM
+
+ ; EDI points to last VSM in memory. Find end of last VSM.
+ mov edx, edi
+ add edi, (VSM_Header PTR fs:[edi]).DS_Limit
+
+
+ ; Copy this VSM's image
+ mov ecx, (VSM_Header PTR fs:[esi]).DS_Limit
+ cmp [MemoryModel], 0 ; Use same Code segment ?
+ je short CopyImage
+ mov ecx, sizeof(VSM_Header) + VSM_STACK_SIZE
+CopyImage:
+ push edi
+ push esi
+ push ecx
+ shr ecx, 2 ; Convert BYTE count to DWORDs
+ rep movsd [edi], es:[esi]
+ pop ecx
+ pop esi
+ pop edi
+
+ ; Patch descriptors
+ mov (VSM_Header PTR fs:[edi])._DS.base_15_0, di
+ mov (VSM_Header PTR fs:[edi])._SS.base_15_0, di
+ mov eax, edi
+ shr eax, 16
+ mov (VSM_Header PTR fs:[edi])._DS.base_31_24, ah
+ mov (VSM_Header PTR fs:[edi])._DS.base_23_16, al
+ mov (VSM_Header PTR fs:[edi])._SS.base_31_24, ah
+ mov (VSM_Header PTR fs:[edi])._SS.base_23_16, al
+
+ mov (VSM_Header PTR fs:[edi])._DS.limit_15_0, cx
+ mov (VSM_Header PTR fs:[edi])._SS.limit_15_0, cx
+; Required for segments > 64K
+; shr ecx, 16
+; mov (VSM_Header PTR fs:[edi])._DS.limit_19_16, cl
+; mov (VSM_Header PTR fs:[edi])._SS.limit_19_16, cl
+
+
+ cmp [MemoryModel], 0 ; Use same Code segment ?
+ jne short LinkNewVSM
+ mov (VSM_Header PTR fs:[edi]).SysStuff.State._CS.base, edi
+
+LinkNewVSM:
+ ; Link the new VSM into the VSM list
+ mov (VSM_Header PTR fs:[edx]).SysStuff.Flink, edi
+ mov (VSM_Header PTR fs:[edi]).SysStuff.Blink, edx
+ mov (VSM_Header PTR fs:[edi]).SysStuff.Flink, 0
+
+ ; Init EIP
+ movzx eax, (VSM_Header PTR fs:[edi]).EntryPoint
+ mov (VSM_Header PTR fs:[edi]).SysStuff.State.Next_EIP, eax
+
+ ; Init ESP & create the initial stack frame
+ mov eax, (VSM_Header PTR fs:[edi]).DS_Limit
+ sub ax, VSM_STACK_FRAME
+ mov (VSM_Header PTR fs:[edi]).SysStuff.SavedESP, eax
+
+ ; Schedule the new VSM
+ push edi
+ call Schedule_VSM
+
+ jmp ExitSysCall
+ ret ; Gets rid of assembler warning
+
+; Warning: don't make MemoryModel a variable on the stack
+; The JMP ExitSysCall bypasses the LEAVE instruction and BP is trashed
+MemoryModel dw 0
+
+Sys_Duplicate endp
+
+
+;***********************************************************************
+; Returns TRUE if the VSM is currently yielded
+;***********************************************************************
+VSM_Is_Yielded proc Vsm: dword
+
+ mov ebx, [Vsm]
+ mov al, 0 ; return FALSE
+ cmp fs:(VSM_Header PTR [ebx]).SysStuff.RunFlag, RUN_FLAG_WAITING
+ jne short Exit
+ mov al, 1 ; return TRUE
+Exit:
+ ret
+
+VSM_Is_Yielded endp
+
+
+ END
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/sysmgr.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/sysmgr.asm
new file mode 100755
index 0000000..0a385df
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/sysmgr.asm
@@ -0,0 +1,804 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file contains the entry point to the SMM code. *
+;* This code performs the following: *
+;* 1) saves the processor state *
+;* 2) reads the top-level SMI source register(s) *
+;* 3) issues message(s) to the appropriate VSM(s) *
+;* 4) dispatches to VSM(s) until all messages are handled *
+;* 5) restores the processor state
+
+include SYSMGR.INC
+include VSA2.INC
+include PCI.INC
+include SMIMAC.MAC
+include CHIPSET.INC
+include CS5536.INC
+include GX2.INC
+
+.model tiny,c
+.586p
+
+.ALPHA
+DGROUP GROUP _CODE, _TEXT
+_CODE SEGMENT PUBLIC use16 'CODE'
+ ASSUME DS:_CODE
+
+
+BRACKETS equ 0
+
+public SysMgr_Entry
+public Nested_SMI
+public Saved_EAX, Saved_AX
+public Saved_EBX, Saved_ECX, Saved_EDX, Saved_PCI
+public Saved_ESI, Saved_EDI, Saved_EBP, Saved_ESP
+public Saved_SS, Saved_ES, Saved_DS, Saved_FS, Saved_GS
+public IDT_Selector, IDT_Base, IDT_Limit
+public VSMs_EAX
+public Nested_PCI, Nested_EDI, Nested_EAX, Nested_ES
+public StartSaveArea, EndSaveArea
+public SchedulerStack
+public Sys_Exit
+public VSM_ListHead
+public SMM_Header
+public SysMgr_VSM
+public Data_Descriptor
+public Flat_Descriptor
+public Current_VSM
+public Nested_Flag
+public HardwareInfo
+public SMI_Base
+public IRQ_Base, IRQ_Mask
+public Header_Addr
+public BracketFlag
+public ExitSysCall
+public EmptyMsgQueue
+public Dispatcher
+public Trap_Code
+
+externdef Trap_Common: proc
+externdef Trap7: proc
+externdef Get_SMI_Sources: proc
+externdef VSA_Entry: proc
+externdef VSA_Exit: proc
+externdef Show_SMI_Source: proc
+externdef Generate_IRQ: proc
+externdef pascal Hex_8: proc
+externdef pascal Hex_16: proc
+externdef pascal Hex_32: proc
+externdef pascal SMINT_Handler:proc
+
+externdef INT_Vectors: dword
+externdef SMI_Sources: dword
+externdef SynchEvents: dword
+externdef HiPrioritySMIs: dword
+externdef MSRs: dword
+
+externdef SysCall_Table: word
+
+externdef NumDescriptors: byte
+externdef Events: byte
+externdef MSRs: byte
+externdef _end: byte
+externdef edata: byte
+
+externdef Handler_Table: SMI_ENTRY
+
+
+
+
+
+
+
+
+; NOTE: "#define EXTRA_SAVE" in SYSMGR.H must match the number of bytes
+; of state (over and above the registers) that is saved by the
+; following two macros:
+SAVE_STATE macro
+ pushad ; Save general purpose registers
+ mov dx, PCI_CONFIG_ADDRESS ; Save PCI Configuration Address
+ in eax, dx
+ push eax
+
+ endm
+
+
+RESTORE_STATE macro
+ pop eax ; PCI Configuration Address
+ mov dx, PCI_CONFIG_ADDRESS
+ out dx, eax
+ popad ; Restore general purpose registers
+
+ endm
+
+
+
+
+Start:
+; NOTE: The VSA II installer patches a "JMP SysMgr_Entry" over the signature field
+ dd VSM_SIGNATURE ; VSM signature
+ db VSM_SYS_MGR ; VSM type
+ db 0FFh ; Any CPU
+ dw DEVICE_ID_5536 ; VSA for CS5536
+ dw VSA_VERSION ; System Manager version
+ dd OFFSET edata ; Size of System Manager
+ dw OFFSET SysMgr_Entry ; EntryPoint
+ dd OFFSET _end ; DS Limit
+ dw 0007h ; Requirements: 4096-byte boundary
+ dw VSA_VERSION ; VSA version
+
+Stack_Descriptor:
+ Descriptor {_end, 0000h, 00h, DATA_ATTR, 00h, 00h, 0000h}
+Data_Descriptor:
+ Descriptor {_end, 0000h, 00h, DATA_ATTR, 00h, 00h, 0000h}
+
+Flat_Descriptor:
+ Descriptor {0FFFFh, 0000h, 00h, DATA_ATTR, 8Fh, 00h, 0000h}
+
+
+ dw 0 ; .AlignSystem
+SMM_Header SmiHeader {} ; .State
+VSM_ListHead dd 0 ; .Flink (ptr to 1st VSM; zero if no VSMs)
+
+Trap macro Trap_Num
+ ORG Trap_Code + (Trap_Num * 8)
+ mov bx, Trap_Num
+ jmp Trap_Common
+ endm
+
+ ORG sizeof(VSM_Header)
+ align 16
+
+;***********************************************************************
+; Exception vectors
+;***********************************************************************
+Trap_Code:
+ Trap 0
+ Trap 1
+ Trap 2
+ Trap 3
+ Trap 4
+ Trap 5
+ Trap 6
+
+ ORG Trap_Code + (7 * 8)
+ jmp Trap7
+
+ Trap 8
+ Trap 9
+ Trap 0Ah
+ Trap 0Bh
+ Trap 0Ch
+ Trap 0Dh
+ Trap 0Eh
+ Trap 0Fh
+
+
+
+;***********************************************************************
+; Non-nested VSA entry point *
+;***********************************************************************
+SysMgr_Entry:
+
+ ;
+ ; Save state of interrupted task & initialize VSA environment
+ ;
+ svdc cs:[Saved_DS], ds ; Save DS descriptor & set to SysMgr segment
+ rsdc ds, cs:[Data_Descriptor]
+ ASSUME DS:_CODE
+
+ svdc [Saved_ES], es ; Save ES descriptor
+ svdc [Saved_FS], fs ; Save FS descriptor
+ svdc [Saved_GS], gs ; Save GS descriptor
+
+ svdc [Saved_SS], ss ; Save SS descriptor & set to SysMgr segment
+ rsdc ss, [Stack_Descriptor]
+ mov [Saved_ESP], esp ; Save ESP & set up SysMgr stack
+ mov esp, OFFSET SysMgrStack
+
+ SAVE_STATE ; Save the general purpose registers on SysMgr's stack
+
+
+ rdtsc ; Get start time of this SMI
+ mov (VSM_Header PTR ds:[0]).SysStuff.StartTime, eax
+ mov (VSM_Header PTR ds:[4]).SysStuff.StartTime, edx
+
+ rsdc fs, [Flat_Descriptor] ; Set FS descriptor to a 4 GB flat segment
+ rsdc es, [Flat_Descriptor] ; Set ES descriptor to a 4 GB flat segment
+
+if BRACKETS
+ cmp [BracketFlag], 0
+ je short NoBracket
+ mov dx, DBG_PORT
+ mov al, '['
+ out dx, al
+
+NoBracket:
+endif
+
+
+ call VSA_Entry ; Perform VSA entry setup
+
+ xor eax, eax
+ mov [Nested_Flag], eax
+
+ ;
+ ; Check for SMINT
+ ;
+ test [SMM_Header].SMI_Flags, 1000b
+ jz short Main_SMI_Loop
+
+ push word ptr [Saved_EAX]
+ call SMINT_Handler
+ jmp Dispatcher
+
+;***********************************************************************
+;***********************************************************************
+;***********************************************************************
+; *
+; Main SMI Loop *
+; *
+; 1) Read the top-level SMI sources. *
+; 2) If no SMIs are pending, exit SMM. *
+; 3) Call an SMI handler for each pending SMI source. *
+; 4) Dispatch to VSMs that have non-empty message queues. *
+; 5) Rinse and repeat. *
+; *
+;***********************************************************************
+;***********************************************************************
+;***********************************************************************
+Main_SMI_Loop:
+
+ call Get_SMI_Sources ; Get source(s) of external SMIs
+ test ebx, ebx ; If no SMIs pending, exit SMM
+ jz SMI_Resume
+
+
+ ;
+ ; Invoke the handler for each pending SMI source
+ ;
+ mov [SMI_Sources], ebx
+RunHandlers:
+ lea di, Handler_Table - sizeof (SMI_ENTRY)
+NextHandler:
+ add di, sizeof (SMI_ENTRY) ; Advance ptr to next handler entry
+
+ mov eax, (SMI_ENTRY PTR [di]).SMI_Mask
+ and eax, [SMI_Sources] ; Sources = TopLevelSources & Handler_Table.SMI_Mask
+ jz NextHandler
+
+ push eax ; call Handler_Table.Handler(Sources)
+ call (SMI_ENTRY PTR [di]).Handler
+ pop eax
+
+ not eax ; TopLevelSources &= ~Sources;
+ and [SMI_Sources], eax
+ jnz NextHandler ; if (!TopLevelSources) break;
+
+
+
+
+ ;
+ ; Dispatch to the VSM on top of the scheduler's stack
+ ;
+Dispatcher:
+ mov si, [SchedulerStack] ; Get scheduler's ptr
+ mov ebx, [si] ; Pop next VSM
+ sub si, 4
+
+ test ebx, 0FFFF0000h ; Is it a VSM ?
+ jnz RunTask
+ test bx, bx ; Callback routine ?
+ je Main_SMI_Loop
+ mov [SchedulerStack], si ; Yes, update scheduler ptr
+ call bx ; Go to callback routine
+ jmp Dispatcher
+
+
+RunTask:
+ mov [SchedulerStack], si ; Save scheduler's ptr
+ mov [Current_VSM], ebx ; Save ptr to the current VSM
+ExecuteTask:
+ ;
+ ; Point SMHR to the VSM's SMM header.
+ ;
+ lea eax, (VSM_Header PTR [ebx+sizeof(SmiHeader)]).SysStuff.State
+ mov ecx, MSR_SMM_HDR
+ wrmsr
+ ;
+ ; Restore the VSM's state
+ ;
+ rsdc ds, fs:(VSM_Header PTR [ebx])._DS
+
+ xor edi, edi
+ ASSUME di:PTR VSM_Header
+ rsdc gs, [di]._DS
+ rsdc ss, [di]._SS ; Restore VSM's SS:SP
+ lea bx, [di].SysStuff
+ ASSUME bx:PTR System
+ mov sp, word ptr [bx].SavedESP
+
+
+ ;
+ ; Update statistics
+ ;
+ rdtsc ; Record start time of the VSM
+ mov [bx+0].StartTime, eax
+ add [bx+0].NumSMIs, 1 ; Increment SMI count
+ adc [bx+4].NumSMIs, edi
+
+ ;
+ ; Mark VSM active unless it is sleeping
+ ;
+ mov al, RUN_FLAG_ACTIVE
+SetRunFlag:
+ xchg [bx].RunFlag, al
+ cmp al, RUN_FLAG_SLEEPING
+ je SetRunFlag
+
+ RESTORE_STATE ; No, restore registers
+
+ rsm ; Resume to the VSM
+
+
+ ASSUME DI: NOTHING
+ ASSUME BX: NOTHING
+
+
+
+
+
+
+;***********************************************************************
+; Restore state & resume to non-SMM code *
+;***********************************************************************
+ align 16
+SMI_Resume:
+
+
+ ; Generate internal IRQ(s)
+ xor ecx, ecx
+ xchg ecx, [IRQ_Mask]
+ jecxz NoIRQ
+ call Generate_IRQ
+NoIRQ:
+
+
+ call VSA_Exit ; Perform VSA exit
+ jc Main_SMI_Loop
+
+
+
+
+
+
+ ; Increment count of SMIs
+ mov si, OFFSET VSM_Header.SysStuff
+ ASSUME SI: PTR System
+ xor ecx, ecx
+ add [si+0].NumSMIs, 1
+ adc [si+4].NumSMIs, ecx
+
+ ; Compute total clocks for this SMI
+ rdtsc
+ sub eax, [si+0].StartTime
+ ; Accumulate total clocks spent executing VSA code
+ add [si+0].Clocks, eax
+ adc [si+4].Clocks, ecx
+
+ ASSUME SI:NOTHING
+
+
+
+
+if BRACKETS
+ cmp [BracketFlag], 0
+ je @f
+ mov dx, DBG_PORT
+ mov al, ']'
+ out dx, al
+@@:
+endif
+
+
+
+;***********************************************************************
+; Restore the state of the interrupted task *
+;***********************************************************************
+ RESTORE_STATE ; Restore GP registers & PCI addr
+
+ mov esp, [Saved_ESP] ; Restore ESP
+ rsdc ss, [Saved_SS] ; Restore descriptors
+ rsdc es, [Saved_ES]
+ rsdc fs, [Saved_FS]
+ rsdc gs, [Saved_GS]
+ rsdc ds, [Saved_DS] ; Must be restored last
+ rsm ; Resume to non-SMM thread
+
+
+
+
+
+
+;***********************************************************************
+; An SMI has occurred that is not a system call: *
+; *
+; If synchronous SMI: *
+; - Save the state of the interrupted VSM *
+; - Reschedule the interrupted VSM *
+; - Execute SMI handlers *
+; If asynchronous SMI: *
+; - If event is not high priority or VSM is marked no-preempt, *
+; return to interrupted VSM immediately. *
+; - Otherwise, execute SMI handlers *
+;***********************************************************************
+ align 16
+NotSysCall:
+
+ ;
+ ; Save VSM's state and set up SysMgr stack
+ ;
+ SAVE_STATE ; Save the VSM's state
+ mov word ptr gs:(VSM_Header).SysStuff.SavedESP, sp
+
+ rsdc ss, [Stack_Descriptor] ; Setup System Manager's stack
+ lea sp, [StartSaveArea]
+
+
+ call Get_SMI_Sources ; Get source(s) of nested SMIs
+
+ mov [SMI_Sources], ebx ; Record the pending SMI sources
+ test ebx, [SynchEvents] ; Is nested SMI a syncronous event ?
+ jz short AsyncSMI
+
+ ;
+ ; The SMI is synchronous (I/O or virtualized PCI trap)
+ ;
+ and ebx, [SynchEvents] ; Record the nested SMI source
+ or [Nested_Flag], ebx
+
+ ; It's a trapped or virtualized PCI.
+ ; Record some info about the event.
+ svdc [Nested_ES], gs ; Save GS descriptor
+ mov esi, gs:(VSM_Header).SysStuff.SavedESP
+ mov eax, gs:[si+0] ; Get VSM's PCI address
+ mov edi, gs:[si+4] ; Get VSM's EDI
+ mov [Nested_PCI], eax ; Required by PCI_Handler
+ mov [Nested_EDI], edi ; Required if INS
+ add esi, VSM_STACK_FRAME - 4
+ add esi, [Current_VSM] ; Ptr to EAX on VSM's stack
+ mov [Nested_EAX], esi
+
+ServiceNow:
+
+ mov gs:(VSM_Header).SysStuff.RunFlag, RUN_FLAG_READY
+Reschedule:
+ add [SchedulerStack], 4 ; Re-schedule the interrupted VSM
+
+ mov ebp, [SMI_Sources] ; Needed by RunHandlers
+
+ ; Update the clock count used by the VSM
+ rdtsc
+ sub eax, gs:(VSM_Header).SysStuff.StartTime
+ xor edx, edx
+ add gs:(VSM_Header).SysStuff.Clocks+0, eax
+ adc gs:(VSM_Header).SysStuff.Clocks+4, edx
+
+ jmp RunHandlers
+
+
+ ;
+ ; The SMI is asynchronous
+ ;
+AsyncSMI:
+ or ebx, ebx ; If null SMI, just return to VSM
+ jz short NoPreempt
+
+ cmp gs:(VSM_Header).SysStuff.RunFlag, RUN_FLAG_SLEEPING
+ je Reschedule
+
+ jmp ServiceNow
+
+ ; Is this a high priority SMI ?
+; test ebx, [HiPrioritySMIs]
+; jnz short ServiceNow ; Yes, execute SMI handlers
+
+
+ ;
+ ; Resumes to a VSM from an low-priority asynchronous SMI
+ ;
+NoPreempt:
+ ;
+ ; Resumes to a VSM from a system call
+ ;
+ExitSysCall: ; Return to caller
+ rsdc ss, gs:(VSM_Header)._SS
+ mov sp, word ptr gs:(VSM_Header).SysStuff.SavedESP
+ rsdc ds, gs:(VSM_Header)._DS
+ RESTORE_STATE
+ rsm
+
+
+
+
+
+
+
+;***********************************************************************
+; The current VSM has emptied its message queue. It will not be *
+; executed again until a new message is entered into its queue. *
+; NOTE: SysMgr will be using the last VSM's stack. *
+;***********************************************************************
+EmptyMsgQueue:
+
+
+ mov gs:(VSM_Header).SysStuff.RunFlag, RUN_FLAG_INACTIVE
+ jmp short UpdateClocks
+
+Sys_Exit:
+ ; System calls should not count as an SMI
+ sub gs:(VSM_Header).SysStuff.NumSMIs+0, 1 ; Decrement number of SMIs
+ sbb gs:(VSM_Header).SysStuff.NumSMIs+4, 0
+UpdateClocks:
+
+
+ ; Update the clock count used by the VSM
+ rdtsc
+ sub eax, gs:(VSM_Header).SysStuff.StartTime
+ xor edx, edx
+ add gs:(VSM_Header).SysStuff.Clocks+0, eax
+ adc gs:(VSM_Header).SysStuff.Clocks+4, edx
+
+ jmp Dispatcher
+
+
+
+;***********************************************************************
+; Schedules a VSM to execute
+;***********************************************************************
+Schedule_VSM proc pascal uses bx \
+ Vsm: DWORD
+
+ mov eax, [Vsm]
+ test eax, 0FFFF0000h ; Is it a callback ?
+ jz Schedule
+
+ ; Mark VSM ready, if not already on scheduler's stack
+ mov bl, RUN_FLAG_READY
+ xchg bl, fs:(VSM_Header PTR [eax]).SysStuff.RunFlag
+; cmp bl, RUN_FLAG_READY
+; je short Exit
+
+Schedule:
+ mov bx, [SchedulerStack] ; Get scheduler's ptr
+ add bx, 4 ; Push the VSM
+ mov [bx], eax
+ mov [SchedulerStack], bx ; Update scheduler's ptr
+Exit: ret
+
+Schedule_VSM endp
+
+
+
+
+
+
+;***********************************************************************
+;***********************************************************************
+;***********************************************************************
+;* *
+;* Nested SMI Entry Point *
+;* *
+;* A nested SMI can occur for one of four reasons: *
+;* 1) A system call *
+;* 2) An asynchronous event (timer, GPIO, etc.) *
+;* 3) A trapped I/O from a VSM (virtual register, PCI access) *
+;* 4) Return from a BIOS callback *
+;* *
+;***********************************************************************
+;***********************************************************************
+;***********************************************************************
+ align 16
+Nested_SMI:
+
+ ; Set DS descriptor to System Manager's
+ rsdc ds, cs:[Data_Descriptor]
+
+
+ ; Is it a system call (SMINT) ?
+ test byte ptr gs:(VSM_Header).SysStuff.State.SMI_Flags, 1000b
+ jz NotSysCall
+
+;*************************************************************************
+;*************************************************************************
+;*************************************************************************
+; *
+; SMI is a system call *
+; *
+; The VSM's registers are saved on the VSM's stack. *
+; DS: and SS:SP are initialized to SysMgr's environment. *
+; *
+; On Entry: *
+; AX = System call code *
+; Other registers, depending on the system call *
+; *
+;*************************************************************************
+;*************************************************************************
+;*************************************************************************
+SystemCall:
+ cmp ax, SYS_CODE_EXIT ; Check for valid system code
+ ja short IllegalSysCall ; If invalid, record an error
+
+
+ mov [VSMs_EAX], eax
+ SAVE_STATE ; Save the VSM's state
+ mov word ptr gs:(VSM_Header).SysStuff.SavedESP, sp
+
+ ; Setup System Manager's stack
+ rsdc ss, [Stack_Descriptor]
+ lea sp, [StartSaveArea]
+
+ ; Dispatch to system call routine
+ movzx eax, word ptr [VSMs_EAX]
+ jmp [SysCall_Table + eax*2]
+
+
+
+
+;***********************************************************************
+; An illegal system call was detected
+;***********************************************************************
+IllegalSysCall:
+ ; Is it ResumeFromRAM ?
+ cmp ax, SYS_RESUME_FROM_RAM
+ je ResumeFromRAM
+
+ mov di, ERR_UNDEF_SYS_CALL
+ mov ebx, eax ; Info1 = system call code
+ mov ecx, [Current_VSM] ; Info2 = offending VSM
+ mov ax, SYS_CODE_ERROR ; Fake a SYS_CODE_ERROR
+ jmp SystemCall
+
+
+
+;***********************************************************************
+ ; BIOS is resuming after a Save-to-RAM:
+ ; 1) Re-init VSA state
+ ; 2) Re-schedule the suspended VSM
+ ; 3) Go to VSM dispatcher
+;***********************************************************************
+ResumeFromRAM:
+ rsdc fs, [Flat_Descriptor] ; Set FS to a 4 GB flat segment
+ rsdc es, [Flat_Descriptor] ; Set ES to a 4 GB flat segment
+
+ mov ebx, [Current_VSM]
+ mov ax, fs:(VSM_Header PTR [ebx]).SysStuff.ResumeVector
+ mov fs:(VSM_Header PTR [ebx]).SysStuff.State.Next_IP, ax
+ mov fs:(VSM_Header PTR [ebx]).SysStuff.RunFlag, RUN_FLAG_READY
+ jmp ExecuteTask
+
+
+
+
+
+
+
+
+
+ align 4
+Current_VSM dd 0
+HardwareInfo Hardware { }
+BracketFlag db 0
+
+
+
+
+
+;*************************************************************************************
+;
+; IMPLEMENTATION NOTES:
+;
+; - The scheduler's stack and System Manager's stack grow toward each other.
+;
+; - The variables at StartSaveArea are grouped together because they, along with
+; the SMM header, represent the entire state of the interrupted task. This is
+; important since this state must be saved & restored across a BIOS callback.
+;
+;*************************************************************************************
+ align 2
+SchedulerStack dw OFFSET Scheduled_VSMs
+
+ align 4
+Scheduled_VSMs dd 0 ; Marks bottom of scheduler's stack
+
+
+
+ ORG SYSMGRS_STACK
+StartSaveArea:
+Saved_PCI dd ?
+
+; NOTE: the following 8 variables must be in the correct order for PUSHAD/POPAD
+Saved_EDI dd ?
+Saved_ESI dd ?
+Saved_EBP dd ?
+ dd ? ; ESP (not used)
+Saved_EBX dd ?
+Saved_EDX dd ?
+Saved_ECX dd ?
+Saved_AX:
+Saved_EAX dd ?
+SysMgrStack: ; <==== System Manager's stack begins here
+
+Saved_ESP dd OFFSET SysMgrStack ; DO NOT MOVE !!!
+
+
+;
+; NOTE: The SET_REGISTER, GET_REGISTER, GET_DESCRIPTOR, & SET_DESCRIPTOR
+; macros assume these are in this exact location and order:
+Saved_SS Descriptor { }
+Saved_DS Descriptor { }
+Saved_ES Descriptor { }
+Saved_FS Descriptor { }
+Saved_GS Descriptor { }
+
+Header_Addr dd 0 ; Ptr to end of SMM header
+
+IDT_Selector dd 0 ; Saved IDT state
+IDT_Base dd 0
+IDT_Limit dd 0
+
+
+
+ dw 0 ; Pad
+EndSaveArea label byte
+;
+; This table contains System Manager structures accesses by INIT.EXE and INFO.EXE.
+; Must match the InfoStuff structure in VSA2.H
+;
+ ORG SPECIAL_LOC
+
+ dw OFFSET Events
+ dw OFFSET MSRs
+ dw OFFSET INT_Vectors
+ dw OFFSET HardwareInfo
+IRQ_Base dd 0 ; Memory-mapped location of Internal IRQs
+IRQ_Mask dd 0 ; Mask of IRQs to be generated
+; NOTE: The following fields are not referenced by VSMs.
+; They are in this structure so INIT.ASM can initialize them.
+SysMgr_VSM dd 0 ; Logical address of System Manager
+SMI_Base dd 0 ; Memory-mapped location of SMI sources
+ dw OFFSET Header_Addr ; Offset of SysMgr.SysStuff.State
+ dw OFFSET StartSaveArea ; Initial value of SysMgr.SysStuff.SavedESP
+ dw OFFSET MSRs
+ dw OFFSET NumDescriptors
+
+Nested_EAX dd 0 ; Flat ptr to interrupted VSM's EAX
+Nested_EDI dd 0 ; Value of interrupted VSM's EDI
+Nested_PCI dd 0 ; PCI config address of interrupted VSM
+Nested_Flag dd 0
+
+VSMs_EAX dd 0
+Nested_ES Descriptor {}
+
+
+_CODE ENDS
+
+ END Start
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/sysmgr.h b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/sysmgr.h
new file mode 100755
index 0000000..1d84b33
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/sysmgr.h
@@ -0,0 +1,207 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+
+
+// Build flags for various optional features
+#define HISTORY 0 // History support (value determines size of history buffer; 0=disabled)
+#define CHECKED_BUILD 1 // Perform internal sanity checks
+
+#define SUPPORT_CAPABILITIES 1 // Enables support for PCI capabilities list
+#define SUPPORT_PRIORITY 0 // Enables message priority logic
+#define SUPPORT_FS2 1 // Enables MBIU1 descriptors so FS2 sees same map as GX2
+
+#define USB_FIX 0 // 0=none 1=old 2=new
+#define MAX_INT 0x1B // Maximum INT vector supported for BIOS callbacks
+
+
+#define SYS_YIELD 0x40000000L // Must be >= bit 24
+
+#define DBG_PORT 0x84
+#define VSA_POST 0x84 // I/O port for VSA POST codes
+
+#define EXTRA_SAVE 4 // State saved other than registers
+#define VSM_STACK_FRAME (8*4+EXTRA_SAVE)// PUSHAD + EXTRA_SAVE
+
+#define SPECIAL_LOC 0xA80 // Determines depth of SysMgr's stack
+#define STACK_OFFSET 0x94 // Should be: EndSaveArea - StartSaveArea
+#define SYSMGRS_STACK (SPECIAL_LOC-STACK_OFFSET)
+
+#define MAX_REGISTRATIONS 100 // # entries in Events[]
+
+// VSM specific definitions
+#define CODE_ATTR 0x9B
+#define DATA_ATTR 0x93
+#define VSM_CR0 0x00000014
+#define VSM_EFLAGS 0x00000002
+#define VSM_DR7 0x00000400
+#define VSM_STACK_SIZE 0x300 // Size of allocated stack in bytes
+#define BIOS_STACK_SIZE 0x100
+
+// VSM States
+#define RUN_FLAG_INACTIVE 0x00 // VSM is idle
+#define RUN_FLAG_SLEEPING 0x55 // VSM is in Standby/Suspend
+#define RUN_FLAG_ACTIVE 0xAA // VSM is running or scheduled to run
+#define RUN_FLAG_WAITING 0xEE // VSM has yielded control
+#define RUN_FLAG_BLOCKED 0xBB // VSM is blocked
+#define RUN_FLAG_READY 0x77 // VSM is ready to execute
+
+
+// System calls
+#define SYS_CODE_EVENT 0x0000 // Event registration
+#define SYS_CODE_YIELD 0x0001 // VSM is yielding control
+#define SYS_CODE_SW_INT 0x0002 // Software Interrupt (INT xx)
+#define SYS_CODE_PASS_EVENT 0x0003 // VSM did not handle an event
+#define SYS_CODE_UNLOAD 0x0004 // Unload VSM
+#define SYS_CODE_REGISTER 0x0005 // Get/Set special registers
+#define SYS_CODE_PCI_ACCESS 0x0006 // Access a PCI dword with trapping disabled
+#define SYS_CODE_SET_VIRTUAL 0x0007 // Set virtual register
+#define SYS_CODE_GET_VIRTUAL 0x0008 // Get virtual register
+#define SYS_CODE_BROADCAST 0x0009 // Broadcast a message to one or more VSMs
+#define SYS_CODE_STATE 0x000A // Save/Restore non-SMM state
+#define SYS_CODE_ERROR 0x000B // Report error
+#define SYS_CODE_RESOURCE 0x000C // Reserve resource
+#define SYS_CODE_DECODE 0x000D // Set resource to be subtractive/positive decode
+#define SYS_CODE_DESCRIPTOR 0x000E // Get descriptor of virtualized PCI BAR
+#define SYS_CODE_LOOKUP 0x000F // Lookup routing for MBus device
+#define SYS_CODE_IRQ_MAPPER 0x0010 // Set IRQ mapping (CS5535 only)
+#define SYS_CODE_RESULT 0x0011 // Return virtualized result
+#define SYS_CODE_DUPLICATE 0x0012 // Duplicate a VSM
+#define SYS_CODE_EXIT 0x0013 // Exit to System Manager
+
+#define GET_REG 0x80
+#define SET_REG 0x81
+#define GET_HDR 0x82
+#define SET_HDR 0x83
+#define GET_DESCR 0x84
+#define SET_DESCR 0x85
+
+
+// Fields in SMM header flag
+#define SMI_FLAGS_CS_WRITABLE 0x0001 // "Cw" bit CS is writable
+#define SMI_FLAGS_OUTPUT 0x0002 // "I" bit I/O indicator
+#define SMI_FLAGS_REP 0x0004 // "P" bit REP indicator
+#define SMI_FLAGS_SMINT 0x0008 // "S" bit SMI occured due to a SMINT
+#define SMI_FLAGS_HALT 0x0010 // "H" bit SMI occured during CPU halt
+#define SMI_FLAGS_MEMORY 0x0020 // "M" bit 0=I/O, 1=memory
+#define SMI_FLAGS_EXT 0x0040 // "X" bit External SMI source
+#define SMI_FLAGS_VGA 0x0080 // "V" bit VGA emulation source
+#define SMI_FLAGS_NESTED 0x0100 // "N" bit Nested SMI
+#define SMI_FLAGS_CS_READABLE 0x8000 // "Cr" bit CS is writable
+
+
+
+
+typedef void (* SMI_Handler)(void);
+
+typedef struct {
+ SMI_Handler Handler;
+ unsigned long SMI_Mask;
+} SMI_ENTRY;
+
+
+
+typedef struct {
+ unsigned long Vsm;
+
+ union {
+ struct {
+ unsigned long Param1;
+ unsigned long Param2;
+ unsigned long Param3;
+ };
+ struct { // Timers
+ unsigned long Interval;
+ unsigned short Handle;
+ unsigned char Timer;
+ unsigned char Attr;
+ unsigned long RemainingInterval;
+ };
+ struct { // GPIOs
+ unsigned short Pin;
+ unsigned short Pme;
+ unsigned short Attributes;
+ unsigned short Pm1;
+ unsigned long CurrentEdge;
+ };
+ struct { // PCI header
+ unsigned short PCI_Addr;
+ unsigned short Unused;
+ unsigned short PCI_Mask;
+ unsigned short Flags;
+ };
+ struct { // I/O trap & timeout
+ unsigned short IO_Base;
+ unsigned short IO_Timeout;
+ unsigned short IO_Range;
+ };
+ struct { // Virtual Register
+ unsigned long ClassLow;
+ unsigned long ClassHigh;
+ };
+
+ };
+
+ unsigned long Timestamp[2];
+ unsigned char Index;
+ unsigned char Link;
+ unsigned short Priority;
+} EVENT_ENTRY;
+
+typedef struct {
+ unsigned long Vsm;
+ unsigned long Event;
+ unsigned long Param1;
+ unsigned long Param2;
+ unsigned long Count;
+ unsigned long TimeStamp[2];
+} EVENT_HISTORY;
+
+
+typedef struct {
+ unsigned short History_Array;
+ int * History_Start;
+ int * History_End;
+ int * History_Wrap;
+ unsigned short HistoryEntries;
+} HISTORY_INFO;
+
+
+
+
+
+
+
+//
+// An instance of this structure is found in the System Manager at offset SPECIAL_LOC
+//
+typedef struct {
+ unsigned short Events; // Events array
+ unsigned short Descriptors; // MBus Descriptors array
+ unsigned short Vectors; // INT vectors
+ unsigned short HardwareInfo; // Hardware structure
+ unsigned long IRQ_Base; // Used by SYS_GENERATE_IRQ
+ unsigned long IRQ_Mask; // Used by SYS_GENERATE_IRQ
+ unsigned long SysMgr_VSM; // Used in SysMgr only
+ unsigned long SMI_Base; // Used in SysMgr only
+ unsigned short Header_Addr; // Used in SysMgr only
+ unsigned short SysMgr_Stack; // Used in SysMgr only
+ unsigned short MSRs; // Used for DOS_BUILD
+ unsigned short NumDescrs; // Used for DOS_BUILD
+} InfoStuff;
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/timeout.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/timeout.c
new file mode 100755
index 0000000..7285402
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/timeout.c
@@ -0,0 +1,729 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* - Handles I/O inactivity counters
+//******************************************************************************
+
+
+
+#include "VSA2.H"
+#include "PROTOS.H"
+#include "GX2.H"
+#include "VPCI.H"
+#include "DESCR.H"
+#include "CS5536.H"
+
+// External prototypes:
+void Deallocate_Descriptor(DESCRIPTOR *);
+
+
+// External variables:
+extern ULONG LookupMbiu;
+extern ULONG ClocksPerMs;
+extern DESCRIPTOR MSRs[];
+extern UCHAR NumDescriptors;
+extern ULONG Mbiu2;
+extern UCHAR NumMbius;
+extern MBIU_INFO MbiuInfo[MAX_MBIU];
+extern ULONG MbiuSkipFlags[];
+extern Hardware HardwareInfo;
+
+#define NUM_PHYSICAL_COUNTERS 7 // Number of physical statistic counters
+#define NUM_LOGICAL_COUNTERS 20 // Number of logical statistic counters
+#define NUM_LINKED_DESCRIPTORS 3 // Number of descriptors per logical counter
+
+// Local variables:
+UCHAR NumPhysCounters= 0;
+
+typedef struct {
+ ULONG MsrAddr; // MSR address of STATISTICS_CNT
+ ULONG Prescaler;
+ ULONG Mask; // IOD_MASK field
+ ULONG SFlags;
+ USHORT StandbyFlag;
+ USHORT Timeout;
+ USHORT MbiuNumber;
+} PHYSICAL_COUNTERS;
+
+
+typedef struct {
+ ULONG Mask;
+ USHORT Address;
+ USHORT DeviceID;
+ USHORT Timeout;
+ UCHAR PhysIndex; // Index to physical counter
+ UCHAR DescrIndex[NUM_LINKED_DESCRIPTORS]; // Indices to descriptors
+} LOGICAL_COUNTERS;
+
+PHYSICAL_COUNTERS PhysCounter[NUM_PHYSICAL_COUNTERS];
+LOGICAL_COUNTERS LogCounter[NUM_LOGICAL_COUNTERS];
+
+
+//***********************************************************************
+// Initializes a logical timeout counter
+//***********************************************************************
+void InitLogicalCounter(LOGICAL_COUNTERS * LogicalPtr)
+{ int i;
+
+ LogicalPtr->Mask = 0x00000000;
+ for (i = 0; i < NUM_LINKED_DESCRIPTORS; i++) {
+ LogicalPtr->DescrIndex[i] = 0xFF;
+ }
+}
+
+
+//***********************************************************************
+// Deallocates a logical counter.
+// Deallocates all descriptors associated with a logical counter,
+// unless the descriptor is also being used for an I/O trap.
+//***********************************************************************
+void DeallocateLogicalCounter(LOGICAL_COUNTERS * LogicalPtr)
+{ int i, j;
+
+
+ for (i = 0; i < NUM_LINKED_DESCRIPTORS; i++) {
+ // Get index of I/O descriptor used for this logical counter
+ j = LogicalPtr->DescrIndex[i];
+ if (j == 0xFF) {
+ // No more linked descriptors
+ break;
+ }
+
+ // If not used for I/O trap or virtualized PCI BAR
+ if (!(MSRs[j].Flag & IO_TRAP) && !(MSRs[j].Owner)) {
+ Deallocate_Descriptor(&MSRs[j]);
+ }
+ }
+
+ // Deallocate logical counter
+ InitLogicalCounter(LogicalPtr);
+}
+
+
+//***********************************************************************
+// Initializes the logical timeout counter structures
+//***********************************************************************
+void InitLogicalCounters(void)
+{ int i;
+ register LOGICAL_COUNTERS * LogicalPtr;
+
+ // Initialize logical counters
+ LogicalPtr = &LogCounter[0];
+ for (i=0; i < NUM_LOGICAL_COUNTERS; i++) {
+ InitLogicalCounter(LogicalPtr++);
+ }
+}
+
+//***********************************************************************
+// Initializes the physical timeout counter structures & MSRs
+// Called from Init_MBIU().
+//***********************************************************************
+void InitStatCounters(ULONG Msr, UCHAR NumStatCntrs)
+{ int i;
+ ULONG MsrData[2], SFlags;
+ register PHYSICAL_COUNTERS * PhysPtr;
+ static UCHAR Shift=0;
+
+ // Initialize physical counters
+ MsrData[0] = MsrData[1] = 0x00000000;
+ (USHORT)Msr = MSR_STATISTICS_CNT;
+ SFlags = 1L << Shift;
+
+ // Prepare shift count for next MBIU
+ Shift += 8;
+ for (i = 0; i < NumStatCntrs; i++) {
+
+ // Initialize the statistic MSR
+ Write_MSR(Msr+0, MsrData); // MSR_STATISTICS_CNT
+ Write_MSR(Msr+1, MsrData); // MSR_STATISTICS_MASK
+ Write_MSR(Msr+2, MsrData); // MSR_STATISTICS_ACTION
+
+ // Initialize next physical counter
+ if (NumPhysCounters < NUM_PHYSICAL_COUNTERS) {
+
+ PhysPtr = &PhysCounter[NumPhysCounters];
+ PhysPtr->MbiuNumber = NumMbius;
+ PhysPtr->MsrAddr = Msr;
+ PhysPtr->Mask = 0x00000000;
+ PhysPtr->StandbyFlag = 0;
+ PhysPtr->SFlags = SFlags;
+ SFlags <<= 1;
+
+ // Determine 16-bit prescaler
+ if ((Msr & ROUTING) == Mbiu2) {
+ // Clock to Southbridge statistic counters is 66 MHz.
+ PhysPtr->Prescaler = 66000L/8;
+ } else {
+ // Clock to Northbridge statistic counters is DRAM clock.
+ PhysPtr->Prescaler = HardwareInfo.DRAM_MHz * 1000L/8;
+ // If memory is DDR, DRAM clock is running at 1/2 MBUS frequency
+ if (!(Read_MSR_LO(0x4C000014) & 0x400)) {
+ // so adjust the prescaler
+ PhysPtr->Prescaler >>= 1;
+ }
+ }
+ // Shift into PREDIV field
+ PhysPtr->Prescaler <<= 8;
+ // Set counter attributes
+ (UCHAR)PhysPtr->Prescaler = (ALWAYS_DEC | HIT_LDEN | ZERO_SMI);
+
+ // Increment number of statistics counters.
+ NumPhysCounters++;
+
+ } else {
+ Log_Error("The PhysCounter structure has fewer entries than # of h/w counters");
+ // Continue initializing, but don't record MSR in array
+ }
+
+ // Advance to next statistic MSR
+ Msr += 4;
+ }
+}
+
+
+
+
+
+
+
+//***********************************************************************
+// Finds the Address corresponding to a bit set in MBD_MSR_SMI.
+// Clears the next set bit in the EventMask variable.
+//***********************************************************************
+USHORT Get_Timeout(ULONG SFlag, UCHAR * StartIndex)
+{ UCHAR i, j;
+ USHORT Address = 0x0000;
+ register PHYSICAL_COUNTERS * PhysPtr;
+ register LOGICAL_COUNTERS * LogicalPtr;
+
+ // Find the correct logical counter & return the associated address
+ LogicalPtr = &LogCounter[* StartIndex];
+ for (i = * StartIndex; i < NUM_LOGICAL_COUNTERS; i++) {
+ // Is logical counter in use ?
+ if (LogicalPtr->Mask != 0x00000000) {
+
+ // Get physical counter to which it is linked
+ j = LogicalPtr->PhysIndex;
+ PhysPtr = &PhysCounter[j];
+
+ // Is this counter generating an event ?
+ if (PhysPtr->SFlags & SFlag) {
+
+ // Yes, return either the DeviceID or the Inactive Address
+ Address = LogicalPtr->DeviceID;
+ if (!Address) {
+ Address = LogicalPtr->Address;
+ }
+ break;
+ }
+ }
+ LogicalPtr++;
+ }
+
+ // Return logical index
+ * StartIndex = i+1;
+
+ return Address;
+}
+
+
+
+//***********************************************************************
+// Enables/Disables SMIs for a statistic counter
+//***********************************************************************
+void pascal StatCntrSMI(ULONG MsrAddr, UCHAR EnableFlag)
+{ ULONG MsrData[2], Mask;
+ int j;
+
+ MsrData[0] = MsrData[1] = 0x00000000;
+ if (!EnableFlag) {
+ Write_MSR(MsrAddr, MsrData);
+ Write_MSR(MsrAddr+2, MsrData);
+ }
+
+ j = ((UCHAR)MsrAddr - MSR_STATISTICS_CNT) / 4;
+ j++; // HW Emulation is bit 0
+
+
+ (USHORT)MsrAddr = MBD_MSR_SMI;
+
+ Read_MSR(MsrAddr, MsrData);
+ Mask = 1L << j;
+ if (EnableFlag) {
+ MsrData[0] &= ~Mask;
+ } else {
+ MsrData[0] |= Mask;
+ }
+ Write_MSR(MsrAddr, MsrData);
+
+}
+
+
+
+//***********************************************************************
+// Sets the IOD_MASK field of STATISTIC_MASK
+//***********************************************************************
+void pascal Set_IOD_MASK(PHYSICAL_COUNTERS * PhysPtr)
+{
+ Write_MSR_HI(PhysPtr->MsrAddr | 1, PhysPtr->Mask);
+}
+
+
+//***********************************************************************
+// Disables an inactivity timer for the specified parameters.
+// Param1:
+// 31:16 = Timeout in seconds
+// 15:00 = I/O Base
+// Param2:
+// 31:16 = Flags (ONE_SHOT, WRITES_ONLY, READS_ONLY)
+// 15:00 = I/O Range
+//***********************************************************************
+void pascal Clr_MBus_IO_Timeout(ULONG Param1, ULONG Param2)
+{ int i;
+ USHORT Address, Range, Timeout;
+ MBIU_INFO * MbiuPtr;
+ register PHYSICAL_COUNTERS * PhysPtr;
+ register LOGICAL_COUNTERS * LogicalPtr;
+
+ // Unpack parameters
+ Range = (USHORT)Param2;
+ Address = (USHORT)Param1;
+ Timeout = (USHORT)(Param1 >> 16);
+
+ // Find the corresponding logical counter
+ LogicalPtr = &LogCounter[0];
+ for (i = 0; i < NUM_LOGICAL_COUNTERS; i++) {
+ if (LogicalPtr->Address == Address) {
+ break;
+ }
+ LogicalPtr++;
+ }
+
+ if (i >= NUM_LOGICAL_COUNTERS) {
+ // ERROR: VSM is unregistering a non-existent timeout.
+ Report_VSM_Error(ERR_UNREGISTRATION, Address, 0);
+ return;
+ }
+
+ // Get physical counter corresponding to this logical counter
+ PhysPtr = &PhysCounter[LogicalPtr->PhysIndex];
+
+ // Clear IOD_MASK in the corresponding physical counter
+ PhysPtr->Mask &= ~LogicalPtr->Mask;
+ Set_IOD_MASK(PhysPtr);
+
+ // Decrement timer count on this MBIU
+ MbiuPtr = &MbiuInfo[PhysPtr->MbiuNumber];
+ if (MbiuPtr->ActiveCounters) {
+ MbiuPtr->ActiveCounters--;
+ }
+
+
+ // If no more timeouts for this physical counter...
+ if (PhysPtr->Mask == 0x00000000) {
+ PhysPtr->StandbyFlag = 0;
+
+ // Disable the statistics counter
+ StatCntrSMI(PhysPtr->MsrAddr, 0);
+
+
+ if (MbiuPtr->ActiveCounters == 0) {
+ // Restore clock gating on this MBIU
+ if (MbiuPtr->ActiveCounters == 0) {
+ Write_MSR_LO(MbiuPtr->Mbiu + MBD_MSR_PM, MbiuPtr->ClockGating);
+ }
+ }
+ } else {
+ if (MbiuPtr->ActiveCounters == 0) {
+ Log_Error("MbiuInfo->ActiveCounters is out of sync");
+ }
+ }
+
+ // Deallocate descriptor(s)
+ DeallocateLogicalCounter(LogicalPtr);
+
+}
+
+//***********************************************************************
+// Enables an inactivity timer for the specified I/O Range
+// Param1:
+// 31:16 = Timeout in seconds
+// 15:00 = I/O Base
+// Param2:
+// 31:16 = Flags (NOT_GLIUx, ONE_SHOT, WRITES_ONLY, READS_ONLY)
+// 15:00 = I/O Range
+//***********************************************************************
+void pascal Set_MBus_IO_Timeout(USHORT Address, USHORT Timeout, USHORT Range, USHORT Attr, USHORT DeviceID)
+{ ULONG MsrAddr, MsrData[2], Addr, Candidate, Flags;
+ UCHAR i, j, k;
+ MBIU_INFO * MbiuPtr;
+ register DESCRIPTOR * Descr;
+ register PHYSICAL_COUNTERS * PhysPtr;
+ register LOGICAL_COUNTERS * LogicalPtr;
+
+ Flags = (ULONG)Attr << 16;
+
+ // Find an available logical counter
+ LogicalPtr = &LogCounter[0];
+ for (i=0; i < NUM_LOGICAL_COUNTERS; i++) {
+ if (LogicalPtr->Mask == 0x00000000) {
+ break;
+ }
+ LogicalPtr++;
+ }
+
+ if (i >= NUM_LOGICAL_COUNTERS) {
+ Log_Error("The LogCounter structure is not large enough");
+ return;
+ }
+
+
+ // Record info about this timeout
+ LogicalPtr->Address = Address;
+ LogicalPtr->DeviceID = DeviceID;
+ LogicalPtr->Timeout = Timeout;
+
+
+ // Set Flags:NOT_GLIUx for GLIUs with no available counters
+ for (k=0; k < NumMbius; k++) {
+
+ // Skip this MBIU ?
+ if (Flags & MbiuSkipFlags[k]) {
+ continue;
+ }
+ MbiuPtr = &MbiuInfo[k];
+ j = MbiuPtr->NumCounters;
+
+ //
+ PhysPtr = &PhysCounter[0];
+ for (i=0; i < NumPhysCounters; i++) {
+ // Is this counter on the current GLIU ?
+ if ((MbiuPtr->Mbiu & ROUTING) == (PhysPtr->MsrAddr & ROUTING)) {
+ // Is it available ?
+ if (PhysPtr->Mask) {
+ // No, is it the last counter on this GLIU ?
+ if (--j == 0) {
+ // Yes, then exclude from search
+ Flags |= MbiuSkipFlags[k];
+ break;
+ }
+ }
+ }
+ PhysPtr++;
+ }
+ }
+
+ // Allocate descriptor(s) for address range
+ Addr = Flags; // Set Addr = Flags::Address
+ (USHORT)Addr = Address;
+ k = 0;
+ while (Range) {
+
+ // Find existing descriptor(s) that match Address
+ j = Find_Matching_IO_Descriptor(&Addr, &Range, 1);
+ if (j == DESCRIPTOR_NOT_FOUND) {
+ // No compatible descriptor exists, so create one
+ // and route it to the subtractive port.
+ j = Setup_IO_Descriptor(&Addr, &Range, 1);
+ if (j == DESCRIPTOR_NOT_FOUND) {
+ // Error: No free descriptors
+ k = 0xFF;
+ break;
+ }
+ }
+
+ Descr = &MSRs[j];
+
+ // Record the descriptor index
+ LogicalPtr->DescrIndex[k] = j;
+
+ if (k++ == 0) {
+ // Record 1st descriptor
+ MsrAddr = Descr->MsrAddr;
+ } else {
+ // Check that all descriptors are on same MBIU
+ if ((MsrAddr & ROUTING) != (Descr->MsrAddr & ROUTING)) {
+ // No free descriptors on same MBIU
+ k = 0xFF;
+ break;
+ }
+ }
+ // Add the new descriptor to IOD_MASK
+ LogicalPtr->Mask |= 1L << ((UCHAR)Descr->MsrAddr - MSR_IO_DESCR);
+ }
+
+
+ // If no descriptor found...
+ if (k == 0xFF) {
+ // ERROR: Not enough descriptors to handle request
+ Report_VSM_Error(ERR_NO_MORE_DESCRIPTORS, Address, 0);
+
+ // Deallocate descriptor(s) and logical counter
+ DeallocateLogicalCounter(LogicalPtr);
+ return;
+ }
+
+ // Find an appropriate hardware statistic counter
+ Candidate = 0;
+ for (i=0; i < NumPhysCounters; i++) {
+
+ PhysPtr = &PhysCounter[i];
+
+ // Physical counter must be on the same MBIU as the I/O descriptor
+ if ((PhysPtr->MsrAddr & ROUTING) != (Descr->MsrAddr & ROUTING)) {
+ continue;
+ }
+
+ if (PhysPtr->Timeout == Timeout) {
+ // If same timeout, the leverage same counter
+ break;
+ }
+
+ // Is this counter being used for Standby inactivity detection ?
+ if (PhysPtr->StandbyFlag) {
+ // Yes, is the request for Standby ?
+ if (Flags & FOR_STANDBY) {
+ // Yes, then must use the same physical counter
+ break;
+ }
+ }
+
+ // Mark physical counter as a candidate
+ Candidate |= 1L << i;
+ }
+
+ // If an existing counter can't be leveraged, find a new one
+ if (i >= NumPhysCounters) {
+ // Among the candidates, find an unused counter
+ for (i=0; i < NumPhysCounters; i++) {
+ if (Candidate & (1L << i)) {
+ PhysPtr = &PhysCounter[i];
+ if (!(PhysPtr->Mask)) {
+ break;
+ }
+ }
+ }
+ }
+
+ // If physical counter is found, link it to the descriptor
+ if (i < NumPhysCounters) {
+
+ // Increment timer count on this MBIU
+ MbiuPtr = &MbiuInfo[PhysPtr->MbiuNumber];
+ MbiuPtr->ActiveCounters++;
+ // Turn off clock gating on this MBIU
+ Write_MSR_LO(MbiuPtr->Mbiu + MBD_MSR_PM, Read_MSR_LO(MbiuPtr->Mbiu + MBD_MSR_PM) & 0xFFFFFFF0);
+
+ // Record physical counter used for the logical counter
+ LogicalPtr->PhysIndex = i;
+
+ // Mark descriptor as used for I/O timeout
+ Descr->Flag |= IO_TIMEOUT;
+
+ // Record info about this timer
+ PhysPtr->Timeout = Timeout;
+ PhysPtr->Mask |= LogicalPtr->Mask;
+
+ // Set flag if counter is being used for Standby inactivity detection
+ if (Flags & FOR_STANDBY) {
+ PhysPtr->StandbyFlag = 1;
+ }
+
+ // Set STATISTIC_CNT[LOAD_VAL]
+ MsrAddr = PhysPtr->MsrAddr;
+ MsrData[0] = MsrData[1] = Timeout * 8*1000L;
+ Write_MSR(MsrAddr, MsrData);
+
+ // Link counter to the descriptor
+ Set_IOD_MASK(PhysPtr);
+
+ // Set STATISTIC_ACTION[PREDIV]
+ // Set Prescaler to decrement Count every ms
+ Write_MSR_LO(MsrAddr+2, PhysPtr->Prescaler);
+
+
+ // Enable the statistics counter in MBD_MSR_SMI
+ StatCntrSMI(MsrAddr, 1);
+
+ return;
+ }
+
+
+ // ERROR: Not enough statistics counter to handle request
+ Report_VSM_Error(ERR_NO_MORE_DESCRIPTORS, (ULONG)Address, NumPhysCounters);
+
+}
+
+
+typedef struct {
+ union {
+ ULONG dword;
+ struct {
+ USHORT IO_Base;
+ USHORT Timeout;
+ };
+ };
+} TIMEOUT_P1;
+
+typedef struct {
+ union {
+ ULONG Flags;
+ struct {
+ union {
+ USHORT Range;
+ UCHAR Instance;
+ };
+ USHORT Attributes;
+ };
+ };
+} TIMEOUT_P2;
+
+
+//***********************************************************************
+// Enables/disables an inactivity timer for an I/O Range or GLIU device.
+// Param1:
+// 31:16 = Timeout in seconds
+// 15:00 = I/O Base
+// = GLIU DeviceID if Flags[GLIU_ID] is set
+// Param2:
+// 31:16 = Flags
+// 15:00 = Length of I/O range
+// = Instance if Flags[GLIU_ID] is set
+// EnableFlag:
+// 0 = disable
+// 1 = enable
+//***********************************************************************
+void pascal MBus_IO_Timeout(ULONG Param1, ULONG Param2, UCHAR EnableFlag)
+{ UCHAR Port, ByteEnables, i, Hit;
+ USHORT Address, DeviceID = 0x0000;
+ ULONG MsrAddr;
+ register DESCRIPTOR * Descr;
+ TIMEOUT_P1 p1;
+ TIMEOUT_P2 p2;
+
+
+ // Force use of descriptors in Southbridge
+ if (!(Param2 & FOR_STANDBY)) {
+ Param2 |= NOT_GLIU0 | NOT_GLIU1;
+ }
+
+ p1.dword = Param1;
+ p2.Flags = Param2;
+
+ if (p2.Flags & GLIU_ID) {
+ p2.Flags &= ~GLIU_ID;
+
+ DeviceID = p1.IO_Base;
+
+ // Don't allow stupid requests
+ switch (DeviceID) {
+ case ID_MBIU:
+ case ID_MDD:
+ case ID_MCP:
+ case ID_VAIL:
+ // Log an error
+ Report_VSM_Error(ERR_BAD_PARAMETER, EVENT_IO_TIMEOUT, Param1);
+ return;
+ }
+
+
+ // Find specified instance of the requested device
+ MsrAddr = Find_MBus_ID(DeviceID, p2.Instance);
+ Port = (UCHAR)MsrAddr;
+
+ if (!MsrAddr) {
+ // Log an error
+ Report_VSM_Error(ERR_HW_MISMATCH, EVENT_IO_TIMEOUT, Param2);
+ return;
+ }
+
+ MsrAddr = LookupMbiu & ROUTING; // LookupMbiu was set by Find_MBus_ID()
+
+ // Find all descriptors on this MBIU/Port
+ Hit = 0;
+ for (i = 1; i < NumDescriptors; i++) {
+
+ Descr = &MSRs[i];
+
+ // Is descriptor routing to a device ?
+ Address = Descr->Address;
+ if (Address == 0x0000) {
+ continue;
+ }
+ // Is descriptor on correct MBIU ?
+ if (MsrAddr != (Descr->MsrAddr & ROUTING)) {
+ continue;
+ }
+ // Is descriptor routing to the requested device ?
+ if (Port == (Descr->MsrData[1] >> 29)) {
+
+ // Yes, determine start address of descriptor
+ switch (Descr->Type) {
+ case IOD_SC:
+ // Determine start address of IOD_SC descriptor
+ ByteEnables = (UCHAR)(Descr->MsrData[0] >> 24);
+ while (ByteEnables) {
+ if (ByteEnables & 1) {
+ break;
+ } else {
+ Address++;
+ }
+ ByteEnables >>= 1;
+ }
+ // Fall through intended
+
+ case IOD_BM:
+ // Recursive call
+ p1.IO_Base = Address;
+ p2.Range = 1;
+ MBus_IO_Timeout(p1.dword, p2.Flags, EnableFlag);
+ Hit = 1;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (Hit || DeviceID != ID_VG) {
+ DeviceID = 0x0000;
+ return;
+ }
+ // Monitor external video card activity
+ p1.IO_Base = 0x03C0;
+ p2.Range = 32;
+ }
+
+ // Check for illegal combination of flags
+ if ((p2.Flags & ALL_GLIUS) == ALL_GLIUS) {
+ // ERROR: Illegal combination of EVENT_IO_TIMEOUT flags
+ Report_VSM_Error(ERR_BAD_PARAMETER, EVENT_IO_TIMEOUT, p2.Flags);
+ return;
+ }
+
+ if (EnableFlag) {
+ Set_MBus_IO_Timeout(p1.IO_Base, p1.Timeout, p2.Range, p2.Attributes, DeviceID);
+ } else {
+ Clr_MBus_IO_Timeout(p1.dword, p2.Flags);
+ }
+}
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/timer.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/timer.c
new file mode 100755
index 0000000..541e575
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/timer.c
@@ -0,0 +1,183 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//*****************************************************************************
+//* Routines related to timer management.
+//*****************************************************************************
+
+
+#include "VSA2.H"
+#include "CHIPSET.H"
+#include "SYSMGR.H"
+#include "PROTOS.H"
+#include "TIMER.H"
+
+typedef unsigned char (* TIMER_ON)(ULONG, UCHAR);
+typedef void (* TIMER_OFF)(unsigned short);
+
+
+// External prototypes:
+extern UCHAR EnableMsTimer_5536(ULONG, UCHAR);
+extern USHORT DisableMsTimer_5536(USHORT);
+extern void pascal MarkTimerAvailable(USHORT);
+
+
+// External variables:
+extern ULONG MsgPacket[];
+extern EVENT_ENTRY Events[];
+extern ULONG ClocksPerMs;
+extern Hardware HardwareInfo;
+extern TIMERS TimerInfo[];
+
+
+// Local variables:
+TIMER_ON EnableTimer;
+TIMER_OFF DisableTimer;
+USHORT ActiveTimer;
+ULONG ActiveInterval;
+
+
+//***********************************************************************
+// Performs initialization related to timers
+//***********************************************************************
+void InitTimers(void)
+{
+
+ switch (HardwareInfo.Chipset_ID) {
+
+ case DEVICE_ID_5536:
+ EnableTimer = EnableMsTimer_5536;
+ DisableTimer = DisableMsTimer_5536;
+ break;
+ }
+}
+
+
+
+//***********************************************************************
+// This routine handles timer ticks.
+//***********************************************************************
+USHORT FilterTimer(EVENT_ENTRY * EventPtr, EVENT EventIndex)
+{ USHORT ReturnValue=0;
+ ULONG Vsm;
+ static EVENT NextToExpire;
+
+ Vsm = EventPtr->Vsm;
+
+
+ // If 1st registered timer, initialize 'next interval' variables
+ if (EventIndex == EVENT_TIMER) {
+ NextToExpire = 0;
+ }
+
+ // Only decrement timers associated with the expired h/w timer
+ if (EventPtr->Timer == ActiveTimer) {
+
+ // Has this timer expired ?
+ if (ActiveInterval >= EventPtr->RemainingInterval) {
+
+ // Yes, reset the VSM's remaining interval
+ EventPtr->RemainingInterval = EventPtr->Interval;
+
+ // Fill message packet
+ MsgPacket[1] = EventPtr->Interval;
+ MsgPacket[2] = EventPtr->Handle;
+
+ // Was timer due to a SYS_YIELD ?
+ if (EventPtr->Param2 & SYS_YIELD) {
+ // Yes, schedule the slumbering VSM
+ Schedule_VSM(Vsm);
+ }
+
+ // Return its Events[] index
+ ReturnValue = EventIndex;
+ } else {
+ // Decrement RemainingInterval by the expired timer interval
+ EventPtr->RemainingInterval -= ActiveInterval;
+ }
+
+ // Find the next interval on the current h/w timer to expire
+ if (EventPtr->RemainingInterval < Events[NextToExpire].RemainingInterval) {
+ // Ignore one-shots that just expired
+ if (ReturnValue != EventIndex || !(EventPtr->Param2 & ONE_SHOT)) {
+ NextToExpire = EventIndex;
+ }
+ }
+ }
+
+ // If no more timers, then set timer h/w to next interval
+ if (!EventPtr->Link) {
+ // Set the timer h/w to the next interval to expire
+ if (Events[NextToExpire].Vsm) {
+ Enable_Event(EVENT_TIMER, NextToExpire, 2);
+ }
+ }
+
+ return ReturnValue;
+}
+
+
+
+
+
+//***********************************************************************
+// This routine decrements all software timers. If a software timer has
+// expired, it sends an event message to the VSM. The time to the next
+// scheduled event and invokes Enable_Event() to restart the timer.
+//
+//***********************************************************************
+void pascal Timer_Handler(USHORT TimerNumber)
+{
+ // Record the active timer
+ ActiveTimer = TimerNumber;
+ ActiveInterval = TimerInfo[ActiveTimer].Interval;
+
+ // Mark this timer as available
+ MarkTimerAvailable(TimerNumber);
+
+ // Send the timer event
+ Send_Event(EVENT_TIMER, 0x00000000);
+}
+
+
+
+//*****************************************************************************
+// Enables a millisecond timer to the specified interval
+//
+// EnableFlag
+// 0 = disable
+// 1 = new registration
+// 2 = reprogram timer to new interval
+//*****************************************************************************
+void MillisecondTimer(UCHAR EnableFlag, EVENT_ENTRY * EventPtr)
+{
+ if (EnableFlag == 0) {
+
+ // Disable the h/w timer
+ DisableTimer(EventPtr->Timer);
+
+ } else {
+
+ // Program a hardware timer
+ EventPtr->Timer = (UCHAR)EnableTimer(EventPtr->RemainingInterval, EventPtr->Attr);
+
+ }
+}
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/timer.h b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/timer.h
new file mode 100755
index 0000000..76935e2
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/timer.h
@@ -0,0 +1,51 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+
+typedef struct {
+ UCHAR Timer; // Timer number
+ UCHAR Mapper; // Unrestricted Z field
+ USHORT Setup; // Scale factor & clock select
+ USHORT Period; // microseconds/count
+ ULONG Interval; // Current interval in milliseconds
+ USHORT Mask; // Bit mask
+ USHORT TimerBase; // I/O base
+} TIMERS;
+
+
+#define MFGPT_ENABLE 0x8000
+#define MFGPT_COMPARE2 0x4000
+#define MFGPT_COMPARE1 0x2000
+#define MFGPT_INITED 0x1000
+#define MFGPT_STOP_EN 0x0800
+#define MFGPT_EXT_EN 0x0400
+#define MFGPT_CMP2MODE 0x0300
+#define MFGPT_CMP2GE 0x0200
+#define MFGPT_CMP1MODE 0x00C0
+#define MFGPT_CMP1GE 0x0080
+#define MFGPT_REV_EN 0x0020
+#define MFGPT_CLK_SEL 0x0010
+#define MFGPT_SCALE_32 0x0005
+#define MFGPT_SCALE_1K 0x000A
+#define MFGPT_SCALE_2K 0x000B
+#define MFGPT_SCALE_4K 0x000C
+#define MFGPT_SCALE_8K 0x000D
+#define MFGPT_SCALE_16K 0x000E
+#define MFGPT_SCALE_32K 0x000F
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/topology.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/topology.c
new file mode 100755
index 0000000..675bed5
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/topology.c
@@ -0,0 +1,348 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//*****************************************************************************
+//* Implements tables that determine the virtualized PCI topology
+//* and register definitions.
+//*****************************************************************************
+
+#include "VSA2.H"
+#include "VPCI.H"
+#include "PCI.H"
+#include "CHIPSET.H"
+#include "CS5536.H"
+#include "SYSMGR.H"
+#include "MDD.H"
+#include "MAPPER.H"
+
+//***********************************************************************
+// Notes on Virtualized PCI Header Tables
+//
+// 1) The PCI_HEADER_ENTRY structure must contain at a minimum:
+// - Vendor & Device IDs
+// - Command/Status
+// - RevisionID/ClassCode
+// - CacheLine/LatencyTimer/HeaderType/BIST
+// 2) The Flag field of the last (and only last) entry must have EOL set.
+// 3) The Mask field contains a 1 in each bit position that is R/W,
+// except for bits 11-15 of the Status register. In this case, a set
+// bit means that this feature is reportable.
+// 4) Memory BARs require a minimum of 4 KB alignment.
+// 5) Registers up to and including BAR0 must be present and in ascending order
+//***********************************************************************
+
+// Write-to-Clear Status bits
+#define WC_STATUS_BITS ((ULONG)(SIGNALED_TARGET_ABORT | RECEIVED_TARGET_ABORT | RECEIVED_MASTER_ABORT | \
+ SIGNALED_SYSTEM_ERROR | DETECTED_PARITY_ERROR ))
+
+
+#define DEVSEL_TIMING (DEVSEL_MEDIUM)
+// Defaults
+#define DEF_STATUS (PCI_66MHZ_CAPABLE | DEVSEL_TIMING | BACK2BACK_CAPABLE)
+#define DEF_MASK (FAST_BACK_TO_BACK | PARITY_RESPONSE)
+
+// Northbridge
+#define NB_STATUS (DEF_STATUS | BUS_MASTER) & ~(BACK2BACK_CAPABLE)
+#define NB_MASK (DEF_MASK | BUS_MASTER | IO_SPACE) & \
+ ~(SERR_ENABLE | PARITY_RESPONSE | SIGNALED_SYSTEM_ERROR | FAST_BACK_TO_BACK)
+
+// Southbridge
+#define SB_MASK (DEF_MASK | SPECIAL_CYCLES)
+#define SB_STATUS (DEF_STATUS)
+
+// Graphics
+#define GFX_STATUS (DEF_STATUS) & ~(BACK2BACK_CAPABLE)
+#define GFX_MASK (DEF_MASK | BUS_MASTER) & \
+ ~(SERR_ENABLE | PARITY_RESPONSE | SIGNALED_SYSTEM_ERROR | FAST_BACK_TO_BACK)
+
+// AES
+#define AES_STATUS (DEF_STATUS)
+#define AES_MASK (GFX_MASK)
+
+// Bus Masters
+#define BM_STATUS (DEF_STATUS)
+#define BM_MASK (DEF_MASK | BUS_MASTER)
+
+// OHCI Controllers
+#define OHCI_MASK (BM_MASK | IO_SPACE | PARITY_RESPONSE)
+
+
+
+//***********************************************************************
+// Virtualized Northbridge PCI Device
+//***********************************************************************
+PCI_HEADER_ENTRY HostBridge_Hdr[] = {
+ // Reg Flag Value Mask
+ { 0x00, 0x00, 0x20801022, 0x00000000},
+ { COMMAND, 0x00, NB_STATUS, NB_MASK,0,0,WC_STATUS_BITS},
+ { 0x08, 0x00, 0x06000000, 0x00000000}, // Bridge: Host
+ { 0x0C, 0x00, 0x00800008, 0x0000F808},
+ { BAR0, 0x00, 0x00000000, 0x00000000}, // Virtual registers
+ { BAR1, 0x00, 0x00000000, 0x00000000}, // CPU PM functionality
+ { 0x58, EOL, 0x00000000, 0xFFFFFFFF}, // Regression testing
+};
+
+
+PCI_HEADER_ENTRY Graphics_Hdr[] = {
+ // Reg Flag Value Mask
+ { 0x00, 0x00, 0x20811022, 0x00000000},
+ { COMMAND, 0x00, GFX_STATUS, GFX_MASK,0,0,WC_STATUS_BITS},
+ { 0x08, 0x00, 0x03000000, 0x00000000}, // Display: VGA-compatible
+ { 0x0C, 0x00, 0x00000008, 0x00000008},
+ { BAR0, 0x00, 0x00000000, 0x00000000}, // Graphics memory
+ { BAR1, 0x00, 0x00000000, 0x00000000}, // GP
+ { BAR2, 0x00, 0x00000000, 0x00000000}, // VG
+ { BAR3, 0x00, 0x00000000, 0x00000000}, // DF
+ { BAR4, 0x00, 0x00000000, 0x00000000}, // VIP (LX only)
+ { 0x3C, 0x00, 0x00000000, 0x00000000}, // LX only
+ { OEM_BAR0, 0x00, 0x00000000, 0x00000000}, // VG
+ { OEM_BAR1, 0x00, 0x00000000, 0x00000000}, // VG
+ { OEM_BAR2, 0x00, 0x00000000, 0x00000000}, // A0000-AFFFF or A0000-BFFFF if no MONO
+ { OEM_BAR3, EOL, 0x00000000, 0x00000000}, // B8000-BFFFF only if MONO present
+};
+
+PCI_HEADER_ENTRY AES_Hdr[] = {
+ // Reg Flag Value Mask
+ { 0x00, 0x00, 0x20821022, 0x00000000},
+ { COMMAND, 0x00, AES_STATUS, AES_MASK,0,0,WC_STATUS_BITS},
+ { 0x08, 0x00, 0x10100000, 0x00000000}, // Encryption: entertainment
+ { 0x0C, 0x00, 0x00000008, 0x00000008},
+ { BAR0, 0x00, 0x00000000, 0x00000000}, //
+ { 0x3C, EOL, 0x00000100, 0x000000FF}, // INTA
+};
+
+
+
+//***********************************************************************
+// Virtualized Southbridge PCI Device
+//***********************************************************************
+
+PCI_HEADER_ENTRY ISA_Hdr[] = {
+ // Reg Flag Value Mask
+ { 0x00, 0x00, 0x20901022, 0x00000000},
+ { COMMAND, 0x00, SB_STATUS, SB_MASK,0,0,WC_STATUS_BITS},
+ { 0x08, 0x00, 0x06010000, 0x00000000}, // Bridge: ISA
+ { 0x0C, 0x00, 0x00800008, 0x0000F808},
+ { BAR0, 0x00, 0x00000000, 0x00000008, MSR_LBAR_SMB }, // 8 byte I/O BAR (SMB)
+ { BAR1, 0x00, 0x00000000, 0x00000100, MSR_LBAR_GPIO }, // 256 byte I/O BAR (GPIO)
+ { BAR2, 0x00, 0x00000000, 0x00000040, MSR_LBAR_MFGPT}, // 64 byte I/O BAR (MFGPT)
+ { BAR3, 0x00, 0x00000000, 0x00000020, MSR_LBAR_IRQ }, // 32 byte I/O BAR (IRQ)
+ { BAR4, 0x00, 0x00000000, 0x00000080, MSR_LBAR_PMS }, // 128 byte I/O BAR (PMS)
+ { BAR5, 0x00, 0x00000000, 0x00000040, MSR_LBAR_ACPI }, // 64 byte I/O BAR (ACPI)
+ { 0xD0, EOL, 0x00000000, 0x0000FFFF}, // Software SMI
+};
+
+PCI_HEADER_ENTRY Flash_Hdr[] = {
+ // Reg Flag Value Mask
+ { 0x00, 0x00, 0x20911022, 0x00000000},
+ { COMMAND, 0x00, DEF_STATUS, DEF_MASK,0,0,WC_STATUS_BITS},
+ { 0x08, 0x00, 0x05010000, 0x00000000}, // Memory controller: Flash
+ { 0x0C, 0x00, 0x00000008, 0x00000008},
+ { BAR0, 0x00, 0x00000000, 0x00000000, MSR_LBAR_FLSH0}, // Flash0
+ { BAR1, 0x00, 0x00000000, 0x00000000, MSR_LBAR_FLSH1}, // Flash1
+ { BAR2, 0x00, 0x00000000, 0x00000000, MSR_LBAR_FLSH2}, // Flash2
+ { BAR3, 0x00, 0x00000000, 0x00000000, MSR_LBAR_FLSH3}, // Flash3
+ { 0x3C, 0x00, 0x00000100 | Y_IRQ_FLASH, 0x000000FF}, // INTA
+ { 0x40, EOL, 0x00000000, 0xFFFFFFFF}, // IDE-Flash switch
+};
+
+
+
+PCI_HEADER_ENTRY Audio_Hdr[] = {
+ // Reg Flag Value Mask
+ { 0x00, 0x00, 0x20931022, 0x00000000},
+ { COMMAND, 0x00, BM_STATUS, BM_MASK,0,0,WC_STATUS_BITS},
+ { 0x08, 0x00, 0x04010000, 0x00000000}, // Multimedia: Audio
+ { 0x0C, 0x00, 0x00000008, 0x00000008},
+ { BAR0, 0x00, 0x00000000, 0x00000000}, // 128 byte I/O BAR
+ { 0x3C, EOL, 0x00000200 | Y_IRQ_AUDIO, 0x000000FF} // INTB
+};
+
+
+
+
+#define USB20_INT (0x00000400 | Y_IRQ_USB2) // INTD
+#if SUPPORT_CAPABILITIES
+ #define USB20_CMD (DEVSEL_TIMING | PCI_66MHZ_CAPABLE | CAPABILITIES_LIST)
+#else
+ #define USB20_CMD (DEVSEL_TIMING | PCI_66MHZ_CAPABLE)
+#endif
+#define USB20_MASK (BM_MASK & ~(SERR_ENABLE | PARITY_RESPONSE | SIGNALED_SYSTEM_ERROR | FAST_BACK_TO_BACK | BACK2BACK_CAPABLE))
+
+#define OTG_CMD USB20_CMD
+#define OTG_MASK (USB20_MASK & ~BUS_MASTER)
+
+
+
+PCI_HEADER_ENTRY OHC_Hdr[] = {
+ // Reg Flag Value Mask
+ { 0x00, 0x00, 0x20941022, 0x00000000},
+ { COMMAND, 0x00, USB20_CMD, USB20_MASK,0,0,WC_STATUS_BITS},
+ { 0x08, 0x00, 0x0C031000, 0x00000000}, // Serial Bus: USB : OHCI
+ { 0x0C, 0x00, 0x00000008, 0x00000008},
+ { BAR0, USE_BMK, 0x00000000, 0x00001000, USBMSROHCB},
+#if SUPPORT_CAPABILITIES
+ { 0x34, 0x00, PCI_PM_REG, 0x00000000}, // Capabilities pointer
+ { PCI_PM_REG, 0x00, 0xC8020001, 0x00000000}, // PCI Power Management
+ { PCI_PM_REG+4,PCI_PM, 0x00000000, 0x00008103},
+#endif
+ { 0x3C, EOL, USB20_INT, 0x000000FF},
+};
+
+
+PCI_HEADER_ENTRY EHC_Hdr[] = {
+ // Reg Flag Value Mask
+ { 0x00, 0x00, 0x20951022, 0x00000000},
+ { COMMAND,PCI_EHCI, USB20_CMD, USB20_MASK,0,0,WC_STATUS_BITS},
+ { 0x08, 0x00, 0x0C032000, 0x00000000}, // Serial Bus: USB : EHCI
+ { 0x0C, 0x00, 0x00000008, 0x00000008},
+ { BAR0, PCI_EHCI, 0x00000000, 0x00001000, USBMSREHCB},
+#if SUPPORT_CAPABILITIES
+ { 0x34, 0x00, PCI_PM_REG, 0x00000000}, // Capabilities pointer
+ {PCI_PM_REG, 0x00, 0xC8020001, 0x00000000}, // PCI Power Management
+ {PCI_PM_REG+4,PCI_PM, 0x00000000, 0x00008103},
+#endif
+ { EECP, PCI_EHCI, 0x00000001, 0x01010000}, // USBLEGSUP section 2.1.7 of EHCI spec
+ { EECP+4, PCI_EHCI, 0x00000000, 0x0000E03F,0,0,0xE0000000}, // USBLEGCTLSTS section 2.1.8 of EHCI spec
+ { SRBN_REG,PCI_EHCI, 0x00000020, 0x00003F00}, // FLADJ/SBRN
+ { 0x3C, EOL, USB20_INT, 0x000000FF},
+};
+
+
+PCI_HEADER_ENTRY UDC_Hdr[] = {
+ // Reg Flag Value Mask
+ { 0x00, 0x00, 0x20961022, 0x00000000},
+ { COMMAND, 0x00, USB20_CMD, USB20_MASK,0,0,WC_STATUS_BITS},
+ { 0x08, 0x00, 0x0C03FE00, 0x00000000}, // Serial Bus: USB : device
+ { 0x0C, 0x00, 0x00000008, 0x00000008},
+ { BAR0, 0x00, 0x00000000, 0x00002000, USBMSRUDCB},
+#if SUPPORT_CAPABILITIES
+ { 0x34, 0x00, PCI_PM_REG, 0x00000000}, // Capabilities pointer
+ {PCI_PM_REG, 0x00, 0xC8020001, 0x00000000}, // PCI Power Management
+ {PCI_PM_REG+4,PCI_PM, 0x00000000, 0x00008103},
+#endif
+ { 0x3C, EOL, USB20_INT, 0x000000FF},
+};
+
+
+PCI_HEADER_ENTRY OTG_Hdr[] = {
+ // Reg Flag Value Mask
+ { 0x00, 0x00, 0x20971022, 0x00000000},
+ { COMMAND, 0x00, OTG_CMD, OTG_MASK,0,0,WC_STATUS_BITS},
+ { 0x08, 0x00, 0x0C038000, 0x00000000}, // Serial Bus: USB : No specific interface
+ { 0x0C, 0x00, 0x00000008, 0x00000008},
+ { BAR0, 0x00, 0x00000000, 0x00001000, USBMSRUOCB},
+#if SUPPORT_CAPABILITIES
+ { 0x34, 0x00, PCI_PM_REG, 0x00000000}, // Capabilities pointer
+ {PCI_PM_REG, 0x00, 0xC8020001, 0x00000000}, // PCI Power Management
+ {PCI_PM_REG+4,PCI_PM, 0x00000000, 0x00008103},
+#endif
+ { 0x3C, EOL, USB20_INT, 0x000000FF},
+};
+
+
+#define THOR_MASK (BM_MASK | IO_SPACE)
+PCI_HEADER_ENTRY Thor_Hdr[] = {
+ // Reg Flag Value Mask
+ { 0x00, 0x00, 0x209A1022, 0x00000000},
+ { COMMAND, 0x00, BM_STATUS, THOR_MASK,0,0,WC_STATUS_BITS},
+ { 0x08, 0x00, 0x01018000, 0x00000000}, // Mass Storage: IDE
+ { 0x0C, 0x00, 0x0000F808, 0x00000008},
+ { BAR4, 0x00, 0x00000000, 0x00000000, MSR_LBAR_ATA}, // 16 byte I/O BAR
+// The following 4 registers must be contiguous:
+ { IDE_CFG, 0x00, 0x00000000, 0x0003FFFF, 0x10},
+ { IDE_DTC, 0x00, 0xA8A80000, 0xFFFF0000, 0x12},
+ { IDE_CAST, 0x00, 0xFF0000F0, 0xFF0000F0, 0x13},
+ { IDE_ETC, 0x00, 0x03030000, 0xC7C70000, 0x14},
+ { IDE_PM, EOL, 0x00000000, 0x00000003, 0x15},
+};
+
+
+PCI_HEADER_ENTRY * Virtual_5536[] = {
+ ISA_Hdr, // F0 ISA bridge
+ Flash_Hdr, // F1 Flash
+ Thor_Hdr, // F2 ATA
+ Audio_Hdr, // F3 AC97
+ OHC_Hdr, // F4 OHCI
+ EHC_Hdr, // F5 EHCI
+ UDC_Hdr, // F6 UDC
+ OTG_Hdr, // F7 OTG
+};
+
+
+//***********************************************************************
+// The following tables determine the virtualized PCI topology
+//***********************************************************************
+PCI_HEADER_ENTRY * NorthBridge[] = {
+ HostBridge_Hdr, // F0 Host bridge
+ 0, // F1 Graphics (enabled via softvg)
+ AES_Hdr, // F2 Encryption
+ 0, // F3
+ 0, // F4
+ 0, // F5
+ 0, // F6
+ 0 // F7
+};
+
+
+// Pointer to the virtualized Southbridge table
+VIRTUAL_DEVICE * SouthBridge;
+
+
+
+// NOTE: SouthBridge will be inserted into the following table
+// at the same DEVSEL as the hardware header.
+VIRTUAL_DEVICE * Virtual_Devices[32] = {
+ // IDSEL Dev# Address Description
+ // ----- ----- ---------- ---------------------
+ 0, // N/A 0
+ NorthBridge, // 11 1 0x80000800 HostBridge + Graphics
+ 0, // 12 2
+ 0, // 13 3
+ 0, // 14 4
+ 0, // 15 5
+ 0, // 16 6
+ 0, // 17 7
+ 0, // 18 8
+ 0, // 19 9
+ 0, // 20 10
+ 0, // 21 11
+ 0, // 22 12
+ 0, // 23 13
+ 0, // 24 14
+ 0, // 25 15 0x80007800 CS5535 & CS5536
+ 0, // 26 16
+ 0, // 27 17
+ 0, // 28 18 0x80009000 CS5530
+ 0, // 29 19 0x80009800 CS5530 OHCI
+ 0, // 30 20
+ 0, // 31 21
+ 0, // N/A 22
+ 0, // N/A 23
+ 0, // N/A 24
+ 0, // N/A 25
+ 0, // N/A 26
+ 0, // N/A 27
+ 0, // N/A 28
+ 0, // N/A 29
+ 0, // N/A 30
+ 0, // N/A 31
+};
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/unregstr.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/unregstr.c
new file mode 100755
index 0000000..5beedc7
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/unregstr.c
@@ -0,0 +1,338 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* This file contains the code that unregisters events
+//******************************************************************************
+
+
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "PROTOS.H"
+
+
+
+// Externals:
+extern void pascal Clr_MBus_IO_Trap(ULONG Address, USHORT Range);
+extern UCHAR * VsmNames[];
+extern UCHAR * EventNames[];
+extern UCHAR FreeEvent;
+extern EVENT_ENTRY Events[MAX_REGISTRATIONS];
+
+
+//*****************************************************************************
+// Copies an Events[] entry
+//*****************************************************************************
+extern void pascal Copy_Event(USHORT From, USHORT To);
+
+//*****************************************************************************
+// Retires an Events[] entry to the free list
+//*****************************************************************************
+void pascal Retire_Events_Entry(EVENT Event, USHORT match, USHORT previous)
+{ USHORT i;
+
+ // Remove Events[match] from the linked list.
+ i = Events[match].Link;
+ if (previous) {
+ Events[previous].Link = (UCHAR)i;
+ i = match;
+ } else {
+ // The first entry in the linked list is being removed.
+ Copy_Event(i, Event);
+ }
+
+ // Mark the entry as available.
+ Events[i].Vsm = 0x00000000;
+ if (i) {
+ // Put Events[] entry on free list
+ Events[i].Link = FreeEvent;
+ FreeEvent = (UCHAR)i;
+ }
+}
+
+
+//*****************************************************************************
+// Unregisters a PCI trap
+//*****************************************************************************
+USHORT pascal Unregister_PCI_Trap(VSM Vsm, USHORT PCI_Addr, USHORT PCI_Mask)
+{ USHORT EventIndex, IDSEL_Count=0, previous=0, match=0;
+ register EVENT_ENTRY * EventPtr;
+
+
+ // The entire event chain must be traversed to find out how
+ // many registrations are trapping this IDSEL. If only this
+ // one, then the IDSEL in the MPCI_PBUS MSR will be cleared.
+ EventIndex = EVENT_PCI_TRAP;
+ while (Events[EventIndex].Vsm) {
+ EventPtr = &Events[EventIndex];
+
+ // Check if IDSEL matches
+ if ((EventPtr->PCI_Addr & 0xF800) == (PCI_Addr & 0xF800)) {
+
+ IDSEL_Count++;
+
+ // If it is the requested VSM...
+ if (EventPtr->Vsm == Vsm) {
+ // and the PCI Address/Mask match...
+ if (EventPtr->PCI_Addr == PCI_Addr && EventPtr->PCI_Mask == PCI_Mask) {
+ // Record the EventIndex to be removed
+ match = EventIndex;
+ }
+ }
+ }
+
+ // Record index immediately before the matching Events[] entry
+ if (!match) {
+ previous = EventIndex;
+ }
+
+ // Get the next entry in the linked list
+ EventIndex = EventPtr->Link;
+
+ } // end while
+
+
+ // If this is the only registration for this IDSEL...
+ if (IDSEL_Count == 1) {
+ // disable trapping this IDSEL
+ Disable_Event(EVENT_PCI_TRAP, match);
+ }
+
+ // Retire the Events[] entry
+ Retire_Events_Entry(EVENT_PCI_TRAP, match, previous);
+
+ return match;
+}
+
+
+//*****************************************************************************
+// Disassociates an event from a VSM. This may occur as a result of a
+// VSM performing the UNREGISTER_EVENT() macro, or if a VSM is being
+// removed or replaced.
+//*****************************************************************************
+// RESOURCE_COUNT:
+// 1) Must be power of 2 since the Mod (%) operator is used
+// 2) A minimum of 32 (# GPIOs)
+// 3) A maximum of 256
+#define RESOURCE_COUNT 128
+USHORT pascal Unregister_Event(EVENT Event, VSM Vsm, ULONG Param1, ULONG Param2)
+{ USHORT EventIndex, i, j=4, k=0, previous=0, match=0;
+ static UCHAR HW_Resource[RESOURCE_COUNT];
+ UCHAR IO_Base, IO_Range;
+ ULONG Mask1=0x00000000, Mask2=0x00000000;
+ register EVENT_ENTRY * EventPtr;
+
+
+
+ // Determine which parameters must match
+ switch (Event) {
+
+ case EVENT_TIMER:
+ // Only require Handle to match
+ Mask2 = 0x0000FFFF;
+ j = 8; // # h/w timers
+ break;
+
+ case EVENT_PWM:
+ case EVENT_PME:
+ case EVENT_GPIO:
+ // Only require pin to match
+ Mask1 = 0x0000FFFF;
+ j = 32; // max # GPIO pins
+ break;
+
+ case EVENT_IO_TRAP:
+ j = RESOURCE_COUNT;
+ // Only require I/O addresses within range to match
+ Mask1 = 0x00010000 - RESOURCE_COUNT;
+ break;
+
+ case EVENT_PCI_TRAP:
+ match = Unregister_PCI_Trap(Vsm, (USHORT)Param1, (USHORT)Param2);
+ return match;
+
+ case EVENT_IO_TIMEOUT:
+ // Require Param1 to match
+ Mask1 = 0xFFFFFFFF;
+ break;
+ }
+
+ // Zero the h/w resource usage counters
+ for (i=0; i<j; i++) {
+ HW_Resource[i] = 0;
+ }
+ j = 0;
+
+ // The entire event chain must be traversed to find out how
+ // many registrations are using the resource. If more than
+ // one, then the hardware will not be disabled.
+ EventIndex = Event;
+ while (Events[EventIndex].Vsm) {
+ EventPtr = &Events[EventIndex];
+ switch (Event) {
+ case EVENT_TIMER:
+ j = (USHORT)EventPtr->Timer;
+ break;
+
+ case EVENT_PWM:
+ case EVENT_PME:
+ case EVENT_GPIO:
+ j = (USHORT)EventPtr->Pin;
+ break;
+ }
+
+ // Check if parameters match
+ if ((EventPtr->Param1 & Mask1) == (Param1 & Mask1) &&
+ (EventPtr->Param2 & Mask2) == (Param2 & Mask2)) {
+
+ if (Event == EVENT_IO_TRAP) {
+ // Accumulate usage count for each I/O location in range
+ IO_Base = (UCHAR)EventPtr->IO_Base;
+ IO_Range = (UCHAR)EventPtr->IO_Range;
+ for (i = 0; i < IO_Range; i++) {
+ k = (UCHAR)(i + IO_Base) % RESOURCE_COUNT;
+ HW_Resource[k]++;
+ }
+ }
+
+ // If it is the requested VSM...
+ if (EventPtr->Vsm == Vsm) {
+
+ // Record which h/w resource is being disabled
+ switch (Event) {
+ case EVENT_IO_TRAP:
+ if (match) {
+ // There are overlapping I/O ranges in the same VSM
+ if ((EventPtr->IO_Base != (USHORT)Param1) ||
+ (EventPtr->IO_Range != (USHORT)Param2)) {
+ // This is not the one being removed
+ break;
+ }
+ }
+ case EVENT_PWM:
+ case EVENT_PME:
+ case EVENT_GPIO:
+ case EVENT_TIMER:
+ k = j;
+ default:
+ // Record the EventIndex to be removed
+ if (!match) {
+ match = EventIndex;
+ }
+ break;
+ }
+ }
+ }
+
+ // Record entry previous to 'match'
+ if (!match) {
+ previous = EventIndex;
+ }
+
+ // Increment resource usage count
+ if (Event != EVENT_IO_TRAP) {
+ HW_Resource[j]++;
+ }
+
+ // Link to the next entry in the list.
+ EventIndex = EventPtr->Link;
+
+ } // end while
+
+
+ if (match) {
+
+ switch (Event) {
+ USHORT Range;
+
+ case EVENT_IO_TRAP:
+ Range=0x0000;
+ EventPtr = &Events[match];
+ Param1 |= Param2 & 0xFFFF0000;
+ for (j = 0; j < (UCHAR)Param2; j++) {
+ k = (UCHAR)((j + EventPtr->Param1) % RESOURCE_COUNT);
+ if (HW_Resource[k] > 1) {
+ if (Range) {
+ // Found end of a range used exclusively by this VSM
+ Clr_MBus_IO_Trap(Param1, Range);
+ Param1 += Range;
+ Range = 0;
+ } else {
+ (USHORT)Param1++;
+ }
+ } else {
+ Range++;
+ }
+ }
+ if (Range) {
+ Clr_MBus_IO_Trap(Param1, Range);
+ }
+ break;
+
+ default:
+ // If only one registration is using the h/w resource, disable it
+ if (HW_Resource[k] == 1) {
+ case EVENT_IO_TIMEOUT: // Statistic counter logic keeps track of usage
+ Disable_Event(Event, match);
+ }
+ case EVENT_SOFTWARE_SMI:
+ break;
+ }
+
+ // Retire the Events[] entry
+ Retire_Events_Entry(Event, match, previous);
+
+ } else {
+
+ // A VSM attempted to unregister a event that it is not registered for
+ Log_Error("Attempt to unregister EVENT_%s[0x%08X;0x%08X] by the %s VSM", EventNames[Event], Param1, Param2, VsmNames[Get_VSM_Type(Vsm)]);
+ }
+
+ return match;
+}
+
+
+
+
+
+//*****************************************************************************
+// Removes all events registered to a VSM.
+//*****************************************************************************
+void pascal Unregister_VSM_Events(VSM Vsm)
+{ register EVENT Event;
+ register EVENT_ENTRY * EventPtr;
+
+ // Unregister all events registered to this VSM
+ for (Event=1; Event <= MAX_EVENT; Event++) {
+ EventPtr = &Events[Event];
+ while (EventPtr->Vsm) {
+
+ if (EventPtr->Vsm == Vsm) {
+ if (Unregister_Event(Event, Vsm, EventPtr->Param1, EventPtr->Param2)) {
+ // Start over on this event since there might be others for this VSM.
+ Event--;
+ break;
+ }
+ }
+ EventPtr = &Events[EventPtr->Link];
+ }
+ }
+}
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/utils.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/utils.asm
new file mode 100755
index 0000000..3b682c4
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/utils.asm
@@ -0,0 +1,642 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;*******************************************************************************
+;* Miscellaneous utility routines
+;*******************************************************************************
+
+
+include SYSMGR.INC
+include VSA2.INC
+include PCI.INC
+include GX2.INC
+
+.model tiny,c
+.586p
+.CODE
+
+externdef SchedulerStack: word
+externdef SysMgr_VSM: dword
+externdef Saved_PCI: dword
+externdef Nested_PCI: dword
+externdef MsgPacket: dword
+externdef ClocksPerMs: dword
+externdef StartSaveArea: dword
+externdef Header_Addr: dword
+externdef Nested_Flag: dword
+externdef VSM_Ptrs: dword
+externdef Events: EVENT_ENTRY
+
+
+
+
+;************************************************************************
+;
+; 8 bit I/O routines
+;
+;************************************************************************
+
+in_8 proc pascal \
+ io_port: word
+
+ mov dx, [io_port]
+ in al, dx
+ ret
+
+in_8 endp
+
+
+out_8 proc pascal \
+ io_port: word, \
+ io_data: byte
+
+ mov dx, [io_port]
+ mov al, [io_data]
+ out dx, al
+ ret
+
+out_8 endp
+
+;************************************************************************
+;
+; 16 bit I/O routines
+;
+;************************************************************************
+
+in_16 proc pascal \
+ io_port: word
+
+ mov dx, [io_port]
+ in ax, dx
+ ret
+
+in_16 endp
+
+
+out_16 proc pascal \
+ io_port: word, \
+ io_data: word
+
+ mov dx, [io_port]
+ mov ax, [io_data]
+ out dx, ax
+ ret
+
+out_16 endp
+
+
+;************************************************************************
+;
+; 32 bit I/O routines
+;
+;************************************************************************
+
+in_32 proc pascal \
+ io_port: word
+
+ mov dx, [io_port]
+ in eax, dx
+ mov edx, eax
+ shr edx, 16
+ ret
+
+in_32 endp
+
+
+out_32 proc pascal \
+ io_port: word, \
+ io_data: dword
+
+ mov dx, [io_port]
+ mov eax, [io_data]
+ out dx, eax
+ ret
+
+out_32 endp
+
+
+
+
+;************************************************************************
+;
+; Input:
+; Ptr to a VSM header
+;
+; Output:
+; Ptr to the next VSM in the chain
+;
+;************************************************************************
+GetFlink proc pascal, \
+ VSM_Ptr: dword
+
+ mov ebx, [VSM_Ptr]
+ mov eax, (VSM_Header PTR fs:[ebx]).SysStuff.Flink
+ mov edx, eax
+ shr edx, 16
+ ret
+
+GetFlink endp
+
+
+
+
+;************************************************************************
+; Writes a BYTE, WORD, DWORD to a 32-bit address
+;************************************************************************
+write_flat_size proc pascal \
+ Address: dword, \
+ Data: dword, \
+ Len: byte
+
+ mov ebx, [Address]
+ mov eax, [Data]
+ mov cl, [Len]
+ cld
+ cmp cl, BYTE_IO
+ jne short CheckWord
+ mov fs:[ebx], al
+ jmp short Exit
+
+CheckWord:
+ cmp cl, WORD_IO
+ je short WriteWord
+WriteDword:
+ db 66H
+WriteWord:
+ mov fs:[ebx], ax
+Exit: ret
+
+write_flat_size endp
+
+;************************************************************************
+; Writes a DWORD to a 32-bit address
+;************************************************************************
+write_flat proc pascal \
+ Address: dword, \
+ Data: dword
+
+ mov ebx, [Address]
+ mov eax, [Data]
+ mov fs:[ebx], eax
+ ret
+
+write_flat endp
+
+;************************************************************************
+; Reads a DWORD from a 32-bit address
+;************************************************************************
+read_flat proc pascal \
+ Address: dword
+
+ mov ebx, [Address]
+ mov eax, fs:[ebx]
+ mov edx, eax
+ shr edx, 16
+ ret
+
+read_flat endp
+
+
+
+;************************************************************************
+;
+; Copies the parameters for a synchronous event from the appropriate SMI
+; header to the MsgPacket array.
+; NOTE: This routine should only be called from a Synchronous SMI handler.
+;
+; On exit:
+; MsgPacket[1]: 15:0 - Flags field from SMM header
+; MsgPacket[2]: 15:0 - I/O address (or PCI address) from SMM header
+; 31:16 - Data Size field from SMM header
+; MsgPacket[3]: Data (if I/O write)
+;
+; Returns ptr to appropriate SMM header.
+;
+;************************************************************************
+Get_Header_Params proc pascal \
+ SMI_Event: dword
+
+ mov bx, OFFSET VSM_Header.SysStuff.State
+
+ ASSUME BX: PTR SmiHeader
+
+ mov eax, [SMI_Event] ; Is it a nested event ?
+ test [Nested_Flag], eax
+ je Copy_Params
+
+ not eax ; Yes, clear the event
+ and [Nested_Flag], eax
+
+ push si ; Copy VSM's header to local buffer
+ mov si, bx
+
+ lea bx, [Nested_Header]
+ push bx
+ mov cx, sizeof(SmiHeader)/4
+ cld
+CopyHdr:
+ lodsd gs:[si]
+ mov dword ptr [bx], eax
+ add bx, 4
+ loop CopyHdr
+
+ pop bx
+ pop si
+
+
+
+ ; Copy parameters from SMM header to MsgPacket[]
+Copy_Params:
+
+ movzx eax, [bx].SMI_Flags
+ mov [MsgPacket+4*1], eax ; MsgPacket[1]
+
+
+ ; Is it a PCI trap ?
+ mov eax, dword ptr [bx].IO_addr
+ mov dx, ax
+ and dl, NOT 3
+ cmp dx, PCI_CONFIG_DATA
+ jne short StoreAddr
+
+ ; Yes, get PCI address from appropriate context
+ mov cl, al ; Get 2 LSBs of PCI address
+ and cl, 3
+ mov ax, word ptr [Nested_PCI]
+ cmp bx, OFFSET [Nested_Header]
+ je short Get_PCI
+
+ mov ax, word ptr [Saved_PCI]
+Get_PCI:
+ or al, cl
+StoreAddr:
+ mov [MsgPacket+4*2], eax ; MsgPacket[2]
+
+
+ ; Get write data
+ mov ecx, [bx].write_data
+ shr eax, 16 ; Put I/O size into AL
+ cmp al, DWORD_IO ; Dword I/O ?
+ je short StoreData
+ movzx ecx, cx
+ cmp al, WORD_IO ; Word I/O ?
+ je short StoreData
+ xor ch, ch ; Byte I/O
+
+StoreData:
+ mov [MsgPacket+4*3], ecx ; MsgPacket[3]
+
+ mov ax, bx ; Return ptr to header
+ ret
+
+Nested_Header SmiHeader {}
+
+
+Get_Header_Params endp
+
+ ASSUME BX: NOTHING
+
+
+;************************************************************************
+; Returns the # milliseconds elapsed on a timer.
+;************************************************************************
+ElapsedSoFar proc StartTime: PTR
+
+ rdtsc ; Get current timestamp
+
+ mov bx, [StartTime] ; Subtract timer's start time
+ sub eax, [bx+0]
+ sbb edx, [bx+4]
+
+ idiv [ClocksPerMs] ; Convert delta to milliseconds
+ mov edx, eax
+ shr edx, 16
+ ret
+
+ElapsedSoFar endp
+
+
+
+;************************************************************************
+; Returns the timestamp counter in the passed buffer
+;************************************************************************
+Store_Timestamp proc pascal \
+ TimeStamp: PTR
+
+ rdtsc
+ mov bx, [TimeStamp]
+ mov [bx+0], eax
+ mov [bx+4], edx
+ ret
+
+Store_Timestamp endp
+
+
+
+;************************************************************************
+; Returns the type of the VSM pointed to by the Vsm parameter
+;************************************************************************
+Get_VSM_Type proc pascal \
+ Vsm:dword
+
+ mov ebx, [Vsm]
+ mov al, fs:(VSM_Header PTR [ebx]).VSM_Type
+ ret
+
+Get_VSM_Type endp
+
+
+
+
+
+;************************************************************************
+; Translates a logical address to a physical address via the page tables
+; NOTES:
+; - This routine should only be called if paging is enabled.
+; - All page & segment protection has already occurred.
+;************************************************************************
+
+PAGE_ATTR equ 0FFFh
+CR4_PSE_BIT equ 0010h
+PDIR_PS_BIT equ 0080h
+OFFSET_4M equ 0003FFFFFh
+PAGEBASE_4M equ 0FFC00000h
+
+Convert_To_Physical_Addr proc pascal \
+ Logical: dword
+
+ ; Start by checking for 4MB page possibility
+ mov eax, CR4
+ test ax, CR4_PSE_BIT
+ jz short page4K
+
+ mov ebx, CR3 ; Get ptr to page directory base
+ and ebx, 0FFFFFC00h ; Mask attribute bits
+
+ mov edx, [Logical] ; Get address to translate
+ shr edx, 22 ; Get page directory index
+
+ ; See if this directory entry points to a 4MB page
+ mov ebx, fs:[ebx+edx*4]
+
+ test bx, PDIR_PS_BIT
+ jz short page4K
+
+ and ebx, PAGEBASE_4M ; Get the page base offset
+
+ mov eax, [Logical] ; Get address to translate
+ and eax, OFFSET_4M ; Peel off the directory index
+
+ or eax, ebx ; Combine the base and offset
+
+ jmp short Exit
+
+
+page4K:
+ mov ebx, CR3 ; Get ptr to page directory base
+ and ebx, 0FFFFFC00h ; Mask attribute bits
+
+ mov eax, [Logical] ; Get address to translate
+
+ movzx ecx, ax ; Extract page offset
+ and cx, PAGE_ATTR ; (contains offset into 4K page)
+
+ shr eax, 12 ; Remove page offset
+ mov edx, eax
+
+ shr edx, 10 ; Get page directory offset
+
+ mov ebx, fs:[ebx+edx*4]
+ and bx, NOT PAGE_ATTR ; Remove page directory attributes
+
+ and eax, 03FFh ; Extract page table offset
+ mov eax, fs:[ebx+eax*4]
+ and ax, NOT PAGE_ATTR ; Remove page attributes
+
+ add eax, ecx ; Add page offset
+
+Exit: mov edx, eax ; Return translated addr in DX:AX
+ shr edx, 16
+ ret
+
+Convert_To_Physical_Addr endp
+
+
+;************************************************************************
+; Marks a 'Blocked' VSM to 'Ready'
+;************************************************************************
+Unblock_VSM proc pascal Vsm: dword
+
+ mov ebx, [Vsm]
+ mov fs:(VSM_Header PTR [ebx]).SysStuff.RunFlag, RUN_FLAG_READY
+ ret
+
+Unblock_VSM endp
+
+;MEJ
+;************************************************************************
+; This routine determines if an event should wake the system.
+; If so, the PMCore VSM's RunFlag is changed from 'Sleeping' to 'Ready'.
+; There currently are two cases:
+; 1) A timer for either the APM or PMCore VSM
+; 2) A press of the sleep button while in Legacy PM mode
+;
+; Returns TRUE if the event is a wake event.
+;************************************************************************
+;IsWakeEvent proc pascal \
+; Vsm: DWORD
+;
+; mov ebx, [Vsm]
+;
+; ; Is event for a PM-related VSM ?
+; cmp fs:(VSM_Header PTR [ebx]).VSM_Type, VSM_PM
+; je short PossibleWakeEvent
+; cmp fs:(VSM_Header PTR [ebx]).VSM_Type, VSM_APM
+; jne short NotWakeEvent
+;
+; ; Yes, mark PM VSM 'Ready' if it is 'Sleeping'
+;PossibleWakeEvent:
+; mov ebx, [VSM_Ptrs+4*VSM_PM]
+; mov al, fs:(VSM_Header PTR [ebx]).SysStuff.RunFlag
+; cmp al, RUN_FLAG_SLEEPING
+; jne short NotWakeEvent
+; mov fs:(VSM_Header PTR [ebx]).SysStuff.RunFlag, RUN_FLAG_READY
+; jmp Exit
+;
+;
+;NotWakeEvent:
+; xor al, al
+;
+;Exit: ret
+;
+;IsWakeEvent endp
+
+
+
+;************************************************************************
+; Returns the flat address to the VSM performing a system call
+; Used for reporting errors in a system call.
+;************************************************************************
+Get_SysCall_Address proc pascal \
+ Vsm: dword, \
+ Depth: byte
+
+ mov eax, [Vsm]
+
+ cmp eax, [SysMgr_VSM]
+ jne short Get_VSM_Addr
+
+if CHECKED_BUILD
+
+ mov dx, sp ; Save BP & SP
+ shl edx, 16
+ mov dx, bp
+
+ mov cl, [Depth]
+ add cl, 2 ; Include stack frames for this routine's & Error_Report()
+PopStackFrame:
+ mov bx, sp
+ leave ; Pop a stack frame
+ cmp sp, OFFSET StartSaveArea
+ jae short Bail
+ cmp sp, [SchedulerStack]
+ jb short Bail
+
+
+ dec cl
+ jnz PopStackFrame
+ jmp short GetFault
+
+
+Bail: mov sp, bx
+GetFault:
+ mov bx, sp ; Get return address to faulting CALL
+ movzx ebx, word ptr [bx]
+ sub bx, 3 ; Account for CALL sys_xxxxx
+
+ mov bp, dx ; Restore BP & SP
+ shr edx, 16
+ mov sp, dx
+else
+ xor ebx, ebx ; Don't attempt to determine address
+endif
+ jmp short Result
+
+Get_VSM_Addr:
+
+ ASSUME BX: PTR word
+
+ ; There are 3 cases:
+ ; 1) A system call.
+ ; 2) In-line assembly (e.g. direct I/O virtual register)
+ ; 3) A subroutine call to offending I/O
+ mov bx, word ptr gs:(VSM_Header).SysStuff.State.Next_EIP
+ cmp gs:[bx-2], 380Fh ; Was it from a SMINT (system call)
+ je short Sys_Call
+
+ mov dx, gs:[bx] ; Get next two bytes of VSM's code
+
+ dec bx ; In case it is in-line assembly
+ ; If the next two instructions are LEAVE & RET, then it is a
+ ; subroutine. Report the caller's address.
+ cmp dl, 0C9h ; Is the next instruction a LEAVE ?
+ jne short Result ; No, must be in-line assembly
+ and dh, NOT 1 ; Yes, is the next one a struction a RET ?
+ cmp dh, 0C2h
+ jne short Result ; No, must be in-line assembly
+Sys_Call:
+ mov bx, word ptr gs:(VSM_Header).SysStuff.SavedESP
+ mov bx, gs:[bx+3*4] ; Get caller's BP
+ movzx ebx, gs:[bx+2] ; Get SP at time of CALL sys_xxxx
+ sub bx, 3 ; Account for CALL sys_xxxxx
+Result:
+ add eax, ebx
+
+ mov edx, eax
+ shr edx, 16
+
+ ret
+
+Get_SysCall_Address endp
+
+
+
+;************************************************************************
+; Returns the 8 MSBs of the DEVID field of the Device Capabilities MSR
+;************************************************************************
+GetPortID proc MBD_Addr: dword
+
+ mov ecx, [MBD_Addr]
+ mov cx, MBD_MSR_CAP
+ rdmsr
+ shr eax, ID_SHIFT
+ xor ah, ah
+ ret
+
+GetPortID endp
+
+
+;************************************************************************
+; Clears pending h/w emulation events in an GeodeLink device
+;************************************************************************
+ClearMbiu proc pascal Mbiu: dword
+
+ mov ecx, [Mbiu]
+ or ecx, ecx
+ jz short Exit
+ mov cx, MBD_MSR_SMI
+ rdmsr
+ mov dl, 1
+ wrmsr
+ mov cx, MBD_MSR_ERROR
+ rdmsr
+ wrmsr
+
+Exit: ret
+
+ClearMbiu endp
+
+
+
+;************************************************************************
+; Trims a P2D_R descriptor by Range
+;************************************************************************
+Trim_P2D_R proc pascal uses esi \
+ MsrAddr: dword, \
+ Range: dword, \
+ MsrData: PTR
+
+ mov ecx, [MsrAddr] ; Get current MSR value
+ rdmsr
+
+ mov ebx, [Range] ; Adjust by Range bytes
+ mov esi, ebx
+ shr esi, (12+12)
+ shl ebx, (20-12)
+ sub eax, ebx
+ sbb edx, esi
+ wrmsr
+
+ mov bx, [MsrData] ; Return modified MSR
+ mov dword ptr [bx+0], eax
+ mov dword ptr [bx+4], edx
+ ret
+
+Trim_P2D_R endp
+
+ end
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/virt_pci.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/virt_pci.c
new file mode 100755
index 0000000..003731d
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/virt_pci.c
@@ -0,0 +1,885 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* Utility routines related to virtualized PCI config headers
+//******************************************************************************
+
+
+
+#include "VSA2.H"
+#include "PCI.H"
+#include "GX2.H"
+#include "VPCI.H"
+#include "SYSMGR.H"
+#include "CHIPSET.H"
+#include "PROTOS.H"
+#include "DESCR.H"
+#include "MDD.H"
+
+
+// External function declarations:
+extern void pascal Parse_Descriptor(UCHAR, ULONG *, ULONG *);
+extern void pascal Trim_P2D_R(ULONG, ULONG, ULONG *);
+
+
+// External variable declarations:
+extern UCHAR DynamicVSALoad;
+extern UCHAR MC_Port, VG_Port;
+extern UCHAR MBIU1_SelfReference;
+extern UCHAR End_of_POST;
+extern ULONG MDD_Base;
+extern ULONG Mbiu0, Mbiu1, Mbiu2;
+extern ULONG MPCI_NB, MPCI_SB;
+extern DESCRIPTOR MSRs[];
+extern ULONG ExtendedMemoryDescr0, ExtendedMemoryDescr1;
+extern Hardware HardwareInfo;
+extern VIRTUAL_DEVICE * Virtual_Devices[];
+extern VIRTUAL_DEVICE * SouthBridge;
+extern PCI_HEADER_ENTRY * NorthBridge[];
+extern PCI_HEADER_ENTRY * Virtual_5536[];
+extern PCI_HEADER_ENTRY Graphics_Hdr[];
+extern PCI_HEADER_ENTRY HostBridge_Hdr[];
+extern PCI_HEADER_ENTRY AES_Hdr[];
+extern PCI_HEADER_ENTRY ISA_Hdr[];
+extern PCI_HEADER_ENTRY Thor_Hdr[];
+extern PCI_HEADER_ENTRY Audio_Hdr[];
+extern PCI_HEADER_ENTRY Flash_Hdr[];
+
+
+// Local variable declarations:
+PCI_HEADER_ENTRY * CommandPtr, * HdrPtr;
+PCI_HEADER_ENTRY Dummy_Hdr[] = {
+ {0x00, 0x00, 0xFFFFFFFF, 0x00000000},
+ {0x00, 0x00, 0xFFFFFFFF, 0x00000000},
+ {0x00, 0x00, 0xFFFFFFFF, 0x00000000},
+ {0x00, EOL, 0xFFFFFFFF, 0x00000000},
+};
+VIRTUAL_DEVICE * IDSELs;
+VIRTUAL_PTR * VirtDevPtr;
+USHORT DeviceID;
+USHORT Class;
+UCHAR BaseClass;
+UCHAR Shift, AlignedReg, Function;
+ULONG Virtualized_PCI_Devices=0;
+
+
+//***********************************************************************
+// Given a ptr to a virtual PCI header, finds Register
+//***********************************************************************
+PCI_HEADER_ENTRY * pascal Find_Register(PCI_HEADER_ENTRY * Pci, UCHAR Register)
+{
+ // Keep a ptr to the Vendor ID register
+ HdrPtr = Pci;
+ DeviceID = HdrPtr->Device_ID;
+
+ // Keep a ptr to the Command register
+ CommandPtr = Pci + COMMAND/4;
+
+ // Record the device Class
+ BaseClass = (HdrPtr+REVISION_ID/4)->BaseClass;
+ Class = (HdrPtr+REVISION_ID/4)->Class;
+
+ // Scan the table for the specified register entry
+ do {
+ if (Pci->Reg == Register) {
+ return Pci;
+ }
+ } while (!((Pci++)->Flag & EOL));
+
+
+ // If CommandPtr is used, avoid generating an exception
+ CommandPtr = Dummy_Hdr;
+
+ // Register is not in the table
+ return (PCI_HEADER_ENTRY *) UNIMPLEMENTED_REGISTER;
+}
+
+//***********************************************************************
+// Parses PCI_Address & returns a pointer to the corresponding entry in a
+// virtual header table.
+// Computes global variables:
+// AlignedReg, Function, Shift, HdrPtr, CommandPtr, & DeviceID
+//***********************************************************************
+PCI_HEADER_ENTRY * pascal Get_Structure(USHORT PCI_Address)
+{ register PCI_HEADER_ENTRY * Pci;
+ UCHAR Reg;
+
+ // Compute Function #
+ Function = (UCHAR)(PCI_Address >> 8) & 0x07;
+
+ // Get register offset
+ Reg = (UCHAR) PCI_Address;
+
+ // Compute DWORD aligned register offset
+ AlignedReg = Reg & ~3;
+
+ // Compute shift count
+ Shift = (Reg & 3) << 3;
+
+ // Subsystem Vendor ID & Subsystem ID are same as Vendor ID & Device ID
+ if (AlignedReg == SUBSYSTEM_VENDOR_ID) {
+ AlignedReg = VENDOR_ID;
+ }
+
+
+ // Return value if function not implemented
+ Pci = (PCI_HEADER_ENTRY *) UNIMPLEMENTED_FUNCTION;
+
+ // Is this IDSEL virtualized ?
+ if (IDSELs = *(VirtDevPtr+(PCI_Address >> 11))) {
+
+ // Get ptr to this function (0000 if not implemented)
+ if (Pci = IDSELs[Function]) {
+ Pci = Find_Register(Pci, AlignedReg);
+ }
+ }
+
+ return Pci;
+}
+
+
+
+
+
+//***********************************************************************
+// Trims the MSRs that map extended memory by RangeRequest bytes
+//***********************************************************************
+ULONG Trim_Extended_Memory(ULONG RangeRequest)
+{ ULONG Fields[3], Ext_Mem[2], Msr;
+
+ // Trim the MPCI Region 1 configuration
+ Msr = MPCI_NB + MPCI_R1;
+ Read_MSR(Msr, Ext_Mem);
+ if (DynamicVSALoad) {
+ RangeRequest = 0;
+ }
+ Ext_Mem[1] -= RangeRequest;
+ Write_MSR(Msr, Ext_Mem);
+
+ // Adjust RCONF_DEFAULT[SYSTOP]
+ Read_MSR(MSR_RCONF_DEFAULT, Ext_Mem);
+ Ext_Mem[0] -= RangeRequest >> 4;
+ Write_MSR(MSR_RCONF_DEFAULT, Ext_Mem);
+
+
+ // Trim extended memory in GLIUs 0 & 1
+ Trim_P2D_R(ExtendedMemoryDescr0, RangeRequest, Ext_Mem);
+ Trim_P2D_R(ExtendedMemoryDescr1, RangeRequest, Ext_Mem);
+
+ // Copy Start/End to new descriptor
+ Parse_Descriptor(P2D_R, Ext_Mem, Fields);
+ return (Fields[1] + 1);
+}
+
+
+typedef struct {
+ UCHAR StartType;
+ UCHAR EndType;
+ UCHAR Port;
+ ULONG Msr;
+} ROUTING_INFO;
+#define MAX_ROUTE 5
+ROUTING_INFO Routing[MAX_ROUTE];
+
+
+//***********************************************************************
+// Allocates a Region Configuration Register
+//***********************************************************************
+ROUTING_INFO * pascal Allocate_RCONF(ULONG DevAddress, ROUTING_INFO * RoutingPtr)
+{
+
+ // Allocate a region configuration register
+ // If in Southbridge...
+ if ((DevAddress & MPCI_SB) == MPCI_SB) {
+ // then use SB MPCI R0-R15
+ RoutingPtr->StartType = MPCI_RCONF;
+ RoutingPtr->Msr = MPCI_SB;
+ } else {
+ // else use GX2 RCONF0-RCONF7
+ RoutingPtr->StartType = GX2_RCONF;
+ }
+ RoutingPtr++;
+ return RoutingPtr;
+}
+
+//***********************************************************************
+// This routines creates an association between the virtualized PCI BAR
+// (specified by BaseAddr and Device_ID) and an MBus device (specified by
+// Geode_ID). The Resource parameter specifies the type of BAR (Memory,
+// Memory-mapped I/O, or I/O) and the size of the region by RangeRequest.
+//***********************************************************************
+USHORT pascal Allocate_BAR(UCHAR Resource, USHORT BaseAddr, ULONG RangeRequest, \
+ USHORT Geode_ID, USHORT Device_ID)
+{ ULONG DevAddress, Mbiu, Physical=0;
+ UCHAR LSB, MSB;
+ UCHAR Instance=1;
+ UCHAR Index, StartType, EndType;
+ UCHAR * LinkPtr;
+ USHORT DevNum, Function, PCI_Address;
+ register ROUTING_INFO * RoutingPtr;
+ register PCI_HEADER_ENTRY * Pci;
+ register VIRTUAL_DEVICE * VirtDev;
+ register DESCRIPTOR * Descr;
+ int i;
+
+ // Validate parameters
+ switch (Resource) {
+ case RESOURCE_MEMORY:
+ case RESOURCE_MMIO:
+ case RESOURCE_SCIO:
+ case RESOURCE_IO:
+ break;
+ default:
+ Log_Error("Invalid value for parameter Resource: 0x%02X", Resource);
+ return 0x0000;
+ }
+
+ // Ensure RangeRequest meets PCI & MBus requirements
+ LSB = BitScanForward(RangeRequest);
+ MSB = BitScanReverse(RangeRequest);
+
+ if (Resource == RESOURCE_MEMORY || Resource == RESOURCE_MMIO) {
+ // Memory BARs must be at least 4 KB because of granularity of descriptors
+ if (RangeRequest < 4096) {
+ MSB = LSB = 12;
+ }
+ }
+ // If RangeRequest is not a power of 2...
+ if (LSB != MSB) {
+ // Round size of BAR to next higher power of 2
+ MSB++;
+ }
+
+
+ // Do some massaging based on Device ID
+ switch (Device_ID) {
+
+ // Graphics header is invisible until SoftVG is enabled.
+ case DEVICE_ID_GFX2:
+ case DEVICE_ID_GFX3:
+ NorthBridge[1] = Graphics_Hdr;
+ break;
+ }
+
+ //
+ // Determine the PCI Address by scanning the PCI tables for Device_ID
+ //
+ for (DevNum = 1; DevNum <= 21; DevNum++) {
+ if (VirtDev = *(VirtDevPtr+DevNum)) {
+ // For each defined function...
+ for (Function = 0; Function <= 7; Function++) {
+ if (Pci = *VirtDev++) {
+ // Do the Device IDs match ?
+ if (Pci->Device_ID == Device_ID) {
+ // Handle the 2nd instance of 5536's OHCI
+ if ((Geode_ID == ID_OHCI) && ((Pci+BAR0/4)->Flag & (IO_BAR | MEM_BAR | MMIO_BAR))) {
+ continue;
+ }
+ break;
+ }
+ }
+ }
+ // If Device ID match is found...
+ if (Function < 8) {
+ // Compute the PCI address
+ PCI_Address = (DevNum << 11) + (Function << 8) + (UCHAR)BaseAddr;
+
+ Pci = Find_Register(Pci, (UCHAR)BaseAddr);
+
+ // Check for errors
+ if ((USHORT)Pci > UNIMPLEMENTED_REGISTER) {
+ // Has this BAR already been allocated ?
+ if (Pci->Flag & (IO_BAR | MEM_BAR | MMIO_BAR)) {
+ // Yes, log an error
+ Log_Error("Resource has already been allocated for PCI address 0x%X", PCI_Address);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+
+ // Device_ID was not found in virtual PCI tables
+ if (DevNum > 21) {
+ Log_Error("DeviceID 0x%04X was not found", Device_ID);
+ return 0x0000;
+ }
+
+ // Record Mask for BAR
+ Pci->Mask = ~((1L << MSB)-1);
+
+
+ // Initialize routing structure
+ RoutingPtr = &Routing[0];
+ for (i=0; i<MAX_ROUTE; i++) {
+ RoutingPtr->StartType = 0x00;
+ RoutingPtr->EndType = 0x00;
+ RoutingPtr->Port = 0x00;
+ RoutingPtr->Msr = 0x00000000;
+ RoutingPtr++;
+ }
+ RoutingPtr = &Routing[0];
+
+
+ // Handle special cases
+ switch (Geode_ID) {
+
+ // SMI generation on access (no physical device, e.g. virtual registers)
+ case 0x0000:
+ DevAddress = 0x00000000;
+ break;
+
+ // Routing address of some devices has already been determined
+ case ID_MDD:
+ DevAddress = MDD_Base;
+ break;
+
+ // Handle the 2nd instance of 5536's OHCI
+ case ID_OHCI:
+ if (Function == 4) {
+ Instance = 2;
+ }
+
+ default:
+ // Search for the requested Geode_ID
+ DevAddress = Find_MBus_ID(Geode_ID, Instance);
+ if (!DevAddress) {
+ Log_Error("Geode ID 0x%04X was not found for Device ID 0x%04X", Geode_ID, Device_ID);
+ return 0x0000;
+ }
+ break;
+
+ }
+
+ // If an LBAR is required, allocate it
+ if (Pci->LBar) {
+ RoutingPtr->StartType = MDD_LBAR;
+ RoutingPtr->Msr = MDD_Base;
+ switch (Geode_ID) {
+ case ID_USB_20:
+ // OHCI needs an LBAR in the MDD
+ if ((HdrPtr+REVISION_ID/4)->Interface == 0x10) {
+ (UCHAR)RoutingPtr->Msr = MSR_LBAR_KEL1;
+ RoutingPtr++;
+ }
+ RoutingPtr->StartType = USB_LBAR;
+
+ case ID_ATA:
+ RoutingPtr->Msr = DevAddress;
+ break;
+ }
+ (UCHAR)RoutingPtr->Msr = Pci->LBar;
+ RoutingPtr++;
+ }
+
+ // Get an available descriptor appropriate to the type of BAR
+ switch (Resource) {
+
+ // Physical Memory
+ case RESOURCE_MEMORY:
+
+ // Mark it as a memory BAR
+ Pci->Flag |= MEM_BAR;
+
+ RoutingPtr->StartType = P2D_BMO;
+ RoutingPtr->EndType = P2D_RO;
+ RoutingPtr->Msr = Mbiu0;
+
+ // Legacy VGA frame buffers don't require physical memory
+ if ((UCHAR)BaseAddr > BAR5) {
+ ULONG RegionEnables, RegionProperties[2];
+
+#define OFF_PROPS (REGION_WS) // Frame buffer properties to be disabled
+#define OFF_PROPERTIES ((OFF_PROPS<<24) | (OFF_PROPS<<16) | (OFF_PROPS<<8) | (OFF_PROPS))
+#define ON_PROPS (0) // Frame buffer properties to be enabled
+#define ON_PROPERTIES (( ON_PROPS<<24) | ( ON_PROPS<<16) | ( ON_PROPS<<8) | ( ON_PROPS))
+
+ // Set MPCI Fixed Region Enables and disable write-serialize
+ Read_MSR(MSR_RCONF_A0_BF, RegionProperties);
+
+ Physical = 0xA0000;
+ RegionEnables = 0x00;
+
+ switch (RangeRequest) {
+
+ case 128L*1024:
+ RegionEnables = 0xFF; // A0000-BFFFF
+ RegionProperties[1] &= ~OFF_PROPERTIES;
+ RegionProperties[1] |= ON_PROPERTIES;
+
+ case 64L*1024:
+ RegionEnables |= 0x0F; // A0000-AFFFF
+ RegionProperties[0] &= ~OFF_PROPERTIES;
+ RegionProperties[0] |= ON_PROPERTIES;
+ break;
+
+ case 32L*1024:
+ RegionEnables = 0xC0; // B8000-BFFFF
+ RegionProperties[1] &= ~(OFF_PROPERTIES & 0xFFFF0000);
+ RegionProperties[1] |= (ON_PROPERTIES & 0xFFFF0000);
+ Physical = 0xB8000;
+ break;
+
+ }
+
+ // Set Vail Region Properties (0x180B)
+ Write_MSR(MSR_RCONF_A0_BF, RegionProperties);
+
+ // Set MPCI Fixed Region Enables (0x2014)
+ Write_MSR_LO(MPCI_NB + MPCI_REN, Read_MSR_LO(MPCI_NB + MPCI_REN) | RegionEnables);
+
+ // Allocate P2D_BM
+ switch (Device_ID) {
+ case DEVICE_ID_GFX2:
+ case DEVICE_ID_GFX3:
+ RoutingPtr->StartType = P2D_BM;
+ break;
+ }
+ RoutingPtr++;
+
+ } else {
+
+ // Trim required memory from the end of extended memory
+ Physical = Trim_Extended_Memory(RangeRequest);
+ DevAddress = Find_MBus_ID(ID_MC, 1);
+
+ // Allocate a Region Configuration Register
+ RoutingPtr++;
+ RoutingPtr = Allocate_RCONF(DevAddress, RoutingPtr);
+ }
+ break;
+
+
+ // Memory-mapped I/O
+ case RESOURCE_MMIO:
+ // Mark it as a memory-mapped BAR
+ Pci->Flag |= MMIO_BAR;
+
+ switch (Geode_ID) {
+
+ // Subtractive ports; no MBIU descriptor is necessary
+ case ID_MPCI:
+ case ID_MDD:
+ break;
+
+ case ID_USB_20:
+ case ID_OHCI:
+ // Allocate a P2D_BMK descriptor in MBIU2
+ RoutingPtr->StartType = P2D_BMK;
+ if (!(Pci->Flag & USE_BMK)) {
+ RoutingPtr->EndType = P2D_BM;
+ }
+ RoutingPtr->Msr = Mbiu2;
+ RoutingPtr->Port = (UCHAR)DevAddress;
+ RoutingPtr++;
+
+ if (Pci->Flag & EPCI_RW) {
+ // Allocate the appropriate mailbox address
+ RoutingPtr->StartType = EPCI;
+ RoutingPtr->Msr = DevAddress & ROUTING;
+ RoutingPtr++;
+ }
+ break;
+
+ case ID_VG:
+ RoutingPtr->StartType = P2D_RO;
+ RoutingPtr++;
+ // Fix for VG alias bug: POFFSET field should be set to -PBASE
+ // See Compute_Msr_Value()
+ Physical = 1;
+ break;
+
+ case ID_AES:
+ RoutingPtr->StartType = P2D_R;
+ RoutingPtr++;
+ break;
+
+ default:
+ RoutingPtr->StartType = P2D_BM;
+ RoutingPtr->EndType = P2D_RO;
+ RoutingPtr++;
+ break;
+ }
+
+ // Allocate a Region Configuration Register
+ RoutingPtr = Allocate_RCONF(DevAddress, RoutingPtr);
+ break;
+
+
+ // I/O Space
+ case RESOURCE_SCIO:
+ RoutingPtr->StartType = IOD_SC;
+ RoutingPtr++;
+
+ case RESOURCE_IO:
+ // Mark it as an I/O BAR
+ Pci->Flag |= IO_BAR;
+
+ switch (Geode_ID) {
+ // Subtractive ports; no MBIU descriptor is necessary
+ case ID_MPCI:
+ case ID_MDD:
+ break;
+
+ default:
+ if (Resource != RESOURCE_SCIO) {
+ RoutingPtr->StartType = IOD_BM;
+ RoutingPtr->EndType = IOD_SC;
+ RoutingPtr++;
+ }
+ break;
+ }
+
+ // If device is in the Southbridge...
+ if ((DevAddress & MPCI_SB) == MPCI_SB) {
+ // allocate a Region Configuration Register
+ RoutingPtr = Allocate_RCONF(DevAddress, RoutingPtr);
+ }
+
+ // PCI Spec requires I/O BAR a minimum of 4 bytes
+ Pci->Mask &= 0xFFFFFFFC;
+ break;
+
+ default:
+ Log_Error("Unknown resource requested: 0x%X", Resource);
+ return 0x0000;
+ }
+
+
+
+
+ //
+ // Get device's PCI Revision ID
+ //
+ switch (Device_ID) {
+
+ // Revision of some devices is already determined
+ case DEVICE_ID_OHCI:
+ case DEVICE_ID_5536:
+ case DEVICE_ID_GX2:
+ case DEVICE_ID_LX:
+ break;
+
+ // Graphic's Revision ID comes from GP, not VG or DF
+ case DEVICE_ID_GFX2:
+ case DEVICE_ID_GFX3:
+ if (Geode_ID != ID_GP) {
+ break;
+ }
+
+ default:
+ // Read MBD_MSR_CAP
+ Mbiu = DevAddress;
+ (USHORT)Mbiu = MBD_MSR_CAP;
+
+ // Insert Revision ID into header
+ (HdrPtr+REVISION_ID/4)->Revision_ID = (UCHAR)Read_MSR_LO(Mbiu);
+ break;
+ }
+
+ // Compute number of MSRs needed to support this BAR
+ i = (UCHAR)(RoutingPtr - &Routing[0]);
+
+ if (i >= MAX_ROUTE) {
+ Log_Error("Allocate_BAR- routing failed on PCI address 0x%X", PCI_Address);
+ }
+
+ //
+ // Allocate the required MSRs
+ //
+ RoutingPtr = &Routing[0];
+ LinkPtr = &Pci->Link;
+
+ while (i) {
+
+ // Force use of P2D_RO to prevent ROVER from complaining about overlapped
+ // physical addresses when the frame buffer length is not a power of 2.
+ if (Pci == &Graphics_Hdr[BAR0/4]) {
+ if(RoutingPtr->Msr == Mbiu0) {
+ RoutingPtr->StartType = P2D_RO;
+ }
+ }
+ StartType = RoutingPtr->StartType;
+ EndType = RoutingPtr->EndType;
+
+ // If 2nd choice is not specified, force it to 1st choice
+ if (EndType == 0x00) {
+ EndType = StartType;
+ }
+ // Has the correct MBIU been determined ?
+ if (RoutingPtr->Msr == 0x00000000) {
+ // Determine the MBIU as follows:
+ // - If the 2nd routing field == 0, then it's MBIU0
+ // - If the 1st three routing fields match MBIU2, then it's MBIU2
+ // - Otherwise it's MBIU1
+ if ((DevAddress & (7L << 26)) == 0) {
+ Mbiu = Mbiu0;
+ } else {
+ if ((DevAddress & 0xFF800000) == (Mbiu2 & 0xFF800000)) {
+ Mbiu = Mbiu2;
+ } else {
+ Mbiu = Mbiu1;
+ }
+ }
+ RoutingPtr->Msr = Mbiu;
+ }
+
+
+ if (StartType) {
+
+ Index = Allocate_Descriptor(StartType, EndType, RoutingPtr->Msr);
+
+ if (Index == DESCRIPTOR_NOT_FOUND) {
+
+ // If SMI generation, then any MBIU may be used
+ if (!Geode_ID) {
+ // Try MBIU1
+ Mbiu = Mbiu1;
+ Index = Allocate_Descriptor(StartType, EndType, Mbiu);
+ if (Index == DESCRIPTOR_NOT_FOUND) {
+ if (Mbiu = Mbiu2) {
+ Index = Allocate_Descriptor(StartType, EndType, Mbiu);
+ }
+ }
+ }
+ }
+ }
+
+ if (Index == DESCRIPTOR_NOT_FOUND) {
+ UCHAR Mbiu=9;
+
+ if (RoutingPtr->Msr == Mbiu0) Mbiu = 0;
+ else if (RoutingPtr->Msr == Mbiu1) Mbiu = 1;
+ else if (RoutingPtr->Msr == Mbiu2) Mbiu = 2;
+ Log_Error("MSR allocation failed for GeodeID=%02X/DeviceID=%04X/BAR%x/MBIU%1x", \
+ (UCHAR)Geode_ID, Device_ID, (USHORT)((BaseAddr-BAR0)/4), Mbiu);
+ goto NextMSR;
+ }
+
+ // Record info about the descriptor
+ Descr = &MSRs[Index];
+ Descr->Owner = PCI_Address;
+ Descr->Range = RangeRequest;
+ Descr->Physical = Physical;
+
+
+ if (RoutingPtr->Port == 0) {
+ RoutingPtr->Port = (UCHAR)DevAddress;
+ }
+ Descr->Port = RoutingPtr->Port;
+
+ // If embedded PCI device, record PCI mailbox MSR to Command register
+ if (StartType == EPCI) {
+ CommandPtr->Link = Index;
+ }
+
+ // Link to previous MSRs[] (or Pci->Link)
+ * LinkPtr = Index;
+
+ // Update link pointer
+ LinkPtr = &Descr->Link;
+
+
+ // Is an additional swiss-cheese descriptor necessary ?
+ if (Descr->Type == IOD_SC && RangeRequest > 8) {
+ RangeRequest -= 8;
+ continue;
+ }
+
+ // If the device is on GLIU0, then allocate a descriptor on GLIU1
+ // to route FS2 transactions to GLIU0.
+ if (RoutingPtr->Msr == Mbiu0 && RoutingPtr->StartType < GX2_RCONF ) {
+ // Don't allocate MBUI1 descriptor for virtual register BAR
+ if (Geode_ID) {
+ switch (RoutingPtr->StartType) {
+
+ case IOD_SC:
+ RoutingPtr->StartType = IOD_BM;
+ RoutingPtr->EndType = IOD_SC;
+ RangeRequest = 1L << MSB;
+ break;
+
+ case P2D_RO:
+ if (Pci == &Graphics_Hdr[BAR0/4]) {
+ RoutingPtr->StartType = P2D_R;
+ break;
+ } else {
+ RoutingPtr->StartType = P2D_BM;
+ }
+
+ default:
+ RangeRequest = 1L << MSB;
+ break;
+ }
+
+ // Use only 1 descriptor for northbound VG transactions
+ if (RangeRequest == 16 && Geode_ID == ID_VG) {
+ static UCHAR VG_FS2_Flag=0;
+
+ if (VG_FS2_Flag) {
+ break;
+ } else {
+ VG_FS2_Flag = 1;
+ RangeRequest = 32;
+ }
+ }
+
+ RoutingPtr->Msr = Mbiu1;
+ RoutingPtr->Port = MBIU1_SelfReference;
+ continue;
+ }
+ }
+
+ // Advance ptr to next MSR
+NextMSR:
+ RoutingPtr++;
+ i--;
+ } // end while
+
+
+
+ // Make appropriate Command register bit R/W
+ if (Pci->Flag & IO_BAR) {
+ CommandPtr->Mask |= IO_SPACE;
+ } else {
+ CommandPtr->Mask |= MEM_SPACE;
+ }
+
+ return PCI_Address;
+
+}
+
+
+
+
+
+//***********************************************************************
+//
+// Perform early POST initialization of virtualized PCI config space
+//
+//***********************************************************************
+void VirtualPCI_EarlyInit(void)
+{ USHORT i;
+ ULONG PCI_Address;
+ ULONG MsrAddr;
+ VIRTUAL_PTR DevicePtr;
+ PCI_HEADER_ENTRY * Pci;
+
+
+ // Initialize ptr to virtualized PCI topology
+ VirtDevPtr = &Virtual_Devices[0];
+
+
+ // Virtualize CS5536's configuration space, if present,
+ // at the same device number as the h/w header.
+ i = (UCHAR)((USHORT)HardwareInfo.Chipset_Base >> 11);
+ switch (HardwareInfo.Chipset_ID) {
+
+ case DEVICE_ID_5536:
+ Virtual_Devices[i] = Virtual_5536;
+ break;
+
+ default:
+ return;
+ }
+
+ SouthBridge = Virtual_Devices[i];
+
+ // Compute mask of IDSELs that are to be virtualized
+ for (i = 1; i <= 21; i++) {
+ // If IDSEL is virtualized, set enable mask
+ DevicePtr = * (VirtDevPtr+i);
+ if (DevicePtr) {
+
+ // Record IDSEL to trap
+ Virtualized_PCI_Devices |= (1L << i);
+
+ // Register System Manager for this IDSEL
+ PCI_Address = ((ULONG)i << 11);
+ Register_Event(EVENT_PCI_TRAP, MAX_PRIORITY, SysMgr_VSM, PCI_Address, 0x07FF);
+ }
+ }
+
+ // Enable virtual PCI headers
+ MsrAddr = MPCI_NB + MBD_MSR_SMI;
+ Write_MSR_LO(MsrAddr, Read_MSR_LO(MsrAddr) & ~VPHM);
+
+
+ // Store CPU's Device & Revision IDs in Host Bridge's PCI header
+ HostBridge_Hdr[0].Device_ID = HardwareInfo.CPU_ID;
+ HostBridge_Hdr[2].Revision_ID = (UCHAR)HardwareInfo.CPU_Revision;
+
+
+ // AES header (F2) BAR
+ Allocate_BAR(RESOURCE_MMIO, BAR0, 16*1024, ID_AES, AES_Hdr[0].Device_ID);
+
+ // Implement Interrupt Pin/Line registers in LX graphic header
+ if (Pci = Find_Register(Graphics_Hdr, INTERRUPT_LINE)) {
+ // Make Interrupt Line read-write
+ (UCHAR)Pci->Mask = 0xFF;
+ // Set Interrupt Pin to INTA#
+ Pci->Interrupt_Pin = 0x01;
+ }
+}
+
+
+//***********************************************************************
+// Routine to support INFO getting PCI<->MSR linkages
+//***********************************************************************
+ULONG pascal Get_MSR_Linkage(USHORT PCI_Address)
+{ PCI_HEADER_ENTRY * Pci;
+ ULONG MsrAddr;
+ static UCHAR Link=0x00;
+ static DESCRIPTOR * Descr;
+ static USHORT LastPCI = 0x0000;
+
+ if (PCI_Address != LastPCI) {
+ LastPCI = PCI_Address;
+ Pci = Get_Structure(PCI_Address);
+
+ switch ((USHORT)Pci) {
+
+ case UNIMPLEMENTED_FUNCTION:
+ case UNIMPLEMENTED_REGISTER:
+ Link = 0x00;
+ break;
+
+ default:
+ Link = Pci->Link;
+ break;
+ }
+ }
+
+ Descr = &MSRs[Link];
+
+ // Get link to next descriptor
+ Link = Descr->Link;
+
+ if (!(MsrAddr = Descr->MsrAddr)) {
+ LastPCI = 0x0000;
+ }
+
+ return MsrAddr;
+}
+
+
+
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/vpci.h b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/vpci.h
new file mode 100755
index 0000000..e57fcc3
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/vpci.h
@@ -0,0 +1,174 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+
+#define UNIMPLEMENTED_FUNCTION 0
+#define UNIMPLEMENTED_REGISTER 1
+
+
+struct vpci_header {
+ unsigned char Reg; // Register offset (DWORD aligned)
+ unsigned char Flag; // See flag fields below
+ union {
+ unsigned long Value; // Current value of register
+ struct {
+ unsigned short Value_LO;
+ unsigned short Value_HI;
+ };
+ struct {
+ unsigned short Vendor_ID; // Register 0x00
+ unsigned short Device_ID;
+ };
+ struct { // Register 0x08
+ unsigned char Revision_ID;
+ unsigned char Interface;
+ union {
+ struct {
+ unsigned char SubClass;
+ unsigned char BaseClass;
+ };
+ unsigned short Class;
+ };
+ };
+ struct { // Register 0x0C
+ unsigned char CacheLineSize;
+ unsigned char LatencyTimer;
+ unsigned char HeaderType;
+ unsigned char Bist;
+ };
+ struct { // BARs
+ union {
+ unsigned short IO_Base;
+ unsigned long Memory_Base;
+ };
+ };
+ struct { // Register 0x3C
+ unsigned char Interrupt_Line;
+ unsigned char Interrupt_Pin;
+ unsigned char Min_Gnt;
+ unsigned char Max_Gnt;
+ };
+ struct { // EHCI register 0x54
+ unsigned char EHCI_SMI_Enables;
+ unsigned char reserved1;
+ unsigned char EHCI_Errors;
+ unsigned char reserved2;
+ };
+ struct { // EHCI register 0x60
+ unsigned char SRBN;
+ unsigned char FLADJ;
+ unsigned short PORTWAKECAP;
+ };
+ };
+ unsigned long Mask; // 0 = R/O 1 = R/W
+ unsigned char LBar; // MSR offset of LBAR, if required
+ unsigned char Link; // Index of 1st MSR in chain
+ unsigned long WriteToClear; // 0 = N/A 1 = W/C
+
+};
+
+typedef struct vpci_header PCI_HEADER_ENTRY ;
+
+
+// Device MSRs used to implement a BAR
+// ------------ --------------------------------------------------------------
+// Northbridge MBIUx descriptor
+// Graphics MBIU0 descriptor MBIU1 (for FS2) RCONF
+// Southbridge LBAR
+// IDE MBIU2 descriptor Region config
+// OHCI MBIU2 to OHCI MBIU2 to KEL (P2D_BMK) MDD LBAR
+
+// PCI_HEADER_ENTRY.Flag definitions:
+#define EOL (1 << 7) // End of list
+#define PCI_EHCI (1 << 6) // EHCI (NOTE: leverages same bit as PCI_PM)
+#define PCI_PM (1 << 6) // PCI Power Management
+#define USE_BMK (1 << 5) // P2D_BMK needs Bizarro bit set
+#define IO_BAR (1 << 4) // BAR is I/O
+#define MEM_BAR (1 << 3) // BAR is memory
+#define MMIO_BAR (1 << 2) // BAR is memory-mapped I/O
+#define EPCI_W (1 << 1) // Embedded PCI: write to h/w
+#define EPCI_R (1 << 0) // Embedded PCI: read from h/w
+#define EPCI_RW (EPCI_R | EPCI_W)
+
+typedef PCI_HEADER_ENTRY * VIRTUAL_DEVICE;
+typedef VIRTUAL_DEVICE * VIRTUAL_PTR;
+
+#define MAX_DESCR 110 // Max. # for all descriptor types in all MBIUs
+#define DESCRIPTOR_NOT_FOUND 0
+
+
+
+// NOTE: A copy of this structure exists in INIT.ASM
+typedef struct {
+ unsigned char Type; // Type of MSR
+ unsigned char Flag; // See definitions below
+ unsigned char Link; // Link to next MSR
+ unsigned char Split; // Index of descriptor that was split
+
+ unsigned short Owner; // PCI Address this descriptor belongs to
+ unsigned char Mbiu; // MBUI on which this descriptor is located
+ unsigned char Port; // Port this descriptor routes to
+
+ unsigned long MsrAddr; // Routing address of MSR (descriptor/LBAR/RCONF)
+ unsigned long Physical; // Physical memory assigned (00000000 if none)
+ unsigned long Range; // Actual I/O range for IOD_SC
+ unsigned long MsrData[2];
+ unsigned short Address; // Address of I/O Trap or Timeout
+} DESCRIPTOR;
+
+
+// DESCRIPTOR.Flag definitions
+#define IO_TIMEOUT (1 << 2) // Descriptor is used for I/O timeout
+#define IO_TRAP (1 << 1) // Descriptor is used for I/O trap
+#define AVAILABLE (1 << 0) // Descriptor is available
+
+
+
+
+
+typedef struct {
+ unsigned char NP2D_BM;
+ unsigned char NP2D_BMO;
+ unsigned char NP2D_R;
+ unsigned char NP2D_RO;
+ unsigned char NP2D_SC;
+ unsigned char NP2D_SCO;
+ unsigned char NP2D_BMK;
+ unsigned char NIOD_BM;
+ unsigned char NIOD_SC;
+ unsigned char NPORTS;
+ unsigned char NSTATS;
+} CAPABILITIES;
+
+
+
+
+
+
+// External function prototypes:
+void pascal Read_MSR(unsigned long, unsigned long *);
+void pascal Write_MSR(unsigned long, unsigned long *);
+void pascal Write_MSR_LO(unsigned long, unsigned long);
+void pascal MergeFields(unsigned long *, unsigned long, unsigned long, unsigned long);
+void pascal Parse_Capabilities(unsigned long *, CAPABILITIES *);
+void pascal Free_Descriptor(unsigned char Index);
+void pascal Update_BAR(PCI_HEADER_ENTRY *, unsigned char);
+unsigned char pascal Allocate_Descriptor(unsigned char, unsigned char, unsigned long);
+unsigned long pascal Read_MSR_LO(unsigned long);
+unsigned long pascal Find_MBus_ID(unsigned short, unsigned char);
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/vr.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/vr.c
new file mode 100755
index 0000000..c6f6a11
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/vr.c
@@ -0,0 +1,356 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//******************************************************************************
+//* Implements the virtual register handler
+//******************************************************************************
+
+#include "VSA2.H"
+#include "PROTOS.H"
+#include "SYSMGR.H"
+#include "VR.H"
+#include "PCI.H"
+#include "CHIPSET.H"
+
+// External variables
+extern ULONG Saved_EAX;
+extern USHORT Saved_AX;
+extern SmiHeader SMM_Header;
+extern ULONG IRQ_Mask;
+extern ULONG Audio_IRQ;
+extern ULONG NativeAudioStatus;
+extern ULONG MsgPacket[];
+extern ULONG VSM_Ptrs[];
+extern Hardware HardwareInfo;
+
+
+// External function prototypes
+extern void pascal Send_Synchronous_Event(EVENT, SmiHeader *);
+extern void pascal VR_Miscellaneous_Write(UCHAR);
+extern void pascal Return_Virtual_Value(SmiHeader *, ULONG);
+extern ULONG pascal VR_Miscellaneous_Read(UCHAR);
+
+
+
+
+//***********************************************************************
+// Initialize virtual register trapping
+//***********************************************************************
+void Init_Virtual_Regs(void)
+{ USHORT PCI_Addr;
+ ULONG Enable;
+
+
+ // Allocate a 4-byte I/O BAR0 associated with Northbridge header
+ PCI_Addr = Allocate_BAR(RESOURCE_SCIO, BAR0, 4, 0x0000, HardwareInfo.CPU_ID);
+
+ // Set the base address
+ Virtual_PCI_Write_Handler(PCI_Addr, DWORD_IO, VRC_INDEX);
+
+ // Enable the I/O space
+ PCI_Addr = (PCI_Addr & 0xFF00) + COMMAND;
+ Enable = Virtual_PCI_Read_Handler(PCI_Addr);
+ Enable |= IO_SPACE;
+ Virtual_PCI_Write_Handler(PCI_Addr, DWORD_IO, Enable);
+
+
+}
+
+//***********************************************************************
+// Handles audio virtual registers when there is no audio VSM.
+//***********************************************************************
+void Handle_Audio_VRC(UCHAR Index, ULONG Trapped_Data, USHORT Trapped_Flags, UCHAR Size)
+{ static USHORT AudioVRs[MAX_AUDIO+1] = {
+ 0x201,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xAC97,0xFFFF,0xFFFF,0xFFFF,0x04F0
+ };
+
+
+
+ // If illegal register, ignore it
+ if (Index > MAX_AUDIO) {
+ return;
+ }
+
+ if (Trapped_Flags & SMI_FLAGS_OUTPUT) {
+
+ switch (Index) {
+
+ // Read-only registers
+ case CODEC_TYPE:
+ case AUDIO_VERSION:
+ return;
+
+ // Native audio IRQ
+ case AUDIO_IRQ:
+
+ // Set previous audio IRQ to external
+ IRQ_Mask |= Audio_IRQ << 16;
+
+ Audio_IRQ = 0;
+ if ((UCHAR)Trapped_Data) {
+ Audio_IRQ = 0x00000001L << (UCHAR)Trapped_Data;
+ }
+ break;
+
+ // Native audio status pointer
+ case STATUS_PTR:
+ switch (SMM_Header.data_size) {
+
+ case WORD_IO:
+ (USHORT)NativeAudioStatus = (USHORT)Trapped_Data;
+ break;
+
+ case DWORD_IO:
+ NativeAudioStatus = Trapped_Data;
+ break;
+ }
+ break;
+ }
+
+ AudioVRs[Index] = (USHORT)Trapped_Data;
+
+ } else {
+ // Return virtual register value
+ Saved_AX = AudioVRs[Index];
+ // STATUS_PTR may be read as a DWORD
+ if (Index == STATUS_PTR && DWORD_IO == Size) {
+ Saved_EAX = NativeAudioStatus;
+ }
+ }
+}
+
+
+typedef struct {
+ union {
+ USHORT ClassIndex;
+ struct {
+ UCHAR Index;
+ UCHAR Class;
+ };
+ };
+} CLASS_INDEX;
+
+
+typedef struct {
+ union {
+ ULONG Dword;
+ struct {
+ USHORT Word0;
+ USHORT Word1;
+ };
+ struct {
+ UCHAR Byte0;
+ UCHAR Byte1;
+ UCHAR Byte2;
+ UCHAR Byte3;
+ };
+ };
+} DWORD;
+
+#define VR_LOCKED 0
+#define VR_UNLOCKED 1
+#define VR_INDEXED 2
+
+//***********************************************************************
+// Handles accesses to Virtual Registers
+//***********************************************************************
+void VR_Handler(SmiHeader * SmiHdr)
+{ USHORT Trapped_Addr;
+ ULONG Data, SegOffset;
+ UCHAR Trapped_Flags, IO_Write, Addr_2LSBs, Size;
+ DWORD Trapped_Data;
+ static UCHAR VR_LockState = 0;
+ static CLASS_INDEX VirtReg;
+
+ // Get info from SMM header
+ Trapped_Addr = (USHORT)SmiHdr->IO_addr;
+ Trapped_Flags = (UCHAR)SmiHdr->SMI_Flags_Ushort;
+ IO_Write = (UCHAR)Trapped_Flags & SMI_FLAGS_OUTPUT ? 1 : 0;
+ Size = (UCHAR)SmiHdr->data_size;
+ Addr_2LSBs = (UCHAR)Trapped_Addr & 3;
+ Trapped_Data.Dword = SmiHdr->write_data;
+
+ SegOffset = (ULONG) SmiHdr->_CS.selector << 16;
+ SegOffset += (USHORT)SmiHdr->Current_EIP;
+
+
+ // Validate the I/O as a valid virtual register access
+ switch (Size) {
+
+ case DWORD_IO:
+ // Allow unlock & index to occur in a single SMI
+ if (VR_LockState == VR_LOCKED) {
+ if (IO_Write && (VR_UNLOCK == Trapped_Data.Word1)) {
+ VirtReg.ClassIndex = Trapped_Data.Word0;
+ VR_LockState = VR_INDEXED;
+ return;
+ }
+ }
+
+ case BYTE_IO:
+ // Byte I/O is illegal for virtual registers. Start over.
+ VR_LockState = VR_LOCKED;
+ return;
+
+ } // end switch(Size)
+
+
+ switch(Addr_2LSBs) {
+
+ // Virtual register INDEX
+ case 0:
+
+ switch (VR_LockState) {
+
+ // Virtual registers have been unlocked & Class:Index has been written,
+ // but VR class::index is being re-written.
+ case VR_INDEXED:
+ if (!IO_Write) {
+ goto ReturnClassIndex;
+ }
+ VR_LockState = VR_LOCKED;
+
+ // Virtual registers have not been unlocked yet
+ case VR_LOCKED:
+ if (IO_Write) {
+ if (VR_UNLOCK == Trapped_Data.Word0) {
+ // Virtual registers have been unlocked.
+ // Advance to the next VR_LockState.
+ VR_LockState = VR_UNLOCKED;
+ }
+ }
+ return;
+
+ // Virtual registers have been unlocked.
+ // Next VR write should be Class::Index
+ case VR_UNLOCKED:
+ if (IO_Write) {
+
+ // Record the VR index & advance to the next VR_LockState
+ VirtReg.ClassIndex = Trapped_Data.Word0;
+
+
+ // Report error if illegal VR class
+ if (VirtReg.Class > MAX_VR_CLASS && VirtReg.Class < 0x80) {
+ Log_Error("Invalid virtual register class 0x%02X", VirtReg.Class);
+ goto VR_Error;
+ }
+
+ VR_LockState = VR_INDEXED;
+
+ } else {
+ReturnClassIndex:
+ // Reading back Class::Index
+ Return_Virtual_Value(SmiHdr, (ULONG)VirtReg.ClassIndex);
+ }
+ return;
+
+
+ } // end switch (VR_LockState)
+
+ Log_Error("Incorrect virtual register sequence");
+ goto VR_Error;
+
+
+ // Virtual register DATA
+ case 2:
+ if (VR_INDEXED == VR_LockState) {
+ switch (VirtReg.Class) {
+
+ case VRC_MISCELLANEOUS:
+
+ if (IO_Write) {
+
+ VR_Miscellaneous_Write(VirtReg.Index);
+
+ } else {
+
+ Data = VR_Miscellaneous_Read(VirtReg.Index);
+
+ switch (VirtReg.Index) {
+ case SIGNATURE:
+ case HIGH_MEM_ACCESS:
+ (UCHAR)SmiHdr->data_size = DWORD_IO;
+
+ case VSA_VERSION_NUM:
+ case VSM_VERSION:
+ // Return virtualized PCI device value to the right environment
+ Return_Virtual_Value(SmiHdr, Data);
+ break;
+ }
+ }
+ // If access was to an invalid MSR, ignore the SSMI_FLAG
+ if (VirtReg.Index == MSR_ACCESS) {
+ SmiHdr->SMI_Flags.IO_Trap = 0;
+ SmiHdr->SMI_Flags.Ext_IO_Trap = 0;
+ }
+ break;
+
+
+ default:
+
+ // Prepare message packet
+ MsgPacket[1] = (ULONG)VirtReg.ClassIndex;
+ MsgPacket[2] = 0; // Assume I/O read
+ MsgPacket[3] = 0;
+ if (IO_Write) {
+ (UCHAR) MsgPacket[2] = 1; // I/O write
+ (USHORT)MsgPacket[3] = Trapped_Data.Word0;
+ }
+ // Send EVENT_VIRTUAL_REGISTER to registered VSM(s)
+ Send_Synchronous_Event(EVENT_VIRTUAL_REGISTER, SmiHdr);
+ break;
+
+ } // switch (Class)
+
+ } else {
+ static UCHAR * RdWr[] = {"Read", "Write"};
+
+ Log_Error("%s of locked VR %02X:%02X at %04X:%08X ", RdWr[IO_Write], VirtReg.Class, VirtReg.Index, SmiHdr->_CS.selector, SmiHdr->Current_EIP);
+VR_Error:
+
+
+ // Ignore writes. Return 0's for reads.
+ if (!IO_Write) {
+ // NOTE: We know it is a WORD_IO from above validation.
+ Saved_AX = 0;
+ }
+ }
+ break;
+
+ default:
+ // Report mis-aligned access to virtual register
+ Log_Error("Mis-aligned access to virtual register 0x04X", Trapped_Addr);
+ break;
+ } // end switch(Addr_2LSBs)
+
+ // Reset the VR state machine
+ VR_LockState = VR_LOCKED;
+
+}
+
+
+
+
+
+
+
+
+
+ \ No newline at end of file
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/vr_misc.asm b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/vr_misc.asm
new file mode 100755
index 0000000..f6b94af
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/vr_misc.asm
@@ -0,0 +1,1161 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;******************************************************************************
+;* Implements the virtual register VR_MISCELLANEOUS.
+;******************************************************************************
+
+
+.model tiny,c
+.586
+.CODE
+
+include VSA2.INC
+include SYSMGR.INC
+include VR.INC
+include CHIPSET.INC
+include GX2.INC
+
+externdef MsgPacket: byte
+externdef HistoryStart: word
+externdef HistoryEnd: word
+externdef HistoryWrap: word
+externdef SysMgr_VSM: dword
+externdef VSM_Ptrs: dword
+externdef Saved_EAX: dword
+externdef Saved_EBX: dword
+externdef Saved_ECX: dword
+externdef Saved_EDX: dword
+externdef Saved_ESI: dword
+externdef Saved_EDI: dword
+externdef Saved_EBP: dword
+externdef Saved_DS: dword
+externdef Saved_ES: dword
+externdef Saved_FS: dword
+externdef Saved_GS: dword
+externdef Saved_SS: dword
+externdef IDT_Selector: dword
+externdef IDT_Base: dword
+externdef IDT_Limit: dword
+externdef VSM_ListHead: dword
+
+externdef pascal Get_MSR_Linkage: proc
+externdef pascal Broadcast_Message: proc
+externdef pascal Register_Event: proc
+externdef Get_Errors: proc
+externdef VirtualRegisterEvent: proc
+externdef HardwareInfo: Hardware
+externdef History: EVENT_HISTORY
+externdef Events: EVENT_ENTRY
+externdef SMM_Header: SmiHeader
+
+; Required for OHCI h/w bugs
+externdef OHCI1_Hdr: dword
+externdef OHCI2_Hdr: dword
+externdef OHCI1_Smi: dword
+externdef OHCI2_Smi: dword
+
+;******************************************************************************
+ align 2
+
+public VSM_Filter
+VSM_Filter db VSM_ANY
+ db 0 ; Pad for alignment
+Next_VSM dd 0
+
+
+
+ReadMiscTable:
+ dw OFFSET Get_VSA_Version ; 0
+ dw OFFSET Read_High_Memory ; 1
+ dw OFFSET Get_VSM_Info ; 2
+ dw OFFSET Signature ; 3
+ dw OFFSET Get_HW_Info ; 4
+ dw OFFSET Get_VSM_Version ; 5
+ dw OFFSET JustReturn ; 6
+ dw OFFSET MSR_Read ; 7
+ dw OFFSET JustReturn ; 8
+MAX_READ equ ($-ReadMiscTable)/2
+
+WriteMiscTable:
+ dw OFFSET JustReturn ; 0
+ dw OFFSET Write_High_Memory ; 1
+ dw OFFSET JustReturn ; 2
+ dw OFFSET JustReturn ; 3
+ dw OFFSET Select_HW_Info ; 4
+ dw OFFSET JustReturn ; 5
+ dw OFFSET Warm_Boot ; 6
+ dw OFFSET MSR_Write ; 7
+ dw OFFSET Do_WBINVD ; 8
+MAX_WRITE equ ($-WriteMiscTable)/2
+
+
+VSM_Info_Table:
+ dw OFFSET Get_VSM_Basics
+ dw OFFSET Get_VSM_Events
+ dw OFFSET Get_VSM_Statistics
+ dw OFFSET Get_VSM_History
+ dw OFFSET Get_VSM_Hardware
+ dw OFFSET Get_Errors
+ dw OFFSET Set_VSM_Type
+ dw OFFSET Get_Linkage
+MAX_INFO equ ($-VSM_Info_Table)/2
+
+
+
+;***************************************************************************
+; Handler for reads from a VRC_MISCELLANEOUS register
+; Returns ULONG with value read
+;***************************************************************************
+VR_Miscellaneous_Read proc pascal uses si di \
+ Index: BYTE
+
+ mov al, [Index]
+ cmp al, MAX_READ
+ mov di, 0 ; Read
+ jae short VRC_Common
+
+ lea bx, [ReadMiscTable]
+ call Dispatch
+ ret
+
+VR_Miscellaneous_Read endp
+
+
+;***************************************************************************
+; Handler for writes to a VRC_MISCELLANEOUS register
+;***************************************************************************
+VR_Miscellaneous_Write proc pascal uses si di \
+ Index: BYTE
+
+ mov al, [Index]
+ cmp al, MAX_WRITE
+ jb short UseTable
+ mov di, 1 ; Write
+VRC_Common::
+ mov bh, VRC_MISCELLANEOUS
+ mov bl, al
+ mov edx, [SysMgr_VSM] ; From_VSM
+ mov cx, word ptr [Saved_EAX]
+ call VirtualRegisterEvent
+ jmp short Exit
+
+UseTable:
+ lea bx, [WriteMiscTable]
+ call Dispatch
+Exit: ret
+
+VR_Miscellaneous_Write endp
+
+;***************************************************************************
+; Dispatches to routine defined by table at BX[AL]
+;***************************************************************************
+Dispatch proc
+
+ xor ah, ah
+ add ax, ax
+ add bx, ax
+ call word ptr [bx]
+JustReturn::
+ ret
+Dispatch endp
+
+
+
+
+;***************************************************************************
+; Dispatches to sub-function of GET_VSM_INFO (determined by caller's BL)
+;***************************************************************************
+Get_VSM_Info proc
+
+ mov al, byte ptr [Saved_EBX]
+ cmp al, MAX_INFO
+ jae short Exit
+ lea bx, [VSM_Info_Table]
+ call Dispatch
+Exit: ret
+
+Get_VSM_Info endp
+
+
+;***************************************************************************
+; SI = PCI address
+;***************************************************************************
+Get_Linkage proc
+
+
+ push word ptr [Saved_ESI]
+ call Get_MSR_Linkage
+
+ mov word ptr [Saved_ECX], ax ; Return MSR address in caller's ECX
+ mov word ptr [Saved_ECX+2], dx
+
+ ret
+
+Get_Linkage endp
+
+
+;***************************************************************************
+; Returns in EAX the location by EBX.
+; CF is toggled
+;***************************************************************************
+Read_High_Memory proc
+
+ mov ebx, [Saved_EBX]
+ mov eax, fs:[ebx]
+ mov [Saved_EAX], eax
+ mov edx, eax
+ shr edx, 16
+
+ ; Toggle the caller's carry flag
+ xor byte ptr ([SMM_Header]).EFLAGS, EFLAGS_CF
+ ret
+
+Read_High_Memory endp
+
+;***************************************************************************
+; Modifies a memory location according to:
+; *EBX = *EBX & ESI | EDI;
+; CF is toggled
+;***************************************************************************
+Write_High_Memory proc
+
+ mov ebx, [Saved_EBX] ; Address
+ mov edx, [Saved_ESI] ; AND mask
+ mov eax, [Saved_EDI] ; OR mask
+ or edx, edx
+ jz short WriteBack
+
+ mov ecx, fs:[ebx]
+ and ecx, edx
+ or eax, ecx
+WriteBack:
+ mov fs:[ebx], eax
+ ; Toggle the caller's carry flag
+ xor byte ptr ([SMM_Header]).EFLAGS, EFLAGS_CF
+ ret
+
+Write_High_Memory endp
+
+
+
+
+;***************************************************************************
+; Modifies an MSR
+; On entry:
+; ECX = MSR address
+; ESI:EDI = AND mask
+; EBX:EAX = OR mask
+; On exit:
+; CF is toggled
+;***************************************************************************
+MSR_Write proc
+
+ mov ecx, [Saved_ECX] ; Get MSR address
+ call Read_MSR
+
+ and edx, [Saved_ESI] ; Apply AND mask
+ and eax, [Saved_EDI]
+ or edx, [Saved_EBX] ; Apply OR mask
+ or eax, [Saved_EAX]
+
+ test ecx, 0E0000000h
+ jnz Not_CPU_MSR
+ stc ; Indicate this is a WRMSR
+ call MSR_Handler ; Update the MSR
+ jmp short Exit
+
+Not_CPU_MSR:
+ wrmsr
+ ; Toggle the caller's carry flag
+Exit: xor byte ptr ([SMM_Header]).EFLAGS, EFLAGS_CF
+ ret
+
+MSR_Write endp
+
+
+
+
+
+
+;***************************************************************************
+; Reads an MSR
+; On entry:
+; ECX = MSR address
+; On exit:
+; EDX:EAX = MSR data
+; CF is toggled
+;***************************************************************************
+MSR_Read proc
+
+ mov ecx, [Saved_ECX] ; Get MSR address
+
+ call Read_MSR ; Handle special MSRs
+
+ mov [Saved_EAX], eax ; Return results
+ mov [Saved_EDX], edx
+
+ ; Toggle the caller's carry flag
+ xor byte ptr ([SMM_Header]).EFLAGS, EFLAGS_CF
+ ret
+
+MSR_Read endp
+
+
+;***************************************************************************
+; Input:
+; ECX = MSR address
+; Output:
+; EBX = OHCI BAR for multiplexer workaround (0 if not applicable)
+; EDX:EAX = MSR contents
+;***************************************************************************
+Read_MSR proc
+
+ test ecx, 0E0000000h ; Is the MSR in the CPU ?
+ jnz Not_CPU_MSR
+ xor edx, edx ; Yes, then possibly requires special handling
+ clc ; Indicate this is a RDMSR
+ call MSR_Handler ; Read the MSR
+ ret
+
+Not_CPU_MSR:
+ rdmsr
+ ret
+
+Read_MSR endp
+
+
+
+
+
+
+
+;***************************************************************************
+; Reads/writes MSRs that require special handling
+; a) those modified by SysMgr
+; b) those located in the SMM header
+; c) those that are SMM-related are not allowed to be written
+; On entry:
+; CF = 0 for MSR read
+; 1 for MSR write
+;***************************************************************************
+
+MSR_Handler proc
+ ASSUME BX: PTR SpecialMSR
+ lea bx, [Special_MSRs]
+ mov di, [SpecialMSR.RdHandler]
+ jnc MSR_Loop
+ mov di, [SpecialMSR.WrHandler]
+MSR_Loop:
+ cmp cx, [bx].MSR_Addr ; Does MSR match ?
+ je Match
+ add bx, sizeof(SpecialMSR) ; Advance table ptr
+ cmp [bx].MSR_Addr, 0000h ; End of table ?
+ jne MSR_Loop
+NotSpecial:
+ cmp di, [SpecialMSR.WrHandler] ; Read or Write ?
+ je short WriteMSR
+ rdmsr
+ jmp short Exit
+
+WriteMSR:
+ wrmsr
+ jmp short Exit
+
+
+Match: mov si, [bx].DataOffset
+ call word ptr [bx+di] ; Jump to MSR handler
+Exit: ret
+
+ ASSUME BX: NOTHING
+
+SpecialMSR struc
+ MSR_Addr dw ?
+ RdHandler dw ?
+ WrHandler dw ?
+ DataOffset dw ?
+SpecialMSR ends
+
+
+Special_MSRs:
+ ; MSR_Addr Rd_Handler Wr_Handler DataOffset
+ SpecialMSR {MSR_EFLAGS, Get_Header, Set_Header, (SMM_Header[0]).EFLAGS}
+ SpecialMSR {MSR_CR0, Get_Header, Set_CR0, (SMM_Header[0]).r_CR0}
+ SpecialMSR {MSR_DR7, Get_DR7, Set_DR7, (SMM_Header[0]).r_DR7}
+ SpecialMSR {1321h, Get_CS_Sel, Set_CS_Sel, (SMM_Header[0])}
+ SpecialMSR {1331h, Get_CS_Base, Set_CS_Base, (SMM_Header[0])}
+
+ SpecialMSR {1320h, Get_Selector, Set_Selector, Saved_ES}
+ SpecialMSR {1322h, Get_Selector, Set_Selector, Saved_SS}
+ SpecialMSR {1323h, Get_Selector, Set_Selector, Saved_DS}
+ SpecialMSR {1324h, Get_Selector, Set_Selector, Saved_FS}
+ SpecialMSR {1325h, Get_Selector, Set_Selector, Saved_GS}
+
+ SpecialMSR {1330h, Get_Base, Set_Base, Saved_ES}
+ SpecialMSR {1332h, Get_Base, Set_Base, Saved_SS}
+ SpecialMSR {1333h, Get_Base, Set_Base, Saved_DS}
+ SpecialMSR {1334h, Get_Base, Set_Base, Saved_FS}
+ SpecialMSR {1335h, Get_Base, Set_Base, Saved_GS}
+
+ SpecialMSR {1329h, Get_IDT_Sel, Set_IDT_Sel, IDT_Selector}
+ SpecialMSR {1339h, Get_IDT_Base, Set_IDT_Base, IDT_Base}
+
+ ; SMM related MSRs: don't allow these to be written
+ SpecialMSR {MSR_SMM_CTRL, NotSpecial, Exit}
+ SpecialMSR {MSR_SMM_HDR, NotSpecial, Exit}
+ SpecialMSR {MSR_SMM_LOC, NotSpecial, Exit}
+ SpecialMSR {MSR_RCONF_SMM, NotSpecial, Exit}
+
+ dw 0 ; End of table
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ ; Get MSR value from SMM Header
+Get_Header proc
+ mov eax, [si]
+ ret
+Get_Header endp
+
+
+ ; Store MSR value into SMM Header
+Set_Header proc
+ mov [si], eax
+ ret
+Set_Header endp
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ ; Segment selector & attributes
+ ASSUME SI: PTR Descriptor
+Get_Selector proc
+ mov ax, word ptr [si].attr
+ and ah, 0F0h ; Mask Limit 19:16
+ shl eax, 16
+ mov ax, [si].selector
+ ret
+Get_Selector endp
+
+Set_Selector proc
+ mov [si].selector, ax
+ shr eax, 16
+ and ah, 0F0h ; Mask Limit 19:16
+ and word ptr [si].attr, 0F00h ; Preserve Limit 19:16
+ or word ptr [si].attr, ax
+ ret
+Set_Selector endp
+
+
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ ; Segment base & limit
+Get_Base proc
+ mov ah, [si].base_31_24 ; Get base
+ mov al, [si].base_23_16
+ shl eax, 16
+ mov ax, [si].base_15_0
+
+ movzx dx, [si].limit_19_16 ; Get limit
+ mov bh, dl
+ and dl, 0Fh ; Preserve only limit
+ shl edx, 16
+ mov dx, [si].limit_15_0
+ test bh, G_BIT ; Handle page granular bit
+ jz short Exit
+ shl edx, 12
+ or dx, 0FFFh
+Exit: ret
+Get_Base endp
+
+
+Set_Base proc
+ mov [si].base_15_0, ax ; Set base in [Saved_?S]
+ ror eax, 16
+ mov [si].base_31_24, ah
+ mov [si].base_23_16, al
+ rol eax, 16 ; Restore base
+ and [si].limit_19_16, NOT G_BIT ; Clear Granularity bit
+
+ test edx, 0FFF00000h ; 32-bit limit ?
+ jz short Limit16
+
+ or [si].limit_19_16, G_BIT ; Set Granularity bit
+ shr edx, 12
+Limit16:
+ mov [si].limit_15_0, dx
+ shr edx, 16
+ and [si].limit_19_16, 0F0h
+ and dl, 0Fh
+ or [si].limit_19_16, dl
+ ret
+Set_Base endp
+
+ ASSUME SI: PTR SmiHeader
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ ; CS selector & attributes
+Get_CS_Sel proc
+ mov eax, dword ptr [si]._CS.selector
+ ret
+Get_CS_Sel endp
+
+Set_CS_Sel proc
+ mov dword ptr [si]._CS.selector, eax
+ ret
+Set_CS_Sel endp
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ ; CS base & limit
+Get_CS_Base proc
+ mov eax, [si]._CS.base
+ mov edx, [si]._CS.limit
+ ret
+Get_CS_Base endp
+
+Set_CS_Base proc
+ mov [si]._CS.base, eax
+ mov [si]._CS.limit, edx
+ ret
+Set_CS_Base endp
+
+
+
+ ASSUME SI: NOTHING
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+; CR0
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+Set_CR0 proc
+
+CD equ 40000000h
+NW equ 20000000h
+ mov ebx, (CD+NW)
+ mov edi, ebx
+ not edi
+ and ebx, eax ; Extract CD and NW
+ cmp ebx, NW ; Don't allow CD=0 & NW=1
+ je Exit
+ mov [si], eax ; Write new CR0 to the SMM header
+
+ ; 1) Update VSA's CR0
+ ; 2) Update SMM RCONF cache bits
+ ; 3) Update all VSM's CR0[CD] and CR0[NW]
+ ; 4) Flush the cache
+ wbinvd
+ mov esi, CR0
+ and esi, edi
+ or esi, ebx
+ mov CR0, esi
+
+ push bx
+ mov ecx, MSR_RCONF_DEFAULT ; Re-synch MSR_RCONF_SMM with MSR_RCONF_DEFAULT
+ rdmsr
+ mov bl, al
+ mov ecx, MSR_RCONF_SMM ; Update MSR_RCONF_SMM
+ rdmsr
+ mov al, REGION_WP ; Write-protect SMM region in non-SMM
+ mov dl, bl
+ wrmsr
+ wbinvd
+ pop bx
+
+ ; Update all VSM's CR0
+ mov ecx, [VSM_ListHead]
+VSM_Loop:
+ jecxz Exit
+ and fs:(VSM_Header PTR [ecx]).SysStuff.State.r_CR0, edi
+ or fs:(VSM_Header PTR [ecx]).SysStuff.State.r_CR0, ebx
+ mov ecx, fs:(VSM_Header PTR [ecx]).SysStuff.Flink
+ jmp VSM_Loop
+
+Exit: ret
+Set_CR0 endp
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ ; DR7
+Get_DR7 proc
+ mov edx, [si] ; Get DR7 in SMM header
+ mov eax, DR6
+Exit: ret
+Get_DR7 endp
+
+Set_DR7 proc
+ xchg [si], edx ; Set DR7 field in SMM header
+ mov eax, DR6 ; EAX = current DR7
+ wrmsr ; Update DR6
+ ret
+Set_DR7 endp
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ ; IDT selector & attributes
+Get_IDT_Sel proc
+ mov eax, [si]
+ ret
+Get_IDT_Sel endp
+
+Set_IDT_Sel proc
+ mov [si], eax
+ ret
+Set_IDT_Sel endp
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ ; IDT base & limit
+Set_IDT_Base proc
+ mov [si], eax
+ mov [IDT_Limit], edx
+ ret
+Set_IDT_Base endp
+
+Get_IDT_Base proc
+ mov eax, [si]
+ mov edx, [IDT_Limit]
+ ret
+Get_IDT_Base endp
+
+MSR_Handler endp
+
+
+
+
+
+;***************************************************************************
+; Sets the VSM type for filtering events kept in the History buffer.
+;***************************************************************************
+Set_VSM_Type proc
+
+ mov al, byte ptr [Saved_EBX+1]
+ mov [VSM_Filter], al
+ ret
+
+Set_VSM_Type endp
+
+;***************************************************************************
+; SYS_BROADCAST_MSG(MSG_WARM_BOOT, &Param, VSM_ANY);
+;***************************************************************************
+Warm_Boot proc
+
+ xor eax, eax
+ lea bx, [MsgPacket]
+ mov [bx+0], eax
+ mov [bx+4], eax
+ mov [bx+8], eax
+
+ push word ptr MSG_WARM_BOOT ; Message code
+ push word ptr VSM_ANY ; To VSMs
+ push eax ; From_VSM
+ call Broadcast_Message
+ ret
+
+Warm_Boot endp
+
+
+
+
+;***************************************************************************
+; Returns VSA II signature in caller's EAX
+;***************************************************************************
+Signature proc
+
+ mov ax, VSA2_SIGNATURE AND 0FFFFh
+ mov dx, VSA2_SIGNATURE SHR 16
+ ret
+
+Signature endp
+
+
+;***************************************************************************
+; Returns version of VSA II in caller's AX
+;***************************************************************************
+Get_VSA_Version proc
+
+ mov ax, VSA_VERSION
+ ret
+
+Get_VSA_Version endp
+
+
+
+
+;***************************************************************************
+; Returns the version # of the specified VSM type
+;***************************************************************************
+Get_VSM_Version proc
+
+ ; Get caller's BL
+ mov dl, byte ptr [Saved_EBX]
+Find_VSM::
+ mov ecx, [SysMgr_VSM]
+ mov ax, 0FFFFh ; Not found
+VSM_Loop:
+ jecxz Exit
+ cmp dl, fs:(VSM_Header PTR [ecx]).VSM_Type
+ je Found
+ mov ecx, fs:(VSM_Header PTR [ecx]).SysStuff.Flink
+ jmp VSM_Loop
+
+Found: mov ax, fs:(VSM_Header PTR [ecx]).VSM_Version
+Exit: mov word ptr [Saved_EAX], ax
+ ret
+
+
+Get_VSM_Version endp
+
+
+
+
+
+
+
+;***************************************************************************
+; Helper routine
+; On Entry:
+; Caller's BH - VSM type to process
+; On Exit:
+; ECX - ptr to the next VSM to be processed
+;***************************************************************************
+Common_Entry proc
+
+ mov ecx, [Next_VSM]
+ mov dl, byte ptr [Saved_EBX+1] ; Caller's BH
+ cmp dl, 0FFh ; Next VSM ?
+ je Exit
+
+ call Find_VSM
+ cmp ax, 0FFFFh
+ stc
+ jz Return
+
+Exit: clc
+Return:ret
+
+Common_Entry endp
+
+;***************************************************************************
+; Updates Next_VSM with the Flink field of the current VSM
+;***************************************************************************
+Common_Exit proc
+
+ ; Get ptr to next VSM
+ mov ecx, fs:(VSM_Header PTR [ecx]).SysStuff.Flink
+ mov [Next_VSM], ecx
+ ret
+
+Common_Exit endp
+
+
+
+
+
+;***************************************************************************
+; Return's to caller's registers:
+; EAX - VSM_Version::VSM_Type (0xFFFF if no more)
+; EBX - Base of VSM
+; ECX - IP::SP
+; DX - VSM_Length
+;***************************************************************************
+Get_VSM_Basics proc
+
+ call Common_Entry
+ jc short Exit
+
+ ; Put info into caller's registers
+ mov [Saved_EBX], ecx
+
+ mov ax, fs:(VSM_Header PTR [ecx]).VSM_Version
+ shl eax, 16
+ movzx ax, fs:(VSM_Header PTR [ecx]).VSM_Type
+ mov [Saved_EAX], eax
+
+ mov ax, word ptr fs:(VSM_Header PTR [ecx]).SysStuff.State.Next_EIP
+ shl eax, 16
+ mov ax, word ptr fs:(VSM_Header PTR [ecx]).SysStuff.SavedESP
+ mov [Saved_ECX], eax
+
+ mov ax, word ptr fs:(VSM_Header PTR [ecx]).DS_Limit
+ mov word ptr [Saved_EDX], ax
+
+ call Common_Exit
+
+Exit: ret
+
+Get_VSM_Basics endp
+
+
+;***************************************************************************
+; Entry:
+; CL - History entry # (0-based)
+; CH - 1 to clear history buffer
+; Exit:
+; AL - VSM type
+; AH - Event
+; EBX - Count
+; ECX - Param1
+; EDX - Param2
+; EDI:ESI - TimeStamp
+;***************************************************************************
+Get_VSM_History proc
+
+if HISTORY
+
+ ; Get starting index
+ mov ax, [HistoryStart]
+ mov cx, [HistoryEnd]
+ cmp ax, cx
+ je NoHistory
+
+ movzx dx, byte ptr [Saved_ECX]
+ add ax, dx
+ mov dl, HISTORY ; Index = (HistoryStart+CX) % HISTORY
+ div dl
+ movzx ax, ah
+
+ cmp ax, cx ; if (Index < HistoryEnd)
+ jb short GetItem ; goto GetItem
+ mov dx, ax
+ cmp dx, cx
+ jne short GetItem
+
+ cmp byte ptr [Saved_ECX+1], 1
+ jne NoHistory
+ xor ax, ax
+ mov [HistoryStart], ax
+ mov [HistoryEnd], ax
+ mov [HistoryWrap], ax
+ jmp NoHistory
+
+GetItem:
+
+
+ ; Get ptr to History[] entry
+ lea bx, History
+ ASSUME BX: PTR EVENT_HISTORY
+ mov dl, sizeof(EVENT_HISTORY)
+ mul dl
+ add bx, ax
+
+ ; Get info about the event
+ mov ah, byte ptr [bx].Event
+ mov ecx, [bx].Vsm
+ mov al, fs:(VSM_Header PTR [ecx]).VSM_Type
+ mov word ptr [Saved_EAX], ax
+
+ mov eax, [bx].Count
+ mov [Saved_EBX], eax
+
+ mov eax, [bx].Param1
+ mov [Saved_ECX], eax
+
+ mov eax, [bx].Param2
+ mov [Saved_EDX], eax
+
+ mov eax, [bx].TimeStamp
+ mov [Saved_ESI], eax
+ mov eax, [bx].TimeStamp+4
+ mov [Saved_EDI], eax
+ ret
+
+endif
+
+
+NoHistory:
+ xor eax, eax
+ mov [Saved_EAX], eax
+ ret
+
+
+Get_VSM_History endp
+
+
+;***************************************************************************
+; Returns:
+; AX = Chipset ID
+; BX = CPU ID
+; CX = CPU MHz
+; EDX = PCI address of Southbridge
+;***************************************************************************
+Get_VSM_Hardware proc
+
+ ; Get ptr to Hardware structure
+ lea bx, [HardwareInfo]
+ ASSUME BX: PTR Hardware
+
+ mov ax, [bx].Chipset_ID
+ mov word ptr [Saved_EAX], ax
+
+ mov ax, [bx].CPU_ID
+ mov word ptr [Saved_EBX], ax
+
+ mov ax, [bx].CPU_MHz
+ mov word ptr [Saved_ECX], ax
+
+ mov eax, [bx].Chipset_Base
+ mov [Saved_EDX], eax
+
+ ret
+
+ ASSUME BX: NOTHING
+
+Get_VSM_Hardware endp
+
+
+;***************************************************************************
+; Returns:
+; AX = Chipset ID
+;***************************************************************************
+Get_HW_Info proc
+
+ mov ax, 0FFFFh ; Value for illegal index
+ movzx bx, [HW_Index]
+ cmp bl, MAX_HW_INFO
+ ja short Exit
+
+ add bx, bx
+ mov bx, [HW_Offsets+bx]
+ mov ax, [bx]
+Exit:
+ mov word ptr [Saved_EAX], ax
+ ret
+
+Get_HW_Info endp
+
+HW_Index db 0
+
+HW_Offsets:
+ dw OFFSET HardwareInfo.Chipset_ID
+ dw OFFSET HardwareInfo.Chipset_Rev
+ dw OFFSET HardwareInfo.Chipset_Base
+ dw OFFSET HardwareInfo.CPU_ID
+ dw OFFSET HardwareInfo.CPU_Revision
+ dw OFFSET HardwareInfo.CPU_MHz
+ dw OFFSET HardwareInfo.PCI_MHz
+MAX_HW_INFO equ ($-HW_Offsets)/2-1
+
+
+
+;***************************************************************************
+; Entry:
+; AL - Hardware item to be returned by Select_HW_Info
+; 0 = Southbridge ID
+; 1 = Southbridge Revision
+; 2 = Southbridge PCI address
+; 3 = CPU ID
+; 4 = CPU Revision
+; 5 = CPU MHz
+; 6 = PCI MHz
+;***************************************************************************
+Select_HW_Info proc
+
+ mov al, byte ptr [Saved_EAX]
+ mov [HW_Index], al
+ ret
+
+Select_HW_Info endp
+
+;***************************************************************************
+; Entry:
+; ESI - VSM of interest
+; Exit:
+; EAX - Priority::Event
+; ECX - Param1
+; EDX - Param2
+;***************************************************************************
+Get_VSM_Events proc
+
+ mov esi, [Saved_ESI] ; Get the VSM of interest
+ mov cx, word ptr [CurrentIndex]
+EventIndex:
+ mov al, sizeof(EVENT_ENTRY)
+ mul cl
+ lea bx, [Events]
+ add bx, ax
+ ASSUME BX: PTR EVENT_ENTRY
+ cmp esi, [bx].Vsm ; Is it the VSM of interest ?
+ je FoundEvent
+
+ mov cl, [bx].Link ; Get link to next event
+ or cl, cl
+ jnz EventIndex
+
+ ; Increment Event
+ inc ch ; Increment event index
+ mov cl, ch
+ cmp ch, MAX_EVENT ; Last event ?
+ jbe EventIndex
+ xor cx, cx ; Yes, reset variables
+
+ ; Set the caller's carry flag
+ or byte ptr ([SMM_Header]).EFLAGS, EFLAGS_CF
+ jmp short Exit
+
+
+FoundEvent:
+ mov eax, [bx].Param1 ; Return Param1 in ECX
+ mov [Saved_ECX], eax
+ mov eax, [bx].Param2 ; Return Param2 in EDX
+ mov [Saved_EDX], eax
+
+ mov ax, [bx].Priority ; Return Priority::Event in EAX
+ shl eax, 16
+ movzx ax, ch
+ mov [Saved_EAX], eax
+
+ mov cl, [bx].Link ; Get link to next event
+
+Exit: mov word ptr [CurrentIndex], cx
+ ret
+
+ ASSUME BX:NOTHING
+
+
+CurrentIndex db 0
+CurrentEvent db 0
+
+Get_VSM_Events endp
+
+
+
+;***************************************************************************
+; Entry:
+; Caller's BH - VSM to report (0FFh for next)
+; Caller's CL - clear statistics flag (1=clear)
+; Exit:
+; EDX:EAX - # SMIs
+; EBX:ECX - # clocks
+; BP - VSM Type
+; If SysMgr:
+; EDI:ESI - start time
+; 16 MSBs BP - clock adjustment
+; Carry Flag set if no more VSMs
+;
+;***************************************************************************
+Get_VSM_Statistics proc
+
+ call Common_Entry
+ jc Exit
+ or ecx, ecx
+ jz NoMoreVSMs
+
+
+ mov dl, byte ptr [Saved_ECX] ; Get /S flag
+ cld
+
+
+ ; If SysMgr, freeze statistics & return extra information
+ cmp fs:(VSM_Header PTR [ecx]).VSM_Type, VSM_SYS_MGR
+ jne ReturnInfo
+
+ mov bx, OFFSET VSM_Header.SysStuff
+ ASSUME BX: PTR System
+
+ ; EDI:ESI - start time
+ ; 16 MSBs EBP - adjustment (clocks/SMI)
+ mov ax, word ptr [bx].Adjustment
+ mov word ptr [Saved_EBP+2], ax
+
+ mov eax, [bx+0].StartClocks
+ mov [Saved_ESI], eax
+ mov eax, [bx+4].StartClocks
+ mov [Saved_EDI], eax
+
+ ; Clear statistics ?
+ cmp dl, 1
+ jne short FreezeStats
+
+ ; Yes, record a new start time
+ push dx
+ rdtsc
+ mov [bx+0].StartClocks, eax
+ mov [bx+4].StartClocks, edx
+ pop dx
+
+ ASSUME BX:NOTHING
+
+
+
+ ; Freeze statistics of all VSMs
+FreezeStats:
+ push ecx
+ mov ebx, ecx
+ xor eax, eax
+VSM_Loop:
+ lea esi, (VSM_Header PTR [ebx]).SysStuff.Clocks
+ lea edi, (VSM_Header PTR [ebx]).SysStuff.FrozenClocks
+ mov ecx, 4
+ rep movsd [edi], es:[esi]
+
+ ; Clear statistics ?
+ cmp dl, 1
+ jne short NextVSM
+ lea edi, (VSM_Header PTR [ebx]).SysStuff.Clocks
+ mov cl, 4
+ rep stosd [edi]
+
+NextVSM:
+ mov ebx, es:(VSM_Header PTR [ebx]).SysStuff.Flink
+ or ebx, ebx
+ jnz VSM_Loop
+
+ pop ecx
+
+
+ ; Put info into caller's registers
+ReturnInfo:
+ movzx ax, es:(VSM_Header PTR [ecx]).VSM_Type
+ mov word ptr [Saved_EBP], ax
+
+ lea esi, (VSM_Header PTR [ecx]).SysStuff.FrozenClocks
+ lodsd es:[esi]
+ mov [Saved_EAX], eax
+ lodsd es:[esi]
+ mov [Saved_EDX], eax
+ lodsd es:[esi]
+ mov [Saved_ECX], eax
+ lodsd es:[esi]
+ mov [Saved_EBX], eax
+
+ call Common_Exit
+ ret
+
+NoMoreVSMs:
+ ; Set caller's CF
+ or byte ptr ([SMM_Header]).EFLAGS, EFLAGS_CF
+Exit: ret
+
+Get_VSM_Statistics endp
+
+
+;***************************************************************************
+; Invalidates the cache(s)
+;***************************************************************************
+Do_WBINVD proc
+
+ wbinvd
+ ret
+
+Do_WBINVD endp
+
+
+;***************************************************************************
+; Updates the CR0 field of each VSM with the current non-VSA CR0
+;***************************************************************************
+Update_VSMs_CR0 proc
+
+ mov si, OFFSET [SMM_Header[0].r_CR0]
+ mov eax, [si] ; Get current CR0
+ call Set_CR0
+ ret
+
+Update_VSMs_CR0 endp
+
+ END
diff --git a/cpu/amd/geode_lx/gplvsa_ii/sysmgr/vsa_init.c b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/vsa_init.c
new file mode 100755
index 0000000..9bcbb23
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/sysmgr/vsa_init.c
@@ -0,0 +1,111 @@
+/*
+* Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+*
+* This library is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of the
+* License, or (at your option) any later version.
+*
+* This code is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+
+* You should have received a copy of the GNU Lesser General
+* Public License along with this library; if not, write to the
+* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+* Boston, MA 02111-1307 USA
+*/
+
+//* Function: *
+//* Implements the initialization code for System Manager
+
+#include "VSA2.H"
+#include "SYSMGR.H"
+#include "PROTOS.H"
+#include "VR.H"
+#include "CHIPSET.H"
+
+
+
+// External function prototypes
+extern void Initialize_Events(void);
+extern void Install_SMI_Routines(void);
+extern void Initialize_History(void);
+extern void InitChipset(void);
+extern void Init_MBus(void);
+extern void VirtualPCI_EarlyInit(void);
+extern void Init_Virtual_Regs(void);
+extern void Record_VSM_Locations(void);
+extern void Broadcast_SysMgr_Msg (MSG, UCHAR);
+extern Hardware HardwareInfo;
+
+//***********************************************************************
+// Gets called from early VSA init, but after VSMs have initialized.
+//***********************************************************************
+void Post_VSM_InitInit(void)
+{
+
+}
+
+
+
+//*****************************************************************************
+//
+// Initialize the System Manager
+//
+//*****************************************************************************
+void Init_SysMgr(void)
+{
+
+ // Initialize the array of registered events
+ Initialize_Events();
+
+ // Initialize the history buffers
+ Initialize_History();
+
+
+ // Install SMI routines appropriate to chipset
+ Install_SMI_Routines();
+
+
+ // Initialize MBus related structures & MSRs
+ Init_MBus();
+
+
+ // Initialize virtual PCI headers and MBUS
+ VirtualPCI_EarlyInit();
+
+ // Initialize chipset-specific registers
+ InitChipset();
+
+
+ // Initialize virtual register trapping
+ Init_Virtual_Regs();
+
+
+ // Register System Manager as handler for A20
+ Register_Event(EVENT_A20, MAX_PRIORITY, SysMgr_VSM, 0, 0);
+
+
+
+ // Register System Manager as handler of VRC_MISCELLANEOUS
+ Register_Event(EVENT_VIRTUAL_REGISTER, MAX_PRIORITY, SysMgr_VSM, VRC_MISCELLANEOUS, GET_DESCR_INFO);
+
+
+ // Record locations of VSMs requiring special handling
+ Record_VSM_Locations();
+
+
+ // Schedule control after VSMs have performed initialization
+ Schedule_VSM((USHORT)Post_VSM_InitInit);
+
+
+
+ //
+ // Send a phase 0 initialization message to each VSM
+ //
+ Broadcast_SysMgr_Msg(MSG_INITIALIZE, EARLY_INIT);
+
+
+}
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsabuild.txt b/cpu/amd/geode_lx/gplvsa_ii/vsabuild.txt
new file mode 100755
index 0000000..a6df1ff
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsabuild.txt
@@ -0,0 +1,52 @@
+TOOLS:
+• MASM 6.11c or greater: This is available through an MSDN subscription.
+- Upgrade to 6.14: ftp://ftp.microsoft.com/softlib/mslfiles/ml614.exe
+• NMAKE.EXE Version 1.40 or greater (1.20 is included with MASM 6.11 – the
+ upgrade is needed to build)
+- Update to 1.50: ftp://ftp.microsoft.com/softlib/mslfiles/nmake15.exe
+- Unzip into the masm611\bin directory
+• MSVC Version 1.52: This is available through an MSDN subscription.
+• exe2bin.exe: This is supplied with Microsoft operating systems from DOS
+ to Windows XP.
+
+These are the minimum tools & files you need to build VSA:
+333,312 c13216.exe
+493,056 c23216.exe
+244,224 c33216.exe
+ 1,756 cl.err
+ 91,648 cl.exe
+ 4,279 cl.msg
+ 21,879 h2inc.err
+249,344 h2inc.exe
+ 59,089 lib.exe
+364,544 link.exe
+ 9,687 ml.err
+372,736 ml.exe
+ 5,056 nmake.err
+ 65,536 nmake.exe
+ 5,647 oldnames.lib
+391,207 slibc7.lib
+404,519 slibce.lib
+
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+SETTING THE BUILD ENVIRONMENT:
+The path should include the bin directories from MASM and MSVC, as well as the
+normal path for DOS or Windows.
+Following is a sample batch file to set up the environment:
+
+@echo off
+if "%varset%" == "xpath" goto done
+set path=c:\tools;c:\tools\masm\bin;c:\tools\msvc\bin;%path%
+set lib=c:\tools\msvc\lib
+set varset=xpath
+:done
+
+-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+BUILDING THE ROM:
+Change directories to vsa_ii\build and type NMAKE. This will create the
+VSA .bin file.
+
+Build Targets in the Makefiles:
+• NMAKE all - builds the VSA binary
+• NMAKE clean - cleans up last compile, but leaves the VSM files.
+• NMAKE cleanall - cleans up last compile completely
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/critical.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/critical.asm
new file mode 100755
index 0000000..d544e47
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/critical.asm
@@ -0,0 +1,67 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file implements the critical section macros.
+
+
+include gx2.inc
+
+.model tiny,c
+.586p
+.CODE
+
+
+
+
+
+;***********************************************************************
+; Disables SMI nesting
+;***********************************************************************
+EnterCriticalSection proc
+
+ mov ecx, MSR_SMM_CTRL
+ rdmsr
+ and eax, NOT NEST_SMI_EN
+ wrmsr
+ ret
+
+EnterCriticalSection endp
+
+
+
+;***********************************************************************
+; Enables SMI nesting
+;***********************************************************************
+ExitCriticalSection proc
+
+ mov ecx, MSR_SMM_CTRL
+ rdmsr
+ or eax, NEST_SMI_EN
+ wrmsr
+ ret
+
+ExitCriticalSection endp
+
+
+
+
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/descr.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/descr.asm
new file mode 100755
index 0000000..5160f45
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/descr.asm
@@ -0,0 +1,182 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file library functions for accessing descriptors
+
+include SYSMGR.INC
+include VSA2.INC
+include SMIMAC.MAC
+
+.model tiny,c
+.586p
+.CODE
+
+
+
+
+externdef Function: byte
+externdef ValidateMacro:proc
+externdef ParamError:proc
+
+
+
+;***********************************************************************
+; void sys_get_descriptor(USHORT, void *)
+;***********************************************************************
+sys_get_descriptor proc pascal uses si\
+ seg_reg: WORD, \
+ buffer: PTR
+
+
+ mov [Function], GET_DESCR ; In case of error
+ movzx eax, [seg_reg] ; Get which register
+ call ValidateMacro ; Get ptr to registers
+ jc Exit
+
+ mov si, [buffer] ; Destination ptr
+ cmp ax, R_CS
+ je Get_CS
+
+
+ cmp ax, R_GS ; Validate offset
+ ja Error
+
+ ; Get descriptor from SysMgr's state save area
+ xor ah, ah ; Extract offset
+ lea ebx, [eax-8] ; Offset points to .selector
+ mov ax, fs:[eax] ; Copy 10 bytes of descriptor info
+ mov [si+8], ax
+ mov eax, fs:[ebx]
+ mov [si], eax
+ mov eax, fs:[ebx+4]
+ mov [si+4], eax
+ jmp Exit
+
+
+ ; Get CS from SMM header.
+ ; Convert from linear format to descriptor format
+Get_CS:
+ ASSUME SI: PTR Descriptor
+ ; CS base
+ mov eax, fs:(SmiHeader PTR [ecx])._CS.base
+ mov [si].base_15_0, ax
+ shr eax, 16
+ mov [si].base_23_16, al
+ mov [si].base_31_24, ah
+
+ ; CS limit
+ mov eax, fs:(SmiHeader PTR [ecx])._CS.limit
+ test fs:(SmiHeader PTR [ecx])._CS.attr, 8000h
+ jz short SetLimit
+ shr eax, 12
+ or eax, 800000h ; Set G bit
+SetLimit:
+ mov [si].limit_15_0, ax
+ shr eax, 16
+ mov [si].limit_19_16, al
+
+ ; CS selector
+ mov ax, word ptr fs:(SmiHeader PTR [ecx])._CS.selector
+ mov [si].selector, ax
+
+ ; CS attributes
+ mov ax, fs:(SmiHeader PTR [ecx])._CS.attr
+ mov [si].attr, al
+ jmp short Exit
+
+Error: call ParamError
+Exit: ret
+
+
+sys_get_descriptor endp
+
+
+
+
+;***********************************************************************
+; void sys_set_descriptor(USHORT, void *)
+;***********************************************************************
+sys_set_descriptor proc pascal \
+ seg_reg: word, \
+ buffer: PTR
+
+ movzx eax, [seg_reg] ; Get which register
+ mov [Function], SET_DESCR ; In case of error
+ call ValidateMacro ; Get ptr to registers
+ jc Exit
+
+
+ mov si, [buffer] ; Destination ptr
+ ASSUME SI: PTR Descriptor
+
+ cmp al, R_CS AND 0FFh
+ je Set_CS
+
+ xor ah, ah ; Extract offset
+ lea ecx, [eax-8] ; Offset points to .selector
+
+
+ ; Set a non-SMM descriptor
+ cld
+ lodsd ; Copy 10 bytes of descriptor info
+ mov fs:[ecx+0], eax
+ lodsd
+ mov fs:[ecx+4], eax
+ lodsw
+ mov fs:[ecx+8], ax
+ jmp short Exit
+
+
+
+ ; Convert descriptor format to linear format
+Set_CS:
+ ; Set limit
+ mov al, [si].limit_19_16
+ mov cl, al
+ and ax, 000Fh
+ shl eax, 16
+ mov ax, [si].limit_15_0
+ mov fs:(SmiHeader PTR [ecx])._CS.limit, eax
+
+ ; Set base
+ mov ah, [si].base_31_24
+ mov al, [si].base_23_16
+ shl eax, 16
+ mov ax, [si].base_15_0
+ mov fs:(SmiHeader PTR [ecx])._CS.base, eax
+
+ ; Set attribute
+ mov al, [si].attr
+ mov ah, cl ; Contains G bit
+ mov fs:(SmiHeader PTR [ecx])._CS.attr, ax
+ jmp short Exit
+
+
+Error: call ParamError
+Exit: ret
+
+sys_set_descriptor endp
+
+
+
+
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/hex.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/hex.asm
new file mode 100755
index 0000000..7a777af
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/hex.asm
@@ -0,0 +1,95 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file contains hex debug routines
+
+
+.model tiny,c
+.586p
+.CODE
+
+
+
+
+
+Hex_32 proc pascal Num:dword
+
+ pushad
+ mov ebx, [Num]
+ mov cx, 8
+@@: rol ebx, 4
+ call Hex_4
+ loop @b
+ call Space
+ popad
+ ret
+
+Hex_32 endp
+
+
+
+Hex_16 proc pascal Num:word
+
+ pusha
+ mov cx, 4
+ mov bx, [Num]
+@@: rol bx, 4
+ call Hex_4
+ loop @b
+ call Space
+ popa
+ ret
+
+Hex_16 endp
+
+
+Hex_8 proc pascal Num:byte
+
+ pusha
+ mov cx, 2
+ mov bl, [Num]
+@@: rol bl, 4
+ call Hex_4
+ loop @b
+ call Space
+ popa
+ ret
+
+Hex_8 endp
+
+
+Hex_4: mov al, bl
+ and al, 0Fh
+ add al, '0' ; Convert to ASCII
+ cmp al, '9'
+ jbe Char
+ add al, 7 ; 'A'-'F'
+Char: mov dx, 84h
+ out dx, al
+ in al, 80h
+ ret
+
+Space: mov al, ' '
+ jmp Char
+
+
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/irq.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/irq.asm
new file mode 100755
index 0000000..f707da5
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/irq.asm
@@ -0,0 +1,82 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* Implements the SYS_GENERATE_IRQ & SYS_MAP_IRQ macros.
+
+
+include vsa2.inc
+include sysmgr.inc
+
+.model tiny,c
+.586p
+.CODE
+
+externdef sys_system_call:proc
+
+;***********************************************************************
+;***********************************************************************
+sys_map_irq proc pascal \
+ Y_Source: byte, \
+ IRQ: byte
+
+ mov bl, [Y_Source]
+ mov cl, [IRQ]
+ mov ax, SYS_CODE_IRQ_MAPPER
+ call sys_system_call
+ ret
+
+sys_map_irq endp
+
+
+;***********************************************************************
+; void sys_generate_IRQ(USHORT Irq);
+;
+; Generates an IRQ upon exit from SMM
+; NOTE: If 8 MSBs of Irq are non-zero, then IRQ is set to external
+;***********************************************************************
+sys_generate_IRQ proc pascal \
+ Irq: word
+
+ xor bx, bx ; Get ptr to SysMgr's IRQ_Mask
+ mov ebx, (VSM_Header PTR [bx]).SysStuff.SysMgr_Ptr
+
+ mov cx, [Irq] ; Get IRQ number
+ mov eax, 00010001h ; Generate bit mask
+ shl eax, cl
+ or ch, ch ; Disable internal IRQ external ?
+ jz short AssertIRQ
+
+ not ax ; Yes
+ mov ebx, fs:(InfoStuff PTR [ebx]).IRQ_Base
+ and fs:[ebx], ax ; Mark IRQ as external
+ jmp short Exit
+
+
+AssertIRQ:
+ lea ebx, (InfoStuff PTR [ebx]).IRQ_Mask
+ or fs:[ebx], eax ; Record IRQ to be generated
+
+Exit: ret
+
+sys_generate_IRQ endp
+
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/makefile b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/makefile
new file mode 100755
index 0000000..a9c40da
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/makefile
@@ -0,0 +1,134 @@
+#
+# Copyright (c) 2006 Advanced Micro Devices,Inc. ("AMD").
+#
+# This library is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# This code is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General
+# Public License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+# Boston, MA 02111-1307 USA
+#
+######################################################################
+#
+# Init variables
+#
+######################################################################
+!ifndef VSA2ROOT
+VSA2ROOT = ..
+!endif
+
+BUILD_DIR = $(VSA2ROOT)\build
+OBJECT = obj
+!include $(BUILD_DIR)\setvars.mak
+.SUFFIXES: .asm .h .inc .obj .mac
+
+INCLUDE = $(OBJECT);$(INCLUDE)
+
+VSMNAME = vsm_lib
+
+
+######################################################################
+#
+# Build Macros
+#
+######################################################################
+
+VSMUTILS_ASM_OBJS = \
+ $(OBJECT)\vsa2util.obj \
+ $(OBJECT)\pci.obj \
+ $(OBJECT)\descr.obj \
+ $(OBJECT)\utils.obj \
+ $(OBJECT)\misc.obj \
+ $(OBJECT)\message.obj \
+ $(OBJECT)\virtual.obj \
+ $(OBJECT)\irq.obj \
+ $(OBJECT)\regs.obj \
+ $(OBJECT)\sysinfo.obj \
+ $(OBJECT)\sw_int.obj \
+ $(OBJECT)\resource.obj \
+ $(OBJECT)\critical.obj \
+ $(OBJECT)\yield.obj \
+ $(OBJECT)\hex.obj \
+ $(OBJECT)\present.obj \
+ $(OBJECT)\msrs.obj \
+
+#######################################################################
+#
+# Targets
+#
+#######################################################################
+
+all: $(OBJECT) setenv tools.lib
+!if !exist ($(BUILD_DIR)\obj)
+ md $(BUILD_DIR)\obj
+!endif
+ $(COPY) $(OBJECT)\tools.lib $(BUILD_DIR)\obj
+
+tools.lib: $(VSMUTILS_ASM_OBJS)
+
+#This and only this clean target must exist as it is called by cleanall
+#cleanall and cleanlocal are defined in rules.mak
+
+clean: cleanlocal
+ -@IF EXIST $(BUILD_DIR)\obj\tools.lib $(DEL) $(BUILD_DIR)\obj\tools.lib
+ -@IF NOT EXIST $(BUILD_DIR)\obj\*.* rd $(BUILD_DIR)\obj
+
+$(OBJECT):
+ -@md $(OBJECT)
+
+#######################################################################
+#
+# Dependencies
+#
+#######################################################################
+
+$(VSMUTILS_ASM_OBJS): $(MAKEDIR)\makefile\
+ $(OBJECT)\sysmgr.inc \
+ $(OBJECT)\smimac.mac \
+ $(OBJECT)\vsa2.inc\
+ $(OBJECT)\isa.inc \
+ $(OBJECT)\gx2.inc \
+ $(OBJECT)\pci.inc \
+
+######################################################################
+#
+# Common Targets
+#
+######################################################################
+# include common targets and inference rules
+!include $(BUILD_DIR)\rules.mak
+
+######################################################################
+#
+# Inference Rules
+#
+######################################################################
+# Override common inference rules here
+
+{$(INC_DIR)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zni /C $<
+
+{$(INC_DIR)\$(CPU)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zni /C $<
+
+{$(SYSMGR_SRC)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zns /C $<
+
+{$(SYSMGR_SRC)\$(CPU)}.h{$(OBJECT)}.inc:
+ $(H2) /Fa$(OBJECT)\$(@F) /nologo /Zns /C $<
+
+{$(MAKEDIR)}.asm{$(OBJECT)}.obj:
+ $(AS) /nologo $(AS_OPTS) /Fo$@ $<
+ $(LB) $(OBJECT)\tools.lib -+$@;
+
+{$(MAKEDIR)\$(CPU)}.asm{$(OBJECT)}.obj:
+ $(AS) /nologo $(AS_OPTS) /Fo$@ $<
+ $(LB) $(OBJECT)\tools.lib -+$@;
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/message.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/message.asm
new file mode 100755
index 0000000..422455c
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/message.asm
@@ -0,0 +1,61 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file implements the SYS_BROADCAST_MSG system call
+
+include sysmgr.inc
+include vsa2.inc
+
+.model tiny,c
+.586p
+.CODE
+
+
+
+
+externdef sys_system_call:proc
+externdef Async_VSM: dword
+externdef EventIndex: byte
+
+;***********************************************************************
+; void sys_broadcast_msg(MSG Code, ULONG * Params, UCHAR VSM_Type)
+;***********************************************************************
+sys_broadcast_msg proc pascal uses esi edi \
+ MsgCode: MSG, \
+ Params: PTR, \
+ VSM_Type: WORD
+
+
+ mov bx, [MsgCode] ; Get MSG to broadcast
+ shl ebx, 16 ; Put into 16 MSBs
+ mov di, [Params] ; Get parameters
+ mov ecx, [di+0] ; Param1
+ mov esi, [di+4] ; Param2
+ mov edi, [di+8] ; Param3
+ mov bx, [VSM_Type] ; Get VSM(s) to send message to
+
+ mov ax, SYS_CODE_BROADCAST
+ call sys_system_call
+ ret
+
+sys_broadcast_msg endp
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/misc.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/misc.asm
new file mode 100755
index 0000000..db78032
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/misc.asm
@@ -0,0 +1,62 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;*******************************************************************************
+;* This file contains miscellaneous VSM library functions.
+;*******************************************************************************
+
+
+include sysmgr.inc
+.model tiny,c
+.586p
+.CODE
+
+
+
+externdef sys_system_call:proc
+
+
+
+sys_unload_vsm proc
+
+ mov ax, SYS_CODE_UNLOAD
+ call sys_system_call
+ ret
+
+; Does not return. VSM is removed.
+
+sys_unload_vsm endp
+
+
+
+sys_duplicate_vsm proc pascal \
+ MemoryModel:word
+
+ mov bx, [MemoryModel]
+ mov ax, SYS_CODE_DUPLICATE
+ call sys_system_call
+ ret
+
+sys_duplicate_vsm endp
+
+
+
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/msrs.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/msrs.asm
new file mode 100755
index 0000000..6e2478e
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/msrs.asm
@@ -0,0 +1,98 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function:
+;* This file implements routines to access MSRs.
+
+
+
+.model tiny,c
+.586p
+.CODE
+
+
+
+
+
+;************************************************************************
+; Returns the low dword of the specified MSR
+;************************************************************************
+Read_MSR_LO proc pascal \
+ MSR_Addr: dword
+
+ mov ecx, [MSR_Addr]
+ rdmsr
+ mov edx, eax
+ shr edx, 16
+ ret
+
+Read_MSR_LO endp
+
+;************************************************************************
+; Writes the low dword of the specified MSR
+;************************************************************************
+Write_MSR_LO proc pascal \
+ MSR_Addr: dword, \
+ MSR_Data: dword
+
+ mov ecx, [MSR_Addr]
+ rdmsr
+ mov eax, [MSR_Data]
+ wrmsr
+ ret
+
+Write_MSR_LO endp
+
+
+
+;***********************************************************************
+; Returns an MSR value in a buffer.
+; Usage: Read_MSR(ULONG Msr, ULONG * Buffer);
+;***********************************************************************
+Read_MSR proc pascal \
+ MSR_Addr:DWORD, \
+ pMSR_Data:PTR DWORD
+
+ mov ecx, [MSR_Addr]
+ rdmsr
+ mov bx, [pMSR_Data]
+ mov dword ptr [bx+0], eax
+ mov dword ptr [bx+4], edx
+ ret
+
+Read_MSR endp
+
+
+;***********************************************************************
+; Writes an MSR.
+; Usage: Write_MSR(ULONG Msr, ULONG * Buffer);
+;***********************************************************************
+Write_MSR proc pascal \
+ MSR_Addr:DWORD, \
+ pMSR_Data:PTR DWORD
+
+ mov ecx, [MSR_Addr]
+ mov bx, [pMSR_Data]
+ mov eax, dword ptr [bx+0]
+ mov edx, dword ptr [bx+4]
+ wrmsr
+ ret
+
+Write_MSR endp
+
+ END
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/pci.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/pci.asm
new file mode 100755
index 0000000..65b1885
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/pci.asm
@@ -0,0 +1,296 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;*******************************************************************************
+;* This file contains PCI related library functions.
+;*******************************************************************************
+
+
+include sysmgr.inc
+include pci.inc
+include vsa2.inc
+include gx2.inc
+
+.model tiny,c
+.586p
+.CODE
+
+
+
+
+externdef sys_system_call:proc
+
+
+
+
+
+;**********************************************************************
+; Writes the PCI Config Address
+; Input:
+; EAX = config address
+; Output:
+; DX = points to 0xCFC-0xCFF
+;**********************************************************************
+PCI_Common proc
+
+ mov dx, PCI_CONFIG_ADDRESS
+ ror eax, 16 ; Set 16 MSBs to 8000h
+ mov ax, 8000h
+ ror eax, 16
+ out dx, eax
+ add dl, 4 ; PCI_CONFIG_DATA + 2 LSBs
+ and al, 3
+ add dl, al
+ ret
+
+PCI_Common endp
+
+
+
+;**********************************************************************
+; Reads a byte PCI register
+;**********************************************************************
+read_PCI_byte proc pascal PCI_Config_Addr:DWORD
+
+ mov eax, [PCI_Config_Addr]
+ call PCI_Common
+ in al, dx
+ ret
+
+read_PCI_byte endp
+
+
+;**********************************************************************
+; Reads a word PCI register
+;**********************************************************************
+read_PCI_word proc pascal \
+ PCI_Config_Addr:DWORD
+
+ mov eax, [PCI_Config_Addr]
+ call PCI_Common
+ in ax, dx
+ ret
+
+read_PCI_word endp
+
+
+;**********************************************************************
+; Reads a dword PCI register
+;**********************************************************************
+read_PCI_dword proc pascal \
+ PCI_Config_Addr:DWORD
+
+ mov eax, [PCI_Config_Addr]
+ call PCI_Common
+ in eax, dx
+ mov edx, eax
+ shr edx, 16
+ ret
+
+read_PCI_dword endp
+
+
+;**********************************************************************
+; Writes a byte PCI register
+;**********************************************************************
+write_PCI_byte proc pascal \
+ PCI_Config_Addr: DWORD, \
+ Data: BYTE
+
+ mov eax, [PCI_Config_Addr]
+ call PCI_Common
+ mov al, [Data]
+ out dx, al
+ ret
+
+write_PCI_byte endp
+
+
+;**********************************************************************
+; Writes a word PCI register
+;**********************************************************************
+write_PCI_word proc pascal \
+ PCI_Config_Addr:DWORD, \
+ Data:WORD
+
+ mov eax, [PCI_Config_Addr]
+ call PCI_Common
+ mov ax, [Data]
+ out dx, ax
+ ret
+
+write_PCI_word endp
+
+
+;**********************************************************************
+; Writes a dword PCI register
+;**********************************************************************
+write_PCI_dword proc pascal \
+ PCI_Config_Addr: DWORD, \
+ Data: DWORD
+
+ mov eax, [PCI_Config_Addr]
+ call PCI_Common
+ mov eax, [Data]
+ out dx, eax
+ ret
+
+write_PCI_dword endp
+
+
+
+
+;**********************************************************************
+; Disables PCI trapping (except virtualized PCI devices)
+;**********************************************************************
+Disable_PCI_Traps proc
+
+ ; Has MPCI NB MSR been determined yet ?
+ mov ecx, [PBus_Addr]
+ or ecx, ecx
+ jnz GotPbus
+
+ ; No, get routing address for MPCI NB
+ push bx
+ push ID_MPCI ; MBus ID
+ push 1 ; Instance
+ call sys_lookup_device
+ pop bx
+
+ mov cx, dx
+ shl ecx, 16
+ mov cx, MPCI_PBUS
+ mov [PBus_Addr], ecx
+
+ ; Compute mask for virtual Southbridge
+ mov ax, word ptr (VSM_Header PTR ds:[0]).SysStuff.Southbridge
+ shr ah, 3
+ mov cl, ah
+ mov eax, 1
+ shl eax, cl
+ or al, 2 ; Assume Northbridge is at 0x80000800
+ mov [PBus_Mask], eax
+GotPbus:
+ rdmsr
+ mov [PBus_Hi], edx ; Save original value for Restore_PCI_Traps
+ mov [PBus_Lo], eax
+ and eax, [PBus_Mask] ; Disable all except virtual NB & SB
+ wrmsr
+ ret
+
+Disable_PCI_Traps endp
+
+;**********************************************************************
+; Restores PCI trapping
+;**********************************************************************
+Restore_PCI_Traps proc uses eax edx
+
+ mov edx, [PBus_Hi]
+ mov eax, [PBus_Lo]
+ wrmsr
+ ret
+
+Restore_PCI_Traps endp
+
+
+PBus_Addr dd 0
+PBus_Hi dd 0
+PBus_Lo dd 0
+PBus_Mask dd 0
+
+;**********************************************************************
+; Performs a PCI configuration write cycle sans any PCI trapping except
+; for virtualized PCI devices.
+;**********************************************************************
+write_PCI_no_trap proc pascal uses si \
+ PCI_Config_Addr:DWORD, \
+ Data: DWORD, \
+ DataSize: WORD
+
+ mov ebx, [PCI_Config_Addr]
+ mov si, [DataSize]
+
+ ; Disable PCI trapping on all but virtualized PCI devices
+ call Disable_PCI_Traps
+
+ mov eax, ebx
+ call PCI_Common
+ mov eax, [Data]
+ cmp si, BYTE_IO
+ jne short NotByte
+ out dx, al
+ jmp short RestoreTraps
+
+NotByte:
+ cmp si, WORD_IO
+ je short WordWrite
+ db 66h ; Make the following instruction an OUT DX,EAX
+WordWrite:
+ out dx, ax
+RestoreTraps:
+ call Restore_PCI_Traps ; Restore PCI trapping
+Exit: ret
+
+write_PCI_no_trap endp
+
+
+;**********************************************************************
+; Performs a PCI configuration read cycle sans any PCI trapping except
+; for virtualized PCI devices.
+;**********************************************************************
+read_PCI_no_trap proc pascal uses si\
+ PCI_Config_Addr: DWORD, \
+ DataSize: WORD
+
+ mov ebx, [PCI_Config_Addr]
+ mov si, [DataSize]
+
+
+ ; Disable PCI trapping on all but virtualized PCI devices
+ call Disable_PCI_Traps
+
+ mov eax, ebx ; Output PCI address
+ call PCI_Common
+
+ cmp si, BYTE_IO
+ jne short NotByte
+ in al, dx
+ jmp short RestoreTraps
+
+NotByte:
+ cmp si, WORD_IO
+ je short WordRead
+ db 66h ; Makes the following instruction an IN EAX,DX
+WordRead:
+ in ax, dx
+
+RestoreTraps:
+ push eax
+ call Restore_PCI_Traps ; Restore PCI trapping
+ pop eax
+
+ mov edx, eax
+ shr edx, 16
+Exit: ret
+
+read_PCI_no_trap endp
+
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/present.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/present.asm
new file mode 100755
index 0000000..d533bed
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/present.asm
@@ -0,0 +1,54 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* Implementation of SYS_VSM_PRESENT
+
+
+include sysmgr.inc
+include vsa2.inc
+
+.model tiny,c
+.586p
+.CODE
+
+
+;***********************************************************************
+; Returns TRUE if a VSM of the specified type is present
+;***********************************************************************
+sys_vsm_present PROC pascal \
+ VSM_Type: byte
+
+ mov ecx, (VSM_Header PTR ds:[0]).SysStuff.SysMgr_Ptr
+ sub ecx, SPECIAL_LOC
+ mov ah, [VSM_Type]
+ xor al, al ; Assume VSM is not present
+VSM_Search:
+ mov ecx, fs:(VSM_Header PTR [ecx]).SysStuff.Flink
+ jecxz short Exit
+ cmp ah, fs:(VSM_Header PTR [ecx]).VSM_Type
+ jne VSM_Search
+
+ inc al ; VSM is present
+Exit: ret
+
+sys_vsm_present endp
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/regs.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/regs.asm
new file mode 100755
index 0000000..a61fd25
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/regs.asm
@@ -0,0 +1,368 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file library functions for accessing registers & headers
+
+include SYSMGR.INC
+include VSA2.INC
+include SMIMAC.MAC
+
+
+
+.model tiny,c
+.586p
+.CODE
+
+
+
+public Function
+
+externdef Async_VSM: dword
+externdef sys_system_call:proc
+
+Function db 0, 0, 0, 0
+
+;***********************************************************************
+; Reports a parameter error
+;
+; EAX = parameter
+;***********************************************************************
+ParamError proc
+ ; SYS_REPORT_ERROR(ERR_BAD_PARAMETER, macro, param);
+ push word ptr ERR_BAD_PARAMETER
+ mov bh, [Function]
+ mov bl, 1 ; Parameter #1
+ push ebx ; Info1
+ push eax ; Info2
+ call sys_report_error
+ ret
+
+ParamError endp
+
+
+;***********************************************************************
+; Validates if a macro is valid for the current message.
+; Output: if "invalid macro usage"
+; sys_report_error(ERR_ILLEGAL_MACRO);
+; set CF
+; else
+; clear CF
+; EBX = ptr to relevant VSM's stack
+; ECX = ptr to relevant VSM's state
+; NOTE: Must preserve AX
+;***********************************************************************
+ValidateMacro proc
+ mov ebx, [Async_VSM]
+ test ebx, ebx
+ jz short NotSynchronous
+
+ ; Mark blocked VSM as 'Ready'
+ mov fs:(VSM_Header PTR [ebx]).SysStuff.RunFlag, RUN_FLAG_READY
+ jmp short Macro_OK
+
+
+
+NotSynchronous:
+ ; Always allow GET_REGISTER, GET_DESCRIPTOR & GET_HEADER
+ test byte ptr [Function], 1
+ jnz Async_Error
+
+ ; Get ptr to System Manager's VSM header
+ mov ebx, (VSM_Header PTR [bx]).SysStuff.SysMgr_Ptr
+ sub ebx, SPECIAL_LOC
+
+Macro_OK:
+ mov ecx, ebx
+ add ebx, fs:(VSM_Header PTR [ecx]).SysStuff.SavedESP
+ add ebx, EXTRA_SAVE
+
+ lea ecx, (VSM_Header PTR [ecx]).SysStuff.State
+ clc
+ ret
+
+Async_Error:
+
+ ; SYS_REPORT_ERROR(ERR_ILLEGAL_MACRO, macro, argument);
+ push word ptr ERR_ILLEGAL_MACRO
+ push dword ptr [Function]
+ movzx eax, ax
+ push eax
+ call sys_report_error
+
+ mov ax, 0FFFFh ; Return FFFFs
+ mov dx, ax
+ stc
+ ret
+
+ValidateMacro endp
+
+
+
+
+
+;***********************************************************************
+; Helper routine for SYS_SET_REGISTER and SYS_SET_HEADER_DATA macros.
+; Input:
+; AL = offset
+; EBX = base
+; ECX = data
+; DL = max field offset
+;************************************************************ ***********
+SetHeader:
+ mov dx, R_DR7 ; Max valid field
+SetField proc
+
+ cmp al, dl ; Valid field name ?
+ ja short Error ; No
+
+ mov dx, ax ; Save field size
+ xor ah, ah ; Extract offset
+ movzx eax, ax
+ mov fs:[ebx+eax], cl ; Store data as BYTE
+ test dx, (DWORD_SIZE OR WORD_SIZE)
+ jz Exit
+ test dx, DWORD_SIZE ; WORD or DWORD ?
+ jz Set_Word
+Set_Dword:
+ db 66h ; DWORD
+Set_Word:
+ mov fs:[ebx+eax], cx ; WORD
+ clc
+Exit: ret
+
+Error: call ParamError
+ ret
+
+SetField endp
+
+
+
+;***********************************************************************
+; Helper routine for SYS_GET_REGISTER and SYS_GET_HEADER_DATA macros.
+; Input:
+; EBX = base of structure
+; AX = offset
+; DX = maximum valid offset
+; Output:
+; DX:AX = data
+;***********************************************************************
+GetField proc
+
+ cmp al, dl ; Valid field name ?
+ ja short Error ; No, return FFFFs
+
+ mov cx, ax ; Save field size
+ xor ah, ah ; Extract offset
+ movzx eax, ax
+ mov eax, fs:[ebx+eax] ; Get requested value
+ test cx, DWORD_SIZE ; DWORD field ?
+ jz NotDword
+ mov edx, eax ; Put 16 MSBs into DX
+ shr edx, 16
+ ret
+
+NotDword:
+ xor dx, dx ; Zero 16 MSBs
+ test cx, WORD_SIZE ; WORD field ?
+ jnz Exit
+ xor ah, ah ; BYTE field
+Exit: ret
+
+Error: call ParamError
+ mov ax, 0FFFFh ; Return FFFFs
+ mov dx, ax
+ ret
+
+GetField endp
+
+
+
+
+
+;***********************************************************************
+; ULONG sys_get_register(USHORT register)
+;***********************************************************************
+sys_get_register proc pascal \
+ Register:WORD
+
+ mov ax, [Register] ; Get which register
+ mov [Function], GET_REG ; In case of error
+ call ValidateMacro ; Get ptr to registers
+ jc Exit
+
+ test ax, FROM_HEADER ; Is register in SMM header ?
+ jnz Get_Header
+
+ mov dx, R_GS
+ call GetField ; Get register from saved state buffer
+
+Exit: ret
+
+sys_get_register endp
+
+
+
+
+
+;***********************************************************************
+; void sys_set_register(USHORT register, ULONG Data)
+;***********************************************************************
+sys_set_register proc pascal \
+ Register: WORD, \
+ Data: DWORD
+
+ mov ax, [Register] ; Get register
+ mov [Function], SET_REG ; In case of error
+ call ValidateMacro ; Get ptr to registers
+ jc Exit
+
+ test ax, FROM_HEADER ; Is register in SMM header ?
+ jnz Set_Header
+
+ mov ecx, [Data]
+
+ mov dx, R_ESP ; Max valid register field
+ call SetField
+
+Exit: ret
+
+sys_set_register endp
+
+
+
+
+;***********************************************************************
+; Gets a field from the top-level SMM header
+; ULONG sys_get_header_data(USHORT SMM_Field)
+;***********************************************************************
+sys_get_header_data proc pascal \
+ SMM_Field: WORD
+
+ mov ax, [SMM_Field] ; Get SMM header field
+ mov [Function], GET_HDR ; In case of error
+ call ValidateMacro
+ jc short Exit
+
+ mov ax, [SMM_Field] ; Get SMM header field
+ test ax, FROM_HEADER ; Validate field
+ jnz short Get_Header
+ call ParamError
+ jmp short Exit
+
+Get_Header::
+ mov ebx, ecx
+ mov dx, R_DR7 ; Max valid field
+ call GetField
+Exit: ret
+
+sys_get_header_data endp
+
+
+
+;***********************************************************************
+; void sys_set_header_data(USHORT SMM_Field, ULONG Data)
+;***********************************************************************
+sys_set_header_data proc pascal \
+ SMM_Field: WORD, \
+ Data: DWORD
+
+ mov ax, [SMM_Field] ; Get SMM header field
+ mov [Function], SET_HDR ; In case of error
+ call ValidateMacro
+ jc short Exit
+
+ test ax, FROM_HEADER ; Validate field
+ jnz short Set_Header
+ call ParamError
+ jmp short Exit
+
+Set_Header::
+ mov ebx, ecx
+ mov ecx, [Data]
+ call SetHeader
+Exit: ret
+
+sys_set_header_data endp
+
+
+
+;***********************************************************************
+; Reports an error
+;***********************************************************************
+sys_report_error proc pascal uses di \
+ Error_Code: WORD, \
+ Info1: DWORD, \
+ Info2: DWORD
+
+ mov di, [Error_Code]
+ mov ebx, [Info1]
+ mov ecx, [Info2]
+
+ mov ax, SYS_CODE_ERROR
+ call sys_system_call
+ ret
+
+sys_report_error endp
+
+
+;***********************************************************************
+; void sys_return_result(ULONG Result);
+;
+; Implements the SYS_RETURN_RESULT macro
+; Returns a byte/word/dword result to the appropriate environment
+;
+;***********************************************************************
+sys_return_result proc pascal \
+ Result: DWORD
+
+
+ mov ebx, [Result]
+
+ ; Return to another VSM's environment ?
+ mov ecx, [Async_VSM]
+ mov eax, (VSM_Header PTR ds:[0]).SysStuff.SysMgr_Ptr
+ xor ax, ax
+ cmp ecx, eax
+ je RetToTopLevel
+
+ ; Yes, get the data size
+ mov dl, byte ptr fs:(VSM_Header PTR [ecx]).SysStuff.State.data_size
+ mov ax, R_AL
+ cmp dl, BYTE_IO
+ je SetReg
+ mov ax, R_AX
+ cmp dl, WORD_IO
+ je SetReg
+ mov ax, R_EAX
+SetReg:
+ push ax ; Register AL/AX/EAX
+ push ebx ; Data
+ call sys_set_register
+ jmp Exit
+
+RetToTopLevel:
+ mov ax, SYS_CODE_RESULT ; Let SysMgr return the result
+ call sys_system_call
+Exit: ret
+
+sys_return_result endp
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/resource.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/resource.asm
new file mode 100755
index 0000000..0290312
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/resource.asm
@@ -0,0 +1,146 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;*******************************************************************************
+;* This file implements the resource-related macros:
+;* SYS_MBUS_DESCRIPTOR
+;* SYS_IO_DESCRIPTOR
+;* SYS_ALLOCATE_RESOURCE
+;* SYS_SET_DECODE
+;*******************************************************************************
+
+
+include sysmgr.inc
+.model tiny,c
+.586p
+.CODE
+
+
+
+externdef sys_system_call:proc
+
+
+
+;***********************************************************************
+; ULONG sys_mbus_descriptor(USHORT Address, ULONG * Buffer, UCHAR IO_Flag);
+;
+; Returns the MSR address & contents of the descriptor assigned to a
+; virtualized PCI address or an I/O address.
+;
+;***********************************************************************
+sys_mbus_descriptor proc pascal \
+ Address: WORD, \
+ Buffer: PTR, \
+ IO_Flag: WORD
+
+ mov bx, [Address]
+ mov cx, [IO_Flag]
+ mov ax, SYS_CODE_DESCRIPTOR
+ call sys_system_call
+ ; Returns:
+ ; ECX = MSR address
+ ; EDX:EAX = original MSR value
+
+ mov bx, [Buffer] ; Store MSR value into caller's buffer
+ mov [bx+0], eax
+ mov [bx+4], edx
+
+ push ecx ; Return MSR address
+ pop ax
+ pop dx
+ ret
+
+sys_mbus_descriptor endp
+
+
+
+
+;***********************************************************************
+; ULONG sys_resource(USHORT Resource, ULONG Param1, ULONG Param2);
+;
+; Records a VSM's use of a non-shareable resource (e.g. GPIO, IRQ, etc.)
+; If the resources is a memory or I/O PCI BAR, it returns the assigned
+; PCI address.
+;
+;***********************************************************************
+sys_resource proc pascal uses edi si \
+ Resource: BYTE, \
+ BAR: WORD, \
+ BaseRange: DWORD, \
+ Pci_ID: WORD, \
+ MBus_ID: WORD
+
+ mov bl, [Resource]
+ mov si, [BAR]
+ mov ecx, [BaseRange]
+ mov di, [MBus_ID]
+ shl edi, 16
+ mov di, [Pci_ID]
+ mov ax, SYS_CODE_RESOURCE
+ call sys_system_call
+
+ ; If xxxx != 0x0000, then return 0x8000xxxx, where xxxx is return value
+ xor dx, dx
+ or ax, ax
+ jz Exit
+ or dh, 80h
+Exit: ret
+
+sys_resource endp
+
+
+
+
+;***********************************************************************
+; ULONG __pascal sys_lookup_device(USHORT DeviceID, USHORT Instance);
+; Returns the routing bits for the specified Device ID.
+;***********************************************************************
+sys_lookup_device proc pascal \
+ Device_ID: word, \
+ Instance: word
+
+ mov bx, [Device_ID]
+ mov cx, [Instance]
+ mov ax, SYS_CODE_LOOKUP
+ call sys_system_call
+ ret
+
+sys_lookup_device endp
+
+
+
+
+;***********************************************************************
+;void Set_Address_Decode(USHORT Address, USHORT Decode)
+;***********************************************************************
+sys_address_decode proc pascal \
+ Address: WORD, \
+ Decode: WORD
+
+ mov bx, [Address]
+ mov cx, [Decode]
+ mov ax, SYS_CODE_DECODE
+ call sys_system_call
+ ret
+
+sys_address_decode endp
+
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/sw_int.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/sw_int.asm
new file mode 100755
index 0000000..9407b17
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/sw_int.asm
@@ -0,0 +1,87 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file implements the SYS_SW_INTERRUPT macro.
+
+include sysmgr.inc
+.model tiny,c
+.586p
+.CODE
+
+
+
+externdef sys_system_call:proc
+
+
+
+;***********************************************************************
+; void sys_software_interrupt(USHORT Interrupt, Regs * RegsBuffer);
+;
+; This routine performs the equivalent of a software INT.
+;
+; Input:
+; Interrupt = interrupt to execute
+; RegBuffer = ptr to buffer containing general-purpose registers (16 bit)
+;
+;***********************************************************************
+
+sys_software_interrupt proc pascal \
+ Interrupt: WORD, \
+ RegsBuffer: PTR Regs
+
+ movzx ecx, [RegsBuffer] ; Get ptr to Regs[]
+ movzx ebx, [Interrupt] ; Get 4 * INT#
+ shl bx, 2
+ mov ax, SYS_CODE_SW_INT
+ call sys_system_call
+ ret
+
+sys_software_interrupt endp
+
+
+
+;***********************************************************************
+; void sys_state(USHORT Flag, UCHAR * Buffer);
+;
+; This routine saves/restores the non-SMM state.
+; It's intended purpose is to facilitate SaveToRAM and SaveToDisk VSMs.
+;
+; Input:
+; Flag: 0 = Save 1 = Restore
+; RegBuffer: Ptr to state buffer. Must be STATE_SIZE bytes
+;
+;***********************************************************************
+sys_state proc pascal uses di \
+ Flag: WORD, \
+ Buffer: PTR byte
+
+ movzx edi, [Buffer]
+ mov cx, [Flag]
+
+ mov ax, SYS_CODE_STATE
+ call sys_system_call
+
+ ret
+
+sys_state endp
+
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/sysinfo.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/sysinfo.asm
new file mode 100755
index 0000000..f7f4698
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/sysinfo.asm
@@ -0,0 +1,83 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* Implementation of the macros: *
+;* SYS_GET_SYSTEM_INFO *
+;* SYS_LOGICAL_TO_PHYSICAL
+
+include sysmgr.inc
+include vsa2.inc
+
+.model tiny,c
+.586p
+.CODE
+
+
+
+;***********************************************************************
+; Gets hardware information
+;***********************************************************************
+sys_get_system_info proc pascal uses si \
+ buffer: PTR
+
+ ; Get a ptr to the System Manager's hardware information structure
+ xor bx, bx
+ mov esi, (VSM_Header PTR [bx]).SysStuff.SysMgr_Ptr
+ movzx eax, fs:(InfoStuff PTR [esi]).HardwareInfo
+ add esi, eax
+ sub esi, SPECIAL_LOC
+
+
+ mov bx, [buffer]
+
+ ; Fetch the data
+ mov cx, sizeof(Hardware)/2
+ cld
+Copy: lodsw fs:[esi]
+ mov [bx], ax
+ add bx, 2
+ loop Copy
+
+ ret
+
+sys_get_system_info endp
+
+
+
+;***********************************************************************
+; Converts a logical offset to a physical address
+;***********************************************************************
+sys_logical_to_physical proc pascal \
+ Address: PTR
+
+ movzx eax, [Address]
+ xor bx, bx
+ add eax, (VSM_Header PTR [bx]).SysStuff.State._CS.base
+ mov edx, eax
+ shr edx, 16
+ ret
+
+sys_logical_to_physical endp
+
+
+
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/utils.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/utils.asm
new file mode 100755
index 0000000..80e2b44
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/utils.asm
@@ -0,0 +1,203 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file contains generic VSM library functions.
+
+.model tiny,c
+.586p
+.CODE
+
+
+
+
+
+
+;***********************************************************************
+; UCHAR in_8(USHORT io_port)
+;***********************************************************************
+in_8 proc pascal io_port:word
+
+ mov dx, io_port
+ in al, dx
+ ret
+
+in_8 endp
+
+
+;***********************************************************************
+; void out_8(USHORT io_port, UCHAR io_data)
+;***********************************************************************
+out_8 proc pascal \
+ io_port:WORD, \
+ io_data:BYTE
+
+ mov dx, io_port
+ mov al, io_data
+ out dx, al
+ ret
+
+out_8 endp
+
+;***********************************************************************
+; USHORT in_16(USHORT io_port)
+;***********************************************************************
+in_16 proc pascal, io_port:WORD
+
+ mov dx, io_port
+ in ax, dx
+ ret
+
+in_16 endp
+
+
+;***********************************************************************
+; void out_16(USHORT io_port, USHORT io_data)
+;***********************************************************************
+out_16 proc pascal \
+ io_port:WORD, \
+ io_data:WORD
+
+ mov dx, io_port
+ mov ax, io_data
+ out dx, ax
+ ret
+
+out_16 endp
+
+
+
+;***********************************************************************
+; ULONG in_32(USHORT io_port)
+;***********************************************************************
+in_32 proc pascal io_port: WORD
+
+ mov dx, io_port
+ in eax, dx
+ mov edx, eax
+ shr edx, 16
+ ret
+
+in_32 endp
+
+
+;***********************************************************************
+;
+; void out_32(USHORT io_port, ULONG io_data)
+;***********************************************************************
+out_32 proc pascal \
+ io_port:WORD, \
+ io_data:DWORD
+
+ mov dx, io_port
+ mov eax, io_data
+ out dx, eax
+ ret
+
+out_32 endp
+
+
+
+
+
+
+
+write_flat proc pascal \
+ Address: DWORD,\
+ Data: DWORD
+
+ mov ebx, [Address]
+ mov eax, [Data]
+ mov fs:[ebx], eax
+ ret
+
+write_flat endp
+
+
+read_flat proc pascal \
+ Address: DWORD
+
+ mov ebx, [Address]
+ mov eax, fs:[ebx]
+ mov edx, eax
+ shr edx, 16
+ ret
+
+read_flat endp
+
+
+write_flat_word proc pascal \
+ Address: DWORD,\
+ Data: WORD
+
+ mov ebx, [Address]
+ mov ax, [Data]
+ mov fs:[ebx], ax
+ ret
+
+write_flat_word endp
+
+
+read_flat_word proc pascal \
+ Address: DWORD
+
+ mov ebx, [Address]
+ mov ax, fs:[ebx]
+ ret
+
+read_flat_word endp
+
+
+
+write_flat_byte proc pascal \
+ Address: DWORD,\
+ Data: BYTE
+
+ mov ebx, [Address]
+ mov al, [Data]
+ mov fs:[ebx], al
+ ret
+
+write_flat_byte endp
+
+
+read_flat_byte proc pascal \
+ Address: DWORD
+
+ mov ebx, [Address]
+ mov al, fs:[ebx]
+ ret
+
+read_flat_byte endp
+
+
+
+
+read_timestamp proc
+
+ RDTSC
+ mov edx, eax
+ shr edx, 16
+ ret
+
+read_timestamp endp
+
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/virtual.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/virtual.asm
new file mode 100755
index 0000000..56d3585
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/virtual.asm
@@ -0,0 +1,94 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file contains the virtual register library functions.
+
+include sysmgr.inc
+include vsa2.inc
+
+.model tiny,c
+.586p
+.CODE
+
+
+
+
+externdef sys_system_call:proc
+
+
+
+
+;***********************************************************************
+; IMPLEMENTATION NOTE:
+;
+; Using a system call for virtual register access by a VSM has
+; advantages over performing I/O:
+;
+; 1) There is no dependency on VIRTUAL_BASE. It can be changed
+; without requiring recompilation of the VSM.
+;
+; 2) Better performance. There is only one SMI for a system call
+; versus two for I/O (index & data).
+;
+; 3) It solves the problem of atomic accesses to index/data pairs.
+;
+;***********************************************************************
+
+
+;***********************************************************************
+; void sys_set_virtual_register(USHORT Index, USHORT Data)
+;***********************************************************************
+
+sys_set_virtual_register proc pascal \
+ VR_Index:WORD, \
+ VR_Data: WORD
+
+ mov bx, VR_Index
+ mov cx, VR_Data
+ mov ax, SYS_CODE_SET_VIRTUAL
+ call sys_system_call
+
+ ret
+
+sys_set_virtual_register endp
+
+
+
+
+;***********************************************************************
+; USHORT sys_get_virtual_register(USHORT Index)
+;***********************************************************************
+sys_get_virtual_register proc pascal \
+ VR_Index:word
+
+ mov bx, VR_Index
+ mov ax, SYS_CODE_GET_VIRTUAL
+ call sys_system_call
+
+ ret
+
+sys_get_virtual_register endp
+
+
+
+
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/vsa2util.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/vsa2util.asm
new file mode 100755
index 0000000..c0c3827
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/vsa2util.asm
@@ -0,0 +1,204 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file implements the SYS_GET_NEXT_MSG & SYS_REGISTER_EVENT *
+;* macros as well as the code to perform a system call.
+
+include sysmgr.inc
+include smimac.mac
+include vsa2.inc
+
+.model tiny,c
+.586p
+.CODE
+
+
+
+
+public Async_VSM
+
+Async_VSM dd 0
+
+
+;***********************************************************************
+; USHORT sys_get_next_msg(ULONG *)
+;
+; This routine retrieves a message packet from a VSM's message queue.
+;
+; Input:
+; MsgPacket = ptr to message packet (relative to DS)
+; Returns:
+; Message code
+;***********************************************************************
+
+sys_get_next_msg proc uses si di \
+ MsgPacket: PTR
+
+CheckMsgQ:
+ xor di, di
+ ASSUME di: PTR VSM_Header
+
+ mov si, [di].SysStuff.Qtail ; Is the message queue empty ?
+ cmp si, [di].SysStuff.Qhead
+ jne MessageIsWaiting
+
+ mov ax, SYS_CODE_EXIT ; Return to the System Manager
+ smint
+
+ ; Returns here when there are message(s) pending for this VSM.
+ jmp short CheckMsgQ
+
+
+MessageIsWaiting:
+ ASSUME si: PTR Message
+ lea di, [si+sizeof(Message)]
+ mov dx, [si].Msg ; Get the message code
+
+ mov eax, [si].From_VSM ; Get VSM message is from
+ mov [Async_VSM], eax
+
+
+ ; Copy message packet into caller's buffer
+ cld
+ lea si, [si].Param
+ mov cx, MAX_MSG_PARAM
+ mov bx, [MsgPacket] ; Get ptr to message buffer
+CopyMsg:
+ lodsd
+ mov [bx], eax
+ add bx, 4
+ loop CopyMsg
+
+ ;
+ ; Advance the message queue ptr
+ ;
+ mov si, OFFSET VSM_Header.SysStuff
+ ASSUME si: PTR System
+ cmp di, [si].EndMsgQ ; Is Qtail at end ?
+ jb UpdateQtail
+ lea di, [si].MsgQueue ; Yes, wrap ptr to start of queue
+UpdateQtail:
+ mov [si].Qtail, di
+
+
+ ; Return value of function is the message code
+ mov ax, dx
+Exit: ret
+
+
+
+ ASSUME si:NOTHING
+
+sys_get_next_msg endp
+
+
+;***********************************************************************
+; USHORT sys_query_msg_queue(ULONG *)
+;
+; This routine queries the VSM's message queue
+;
+; Input:
+; If a message is present:
+; MsgPacket = ptr to message packet (relative to DS)
+; Returns:
+; If a message is present:
+; Message code
+; Else
+; 0xFFFF
+;***********************************************************************
+
+sys_query_msg_queue proc uses si \
+ MsgPacket: PTR
+
+ xor bx, bx
+ ASSUME bx: PTR VSM_Header
+
+ mov si, [bx].SysStuff.Qtail ; Is the message queue empty ?
+ cmp si, [bx].SysStuff.Qhead
+ mov ax, 0FFFFh ; Return value if queue is empty
+ je short Exit
+
+
+ ASSUME si: PTR Message
+ mov dx, [si].Msg ; Get the message code
+
+
+ ; Copy message packet into caller's buffer
+ cld
+ lea si, [si].Param
+ mov cx, MAX_MSG_PARAM
+ mov bx, [MsgPacket] ; Get ptr to message buffer
+CopyMsg:
+ lodsd
+ mov dword ptr [bx], eax
+ add bx, 4
+ loop CopyMsg
+
+ ; NOTE: Qtail is not advanced !!
+
+ ; Return value of function is the message code
+ mov ax, dx
+Exit: ret
+
+sys_query_msg_queue endp
+
+
+
+
+
+
+;***********************************************************************
+; Registers this VSM as a handler for an event
+;***********************************************************************
+sys_register_event proc pascal uses edi \
+ Event: EVENT, \
+ Param1: DWORD, \
+ Param2: DWORD, \
+ Priority: WORD
+
+ mov bx, [Event] ; Get event to register
+ shl ebx, 16
+ mov bx, [Priority] ; Get event priority
+ mov ecx, [Param1] ; Get parameters
+ mov edi, [Param2]
+
+ mov ax, SYS_CODE_EVENT
+ call sys_system_call
+ ret
+
+sys_register_event endp
+
+
+
+
+
+ ;***********************************************************************
+; Performs a system call
+;***********************************************************************
+sys_system_call proc
+
+ smint
+ ret
+
+sys_system_call endp
+
+
+
+ END
+
diff --git a/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/yield.asm b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/yield.asm
new file mode 100755
index 0000000..9cbf987
--- /dev/null
+++ b/cpu/amd/geode_lx/gplvsa_ii/vsm_lib/yield.asm
@@ -0,0 +1,49 @@
+;
+; Copyright (c) 2006-2008 Advanced Micro Devices,Inc. ("AMD").
+;
+; This library is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as
+; published by the Free Software Foundation; either version 2.1 of the
+; License, or (at your option) any later version.
+;
+; This code is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+;
+; You should have received a copy of the GNU Lesser General
+; Public License along with this library; if not, write to the
+; Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+; Boston, MA 02111-1307 USA
+;
+;* Function: *
+;* This file implements the SYS_YIELD_CONTROL macro.
+
+include vsa2.inc
+include sysmgr.inc
+.model tiny,c
+.586p
+.CODE
+
+
+
+externdef sys_system_call:proc
+
+
+
+sys_yield_control proc pascal \
+ Milliseconds: DWORD
+
+ mov ecx, [Milliseconds]
+ jecxz Exit
+
+ mov ax, SYS_CODE_YIELD ; Yield control to the System Manager
+ call sys_system_call
+
+Exit: ret
+
+sys_yield_control endp
+
+
+ END
+