/*++ Copyright (c) 1994 Microsoft Corporation Module Name: allstart.c Abstract: This module implements the platform specific operations that must be performed after all processors have been started. --*/ /* */ #include "halp.h" KINTERRUPT HalpEifInterrupt[R98B_MAX_CPU]; // // This is Interrupt Level define. // HalpIntLevelofIpr[HalpMachineType][Ipr] = INT X // UCHAR HalpIntLevelofIpr[R98_CPU_NUM_TYPE][NUMBER_OF_IPR_BIT]={ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 2,2,2,2,2,2,2,2,2,2,2,2,4,4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,5,5,5,5}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,4,4,4,4} }; // // This is Interrupt connect pattern. // [NumberOfCpu][IPR] meas what connect cpu(Affinity But UCHAR. when use you must Cast Affinity) // UCHAR HalpIntConnectPattern[R98B_MAX_CPU][NUMBER_OF_IPR_BIT]={ // At 1 Processor System {0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1, 0,0,0x0,0x1,1,1,1,1,0,0,0,0,0,0,0,0, 0x1,0x1,0x1,0x1,0,0,0,0,0x1,0x1,0,0,0,0x1,0x1,0}, // At 2 Processor System // {0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,1,1,1,1,1,1,0,0,0,1,1,1, // snes kai {0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,2,2,2,2,2,2,0,0,0,2,2,2, 0,0,0x0,0x3,1,1,1,1,0,0,0,0,0,0,0,0, 0x3,0x3,0x3,0x3,0,0,0,0,0x3,0x3,0,0,0,0x3,0x3,0}, // At 3 Processor System {0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,2,2,4,4,2,2,0,0,0,2,4,4, 0,0,0x0,0x7,1,1,1,1,0,0,0,0,0,0,0,0, 0x7,0x7,0x7,0x7,0,0,0,0,0x7,0x7,0,0,0,0x7,0x7,0}, // At 4 Processor System {0,1,1,0,1,1,0,1,1,0,0,0,0,1,1,1, 0,0,0,0,2,2,4,8,2,2,0,0,0,2,4,8, 0,0,0x0,0xF,1,1,1,1,0,0,0,0,0,0,0,0, 0xF,0xF,0xF,0xF,0,0,0,0,0xf,0xf,0,0,0,0xF,0xF,0} }; extern ULONG HalpLogicalCPU2PhysicalCPU[R98B_MAX_CPU]; BOOLEAN HalAllProcessorsStarted ( VOID ) /*++ Routine Description: This function executes platform specific operations that must be performed after all processors have been started. It is called for each processor in the host configuration. Arguments: None. Return Value: If platform specific operations are successful, then return TRUE. Otherwise, return FALSE. --*/ { ULONG ipr; PULONG Vp; ULONG NumCpu; KIRQL OldIrql; ULONG Value[2]; ULONG IntNo; ULONG MagBuffer; KeRaiseIrql(HIGH_LEVEL, &OldIrql); // // In This Time I know Number Of CPU. // NumCpu = **((PULONG *)(&KeNumberProcessors)); // // Number to Array Index. // NumCpu--; for(ipr=0;ipr<64; ipr++){ if((HalpIntConnectPattern[NumCpu][ipr] & (1 <Number))== 0 ){ // // This Interrupt Connect Target CPU Not for me. So Set // ~~~ Vp = (PULONG)&(HalpIntEntry[HalpMachineCpu][PCR->Number][ HalpIntLevelofIpr[HalpMachineCpu][ipr] ].Enable); if( ipr < 32){ Vp[0] &= ~(0x1 << ipr); Vp[1] &= 0xffffffff; }else{ Vp[0] &= 0xffffffff; Vp[1] &= ~(0x1 << (ipr-32)); } } } // // Enable Interrupt at Columnbs // At This Interrupt Mask is perfact. // Value[0] = (ULONG)0xFFFFFFFF; Value[1] = (ULONG)0xFFFFFFFF; // // ReBuild Mask // for(IntNo=0 ; IntNo< 6 ;IntNo++){ Vp = (PULONG)&(HalpIntEntry[HalpMachineCpu][PCR->Number][IntNo].Enable); Value[0] &= ~Vp[0]; Value[1] &= ~Vp[1]; } Vp = (PULONG)&(COLUMNBS_LCNTL)->MKR; WRITE_REGISTER_ULONG( Vp++,Value[0]); WRITE_REGISTER_ULONG( Vp, Value[1]); // 2CPU // Reset Interrupt of do Mask. // Vp = (PULONG)&(COLUMNBS_LCNTL)->IPRR; WRITE_REGISTER_ULONG( Vp++,Value[0]); WRITE_REGISTER_ULONG( Vp, Value[1]); // // ECC ERROR CHECK START // #if 1 // ECC 1bit error/Multi bit error enable if (PCR->Number == 0) { if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN0) == 0 ){ MagBuffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI ) ; MagBuffer &= ECC_ERROR_ENABLE; WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(0)->ERRI, MagBuffer ) ; } if ( (HalpPhysicalNode & CNFG_CONNECT4_MAGELLAN1) == 0 ){ MagBuffer = READ_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI ) ; MagBuffer &= ECC_ERROR_ENABLE; WRITE_REGISTER_ULONG( (PULONG)&MAGELLAN_X_CNTL(1)->ERRI, MagBuffer ) ; } } #endif KeLowerIrql(OldIrql); #if DBG DbgPrint("All Pro 0 CPU= %x :MKR = Low = 0x%x High = 0x%x\n",PCR->Number,Value[0],Value[1]); #endif // // Restart all timer interrupt. because, generate interrupt for same time // All CPU if (PCR->Number == 0) { WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->TCIR, TCIR_ALL_CLOCK_RESTART| 0x000f0000); } #if 0 // // F/W Setup. So Never Fix. // if (PCR->Number == 0) { IntNo = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->PERRI); DbgPrint(" PONCE_PERRI 0= 0x%x\n",IntNo); IntNo = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(0)->PERRM); DbgPrint(" PONCE_PERRM 0= 0x%x\n",IntNo); #if 0 // // Ponce #0 PCI Error Eif Enable. // Future implement. // WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->PERRM,PONCE_PXERR_PMDER); // // PCI Error Eif inhibit off. // WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->PERRI,PONCE_PXERR_PMDER); #else //test kbnes WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->PERRM,(PONCE_PXERR_PMDER|PONCE_PXERR_PPERM)); // // PCI Error Eif inhibit off. // WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(0)->PERRI, PONCE_PXERR_PPERM)); #endif // // Ponce #1 PCI Error Eif Enable. // Future implement. // #if 0 WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->PERRM,(PONCE_PXERR_PMDER|PONCE_PXERR_PPERM)); // // PCI Error Eif inhibit off. // WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->PERRI, (PONCE_PXERR_PMDER|PONCE_PXERR_PPERM)); #else //SNES tst IntNo = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(1)->PERRI); DbgPrint(" PONCE_PERRI 1= 0x%x\n",IntNo); IntNo = READ_REGISTER_ULONG((PULONG)&PONCE_CNTL(1)->PERRM); DbgPrint(" PONCE_PERRM 1= 0x%x\n",IntNo); WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->PERRM,(PONCE_PXERR_PMDER|PONCE_PXERR_PPERM)); // // PCI Error Eif inhibit off. // WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(1)->PERRI, PONCE_PXERR_PPERM)); #endif } #endif // // On phase 0 EIF_VECTOR: direct connect by hal. so early interrupt imprement!! // After This time. Eif Vector can share with ather device( MRC Driver) // KeInitializeInterrupt( &HalpEifInterrupt[PCR->Number], HalpHandleEif, NULL, NULL, EIF_VECTOR, (KIRQL)(INT0_LEVEL + HalpIntLevelofIpr[HalpMachineCpu][EIF_VECTOR - DEVICE_VECTORS]), (KIRQL)(INT0_LEVEL + HalpIntLevelofIpr[HalpMachineCpu][EIF_VECTOR - DEVICE_VECTORS]), LevelSensitive, TRUE, PCR->Number, FALSE ); KeConnectInterrupt( &HalpEifInterrupt[PCR->Number]); PCR->InterruptRoutine[UNDEFINE_TLB_VECTOR] = (PKINTERRUPT_ROUTINE)HalpIoTlbLimitOver; // F/W Setup. So Never Fix. // // // Columnbs Error Eif and NMI Enable. // Future implement. // // WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRMK,0x0); // // inhibit off. // // WRITE_REGISTER_ULONG( (PULONG)&(COLUMNBS_LCNTL)->ERRI,0x0); // // If the number of processors in the host configuration is one, // all Interrupt connect processor 0. // #if DBG DbgPrint("SecondLevelIcacheFillSize = 0x%x\n",PCR->SecondLevelIcacheFillSize); #endif return HalpConnectIoInterrupt(NumCpu); } // // // Which MPU X IPR Bit X Connect // N.B // All CPU Execute!! // BOOLEAN HalpConnectIoInterrupt( IN ULONG NumCpu ) { PULONG IntTg; PUCHAR Cnpttn; UCHAR Number; ULONG OldIntGValue; ULONG ipr; ULONG PhysicalNumber; Cnpttn = &HalpIntConnectPattern[NumCpu][0]; Number = PCR->Number; // // If Interrupt for me!! then do so myself. // Ipr 44 of max device interrupt. upper 44 is ipi or clock or profile // or eif. etc... // KiAcquireSpinLock(&HalpIprInterruptLock); for(ipr=0;ipr< 43;ipr++){ // // BroadCast Type Implement OK!!. // N.B // But INT Dispatcher not Supported. // if(Cnpttn[ipr] & (0x1 << Number)){ HalpResetValue[ipr].Cpu = (UCHAR)Number; IntTg = (PULONG) &PONCE_CNTL(HalpResetValue[ipr].Ponce)->INTTG[10 - HalpResetValue[ipr].IntGResetBit]; #if 0 // // Broadcast But Imprement Not Complete. // // OldIntGValue = READ_REGISTER_ULONG( IntTg ); OldIntGValue &= 0xf0; #else // // Device Interrupt Connect to 1 CPU Only. // Not Broadcast // OldIntGValue = 0x0; #endif PhysicalNumber=HalpLogicalCPU2PhysicalCPU[Number]; WRITE_REGISTER_ULONG( IntTg, (OldIntGValue | (0x10 << PhysicalNumber)) ); } } KiReleaseSpinLock(&HalpIprInterruptLock); // // if eisa interrupt connect to me! // Initialize EISA bus interrupts. // if(HalpResetValue[EISA_DISPATCH_VECTOR - DEVICE_VECTORS].Cpu == Number){ HalpCreateEisaStructures(); } return TRUE; } // // Default All Interrupt Disable. // ULONG HalpInterruptPonceMask[PONCE_MAX] = { 0x000007ff,0x000007ff,0x000007ff}; // // // This function Enable or Disable Interrupt connect to Ponce. // BOOLEAN HalpInterruptFromPonce( IN ULONG Vector, IN ULONG Enable ) { ULONG Ponce; ULONG IprBitNum; IprBitNum = Vector - DEVICE_VECTORS; //SNES // // Check interrupt was connected to ponce!!. // if( HalpResetValue[IprBitNum].IntGResetBit > INTSA0) return FALSE; Ponce = HalpResetValue[IprBitNum].Ponce; KiAcquireSpinLock(&HalpSystemInterruptLock); // Bit X // 1: Enable Interrupt // 0: Disable Interrupt if(Enable){ HalpInterruptPonceMask[Ponce] &= (ULONG) ~(0x1 << HalpResetValue[IprBitNum].IntGResetBit); }else{ HalpInterruptPonceMask[Ponce] |= (ULONG) (0x1 << HalpResetValue[IprBitNum].IntGResetBit); } WRITE_REGISTER_ULONG( (PULONG)&PONCE_CNTL(Ponce)->INTM,HalpInterruptPonceMask[Ponce]); KiReleaseSpinLock(&HalpSystemInterruptLock); }