Logo Search packages:      
Sourcecode: xserver-xorg-video-ati version File versions

Decoder.c

/*
 * Copyright 2006-2007 Advanced Micro Devices, Inc.  
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**

Module Name:

    Decoder.c
    
Abstract:

            Commands Decoder

Revision History:

      NEG:24.09.2002    Initiated.
--*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <X11/Xos.h>
#include "xorg-server.h"

#include "Decoder.h"

#ifndef DISABLE_EASF
      #include "easf.h"
#endif



#define INDIRECT_IO_TABLE (((UINT16)(ULONG_PTR)&((ATOM_MASTER_LIST_OF_DATA_TABLES*)0)->IndirectIOAccess)/sizeof(TABLE_UNIT_TYPE) )
extern COMMANDS_PROPERTIES CallTable[];


UINT8 ProcessCommandProperties(PARSER_TEMP_DATA STACK_BASED *     pParserTempData)
{
  UINT8 opcode=((COMMAND_HEADER*)pParserTempData->pWorkingTableData->IP)->Opcode;
  pParserTempData->pWorkingTableData->IP+=CallTable[opcode].headersize;
  pParserTempData->ParametersType.Destination=CallTable[opcode].destination;
  pParserTempData->ParametersType.Source = pParserTempData->pCmd->Header.Attribute.Source;
  pParserTempData->CD_Mask.SrcAlignment=pParserTempData->pCmd->Header.Attribute.SourceAlignment;
  pParserTempData->CD_Mask.DestAlignment=pParserTempData->pCmd->Header.Attribute.DestinationAlignment;
  return opcode;
}

UINT16* GetCommandMasterTablePointer(DEVICE_DATA STACK_BASED*  pDeviceData)
{
      UINT16            *MasterTableOffset;
#ifndef DISABLE_EASF
      if (pDeviceData->format == TABLE_FORMAT_EASF)
      {
    /*
    make MasterTableOffset point to EASF_ASIC_SETUP_TABLE structure, including usSize.
    */
            MasterTableOffset = (UINT16 *) (pDeviceData->pBIOS_Image+(UINT16LE_TO_CPU(((EASF_ASIC_DESCRIPTOR*)pDeviceData->pBIOS_Image)->usAsicSetupTable_Offset));
      } else
#endif
      {
#ifndef           UEFI_BUILD
            MasterTableOffset = (UINT16 *)(UINT16LE_TO_CPU(*(UINT16 *)(pDeviceData->pBIOS_Image+OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)) + pDeviceData->pBIOS_Image);
            MasterTableOffset = (UINT16 *)((ULONG)UINT16LE_TO_CPU(((ATOM_ROM_HEADER *)MasterTableOffset)->usMasterCommandTableOffset) + pDeviceData->pBIOS_Image );
            MasterTableOffset =(UINT16 *) &(((ATOM_MASTER_COMMAND_TABLE *)MasterTableOffset)->ListOfCommandTables);
#else
      MasterTableOffset = (UINT16 *)(&(GetCommandMasterTable( )->ListOfCommandTables));
#endif
      }
      return MasterTableOffset;
}

UINT16* GetDataMasterTablePointer(DEVICE_DATA STACK_BASED*  pDeviceData)
{
      UINT16            *MasterTableOffset;
      
#ifndef           UEFI_BUILD
      MasterTableOffset = (UINT16 *)(UINT16LE_TO_CPU(*(UINT16 *)(pDeviceData->pBIOS_Image+OFFSET_TO_POINTER_TO_ATOM_ROM_HEADER)) + pDeviceData->pBIOS_Image);
      MasterTableOffset = (UINT16 *)((ULONG)(UINT16LE_TO_CPU(((ATOM_ROM_HEADER *)MasterTableOffset)->usMasterDataTableOffset)) + pDeviceData->pBIOS_Image );
      MasterTableOffset =(UINT16 *) &(((ATOM_MASTER_DATA_TABLE *)MasterTableOffset)->ListOfDataTables);
#else
      MasterTableOffset = (UINT16 *)(&(GetDataMasterTable( )->ListOfDataTables));
#endif
      return MasterTableOffset;
}


