Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

516 lines
12 KiB

4 years ago
  1. #ifdef DUO
  2. /*++
  3. Copyright (c) 1990 Microsoft Corporation
  4. Module Name:
  5. duosync.c
  6. Abstract:
  7. This module contains the routines that perform synchronization
  8. among processors.
  9. Author:
  10. Lluis Abello (lluis) 06-Apr-1993
  11. Environment:
  12. Revision History:
  13. --*/
  14. #include "fwp.h"
  15. #include "iodevice.h"
  16. #include "led.h"
  17. #include "selfmap.h"
  18. #include "selftest.h"
  19. #include "ioaccess.h"
  20. #include "fwstring.h"
  21. volatile PROCESSOR_B_TASK_VECTOR ProcessorBTask;
  22. extern BOOLEAN ProcessorBEnabled;
  23. VOID
  24. InitializePCR(
  25. );
  26. MEMORY_TEST_DATA BMemTest1 = {
  27. 0xA0100000,
  28. 0x100000,
  29. 0,
  30. LED_B_MEMORY_TEST_1
  31. };
  32. MEMORY_TEST_DATA BMemTest2 = {
  33. 0x80200000,
  34. 0x100000,
  35. 0,
  36. LED_B_MEMORY_TEST_2
  37. };
  38. MEMORY_TEST_DATA BMemTest3 = {
  39. VIDEO_MEMORY_VIRTUAL_BASE+1280*1024, // start adr = end of visible screen
  40. 0x200000-1280*1024, // size = rest of video memory.
  41. 0,
  42. LED_VIDEOMEM
  43. };
  44. //
  45. // The following table defines the selftest routines that will be executed
  46. // by processor B.
  47. //
  48. PROCESSOR_B_TEST ProcessorBSelfTests[] = {
  49. {ProcessorBMemoryTest,&BMemTest1},
  50. {ProcessorBMemoryTest,&BMemTest2},
  51. {ProcessorBVideoMemoryTest,&BMemTest3},
  52. {NULL,0}
  53. };
  54. ULONG
  55. ExecuteOnProcessorB(
  56. IN PPROCESSOR_TASK_ROUTINE Routine,
  57. IN PVOID Data
  58. )
  59. /*++
  60. Routine Description:
  61. This routine puts the supplied Routine and Data in processor B task vector
  62. and issues an IP interrupt to processor B which will then execute
  63. it and set the return value.
  64. Arguments:
  65. None
  66. Return Value:
  67. None
  68. --*/
  69. {
  70. PPROCESSOR_B_TASK_VECTOR TaskVector;
  71. if (!ProcessorBEnabled) {
  72. return 0;
  73. }
  74. //
  75. // Get a non pointer to the Task Vector
  76. //
  77. TaskVector = (PPROCESSOR_B_TASK_VECTOR)&ProcessorBTask;
  78. TaskVector->Routine = Routine;
  79. TaskVector->Data = Data;
  80. //
  81. // Issue an IP interrupt to notify processor B that a task has
  82. // been scheduled for execution.
  83. //
  84. WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,2);
  85. //
  86. // If timeout or Return Value indicates error, stop here.
  87. //
  88. if (WaitForIpInterrupt(5000) == FALSE) {
  89. FwPrint("\r\nTimeout waiting for B to execute %lx\r\n",Routine);
  90. }
  91. return (TaskVector->ReturnValue);
  92. }
  93. VOID
  94. ProcessorBMain(
  95. )
  96. /*++
  97. Routine Description:
  98. This is the main routine for processor B.
  99. It jumps here after initialization.
  100. The startup sequence is as follows:
  101. ProcessorA sets the address of this routine in the ProcessorBTask vector.
  102. ProcessorA Enables Processor B in the Global Configuration register.
  103. ProcessorA Calls WaitForIPInterrupt.
  104. When Processor B is enabled it runs at the PROM reset vector, it
  105. initializes itself and jumps to the routine pointed to by ProcessorTask
  106. which is this routine.
  107. Once here processor B Wakes up processor A by issuing an IP interrupt
  108. and Loops for ever waiting for IP interrupts and executing the Task
  109. pointed to by ProcessorBTask.
  110. Arguments:
  111. None
  112. Return Value:
  113. None
  114. --*/
  115. {
  116. PPROCESSOR_TASK_ROUTINE Task;
  117. PVOID TaskData;
  118. ULONG ReturnValue;
  119. //
  120. // Get a pointer to the Task Vector
  121. //
  122. PPROCESSOR_B_TASK_VECTOR TaskVector = (PPROCESSOR_B_TASK_VECTOR)&ProcessorBTask;
  123. //
  124. // Enable IP interrupts.
  125. // All interrupts are disabled in the psr.
  126. //
  127. WRITE_REGISTER_ULONG(&DMA_CONTROL->InterruptEnable.Long,ENABLE_IP_INTERRUPTS);
  128. for (;;) {
  129. //
  130. // Wake up processor A
  131. //
  132. WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,1);
  133. WaitForIpInterrupt(0);
  134. //
  135. // Execute Task
  136. //
  137. Task = TaskVector->Routine;
  138. TaskData = TaskVector->Data;
  139. ReturnValue = Task(TaskData);
  140. TaskVector->ReturnValue = ReturnValue;
  141. }
  142. }
  143. ULONG
  144. ProcessorBMemoryTest(
  145. IN PMEMORY_TEST_DATA MemoryData
  146. )
  147. /*++
  148. Routine Description:
  149. This routine tests the portion of memory supplied by Data.
  150. Arguments:
  151. MemoryData - Pointer to a data structure describing the range of
  152. memory to be tested.
  153. Return Value:
  154. None
  155. --*/
  156. {
  157. PutLedDisplay(MemoryData->LedDisplayValue);
  158. WriteMemoryAddressTest(MemoryData->StartAddress,MemoryData->Size,MemoryData->XorPattern);
  159. CheckMemoryAddressTest(MemoryData->StartAddress,MemoryData->Size,MemoryData->XorPattern,MemoryData->LedDisplayValue);
  160. return 1;
  161. }
  162. ULONG
  163. ProcessorBVideoMemoryTest(
  164. IN PMEMORY_TEST_DATA MemoryData
  165. )
  166. /*++
  167. Routine Description:
  168. This routine tests the portion of video memory supplied by Data.
  169. Arguments:
  170. MemoryData - Pointer to a data structure describing the range of
  171. memory to be tested.
  172. Return Value:
  173. None
  174. --*/
  175. {
  176. PutLedDisplay(MemoryData->LedDisplayValue);
  177. WriteVideoMemoryAddressTest(MemoryData->StartAddress,MemoryData->Size);
  178. CheckVideoMemoryAddressTest(MemoryData->StartAddress,MemoryData->Size);
  179. return 1;
  180. }
  181. ULONG
  182. CoherencyTest(
  183. IN PVOID CoherentPage
  184. )
  185. /*++
  186. Routine Description:
  187. This routine performs a coherency test. This routine will be executed
  188. simultaneously by both processors.
  189. Processor A stores even bytes and Processor B stores the odd bytes.
  190. To make sure that cache blocks are passed back and forth, a semaphore
  191. locks it's access so that the cache line ping pongs from processor to
  192. processor.
  193. Arguments:
  194. CoherentPage. Pointer aligned to a page boundary. Which is marked
  195. either Exclusive or Shared in the TLB.
  196. The first ulong is used as the semaphore. The rest of the page
  197. is used as data.
  198. Return Value:
  199. Number of errors found.
  200. --*/
  201. {
  202. volatile PULONG Semaphore = (PULONG)CoherentPage;
  203. PULONG CoherentData = Semaphore+64/sizeof(ULONG);
  204. ULONG Counter;
  205. ULONG Processor;
  206. ULONG DataLong;
  207. ULONG Errors = 0;
  208. if (READ_REGISTER_ULONG(&DMA_CONTROL->WhoAmI.Long)) {
  209. //
  210. // Processor B
  211. //
  212. Processor = 1;
  213. DataLong = 0xB0B00000;
  214. } else {
  215. Processor = 0;
  216. DataLong = 0xA0A00000;
  217. }
  218. for (Counter = 0; Counter < (0x1000-64)/sizeof(ULONG); Counter += 2) {
  219. //
  220. // Wait for counter.
  221. // No need for interlocks since each processor waits
  222. // for a different value.
  223. //
  224. while (*Semaphore != Counter+Processor) {
  225. }
  226. *(CoherentData+Processor) = DataLong | Counter;
  227. *Semaphore = Counter+Processor+1;
  228. CoherentData += 2;
  229. }
  230. //
  231. // Both processors check all the data.
  232. //
  233. CoherentData = Semaphore+64/sizeof(ULONG);;
  234. for (Counter = 0; Counter < (0x1000-64)/sizeof(ULONG); Counter +=2) {
  235. if (*CoherentData != (Counter | 0xA0A00000)) {
  236. Errors++;
  237. }
  238. CoherentData++;
  239. if (*CoherentData != (Counter | 0xB0B00000)) {
  240. Errors++;
  241. }
  242. CoherentData++;
  243. }
  244. return Errors;
  245. }
  246. BOOLEAN
  247. ProcessorBSelftest(
  248. IN VOID
  249. )
  250. /*++
  251. Routine Description:
  252. This routine sets the different tasks to be executed by processor
  253. b and waits for them to complete. This routine is executed by the
  254. master processor.
  255. Arguments:
  256. None.
  257. Return Value:
  258. TRUE if passed FALSE otherwise
  259. --*/
  260. {
  261. BOOLEAN ReturnValue;
  262. BOOLEAN Timeout;
  263. //
  264. // Get a pointer to the Task Vector
  265. //
  266. PPROCESSOR_B_TASK_VECTOR TaskVector = (PPROCESSOR_B_TASK_VECTOR)&ProcessorBTask;
  267. PPROCESSOR_B_TEST ProcessorBTestList = ProcessorBSelfTests;
  268. //
  269. // Place each task of the SelftestTable in the TaskVector to be executed
  270. // by processor B.
  271. //
  272. while (ProcessorBTestList->Routine != NULL) {
  273. TaskVector->Routine = ProcessorBTestList->Routine;
  274. TaskVector->Data = ProcessorBTestList->Data;
  275. //
  276. // Issue an IP interrupt to notify processor B that a task has
  277. // been scheduled for execution.
  278. //
  279. WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,2);
  280. //
  281. // If timeout or Return Value indicates error, stop here.
  282. //
  283. if (((Timeout = WaitForIpInterrupt(5000)) == FALSE) || (TaskVector->ReturnValue == FALSE)) {
  284. if (!Timeout) {
  285. FwPrint("\r\n Wait for Processor B timeout occurred");
  286. } else {
  287. FwPrint("\r\n Processor B failed a test");
  288. }
  289. FwPrint(" Failed test = %08lx\r\n", (ULONG)ProcessorBTestList->Routine);
  290. //return FALSE;
  291. }
  292. //
  293. // Next test.
  294. //
  295. ProcessorBTestList++;
  296. }
  297. //
  298. // Now perform two CoherencyTest
  299. //
  300. FwPrint("\r\n Coherency Test.");
  301. ReturnValue = TRUE;
  302. //
  303. // Zero the page. Set the Task and notify processor B.
  304. // And execute the test simultaneously.
  305. //
  306. RtlZeroMemory((PVOID)EXCLUSIVE_PAGE_VIRTUAL_BASE,0x1000);
  307. FwFlushAllCaches();
  308. TaskVector->Routine = CoherencyTest;
  309. TaskVector->Data = (PVOID)EXCLUSIVE_PAGE_VIRTUAL_BASE;
  310. WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,2);
  311. if (CoherencyTest((PVOID)EXCLUSIVE_PAGE_VIRTUAL_BASE) != 0) {
  312. FwPrint(" Processor A Failed.");
  313. ReturnValue = FALSE;
  314. } else {
  315. FwPrint("...");
  316. }
  317. //
  318. // Get and display results from B
  319. //
  320. WaitForIpInterrupt(1000);
  321. if (TaskVector->ReturnValue != 0) {
  322. FwPrint(" Processor B Failed.");
  323. ReturnValue = FALSE;
  324. } else {
  325. FwPrint("...");
  326. }
  327. //
  328. // Do the same with a shared page
  329. //
  330. RtlZeroMemory((PVOID)SHARED_PAGE_VIRTUAL_BASE,0x1000);
  331. FwFlushAllCaches();
  332. TaskVector->Routine = CoherencyTest;
  333. TaskVector->Data = (PVOID)SHARED_PAGE_VIRTUAL_BASE;
  334. WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,2);
  335. if (CoherencyTest((PVOID)SHARED_PAGE_VIRTUAL_BASE) != 0) {
  336. FwPrint(" Processor A Failed.");
  337. ReturnValue = FALSE;
  338. } else {
  339. FwPrint("...");
  340. }
  341. WaitForIpInterrupt(1000);
  342. if (TaskVector->ReturnValue != 0) {
  343. FwPrint(" Processor B Failed.");
  344. ReturnValue = FALSE;
  345. } else {
  346. FwPrint("...");
  347. }
  348. //
  349. // Make processor B initialize its PCR
  350. //
  351. TaskVector->Routine = (PPROCESSOR_TASK_ROUTINE)InitializePCR;
  352. TaskVector->Data = 0;
  353. //
  354. // Issue an IP interrupt to notify processor B that a task has
  355. // been scheduled for execution.
  356. //
  357. WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,2);
  358. //
  359. // If timeout or Return Value indicates error, stop here.
  360. //
  361. if (WaitForIpInterrupt(5000) == FALSE) {
  362. // FwPrint("\r\n Wait for Processor B timeout occurred in init PCR\r\n");
  363. return FALSE;
  364. }
  365. //
  366. // Make processor B cleanup it's caches.
  367. //
  368. TaskVector->Routine = (PPROCESSOR_TASK_ROUTINE)HalSweepDcache;
  369. TaskVector->Data = 0;
  370. //
  371. // Issue an IP interrupt to notify processor B that a task has
  372. // been scheduled for execution.
  373. //
  374. WRITE_REGISTER_ULONG(&DMA_CONTROL->IpInterruptRequest.Long,2);
  375. //
  376. // If timeout or Return Value indicates error, stop here.
  377. //
  378. if (WaitForIpInterrupt(5000) == FALSE) {
  379. // FwPrint("\r\n Wait for Processor B timeout occurred Hal sweep d cachew\r\n");
  380. return FALSE;
  381. }
  382. FwPrint(FW_OK_MSG);
  383. return ReturnValue;
  384. }
  385. #endif // DUO