Decoder.c revision b7e1c893
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>
43b7e1c893Smrg#include "xorg-server.h"
44209ff23fSmrg
45209ff23fSmrg#include "Decoder.h"
46209ff23fSmrg
47209ff23fSmrg#ifndef DISABLE_EASF
48209ff23fSmrg	#include "easf.h"
49209ff23fSmrg#endif
50209ff23fSmrg
51209ff23fSmrg
52209ff23fSmrg
53209ff23fSmrg#define INDIRECT_IO_TABLE (((UINT16)(ULONG_PTR)&((ATOM_MASTER_LIST_OF_DATA_TABLES*)0)->IndirectIOAccess)/sizeof(TABLE_UNIT_TYPE) )
54209ff23fSmrgextern COMMANDS_PROPERTIES CallTable[];
55209ff23fSmrg
56209ff23fSmrg
57209ff23fSmrgUINT8 ProcessCommandProperties(PARSER_TEMP_DATA STACK_BASED *	pParserTempData)
58209ff23fSmrg{
59209ff23fSmrg  UINT8 opcode=((COMMAND_HEADER*)pParserTempData->pWorkingTableData->IP)->Opcode;
60209ff23fSmrg  pParserTempData->pWorkingTableData->IP+=CallTable[opcode].headersize;
61209ff23fSmrg  pParserTempData->ParametersType.Destination=CallTable[opcode].destination;
62209ff23fSmrg  pParserTempData->ParametersType.Source = pParserTempData->pCmd->Header.Attribute.Source;
63209ff23fSmrg  pParserTempData->CD_Mask.SrcAlignment=pParserTempData->pCmd->Header.Attribute.SourceAlignment;
64209ff23fSmrg  pParserTempData->CD_Mask.DestAlignment=pParserTempData->pCmd->Header.Attribute.DestinationAlignment;
65209ff23fSmrg  return opcode;
66209ff23fSmrg}
67209ff23fSmrg
68209ff23fSmrgUINT16* GetCommandMasterTablePointer(DEVICE_DATA STACK_BASED*  pDeviceData)
69209ff23fSmrg{
70209ff23fSmrg	UINT16		*MasterTableOffset;
71209ff23fSmrg#ifndef DISABLE_EASF
72209ff23fSmrg	if (pDeviceData->format == TABLE_FORMAT_EASF)
73209ff23fSmrg	{
74209ff23fSmrg    /*
75209ff23fSmrg    make MasterTableOffset point to EASF_ASIC_SETUP_TABLE structure, including usSize.
76209ff23fSmrg    */
77b7e1c893Smrg		MasterTableOffset = (UINT16 *) (pDeviceData->pBIOS_Image+(UINT16LE_TO_CPU(((EASF_ASIC_DESCRIPTOR*)pDeviceData->pBIOS_Image)->usAsicSetupTable_Offset));
78209ff23fSmrg	} else
79209ff23fSmrg#endif
80209ff23fSmrg	{
81209ff23fSmrg#ifndef		UEFI_BUILD
82b7e1c893Smrg		MasterTableOffset = (UINT16 *)(UINT16LE_TO_CPU(*(UINT16 *)(pDeviceData->pBIOS_Image+OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)) + pDeviceData->pBIOS_Image);
83b7e1c893Smrg		MasterTableOffset = (UINT16 *)((ULONG)UINT16LE_TO_CPU(((ATOM_ROM_HEADER *)MasterTableOffset)->usMasterCommandTableOffset) + pDeviceData->pBIOS_Image );
84209ff23fSmrg		MasterTableOffset =(UINT16 *) &(((ATOM_MASTER_COMMAND_TABLE *)MasterTableOffset)->ListOfCommandTables);
85209ff23fSmrg#else
86209ff23fSmrg	MasterTableOffset = (UINT16 *)(&(GetCommandMasterTable( )->ListOfCommandTables));
87209ff23fSmrg#endif
88209ff23fSmrg	}
89209ff23fSmrg	return MasterTableOffset;
90209ff23fSmrg}
91209ff23fSmrg
92209ff23fSmrgUINT16* GetDataMasterTablePointer(DEVICE_DATA STACK_BASED*  pDeviceData)
93209ff23fSmrg{
94209ff23fSmrg	UINT16		*MasterTableOffset;
95209ff23fSmrg
96209ff23fSmrg#ifndef		UEFI_BUILD
97b7e1c893Smrg	MasterTableOffset = (UINT16 *)(UINT16LE_TO_CPU(*(UINT16 *)(pDeviceData->pBIOS_Image+OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)) + pDeviceData->pBIOS_Image);
98b7e1c893Smrg	MasterTableOffset = (UINT16 *)((ULONG)(UINT16LE_TO_CPU(((ATOM_ROM_HEADER *)MasterTableOffset)->usMasterDataTableOffset)) + pDeviceData->pBIOS_Image );
99209ff23fSmrg	MasterTableOffset =(UINT16 *) &(((ATOM_MASTER_DATA_TABLE *)MasterTableOffset)->ListOfDataTables);
100209ff23fSmrg#else
101209ff23fSmrg	MasterTableOffset = (UINT16 *)(&(GetDataMasterTable( )->ListOfDataTables));
102209ff23fSmrg#endif
103209ff23fSmrg	return MasterTableOffset;
104209ff23fSmrg}
105209ff23fSmrg
106209ff23fSmrg
107209ff23fSmrgUINT8 GetTrueIndexInMasterTable(PARSER_TEMP_DATA STACK_BASED * pParserTempData, UINT8 IndexInMasterTable)
108209ff23fSmrg{
109209ff23fSmrg#ifndef DISABLE_EASF
110209ff23fSmrg	UINT16 i;
111209ff23fSmrg	if ( pParserTempData->pDeviceData->format == TABLE_FORMAT_EASF)
112209ff23fSmrg	{
113209ff23fSmrg/*
114209ff23fSmrg		Consider EASF_ASIC_SETUP_TABLE structure pointed by pParserTempData->pCmd as UINT16[]
115209ff23fSmrg		((UINT16*)pParserTempData->pCmd)[0] = EASF_ASIC_SETUP_TABLE.usSize;
116209ff23fSmrg		((UINT16*)pParserTempData->pCmd)[1+n*4] = usFunctionID;
117209ff23fSmrg		usFunctionID has to be shifted left by 2 before compare it to the value provided by caller.
118209ff23fSmrg*/
119209ff23fSmrg		for (i=1; (i < ((UINT16*)pParserTempData->pCmd)[0] >> 1);i+=4)
120209ff23fSmrg	  		if ((UINT8)(((UINT16*)pParserTempData->pCmd)[i] << 2)==(IndexInMasterTable & EASF_TABLE_INDEX_MASK)) return (i+1+(IndexInMasterTable & EASF_TABLE_ATTR_MASK));
121209ff23fSmrg		return 1;
122209ff23fSmrg	} else
123209ff23fSmrg#endif
124209ff23fSmrg	{
125209ff23fSmrg		return IndexInMasterTable;
126209ff23fSmrg	}
127209ff23fSmrg}
128209ff23fSmrg
129b7e1c893SmrgATOM_TABLE_ATTRIBUTE GetCommandTableAttribute(UINT8 *pTableHeader)
130b7e1c893Smrg{
131b7e1c893Smrg  ATOM_TABLE_ATTRIBUTE_ACCESS lTableAccess;
132b7e1c893Smrg
133b7e1c893Smrg  /* It's unclear whether this union trick breaks C aliasing rules,
134b7e1c893Smrg   * however, it's explicitely permitted by gcc, and we have other
135b7e1c893Smrg   * case where the code relies on a union being accessed by either
136b7e1c893Smrg   * of the "ways" and stay consistent so if a compiler breaks this
137b7e1c893Smrg   * assumption, it will probably need us to compile without strict
138b7e1c893Smrg   * aliasing enforcement
139b7e1c893Smrg	 */
140b7e1c893Smrg	lTableAccess.sbfAccess = ((ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *)pTableHeader)->TableAttribute;
141b7e1c893Smrg	lTableAccess.susAccess = UINT16LE_TO_CPU(lTableAccess.susAccess);
142b7e1c893Smrg
143b7e1c893Smrg	return lTableAccess.sbfAccess;
144b7e1c893Smrg}
145b7e1c893Smrg
146209ff23fSmrgCD_STATUS ParseTable(DEVICE_DATA STACK_BASED* pDeviceData, UINT8 IndexInMasterTable)
147209ff23fSmrg{
148209ff23fSmrg	PARSER_TEMP_DATA	ParserTempData;
149209ff23fSmrg  WORKING_TABLE_DATA STACK_BASED* prevWorkingTableData;
150209ff23fSmrg
151b7e1c893Smrg  memset(&ParserTempData, 0, sizeof(PARSER_TEMP_DATA));
152209ff23fSmrg  ParserTempData.pDeviceData=(DEVICE_DATA*)pDeviceData;
153209ff23fSmrg#ifndef DISABLE_EASF
154209ff23fSmrg  if (pDeviceData->format == TABLE_FORMAT_EASF)
155209ff23fSmrg  {
156209ff23fSmrg      ParserTempData.IndirectIOTablePointer = 0;
157209ff23fSmrg  } else
158209ff23fSmrg#endif
159209ff23fSmrg  {
160209ff23fSmrg    ParserTempData.pCmd=(GENERIC_ATTRIBUTE_COMMAND*)GetDataMasterTablePointer(pDeviceData);
161b7e1c893Smrg    ParserTempData.IndirectIOTablePointer=(UINT8*)((ULONG)(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[INDIRECT_IO_TABLE])) + pDeviceData->pBIOS_Image);
162209ff23fSmrg    ParserTempData.IndirectIOTablePointer+=sizeof(ATOM_COMMON_TABLE_HEADER);
163209ff23fSmrg  }
164209ff23fSmrg
165209ff23fSmrg	ParserTempData.pCmd=(GENERIC_ATTRIBUTE_COMMAND*)GetCommandMasterTablePointer(pDeviceData);
166209ff23fSmrg    IndexInMasterTable=GetTrueIndexInMasterTable((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData,IndexInMasterTable);
167209ff23fSmrg	if(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]!=0 )  // if the offset is not ZERO
168209ff23fSmrg	{
169209ff23fSmrg		ParserTempData.CommandSpecific.IndexInMasterTable=IndexInMasterTable;
170209ff23fSmrg		ParserTempData.Multipurpose.CurrentPort=ATI_RegsPort;
171209ff23fSmrg		ParserTempData.CurrentPortID=INDIRECT_IO_MM;
172209ff23fSmrg		ParserTempData.CurrentRegBlock=0;
173209ff23fSmrg		ParserTempData.CurrentFB_Window=0;
174209ff23fSmrg    prevWorkingTableData=NULL;
175209ff23fSmrg		ParserTempData.Status=CD_CALL_TABLE;
176209ff23fSmrg
177209ff23fSmrg		do{
178b7e1c893Smrg
179209ff23fSmrg			if (ParserTempData.Status==CD_CALL_TABLE)
180b7e1c893Smrg			{
181209ff23fSmrg				IndexInMasterTable=ParserTempData.CommandSpecific.IndexInMasterTable;
182209ff23fSmrg				if(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]!=0)  // if the offset is not ZERO
183b7e1c893Smrg				{
184b7e1c893Smrg				  ATOM_TABLE_ATTRIBUTE lTableAttr;
185b7e1c893Smrg				  lTableAttr = GetCommandTableAttribute(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable])+pDeviceData->pBIOS_Image);
186209ff23fSmrg#ifndef		UEFI_BUILD
187209ff23fSmrg  					ParserTempData.pWorkingTableData =(WORKING_TABLE_DATA STACK_BASED*) AllocateWorkSpace(pDeviceData,
188b7e1c893Smrg															      lTableAttr.WS_SizeInBytes+sizeof(WORKING_TABLE_DATA));
189209ff23fSmrg#else
190b7e1c893Smrg				  ParserTempData.pWorkingTableData =(WORKING_TABLE_DATA STACK_BASED*) AllocateWorkSpace(pDeviceData,
191b7e1c893Smrg															lTableAttr.WS_SizeInBytes+sizeof(WORKING_TABLE_DATA));
192209ff23fSmrg#endif
193b7e1c893Smrg					if (ParserTempData.pWorkingTableData!=NULL)
194b7e1c893Smrg					{
195b7e1c893Smrg						ParserTempData.pWorkingTableData->pWorkSpace=(WORKSPACE_POINTER STACK_BASED*)((UINT8*)ParserTempData.pWorkingTableData+sizeof(WORKING_TABLE_DATA));
196209ff23fSmrg#ifndef		UEFI_BUILD
197b7e1c893Smrg				      ParserTempData.pWorkingTableData->pTableHead  = (UINT8 *)(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable])+pDeviceData->pBIOS_Image);
198209ff23fSmrg#else
199b7e1c893Smrg				      ParserTempData.pWorkingTableData->pTableHead  = (UINT8 *)(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]));
200209ff23fSmrg#endif
201b7e1c893Smrg						ParserTempData.pWorkingTableData->IP=((UINT8*)ParserTempData.pWorkingTableData->pTableHead)+sizeof(ATOM_COMMON_ROM_COMMAND_TABLE_HEADER);
202b7e1c893Smrg						ParserTempData.pWorkingTableData->prevWorkingTableData=prevWorkingTableData;
203b7e1c893Smrg						prevWorkingTableData=ParserTempData.pWorkingTableData;
204b7e1c893Smrg						ParserTempData.Status = CD_SUCCESS;
205b7e1c893Smrg					} else ParserTempData.Status = CD_UNEXPECTED_BEHAVIOR;
206b7e1c893Smrg				} else ParserTempData.Status = CD_EXEC_TABLE_NOT_FOUND;
207209ff23fSmrg			}
208209ff23fSmrg			if (!CD_ERROR(ParserTempData.Status))
209209ff23fSmrg			{
210b7e1c893Smrg				ParserTempData.Status = CD_SUCCESS;
211209ff23fSmrg				while (!CD_ERROR_OR_COMPLETED(ParserTempData.Status))
212b7e1c893Smrg				{
213209ff23fSmrg					if (IS_COMMAND_VALID(((COMMAND_HEADER*)ParserTempData.pWorkingTableData->IP)->Opcode))
214b7e1c893Smrg					{
215209ff23fSmrg						ParserTempData.pCmd = (GENERIC_ATTRIBUTE_COMMAND*)ParserTempData.pWorkingTableData->IP;
216b7e1c893Smrg
217209ff23fSmrg						if (IS_END_OF_TABLE(((COMMAND_HEADER*)ParserTempData.pWorkingTableData->IP)->Opcode))
218209ff23fSmrg						{
219209ff23fSmrg							ParserTempData.Status=CD_COMPLETED;
220b7e1c893Smrg							prevWorkingTableData=ParserTempData.pWorkingTableData->prevWorkingTableData;
221b7e1c893Smrg
222209ff23fSmrg							FreeWorkSpace(pDeviceData, ParserTempData.pWorkingTableData);
223b7e1c893Smrg							ParserTempData.pWorkingTableData=prevWorkingTableData;
224b7e1c893Smrg							if (prevWorkingTableData!=NULL)
225b7e1c893Smrg							{
226b7e1c893Smrg								ATOM_TABLE_ATTRIBUTE lTableAttr;
227b7e1c893Smrg								lTableAttr = GetCommandTableAttribute(ParserTempData.pWorkingTableData->pTableHead);
228b7e1c893Smrg								ParserTempData.pDeviceData->pParameterSpace-=(lTableAttr.PS_SizeInBytes>>2);
229b7e1c893Smrg							}
230b7e1c893Smrg							// if there is a parent table where to return, then restore PS_pointer to the original state
231209ff23fSmrg						}
232209ff23fSmrg						else
233209ff23fSmrg						{
234b7e1c893Smrg							IndexInMasterTable=ProcessCommandProperties((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData);
235209ff23fSmrg							(*CallTable[IndexInMasterTable].function)((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData);
236209ff23fSmrg#if (PARSER_TYPE!=DRIVER_TYPE_PARSER)
237b7e1c893Smrg							BIOS_STACK_MODIFIER();
238209ff23fSmrg#endif
239209ff23fSmrg						}
240209ff23fSmrg					}
241209ff23fSmrg					else
242209ff23fSmrg					{
243209ff23fSmrg						ParserTempData.Status=CD_INVALID_OPCODE;
244209ff23fSmrg						break;
245209ff23fSmrg					}
246b7e1c893Smrg
247209ff23fSmrg				}	// while
248209ff23fSmrg			}	// if
249209ff23fSmrg			else
250209ff23fSmrg				break;
251209ff23fSmrg		} while (prevWorkingTableData!=NULL);
252b7e1c893Smrg		if (ParserTempData.Status == CD_COMPLETED) return CD_SUCCESS;
253209ff23fSmrg		return ParserTempData.Status;
254209ff23fSmrg	} else return CD_SUCCESS;
255209ff23fSmrg}
256209ff23fSmrg
257209ff23fSmrg// EOF
258209ff23fSmrg
259