Decoder.c revision 209ff23f
1209ff23fSmrg/*
2209ff23fSmrg * Copyright 2006-2007 Advanced Micro Devices, Inc.
3209ff23fSmrg *
4209ff23fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
5209ff23fSmrg * copy of this software and associated documentation files (the "Software"),
6209ff23fSmrg * to deal in the Software without restriction, including without limitation
7209ff23fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8209ff23fSmrg * and/or sell copies of the Software, and to permit persons to whom the
9209ff23fSmrg * Software is furnished to do so, subject to the following conditions:
10209ff23fSmrg *
11209ff23fSmrg * The above copyright notice and this permission notice shall be included in
12209ff23fSmrg * all copies or substantial portions of the Software.
13209ff23fSmrg *
14209ff23fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15209ff23fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16209ff23fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17209ff23fSmrg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18209ff23fSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19209ff23fSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20209ff23fSmrg * OTHER DEALINGS IN THE SOFTWARE.
21209ff23fSmrg */
22209ff23fSmrg
23209ff23fSmrg/**
24209ff23fSmrg
25209ff23fSmrgModule Name:
26209ff23fSmrg
27209ff23fSmrg    Decoder.c
28209ff23fSmrg
29209ff23fSmrgAbstract:
30209ff23fSmrg
31209ff23fSmrg		Commands Decoder
32209ff23fSmrg
33209ff23fSmrgRevision History:
34209ff23fSmrg
35209ff23fSmrg	NEG:24.09.2002	Initiated.
36209ff23fSmrg--*/
37209ff23fSmrg
38209ff23fSmrg#ifdef HAVE_CONFIG_H
39209ff23fSmrg#include "config.h"
40209ff23fSmrg#endif
41209ff23fSmrg
42209ff23fSmrg#include <X11/Xos.h>
43209ff23fSmrg
44209ff23fSmrg
45209ff23fSmrg#include "Decoder.h"
46209ff23fSmrg#include "atombios.h"
47209ff23fSmrg#include "CD_binding.h"
48209ff23fSmrg#include "CD_Common_Types.h"
49209ff23fSmrg
50209ff23fSmrg#ifndef DISABLE_EASF
51209ff23fSmrg	#include "easf.h"
52209ff23fSmrg#endif
53209ff23fSmrg
54209ff23fSmrg
55209ff23fSmrg
56209ff23fSmrg#define INDIRECT_IO_TABLE (((UINT16)(ULONG_PTR)&((ATOM_MASTER_LIST_OF_DATA_TABLES*)0)->IndirectIOAccess)/sizeof(TABLE_UNIT_TYPE) )
57209ff23fSmrgextern COMMANDS_PROPERTIES CallTable[];
58209ff23fSmrg
59209ff23fSmrg
60209ff23fSmrgUINT8 ProcessCommandProperties(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
61209ff23fSmrg{
62209ff23fSmrg  UINT8 opcode=((COMMAND_HEADER*)pParserTempData->pWorkingTableData->IP)->Opcode;
63209ff23fSmrg  pParserTempData->pWorkingTableData->IP+=CallTable[opcode].headersize;
64209ff23fSmrg  pParserTempData->ParametersType.Destination=CallTable[opcode].destination;
65209ff23fSmrg  pParserTempData->ParametersType.Source = pParserTempData->pCmd->Header.Attribute.Source;
66209ff23fSmrg  pParserTempData->CD_Mask.SrcAlignment=pParserTempData->pCmd->Header.Attribute.SourceAlignment;
67209ff23fSmrg  pParserTempData->CD_Mask.DestAlignment=pParserTempData->pCmd->Header.Attribute.DestinationAlignment;
68209ff23fSmrg  return opcode;
69209ff23fSmrg}
70209ff23fSmrg
71209ff23fSmrgUINT16* GetCommandMasterTablePointer(DEVICE_DATA STACK_BASED*  pDeviceData)
72209ff23fSmrg{
73209ff23fSmrg	UINT16		*MasterTableOffset;
74209ff23fSmrg#ifndef DISABLE_EASF
75209ff23fSmrg	if (pDeviceData->format == TABLE_FORMAT_EASF)
76209ff23fSmrg	{
77209ff23fSmrg    /*
78209ff23fSmrg    make MasterTableOffset point to EASF_ASIC_SETUP_TABLE structure, including usSize.
79209ff23fSmrg    */
80209ff23fSmrg		MasterTableOffset = (UINT16 *) (pDeviceData->pBIOS_Image+((EASF_ASIC_DESCRIPTOR*)pDeviceData->pBIOS_Image)->usAsicSetupTable_Offset);
81209ff23fSmrg	} else
82209ff23fSmrg#endif
83209ff23fSmrg	{
84209ff23fSmrg#ifndef		UEFI_BUILD
85209ff23fSmrg		MasterTableOffset = (UINT16 *)(*(UINT16 *)(pDeviceData->pBIOS_Image+OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER) + pDeviceData->pBIOS_Image);
86209ff23fSmrg		MasterTableOffset = (UINT16 *)((ULONG)((ATOM_ROM_HEADER *)MasterTableOffset)->usMasterCommandTableOffset + pDeviceData->pBIOS_Image );
87209ff23fSmrg		MasterTableOffset =(UINT16 *) &(((ATOM_MASTER_COMMAND_TABLE *)MasterTableOffset)->ListOfCommandTables);
88209ff23fSmrg#else
89209ff23fSmrg	MasterTableOffset = (UINT16 *)(&(GetCommandMasterTable( )->ListOfCommandTables));
90209ff23fSmrg#endif
91209ff23fSmrg	}
92209ff23fSmrg	return MasterTableOffset;
93209ff23fSmrg}
94209ff23fSmrg
95209ff23fSmrgUINT16* GetDataMasterTablePointer(DEVICE_DATA STACK_BASED*  pDeviceData)
96209ff23fSmrg{
97209ff23fSmrg	UINT16		*MasterTableOffset;
98209ff23fSmrg
99209ff23fSmrg#ifndef		UEFI_BUILD
100209ff23fSmrg	MasterTableOffset = (UINT16 *)(*(UINT16 *)(pDeviceData->pBIOS_Image+OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER) + pDeviceData->pBIOS_Image);
101209ff23fSmrg	MasterTableOffset = (UINT16 *)((ULONG)((ATOM_ROM_HEADER *)MasterTableOffset)->usMasterDataTableOffset + pDeviceData->pBIOS_Image );
102209ff23fSmrg	MasterTableOffset =(UINT16 *) &(((ATOM_MASTER_DATA_TABLE *)MasterTableOffset)->ListOfDataTables);
103209ff23fSmrg#else
104209ff23fSmrg	MasterTableOffset = (UINT16 *)(&(GetDataMasterTable( )->ListOfDataTables));
105209ff23fSmrg#endif
106209ff23fSmrg	return MasterTableOffset;
107209ff23fSmrg}
108209ff23fSmrg
109209ff23fSmrg
110209ff23fSmrgUINT8 GetTrueIndexInMasterTable(PARSER_TEMP_DATA STACK_BASED * pParserTempData, UINT8 IndexInMasterTable)
111209ff23fSmrg{
112209ff23fSmrg#ifndef DISABLE_EASF
113209ff23fSmrg	UINT16 i;
114209ff23fSmrg	if ( pParserTempData->pDeviceData->format == TABLE_FORMAT_EASF)
115209ff23fSmrg	{
116209ff23fSmrg/*
117209ff23fSmrg		Consider EASF_ASIC_SETUP_TABLE structure pointed by pParserTempData->pCmd as UINT16[]
118209ff23fSmrg		((UINT16*)pParserTempData->pCmd)[0] = EASF_ASIC_SETUP_TABLE.usSize;
119209ff23fSmrg		((UINT16*)pParserTempData->pCmd)[1+n*4] = usFunctionID;
120209ff23fSmrg		usFunctionID has to be shifted left by 2 before compare it to the value provided by caller.
121209ff23fSmrg*/
122209ff23fSmrg		for (i=1; (i < ((UINT16*)pParserTempData->pCmd)[0] >> 1);i+=4)
123209ff23fSmrg	  		if ((UINT8)(((UINT16*)pParserTempData->pCmd)[i] << 2)==(IndexInMasterTable & EASF_TABLE_INDEX_MASK)) return (i+1+(IndexInMasterTable & EASF_TABLE_ATTR_MASK));
124209ff23fSmrg		return 1;
125209ff23fSmrg	} else
126209ff23fSmrg#endif
127209ff23fSmrg	{
128209ff23fSmrg		return IndexInMasterTable;
129209ff23fSmrg	}
130209ff23fSmrg}
131209ff23fSmrg
132209ff23fSmrgCD_STATUS ParseTable(DEVICE_DATA STACK_BASED* pDeviceData, UINT8 IndexInMasterTable)
133209ff23fSmrg{
134209ff23fSmrg	PARSER_TEMP_DATA	ParserTempData;
135209ff23fSmrg  WORKING_TABLE_DATA STACK_BASED* prevWorkingTableData;
136209ff23fSmrg
137209ff23fSmrg  ParserTempData.pDeviceData=(DEVICE_DATA*)pDeviceData;
138209ff23fSmrg#ifndef DISABLE_EASF
139209ff23fSmrg  if (pDeviceData->format == TABLE_FORMAT_EASF)
140209ff23fSmrg  {
141209ff23fSmrg      ParserTempData.IndirectIOTablePointer = 0;
142209ff23fSmrg  } else
143209ff23fSmrg#endif
144209ff23fSmrg  {
145209ff23fSmrg    ParserTempData.pCmd=(GENERIC_ATTRIBUTE_COMMAND*)GetDataMasterTablePointer(pDeviceData);
146209ff23fSmrg    ParserTempData.IndirectIOTablePointer=(UINT8*)((ULONG)(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[INDIRECT_IO_TABLE]) + pDeviceData->pBIOS_Image);
147209ff23fSmrg    ParserTempData.IndirectIOTablePointer+=sizeof(ATOM_COMMON_TABLE_HEADER);
148209ff23fSmrg  }
149209ff23fSmrg
150209ff23fSmrg	ParserTempData.pCmd=(GENERIC_ATTRIBUTE_COMMAND*)GetCommandMasterTablePointer(pDeviceData);
151209ff23fSmrg    IndexInMasterTable=GetTrueIndexInMasterTable((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData,IndexInMasterTable);
152209ff23fSmrg	if(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]!=0 )  // if the offset is not ZERO
153209ff23fSmrg	{
154209ff23fSmrg		ParserTempData.CommandSpecific.IndexInMasterTable=IndexInMasterTable;
155209ff23fSmrg		ParserTempData.Multipurpose.CurrentPort=ATI_RegsPort;
156209ff23fSmrg		ParserTempData.CurrentPortID=INDIRECT_IO_MM;
157209ff23fSmrg		ParserTempData.CurrentRegBlock=0;
158209ff23fSmrg		ParserTempData.CurrentFB_Window=0;
159209ff23fSmrg    prevWorkingTableData=NULL;
160209ff23fSmrg		ParserTempData.Status=CD_CALL_TABLE;
161209ff23fSmrg
162209ff23fSmrg		do{
163209ff23fSmrg
164209ff23fSmrg			if (ParserTempData.Status==CD_CALL_TABLE)
165209ff23fSmrg      {
166209ff23fSmrg				IndexInMasterTable=ParserTempData.CommandSpecific.IndexInMasterTable;
167209ff23fSmrg				if(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]!=0)  // if the offset is not ZERO
168209ff23fSmrg					{
169209ff23fSmrg#ifndef		UEFI_BUILD
170209ff23fSmrg  					ParserTempData.pWorkingTableData =(WORKING_TABLE_DATA STACK_BASED*) AllocateWorkSpace(pDeviceData,
171209ff23fSmrg								((ATOM_COMMON_ROM_COMMAND_TABLE_HEADER*)(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]+pDeviceData->pBIOS_Image))->TableAttribute.WS_SizeInBytes+sizeof(WORKING_TABLE_DATA));
172209ff23fSmrg#else
173209ff23fSmrg  					ParserTempData.pWorkingTableData =(WORKING_TABLE_DATA STACK_BASED*) AllocateWorkSpace(pDeviceData,
174209ff23fSmrg								((ATOM_COMMON_ROM_COMMAND_TABLE_HEADER*)(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]))->TableAttribute.WS_SizeInBytes+sizeof(WORKING_TABLE_DATA));
175209ff23fSmrg#endif
176209ff23fSmrg            if (ParserTempData.pWorkingTableData!=NULL)
177209ff23fSmrg            {
178209ff23fSmrg						  ParserTempData.pWorkingTableData->pWorkSpace=(WORKSPACE_POINTER STACK_BASED*)((UINT8*)ParserTempData.pWorkingTableData+sizeof(WORKING_TABLE_DATA));
179209ff23fSmrg#ifndef		UEFI_BUILD
180209ff23fSmrg						  ParserTempData.pWorkingTableData->pTableHead  = (UINT8 *)(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]+pDeviceData->pBIOS_Image);
181209ff23fSmrg#else
182209ff23fSmrg						  ParserTempData.pWorkingTableData->pTableHead  = (UINT8 *)(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]);
183209ff23fSmrg#endif
184209ff23fSmrg	 					  ParserTempData.pWorkingTableData->IP=((UINT8*)ParserTempData.pWorkingTableData->pTableHead)+sizeof(ATOM_COMMON_ROM_COMMAND_TABLE_HEADER);
185209ff23fSmrg              ParserTempData.pWorkingTableData->prevWorkingTableData=prevWorkingTableData;
186209ff23fSmrg              prevWorkingTableData=ParserTempData.pWorkingTableData;
187209ff23fSmrg              ParserTempData.Status = CD_SUCCESS;
188209ff23fSmrg            } else ParserTempData.Status = CD_UNEXPECTED_BEHAVIOR;
189209ff23fSmrg					} else ParserTempData.Status = CD_EXEC_TABLE_NOT_FOUND;
190209ff23fSmrg			}
191209ff23fSmrg			if (!CD_ERROR(ParserTempData.Status))
192209ff23fSmrg			{
193209ff23fSmrg        ParserTempData.Status = CD_SUCCESS;
194209ff23fSmrg				while (!CD_ERROR_OR_COMPLETED(ParserTempData.Status))
195209ff23fSmrg        {
196209ff23fSmrg
197209ff23fSmrg					if (IS_COMMAND_VALID(((COMMAND_HEADER*)ParserTempData.pWorkingTableData->IP)->Opcode))
198209ff23fSmrg          {
199209ff23fSmrg						ParserTempData.pCmd = (GENERIC_ATTRIBUTE_COMMAND*)ParserTempData.pWorkingTableData->IP;
200209ff23fSmrg
201209ff23fSmrg						if (IS_END_OF_TABLE(((COMMAND_HEADER*)ParserTempData.pWorkingTableData->IP)->Opcode))
202209ff23fSmrg						{
203209ff23fSmrg							ParserTempData.Status=CD_COMPLETED;
204209ff23fSmrg              prevWorkingTableData=ParserTempData.pWorkingTableData->prevWorkingTableData;
205209ff23fSmrg
206209ff23fSmrg							FreeWorkSpace(pDeviceData, ParserTempData.pWorkingTableData);
207209ff23fSmrg              ParserTempData.pWorkingTableData=prevWorkingTableData;
208209ff23fSmrg              if (prevWorkingTableData!=NULL)
209209ff23fSmrg              {
210209ff23fSmrg							  ParserTempData.pDeviceData->pParameterSpace-=
211209ff23fSmrg								  		(((ATOM_COMMON_ROM_COMMAND_TABLE_HEADER*)ParserTempData.pWorkingTableData->
212209ff23fSmrg									  		pTableHead)->TableAttribute.PS_SizeInBytes>>2);
213209ff23fSmrg              }
214209ff23fSmrg						// if there is a parent table where to return, then restore PS_pointer to the original state
215209ff23fSmrg						}
216209ff23fSmrg						else
217209ff23fSmrg						{
218209ff23fSmrg              IndexInMasterTable=ProcessCommandProperties((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData);
219209ff23fSmrg							(*CallTable[IndexInMasterTable].function)((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData);
220209ff23fSmrg#if (PARSER_TYPE!=DRIVER_TYPE_PARSER)
221209ff23fSmrg              BIOS_STACK_MODIFIER();
222209ff23fSmrg#endif
223209ff23fSmrg						}
224209ff23fSmrg					}
225209ff23fSmrg					else
226209ff23fSmrg					{
227209ff23fSmrg						ParserTempData.Status=CD_INVALID_OPCODE;
228209ff23fSmrg						break;
229209ff23fSmrg					}
230209ff23fSmrg
231209ff23fSmrg				}	// while
232209ff23fSmrg			}	// if
233209ff23fSmrg			else
234209ff23fSmrg				break;
235209ff23fSmrg		} while (prevWorkingTableData!=NULL);
236209ff23fSmrg    if (ParserTempData.Status == CD_COMPLETED) return CD_SUCCESS;
237209ff23fSmrg		return ParserTempData.Status;
238209ff23fSmrg	} else return CD_SUCCESS;
239209ff23fSmrg}
240209ff23fSmrg
241209ff23fSmrg// EOF
242209ff23fSmrg
243