UINT8 GetTrueIndexInMasterTable(PARSER_TEMP_DATA STACK_BASED * pParserTempData, UINT8 IndexInMasterTable)
{
#ifndef DISABLE_EASF
      UINT16 i;
      if ( pParserTempData->pDeviceData->format == TABLE_FORMAT_EASF)
      {
/*
            Consider EASF_ASIC_SETUP_TABLE structure pointed by pParserTempData->pCmd as UINT16[]
            ((UINT16*)pParserTempData->pCmd)[0] = EASF_ASIC_SETUP_TABLE.usSize;
            ((UINT16*)pParserTempData->pCmd)[1+n*4] = usFunctionID;
            usFunctionID has to be shifted left by 2 before compare it to the value provided by caller.
*/
            for (i=1; (i < ((UINT16*)pParserTempData->pCmd)[0] >> 1);i+=4)
                  if ((UINT8)(((UINT16*)pParserTempData->pCmd)[i] << 2)==(IndexInMasterTable & EASF_TABLE_INDEX_MASK)) return (i+1+(IndexInMasterTable & EASF_TABLE_ATTR_MASK));
            return 1;
      } else
#endif
      {
            return IndexInMasterTable;
      }
}

ATOM_TABLE_ATTRIBUTE GetCommandTableAttribute(UINT8 *pTableHeader)
{
  ATOM_TABLE_ATTRIBUTE_ACCESS lTableAccess;

  /* It's unclear whether this union trick breaks C aliasing rules,
   * however, it's explicitely permitted by gcc, and we have other
   * case where the code relies on a union being accessed by either
   * of the "ways" and stay consistent so if a compiler breaks this
   * assumption, it will probably need us to compile without strict
   * aliasing enforcement
       */
      lTableAccess.sbfAccess = ((ATOM_COMMON_ROM_COMMAND_TABLE_HEADER *)pTableHeader)->TableAttribute;
      lTableAccess.susAccess = UINT16LE_TO_CPU(lTableAccess.susAccess);

      return lTableAccess.sbfAccess;
}

CD_STATUS ParseTable(DEVICE_DATA STACK_BASED* pDeviceData, UINT8 IndexInMasterTable)
{
      PARSER_TEMP_DATA  ParserTempData;
  WORKING_TABLE_DATA STACK_BASED* prevWorkingTableData;

  memset(&ParserTempData, 0, sizeof(PARSER_TEMP_DATA));
  ParserTempData.pDeviceData=(DEVICE_DATA*)pDeviceData;
#ifndef DISABLE_EASF
  if (pDeviceData->format == TABLE_FORMAT_EASF)
  {
      ParserTempData.IndirectIOTablePointer = 0;
  } else
#endif
  {
    ParserTempData.pCmd=(GENERIC_ATTRIBUTE_COMMAND*)GetDataMasterTablePointer(pDeviceData);
    ParserTempData.IndirectIOTablePointer=(UINT8*)((ULONG)(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[INDIRECT_IO_TABLE])) + pDeviceData->pBIOS_Image);
    ParserTempData.IndirectIOTablePointer+=sizeof(ATOM_COMMON_TABLE_HEADER);
  }

      ParserTempData.pCmd=(GENERIC_ATTRIBUTE_COMMAND*)GetCommandMasterTablePointer(pDeviceData);
    IndexInMasterTable=GetTrueIndexInMasterTable((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData,IndexInMasterTable);
      if(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]!=0 )  // if the offset is not ZERO
      {
            ParserTempData.CommandSpecific.IndexInMasterTable=IndexInMasterTable;
            ParserTempData.Multipurpose.CurrentPort=ATI_RegsPort;
            ParserTempData.CurrentPortID=INDIRECT_IO_MM;
            ParserTempData.CurrentRegBlock=0;
            ParserTempData.CurrentFB_Window=0;
    prevWorkingTableData=NULL;
            ParserTempData.Status=CD_CALL_TABLE;

            do{
                  
                  if (ParserTempData.Status==CD_CALL_TABLE)
                  {
                        IndexInMasterTable=ParserTempData.CommandSpecific.IndexInMasterTable;
                        if(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]!=0)  // if the offset is not ZERO
                        {
                          ATOM_TABLE_ATTRIBUTE lTableAttr;
                          lTableAttr = GetCommandTableAttribute(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable])+pDeviceData->pBIOS_Image);
#ifndef           UEFI_BUILD
                              ParserTempData.pWorkingTableData =(WORKING_TABLE_DATA STACK_BASED*) AllocateWorkSpace(pDeviceData,
                                                                                                lTableAttr.WS_SizeInBytes+sizeof(WORKING_TABLE_DATA));
#else
                          ParserTempData.pWorkingTableData =(WORKING_TABLE_DATA STACK_BASED*) AllocateWorkSpace(pDeviceData,
                                                                                          lTableAttr.WS_SizeInBytes+sizeof(WORKING_TABLE_DATA));
#endif
                              if (ParserTempData.pWorkingTableData!=NULL)
                              {
                                    ParserTempData.pWorkingTableData->pWorkSpace=(WORKSPACE_POINTER STACK_BASED*)((UINT8*)ParserTempData.pWorkingTableData+sizeof(WORKING_TABLE_DATA));
#ifndef           UEFI_BUILD
                              ParserTempData.pWorkingTableData->pTableHead  = (UINT8 *)(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable])+pDeviceData->pBIOS_Image);
