windows-nt/Source/XPSP1/NT/base/hals/halsp/i386/spsproc.c

328 lines
7.4 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
spsproc.c
Abstract:
SystemPro Start Next Processor c code.
This module implements the initialization of the system dependent
functions that define the Hardware Architecture Layer (HAL) for an
MP Compaq SystemPro
Author:
Ken Reneris (kenr) 22-Jan-1991
Environment:
Kernel mode only.
Revision History:
--*/
#include "halp.h"
const UCHAR HalName[] = "SystemPro or compatible MP Hal"; // This is placed in .text for debugging
#define HalName L"SystemPro or compatible MP Hal"
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg("INITCONST")
#endif // ALLOC_DATA_PRAGMA
WCHAR HalHardwareIdString[] = L"syspro_mp\0";
ADDRESS_USAGE HalpSystemProIoSpace = {
NULL, CmResourceTypePort, InternalUsage,
{
0xC70, 1, // WhoAmI
0xC6A, 1, // P0 Processor control register
0xFC6A, 1, // P1 Processor control register
0xFC67, 2, // P1 cache control, interrupt vector
0,0
}
};
ADDRESS_USAGE HalpAcerIoSpace = {
NULL, CmResourceTypePort, InternalUsage,
{
0xCC67, 2, // P2 cache control, interrupt vector
0xCC6A, 1, // P2 Processor control register
0xDC67, 2, // P3 cache control, interrupt vector
0xDC6A, 1, // P3 Processor control register
0,0
}
};
ADDRESS_USAGE HalpBelizeIoSpace = {
NULL, CmResourceTypePort, InternalUsage,
{
0xC67, 1, // Mode Select
0xC71, 6, // CPU assignment, reserverd[2], CPU index, address, data
0xCB0, 36, // IRQx Control/Status
0xCC9, 1, // INT13 Extended control/status port
0,0
}
};
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg()
#endif // ALLOC_DATA_PRAGMA
VOID
HalpNonPrimaryClockInterrupt(
VOID
);
BOOLEAN
HalpInitMP (
IN ULONG Phase,
IN PLOADER_PARAMETER_BLOCK LoaderBlock
);
VOID HalpInitOtherBuses (VOID);
VOID HalpInitializePciBus (VOID);
VOID HalpInitializePciStubs (VOID);
#define LOW_MEMORY 0x000100000
#define MAX_PT 8
extern VOID StartPx_PMStub(VOID);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,HalpInitMP)
#pragma alloc_text(INIT,HalAllProcessorsStarted)
#pragma alloc_text(INIT,HalReportResourceUsage)
#pragma alloc_text(INIT,HalReportResourceUsage)
#pragma alloc_text(INIT,HalpInitOtherBuses)
#endif
ULONG MpCount; // zero based. 0 = 1, 1 = 2, ...
PUCHAR MpLowStub; // pointer to low memory bootup stub
PVOID MpLowStubPhysicalAddress; // pointer to low memory bootup stub
PUCHAR MppIDT; // pointer to physical memory 0:0
extern ULONG HalpIpiClock; // bitmask of processors to ipi
extern UCHAR SpCpuCount;
extern UCHAR Sp8259PerProcessorMode;
extern UCHAR SpType;
extern PKPCR HalpProcessorPCR[];
BOOLEAN
HalpInitMP (
IN ULONG Phase,
IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
/*++
Routine Description:
Allows MP initialization from HalInitSystem.
Arguments:
Same as HalInitSystem
Return Value:
none.
--*/
{
ULONG paddress;
ULONG adjust;
PKPCR pPCR;
pPCR = KeGetPcr();
if (Phase == 0) {
//
// Register the IO space used by the SystemPro
//
HalpRegisterAddressUsage (&HalpSystemProIoSpace);
switch (SpType) {
case 2:
HalpRegisterAddressUsage (&HalpBelizeIoSpace);
break;
case 3:
HalpRegisterAddressUsage (&HalpAcerIoSpace);
break;
}
#if 0
//
// Register IPI vector
//
HalpRegisterVector (
DeviceUsage,
13,
13 + PRIMARY_VECTOR_BASE,
IPI_LEVEL );
#endif
//
// Get pointer to real-mode idt table
//
MppIDT = HalpMapPhysicalMemory (0, 1);
//
// Allocate some low memory for processor bootup stub
//
MpLowStubPhysicalAddress = (PVOID)HalpAllocPhysicalMemory (LoaderBlock,
LOW_MEMORY, 1, FALSE);
if (!MpLowStubPhysicalAddress)
return TRUE;
MpLowStub = (PCHAR) HalpMapPhysicalMemory (MpLowStubPhysicalAddress, 1);
MpCount = SpCpuCount-1;
return TRUE;
} else {
//
// Phase 1 for another processor
//
if (pPCR->Prcb->Number != 0) {
if (Sp8259PerProcessorMode & 1) {
//
// Each processor has it's own pics - we broadcast profile
// interrupts to each processor by enabling it on each
// processor
//
HalpInitializeStallExecution( pPCR->Prcb->Number );
HalpEnableInterruptHandler (
DeviceUsage, // Report as device vector
V2I (PROFILE_VECTOR), // Bus interrupt level
PROFILE_VECTOR, // System IDT
PROFILE_LEVEL, // System Irql
HalpProfileInterrupt, // ISR
Latched );
} else {
//
// Without a profile interrupt we can not callibrate
// KeStallExecutionProcessor, so we inherrit the value from P0.
//
pPCR->StallScaleFactor = HalpProcessorPCR[0]->StallScaleFactor;
}
if (Sp8259PerProcessorMode & 4) {
//
// Each processor can get it's own clock device - we
// program each processor's 8254 and enable to interrupt
// on each processor
//
HalpInitializeClock ();
HalpEnableInterruptHandler (
DeviceUsage, // Report as device vector
V2I (CLOCK_VECTOR), // Bus interrupt level
CLOCK_VECTOR, // System IDT
CLOCK2_LEVEL, // System Irql
HalpNonPrimaryClockInterrupt, // ISR
Latched );
} else {
//
// This processor doesn't have a clock, so we emulate it by
// sending an ipi at clock intervals.
//
HalpIpiClock |= 1 << pPCR->Prcb->Number;
}
}
}
return TRUE;
}
BOOLEAN
HalAllProcessorsStarted (
VOID
)
{
if (HalpFeatureBits & HAL_NO_SPECULATION) {
//
// Processor doesn't perform speculative execeution,
// remove fences in critical code paths
//
HalpRemoveFences ();
}
return TRUE;
}
VOID
HalReportResourceUsage (
VOID
)
/*++
Routine Description:
The registery is now enabled - time to report resources which are
used by the HAL.
Arguments:
Return Value:
--*/
{
UNICODE_STRING UHalName;
HalInitSystemPhase2();
RtlInitUnicodeString (&UHalName, HalName);
HalpReportResourceUsage (
&UHalName, // descriptive name
Eisa // SystemPro's are Eisa machines
);
//
// Turn on MCA support if present
//
HalpMcaInit();
//
// Registry is now intialized, see if there are any PCI buses
//
HalpInitializePciBus ();
HalpInitializePciStubs ();
}
VOID
HalpInitOtherBuses (
VOID
)
{
// no other buses
}