windows-nt/Source/XPSP1/NT/base/hals/halmps/i386/mpdebug.c
2020-09-26 16:20:57 +08:00

678 lines
17 KiB
C

/*++
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; j<HalpMpInfoPtr->IOApicCount; 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