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.

556 lines
16 KiB

4 years ago
  1. #ident "@(#) NEC xxinitnt.c 1.18 95/03/17 11:59:37"
  2. /*++
  3. Copyright (c) 1991-1994 Microsoft Corporation
  4. Module Name:
  5. xxinitnt.c
  6. Abstract:
  7. This module implements the interrupt initialization for a MIPS R3000
  8. or R4000 system.
  9. --*/
  10. /*
  11. * Original source: Build Number 1.612
  12. *
  13. * Modify for R98(MIPS/R4400)
  14. *
  15. ***********************************************************************
  16. *
  17. * L001 94.03/22-5/13 T.Samezima
  18. *
  19. * add control of Eif interrupt.
  20. * make table of change from iRRE bit number to NABus code.
  21. * make table of arbitration table and arbitration pointer.
  22. * make variable for access of registers.
  23. * connect the timer interrupt service routine.
  24. * clear unknown interrupt counter
  25. *
  26. * del only '#if defined(_DUO_)'
  27. * '#if defined(_JAZZ_)' with content
  28. * HalpCountInterrupt()
  29. *
  30. * change interrupt control
  31. * various vector of interrupt service routine
  32. *
  33. ***********************************************************************
  34. *
  35. * S002 94.5/17 T.Samezima
  36. *
  37. * del Arbitration table
  38. *
  39. ***********************************************************************
  40. *
  41. * S003 94.6/10-14 T.Samezima
  42. *
  43. * del Compile err
  44. *
  45. ***********************************************************************
  46. *
  47. * S004 94.7/7 T.Samezima
  48. *
  49. * Chg Use UNKNOWN_COUNT_BUF_LEN to max
  50. * for HalpUnknownInterruptCount
  51. *
  52. ***********************************************************************
  53. *
  54. * S005 94.7/7 T.Samezima
  55. *
  56. * Del move interrupt arbitration pointer to r98dspt.c
  57. *
  58. ***********************************************************************
  59. *
  60. * S006 94.7/23 T.Samezima
  61. *
  62. * Add Enable EIF interrupt on SIC.
  63. *
  64. ***********************************************************************
  65. *
  66. * S007 94.8/22 T.Samezima on SNES
  67. *
  68. * Chg Register buffer size from USHORT to ULONG
  69. * Value of set to MKSR register
  70. * Condition change
  71. *
  72. * Add Clear interrupt pending bit on edge level interrupt
  73. *
  74. * Del Move EISA NMI enable logic to HalpCreateEisaStructure()
  75. *
  76. ***********************************************************************
  77. *
  78. * S008 94.9/5 T.Samezima
  79. *
  80. * Add Institute number of repeat for interrupt clear loop
  81. *
  82. ***********************************************************************
  83. *
  84. * S009 94.9/16 T.Samezima
  85. *
  86. * Chg Only CPU#0 on I/O Initerrupt clear
  87. *
  88. ***********************************************************************
  89. *
  90. * S00a 94.10/14 T.Samezima
  91. *
  92. * Fix Version Up at build807
  93. * -Move Int1 interrupt enable to allstart.c
  94. *
  95. * S00b 94.10/18 T.Samezima
  96. * Chg Enable interrupt on MKR register only exist device,
  97. *
  98. * S00c 94.12/06 T.Samezima
  99. * Bug Disable ECC 1bit error interrupt.
  100. *
  101. * S00d 94.12/06 T.Samezima
  102. * Add Disable NMI
  103. *
  104. * S00e 95.01/10 T.Samezima
  105. * Add Enable ECC 1bit error interrupt
  106. * Rewrite cycle start on ecc 1bit error
  107. *
  108. * S00f 95.01/24 T.Samezima
  109. * Add Disable rewrite cycle on ecc 1bit error
  110. *
  111. * S010 95.03/13 T.Samezima
  112. * Add Enable HW cache flush.
  113. *
  114. */
  115. #include "halp.h"
  116. #include "eisa.h" // S003
  117. //
  118. // Put all code for HAL initialization in the INIT section. It will be
  119. // deallocated by memory management when phase 1 initialization is
  120. // completed.
  121. //
  122. #if defined(ALLOC_PRAGMA)
  123. #pragma alloc_text(INIT, HalpInitializeInterrupts)
  124. #endif
  125. //
  126. // Define global data for builtin device interrupt enables.
  127. //
  128. ULONG HalpBuiltinInterruptEnable; // S007
  129. //
  130. // Define the IRQL mask and level mapping table.
  131. //
  132. // These tables are transfered to the PCR and determine the priority of
  133. // interrupts.
  134. //
  135. // N.B. The two software interrupt levels MUST be the lowest levels.
  136. //
  137. UCHAR HalpIrqlMask[] = {4, 5, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
  138. 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
  139. 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
  140. 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
  141. UCHAR HalpIrqlTable[] = {0xff, // IRQL 0
  142. 0xfe, // IRQL 1
  143. 0xfc, // IRQL 2
  144. 0xf8, // IRQL 3
  145. 0xf0, // IRQL 4
  146. 0xe0, // IRQL 5
  147. 0xc0, // IRQL 6
  148. 0x80, // IRQL 7
  149. 0x00}; // IRQL 8
  150. /* Start L001 */
  151. //
  152. // Define table of change from iRRE bit number to NABus code
  153. //
  154. ULONG HalpNaBusCodeTable[] = {0x8000, 0x0010, // iRRE bit0,1
  155. 0x0006, 0x0000, // iRRE bit2,3
  156. 0x0002, 0x0002, // iRRE bit4,5
  157. 0x000a, 0x000a, // iRRE bit6,7
  158. 0x0008, 0x000c, // iRRE bit8,9
  159. 0x8000, 0x8000, // iRRE bit10,11
  160. 0x8000, 0x8000, // iRRE bit12,13
  161. 0x8000, 0x8000, // iRRE bit14,15
  162. 0x8000, 0x0004, // iRRE bit16,17
  163. 0x8000, 0x8000, // iRRE bit18,19
  164. 0x8000, 0x8000, // iRRE bit20,21
  165. 0x000c, 0x8000, // iRRE bit22,23
  166. 0x8000, 0x8000, // iRRE bit24,25
  167. 0x8000, 0x8000, // iRRE bit26,27
  168. 0x8000, 0x8000, // iRRE bit28,29
  169. 0x8000, 0x8000 }; // iRRE bit30,31
  170. //
  171. // Define table of order of interrupt arbitration
  172. //
  173. ULONG HalpUnknownInterruptCount[UNKNOWN_COUNT_BUF_LEN]; // S004
  174. /* End L001*/
  175. BOOLEAN
  176. HalpInitializeInterrupts (
  177. VOID
  178. )
  179. /*++
  180. Routine Description:
  181. This function initializes interrupts for a Jazz or Duo MIPS system.
  182. N.B. This function is only called during phase 0 initialization.
  183. Arguments:
  184. None.
  185. Return Value:
  186. A value of TRUE is returned if the initialization is successfully
  187. completed. Otherwise a value of FALSE is returned.
  188. --*/
  189. {
  190. USHORT DataShort;
  191. ULONG DataLong;
  192. ULONG Index;
  193. PKPRCB Prcb;
  194. /* Start L001 */
  195. ULONG pmcRegisterAddr;
  196. ULONG pmcRegisterUpperPart;
  197. ULONG pmcRegisterLowerPart;
  198. ULONG bitCount;
  199. ULONG buffer;
  200. ULONG buffer2; // S006
  201. UCHAR charBuffer;
  202. LONG repeatCounter; // S008
  203. /* End L001 */
  204. //
  205. // Get the address of the processor control block for the current
  206. // processor.
  207. //
  208. Prcb = PCR->Prcb;
  209. //
  210. // Initialize the IRQL translation tables in the PCR. These tables are
  211. // used by the interrupt dispatcher to determine the new IRQL and the
  212. // mask value that is to be loaded into the PSR. They are also used by
  213. // the routines that raise and lower IRQL to load a new mask value into
  214. // the PSR.
  215. //
  216. for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
  217. PCR->IrqlMask[Index] = HalpIrqlMask[Index];
  218. }
  219. for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
  220. PCR->IrqlTable[Index] = HalpIrqlTable[Index];
  221. }
  222. /* Start L001 */
  223. //
  224. // All interrupt disables.
  225. //
  226. pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003
  227. pmcRegisterUpperPart = MKR_DISABLE_ALL_INTERRUPT_HIGH;
  228. pmcRegisterLowerPart = MKR_DISABLE_ALL_INTERRUPT_LOW;
  229. HalpWriteLargeRegister( pmcRegisterAddr,
  230. &pmcRegisterUpperPart,
  231. &pmcRegisterLowerPart );
  232. //
  233. // If processor 0 is being initialized, then set all device
  234. // interrupt disables.
  235. //
  236. if (Prcb->Number == 0) {
  237. HalpBuiltinInterruptEnable = iREN_DISABLE_ALL_INTERRUPT;
  238. for (Index = 0; Index < UNKNOWN_COUNT_BUF_LEN; Index += 1) { // S004
  239. HalpUnknownInterruptCount[Index] = 0;
  240. }
  241. // } // S009
  242. /* End L001 */
  243. //
  244. // Disable individual device interrupts and make sure no device interrupts
  245. // are pending.
  246. //
  247. /* Start L001 */
  248. WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
  249. HalpBuiltinInterruptEnable );
  250. WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIMR.Long,
  251. EIMR_DISABLE_ALL_EIF );
  252. repeatCounter = 0; // S008
  253. while( ((DataLong = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE) & iRRE_MASK) != 0) &&
  254. (++repeatCounter < 16) ) { // S008
  255. for( bitCount = 0 ; bitCount <= 31 ; bitCount++ ) {
  256. if( (DataLong & ( 1 << bitCount )) != 0) {
  257. // Start S007
  258. if( bitCount < 15 ){
  259. WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iRSF,
  260. ( 1 << bitCount ) );
  261. }
  262. // End S007
  263. WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AIMR.Long,
  264. HalpNaBusCodeTable[bitCount] );
  265. }
  266. }
  267. WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iRSF,
  268. iRSF_CLEAR_INTERRUPT );
  269. pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->IPRR ); // S003
  270. pmcRegisterUpperPart = 0x0;
  271. pmcRegisterLowerPart = 0xffffffff;
  272. HalpWriteLargeRegister( pmcRegisterAddr,
  273. &pmcRegisterUpperPart,
  274. &pmcRegisterLowerPart );
  275. }
  276. /* End L001 */
  277. HalpBuiltinInterruptEnable |= 0x10; // S010
  278. //
  279. // If processor 0 is being initialized, then enable device interrupts.
  280. //
  281. // if (Prcb->Number == 0) { // S009
  282. /* Start L001 */
  283. //
  284. // Enable INT0-1 interrupt on PMC
  285. //
  286. /* Start S003 */
  287. WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII0.Long,
  288. AII_INIT_DATA );
  289. WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII1.Long,
  290. AII_INIT_DATA );
  291. WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII2.Long,
  292. AII_INIT_DATA );
  293. WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII3.Long,
  294. AII_INIT_DATA );
  295. /* End S003 */
  296. pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003
  297. HalpReadLargeRegister( pmcRegisterAddr,
  298. &pmcRegisterUpperPart,
  299. &pmcRegisterLowerPart );
  300. pmcRegisterLowerPart = ( pmcRegisterLowerPart
  301. | MKR_INT0_DEVICE_ENABLE_LOW // S00b
  302. // | MKR_INT1_DEVICE_ENABLE_LOW // S00a, S00b
  303. | MKR_INT2_DEVICE_ENABLE_LOW // S00b
  304. ); // S003
  305. HalpWriteLargeRegister( pmcRegisterAddr,
  306. &pmcRegisterUpperPart,
  307. &pmcRegisterLowerPart );
  308. // DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long);
  309. // DataLong |= ENABLE_DEVICE_INTERRUPTS;
  310. // WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
  311. // DataLong);
  312. /* End L001 */
  313. }
  314. /* Start L001 */
  315. //
  316. // Connect the eif interrupt to the eif interrupt routine
  317. //
  318. PCR->InterruptRoutine[EIF_LEVEL] = HalpEifDispatch;
  319. //
  320. // Enable the eif interrupt
  321. //
  322. pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003
  323. HalpReadLargeRegister( pmcRegisterAddr,
  324. &pmcRegisterUpperPart,
  325. &pmcRegisterLowerPart );
  326. pmcRegisterUpperPart = ( pmcRegisterUpperPart | MKR_INT5_ENABLE_HIGH );
  327. pmcRegisterLowerPart = ( pmcRegisterLowerPart | MKR_INT5_ENABLE_LOW );
  328. HalpWriteLargeRegister( pmcRegisterAddr,
  329. &pmcRegisterUpperPart,
  330. &pmcRegisterLowerPart );
  331. buffer = READ_REGISTER_ULONG( &( PMC_CONTROL1 )->STSR.Long);
  332. buffer = (buffer | STSR_EIF_ENABLE);
  333. #if defined(DISABLE_NMI) // S00d
  334. buffer = (buffer | STSR_NMI_DISABLE);
  335. #endif
  336. WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->STSR.Long, buffer);
  337. WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->ERRMK.Long, ERRMK_EIF_ENABLE);
  338. WRITE_REGISTER_ULONG( &( IOB_CONTROL )->IEMR.Long, IEMR_ENABLE_ALL_EIF);
  339. WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIMR.Long, EIMR_ENABLE_ALL_EIF);
  340. /* Start S006 */
  341. buffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->SCFR.Long );
  342. IOB_DUMMY_READ;
  343. if( (buffer & SCFR_SIC_SET0_CONNECT) == 0 ) { // S007
  344. buffer2 = READ_REGISTER_ULONG( &(SIC_ERR_CONTROL_OR(SIC_NO0_OFFSET))->CKE0.Long );
  345. buffer2 &= CKE0_DISABLE_SBE; // S00c
  346. buffer2 |= CKE0_ENABLE_ALL_EIF;
  347. WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET0_OFFSET) )->CKE0.Long,
  348. buffer2
  349. );
  350. // S00e vvv
  351. buffer2 = READ_REGISTER_ULONG( &(SIC_DATA_CONTROL_OR(SIC_NO0_OFFSET))->DPCM.Long );
  352. buffer2 &= DPCM_ENABLE_MASK; // S00c
  353. WRITE_REGISTER_ULONG( &( SIC_DATA_CONTROL_OR(SIC_SET0_OFFSET) )->DPCM.Long,
  354. buffer2
  355. );
  356. #if 0 // S00f
  357. WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET0_OFFSET) )->SECT.Long,
  358. SECT_REWRITE_ENABLE
  359. );
  360. #endif
  361. // S00e ^^^
  362. WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET0_OFFSET) )->CKE1.Long,
  363. CKE1_ENABLE_ALL_EIF
  364. );
  365. }
  366. if( (buffer & SCFR_SIC_SET1_CONNECT) == 0 ) { // S007
  367. buffer2 = READ_REGISTER_ULONG( &(SIC_ERR_CONTROL_OR(SIC_NO2_OFFSET))->CKE0.Long );
  368. buffer2 &= CKE0_DISABLE_SBE; // S00c
  369. buffer2 |= CKE0_ENABLE_ALL_EIF;
  370. WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET1_OFFSET) )->CKE0.Long,
  371. buffer2
  372. );
  373. // S00e vvv
  374. buffer2 = READ_REGISTER_ULONG( &(SIC_DATA_CONTROL_OR(SIC_NO2_OFFSET))->DPCM.Long );
  375. buffer2 &= DPCM_ENABLE_MASK; // S00c
  376. WRITE_REGISTER_ULONG( &( SIC_DATA_CONTROL_OR(SIC_SET1_OFFSET) )->DPCM.Long,
  377. buffer2
  378. );
  379. #if 0 // S00f
  380. WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET1_OFFSET) )->SECT.Long,
  381. SECT_REWRITE_ENABLE
  382. );
  383. #endif
  384. // S00e ^^^
  385. WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET1_OFFSET) )->CKE1.Long,
  386. CKE1_ENABLE_ALL_EIF
  387. );
  388. }
  389. /* End S006 */
  390. // S007
  391. //
  392. // If processor 0 is being initialized, then connect the interval timer
  393. // interrupt to the stall interrupt routine so the stall execution count
  394. // can be computed during phase 1 initialization. Otherwise, connect the
  395. // interval timer interrupt to the appropriate interrupt service routine
  396. // and set stall execution count from the computation made on processor
  397. // 0.
  398. //
  399. PCR->InterruptRoutine[TIMER_LEVEL] = HalpTimerDispatch; // S003
  400. if (Prcb->Number == 0) {
  401. /* Start L001 */
  402. PCR->InterruptRoutine[CLOCK_VECTOR] = HalpStallInterrupt;
  403. /* End L001 */
  404. } else {
  405. /* Start L001 */
  406. PCR->InterruptRoutine[CLOCK_VECTOR] = HalpClockInterrupt1;
  407. /* End L001 */
  408. PCR->StallScaleFactor = HalpStallScaleFactor;
  409. }
  410. //
  411. // Initialize the interval timer to interrupt at the specified interval.
  412. //
  413. /* Start L001 */
  414. WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR1.Long, CLOCK_INTERVAL);
  415. //
  416. // Initialize the profile timer to interrupt at the default interval.
  417. //
  418. WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR2.Long,
  419. DEFAULT_PROFILETIMER_COUNT);
  420. /* End L001 */
  421. //
  422. // Enable the interval timer interrupt on the current processor.
  423. //
  424. /* Start L001 */
  425. WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->MKSR.Long, 0x3f-IPR_CLOCK_BIT_NO); // S007
  426. WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR1.Long, 0x3);
  427. /* End L001 */
  428. //
  429. // If processor 0 is being initialized, then connect the count/compare
  430. // interrupt to the count interrupt routine to handle early count/compare
  431. // interrupts during phase 1 initialization. Otherwise, connect the
  432. // count\comapre interrupt to the appropriate interrupt service routine.
  433. //
  434. /* Start L001 */
  435. if (Prcb->Number != 0) {
  436. PCR->InterruptRoutine[PROFILE_VECTOR] = HalpProfileInterrupt;
  437. WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->MKSR.Long, 0x3f-IPR_PROFILE_BIT_NO); // S007
  438. WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR2.Long, 0x3);
  439. }
  440. /* End L001 */
  441. //
  442. // Connect the interprocessor interrupt service routine and enable
  443. // interprocessor interrupts.
  444. //
  445. PCR->InterruptRoutine[IPI_LEVEL] = HalpIpiInterrupt;
  446. /*Start L001 */
  447. pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003
  448. HalpReadLargeRegister( pmcRegisterAddr,
  449. &pmcRegisterUpperPart,
  450. &pmcRegisterLowerPart );
  451. pmcRegisterUpperPart = ( pmcRegisterUpperPart | MKR_INT4_ENABLE_HIGH );
  452. pmcRegisterLowerPart = ( pmcRegisterLowerPart | MKR_INT4_ENABLE_LOW );
  453. HalpWriteLargeRegister( pmcRegisterAddr,
  454. &pmcRegisterUpperPart,
  455. &pmcRegisterLowerPart );
  456. /*End L001 */
  457. //
  458. // Reserve the local device interrupt vector for exclusive use by the HAL.
  459. //
  460. /* Start L001 */
  461. // PCR->ReservedVectors |= (1 << DEVICE_LEVEL);
  462. // PCR->ReservedVectors |= (1 << INT1_LEVEL); // S00a
  463. PCR->ReservedVectors |= (1 << INT2_LEVEL);
  464. /* End L001 */
  465. return TRUE;
  466. }