Author: stepan Date: 2009-03-20 19:32:39 +0100 (Fri, 20 Mar 2009) New Revision: 1
Added: branches/ tags/ trunk/ trunk/gplvsa2/ trunk/gplvsa2/README.txt trunk/gplvsa2/amd_vsa_lx.bin trunk/gplvsa2/build/ trunk/gplvsa2/build/legacy.mak trunk/gplvsa2/build/lxvg.mak trunk/gplvsa2/build/makefile trunk/gplvsa2/build/rules.mak trunk/gplvsa2/build/setvars.mak trunk/gplvsa2/build/sysmgr.mak trunk/gplvsa2/build/vsainit.mak trunk/gplvsa2/inc/ trunk/gplvsa2/inc/acpi.h trunk/gplvsa2/inc/chipset.h trunk/gplvsa2/inc/cs5536.h trunk/gplvsa2/inc/gx2.h trunk/gplvsa2/inc/hce.h trunk/gplvsa2/inc/isa.h trunk/gplvsa2/inc/pci.h trunk/gplvsa2/inc/vr.h trunk/gplvsa2/inc/vsa2.h trunk/gplvsa2/legacy/ trunk/gplvsa2/legacy/blockio.c trunk/gplvsa2/legacy/cs5536.c trunk/gplvsa2/legacy/events.c trunk/gplvsa2/legacy/flash.bak trunk/gplvsa2/legacy/flash.c trunk/gplvsa2/legacy/header.asm trunk/gplvsa2/legacy/ide.c trunk/gplvsa2/legacy/init.c trunk/gplvsa2/legacy/legacy.c trunk/gplvsa2/legacy/legacy.h trunk/gplvsa2/legacy/makefile trunk/gplvsa2/legacy/msr.asm trunk/gplvsa2/legacy/swapsif.c trunk/gplvsa2/legacy/sysinfo.c trunk/gplvsa2/legacy/uarts.c trunk/gplvsa2/legacy/virtregs.c trunk/gplvsa2/lxvg/ trunk/gplvsa2/lxvg/decode.c trunk/gplvsa2/lxvg/init.c trunk/gplvsa2/lxvg/lxhwctl.c trunk/gplvsa2/lxvg/lxvg.h trunk/gplvsa2/lxvg/main.asm trunk/gplvsa2/lxvg/makefile trunk/gplvsa2/lxvg/msr.c trunk/gplvsa2/lxvg/utils.asm trunk/gplvsa2/lxvg/vgdata.c trunk/gplvsa2/lxvg/vgdata.h trunk/gplvsa2/lxvg/vsa2.c trunk/gplvsa2/sysmgr/ trunk/gplvsa2/sysmgr/bugs.asm trunk/gplvsa2/sysmgr/chip.asm trunk/gplvsa2/sysmgr/chipset.c trunk/gplvsa2/sysmgr/cpu.asm trunk/gplvsa2/sysmgr/cpu_init.asm trunk/gplvsa2/sysmgr/cs5536.c trunk/gplvsa2/sysmgr/debug.asm trunk/gplvsa2/sysmgr/descr.c trunk/gplvsa2/sysmgr/descr.h trunk/gplvsa2/sysmgr/errors.c trunk/gplvsa2/sysmgr/events.c trunk/gplvsa2/sysmgr/gpio.c trunk/gplvsa2/sysmgr/gpio5536.c trunk/gplvsa2/sysmgr/handlers.c trunk/gplvsa2/sysmgr/history.c trunk/gplvsa2/sysmgr/idt.asm trunk/gplvsa2/sysmgr/image.asm trunk/gplvsa2/sysmgr/init.asm trunk/gplvsa2/sysmgr/init.h trunk/gplvsa2/sysmgr/io.c trunk/gplvsa2/sysmgr/io_trap.c trunk/gplvsa2/sysmgr/makefile trunk/gplvsa2/sysmgr/mapper.c trunk/gplvsa2/sysmgr/mapper.h trunk/gplvsa2/sysmgr/mbiu.c trunk/gplvsa2/sysmgr/mbus.c trunk/gplvsa2/sysmgr/mdd.c trunk/gplvsa2/sysmgr/mdd.h trunk/gplvsa2/sysmgr/message.asm trunk/gplvsa2/sysmgr/mfgpt.c trunk/gplvsa2/sysmgr/msr.asm trunk/gplvsa2/sysmgr/ohci.c trunk/gplvsa2/sysmgr/pci_pm.c trunk/gplvsa2/sysmgr/pci_rd.c trunk/gplvsa2/sysmgr/pci_wr.c trunk/gplvsa2/sysmgr/port92.asm trunk/gplvsa2/sysmgr/protos.h trunk/gplvsa2/sysmgr/smimac.mac trunk/gplvsa2/sysmgr/smis.asm trunk/gplvsa2/sysmgr/sw_int.asm trunk/gplvsa2/sysmgr/swapsif.c trunk/gplvsa2/sysmgr/syscalls.asm trunk/gplvsa2/sysmgr/sysmgr.asm trunk/gplvsa2/sysmgr/sysmgr.h trunk/gplvsa2/sysmgr/timeout.c trunk/gplvsa2/sysmgr/timer.c trunk/gplvsa2/sysmgr/timer.h trunk/gplvsa2/sysmgr/topology.c trunk/gplvsa2/sysmgr/unregstr.c trunk/gplvsa2/sysmgr/utils.asm trunk/gplvsa2/sysmgr/virt_pci.c trunk/gplvsa2/sysmgr/vpci.h trunk/gplvsa2/sysmgr/vr.c trunk/gplvsa2/sysmgr/vr_misc.asm trunk/gplvsa2/sysmgr/vsa_init.c trunk/gplvsa2/vsabuild.txt trunk/gplvsa2/vsm_lib/ trunk/gplvsa2/vsm_lib/critical.asm trunk/gplvsa2/vsm_lib/descr.asm trunk/gplvsa2/vsm_lib/hex.asm trunk/gplvsa2/vsm_lib/irq.asm trunk/gplvsa2/vsm_lib/makefile trunk/gplvsa2/vsm_lib/message.asm trunk/gplvsa2/vsm_lib/misc.asm trunk/gplvsa2/vsm_lib/msrs.asm trunk/gplvsa2/vsm_lib/pci.asm trunk/gplvsa2/vsm_lib/present.asm trunk/gplvsa2/vsm_lib/regs.asm trunk/gplvsa2/vsm_lib/resource.asm trunk/gplvsa2/vsm_lib/sw_int.asm trunk/gplvsa2/vsm_lib/sysinfo.asm trunk/gplvsa2/vsm_lib/utils.asm trunk/gplvsa2/vsm_lib/virtual.asm trunk/gplvsa2/vsm_lib/vsa2util.asm trunk/gplvsa2/vsm_lib/yield.asm Log: Initial import of AMD's GPL version of VSA2
Added: trunk/gplvsa2/README.txt =================================================================== --- trunk/gplvsa2/README.txt (rev 0) +++ trunk/gplvsa2/README.txt 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/README.txt ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/amd_vsa_lx.bin =================================================================== (Binary files differ)
Property changes on: trunk/gplvsa2/amd_vsa_lx.bin ___________________________________________________________________ Added: svn:executable + * Added: svn:mime-type + application/octet-stream
Added: trunk/gplvsa2/build/legacy.mak =================================================================== --- trunk/gplvsa2/build/legacy.mak (rev 0) +++ trunk/gplvsa2/build/legacy.mak 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/build/legacy.mak ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/build/lxvg.mak =================================================================== --- trunk/gplvsa2/build/lxvg.mak (rev 0) +++ trunk/gplvsa2/build/lxvg.mak 2009-03-20 18:32:39 UTC (rev 1) @@ -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)
Property changes on: trunk/gplvsa2/build/lxvg.mak ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/build/makefile =================================================================== --- trunk/gplvsa2/build/makefile (rev 0) +++ trunk/gplvsa2/build/makefile 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/build/makefile ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/build/rules.mak =================================================================== --- trunk/gplvsa2/build/rules.mak (rev 0) +++ trunk/gplvsa2/build/rules.mak 2009-03-20 18:32:39 UTC (rev 1) @@ -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) $< $@ +
Property changes on: trunk/gplvsa2/build/rules.mak ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/build/setvars.mak =================================================================== --- trunk/gplvsa2/build/setvars.mak (rev 0) +++ trunk/gplvsa2/build/setvars.mak 2009-03-20 18:32:39 UTC (rev 1) @@ -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 + +
Property changes on: trunk/gplvsa2/build/setvars.mak ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/build/sysmgr.mak =================================================================== --- trunk/gplvsa2/build/sysmgr.mak (rev 0) +++ trunk/gplvsa2/build/sysmgr.mak 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/build/sysmgr.mak ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/build/vsainit.mak =================================================================== --- trunk/gplvsa2/build/vsainit.mak (rev 0) +++ trunk/gplvsa2/build/vsainit.mak 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/build/vsainit.mak ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/inc/acpi.h =================================================================== --- trunk/gplvsa2/inc/acpi.h (rev 0) +++ trunk/gplvsa2/inc/acpi.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/inc/acpi.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/inc/chipset.h =================================================================== --- trunk/gplvsa2/inc/chipset.h (rev 0) +++ trunk/gplvsa2/inc/chipset.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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) + + +
Property changes on: trunk/gplvsa2/inc/chipset.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/inc/cs5536.h =================================================================== --- trunk/gplvsa2/inc/cs5536.h (rev 0) +++ trunk/gplvsa2/inc/cs5536.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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)
Property changes on: trunk/gplvsa2/inc/cs5536.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/inc/gx2.h =================================================================== --- trunk/gplvsa2/inc/gx2.h (rev 0) +++ trunk/gplvsa2/inc/gx2.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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) + + + + +
Property changes on: trunk/gplvsa2/inc/gx2.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/inc/hce.h =================================================================== --- trunk/gplvsa2/inc/hce.h (rev 0) +++ trunk/gplvsa2/inc/hce.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/inc/hce.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/inc/isa.h =================================================================== --- trunk/gplvsa2/inc/isa.h (rev 0) +++ trunk/gplvsa2/inc/isa.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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 + + + +
Property changes on: trunk/gplvsa2/inc/isa.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/inc/pci.h =================================================================== --- trunk/gplvsa2/inc/pci.h (rev 0) +++ trunk/gplvsa2/inc/pci.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/inc/pci.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/inc/vr.h =================================================================== --- trunk/gplvsa2/inc/vr.h (rev 0) +++ trunk/gplvsa2/inc/vr.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/inc/vr.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/inc/vsa2.h =================================================================== --- trunk/gplvsa2/inc/vsa2.h (rev 0) +++ trunk/gplvsa2/inc/vsa2.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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; + + + +
Property changes on: trunk/gplvsa2/inc/vsa2.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/blockio.c =================================================================== --- trunk/gplvsa2/legacy/blockio.c (rev 0) +++ trunk/gplvsa2/legacy/blockio.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + +}
Property changes on: trunk/gplvsa2/legacy/blockio.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/cs5536.c =================================================================== --- trunk/gplvsa2/legacy/cs5536.c (rev 0) +++ trunk/gplvsa2/legacy/cs5536.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); +} +
Property changes on: trunk/gplvsa2/legacy/cs5536.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/events.c =================================================================== --- trunk/gplvsa2/legacy/events.c (rev 0) +++ trunk/gplvsa2/legacy/events.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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; + } +}
Property changes on: trunk/gplvsa2/legacy/events.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/flash.bak =================================================================== --- trunk/gplvsa2/legacy/flash.bak (rev 0) +++ trunk/gplvsa2/legacy/flash.bak 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + } + } +}
Property changes on: trunk/gplvsa2/legacy/flash.bak ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/flash.c =================================================================== --- trunk/gplvsa2/legacy/flash.c (rev 0) +++ trunk/gplvsa2/legacy/flash.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + } + } +}
Property changes on: trunk/gplvsa2/legacy/flash.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/header.asm =================================================================== --- trunk/gplvsa2/legacy/header.asm (rev 0) +++ trunk/gplvsa2/legacy/header.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/legacy/header.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/ide.c =================================================================== --- trunk/gplvsa2/legacy/ide.c (rev 0) +++ trunk/gplvsa2/legacy/ide.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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; +}
Property changes on: trunk/gplvsa2/legacy/ide.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/init.c =================================================================== --- trunk/gplvsa2/legacy/init.c (rev 0) +++ trunk/gplvsa2/legacy/init.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + +}
Property changes on: trunk/gplvsa2/legacy/init.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/legacy.c =================================================================== --- trunk/gplvsa2/legacy/legacy.c (rev 0) +++ trunk/gplvsa2/legacy/legacy.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/legacy/legacy.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/legacy.h =================================================================== --- trunk/gplvsa2/legacy/legacy.h (rev 0) +++ trunk/gplvsa2/legacy/legacy.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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 + + +
Property changes on: trunk/gplvsa2/legacy/legacy.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/makefile =================================================================== --- trunk/gplvsa2/legacy/makefile (rev 0) +++ trunk/gplvsa2/legacy/makefile 2009-03-20 18:32:39 UTC (rev 1) @@ -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 $<
Property changes on: trunk/gplvsa2/legacy/makefile ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/msr.asm =================================================================== --- trunk/gplvsa2/legacy/msr.asm (rev 0) +++ trunk/gplvsa2/legacy/msr.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 + + +
Property changes on: trunk/gplvsa2/legacy/msr.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/swapsif.c =================================================================== --- trunk/gplvsa2/legacy/swapsif.c (rev 0) +++ trunk/gplvsa2/legacy/swapsif.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/legacy/swapsif.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/sysinfo.c =================================================================== --- trunk/gplvsa2/legacy/sysinfo.c (rev 0) +++ trunk/gplvsa2/legacy/sysinfo.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); +}
Property changes on: trunk/gplvsa2/legacy/sysinfo.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/uarts.c =================================================================== --- trunk/gplvsa2/legacy/uarts.c (rev 0) +++ trunk/gplvsa2/legacy/uarts.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + } + } + +} + + +
Property changes on: trunk/gplvsa2/legacy/uarts.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/legacy/virtregs.c =================================================================== --- trunk/gplvsa2/legacy/virtregs.c (rev 0) +++ trunk/gplvsa2/legacy/virtregs.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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; + } +} + + + + + +
Property changes on: trunk/gplvsa2/legacy/virtregs.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/lxvg/decode.c =================================================================== --- trunk/gplvsa2/lxvg/decode.c (rev 0) +++ trunk/gplvsa2/lxvg/decode.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/lxvg/decode.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/lxvg/init.c =================================================================== --- trunk/gplvsa2/lxvg/init.c (rev 0) +++ trunk/gplvsa2/lxvg/init.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/lxvg/init.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/lxvg/lxhwctl.c =================================================================== --- trunk/gplvsa2/lxvg/lxhwctl.c (rev 0) +++ trunk/gplvsa2/lxvg/lxhwctl.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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; +} +
Property changes on: trunk/gplvsa2/lxvg/lxhwctl.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/lxvg/lxvg.h =================================================================== --- trunk/gplvsa2/lxvg/lxvg.h (rev 0) +++ trunk/gplvsa2/lxvg/lxvg.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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); +
Property changes on: trunk/gplvsa2/lxvg/lxvg.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/lxvg/main.asm =================================================================== --- trunk/gplvsa2/lxvg/main.asm (rev 0) +++ trunk/gplvsa2/lxvg/main.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 + + + +
Property changes on: trunk/gplvsa2/lxvg/main.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/lxvg/makefile =================================================================== --- trunk/gplvsa2/lxvg/makefile (rev 0) +++ trunk/gplvsa2/lxvg/makefile 2009-03-20 18:32:39 UTC (rev 1) @@ -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$@ $<
Property changes on: trunk/gplvsa2/lxvg/makefile ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/lxvg/msr.c =================================================================== --- trunk/gplvsa2/lxvg/msr.c (rev 0) +++ trunk/gplvsa2/lxvg/msr.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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; + +} +
Property changes on: trunk/gplvsa2/lxvg/msr.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/lxvg/utils.asm =================================================================== --- trunk/gplvsa2/lxvg/utils.asm (rev 0) +++ trunk/gplvsa2/lxvg/utils.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/lxvg/utils.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/lxvg/vgdata.c =================================================================== --- trunk/gplvsa2/lxvg/vgdata.c (rev 0) +++ trunk/gplvsa2/lxvg/vgdata.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/lxvg/vgdata.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/lxvg/vgdata.h =================================================================== --- trunk/gplvsa2/lxvg/vgdata.h (rev 0) +++ trunk/gplvsa2/lxvg/vgdata.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/lxvg/vgdata.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/lxvg/vsa2.c =================================================================== --- trunk/gplvsa2/lxvg/vsa2.c (rev 0) +++ trunk/gplvsa2/lxvg/vsa2.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/lxvg/vsa2.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/bugs.asm =================================================================== --- trunk/gplvsa2/sysmgr/bugs.asm (rev 0) +++ trunk/gplvsa2/sysmgr/bugs.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/sysmgr/bugs.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/chip.asm =================================================================== --- trunk/gplvsa2/sysmgr/chip.asm (rev 0) +++ trunk/gplvsa2/sysmgr/chip.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/chip.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/chipset.c =================================================================== --- trunk/gplvsa2/sysmgr/chipset.c (rev 0) +++ trunk/gplvsa2/sysmgr/chipset.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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; + } +} + + +
Property changes on: trunk/gplvsa2/sysmgr/chipset.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/cpu.asm =================================================================== --- trunk/gplvsa2/sysmgr/cpu.asm (rev 0) +++ trunk/gplvsa2/sysmgr/cpu.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/cpu.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/cpu_init.asm =================================================================== --- trunk/gplvsa2/sysmgr/cpu_init.asm (rev 0) +++ trunk/gplvsa2/sysmgr/cpu_init.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/cpu_init.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/cs5536.c =================================================================== --- trunk/gplvsa2/sysmgr/cs5536.c (rev 0) +++ trunk/gplvsa2/sysmgr/cs5536.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + } + } + } + } + } +}
Property changes on: trunk/gplvsa2/sysmgr/cs5536.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/debug.asm =================================================================== --- trunk/gplvsa2/sysmgr/debug.asm (rev 0) +++ trunk/gplvsa2/sysmgr/debug.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/sysmgr/debug.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/descr.c =================================================================== --- trunk/gplvsa2/sysmgr/descr.c (rev 0) +++ trunk/gplvsa2/sysmgr/descr.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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; +} + + + + +
Property changes on: trunk/gplvsa2/sysmgr/descr.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/descr.h =================================================================== --- trunk/gplvsa2/sysmgr/descr.h (rev 0) +++ trunk/gplvsa2/sysmgr/descr.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/descr.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/errors.c =================================================================== --- trunk/gplvsa2/sysmgr/errors.c (rev 0) +++ trunk/gplvsa2/sysmgr/errors.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + } +} + +
Property changes on: trunk/gplvsa2/sysmgr/errors.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/events.c =================================================================== --- trunk/gplvsa2/sysmgr/events.c (rev 0) +++ trunk/gplvsa2/sysmgr/events.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/events.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/gpio.c =================================================================== --- trunk/gplvsa2/sysmgr/gpio.c (rev 0) +++ trunk/gplvsa2/sysmgr/gpio.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + +} + + + + + + + +
Property changes on: trunk/gplvsa2/sysmgr/gpio.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/gpio5536.c =================================================================== --- trunk/gplvsa2/sysmgr/gpio5536.c (rev 0) +++ trunk/gplvsa2/sysmgr/gpio5536.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + +}
Property changes on: trunk/gplvsa2/sysmgr/gpio5536.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/handlers.c =================================================================== --- trunk/gplvsa2/sysmgr/handlers.c (rev 0) +++ trunk/gplvsa2/sysmgr/handlers.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/handlers.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/history.c =================================================================== --- trunk/gplvsa2/sysmgr/history.c (rev 0) +++ trunk/gplvsa2/sysmgr/history.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/history.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/idt.asm =================================================================== --- trunk/gplvsa2/sysmgr/idt.asm (rev 0) +++ trunk/gplvsa2/sysmgr/idt.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/sysmgr/idt.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/image.asm =================================================================== --- trunk/gplvsa2/sysmgr/image.asm (rev 0) +++ trunk/gplvsa2/sysmgr/image.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/image.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/init.asm =================================================================== --- trunk/gplvsa2/sysmgr/init.asm (rev 0) +++ trunk/gplvsa2/sysmgr/init.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 + + +
Property changes on: trunk/gplvsa2/sysmgr/init.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/init.h =================================================================== --- trunk/gplvsa2/sysmgr/init.h (rev 0) +++ trunk/gplvsa2/sysmgr/init.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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) +
Property changes on: trunk/gplvsa2/sysmgr/init.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/io.c =================================================================== --- trunk/gplvsa2/sysmgr/io.c (rev 0) +++ trunk/gplvsa2/sysmgr/io.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + } +}
Property changes on: trunk/gplvsa2/sysmgr/io.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/io_trap.c =================================================================== --- trunk/gplvsa2/sysmgr/io_trap.c (rev 0) +++ trunk/gplvsa2/sysmgr/io_trap.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + } +}
Property changes on: trunk/gplvsa2/sysmgr/io_trap.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/makefile =================================================================== --- trunk/gplvsa2/sysmgr/makefile (rev 0) +++ trunk/gplvsa2/sysmgr/makefile 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/sysmgr/makefile ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/mapper.c =================================================================== --- trunk/gplvsa2/sysmgr/mapper.c (rev 0) +++ trunk/gplvsa2/sysmgr/mapper.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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++; + } +} +
Property changes on: trunk/gplvsa2/sysmgr/mapper.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/mapper.h =================================================================== --- trunk/gplvsa2/sysmgr/mapper.h (rev 0) +++ trunk/gplvsa2/sysmgr/mapper.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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 + +
Property changes on: trunk/gplvsa2/sysmgr/mapper.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/mbiu.c =================================================================== --- trunk/gplvsa2/sysmgr/mbiu.c (rev 0) +++ trunk/gplvsa2/sysmgr/mbiu.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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++; +} + + + + + + +
Property changes on: trunk/gplvsa2/sysmgr/mbiu.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/mbus.c =================================================================== --- trunk/gplvsa2/sysmgr/mbus.c (rev 0) +++ trunk/gplvsa2/sysmgr/mbus.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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; +}
Property changes on: trunk/gplvsa2/sysmgr/mbus.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/mdd.c =================================================================== --- trunk/gplvsa2/sysmgr/mdd.c (rev 0) +++ trunk/gplvsa2/sysmgr/mdd.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + } + } +}
Property changes on: trunk/gplvsa2/sysmgr/mdd.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/mdd.h =================================================================== --- trunk/gplvsa2/sysmgr/mdd.h (rev 0) +++ trunk/gplvsa2/sysmgr/mdd.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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) +
Property changes on: trunk/gplvsa2/sysmgr/mdd.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/message.asm =================================================================== --- trunk/gplvsa2/sysmgr/message.asm (rev 0) +++ trunk/gplvsa2/sysmgr/message.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 + + +
Property changes on: trunk/gplvsa2/sysmgr/message.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/mfgpt.c =================================================================== --- trunk/gplvsa2/sysmgr/mfgpt.c (rev 0) +++ trunk/gplvsa2/sysmgr/mfgpt.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); +} +
Property changes on: trunk/gplvsa2/sysmgr/mfgpt.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/msr.asm =================================================================== --- trunk/gplvsa2/sysmgr/msr.asm (rev 0) +++ trunk/gplvsa2/sysmgr/msr.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/msr.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/ohci.c =================================================================== --- trunk/gplvsa2/sysmgr/ohci.c (rev 0) +++ trunk/gplvsa2/sysmgr/ohci.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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; +}
Property changes on: trunk/gplvsa2/sysmgr/ohci.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/pci_pm.c =================================================================== --- trunk/gplvsa2/sysmgr/pci_pm.c (rev 0) +++ trunk/gplvsa2/sysmgr/pci_pm.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/pci_pm.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/pci_rd.c =================================================================== --- trunk/gplvsa2/sysmgr/pci_rd.c (rev 0) +++ trunk/gplvsa2/sysmgr/pci_rd.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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; +} + + +
Property changes on: trunk/gplvsa2/sysmgr/pci_rd.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/pci_wr.c =================================================================== --- trunk/gplvsa2/sysmgr/pci_wr.c (rev 0) +++ trunk/gplvsa2/sysmgr/pci_wr.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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; +} + + +
Property changes on: trunk/gplvsa2/sysmgr/pci_wr.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/port92.asm =================================================================== --- trunk/gplvsa2/sysmgr/port92.asm (rev 0) +++ trunk/gplvsa2/sysmgr/port92.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/port92.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/protos.h =================================================================== --- trunk/gplvsa2/sysmgr/protos.h (rev 0) +++ trunk/gplvsa2/sysmgr/protos.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + + +
Property changes on: trunk/gplvsa2/sysmgr/protos.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/smimac.mac =================================================================== --- trunk/gplvsa2/sysmgr/smimac.mac (rev 0) +++ trunk/gplvsa2/sysmgr/smimac.mac 2009-03-20 18:32:39 UTC (rev 1) @@ -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 + +
Property changes on: trunk/gplvsa2/sysmgr/smimac.mac ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/smis.asm =================================================================== --- trunk/gplvsa2/sysmgr/smis.asm (rev 0) +++ trunk/gplvsa2/sysmgr/smis.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/sysmgr/smis.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/sw_int.asm =================================================================== --- trunk/gplvsa2/sysmgr/sw_int.asm (rev 0) +++ trunk/gplvsa2/sysmgr/sw_int.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/sw_int.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/swapsif.c =================================================================== --- trunk/gplvsa2/sysmgr/swapsif.c (rev 0) +++ trunk/gplvsa2/sysmgr/swapsif.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/swapsif.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/syscalls.asm =================================================================== --- trunk/gplvsa2/sysmgr/syscalls.asm (rev 0) +++ trunk/gplvsa2/sysmgr/syscalls.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 + + +
Property changes on: trunk/gplvsa2/sysmgr/syscalls.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/sysmgr.asm =================================================================== --- trunk/gplvsa2/sysmgr/sysmgr.asm (rev 0) +++ trunk/gplvsa2/sysmgr/sysmgr.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/sysmgr/sysmgr.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/sysmgr.h =================================================================== --- trunk/gplvsa2/sysmgr/sysmgr.h (rev 0) +++ trunk/gplvsa2/sysmgr/sysmgr.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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;
Property changes on: trunk/gplvsa2/sysmgr/sysmgr.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/timeout.c =================================================================== --- trunk/gplvsa2/sysmgr/timeout.c (rev 0) +++ trunk/gplvsa2/sysmgr/timeout.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + } +} + +
Property changes on: trunk/gplvsa2/sysmgr/timeout.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/timer.c =================================================================== --- trunk/gplvsa2/sysmgr/timer.c (rev 0) +++ trunk/gplvsa2/sysmgr/timer.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + + } +} + +
Property changes on: trunk/gplvsa2/sysmgr/timer.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/timer.h =================================================================== --- trunk/gplvsa2/sysmgr/timer.h (rev 0) +++ trunk/gplvsa2/sysmgr/timer.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/sysmgr/timer.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/topology.c =================================================================== --- trunk/gplvsa2/sysmgr/topology.c (rev 0) +++ trunk/gplvsa2/sysmgr/topology.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +}; + +
Property changes on: trunk/gplvsa2/sysmgr/topology.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/unregstr.c =================================================================== --- trunk/gplvsa2/sysmgr/unregstr.c (rev 0) +++ trunk/gplvsa2/sysmgr/unregstr.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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]; + } + } +} +
Property changes on: trunk/gplvsa2/sysmgr/unregstr.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/utils.asm =================================================================== --- trunk/gplvsa2/sysmgr/utils.asm (rev 0) +++ trunk/gplvsa2/sysmgr/utils.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/utils.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/virt_pci.c =================================================================== --- trunk/gplvsa2/sysmgr/virt_pci.c (rev 0) +++ trunk/gplvsa2/sysmgr/virt_pci.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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; +} + + + +
Property changes on: trunk/gplvsa2/sysmgr/virt_pci.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/vpci.h =================================================================== --- trunk/gplvsa2/sysmgr/vpci.h (rev 0) +++ trunk/gplvsa2/sysmgr/vpci.h 2009-03-20 18:32:39 UTC (rev 1) @@ -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);
Property changes on: trunk/gplvsa2/sysmgr/vpci.h ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/vr.c =================================================================== --- trunk/gplvsa2/sysmgr/vr.c (rev 0) +++ trunk/gplvsa2/sysmgr/vr.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/vr.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/vr_misc.asm =================================================================== --- trunk/gplvsa2/sysmgr/vr_misc.asm (rev 0) +++ trunk/gplvsa2/sysmgr/vr_misc.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/sysmgr/vr_misc.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/sysmgr/vsa_init.c =================================================================== --- trunk/gplvsa2/sysmgr/vsa_init.c (rev 0) +++ trunk/gplvsa2/sysmgr/vsa_init.c 2009-03-20 18:32:39 UTC (rev 1) @@ -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); + + +}
Property changes on: trunk/gplvsa2/sysmgr/vsa_init.c ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsabuild.txt =================================================================== --- trunk/gplvsa2/vsabuild.txt (rev 0) +++ trunk/gplvsa2/vsabuild.txt 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/vsabuild.txt ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/critical.asm =================================================================== --- trunk/gplvsa2/vsm_lib/critical.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/critical.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/critical.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/descr.asm =================================================================== --- trunk/gplvsa2/vsm_lib/descr.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/descr.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/descr.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/hex.asm =================================================================== --- trunk/gplvsa2/vsm_lib/hex.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/hex.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/hex.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/irq.asm =================================================================== --- trunk/gplvsa2/vsm_lib/irq.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/irq.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/irq.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/makefile =================================================================== --- trunk/gplvsa2/vsm_lib/makefile (rev 0) +++ trunk/gplvsa2/vsm_lib/makefile 2009-03-20 18:32:39 UTC (rev 1) @@ -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 -+$@;
Property changes on: trunk/gplvsa2/vsm_lib/makefile ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/message.asm =================================================================== --- trunk/gplvsa2/vsm_lib/message.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/message.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/message.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/misc.asm =================================================================== --- trunk/gplvsa2/vsm_lib/misc.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/misc.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/misc.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/msrs.asm =================================================================== --- trunk/gplvsa2/vsm_lib/msrs.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/msrs.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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
Property changes on: trunk/gplvsa2/vsm_lib/msrs.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/pci.asm =================================================================== --- trunk/gplvsa2/vsm_lib/pci.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/pci.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/pci.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/present.asm =================================================================== --- trunk/gplvsa2/vsm_lib/present.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/present.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/present.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/regs.asm =================================================================== --- trunk/gplvsa2/vsm_lib/regs.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/regs.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/regs.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/resource.asm =================================================================== --- trunk/gplvsa2/vsm_lib/resource.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/resource.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/resource.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/sw_int.asm =================================================================== --- trunk/gplvsa2/vsm_lib/sw_int.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/sw_int.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/sw_int.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/sysinfo.asm =================================================================== --- trunk/gplvsa2/vsm_lib/sysinfo.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/sysinfo.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/sysinfo.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/utils.asm =================================================================== --- trunk/gplvsa2/vsm_lib/utils.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/utils.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/utils.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/virtual.asm =================================================================== --- trunk/gplvsa2/vsm_lib/virtual.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/virtual.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/virtual.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/vsa2util.asm =================================================================== --- trunk/gplvsa2/vsm_lib/vsa2util.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/vsa2util.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/vsa2util.asm ___________________________________________________________________ Added: svn:executable + *
Added: trunk/gplvsa2/vsm_lib/yield.asm =================================================================== --- trunk/gplvsa2/vsm_lib/yield.asm (rev 0) +++ trunk/gplvsa2/vsm_lib/yield.asm 2009-03-20 18:32:39 UTC (rev 1) @@ -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 +
Property changes on: trunk/gplvsa2/vsm_lib/yield.asm ___________________________________________________________________ Added: svn:executable + *