1/* 2 * Copyright 2006-2007 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23/** 24 25Module Name: 26 27 Decoder.c 28 29Abstract: 30 31 Commands Decoder 32 33Revision History: 34 35 NEG:24.09.2002 Initiated. 36--*/ 37 38#ifdef HAVE_CONFIG_H 39#include "config.h" 40#endif 41 42#include <X11/Xos.h> 43#include "xorg-server.h" 44 45#include "Decoder.h" 46 47#ifndef DISABLE_EASF 48 #include "easf.h" 49#endif 50 51 52 53#define INDIRECT_IO_TABLE (((UINT16)(ULONG_PTR)&((ATOM_MASTER_LIST_OF_DATA_TABLES*)0)->IndirectIOAccess)/sizeof(TABLE_UNIT_TYPE) ) 54extern COMMANDS_PROPERTIES CallTable[]; 55 56 57UINT8 ProcessCommandProperties(PARSER_TEMP_DATA STACK_BASED * pParserTempData) 58{ 59 UINT8 opcode=((COMMAND_HEADER*)pParserTempData->pWorkingTableData->IP)->Opcode; 60 pParserTempData->pWorkingTableData->IP+=CallTable[opcode].headersize; 61 pParserTempData->ParametersType.Destination=CallTable[opcode].destination; 62 pParserTempData->ParametersType.Source = pParserTempData->pCmd->Header.Attribute.Source; 63 pParserTempData->CD_Mask.SrcAlignment=pParserTempData->pCmd->Header.Attribute.SourceAlignment; 64 pParserTempData->CD_Mask.DestAlignment=pParserTempData->pCmd->Header.Attribute.DestinationAlignment; 65 return opcode; 66} 67 68UINT16* GetCommandMasterTablePointer(DEVICE_DATA STACK_BASED* pDeviceData) 69{ 70 UINT16 *MasterTableOffset; 71#ifndef DISABLE_EASF 72 if (pDeviceData->format == TABLE_FORMAT_EASF) 73 { 74 /* 75 make MasterTableOffset point to EASF_ASIC_SETUP_TABLE structure, including usSize. 76 */ 77 MasterTableOffset = (UINT16 *) (pDeviceData->pBIOS_Image+(UINT16LE_TO_CPU(((EASF_ASIC_DESCRIPTOR*)pDeviceData->pBIOS_Image)->usAsicSetupTable_Offset)); 78 } else 79#endif 80 { 81#ifndef UEFI_BUILD 82 MasterTableOffset = (UINT16 *)(UINT16LE_TO_CPU(*(UINT16 *)(pDeviceData->pBIOS_Image+OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)) + pDeviceData->pBIOS_Image); 83 MasterTableOffset = (UINT16 *)((ULONG)UINT16LE_TO_CPU(((ATOM_ROM_HEADER *)MasterTableOffset)->usMasterCommandTableOffset) + pDeviceData->pBIOS_Image ); 84 MasterTableOffset =(UINT16 *) &(((ATOM_MASTER_COMMAND_TABLE *)MasterTableOffset)->ListOfCommandTables); 85#else 86 MasterTableOffset = (UINT16 *)(&(GetCommandMasterTable( )->ListOfCommandTables)); 87#endif 88 } 89 return MasterTableOffset; 90} 91 92UINT16* GetDataMasterTablePointer(DEVICE_DATA STACK_BASED* pDeviceData) 93{ 94 UINT16 *MasterTableOffset; 95 96#ifndef UEFI_BUILD 97 MasterTableOffset = (UINT16 *)(UINT16LE_TO_CPU(*(UINT16 *)(pDeviceData->pBIOS_Image+OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)) + pDeviceData->pBIOS_Image); 98 MasterTableOffset = (UINT16 *)((ULONG)(UINT16LE_TO_CPU(((ATOM_ROM_HEADER *)MasterTableOffset)->usMasterDataTableOffset)) + pDeviceData->pBIOS_Image ); 99 MasterTableOffset =(UINT16 *) &(((ATOM_MASTER_DATA_TABLE *)MasterTableOffset)->ListOfDataTables); 100#else 101 MasterTableOffset = (UINT16 *)(&(GetDataMasterTable( )->ListOfDataTables)); 102#endif 103 return MasterTableOffset; 104} 105 106 107UINT8 GetTrueIndexInMasterTable(PARSER_TEMP_DATA STACK_BASED * pParserTempData, UINT8 IndexInMasterTable) 108{ 109#ifndef DISABLE_EASF 110 UINT16 i; 111 if ( pParserTempData->pDeviceData->format == TABLE_FORMAT_EASF) 112 { 113/* 114 Consider EASF_ASIC_SETUP_TABLE structure pointed by pParserTempData->pCmd as UINT16[] 115 ((UINT16*)pParserTempData->pCmd)[0] = EASF_ASIC_SETUP_TABLE.usSize; 116 ((UINT16*)pParserTempData->pCmd)[1+n*4] = usFunctionID; 117 usFunctionID has to be shifted left by 2 before compare it to the value provided by caller. 118*/ 119 for (i=1; (i < ((UINT16*)pParserTempData->pCmd)[0] >> 1);i+=4) 120 if ((UINT8)(((UINT16*)pParserTempData->pCmd)[i] << 2)==(IndexInMasterTable & EASF_TABLE_INDEX_MASK)) return (i+1+(IndexInMasterTable & EASF_TABLE_ATTR_MASK)); 121 return 1; 122 } else 123#endif 124 { 125 return IndexInMasterTable; 126 } 127} 128 129ATOM_TABLE_ATTRIBUTE GetCommandTableAttribute(UINT8 *pTableHeader) 130{ 131 ATOM_TABLE_ATTRIBUTE_ACCESS lTableAccess; 132 133 /* It's unclear whether this union trick breaks C aliasing rules, 134 * however, it's explicitely permitted by gcc, and we have other 135 * case where the code relies on a union being accessed by either 136 * of the "ways" and stay consistent so if a compiler breaks this 137 * assumption, it will probably need us to compile without strict 138 * aliasing enforcement 139 */ 140 lTableAccess.sbfAccess = ((ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *)pTableHeader)->TableAttribute; 141 lTableAccess.susAccess = UINT16LE_TO_CPU(lTableAccess.susAccess); 142 143 return lTableAccess.sbfAccess; 144} 145 146CD_STATUS ParseTable(DEVICE_DATA STACK_BASED* pDeviceData, UINT8 IndexInMasterTable) 147{ 148 PARSER_TEMP_DATA ParserTempData; 149 WORKING_TABLE_DATA STACK_BASED* prevWorkingTableData; 150 151 memset(&ParserTempData, 0, sizeof(PARSER_TEMP_DATA)); 152 ParserTempData.pDeviceData=(DEVICE_DATA*)pDeviceData; 153#ifndef DISABLE_EASF 154 if (pDeviceData->format == TABLE_FORMAT_EASF) 155 { 156 ParserTempData.IndirectIOTablePointer = 0; 157 } else 158#endif 159 { 160 ParserTempData.pCmd=(GENERIC_ATTRIBUTE_COMMAND*)GetDataMasterTablePointer(pDeviceData); 161 ParserTempData.IndirectIOTablePointer=(UINT8*)((ULONG)(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[INDIRECT_IO_TABLE])) + pDeviceData->pBIOS_Image); 162 ParserTempData.IndirectIOTablePointer+=sizeof(ATOM_COMMON_TABLE_HEADER); 163 } 164 165 ParserTempData.pCmd=(GENERIC_ATTRIBUTE_COMMAND*)GetCommandMasterTablePointer(pDeviceData); 166 IndexInMasterTable=GetTrueIndexInMasterTable((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData,IndexInMasterTable); 167 if(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]!=0 ) // if the offset is not ZERO 168 { 169 ParserTempData.CommandSpecific.IndexInMasterTable=IndexInMasterTable; 170 ParserTempData.Multipurpose.CurrentPort=ATI_RegsPort; 171 ParserTempData.CurrentPortID=INDIRECT_IO_MM; 172 ParserTempData.CurrentRegBlock=0; 173 ParserTempData.CurrentFB_Window=0; 174 prevWorkingTableData=NULL; 175 ParserTempData.Status=CD_CALL_TABLE; 176 177 do{ 178 179 if (ParserTempData.Status==CD_CALL_TABLE) 180 { 181 IndexInMasterTable=ParserTempData.CommandSpecific.IndexInMasterTable; 182 if(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]!=0) // if the offset is not ZERO 183 { 184 ATOM_TABLE_ATTRIBUTE lTableAttr; 185 lTableAttr = GetCommandTableAttribute(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable])+pDeviceData->pBIOS_Image); 186#ifndef UEFI_BUILD 187 ParserTempData.pWorkingTableData =(WORKING_TABLE_DATA STACK_BASED*) AllocateWorkSpace(pDeviceData, 188 lTableAttr.WS_SizeInBytes+sizeof(WORKING_TABLE_DATA)); 189#else 190 ParserTempData.pWorkingTableData =(WORKING_TABLE_DATA STACK_BASED*) AllocateWorkSpace(pDeviceData, 191 lTableAttr.WS_SizeInBytes+sizeof(WORKING_TABLE_DATA)); 192#endif 193 if (ParserTempData.pWorkingTableData!=NULL) 194 { 195 ParserTempData.pWorkingTableData->pWorkSpace=(WORKSPACE_POINTER STACK_BASED*)((UINT8*)ParserTempData.pWorkingTableData+sizeof(WORKING_TABLE_DATA)); 196#ifndef UEFI_BUILD 197 ParserTempData.pWorkingTableData->pTableHead = (UINT8 *)(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable])+pDeviceData->pBIOS_Image); 198#else 199 ParserTempData.pWorkingTableData->pTableHead = (UINT8 *)(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable])); 200#endif 201 ParserTempData.pWorkingTableData->IP=((UINT8*)ParserTempData.pWorkingTableData->pTableHead)+sizeof(ATOM_COMMON_ROM_COMMAND_TABLE_HEADER); 202 ParserTempData.pWorkingTableData->prevWorkingTableData=prevWorkingTableData; 203 prevWorkingTableData=ParserTempData.pWorkingTableData; 204 ParserTempData.Status = CD_SUCCESS; 205 } else ParserTempData.Status = CD_UNEXPECTED_BEHAVIOR; 206 } else ParserTempData.Status = CD_EXEC_TABLE_NOT_FOUND; 207 } 208 if (!CD_ERROR(ParserTempData.Status)) 209 { 210 ParserTempData.Status = CD_SUCCESS; 211 while (!CD_ERROR_OR_COMPLETED(ParserTempData.Status)) 212 { 213 if (IS_COMMAND_VALID(((COMMAND_HEADER*)ParserTempData.pWorkingTableData->IP)->Opcode)) 214 { 215 ParserTempData.pCmd = (GENERIC_ATTRIBUTE_COMMAND*)ParserTempData.pWorkingTableData->IP; 216 217 if (IS_END_OF_TABLE(((COMMAND_HEADER*)ParserTempData.pWorkingTableData->IP)->Opcode)) 218 { 219 ParserTempData.Status=CD_COMPLETED; 220 prevWorkingTableData=ParserTempData.pWorkingTableData->prevWorkingTableData; 221 222 FreeWorkSpace(pDeviceData, ParserTempData.pWorkingTableData); 223 ParserTempData.pWorkingTableData=prevWorkingTableData; 224 if (prevWorkingTableData!=NULL) 225 { 226 ATOM_TABLE_ATTRIBUTE lTableAttr; 227 lTableAttr = GetCommandTableAttribute(ParserTempData.pWorkingTableData->pTableHead); 228 ParserTempData.pDeviceData->pParameterSpace-=(lTableAttr.PS_SizeInBytes>>2); 229 } 230 // if there is a parent table where to return, then restore PS_pointer to the original state 231 } 232 else 233 { 234 IndexInMasterTable=ProcessCommandProperties((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData); 235 (*CallTable[IndexInMasterTable].function)((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData); 236#if (PARSER_TYPE!=DRIVER_TYPE_PARSER) 237 BIOS_STACK_MODIFIER(); 238#endif 239 } 240 } 241 else 242 { 243 ParserTempData.Status=CD_INVALID_OPCODE; 244 break; 245 } 246 247 } // while 248 } // if 249 else 250 break; 251 } while (prevWorkingTableData!=NULL); 252 if (ParserTempData.Status == CD_COMPLETED) return CD_SUCCESS; 253 return ParserTempData.Status; 254 } else return CD_SUCCESS; 255} 256 257// EOF 258 259