/*++ Copyright (c) 1991 Microsoft Corporation Copyright (c) 1992 Intel Corporation All rights reserved INTEL CORPORATION PROPRIETARY INFORMATION This software is supplied to Microsoft under the terms of a license agreement with Intel Corporation and may not be copied nor disclosed except in accordance with the terms of that agreement. Module Name: mpdebug.c Abstract: This module has some useful modules for debug aid. Author: Ron Mosgrove (Intel) - Aug 1993. Environment: Kernel mode or from textmode setup. Revision History: --*/ #ifndef _NTOS_ #include "halp.h" #endif #include "apic.inc" #include "pcmp_nt.inc" #include "stdio.h" #define PCMP_TABLE_PTR_BASE 0x09f000 #define PCMP_TABLE_PTR_OFFSET 0x00000c00 // Create dummy PC+MP table at physical address 400K #define PCMP_TEST_TABLE 0x64000 #define TEST_FLOAT_PTR 0x7d000 extern struct PcMpTable *PcMpTablePtr, *PcMpDefaultTablePtrs[]; //extern struct HalpMpInfo *HalpMpInfoPtr; CHAR Cbuf[120]; UCHAR ComputeCheckSum( IN PUCHAR SourcePtr, IN USHORT NumOfBytes ); #ifdef OLD_DEBUG extern struct PcMpConfigTable *PcMpTablePtr; #endif #ifdef DEBUGGING ULONG HalpUseDbgPrint = 0; void HalpDisplayString( IN PVOID String ) { if (!HalpUseDbgPrint) { HalDisplayString(String); } else { DbgPrint(String); } } void HalpDisplayItemBuf( IN UCHAR Length, IN PUCHAR Buffer, IN PVOID Name ) { ULONG i; CHAR TmpBuf[80]; sprintf(TmpBuf, " %s -", Name); HalpDisplayString(TmpBuf); for (i=0; i< Length; i++) { sprintf(TmpBuf, " 0x%x", Buffer[i]); HalpDisplayString(TmpBuf); } HalpDisplayString("\n"); } void HalpDisplayULItemBuf( IN UCHAR Length, IN PULONG Buffer, IN PVOID Name ) { ULONG i; CHAR TmpBuf[80]; sprintf(TmpBuf, " %s -", Name); HalpDisplayString(TmpBuf); for (i=0; i< Length; i++) { sprintf(TmpBuf, " 0x%lx", Buffer[i]); HalpDisplayString(TmpBuf); } HalpDisplayString("\n"); } void HalpDisplayItem( IN ULONG Item, IN PVOID ItemStr ) { CHAR TmpBuf[80]; sprintf(TmpBuf, " %s - 0x%x\n", ItemStr, Item); HalpDisplayString(TmpBuf); } VOID HalpDisplayBIOSSysCfg( IN struct SystemConfigTable *SysCfgPtr ) { HalpDisplayString("BIOS System Configuration Table\n"); HalpDisplayItem(SysCfgPtr->ModelType, "ModelType"); HalpDisplayItem(SysCfgPtr->SubModelType, "SubModelType"); HalpDisplayItem(SysCfgPtr->BIOSRevision, "BIOSRevision"); HalpDisplayItemBuf(3,SysCfgPtr->FeatureInfoByte,"FeatureInfoByte"); HalpDisplayItem(SysCfgPtr->MpFeatureInfoByte1, "MpFeatureInfoByte1"); HalpDisplayItem(SysCfgPtr->MpFeatureInfoByte2, "MpFeatureInfoByte2"); } VOID HalpDisplayLocalUnit( ) { ULONG Data; PKPCR pPCR; pPCR = KeGetPcr(); sprintf(Cbuf, "\nLocal Apic for P%d\n", pPCR->Prcb->Number); HalpDisplayString(Cbuf); #define DisplayLuReg(Reg, RegStr) Data = *((PVULONG) (LOCALAPIC+Reg)); \ HalpDisplayItem(Data , RegStr); DisplayLuReg( LU_ID_REGISTER , "LU_ID_REGISTER" ); DisplayLuReg( LU_VERS_REGISTER, "LU_VERS_REGISTER" ); DisplayLuReg( LU_TPR, "LU_TPR"); DisplayLuReg( LU_APR, "LU_APR"); DisplayLuReg( LU_PPR, "LU_PPR"); DisplayLuReg( LU_EOI, "LU_EOI"); DisplayLuReg( LU_REMOTE_REGISTER, "LU_REMOTE_REGISTER"); DisplayLuReg( LU_LOGICAL_DEST, "LU_LOGICAL_DEST"); DisplayLuReg( LU_DEST_FORMAT, "LU_DEST_FORMAT"); DisplayLuReg( LU_SPURIOUS_VECTOR , "LU_SPURIOUS_VECTOR" ); DisplayLuReg( LU_ISR_0, "LU_ISR_0"); DisplayLuReg( LU_TMR_0, "LU_TMR_0"); DisplayLuReg( LU_IRR_0, "LU_IRR_0"); DisplayLuReg( LU_ERROR_STATUS, "LU_ERROR_STATUS"); DisplayLuReg( LU_INT_CMD_LOW, "LU_INT_CMD_LOW"); DisplayLuReg( LU_INT_CMD_HIGH, "LU_INT_CMD_HIGH"); DisplayLuReg( LU_TIMER_VECTOR, "LU_TIMER_VECTOR"); DisplayLuReg( LU_INT_VECTOR_0, "LU_INT_VECTOR_0"); DisplayLuReg( LU_INT_VECTOR_1, "LU_INT_VECTOR_1"); DisplayLuReg( LU_INITIAL_COUNT, "LU_INITIAL_COUNT"); DisplayLuReg( LU_CURRENT_COUNT, "LU_CURRENT_COUNT"); DisplayLuReg( LU_DIVIDER_CONFIG, "LU_DIVIDER_CONFIG"); HalpDisplayString("\n"); } VOID HalpDisplayIoUnit( ) /*++ Routine Description: Verify that an IO Unit exists at the specified address Arguments: BaseAddress - Address of the IO Unit to test. Return Value: BOOLEAN - TRUE if a IO Unit was found at the passed address - FALSE otherwise --*/ { #if 0 struct ApicIoUnit *IoUnitPtr; ULONG Data,i,j; PKPCR pPCR; pPCR = KeGetPcr(); // // The documented detection mechanism is to write all zeros to // the Version register. Then read it back. The IO Unit exists if the // same result is read both times and the Version is valid. // for (j=0; jIOApicCount; j++) { IoUnitPtr = (struct ApicIoUnit *) HalpMpInfoPtr->IoApicBase[j]; sprintf(Cbuf,"\nIoApic %d at Vaddr 0x%x\n",j,(ULONG) IoUnitPtr); HalpDisplayString(Cbuf); IoUnitPtr->RegisterSelect = IO_ID_REGISTER; HalpDisplayItem(IoUnitPtr->RegisterWindow, "IO_ID_REGISTER"); IoUnitPtr->RegisterSelect = IO_VERS_REGISTER; HalpDisplayItem(IoUnitPtr->RegisterWindow, "IO_VERS_REGISTER"); for (i=0; i<16; i++) { IoUnitPtr->RegisterSelect = IO_REDIR_00_LOW+(i*2); Data = IoUnitPtr->RegisterWindow; sprintf(Cbuf, " Redir [0x%x] - 0x%x, ", i, Data); HalpDisplayString(Cbuf); IoUnitPtr->RegisterSelect = IO_REDIR_00_LOW+(i*2)+1; Data = IoUnitPtr->RegisterWindow; sprintf(Cbuf, "0x%x\n", Data); HalpDisplayString(Cbuf); } // for each Redirection entry } // for all Io Apics #endif } void HalpDisplayConfigTable () /*+++ Debug routine to display the PC+MP config table --*/ { struct PcMpTable *MpPtr = PcMpTablePtr; PPCMPPROCESSOR ProcPtr; ULONG EntriesInTable = MpPtr->NumOfEntries; union PL { USHORT us; POLARITYANDLEVEL PnL; }; HalpDisplayString("PcMp Configuration Table\n"); HalpDisplayItem(MpPtr->Signature, "Signature"); HalpDisplayItem(MpPtr->TableLength, "TableLength"); HalpDisplayItem(MpPtr->Revision, "Revision"); HalpDisplayItem(MpPtr->Checksum, "Checksum"); HalpDisplayItemBuf(sizeof(MpPtr->OemId), MpPtr->OemId,"OemId"); HalpDisplayItemBuf(sizeof(MpPtr->OemProductId), MpPtr->OemProductId,"OemProductId"); HalpDisplayItem((ULONG) MpPtr->OemTablePtr, "OemTablePtr"); HalpDisplayItem(MpPtr->OemTableSize, "OemTableSize"); HalpDisplayItem(MpPtr->NumOfEntries, "NumOfEntries"); HalpDisplayItem((ULONG) MpPtr->LocalApicAddress, "LocalApicAddress"); HalpDisplayItem(MpPtr->Reserved, "Reserved"); ProcPtr = (PPCMPPROCESSOR) ((PUCHAR) MpPtr + HEADER_SIZE); while (EntriesInTable) { EntriesInTable--; switch ( ProcPtr->EntryType ) { case ENTRY_PROCESSOR: { union xxx { ULONG ul; CPUIDENTIFIER CpuId; } u; sprintf (Cbuf, "Proc..: ApicId %x, Apic ver %x, Flags %x\n", ProcPtr->LocalApicId, ProcPtr->LocalApicVersion, ProcPtr->CpuFlags ); HalpDisplayString (Cbuf); ProcPtr++; break; } case ENTRY_BUS: { PPCMPBUS BusPtr = (PPCMPBUS) ProcPtr; sprintf (Cbuf, "Bus...: id %02x, type '%.6s'\n", BusPtr->BusId, BusPtr->BusType); HalpDisplayString (Cbuf); BusPtr++; ProcPtr = (PPCMPPROCESSOR) BusPtr; break; } case ENTRY_IOAPIC: { PPCMPIOAPIC IoApPtr = (PPCMPIOAPIC) ProcPtr; sprintf (Cbuf, "IoApic: id %02x, ver %x, Flags %x, Address %x\n", IoApPtr->IoApicId, IoApPtr->IoApicVersion, IoApPtr->IoApicFlag, (ULONG) IoApPtr->IoApicAddress ); HalpDisplayString (Cbuf); IoApPtr++; ProcPtr = (PPCMPPROCESSOR) IoApPtr; break; } case ENTRY_INTI: { PPCMPINTI IntiPtr = (PPCMPINTI) ProcPtr; union PL u; u.PnL = IntiPtr->Signal; sprintf (Cbuf, "Inti..: t%x, s%x, SInt %x-%x, Inti %x-%x\n", IntiPtr->IntType, u.us, IntiPtr->SourceBusId, IntiPtr->SourceBusIrq, IntiPtr->IoApicId, IntiPtr->IoApicInti ); HalpDisplayString (Cbuf); IntiPtr++; ProcPtr = (PPCMPPROCESSOR) IntiPtr; break; } case ENTRY_LINTI: { PPCMPLINTI LIntiPtr = (PPCMPLINTI) ProcPtr; union PL u; u.PnL = LIntiPtr->Signal; sprintf (Cbuf, "Linti.: t%x, s%x, SInt %x-%x, Linti %x-%x\n", LIntiPtr->IntType, u.us, LIntiPtr->SourceBusId, LIntiPtr->SourceBusIrq, LIntiPtr->DestLocalApicId, LIntiPtr->DestLocalApicInti ); HalpDisplayString (Cbuf); LIntiPtr++; ProcPtr = (PPCMPPROCESSOR) LIntiPtr; break; } default: { HalpDisplayItem(ProcPtr->EntryType, "Unknown Type"); return; } } } } void HalpDisplayExtConfigTable () { PMPS_EXTENTRY ExtTable; extern struct HalpMpInfo HalpMpInfoTable; ExtTable = HalpMpInfoTable.ExtensionTable; while (ExtTable < HalpMpInfoTable.EndOfExtensionTable) { switch (ExtTable->Type) { case EXTTYPE_BUS_ADDRESS_MAP: sprintf (Cbuf, "BusMap: id %02x, t%x Base %08x Len %08x\n", ExtTable->u.AddressMap.BusId, ExtTable->u.AddressMap.Type, (ULONG) ExtTable->u.AddressMap.Base, (ULONG) ExtTable->u.AddressMap.Length ); HalpDisplayString (Cbuf); break; case EXTTYPE_BUS_HIERARCHY: sprintf (Cbuf, "BusHie: id %02x, Parent:%x sd:%x\n", ExtTable->u.BusHierarchy.BusId, ExtTable->u.BusHierarchy.ParentBusId, ExtTable->u.BusHierarchy.SubtractiveDecode ); HalpDisplayString (Cbuf); break; case EXTTYPE_BUS_COMPATIBLE_MAP: sprintf (Cbuf, "ComBus: id %02x %c List %x\n", ExtTable->u.CompatibleMap.BusId, ExtTable->u.CompatibleMap.Modifier ? '-' : '+', ExtTable->u.CompatibleMap.List ); HalpDisplayString (Cbuf); break; case EXTTYPE_PERSISTENT_STORE: sprintf (Cbuf, "PreSTR: Address %08x Len %08x\n", (ULONG) ExtTable->u.PersistentStore.Address, (ULONG) ExtTable->u.PersistentStore.Length ); HalpDisplayString (Cbuf); break; default: HalpDisplayItem(ExtTable->Type, "Unknown Type"); break; } ExtTable = (PMPS_EXTENTRY) (((PUCHAR) ExtTable) + ExtTable->Length); } } void HalpDisplayMpInfo() { #if 0 struct HalpMpInfo *MpPtr = HalpMpInfoPtr; HalpDisplayString("\nHAL: Private Mp Info\n"); HalpDisplayItem(MpPtr->ApicVersion, "ApicVersion"); HalpDisplayItem(MpPtr->ProcessorCount, "ProcessorCount"); HalpDisplayItem(MpPtr->BusCount, "BusCount"); HalpDisplayItem(MpPtr->IOApicCount, "IOApicCount"); HalpDisplayItem(MpPtr->IntiCount, "IntiCount"); HalpDisplayItem(MpPtr->LintiCount, "LintiCount"); HalpDisplayItem(MpPtr->IMCRPresent, "IMCRPresent"); HalpDisplayULItemBuf(4,(PULONG) MpPtr->IoApicBase,"IoApicBase"); HalpDisplayString("\n"); HalpDisplayConfigTable(); #endif } #ifdef OLD_DEBUG BOOLEAN HalpVerifyLocalUnit( IN UCHAR ApicID ) /*++ Routine Description: Verify that a Local Apic has the specified Apic Id. Arguments: ApicId - Id to verify. Return Value: BOOLEAN - TRUE if found - FALSE otherwise --*/ { union ApicUnion Temp; // // The remote read command must be: // // Vector - Bits 4-9 of the Version register // Destination Mode - Physical // Trigger Mode - Edge // Delivery Mode - Remote Read // Destination Shorthand - Destination Field // #define LU_READ_REMOTE_VERSION ( (LU_VERS_REGISTER >> 4) | \ DELIVER_REMOTE_READ | \ ICR_USE_DEST_FIELD) #define DEFAULT_DELAY 100 PVULONG LuDestAddress = (PVULONG) (LOCALAPIC + LU_INT_CMD_HIGH); PVULONG LuICR = (PVULONG) (LOCALAPIC + LU_INT_CMD_LOW); PVULONG LuRemoteReg = (PVULONG) (LOCALAPIC + LU_REMOTE_REGISTER); ULONG RemoteReadStatus; ULONG DelayCount = DEFAULT_DELAY; // // First make sure we can get to the Apic Bus // while ( ( DelayCount-- ) && ( *LuICR & DELIVERY_PENDING ) ); if (DelayCount == 0) { // // We're toast, can't gain access to the APIC Bus // return (FALSE); } // // Set the Address of the APIC we're looking for // *LuDestAddress = (ApicID << DESTINATION_SHIFT); // // Issue the request // *LuICR = LU_READ_REMOTE_VERSION; // // Reset the Delay so we can get out of here just in case... // DelayCount = DEFAULT_DELAY; while (DelayCount--) { RemoteReadStatus = *LuICR & ICR_RR_STATUS_MASK; if ( RemoteReadStatus == ICR_RR_INVALID) { // // No One responded, device timed out // return (FALSE); } if ( RemoteReadStatus == ICR_RR_VALID) { // // Someone is there and the Remote Register is valid // Temp.Raw = *LuRemoteReg; // // Do what we can to verify the Version // if (Temp.Ver.Version > 0x1f) { // // Only known devices are 0.x and 1.x // return (FALSE); } return (TRUE); } // RemoteRead Successfull } // While DelayCount // // No One responded, and the device did not time out // This should never happen // return (FALSE); } #endif // OLD_DEBUG VOID CreateBIOSTables( VOID) /*++ Routine Description: This routine is used to test the PC+MP detect code in the HAL. It creates the PC+MP structures that are really created by the BIOS. Since we presently do not have a BIOS that builds a PC+MP table, we need this for now. Arguments: None. Return Value: None. --*/ { PUCHAR TempPtr, BytePtr; UCHAR CheckSum; PULONG TraversePtr; USHORT BytesToCopy; HalpDisplayString("CreateBIOSTables : Entered\n"); // First, copy default PC+MP configuration 2 table at physical // address PCMP_TEST_TABLE TempPtr = (PUCHAR) HalpMapPhysicalMemory( (PVOID) PCMP_TEST_TABLE, 1); BytesToCopy = (PcMpDefaultTablePtrs[1])->TableLength; RtlMoveMemory(TempPtr, (PUCHAR)PcMpDefaultTablePtrs[1], BytesToCopy); // Populate the checksum entry for the table. CheckSum = ComputeCheckSum(TempPtr, BytesToCopy); sprintf(Cbuf, "CreateBIOSTables: PC+MP table computed checksum = %x\n", CheckSum); HalpDisplayString(Cbuf); CheckSum = ~CheckSum + 1; ((struct PcMpTable *)TempPtr)->Checksum = CheckSum; sprintf(Cbuf, "CreateBIOSTables: PC+MP table written checksum = %x\n", CheckSum); HalpDisplayString(Cbuf); // Now create the floating pointer structure for the table. TraversePtr = (PULONG) HalpMapPhysicalMemory( (PVOID) TEST_FLOAT_PTR, 1); TempPtr = (PUCHAR) TraversePtr; *TraversePtr++ = MP_PTR_SIGNATURE; *TraversePtr++ = PCMP_TEST_TABLE; BytePtr = (PUCHAR)TraversePtr; *BytePtr++ = 1; // Length in number of 16 byte paragraphs *BytePtr++ = 1; // Spec Rev. *BytePtr++ = 0; // CheckSum *BytePtr++ = 0; // Reserved TraversePtr = (PULONG)BytePtr; *TraversePtr = 0; // Reserved CheckSum = ComputeCheckSum(TempPtr,16); sprintf(Cbuf, "CreateBIOSTables: FLOAT_PTR computed checksum = %x\n", CheckSum); HalpDisplayString(Cbuf); CheckSum = ~CheckSum + 1; sprintf(Cbuf, "CreateBIOSTables: FLOAT_PTR written checksum = %x\n", CheckSum); HalpDisplayString(Cbuf); ((struct PcMpTableLocator *)TempPtr)->TableChecksum = CheckSum; HalpDisplayString("CreateBIOSTables : Done\n"); } #endif // DEBUGGING