summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEgbert Eich <eich@freedesktop.org>2008-08-12 08:53:21 +0200
committerEgbert Eich <eich@freedesktop.org>2008-08-12 08:53:21 +0200
commit41a36f3047e31ebede8d6027d70176c753cdabe9 (patch)
treece829661402d0970f5bc64abe16511391058e12a
parentf5b0d7c452fd49e8581485b5a8efc7a0ad37ba9f (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.c115
-rw-r--r--src/rhd_driver.c2
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