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