NT4/private/ntos/nthals/halr98b/mips/allstart.c
2020-09-30 17:12:29 +02:00

413 lines
10 KiB
C

/*++
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 <<PCR->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);
}