diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/fw/mips/duosync.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/fw/mips/duosync.c')
-rw-r--r-- | private/ntos/fw/mips/duosync.c | 516 |
1 files changed, 516 insertions, 0 deletions
diff --git a/private/ntos/fw/mips/duosync.c b/private/ntos/fw/mips/duosync.c new file mode 100644 index 000000000..09b515258 --- /dev/null +++ b/private/ntos/fw/mips/duosync.c @@ -0,0 +1,516 @@ +#ifdef DUO +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Module Name: + + duosync.c + +Abstract: + + This module contains the routines that perform synchronization + among processors. + +Author: + + Lluis Abello (lluis) 06-Apr-1993 + +Environment: + + +Revision History: + +--*/ + +#include "fwp.h" +#include "iodevice.h" +#include "led.h" +#include "selfmap.h" +#include "selftest.h" +#include "ioaccess.h" +#include "fwstring.h" + +volatile PROCESSOR_B_TASK_VECTOR ProcessorBTask; +extern BOOLEAN ProcessorBEnabled; + +VOID +InitializePCR( + ); + + + +MEMORY_TEST_DATA BMemTest1 = { + 0xA0100000, + 0x100000, + 0, + LED_B_MEMORY_TEST_1 + }; + + +MEMORY_TEST_DATA BMemTest2 = { + 0x80200000, + 0x100000, + 0, + LED_B_MEMORY_TEST_2 + }; + + +MEMORY_TEST_DATA BMemTest3 = { + VIDEO_MEMORY_VIRTUAL_BASE+1280*1024, // start adr = end of visible screen + 0x200000-1280*1024, // size = rest of video memory. + 0, + LED_VIDEOMEM + }; + +// +// The following table defines the selftest routines that will be executed +// by processor B. +// + +PROCESSOR_B_TEST ProcessorBSelfTests[] = { + {ProcessorBMemoryTest,&BMemTest1}, + {ProcessorBMemoryTest,&BMemTest2}, + {ProcessorBVideoMemoryTest,&BMemTest3}, + {NULL,0} + }; + +ULONG +ExecuteOnProcessorB( + IN PPROCESSOR_TASK_ROUTINE Routine, + IN PVOID Data + ) +/*++ + +Routine Description: + + This routine puts the supplied Routine and Data in processor B task vector + and issues an IP interrupt to processor B which will then execute + it and set the return value. + +Arguments: + + None + +Return Value: + + None + +--*/ + +{ + + PPROCESSOR_B_TASK_VECTOR TaskVector; + + if (!ProcessorBEnabled) { + return 0; + } + + // + // Get a non pointer to the Task Vector + // + TaskVector = (PPROCESSOR_B_TASK_VECTOR)&ProcessorBTask; + + TaskVector->Routine = Routine; + TaskVector->Data = Data; + // + // Issue an IP interrupt to notify processor B that a task has + // been scheduled for execution. + // + WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,2); + + // + // If timeout or Return Value indicates error, stop here. + // + + if (WaitForIpInterrupt(5000) == FALSE) { + FwPrint("\r\nTimeout waiting for B to execute %lx\r\n",Routine); + } + + return (TaskVector->ReturnValue); +} + + +VOID +ProcessorBMain( + ) +/*++ + +Routine Description: + + This is the main routine for processor B. + It jumps here after initialization. + The startup sequence is as follows: + + ProcessorA sets the address of this routine in the ProcessorBTask vector. + ProcessorA Enables Processor B in the Global Configuration register. + ProcessorA Calls WaitForIPInterrupt. + + When Processor B is enabled it runs at the PROM reset vector, it + initializes itself and jumps to the routine pointed to by ProcessorTask + which is this routine. + + Once here processor B Wakes up processor A by issuing an IP interrupt + and Loops for ever waiting for IP interrupts and executing the Task + pointed to by ProcessorBTask. + +Arguments: + + None + +Return Value: + + None + +--*/ + +{ + PPROCESSOR_TASK_ROUTINE Task; + PVOID TaskData; + ULONG ReturnValue; + + // + // Get a pointer to the Task Vector + // + + PPROCESSOR_B_TASK_VECTOR TaskVector = (PPROCESSOR_B_TASK_VECTOR)&ProcessorBTask; + + // + // Enable IP interrupts. + // All interrupts are disabled in the psr. + // + WRITE_REGISTER_ULONG(&DMA_CONTROL->InterruptEnable.Long,ENABLE_IP_INTERRUPTS); + + for (;;) { + + // + // Wake up processor A + // + WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,1); + + WaitForIpInterrupt(0); + + // + // Execute Task + // + Task = TaskVector->Routine; + TaskData = TaskVector->Data; + ReturnValue = Task(TaskData); + TaskVector->ReturnValue = ReturnValue; + } +} + + +ULONG +ProcessorBMemoryTest( + IN PMEMORY_TEST_DATA MemoryData + ) + +/*++ + +Routine Description: + + This routine tests the portion of memory supplied by Data. + +Arguments: + + MemoryData - Pointer to a data structure describing the range of + memory to be tested. + +Return Value: + + None + +--*/ + + +{ + PutLedDisplay(MemoryData->LedDisplayValue); + WriteMemoryAddressTest(MemoryData->StartAddress,MemoryData->Size,MemoryData->XorPattern); + CheckMemoryAddressTest(MemoryData->StartAddress,MemoryData->Size,MemoryData->XorPattern,MemoryData->LedDisplayValue); + return 1; +} + + +ULONG +ProcessorBVideoMemoryTest( + IN PMEMORY_TEST_DATA MemoryData + ) + +/*++ + +Routine Description: + + This routine tests the portion of video memory supplied by Data. + +Arguments: + + MemoryData - Pointer to a data structure describing the range of + memory to be tested. + +Return Value: + + None + +--*/ + + +{ + PutLedDisplay(MemoryData->LedDisplayValue); + WriteVideoMemoryAddressTest(MemoryData->StartAddress,MemoryData->Size); + CheckVideoMemoryAddressTest(MemoryData->StartAddress,MemoryData->Size); + return 1; +} + +ULONG +CoherencyTest( + IN PVOID CoherentPage + ) +/*++ + +Routine Description: + + This routine performs a coherency test. This routine will be executed + simultaneously by both processors. + + Processor A stores even bytes and Processor B stores the odd bytes. + To make sure that cache blocks are passed back and forth, a semaphore + locks it's access so that the cache line ping pongs from processor to + processor. + + +Arguments: + + CoherentPage. Pointer aligned to a page boundary. Which is marked + either Exclusive or Shared in the TLB. + + The first ulong is used as the semaphore. The rest of the page + is used as data. + + +Return Value: + + Number of errors found. + +--*/ + + +{ + volatile PULONG Semaphore = (PULONG)CoherentPage; + PULONG CoherentData = Semaphore+64/sizeof(ULONG); + ULONG Counter; + ULONG Processor; + ULONG DataLong; + ULONG Errors = 0; + if (READ_REGISTER_ULONG(&DMA_CONTROL->WhoAmI.Long)) { + // + // Processor B + // + Processor = 1; + DataLong = 0xB0B00000; + } else { + Processor = 0; + DataLong = 0xA0A00000; + } + + for (Counter = 0; Counter < (0x1000-64)/sizeof(ULONG); Counter += 2) { + + // + // Wait for counter. + // No need for interlocks since each processor waits + // for a different value. + // + + while (*Semaphore != Counter+Processor) { + } + *(CoherentData+Processor) = DataLong | Counter; + *Semaphore = Counter+Processor+1; + CoherentData += 2; + } + + // + // Both processors check all the data. + // + CoherentData = Semaphore+64/sizeof(ULONG);; + for (Counter = 0; Counter < (0x1000-64)/sizeof(ULONG); Counter +=2) { + if (*CoherentData != (Counter | 0xA0A00000)) { + Errors++; + } + CoherentData++; + if (*CoherentData != (Counter | 0xB0B00000)) { + Errors++; + } + CoherentData++; + } + return Errors; +} + + +BOOLEAN +ProcessorBSelftest( + IN VOID + ) +/*++ + +Routine Description: + + This routine sets the different tasks to be executed by processor + b and waits for them to complete. This routine is executed by the + master processor. + +Arguments: + + None. + +Return Value: + + TRUE if passed FALSE otherwise + + +--*/ +{ + BOOLEAN ReturnValue; + BOOLEAN Timeout; + + // + // Get a pointer to the Task Vector + // + PPROCESSOR_B_TASK_VECTOR TaskVector = (PPROCESSOR_B_TASK_VECTOR)&ProcessorBTask; + PPROCESSOR_B_TEST ProcessorBTestList = ProcessorBSelfTests; + + // + // Place each task of the SelftestTable in the TaskVector to be executed + // by processor B. + // + while (ProcessorBTestList->Routine != NULL) { + TaskVector->Routine = ProcessorBTestList->Routine; + TaskVector->Data = ProcessorBTestList->Data; + // + // Issue an IP interrupt to notify processor B that a task has + // been scheduled for execution. + // + WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,2); + + // + // If timeout or Return Value indicates error, stop here. + // + if (((Timeout = WaitForIpInterrupt(5000)) == FALSE) || (TaskVector->ReturnValue == FALSE)) { + if (!Timeout) { + FwPrint("\r\n Wait for Processor B timeout occurred"); + } else { + FwPrint("\r\n Processor B failed a test"); + } + FwPrint(" Failed test = %08lx\r\n", (ULONG)ProcessorBTestList->Routine); + //return FALSE; + } + + // + // Next test. + // + ProcessorBTestList++; + } + + // + // Now perform two CoherencyTest + // + + FwPrint("\r\n Coherency Test."); + ReturnValue = TRUE; + + // + // Zero the page. Set the Task and notify processor B. + // And execute the test simultaneously. + // + RtlZeroMemory((PVOID)EXCLUSIVE_PAGE_VIRTUAL_BASE,0x1000); + FwFlushAllCaches(); + TaskVector->Routine = CoherencyTest; + TaskVector->Data = (PVOID)EXCLUSIVE_PAGE_VIRTUAL_BASE; + WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,2); + + if (CoherencyTest((PVOID)EXCLUSIVE_PAGE_VIRTUAL_BASE) != 0) { + FwPrint(" Processor A Failed."); + ReturnValue = FALSE; + } else { + FwPrint("..."); + } + + // + // Get and display results from B + // + WaitForIpInterrupt(1000); + if (TaskVector->ReturnValue != 0) { + FwPrint(" Processor B Failed."); + ReturnValue = FALSE; + } else { + FwPrint("..."); + } + + // + // Do the same with a shared page + // + RtlZeroMemory((PVOID)SHARED_PAGE_VIRTUAL_BASE,0x1000); + FwFlushAllCaches(); + TaskVector->Routine = CoherencyTest; + TaskVector->Data = (PVOID)SHARED_PAGE_VIRTUAL_BASE; + WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,2); + if (CoherencyTest((PVOID)SHARED_PAGE_VIRTUAL_BASE) != 0) { + FwPrint(" Processor A Failed."); + ReturnValue = FALSE; + } else { + FwPrint("..."); + } + WaitForIpInterrupt(1000); + if (TaskVector->ReturnValue != 0) { + FwPrint(" Processor B Failed."); + ReturnValue = FALSE; + } else { + FwPrint("..."); + } + + // + // Make processor B initialize its PCR + // + + TaskVector->Routine = (PPROCESSOR_TASK_ROUTINE)InitializePCR; + TaskVector->Data = 0; + // + // Issue an IP interrupt to notify processor B that a task has + // been scheduled for execution. + // + + WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,2); + + // + // If timeout or Return Value indicates error, stop here. + // + if (WaitForIpInterrupt(5000) == FALSE) { +// FwPrint("\r\n Wait for Processor B timeout occurred in init PCR\r\n"); + return FALSE; + } + + // + // Make processor B cleanup it's caches. + // + + TaskVector->Routine = (PPROCESSOR_TASK_ROUTINE)HalSweepDcache; + TaskVector->Data = 0; + // + // Issue an IP interrupt to notify processor B that a task has + // been scheduled for execution. + // + + WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,2); + + // + // If timeout or Return Value indicates error, stop here. + // + if (WaitForIpInterrupt(5000) == FALSE) { +// FwPrint("\r\n Wait for Processor B timeout occurred Hal sweep d cachew\r\n"); + return FALSE; + } + FwPrint(FW_OK_MSG); + return ReturnValue; +} + + +#endif // DUO |