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