summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halncr/i386/ncrmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/halncr/i386/ncrmp.c')
-rw-r--r--private/ntos/nthals/halncr/i386/ncrmp.c2443
1 files changed, 2443 insertions, 0 deletions
diff --git a/private/ntos/nthals/halncr/i386/ncrmp.c b/private/ntos/nthals/halncr/i386/ncrmp.c
new file mode 100644
index 000000000..0c41cbb59
--- /dev/null
+++ b/private/ntos/nthals/halncr/i386/ncrmp.c
@@ -0,0 +1,2443 @@
+/*++
+
+Copyright (c) 1992 NCR Corporation
+
+Module Name:
+
+ ncrmp.c
+
+Abstract:
+
+
+Author:
+
+ Richard Barton (o-richb) 24-Jan-1992
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "ixkdcom.h"
+#include "ncr.h"
+#include "stdio.h"
+#include "ncrnls.h"
+#include "ncrcat.h"
+#include "ncrcatp.h"
+#include "ncrsus.h"
+#include "ncrmem.h"
+
+UCHAR HalName[] = "NCR 3x series MP HAL";
+
+ADDRESS_USAGE HalpNCRIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0xF800, 0x100, // IO space reserved for CAT
+ 0xFC00, 0x100, // IO space reserved for VIC
+ 0x97, 0x2, // IO space for 3450 and up CAT SELECT/BASE port
+ 0,0
+ }
+};
+
+ULONG NCRDebug = 0x2;
+ // 0x01 - none
+ // 0x02 - stop on memory edits
+ // 0x04 - enable nmi button on 3360
+ // 0x08 - enable boot on 3550
+ // 0x10 - disable reprogram of QCC and QABC Asics for cache ownership
+ // 0x20 - Enable LARCs
+
+
+ULONG NCRProcessorsToBringup = 0xFFFF;
+ULONG NCRExistingProcessorMask = 0x00;
+ULONG NCRExistingDyadicProcessorMask = 0x00;
+ULONG NCRExistingQuadProcessorMask = 0x00;
+ULONG NCRExtendedProcessorMask = 0x00;
+ULONG NCRExtendedProcessor0Mask = 0x00;
+ULONG NCRExtendedProcessor1Mask = 0x00;
+ULONG NCRActiveProcessorMask = 0x00;
+ULONG NCRActiveProcessorLogicalMask = 0x00;
+ULONG NCRActiveProcessorCount = 0;
+ULONG NCRMaxProcessorCount = NCR_MAX_NUMBER_QUAD_PROCESSORS;
+ULONG LimitMemory = 0;
+
+ULONG NCRNeverClaimIRQs = 0xffffffff; // we start out claiming none
+
+#if 0
+
+//
+// BUGBUG - (shielint) This is requested by Ncr.
+// For now don't let cpus claim any IRQ by setting the flag to -1.
+// NCR/ATT will revisit this problem after NT4.0 release.
+//
+
+ULONG DefaultNeverClaimIRQs = 1 // lets don't claim the timer interrupt
+
+#else
+
+ULONG DefaultNeverClaimIRQs = 0xffffffff; // lets don't claim the timer interrupt
+
+#endif
+
+ULONG NCRMaxIRQsToClaim = 0;
+ULONG NCRGlobalClaimedIRQs = 0;
+
+ULONG NCRLogicalNumberToPhysicalMask[NCR_MAX_NUMBER_PROCESSORS] = {0};
+
+ULONG NCRProcessorIDR[NCR_MAX_NUMBER_PROCESSORS];
+
+ULONG NCRLarcPageMask = 0x1; // only one page by default (4 Meg)
+
+#ifdef DBG
+ULONG NCRProcessorClaimedIRQs[NCR_MAX_NUMBER_PROCESSORS] = {0};
+ULONG NCRClaimCount = 0;
+ULONG NCRStolenCount = 0;
+ULONG NCRUnclaimCount = 0;
+#endif
+
+ULONG NCRLogicalDyadicProcessorMask = 0x00;
+ULONG NCRLogicalQuadProcessorMask = 0x00;
+
+UCHAR NCRSlotExtended0ToVIC[4] = {0, 5, 2, 7};
+UCHAR NCRSlotExtended1ToVIC[4] = {1, 4, 3, 6};
+
+extern ULONG NCRPlatform;
+
+ULONG NCRStatusChangeInterruptEnabled = 0;
+
+extern ULONG HalpDefaultInterruptAffinity;
+
+extern ULONG NCRLarcEnabledPages[]; // LARC size by Voyager slot
+
+/*
+ * Struct used to report secondary MC information to the
+ * Registery
+ */
+
+typedef struct _SMC_RESOURCES {
+ CM_FULL_RESOURCE_DESCRIPTOR ConfigurationData;
+ CM_MCA_POS_DATA PosData[10];
+ } SMC_RESOURCES, *PSMC_RESOURCES;
+
+
+/*
+ * Global variables used for acessing Secondary Microchannel
+ *
+ */
+
+
+ULONG NCRSegmentIoAddress = 0xffe00000;
+PUCHAR NCRSegmentIoRegister = NULL;
+
+/*
+ * Spin lock used to lock the CAT Bus. HalpAcquireCatBusSpinLock and
+ * HalpReleaseCatBusSpinLock use this lock.
+ */
+
+KSPIN_LOCK HalpCatBusLock;
+
+
+typedef struct {
+ ULONG StartingByte;
+ ULONG Pages;
+} NCRClickMapEntry;
+#define ClickMapEntryCount 16
+#define NoExtraDescriptors 16
+
+ULONG NCRAddedDescriptorCount;
+MEMORY_ALLOCATION_DESCRIPTOR NCRAdditionalMemoryDescriptors[NoExtraDescriptors];
+
+
+PVOID NonbootStartupPhysicalPtr;
+PUCHAR NonbootStartupVirtualPtr;
+PUCHAR PageZeroVirtualPtr;
+
+VOID NCRVicIPIHandler(VOID);
+VOID NCRQicIPIHandler(VOID);
+VOID NCRClockBroadcastHandler(VOID);
+
+VOID __cdecl NCRVICErrataHandler1();
+VOID __cdecl NCRVICErrataHandler3();
+VOID __cdecl NCRVICErrataHandler4();
+VOID __cdecl NCRVICErrataHandler5();
+VOID __cdecl NCRVICErrataHandler6();
+VOID __cdecl NCRVICErrataHandler7();
+VOID __cdecl NCRVICErrataHandler15();
+
+VOID __cdecl NCRProfileHandler();
+VOID __cdecl NCRSysIntHandler();
+VOID __cdecl NCRQicSpuriousHandler();
+
+PUCHAR NCRDeterminePlatform(PBOOLEAN);
+VOID NCRFixMemory(PLOADER_PARAMETER_BLOCK);
+VOID NCRLimitMemory(PLOADER_PARAMETER_BLOCK);
+VOID NCRVerifyMemoryRange (ULONG, ULONG, PLOADER_PARAMETER_BLOCK);
+//VOID NCRAdjustMemoryDescriptor(PMEMORY_ALLOCATION_DESCRIPTOR,
+// NCRClickMapEntry *);
+VOID NCRSetupDiagnosticProcessor(PLOADER_PARAMETER_BLOCK);
+
+VOID NCRLockedOr(PULONG, ULONG);
+VOID NCRParseLoaderOptions (PUCHAR Options);
+BOOLEAN NCRGetValue (PUCHAR Options, PUCHAR String, PULONG Value);
+ULONG HalpGetCmosData (ULONG SourceLocation, ULONG SourceAddress,
+ PUCHAR Buffer, ULONG Length);
+
+VOID HalpDisableSingleBitErrorDET();
+VOID HalpInitializeSMCInterface();
+VOID HalpCatReportSMC();
+
+VOID HalEnableStatusChangeInterrupt (
+ IN ULONG
+ );
+
+BOOLEAN
+HalpTranslateSMCBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetMCAInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetSMCAInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+ULONG
+HalpNCRGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+HalpGetPosData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+#define HalpAdjustMCAResourceList HalpAdjustEisaResourceList;
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ );
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ );
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ );
+
+VOID HalpInitOtherBuses (VOID);
+
+ULONG NCRTranslateCMOSMask(ULONG);
+ULONG NCRTranslateToCMOSMask(ULONG);
+VOID NCRFindExtendedProcessors();
+VOID NCRMapIpiAddresses();
+
+VOID NCRAdjustDynamicClaims();
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#pragma alloc_text(INIT,NCRFixMemory)
+#pragma alloc_text(INIT,NCRLimitMemory)
+//#pragma alloc_text(INIT,NCRAdjustMemoryDescriptor)
+#pragma alloc_text(INIT,NCRVerifyMemoryRange)
+#pragma alloc_text(INIT,NCRSetupDiagnosticProcessor)
+#pragma alloc_text(INIT,NCRParseLoaderOptions)
+#pragma alloc_text(INIT,NCRGetValue)
+#pragma alloc_text(INIT,HalpFreeTiledCR3)
+#pragma alloc_text(INIT,HalpMapCR3)
+#pragma alloc_text(INIT,HalpBuildTiledCR3)
+#pragma alloc_text(INIT,HalpInitializeCatBusDriver)
+#pragma alloc_text(INIT,HalpDisableSingleBitErrorDET)
+#pragma alloc_text(INIT,HalpInitializeSUSInterface)
+#pragma alloc_text(INIT,HalpInitializeSMCInterface)
+#pragma alloc_text(INIT,HalpCatReportSystemModules)
+#pragma alloc_text(INIT,HalpCatReportSMC)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+ Allows MP initialization from HalInitSystem.
+
+Arguments:
+ Same as HalInitSystem
+
+Return Value:
+ none.
+
+--*/
+{
+ PKPCR pPCR;
+ UCHAR Buffer[64];
+ UCHAR id;
+ PUCHAR PlatformStringPtr;
+ ULONG MyLogicalNumber;
+ ULONG MyLogicalMask;
+ BOOLEAN ConfiguredMp;
+ ULONG trans;
+ CAT_CONTROL cat_control;
+
+ pPCR = KeGetPcr();
+ MyLogicalNumber =
+ ((PProcessorPrivateData)pPCR->HalReserved)->MyLogicalNumber;
+
+ if (Phase == 0) {
+
+ //
+ // Register NCR machine IO space, so drivers don't try to
+ // use it
+ //
+
+ HalpRegisterAddressUsage (&HalpNCRIoSpace);
+
+ NCRParseLoaderOptions (LoaderBlock->LoadOptions);
+
+ /*
+ * only the boot processor sees phase zero.
+ */
+ if ((PlatformStringPtr = NCRDeterminePlatform(&ConfiguredMp)) == NULL) {
+ sprintf(Buffer, MSG_UNKOWN_NCR_PLATFORM, NCRPlatform);
+ HalDisplayString(Buffer);
+
+ /*
+ may not want to continue here, but for now let's
+ go on, assuming a UP machine
+ */
+
+ NCRExistingProcessorMask = 0x1;
+
+ } else {
+ sprintf(Buffer, MSG_NCR_PLATFORM, PlatformStringPtr);
+ HalDisplayString(Buffer);
+
+ HalpGetCmosData(1, 0x88A, (PUCHAR)&NCRExistingProcessorMask, 4);
+
+ trans = NCRTranslateCMOSMask(NCRExistingProcessorMask);
+ NCRExtendedProcessorMask = 0x0;
+
+ DBGMSG(("HalpInitMP: CMOS NCRExistingProcessorMask = 0x%x, translated = 0x%x\n",
+ NCRExistingProcessorMask,
+ trans));
+
+ NCRExistingProcessorMask = trans;
+
+
+ // additional stuff only if MSBU machine
+
+ if (NCRPlatform != NCR3360) {
+
+ KeInitializeSpinLock(&HalpCatBusLock);
+
+ /*
+ * This is to allow tweeking the memory descriptors.
+ */
+
+ NCRFixMemory(LoaderBlock);
+
+ /*
+ * This is to determine whether we ought to save COM1
+ * for the diagnostic processors use.
+ */
+ NCRSetupDiagnosticProcessor(LoaderBlock);
+
+ }
+
+ if (NCRPlatform == NCR3360) {
+ id = 1;
+ HalpSetCmosData(1, 0x41E, &id, 1);
+
+ if (NCRDebug & 0x04) {
+ NCR3360EnableNmiButton();
+ }
+ }
+
+ }
+
+
+
+ if (LimitMemory) {
+ NCRLimitMemory (LoaderBlock);
+ }
+
+ PageZeroVirtualPtr = HalpMapPhysicalMemory(0, 1);
+
+ if ((NCRExistingProcessorMask ^ NCRActiveProcessorMask) != 0) {
+ /*
+ * there are non-boot processors to bring up...
+ *
+ * allocate some space to put the non-boot processors
+ * startup code.
+ */
+ NonbootStartupPhysicalPtr =
+ (PVOID)HalpAllocPhysicalMemory(LoaderBlock,
+ (1*1024*1024),
+ 1, FALSE);
+ NonbootStartupVirtualPtr =
+ (PUCHAR)HalpMapPhysicalMemory(NonbootStartupPhysicalPtr,
+ 1);
+ }
+
+ if (NCRPlatform != NCR3360) {
+
+ HalpInitializeSUSInterface();
+
+ DBGMSG(("HalpInitMP: End of Phase 0, NCRExistingProcessorMask = 0x%x, NCRActiveProcessorMask = 0x%x\n",
+ NCRExistingProcessorMask,
+ NCRActiveProcessorMask));
+
+ NCRMapIpiAddresses(); // Map all QIC Ipi address
+ NCRFindIpiAddress(0); // lookup processor 0 Ipi address
+
+#ifdef NEVER
+ DBGMSG(("HalpInitMP: Lets break into the debug..\n"));
+ _asm {
+ int 3
+ }
+#endif // NEVER
+
+ } else {
+ NCRExistingDyadicProcessorMask = NCRExistingProcessorMask;
+ }
+
+
+
+ } else {
+ // Phase 1...
+
+ DBGMSG(("HalpInitMP: Start Phase %d for Proc %d\n", Phase, MyLogicalNumber));
+
+
+ /*
+ * set up idt for cpis
+ */
+ HalpEnableInterruptHandler (
+ InternalUsage, // Report as device vector
+ NCR_CPI_VECTOR_BASE + NCR_IPI_LEVEL_CPI,
+ NCR_CPI_VECTOR_BASE + NCR_IPI_LEVEL_CPI, // IDT
+ IPI_LEVEL, // System Irql
+ NCRVicIPIHandler, // ISR
+ LevelSensitive );
+
+
+ NCRSetHandlerAddressToIDT((NCR_QIC_CPI_VECTOR_BASE +
+ NCR_IPI_LEVEL_CPI),
+ NCRQicIPIHandler);
+
+
+ /*
+ * put the broadcast clock handler at the
+ * same irql as the clock. that way enabling
+ * the clock enables the broadcast.
+ */
+ HalpEnableInterruptHandler (
+ InternalUsage, // Report as device vector
+ NCR_CPI_VECTOR_BASE + NCR_CLOCK_LEVEL_CPI,
+ NCR_CPI_VECTOR_BASE + NCR_CLOCK_LEVEL_CPI, // IDT
+ CLOCK2_LEVEL, // System Irql
+ NCRClockBroadcastHandler, // ISR
+ LevelSensitive );
+
+ NCRSetHandlerAddressToIDT((NCR_QIC_CPI_VECTOR_BASE +
+ NCR_CLOCK_LEVEL_CPI),
+ NCRClockBroadcastHandler);
+
+ KiSetHandlerAddressToIDT(PROFILE_VECTOR,
+ NCRProfileHandler);
+
+ /*
+ * Set up handlers for sysints
+ */
+
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SYSTEM_INTERRUPT),
+ NCRSysIntHandler);
+
+ HalEnableSystemInterrupt((NCR_CPI_VECTOR_BASE +
+ NCR_SYSTEM_INTERRUPT),
+ (HIGH_LEVEL -
+ (NCR_SYSTEM_INTERRUPT & 0x7)),
+ LevelSensitive);
+
+ // due to a VIC errata, may get a bad vector (offset
+ // by 8) for a CPI when a sysint or sbe is active.
+ // Only CPIs 0 (NCR_IPI_LEVEL_CPI) and 2
+ // (NCR_CLOCK_LEVEL_CPI) are currently are used. Thus,
+ // need to handle CPIs 0/2 at CPI vectors 8/10 as
+ // well. Since CPI 10 is not used for anything else,
+ // it can be set identical to CPI 2. However, CPI 8
+ // is used by sysint. Thus, the handler for CPI 8
+ // needs to handle this case
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_CLOCK_LEVEL_CPI + 8),
+ NCRClockBroadcastHandler);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_9),
+ NCRVICErrataHandler1);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_9 + 8),
+ NCRVICErrataHandler1);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_11_3),
+ NCRVICErrataHandler3);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_11_3 + 8),
+ NCRVICErrataHandler3);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_12_4),
+ NCRVICErrataHandler4);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_12_4 + 8),
+ NCRVICErrataHandler4);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_13_5),
+ NCRVICErrataHandler5);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_13_5 + 8),
+ NCRVICErrataHandler5);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_14_6),
+ NCRVICErrataHandler6);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_14_6 + 8),
+ NCRVICErrataHandler6);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_15_7),
+ NCRVICErrataHandler7);
+
+ NCRSetHandlerAddressToIDT((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_15_7 + 8),
+ NCRVICErrataHandler15);
+
+ //
+ // Lets go ahead an enable the interrupt for single bit/status change.
+ // The following HalEnableSystemInterrupt call will enable the interrupt
+ // that will be serviced by NCRVICErrataHandler15. The reason we enable
+ // interrupt level 7 is because the single bit/status interrupt is on vector
+ // CPI+f and is a level 7 interrupt.
+ //
+
+ if (NCRPlatform != NCR3360) {
+
+ // This code was removed since enabled this vector
+ // also enables 0x37. (Microchanel IRQ 7). If there
+ // is a device connected to IRQ 7 which has an interrupt
+ // asserted, it could start sending interrupts as soon
+ // as ncr_single_bit_error is enabled - which is before
+ // the corrisponding driver could be loaded.
+
+ HalEnableSystemInterrupt((NCR_CPI_VECTOR_BASE +
+ NCR_SMCA_15_7),
+ (HIGH_LEVEL -
+ (NCR_SMCA_15_7 & 0x7)),
+ LevelSensitive);
+
+ }
+
+
+ //
+ // If this is a processor on the Quad board then we need to handle the
+ // Qic Spurious interrupt
+ //
+
+
+ MyLogicalMask = 0x1 << MyLogicalNumber;
+
+ if (MyLogicalMask & NCRLogicalQuadProcessorMask) {
+ NCRSetHandlerAddressToIDT(NCR_QIC_SPURIOUS_VECTOR, NCRQicSpuriousHandler);
+ }
+
+ if (MyLogicalNumber != 0) {
+ /*
+ * not the boot processor
+ */
+ HalpInitializeStallExecution((CCHAR)MyLogicalNumber);
+
+ /*
+ * Allow clock interrupts on all processors
+ */
+ HalEnableSystemInterrupt(CLOCK_VECTOR,
+ CLOCK2_LEVEL, LevelSensitive);
+
+ /*
+ * Allow profile interrupt on all processors
+ */
+ HalEnableSystemInterrupt(PROFILE_VECTOR,
+ PROFILE_LEVEL, LevelSensitive);
+
+ }
+
+ NCRLockedOr(&NCRActiveProcessorLogicalMask,
+ ((PProcessorPrivateData)pPCR->HalReserved)->MyLogicalMask);
+ }
+
+ return(TRUE);
+}
+
+NCRSetHandlerAddressToIDT (
+ IN ULONG IdtEntry,
+ IN VOID (*Handler)(VOID)
+ )
+{
+
+
+ HalpRegisterVector (InternalUsage, IdtEntry, IdtEntry, (HIGH_LEVEL - (IdtEntry & 0x7)));
+ KiSetHandlerAddressToIDT (IdtEntry, Handler);
+}
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ 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:
+
+--*/
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ HalInitSystemPhase2 ();
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ MicroChannel // NCR's are MCA machines
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now online, check for any PCI buses to support
+ //
+
+ HalpInitializePciBus ();
+
+ if (NCRPlatform != NCR3360) {
+ HalpCatReportSystemModules();
+ if (NCRSegmentIoRegister != NULL) {
+ HalpCatReportSMC();
+ }
+ }
+}
+
+
+
+VOID
+NCRFixMemory (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+ Consult the firmware click map to determine what the memory
+ really looks like. Fix up the memory descriptors as necessary.
+
+ Note this function only adds memory which is in the clickmap
+ to NTs memory descriptors.
+
+Arguments:
+ Pointer to the loader block
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG BPage, EPage, Temp;
+ PVOID ClickMapPage;
+ NCRClickMapEntry *BaseOfClickMap;
+ NCRClickMapEntry *ClickMapEntryPtr;
+ MEMORY_ALLOCATION_DESCRIPTOR TempDesc;
+
+ /*
+ * First get the physical address of the firmware's click map.
+ */
+ HalpGetCmosData(1, 0xA23, (PUCHAR)&BaseOfClickMap, 4);
+ if (BaseOfClickMap == NULL) {
+#if DBG
+ HalDisplayString("NCRFixMemory: No click map?!\n");
+#endif
+ return;
+ }
+
+ /*
+ * Now get a virtual address for the firmware's click map.
+ */
+ ClickMapPage = (PVOID)((ULONG)BaseOfClickMap & ~(PAGE_SIZE - 1));
+ ClickMapPage = HalpMapPhysicalMemory(ClickMapPage, 2);
+ if (ClickMapPage == NULL) {
+#if DBG
+ HalDisplayString("NCRFixMemory: Can't map in click map?!\n");
+#endif
+ return;
+ }
+
+ ClickMapEntryPtr = (NCRClickMapEntry *)((ULONG)ClickMapPage +
+ ((ULONG)BaseOfClickMap & (PAGE_SIZE - 1)));
+ BaseOfClickMap = ClickMapEntryPtr;
+
+
+ /*
+ * Run the firmware's click map and verify NT has some type of
+ * descriptor for all memory in the click map.
+ */
+
+ // The hal allocates various memory by just removing it from the memory
+ // map, we can't add that memory back in.
+
+ // make bogus descriptor for 0-16M
+ TempDesc.MemoryType = -1;
+ TempDesc.BasePage = 0;
+ TempDesc.PageCount = 0x1000;
+ InsertHeadList(&LoaderBlock->MemoryDescriptorListHead, &TempDesc.ListEntry);
+
+ for (ClickMapEntryPtr = BaseOfClickMap;
+ ((ClickMapEntryPtr < &BaseOfClickMap[ClickMapEntryCount]) &&
+ (ClickMapEntryPtr->Pages != 0)); ++ClickMapEntryPtr) {
+
+ BPage = ClickMapEntryPtr->StartingByte >> PAGE_SHIFT;
+ EPage = BPage + ClickMapEntryPtr->Pages;
+
+ NCRVerifyMemoryRange (BPage, EPage, LoaderBlock);
+ }
+
+ RemoveEntryList(&TempDesc.ListEntry);
+
+ /*
+ * Clear the mapping to the scratchpad. Not all of it is
+ * reinitialized on a warm reset and the data may get corrupted.
+ * We mapped in two pages.
+ */
+ Temp = (ULONG)MiGetPteAddress(ClickMapPage);
+ *(PULONG)Temp = 0;
+ *((PULONG)Temp+1) = 0;
+ /*
+ * Flush the TLB.
+ */
+ _asm {
+ mov eax, cr3
+ mov cr3, eax
+ }
+}
+
+VOID NCRVerifyMemoryRange (
+ IN ULONG StartPage,
+ IN ULONG EndPage,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+ Ensure there is an NT descriptor for this memory range. Any
+ part of the range which does not have a descriptor is added
+ as available memory.
+
+Arguments:
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG sp, ep;
+ PLIST_ENTRY NextListEntry;
+ PMEMORY_ALLOCATION_DESCRIPTOR Desc;
+
+ if (StartPage == EndPage) {
+ return ;
+ }
+
+ for (NextListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ NextListEntry != &LoaderBlock->MemoryDescriptorListHead;
+ NextListEntry = NextListEntry->Flink) {
+
+ //
+ // Check each descriptor to see if it intersects with the range
+ // in question
+ //
+
+ Desc = CONTAINING_RECORD(NextListEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ sp = Desc->BasePage;
+ ep = sp + Desc->PageCount;
+
+ if (sp < StartPage) {
+ if (ep > StartPage && ep < EndPage) {
+ // bump target area past this descriptor
+ StartPage = ep;
+ }
+
+ if (ep > EndPage) {
+ //
+ // Target area is contained totally within this
+ // descriptor. This range is fully accounted for.
+ //
+
+ StartPage = EndPage;
+ }
+
+ } else {
+ // sp >= StartPage
+
+ if (sp < EndPage) {
+ if (ep < EndPage) {
+ //
+ // This descriptor is totally within the target area -
+ // check the area on either side of this desctipor
+ //
+
+ NCRVerifyMemoryRange (StartPage, sp, LoaderBlock);
+ StartPage = ep;
+
+ } else {
+ // bump begining page of this descriptor
+ EndPage = sp;
+ }
+ }
+ }
+
+ //
+ // Anything left of target area?
+ //
+
+ if (StartPage == EndPage) {
+ return ;
+ }
+ } // next descrtiptor
+
+ //
+ // The range StartPage - EndPage is a missing range from NTs descriptor
+ // list. Add it as available memory.
+ //
+
+ if (NCRAddedDescriptorCount == NoExtraDescriptors) {
+ return ;
+ }
+
+ Desc = &NCRAdditionalMemoryDescriptors[NCRAddedDescriptorCount];
+ NCRAddedDescriptorCount += 1;
+
+ Desc->MemoryType = MemoryFree;
+ Desc->BasePage = StartPage;
+ Desc->PageCount = EndPage - StartPage;
+ InsertTailList(&LoaderBlock->MemoryDescriptorListHead, &Desc->ListEntry);
+}
+
+
+
+#if 0
+VOID
+NCRFixMemory(LoaderBlockPtr)
+PLOADER_PARAMETER_BLOCK LoaderBlockPtr;
+/*++
+
+Routine Description:
+ Consult the firmware click map to determine what the memory
+ really looks like. Fix up the memory descriptors as necessary.
+
+ Note that we may remove memory descriptors due to the clickmap
+ disagreeing. However, we will only add memory descriptors to
+ the end as necessary. Therefore, in theory, it is possible to
+ have unused memory. But not likely.
+
+ New descriptors may be added due to holes in physical
+ memory caused by memory mapped adapters.
+ This means that firmware is expected to give the
+ loader (via BIOS int 15 function 88) the amount of contiguous
+ extended memory with the lowest addresses.
+
+Arguments:
+ Pointer to the loader block
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG MaxDescriptorPage;
+ ULONG Temp;
+ ULONG StartingPage;
+ PLIST_ENTRY NextListEntry;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptorPtr;
+ PMEMORY_ALLOCATION_DESCRIPTOR HighestMemoryDescriptor;
+ PMEMORY_ALLOCATION_DESCRIPTOR NextFreeMemoryDescriptor;
+ PVOID ClickMapPage;
+ NCRClickMapEntry *BaseOfClickMap;
+ NCRClickMapEntry *ClickMapEntryPtr;
+
+ /*
+ * First get the physical address of the firmware's click map.
+ */
+ HalpGetCmosData(1, 0xA23, (PUCHAR)&BaseOfClickMap, 4);
+ if (BaseOfClickMap == NULL) {
+#if DBG
+ HalDisplayString("NCRFixMemory: No click map?!\n");
+#endif
+ return;
+ }
+
+ /*
+ * Now get a virtual address for the firmware's click map.
+ */
+ ClickMapPage = (PVOID)((ULONG)BaseOfClickMap & ~(PAGE_SIZE - 1));
+ ClickMapPage = HalpMapPhysicalMemory(ClickMapPage, 2);
+ if (ClickMapPage == NULL) {
+#if DBG
+ HalDisplayString("NCRFixMemory: Can't map in click map?!\n");
+#endif
+ return;
+ }
+ ClickMapEntryPtr = (NCRClickMapEntry *)((ULONG)ClickMapPage +
+ ((ULONG)BaseOfClickMap & (PAGE_SIZE - 1)));
+ BaseOfClickMap = ClickMapEntryPtr;
+
+ /*
+ * the firmware guys say that contiguous memory
+ * will always be coalesced into one clickmap
+ * entry. we "trust but verify."
+ */
+ for (; ((ClickMapEntryPtr <
+ &BaseOfClickMap[ClickMapEntryCount-1]) &&
+ (ClickMapEntryPtr->Pages != 0)); ++ClickMapEntryPtr) {
+ Temp = ClickMapEntryPtr->StartingByte +
+ (ClickMapEntryPtr->Pages << PAGE_SHIFT);
+ while (((ClickMapEntryPtr+1)->Pages != 0) &&
+ ((ClickMapEntryPtr+1)->StartingByte <= Temp)) {
+ /*
+ * this should never happen...but if it does
+ * it's easily fixed
+ */
+ NCRClickMapEntry *NextClickMapEntryPtr;
+
+ DBGMSG(("NCRFixMemory: Fixing clickmap!?!\n"));
+
+ NextClickMapEntryPtr = ClickMapEntryPtr + 1;
+ /*
+ * note that this ending byte address is used
+ * to determine whether we iterate again.
+ */
+ Temp = NextClickMapEntryPtr->StartingByte +
+ (NextClickMapEntryPtr->Pages << PAGE_SHIFT);
+
+ if (Temp <= ClickMapEntryPtr->StartingByte) {
+ /*
+ * Whoa!!! this ain't so easy to fix.
+ * I'm not interested in sorting right now.
+ */
+ DbgBreakPoint();
+ }
+
+ /*
+ * here again, in theory, if the planets are really
+ * off their courses we could decrease the page
+ * count
+ */
+ ClickMapEntryPtr->Pages =
+ (Temp - ClickMapEntryPtr->StartingByte) >>
+ PAGE_SHIFT;
+
+ /*
+ * we just removed an entry...shift all subsequent
+ * entries down
+ */
+ for (++NextClickMapEntryPtr;
+ (NextClickMapEntryPtr <
+ &BaseOfClickMap[ClickMapEntryCount]);
+ ++NextClickMapEntryPtr) {
+ (NextClickMapEntryPtr-1)->StartingByte =
+ NextClickMapEntryPtr->StartingByte;
+ (NextClickMapEntryPtr-1)->Pages =
+ NextClickMapEntryPtr->Pages;
+ if (NextClickMapEntryPtr->Pages == 0) {
+ /*
+ * we just copied the sentinel
+ */
+ break;
+ }
+ }
+ }
+ }
+
+ /*
+ * go through all the memory descriptor entries...
+ */
+ HighestMemoryDescriptor = NULL;
+ NextListEntry = LoaderBlockPtr->MemoryDescriptorListHead.Flink;
+ while (NextListEntry != &LoaderBlockPtr->MemoryDescriptorListHead) {
+ MemoryDescriptorPtr =
+ CONTAINING_RECORD(NextListEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ /*
+ * find clickmap entry that contains this memory descriptor
+ */
+ for (ClickMapEntryPtr = BaseOfClickMap;
+ ((ClickMapEntryPtr <
+ &BaseOfClickMap[ClickMapEntryCount]) &&
+ (ClickMapEntryPtr->Pages != 0)); ++ClickMapEntryPtr) {
+ StartingPage = ClickMapEntryPtr->StartingByte >>
+ PAGE_SHIFT;
+ Temp = StartingPage + ClickMapEntryPtr->Pages;
+ MaxDescriptorPage = MemoryDescriptorPtr->BasePage +
+ MemoryDescriptorPtr->PageCount;
+
+ if ((MemoryDescriptorPtr->BasePage >= StartingPage) &&
+ (MemoryDescriptorPtr->BasePage < Temp)) {
+ /*
+ * this memory descriptor starts in this
+ * clickmap entry...
+ */
+ if (MaxDescriptorPage > Temp) {
+ /*
+ * and goes beyond
+ */
+ NCRAdjustMemoryDescriptor(MemoryDescriptorPtr,
+ ClickMapEntryPtr);
+ }
+ break;
+ }
+ if ((MaxDescriptorPage > StartingPage) &&
+ (MaxDescriptorPage <= Temp)) {
+ /*
+ * this memory descriptor ends in this
+ * clickmap entry...
+ */
+ if (MemoryDescriptorPtr->BasePage <
+ StartingPage) {
+ /*
+ * but starts before
+ */
+ NCRAdjustMemoryDescriptor(MemoryDescriptorPtr,
+ ClickMapEntryPtr);
+ }
+ break;
+ }
+ if ((MemoryDescriptorPtr->BasePage < StartingPage) &&
+ (MaxDescriptorPage > Temp)) {
+ /*
+ * this memory descriptor is a superset of
+ * this clickmap entry
+ */
+ NCRAdjustMemoryDescriptor(MemoryDescriptorPtr,
+ ClickMapEntryPtr);
+ break;
+ }
+ }
+
+ /*
+ * question...it's possible with the adjustments we did above
+ * to have a memory descriptor with zero pages. should we
+ * remove it too? i've seen other memory descriptors with
+ * zero pages. for now we don't remove them.
+ *
+ * Also the ClickMap doesn't contain any memory for regions
+ * between 640-1M, but the memory descriptor may. we leave
+ * those memory descriptors alone.
+ */
+ if ((ClickMapEntryPtr >= &BaseOfClickMap[ClickMapEntryCount] ||
+ ClickMapEntryPtr->Pages == 0) &&
+ (MemoryDescriptorPtr->BasePage < 0x9f ||
+ MemoryDescriptorPtr->BasePage+MemoryDescriptorPtr->PageCount > 0x100) ) {
+
+ /*
+ * no part of this memory descriptor was found to be
+ * contained within any clickmap entry...remove it
+ */
+ NCRAdjustMemoryDescriptor(MemoryDescriptorPtr,
+ NULL);
+ /*
+ * a memory descriptor was removed. it's probably
+ * safest to just start over
+ */
+ NextListEntry =
+ LoaderBlockPtr->MemoryDescriptorListHead.Flink;
+ continue;
+ }
+
+ /*
+ * remember the entry for the memory range with the highest
+ * address
+ */
+ if ((HighestMemoryDescriptor == NULL) ||
+ (HighestMemoryDescriptor->BasePage <
+ MemoryDescriptorPtr->BasePage)) {
+ HighestMemoryDescriptor = MemoryDescriptorPtr;
+ }
+
+ NextListEntry = NextListEntry->Flink;
+ }
+
+ /*
+ * We depend on NextListEntry being the list head later.
+ */
+
+ MaxDescriptorPage = HighestMemoryDescriptor->BasePage +
+ HighestMemoryDescriptor->PageCount;
+
+ NextFreeMemoryDescriptor = NCRAdditionalMemoryDescriptors;
+ /*
+ * Go through firmware's click map and find the entry that contains
+ * the highest memory descriptor.
+ */
+ for (ClickMapEntryPtr = BaseOfClickMap;
+ ((ClickMapEntryPtr < &BaseOfClickMap[ClickMapEntryCount]) &&
+ (ClickMapEntryPtr->Pages != 0)); ++ClickMapEntryPtr) {
+ StartingPage = ClickMapEntryPtr->StartingByte >> PAGE_SHIFT;
+ Temp = StartingPage + ClickMapEntryPtr->Pages;
+ if (MaxDescriptorPage >= Temp) {
+ continue;
+ }
+
+ /*
+ * The click map has memory above the highest memory
+ * descriptor.
+ *
+ * We always add a new memory descriptor to the list.
+ */
+
+ NextFreeMemoryDescriptor->MemoryType = MemoryFree;
+ NextFreeMemoryDescriptor->BasePage = StartingPage;
+ NextFreeMemoryDescriptor->PageCount =
+ ClickMapEntryPtr->Pages;
+ if (MaxDescriptorPage > NextFreeMemoryDescriptor->BasePage) {
+ /*
+ * another descriptor already contains part of this
+ * clickmap entry...adjust the new descriptor so
+ * that it excludes the already accounted for memory.
+ * note that we should get into this condition
+ * at most once.
+ */
+ NextFreeMemoryDescriptor->PageCount -=
+ MaxDescriptorPage -
+ NextFreeMemoryDescriptor->BasePage;
+ NextFreeMemoryDescriptor->BasePage = MaxDescriptorPage;
+ }
+ InsertTailList(NextListEntry,
+ &NextFreeMemoryDescriptor->ListEntry);
+
+ /*
+ * This is the new highest memory descriptor.
+ */
+ HighestMemoryDescriptor = NextFreeMemoryDescriptor;
+ MaxDescriptorPage = HighestMemoryDescriptor->BasePage +
+ HighestMemoryDescriptor->PageCount;
+
+ /*
+ * We can never run out since the maximum was
+ * declared.
+ */
+ ++NextFreeMemoryDescriptor;
+ }
+
+ /*
+ * Clear the mapping to the scratchpad. Not all of it is
+ * reinitialized on a warm reset and the data may get corrupted.
+ * We mapped in two pages.
+ */
+ Temp = (ULONG)MiGetPteAddress(ClickMapPage);
+ *(PULONG)Temp = 0;
+ *((PULONG)Temp+1) = 0;
+ /*
+ * Flush the TLB.
+ */
+ _asm {
+ mov eax, cr3
+ mov cr3, eax
+ }
+}
+
+VOID
+NCRAdjustMemoryDescriptor(MemoryDescriptorPtr, ClickMapEntryPtr)
+PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptorPtr;
+NCRClickMapEntry *ClickMapEntryPtr;
+/*++
+
+Routine Description:
+ Make the memory descriptor fit into the clickmap entry
+
+Arguments:
+ Pointer to the memory descriptor
+
+ Pointer to the clickmap entry
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG Temp;
+ UCHAR Buffer[64];
+
+#if DBG
+ if ((NCRDebug & 0x2) &&
+ (MemoryDescriptorPtr->MemoryType != LoaderFree) &&
+ (MemoryDescriptorPtr->MemoryType != LoaderLoadedProgram) &&
+ (MemoryDescriptorPtr->MemoryType != MemoryFirmwareTemporary) &&
+ (MemoryDescriptorPtr->MemoryType != MemoryFirmwarePermanent) &&
+ (MemoryDescriptorPtr->MemoryType != LoaderOsloaderStack)) {
+ /*
+ * looks like it's already been allocated to
+ * to something other than available
+ */
+ DbgBreakPoint();
+ }
+#endif
+
+ sprintf(Buffer,
+ "MD: Type: %d; BasePage: 0x%08X; PageCount: 0x%X\n",
+ MemoryDescriptorPtr->MemoryType,
+ MemoryDescriptorPtr->BasePage,
+ MemoryDescriptorPtr->PageCount);
+ DBGMSG((Buffer));
+
+ if (ClickMapEntryPtr == NULL) {
+ /*
+ * remove the entry from the list
+ */
+ RemoveEntryList(&MemoryDescriptorPtr->ListEntry);
+ return;
+ }
+
+ sprintf(Buffer,
+ "CM: StartingByte: 0x%08X; Pages: 0x%X\n",
+ ClickMapEntryPtr->StartingByte,
+ ClickMapEntryPtr->Pages);
+ DBGMSG((Buffer));
+
+ Temp = ClickMapEntryPtr->StartingByte >> PAGE_SHIFT;
+ if (MemoryDescriptorPtr->BasePage < Temp) {
+ /*
+ * the memory descriptor starts before the clickmap
+ * entry.
+ */
+ MemoryDescriptorPtr->PageCount -=
+ Temp - MemoryDescriptorPtr->BasePage;
+ MemoryDescriptorPtr->BasePage = Temp;
+ }
+
+ Temp += ClickMapEntryPtr->Pages;
+ if ((MemoryDescriptorPtr->BasePage +
+ MemoryDescriptorPtr->PageCount) > Temp) {
+ /*
+ * the memory descriptor ends after the clickmap
+ * entry.
+ */
+ MemoryDescriptorPtr->PageCount =
+ Temp - MemoryDescriptorPtr->BasePage;
+ }
+}
+
+#endif
+
+VOID
+NCRLimitMemory(LoaderBlockPtr)
+PLOADER_PARAMETER_BLOCK LoaderBlockPtr;
+/*++
+
+Routine Description:
+ For performance work the machine can be booted to only
+ use some of the memory in the machine with the /MAXMEM setting.
+
+ Here we will go through the memory list and remove and free memory
+ above the LimitMemory address
+
+Arguments:
+ Pointer to the loader block
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG LimitPage;
+ PLIST_ENTRY NextListEntry;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemDesc;
+
+ //
+ // Calculate highest page address
+ //
+
+ LimitPage = LimitMemory * 1024 * 1024 / PAGE_SIZE;
+
+ //
+ // Walk memory descritpor list looking for any pages above LimitPage
+ //
+
+ NextListEntry = LoaderBlockPtr->MemoryDescriptorListHead.Flink;
+ while (NextListEntry != &LoaderBlockPtr->MemoryDescriptorListHead) {
+ MemDesc = CONTAINING_RECORD(NextListEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ NextListEntry = NextListEntry->Flink;
+
+ if (MemDesc->BasePage + MemDesc->PageCount > LimitPage) {
+ //
+ // For memory descriptor which extends above LimitPage
+ // Either remove the memory descriptor from the system, or
+ // shrink it.
+ //
+
+ if (MemDesc->MemoryType != MemoryFree) {
+ DBGMSG(("NCRLimitMemory: non free memory region not freed"));
+ continue;
+ }
+
+ if (MemDesc->BasePage > LimitPage) {
+ RemoveEntryList(&MemDesc->ListEntry);
+ } else {
+ MemDesc->PageCount = MemDesc->BasePage + MemDesc->PageCount - LimitPage;
+ }
+ }
+ }
+}
+
+
+VOID
+NCRSetupDiagnosticProcessor(LoaderBlockPtr)
+PLOADER_PARAMETER_BLOCK LoaderBlockPtr;
+/*++
+
+Routine Description:
+ Determine whether the diagnostic processor is using COM1. If so,
+ make sure that the serial driver leaves COM1 alone.
+
+ Note that the interface used will have to be changed to use
+ the registry when the serial driver makes the switch.
+
+Arguments:
+ Pointer to the loader block
+
+Return Value:
+ none.
+
+--*/
+{
+ extern PUCHAR KdComPortInUse;
+
+ UCHAR FirmwareFlags;
+
+ HalpGetCmosData(1, 0x7803, (PUCHAR)&FirmwareFlags, 1);
+ if ((FirmwareFlags & 0x80) == 0) {
+ /*
+ * Kernel debug not set.
+ */
+ return;
+ }
+
+ if (KdComPortInUse == (PUCHAR)COM1_PORT) {
+ /*
+ * The debugger is using COM1.
+ */
+ return;
+ }
+
+ HalDisplayString(MSG_DIAG_ENABLED);
+ UNREFERENCED_PARAMETER(LoaderBlockPtr);
+}
+
+VOID
+NCRParseLoaderOptions (PUCHAR Options)
+{
+ ULONG l;
+
+ if (Options == NULL)
+ return;
+
+ NCRGetValue (Options, "NCRDEBUG", &NCRDebug);
+
+ NCRGetValue (Options, "MAXMEM", &LimitMemory);
+
+ if (NCRGetValue (Options, "PROCESSORS", &l)) {
+ if (l >= 1 && l <= NCR_MAX_NUMBER_QUAD_PROCESSORS)
+ NCRMaxProcessorCount = l;
+ }
+
+ if (NCRGetValue (Options, "NEVERCLAIM", &l)) {
+ DefaultNeverClaimIRQs = l;
+ }
+
+ if (NCRGetValue (Options, "LARCPAGEMASK", &l)) {
+ NCRLarcPageMask = l;
+ }
+}
+
+
+BOOLEAN
+NCRGetValue (PUCHAR Options, PUCHAR String, PULONG Value)
+{
+ PUCHAR p, s, t;
+
+ // strstr (Options, String);
+ for (p=Options; *p; p++) {
+ for (s=String, t=p; *t == *s; s++, t++) {
+ if (*s == 0)
+ break;
+ }
+
+ if (*s == 0)
+ break;
+ }
+
+ if (*p == 0) {
+ return FALSE;
+ }
+
+
+ for (p += strlen (String); *p && (*p < '0' || *p > '9'); p++) ;
+
+ // atol (p)
+ for (*Value = 0L; *p >= '0' && *p <= '9'; p++) {
+ *Value = *Value * 10 + *p - '0';
+ }
+
+ return TRUE;
+}
+
+
+
+#define MAX_PT 8
+
+extern StartPx_PMStub();
+
+
+PVOID MpFreeCR3[MAX_PT]; // remember pool memory to free
+
+ULONG
+HalpBuildTiledCR3 (
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+/*++
+
+Routine Description:
+ When the x86 processor is reset it starts in real-mode. In order to
+ move the processor from real-mode to protected mode with flat addressing
+ the segment which loads CR0 needs to have it's linear address mapped
+ to machine the phyiscal location of the segment for said instruction so
+ the processor can continue to execute the following instruction.
+
+ This function is called to built such a tiled page directory. In
+ addition, other flat addresses are tiled to match the current running
+ flat address for the new state. Once the processor is in flat mode,
+ we move to a NT tiled page which can then load up the remaining processors
+ state.
+
+Arguments:
+ ProcessorState - The state the new processor should start in.
+
+Return Value:
+ Physical address of Tiled page directory
+
+
+--*/
+{
+#define GetPdeAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 22) & 0x3ff) << 2) + (PUCHAR)MpFreeCR3[0]))
+#define GetPteAddress(va) ((PHARDWARE_PTE)((((((ULONG)(va)) >> 12) & 0x3ff) << 2) + (PUCHAR)pPageTable))
+
+// bugbug kenr 27mar92 - fix physical memory usage!
+
+ MpFreeCR3[0] = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (MpFreeCR3[0], PAGE_SIZE);
+
+ //
+ // Map page for real mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) NonbootStartupPhysicalPtr,
+ NonbootStartupPhysicalPtr,
+ PAGE_SIZE);
+
+ //
+ // Map page for protect mode stub (one page)
+ //
+ HalpMapCR3 ((ULONG) &StartPx_PMStub, NULL, 0x1000);
+
+
+ //
+ // Map page(s) for processors GDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Gdtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Gdtr.Limit);
+
+
+ //
+ // Map page(s) for processors IDT
+ //
+ HalpMapCR3 (ProcessorState->SpecialRegisters.Idtr.Base, NULL,
+ ProcessorState->SpecialRegisters.Idtr.Limit);
+
+ return MmGetPhysicalAddress (MpFreeCR3[0]).LowPart;
+}
+
+
+VOID
+HalpMapCR3 (
+ IN ULONG VirtAddress,
+ IN PVOID PhysicalAddress,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+ Called to build a page table entry for the passed page directory.
+ Used to build a tiled page directory with real-mode & flat mode.
+
+Arguments:
+ VirtAddress - Current virtual address
+ PhysicalAddress - Optional. Physical address to be mapped to, if passed
+ as a NULL then the physical address of the passed
+ virtual address is assumed.
+ Length - number of bytes to map
+
+Return Value:
+ none.
+
+--*/
+{
+ ULONG i;
+ PHARDWARE_PTE PTE;
+ PVOID pPageTable;
+ PHYSICAL_ADDRESS pPhysicalPage;
+
+
+ while (Length) {
+ PTE = GetPdeAddress (VirtAddress);
+ if (!PTE->PageFrameNumber) {
+ pPageTable = ExAllocatePool (NonPagedPool, PAGE_SIZE);
+ RtlZeroMemory (pPageTable, PAGE_SIZE);
+
+ for (i=0; i<MAX_PT; i++) {
+ if (!MpFreeCR3[i]) {
+ MpFreeCR3[i] = pPageTable;
+ break;
+ }
+ }
+ ASSERT (i<MAX_PT);
+
+ pPhysicalPage = MmGetPhysicalAddress (pPageTable);
+ PTE->PageFrameNumber = (pPhysicalPage.LowPart >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+ }
+
+ pPhysicalPage.LowPart = PTE->PageFrameNumber << PAGE_SHIFT;
+ pPhysicalPage.HighPart = 0;
+ pPageTable = MmMapIoSpace (pPhysicalPage, PAGE_SIZE, TRUE);
+
+ PTE = GetPteAddress (VirtAddress);
+
+ if (!PhysicalAddress) {
+ PhysicalAddress = (PVOID)MmGetPhysicalAddress ((PVOID)VirtAddress).LowPart;
+ }
+
+ PTE->PageFrameNumber = ((ULONG) PhysicalAddress >> PAGE_SHIFT);
+ PTE->Valid = 1;
+ PTE->Write = 1;
+
+ MmUnmapIoSpace (pPageTable, PAGE_SIZE);
+
+ PhysicalAddress = 0;
+ VirtAddress += PAGE_SIZE;
+ if (Length > PAGE_SIZE) {
+ Length -= PAGE_SIZE;
+ } else {
+ Length = 0;
+ }
+ }
+}
+
+
+
+VOID
+HalpFreeTiledCR3 (
+ VOID
+ )
+/*++
+
+Routine Description:
+ Free's any memory allocated when the tiled page directory was built.
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+{
+ ULONG i;
+
+ for (i=0; MpFreeCR3[i]; i++) {
+ ExFreePool (MpFreeCR3[i]);
+ MpFreeCR3[i] = 0;
+ }
+}
+
+
+
+
+ULONG
+HalpNCRGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+ ULONG SystemVector;
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+
+ SystemVector = BusInterruptVector + PRIMARY_VECTOR_BASE;
+
+ if (SystemVector < PRIMARY_VECTOR_BASE ||
+ HalpIDTUsage[SystemVector].Flags & IDTOwned ) {
+
+ //
+ // This is an illegal BusInterruptVector and cannot be connected.
+ //
+
+ return(0);
+ }
+
+ *Irql = (KIRQL)(HIGHEST_LEVEL_FOR_8259 - BusInterruptLevel);
+ *Affinity = HalpDefaultInterruptAffinity;
+ ASSERT(HalpDefaultInterruptAffinity);
+
+ return SystemVector;
+}
+
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ PBUS_HANDLER InternalBus;
+ PBUS_HANDLER McaBus;
+ PBUS_HANDLER Bus;
+ CAT_CONTROL cat_control;
+ UCHAR data;
+ LONG status;
+
+
+ if (NCRPlatform != NCR3360) {
+ HalpInitializeCatBusDriver();
+ HalpDisableSingleBitErrorDET();
+ HalpInitializeSMCInterface();
+ NCRFindExtendedProcessors();
+ if ((NCRDebug & 0x20) == 1) {
+ HalpInitializeLarc();
+ }
+
+
+//
+// Turn off cache ownership it NCRDebug bit is set and you only have one Quad board installed
+// in slot 1
+//
+
+ if ((NCRDebug & 0x10) && (NCRExistingProcessorMask == 0xf)) {
+
+ DBGMSG(("HalpInitOtherBuses: Changing QCC Asic on Quad\n"));
+ cat_control.Module = QUAD_LL2_A0;
+ cat_control.Asic = QCC0;
+ cat_control.Command = READ_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ DBGMSG(("HalpInitOtherBuses: QCC0 A0 Nside Config 0 read 0x%x\n", data));
+
+ data |= 0x40;
+
+ cat_control.Module = QUAD_LL2_A0;
+ cat_control.Asic = QCC0;
+ cat_control.Command = WRITE_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ cat_control.Module = QUAD_LL2_B0;
+ cat_control.Asic = QCC0;
+ cat_control.Command = READ_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ DBGMSG(("HalpInitOtherBuses: QCC0 B0 Nside Config 0 read 0x%x\n", data));
+
+ data |= 0x40;
+
+ cat_control.Module = QUAD_LL2_B0;
+ cat_control.Asic = QCC0;
+ cat_control.Command = WRITE_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ cat_control.Module = QUAD_LL2_A0;
+ cat_control.Asic = QCC1;
+ cat_control.Command = READ_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ DBGMSG(("HalpInitOtherBuses: QCC1 A0 Nside Config 0 read 0x%x\n", data));
+
+ data |= 0x40;
+
+ cat_control.Module = QUAD_LL2_A0;
+ cat_control.Asic = QCC1;
+ cat_control.Command = WRITE_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ cat_control.Module = QUAD_LL2_B0;
+ cat_control.Asic = QCC1;
+ cat_control.Command = READ_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ DBGMSG(("HalpInitOtherBuses: QCC1 B0 Nside Config 0 read 0x%x\n", data));
+
+ data |= 0x40;
+
+ cat_control.Module = QUAD_LL2_B0;
+ cat_control.Asic = QCC1;
+ cat_control.Command = WRITE_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x4;
+ status = HalpCatBusIo(&cat_control,&data);
+
+
+ cat_control.Module = QUAD_BB0;
+ cat_control.Asic = QABC;
+ cat_control.Command = READ_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0xb;
+ status = HalCatBusIo(&cat_control,&data);
+
+ DBGMSG(("HalpInitOtherBuses: QABC Nbus Config read 0x%x\n", data));
+
+ data |= 0x10;
+
+ cat_control.Module = QUAD_BB0;
+ cat_control.Asic = QABC;
+ cat_control.Command = WRITE_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0xb;
+ status = HalCatBusIo(&cat_control,&data);
+ }
+
+
+ InternalBus = HalpHandlerForBus( Internal, 0);
+ InternalBus->GetInterruptVector = HalpNCRGetSystemInterruptVector;
+
+ //
+ // Change MCA bus #0
+ //
+
+ McaBus = HalpHandlerForBus( MicroChannel, 0);
+ McaBus->GetInterruptVector = HalpGetMCAInterruptVector;
+
+
+ //
+ // Build MCA bus #1 if present
+ //
+
+ if (NCRSegmentIoRegister != NULL) {
+ Bus = HalpAllocateBusHandler (MicroChannel, Pos, 1, Internal, 0, 0);
+ Bus->GetBusData = HalpGetPosData;
+ Bus->GetInterruptVector = HalpGetSMCAInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSMCBusAddress;
+ Bus->AdjustResourceList = HalpAdjustMCAResourceList;
+ }
+ }
+}
+
+
+
+VOID
+HalpDisableSingleBitErrorDET (
+
+ )
+/*++
+
+Routine Description:
+ Disable Single Bit Error Reporting
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+{
+ CAT_CONTROL cat_control;
+ UCHAR data;
+ LONG status;
+
+//
+// Disable single bit error interrupt MMC on memory board 0
+//
+
+ cat_control.Module = MEMORY0;
+ cat_control.Asic = MMC1;
+
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = MMC1_Config1;
+ cat_control.Command = READ_REGISTER;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ if (status == CATNOERR) {
+//
+// disable reporting via mem_error_int
+// correction still enabled
+//
+ data |= MMC1_SBErr_DetectDisable;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = MMC1_Config1;
+ cat_control.Command = WRITE_REGISTER;
+ HalpCatBusIo(&cat_control,&data);
+ }
+
+
+//
+// Disable single bit error interrupt MMC on memory board 1
+//
+
+ cat_control.Module = MEMORY1;
+ cat_control.Asic = MMC1;
+
+
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = MMC1_Config1;
+ cat_control.Command = READ_REGISTER;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ if (status == CATNOERR) {
+//
+// disable reporting via mem_error_int
+// correction still enabled
+//
+ data |= MMC1_SBErr_DetectDisable;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = MMC1_Config1;
+ cat_control.Command = WRITE_REGISTER;
+ HalpCatBusIo(&cat_control,&data);
+ }
+
+}
+
+
+VOID
+HalpInitializeSMCInterface (
+
+ )
+/*++
+
+Routine Description:
+ Check for SMC board and it present setup segment register.
+
+Arguments:
+ none
+
+Return Value:
+ none
+--*/
+
+{
+ CAT_CONTROL cat_control;
+ UCHAR data;
+ LONG status;
+ PHYSICAL_ADDRESS physical_address;
+ PUCHAR mapped_segment_address;
+
+ cat_control.Module = SECONDARYMC;
+ cat_control.Asic = CAT_I;
+ cat_control.Command = READ_REGISTER;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0;
+ status = HalpCatBusIo(&cat_control,&data);
+
+ if (status != CATNOMOD) {
+
+/*
+ * SMC is installed in this unit
+ */
+ DBGMSG(("HalpInitializeSMCInterface: SMC has been detected...\n"));
+
+ physical_address.HighPart = 0;
+ physical_address.LowPart = NCRSegmentIoAddress;
+
+ mapped_segment_address = (PUCHAR) MmMapIoSpace(physical_address, sizeof(UCHAR), FALSE);
+
+ if (mapped_segment_address != NULL) {
+ NCRSegmentIoRegister = mapped_segment_address;
+ }
+
+/*RMU temp fix for arb control register on DMA asic. */
+
+ WRITE_PORT_UCHAR((PUCHAR)0x10090, (UCHAR)0x8f);
+ }
+}
+
+
+
+
+
+
+VOID
+HalpCatReportSMC (
+ )
+
+/*++
+
+Routine Description:
+ Place information about system modules into the registry.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ PMODULE module;
+ PASIC asic;
+
+ PWSTR smc_path = L"\\Registry\\Machine\\Hardware\\DESCRIPTION\\System\\MultifunctionAdapter\\1";
+
+
+ UNICODE_STRING unicode_smc;
+ OBJECT_ATTRIBUTES smc_attributes;
+ HANDLE smc_handle;
+
+
+ UNICODE_STRING unicode_name;
+
+ UNICODE_STRING unicode_mca;
+
+ NTSTATUS status;
+ ULONG tmp;
+
+ CONFIGURATION_COMPONENT component;
+
+ ULONG ConfigurationDataLength;
+ SMC_RESOURCES SmcConfig;
+ int i;
+
+
+/*
+ *
+ */
+ RtlInitUnicodeString(&unicode_smc,smc_path);
+
+ InitializeObjectAttributes( &smc_attributes, &unicode_smc,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status = ZwCreateKey(&smc_handle, KEY_READ | KEY_WRITE, &smc_attributes, 0,
+ (PUNICODE_STRING)NULL, REG_OPTION_VOLATILE, NULL);
+
+
+
+ RtlInitUnicodeString(&unicode_name,L"Component Information");
+ RtlZeroMemory (&component, sizeof(CONFIGURATION_COMPONENT));
+ component.AffinityMask = 0xffffffff;
+
+ status = ZwSetValueKey(
+ smc_handle,
+ &unicode_name,
+ 0,
+ REG_BINARY,
+ &component.Flags,
+ FIELD_OFFSET(CONFIGURATION_COMPONENT, ConfigurationDataLength) -
+ FIELD_OFFSET(CONFIGURATION_COMPONENT, Flags)
+ );
+
+
+ RtlInitUnicodeString(&unicode_name,L"Configuration Data");
+ RtlZeroMemory (&SmcConfig, sizeof(SMC_RESOURCES));
+
+ ConfigurationDataLength = sizeof(SMC_RESOURCES);
+
+ //
+ // Set up InterfaceType and BusNumber for the component.
+ //
+
+ SmcConfig.ConfigurationData.InterfaceType = MicroChannel;
+ SmcConfig.ConfigurationData.BusNumber = 1;
+ SmcConfig.ConfigurationData.PartialResourceList.Count = 1;
+
+ SmcConfig.ConfigurationData.PartialResourceList.PartialDescriptors[0].Type =
+ CmResourceTypeDeviceSpecific;
+
+ SmcConfig.ConfigurationData.PartialResourceList.PartialDescriptors[0].ShareDisposition =
+ CmResourceShareUndetermined;
+
+ SmcConfig.ConfigurationData.PartialResourceList.PartialDescriptors[0].u.DeviceSpecificData.DataSize =
+ sizeof(CM_MCA_POS_DATA)*10;
+
+ for (i = 0; i < 8; i++) {
+ HalGetBusData(Pos, 1, i, &SmcConfig.PosData[i], sizeof(CM_MCA_POS_DATA));
+ }
+
+
+ //
+ // Write the newly constructed configuration data to the hardware registry
+ //
+
+ status = ZwSetValueKey(
+ smc_handle,
+ &unicode_name,
+ 0,
+ REG_FULL_RESOURCE_DESCRIPTOR,
+ &SmcConfig,
+ ConfigurationDataLength
+ );
+
+
+
+ RtlInitUnicodeString(&unicode_name,L"Identifier");
+ RtlInitUnicodeString(&unicode_mca,L"MCA");
+ status = ZwSetValueKey(smc_handle, &unicode_name, 0, REG_SZ,
+ unicode_mca.Buffer,
+ unicode_mca.Length + sizeof(UNICODE_NULL));
+
+ status = ZwClose(smc_handle);
+
+}
+
+
+
+
+VOID
+HalSetStatusChangeInterruptState(
+ ULONG State
+ )
+
+/*++
+
+Routine Description:
+ This HAL function will enable or disable the revectoring of the
+ Status Change Interrupt to vector 57.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+{
+ if (State) {
+ NCRStatusChangeInterruptEnabled = 0x1;
+ } else {
+ NCRStatusChangeInterruptEnabled = 0x0;
+ }
+
+}
+
+
+
+
+ULONG
+NCRTranslateCMOSMask(
+ ULONG CmosMask
+ )
+
+/*++
+
+Routine Description:
+ This function translates the CMOS processor Mask into what we want to use.
+ This function must change for 32 way
+
+ CMOS format is: each nibble contains all processors 0 in the system where each bit
+ position denotes the processor slot. Therefore a system with
+ one Quad board has a mask of (0x1111), 2 Quad boards has a
+ mask of (0x3333), 3 Quad boards has a mask of (0x7777), and
+ 4 Quad boards has a mask of (0xffff).
+
+ Our format is: each nibble contains all processors on one Quad board where each
+ bit position denotes the processor on one board. Therefore a
+ system with one Quad board has a mask of (0x000f), 2 Quad boards
+ has a mask of (0x00ff), 3 Quad boards has a mask of (0x0ffff), and
+ 4 Quad boards has a mask of (xffff);
+
+Arguments:
+
+Return Value:
+ The Processor Mask that the Hal wants to use for bringing up the system.
+
+
+--*/
+
+{
+ ULONG working_mask = CmosMask;
+ ULONG existing_mask = 0x0;
+ int i, j;
+
+ // loop thru each processor number
+
+ for (i = 0; i < 4; i++ ) {
+
+ // loop thru each processor slot
+
+ for (j = 0; j < 4; j++) {
+ if (working_mask & 0x1) {
+ existing_mask |= ((1 << i) << (j<<2));
+ }
+ working_mask >>= 1;
+ }
+ }
+
+ return existing_mask;
+}
+
+
+ULONG
+NCRTranslateToCMOSMask(
+ ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+ Do the oppsite of NCRTranslateCMOSMask()
+
+Arguments:
+
+Return Value:
+ The Processor Mask that CMOS uses.
+
+
+--*/
+
+{
+ ULONG working_mask = Mask;
+ ULONG cmos_mask = 0x0;
+ int i;
+
+ for (i = 0; i < 4; i++ ) {
+
+ if (working_mask & 1) {
+ cmos_mask |= (0x1 << i);
+ }
+
+ if (working_mask & 2) {
+ cmos_mask |= (0x10 << i);
+ }
+ working_mask >>= 4;
+ }
+ return cmos_mask;
+}
+
+
+VOID
+NCRFindExtendedProcessors(
+ )
+/*++
+
+Routine Description:
+ Loop over the CAT bus and find all extended processors
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ CAT_CONTROL cat_control;
+ UCHAR data;
+ UCHAR qabc_ext;
+ LONG status;
+ UCHAR module;
+ int slot;
+
+
+ for(slot = 0; slot < 4; slot++) {
+
+ switch (slot) {
+ case 0:
+ module = QUAD_BB0;
+ break;
+ case 1:
+ module = QUAD_BB1;
+ break;
+ case 2:
+ module = QUAD_BB2;
+ break;
+ case 3:
+ module = QUAD_BB3;
+ break;
+ }
+ cat_control.Module = module;
+ cat_control.Asic = QABC;
+ cat_control.Command = READ_SUBADDR;
+ cat_control.NumberOfBytes = 1;
+ cat_control.Address = 0x8;
+ status = HalpCatBusIo(&cat_control,&qabc_ext);
+
+ if (status == CATNOERR) {
+// NCRExtendedProcessor0Mask |= (qabc_ext & 0xf) << (qabc_ext << 2);
+ NCRExtendedProcessor0Mask |= (qabc_ext & 0xf) << (slot << 2);
+ NCRExtendedProcessor1Mask |= (qabc_ext >> 4) << (slot << 2);
+ }
+ }
+ NCRExtendedProcessorMask = NCRExtendedProcessor0Mask | NCRExtendedProcessor1Mask;
+
+ DBGMSG(("NCRFindExtendedProcessors: Extended 0 = 0x%x, 1 = 0x%x\n",
+ NCRExtendedProcessor0Mask, NCRExtendedProcessor1Mask));
+}
+
+
+
+
+
+
+
+
+VOID
+NCRAdjustDynamicClaims(
+ )
+/*++
+
+Routine Description:
+ Determine how man interrupts a processor should claim. This is called when
+ processors are enabled and with interrups are enabled and disabled
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+
+ ULONG processors = 0;
+ ULONG max_claimable_irqs = 0;
+ ULONG processor;
+ ULONG irq_count;
+ ULONG mask;
+
+ //
+ // Count the number of processors that can take device interrupts.
+ //
+
+ for (mask = HalpDefaultInterruptAffinity; mask != 0; mask >>= 1) {
+ if (mask & 0x1) {
+ processors++;
+ }
+ }
+
+ for (processor = 0; processor < NCRActiveProcessorCount; processor++) {
+
+ mask = NCRProcessorIDR[processor];
+ mask |= NCRNeverClaimIRQs; // do not count never claim IRQs
+
+ irq_count = 0;
+
+ for (mask = ~mask; (mask != 0); mask >>= 1) {
+ if (mask & 0x1) {
+ irq_count++;
+ }
+ }
+ if (irq_count > max_claimable_irqs) {
+ max_claimable_irqs = irq_count;
+ }
+ }
+
+ if ((max_claimable_irqs % processors) == 0) {
+ max_claimable_irqs /= processors;
+ } else {
+ max_claimable_irqs /= processors;
+ max_claimable_irqs++;
+ }
+ if (max_claimable_irqs == 0) {
+ max_claimable_irqs = 1;
+ }
+ NCRMaxIRQsToClaim = max_claimable_irqs;
+}
+
+
+#ifdef DBG
+
+
+VOID
+NCRConsoleDebug(
+ ULONG MsgNumber,
+ ULONG Data
+ )
+
+{
+ CHAR buffer[256];
+
+ switch (MsgNumber) {
+
+ case 1:
+ sprintf(buffer, "HalInitializeProcessor called for processor %d\n", Data);
+ HalDisplayString(buffer);
+ break;
+ case 2:
+ sprintf(buffer, "HalStartNextProcessor trying to wakeup 0x%x\n", Data);
+ HalDisplayString(buffer);
+ break;
+ case 3:
+ sprintf(buffer, "HalStartNextProcessor Processor is now awake\n", Data);
+ HalDisplayString(buffer);
+ break;
+
+
+
+ }
+}
+
+#endif
+
+
+NTSTATUS
+HalpGetMcaLog (
+ OUT PMCA_EXCEPTION Exception,
+ OUT PULONG ReturnedLength
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+NTSTATUS
+HalpMcaRegisterDriver(
+ IN PMCA_DRIVER_INFO DriverInfo
+ )
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+
+ULONG
+FASTCALL
+HalSystemVectorDispatchEntry (
+ IN ULONG Vector,
+ OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+ OUT PKINTERRUPT_ROUTINE *NoConnection
+ )
+{
+ return FALSE;
+}