diff options
author | Egbert Eich <eich@freedesktop.org> | 2008-08-12 08:53:21 +0200 |
---|---|---|
committer | Egbert Eich <eich@freedesktop.org> | 2008-08-12 08:53:21 +0200 |
commit | 41a36f3047e31ebede8d6027d70176c753cdabe9 (patch) | |
tree | ce829661402d0970f5bc64abe16511391058e12a | |
parent | f5b0d7c452fd49e8581485b5a8efc7a0ad37ba9f (diff) |
AtomBIOS: Check all lists if a register has already been saved.atombios_support
This is the proper fix to the problem 'hot-fixed' in
f5b0d7c452fd49e8581485b5a8efc7a0ad37ba9f.
It we record all save lists (ie. lists from all subsystems) that have been
used and check them all if a register has already been saved.
This saves us from saving a register twice (the second time with an already
modified value) in which case restore becomes very order dependent.
-rw-r--r-- | src/rhd_atombios.c | 115 | ||||
-rw-r--r-- | src/rhd_driver.c | 2 |
2 files changed, 100 insertions, 17 deletions
diff --git a/src/rhd_atombios.c b/src/rhd_atombios.c index 576d6f5..c0c9653 100644 --- a/src/rhd_atombios.c +++ b/src/rhd_atombios.c @@ -342,7 +342,7 @@ typedef struct _atomDataTables ATOM_POWER_SOURCE_INFO *PowerSourceInfo; } atomDataTables, *atomDataTablesPtr; -struct atomRegisterSaveList +struct atomSaveListRecord { /* header */ int Length; @@ -354,6 +354,12 @@ struct atomRegisterSaveList } RegisterList[1]; }; +struct atomSaveListObject +{ + struct atomSaveListObject *next; + struct atomSaveListRecord **SaveList; +}; + typedef struct _atomBiosHandle { int scrnIndex; unsigned char *BIOSBase; @@ -362,7 +368,8 @@ typedef struct _atomBiosHandle { CARD32 fbBase; unsigned int BIOSImageSize; unsigned char *codeTable; - struct atomRegisterSaveList **SaveList; + struct atomSaveListRecord **SaveList; + struct atomSaveListObject *SaveListObjects; } atomBiosHandleRec; enum { @@ -713,9 +720,9 @@ rhdAtomASICInit(atomBiosHandlePtr handle) data.exec.dataSpace = NULL; data.exec.index = GetIndexIntoMasterTable(COMMAND, ASIC_Init); data.exec.pspace = &asicInit; - + xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling ASIC Init\n"); - atomDebugPrintPspace(handle, &data, sizeof(ASIC_INIT_PS_ALLOCATION)); + atomDebugPrintPspace(handle, &data, sizeof(asicInit)); if (RHDAtomBiosFunc(handle->scrnIndex, handle, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { xf86DrvMsg(handle->scrnIndex, X_INFO, "ASIC_INIT Successful\n"); @@ -775,7 +782,7 @@ rhdAtomSetScaler(atomBiosHandlePtr handle, enum atomScaler scalerID, enum atomSc data.exec.dataSpace = NULL; data.exec.index = GetIndexIntoMasterTable(COMMAND, EnableScaler); data.exec.pspace = &scaler; - atomDebugPrintPspace(handle, &data, sizeof(ENABLE_SCALER_PARAMETERS)); + atomDebugPrintPspace(handle, &data, sizeof(scaler)); xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling EnableScaler\n"); if (RHDAtomBiosFunc(handle->scrnIndex, handle, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { @@ -817,7 +824,7 @@ rhdAtomSetTVEncoder(atomBiosHandlePtr handle, Bool enable, int mode) data.exec.index = GetIndexIntoMasterTable(COMMAND, TVEncoderControl); xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling SetTVEncoder\n"); - atomDebugPrintPspace(handle, &data, sizeof(TV_ENCODER_CONTROL_PS_ALLOCATION)); + atomDebugPrintPspace(handle, &data, sizeof(tvEncoder)); if (RHDAtomBiosFunc(handle->scrnIndex, handle, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { xf86DrvMsg(handle->scrnIndex, X_INFO, "SetTVEncoder Successful\n"); @@ -962,7 +969,7 @@ rhdAtomDigTransmitterControl(atomBiosHandlePtr handle, enum atomTransmitter id, data.exec.pspace = &Transmitter; xf86DrvMsg(handle->scrnIndex, X_INFO, "Calling %s\n",name); - atomDebugPrintPspace(handle, &data, sizeof(DIG_TRANSMITTER_CONTROL_PARAMETERS)); + atomDebugPrintPspace(handle, &data, sizeof(Transmitter)); if (RHDAtomBiosFunc(handle->scrnIndex, handle, ATOMBIOS_EXEC, &data) == ATOM_SUCCESS) { xf86DrvMsg(handle->scrnIndex, X_INFO, "%s Successful\n",name); @@ -2661,6 +2668,7 @@ rhdAtomInit(atomBiosHandlePtr unused1, AtomBiosRequestID unused2, handle->scrnIndex = scrnIndex; handle->BIOSImageSize = BIOSImageSize; handle->codeTable = codeTable; + handle->SaveListObjects = NULL; # ifdef ATOM_BIOS_PARSER /* Try to find out if BIOS has been posted (either by system or int10 */ @@ -4769,21 +4777,78 @@ RHDAtomBiosFunc(int scrnIndex, atomBiosHandlePtr handle, return ret; } +/* + * + */ +static void +atomRegisterSaveList(atomBiosHandlePtr handle, struct atomSaveListRecord **SaveList) +{ + struct atomSaveListObject *ListObject = handle->SaveListObjects; + RHDFUNC(handle); + while (ListObject) { + if (ListObject->SaveList == SaveList) + return; + ListObject = ListObject->next; + } + if (!(ListObject = (struct atomSaveListObject *)xcalloc(1,sizeof (struct atomSaveListObject)))) + return; + ListObject->next = handle->SaveListObjects; + ListObject->SaveList = SaveList; + handle->SaveListObjects = ListObject; +} + +/* + * + */ +static void +atomUnregisterSaveList(atomBiosHandlePtr handle, struct atomSaveListRecord **SaveList) +{ + struct atomSaveListObject **ListObject; + RHDFUNC(handle); + + if (!handle->SaveListObjects) + return; + ListObject = &handle->SaveListObjects; + + while (1) { + if ((*ListObject)->SaveList == SaveList) { + struct atomSaveListObject *tmp = *ListObject; + *ListObject = ((*ListObject)->next); + xfree(tmp); + } + if (!(*ListObject) || !(*ListObject)->next) + return; + ListObject = &((*ListObject)->next); + } +} + +/* + * + */ static AtomBiosResult atomSetRegisterListLocation(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosArgPtr data) { - handle->SaveList = (struct atomRegisterSaveList **)data->Address; + RHDFUNC(handle); + + handle->SaveList = (struct atomSaveListRecord **)data->Address; + if (handle->SaveList) + atomRegisterSaveList(handle, handle->SaveList); return ATOM_SUCCESS; } +/* + * + */ static AtomBiosResult atomRestoreRegisters(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosArgPtr data) { - struct atomRegisterSaveList *List = *(data->Address); + struct atomSaveListRecord *List = *(data->Address); int i; + RHDFUNC(handle); + if (!List) return ATOM_FAILED; @@ -4824,6 +4889,7 @@ atomRestoreRegisters(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosA } /* deallocate list */ + atomUnregisterSaveList(handle, (struct atomSaveListRecord **)data->Address); xfree(List); *(data->Address) = NULL; @@ -4834,25 +4900,31 @@ atomRestoreRegisters(atomBiosHandlePtr handle, AtomBiosRequestID func, AtomBiosA #define ALLOC_CNT 25 +/* + * + */ static void atomSaveRegisters(atomBiosHandlePtr handle, enum atomRegisterType Type, CARD32 address) { - struct atomRegisterSaveList *List; + struct atomSaveListRecord *List; CARD32 val = 0; int i; + struct atomSaveListObject *SaveListObj = handle->SaveListObjects; + + RHDFUNC(handle); if (!handle->SaveList) return; if (!(*(handle->SaveList))) { - if (!(*handle->SaveList = (struct atomRegisterSaveList *)xalloc(sizeof(struct atomRegisterSaveList) + if (!(*handle->SaveList = (struct atomSaveListRecord *)xalloc(sizeof(struct atomSaveListRecord) + sizeof(struct atomRegisterList) * (ALLOC_CNT - 1)))) return; (*(handle->SaveList))->Length = ALLOC_CNT; (*(handle->SaveList))->Last = 0; } else if ((*(handle->SaveList))->Length == (*(handle->SaveList))->Last) { - if (!(List = (struct atomRegisterSaveList *)xrealloc(*handle->SaveList, - sizeof(struct atomRegisterSaveList) + if (!(List = (struct atomSaveListRecord *)xrealloc(*handle->SaveList, + sizeof(struct atomSaveListRecord) + (sizeof(struct atomRegisterList) * ((*(handle->SaveList))->Length + ALLOC_CNT - 1))))) return; @@ -4861,9 +4933,17 @@ atomSaveRegisters(atomBiosHandlePtr handle, enum atomRegisterType Type, CARD32 a } List = *handle->SaveList; - for (i = 0; i < List->Last; i++) - if (List->RegisterList[i].Address == address) - return; + while (SaveListObj) { + struct atomSaveListRecord *ListFromObj = *(SaveListObj->SaveList); + + ASSERT(ListFromObj); + + for (i = 0; i < ListFromObj->Last; i++) + if (ListFromObj->RegisterList[i].Address == address + && ListFromObj->RegisterList[i].Type == Type) + return; + SaveListObj = SaveListObj->next; + } switch (Type) { case atomRegisterMMIO: @@ -4897,6 +4977,9 @@ atomSaveRegisters(atomBiosHandlePtr handle, enum atomRegisterType Type, CARD32 a List->Last++; } +/* + * + */ VOID* CailAllocateMemory(VOID *CAIL,UINT16 size) { diff --git a/src/rhd_driver.c b/src/rhd_driver.c index f9b9525..3bb772b 100644 --- a/src/rhd_driver.c +++ b/src/rhd_driver.c @@ -2183,8 +2183,8 @@ rhdRestore(RHDPtr rhdPtr) RHDVGARestore(rhdPtr); - RHDCrtcRestore(rhdPtr->Crtc[1]); RHDCrtcRestore(rhdPtr->Crtc[0]); + RHDCrtcRestore(rhdPtr->Crtc[1]); RHDOutputsRestore(rhdPtr); #ifdef ATOM_BIOS |