summaryrefslogtreecommitdiffstats
path: root/private/ntos/fw/mips/duosync.c
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/fw/mips/duosync.c
downloadNT4.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.c516
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