#else
                              ParserTempData.pWorkingTableData->pTableHead  = (UINT8 *)(UINT16LE_TO_CPU(((PTABLE_UNIT_TYPE)ParserTempData.pCmd)[IndexInMasterTable]));
#endif
                                    ParserTempData.pWorkingTableData->IP=((UINT8*)ParserTempData.pWorkingTableData->pTableHead)+sizeof(ATOM_COMMON_ROM_COMMAND_TABLE_HEADER);
                                    ParserTempData.pWorkingTableData->prevWorkingTableData=prevWorkingTableData;
                                    prevWorkingTableData=ParserTempData.pWorkingTableData;
                                    ParserTempData.Status = CD_SUCCESS;
                              } else ParserTempData.Status = CD_UNEXPECTED_BEHAVIOR;
                        } else ParserTempData.Status = CD_EXEC_TABLE_NOT_FOUND;
                  }
                  if (!CD_ERROR(ParserTempData.Status))
                  {
                        ParserTempData.Status = CD_SUCCESS;
                        while (!CD_ERROR_OR_COMPLETED(ParserTempData.Status))  
                        {
                              if (IS_COMMAND_VALID(((COMMAND_HEADER*)ParserTempData.pWorkingTableData->IP)->Opcode))
                              {
                                    ParserTempData.pCmd = (GENERIC_ATTRIBUTE_COMMAND*)ParserTempData.pWorkingTableData->IP;
                                    
                                    if (IS_END_OF_TABLE(((COMMAND_HEADER*)ParserTempData.pWorkingTableData->IP)->Opcode))
                                    {
                                          ParserTempData.Status=CD_COMPLETED;
                                          prevWorkingTableData=ParserTempData.pWorkingTableData->prevWorkingTableData;
                                          
                                          FreeWorkSpace(pDeviceData, ParserTempData.pWorkingTableData);
                                          ParserTempData.pWorkingTableData=prevWorkingTableData;
                                          if (prevWorkingTableData!=NULL)
                                          {
                                                ATOM_TABLE_ATTRIBUTE lTableAttr;
                                                lTableAttr = GetCommandTableAttribute(ParserTempData.pWorkingTableData->pTableHead);
                                                ParserTempData.pDeviceData->pParameterSpace-=(lTableAttr.PS_SizeInBytes>>2);
                                          } 
                                          // if there is a parent table where to return, then restore PS_pointer to the original state
                                    }
                                    else
                                    {
                                          IndexInMasterTable=ProcessCommandProperties((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData);
                                          (*CallTable[IndexInMasterTable].function)((PARSER_TEMP_DATA STACK_BASED *)&ParserTempData);
#if (PARSER_TYPE!=DRIVER_TYPE_PARSER)
                                          BIOS_STACK_MODIFIER();
#endif
                                    }
                              }
                              else
                              {
                                    ParserTempData.Status=CD_INVALID_OPCODE;
                                    break;
                              }
                              
                        }     // while
                  }     // if
                  else
                        break;
            } while (prevWorkingTableData!=NULL);
            if (ParserTempData.Status == CD_COMPLETED) return CD_SUCCESS;
            return ParserTempData.Status;
      } else return CD_SUCCESS;
}

// EOF


Generated by  Doxygen 1.6.0   Back to index