VOID HalpInitializeDisplay( VOID ) /*++ Routine Description: Initializes the VGA display. This uses HalpMapPhysicalMemory to map the video buffer at 0xb8000 - 0xba000 into high virtual memory. Arguments: None. Return Value: None. --*/ { if (HalpDisplayInitialized == FALSE) { HalpDisplayInitialized = TRUE; KeInitializeSpinLock(&HalpDisplayLock); // // If somebody called HalDisplayString before Phase 0 initialization, // the video buffer has already been mapped and cleared, and a // message has already been displayed. So we don't want to clear // the screen again, or map the screen again. // // // Map two pages of memory starting at physical address 0xb8000. // VideoBuffer = (PUSHORT)HalpMapPhysicalMemory((PVOID)0xb8000,2); HalpClearDisplay(); } }
VOID HalpResetThisProcessor ( VOID ) /*++ Routine Description: This procedure is called by the HalpReboot routine. It is called in response to a system reset request. This routine is called by the reboot ISR (linked to APIC_REBOOT_VECTOR). The HalpResetAllProcessors generates the reboot request via the APIC's ICR. The function of this routine is to perform any processor specific shutdown code needed and then reset the system (on the BSP==P0 only). This routine will NOT return. --*/ { PUSHORT Magic; ULONG ThisProcessor = 0; ULONG i, j, max, RedirEntry; ULONG AllProcessorsHalted; struct ApicIoUnit *IoUnitPtr; ThisProcessor = KeGetPcr()->Prcb->Number; // // Do whatever is needed to this processor to restore // system to a bootable state // pLocalApic[LU_TPR/4] = 0xff; pLocalApic[LU_TIMER_VECTOR/4] = (APIC_SPURIOUS_VECTOR |PERIODIC_TIMER | INTERRUPT_MASKED); pLocalApic[LU_INT_VECTOR_0/4] = (APIC_SPURIOUS_VECTOR | INTERRUPT_MASKED); pLocalApic[LU_INT_VECTOR_1/4] = ( LEVEL_TRIGGERED | ACTIVE_HIGH | DELIVER_NMI | INTERRUPT_MASKED | NMI_VECTOR); if (HalpMpInfoTable.ApicVersion != APIC_82489DX) { pLocalApic[LU_FAULT_VECTOR/4] = APIC_FAULT_VECTOR | INTERRUPT_MASKED; } if (ThisProcessor == 0) { _asm { lock dec HalpProcessorsNotHalted } // // we are running on the BSP, wait for everyone to // complete the re-initialization code above // AllProcessorsHalted = 0; while(!AllProcessorsHalted) { _asm { lock and HalpProcessorsNotHalted,0xffffffff jnz EveryOneNotDone inc AllProcessorsHalted EveryOneNotDone: } // asm block } // NOT AllProcessorsHalted KeStallExecutionProcessor(100); // // Write the Shutdown reason code, so the BIOS knows // this is a reboot // WRITE_PORT_UCHAR(CMOS_CTRL, 0x0f); // CMOS Addr 0f WRITE_PORT_UCHAR(CMOS_DATA, 0x00); // Reason Code Reset Magic = HalpMapPhysicalMemory(0, 1); Magic[0x472 / sizeof(USHORT)] = 0x1234; // warm boot // // If required, disable APIC mode // if (HalpMpInfoTable.IMCRPresent) { _asm { mov al, ImcrPort out ImcrRegPortAddr, al } KeStallExecutionProcessor(100); _asm { mov al, ImcrDisableApic out ImcrDataPortAddr, al } }
VOID 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; pPCR = KeGetPcr(); // // Increment a count of the number of processors // running NT, This could be different from the // number of enabled processors, if one or more // of the processor failed to start. // if (Phase == 1) HalpMpInfoTable.NtProcessors++; #ifdef DEBUGGING sprintf(Cbuf, "HalpInitMP: Number of Processors = 0x%x\n", HalpMpInfoTable.NtProcessors); HalpDisplayString(Cbuf); #endif if (Phase == 0) { #if defined(NT_UP) // // On UP build - done // return ; #endif // // Map the 1st Physical page of memory // Halp1stPhysicalPageVaddr = HalpMapPhysicalMemory (0, 1); // // Allocate some low memory for processor bootup stub // MpLowStubPhysicalAddress = (PVOID)HalpAllocPhysicalMemory (LoaderBlock, LOW_MEMORY, 1, FALSE); if (!MpLowStubPhysicalAddress) { // // Can't get memory // #if DBG DbgPrint("HAL: can't allocate memory to start processors\n"); #endif return; } MpLowStub = (PCHAR) HalpMapPhysicalMemory (MpLowStubPhysicalAddress, 1); } else { // // Phase 1 for another processor // if (pPCR->Prcb->Number != 0) { HalpIpiClock = 0xff; } } }
PUCHAR NCRDeterminePlatform( OUT PBOOLEAN IsConfiguredMp ) /*++ Routine Description: Determine on which NCR platform we are running. For now just display a message. Later we may not continue the boot if we're on an unrecognized platform. Arguments: none. Return Value: Pointer to character string identifying which NCR platform. NULL means it is unrecognized, and we shouldn't continue. --*/ { BOOLEAN Matchfound; MSBUPlatformMapEntry *MSBUPlatformMapPtr; PVOID BIOSPagePtr; PUCHAR StringPtr; PUCHAR CopyrightPtr; PUCHAR SearchPtr; UCHAR CpuFlags; // first check for a WPD platform by searching the 0xE000 BIOS segment // for a ROM string that identifies this system as a 3360 // get virtual address to the BIOS region (assuming region is both // page aligned and multiple pages in size) BIOSPagePtr = HalpMapPhysicalMemory((PVOID) WPDStringIDRangeStart, (WPDStringIDRangeSize >> 12)); if (BIOSPagePtr != NULL) { SearchPtr = BIOSPagePtr; // begin search at start of region Matchfound = FALSE; // search until string is found or we are beyond the region while (!Matchfound && (SearchPtr <= (PUCHAR)((ULONG)BIOSPagePtr + WPDStringIDRangeSize - WPDStringIDLength))) { // see if SearchPtr points to the desired string StringPtr = (PUCHAR)((ULONG)SearchPtr++); CopyrightPtr = WPDStringID; // continue compare as long as characters compare // and not at end of string while ((Matchfound = (*CopyrightPtr++ == *StringPtr++)) && (CopyrightPtr < WPDStringID + WPDStringIDLength)); } // see if string was found (i.e., if this is a 3360) if (Matchfound) { // store system identifier ("3360") for later HAL use NCRPlatform = NCR3360; // read CPU good flags from CMOS and determine if MP ReadCMOS(0x88A, 1, &CpuFlags); // *IsConfiguredMp = (CpuFlags & (CpuFlags-1)) ? TRUE : FALSE; // This is an MP hal *IsConfiguredMp = TRUE; return(WPDPlatformName); } } // now check for an MSBU platform /* * Map in the BIOS text so we can look for our copyright string. */ BIOSPagePtr = (PVOID)((ULONG)MSBUCopyrightPhysicalPtr & ~(PAGE_SIZE - 1)); BIOSPagePtr = HalpMapPhysicalMemory(BIOSPagePtr, 2); if (BIOSPagePtr == NULL) return(NULL); StringPtr = (PUCHAR)((ULONG)BIOSPagePtr + ((ULONG)MSBUCopyrightPhysicalPtr & (PAGE_SIZE - 1))) + (MSBUCopyrightStringLen - 1); CopyrightPtr = MSBUCopyrightString + (MSBUCopyrightStringLen - 1); do { Matchfound = ((*CopyrightPtr == '?') || (*CopyrightPtr == *StringPtr)); --CopyrightPtr; --StringPtr; } while (Matchfound && (CopyrightPtr >= MSBUCopyrightString)); // // /* // * Clear the mapping to BIOS. We mapped in two pages. // */ // BIOSPagePtr = MiGetPteAddress(BIOSPagePtr); // *(PULONG)BIOSPagePtr = 0; // *(((PULONG)BIOSPagePtr)+1) = 0; // /* // * Flush the TLB. // */ // _asm { // mov eax, cr3 // mov cr3, eax // } // if (Matchfound) { /* * must be an MSBU machine..determine which. */ ReadCMOS(0xB16, 4, (PUCHAR)&NCRPlatform); for (MSBUPlatformMapPtr = MSBUPlatformMap; (MSBUPlatformMapPtr->ClassFromFirmware != 0); ++MSBUPlatformMapPtr) { if (MSBUPlatformMapPtr->ClassFromFirmware == NCRPlatform) { *IsConfiguredMp = TRUE; return(MSBUPlatformMapPtr->PlatformName); } } /* * prerelease version of firmware had this machine class * at the wrong offset into CMOS. until all those versions * of firmware are extinguished from the face of the earth * we should recognize them with this: */ ReadCMOS(0xAB3, 4, (PUCHAR)&NCRPlatform); for (MSBUPlatformMapPtr = MSBUPlatformMap; (MSBUPlatformMapPtr->ClassFromFirmware != 0); ++MSBUPlatformMapPtr) { if (MSBUPlatformMapPtr->ClassFromFirmware == NCRPlatform) { *IsConfiguredMp = TRUE; return(MSBUPlatformMapPtr->PlatformName); } } } return(NULL); }
BOOLEAN ASTInitEBI2() /*++ Routine Description: Initialize the AST EBI II environment. Only called if an AST machine with EBI II capability. Gets table of EBI II call addresses in ebi_call_table. Sets up EBI2_MMIOTable (EBI II Memory Mapped I/O Table). Arguments: none. Return Value: True if EBI II successfully initialized. False otherwise. --*/ { ULONG i; //ULONG *Alias = (ULONG *)&EBI2_CallTab; //ebi_iiSig *Sig = (ebi_iiSig*)((ULONG)BiosPtr + EBI_II_SIGNATURE); //ULONG *OffTab; IOInfoTable IOInfo[MAX_EBI_SLOTS]; dWord NumSlots; ULONG Pages; procConfigData ConfigData; ULONG ProcCount; //*** v-quangp: This table is already build at astdetct.c ** // // Build the EBI II offset table // // // OffTab =(ULONG *) ((ULONG)BiosPtr + (REAL_TO_LIN(Sig->seg,Sig->off) - // REAL_TO_LIN(BIOS_SEG, 0))); // for( i = 0; i < ( sizeof( offsetTable ) / sizeof( ULONG )); i++ ) // Alias[i] = OffTab[i] + (ULONG)BiosPtr; // // // Get the number of "slots" (logical address spaces) // EBI2_CallTab.GetNumSlots( &NumSlots ); if (NumSlots > MAX_EBI_SLOTS) { DisplPanel(HALSlotProblem); return(FALSE); } // // Get the Memory Mapped I/O Information // if ( (EBI2_CallTab.GetMMIOTable( IOInfo ))) { DisplPanel(HALMMIOProblem); return(FALSE); } for( i = 0; i < NumSlots; i++ ) if( IOInfo[i].length ) { // // Allocate some memory for EBI II // if ( IOInfo[i].flags & ALLOCATE_RAM ) { if (IOInfo[i].length > MAX_EBI_MEMORY) { DisplPanel(HALMemoryProblem); return(FALSE); } EBI2_MMIOTable[i] = EbiMemory; } // // Allocate a virtual address spanning the memory mapped I/O range // for a given slot. // else { Pages = IOInfo[i].length / PAGE_SIZE; if ( IOInfo[i].length % PAGE_SIZE ) Pages++; EBI2_MMIOTable[i] = HalpMapPhysicalMemory( (PVOID)IOInfo[i].address.low, Pages ); if ( EBI2_MMIOTable[i] == NULL ) { DisplPanel(HALPhysicalAllocProblem); return(FALSE); } } } // // Initialize EBI II // if ( (EBI2_CallTab.InitEBI)( EBI2_MMIOTable ) ) { DisplPanel(HALEBIInitProblem); return(FALSE); } // // Put NT on the front panel display // EBI2_CallTab.SetPanelAlphaNum( EBI2_MMIOTable, " NT "); // // Find out the number of good processors // if ( (EBI2_CallTab.GetNumProcs)( EBI2_MMIOTable, &ProcCount ) ) { DisplPanel(HALEBIGetProcProblem); return(FALSE); } EBI2_ProcCnt = ProcCount; for (i=0; i<ProcCount; i++) if ( (EBI2_CallTab.GetProcConf)( EBI2_MMIOTable, i, &ConfigData ) ) EBI2_ProcCnt--; if (EBI2_ProcCnt == 0) { DisplPanel(HALEBINoProcsProblem); return(FALSE); } MpCount = EBI2_ProcCnt - 1; // // Turn on the front panel cpu activity bar graph in histogram mode // EBI2_CallTab.SetPanelProcGraphMode( EBI2_MMIOTable, 0 ); // // Get EBI2 Revision // if ( (EBI2_CallTab.GetRevision( EBI2_MMIOTable, &EBI2_revision ))) { DisplPanel(HALGetRevisionProblem); return(FALSE); } return(TRUE); }
VOID HalpReboot ( VOID ) /*++ Routine Description: This procedure resets the CMOS clock to the standard timer settings so the bios will work, and then issues a reset command to the keyboard to cause a warm boot. It is very machine dependent, this implementation is intended for PC-AT like machines. This code copied from the "old debugger" sources. N.B. Will NOT return. --*/ { UCHAR Scratch; PUSHORT Magic; // // By sticking 0x1234 at physical location 0x472, we can bypass the // memory check after a reboot. // Magic = HalpMapPhysicalMemory(0, 1); Magic[0x472 / sizeof(USHORT)] = 0x1234; // // Turn off interrupts // HalpAcquireCmosSpinLock(); _asm { cli } // // Reset the cmos clock to a standard value // (We are setting the periodic interrupt control on the MC147818) // // // Disable periodic interrupt // WRITE_PORT_UCHAR(CMOS_CTRL, 0x0b); // Set up for control reg B. KeStallExecutionProcessor(1); Scratch = READ_PORT_UCHAR(CMOS_DATA); KeStallExecutionProcessor(1); Scratch &= 0xbf; // Clear periodic interrupt enable WRITE_PORT_UCHAR(CMOS_DATA, Scratch); KeStallExecutionProcessor(1); // // Set "standard" divider rate // WRITE_PORT_UCHAR(CMOS_CTRL, 0x0a); // Set up for control reg A. KeStallExecutionProcessor(1); Scratch = READ_PORT_UCHAR(CMOS_DATA); KeStallExecutionProcessor(1); Scratch &= 0xf0; // Clear rate setting Scratch |= 6; // Set default rate and divider WRITE_PORT_UCHAR(CMOS_DATA, Scratch); KeStallExecutionProcessor(1); // // Set a "neutral" cmos address to prevent weirdness // (Why is this needed? Source this was copied from doesn't say) // WRITE_PORT_UCHAR(CMOS_CTRL, 0x15); KeStallExecutionProcessor(1); // // for 3450/3550 machines - Set shutdown flag to reset // if ((NCRPlatform == NCR3450) || (NCRPlatform == NCR3550)) { WRITE_PORT_UCHAR(CMOS_CTRL, SHUT_DOWN); WRITE_PORT_UCHAR(CMOS_DATA, SHUT5); } // // Send the reset command to the keyboard controller // WRITE_PORT_UCHAR(KEYBPORT, RESETCMD); _asm { hlt } }