/*++ Copyright (c) 1990 Microsoft Corporation Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file contains copyrighted material. Use of this file is restricted by the provisions of a Motorola Software License Agreement. Module Name: pxmemctl.c Abstract: The module initializes any planar registers. This module also implements machince check parity error handling. Author: Jim Wooldridge (jimw@austin.vnet.ibm.com) Steve Johns (sjohns@pets.sps.mot.com) Revision History: --*/ #include "halp.h" #include "pxmemctl.h" #include "pxpcisup.h" #include "pci.h" #include "pcip.h" #include "arccodes.h" #include "pxsystyp.h" #include ULONG PciInterruptRoutingOther = 15; VOID HalDisplayString(PUCHAR String); ULONG HalpGetHID0(VOID); VOID HalpSetHID0(ULONG Value); BOOLEAN HalpStrCmp(); VOID HalpEnableL2Cache(VOID); ULONG HalpSizeL2Cache(VOID); extern ULONG HalpSizeL2(VOID); extern ULONG L2_Cache_Size; extern VOID HalpFlushAndDisableL2(VOID); extern HalpPciConfigSize; BOOLEAN HalpInitPlanar(VOID); BOOLEAN HalpMapPlanarSpace(VOID); VOID HalpEnableEagleSettings(VOID); VOID HalpEnable_HID0_Settings(ULONG); VOID HalpCheckHardwareRevisionLevels(VOID); VOID HalpDumpHardwareState(VOID); #define EAGLECHIPID 0x0001 #define BUF_LEN 120 #define NEGATECHAR '~' #define EagleIndexRegister ((PULONG) (((PUCHAR) HalpIoControlBase) + 0xcf8)) #define EagleDataRegister ((((PUCHAR) HalpIoControlBase) + 0xcfc)) #define HalpReadEagleUlong(Port) \ (*EagleIndexRegister = (Port), __builtin_eieio(), *((PULONG) EagleDataRegister)) #define HalpWriteEagleUlong(Port, Value) \ (*EagleIndexRegister = (Port), *((PULONG) EagleDataRegister) = (Value), __builtin_sync()) #define HalpReadEagleUshort(Port) \ (*EagleIndexRegister = (Port&~3), __builtin_eieio(), *((PUSHORT)(EagleDataRegister+(Port&0x2)))) #define HalpWriteEagleUshort(Port, Value) \ (*EagleIndexRegister = (Port&~3), *((PUSHORT)(EagleDataRegister+(Port&0x2))) = (Value), __builtin_sync()) #define HalpWriteEagleUchar(Port, Value) \ (*EagleIndexRegister = (Port&~3), *((PUCHAR)(EagleDataRegister+(Port&0x3))) = (Value), __builtin_sync()) #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT,HalpStrCmp) #pragma alloc_text(INIT,HalpEnableL2Cache) #pragma alloc_text(INIT,HalpInitPlanar) #pragma alloc_text(INIT,HalpMapPlanarSpace) #pragma alloc_text(INIT,HalpEnableEagleSettings) #pragma alloc_text(INIT,HalpEnable_HID0_Settings) #pragma alloc_text(INIT,HalpCheckHardwareRevisionLevels) #pragma alloc_text(INIT,HalpSizeL2Cache) #endif UCHAR HalpReadEagleUchar(ULONG Port) { UCHAR c; *EagleIndexRegister = Port & ~3; __builtin_eieio(); c = *((PUCHAR)(EagleDataRegister+(Port&0x3))); return (c); } // Eagle rev 2.1 reads Config register 0xC0 bit 4 into bit 3 instead. // Writes to bit 4 are OK. UCHAR HalpReadEagleC0(ULONG Port) { UCHAR c; c = HalpReadEagleUchar(0x800000C0); c |= ((c & 0x08) << 1); return (c); } typedef UCHAR (*PHALP_READ_EAGLE) (ULONG Port); PHALP_READ_EAGLE HalpReadEagleRegC0; #define HalpDisplayHex32(Num, Buf) HalpDisplayHex( 32, Num, Buf) #define HalpDisplayHex16(Num, Buf) HalpDisplayHex( 16, Num, Buf) #define HalpDisplayHex8(Num, Buf) HalpDisplayHex( 8, Num, Buf) VOID HalpDisplayHex( ULONG NoBits, ULONG Number, IN PUCHAR Buffer ) { int Bits; for (Bits=NoBits-4; Bits >= 0; Bits -=4) { *Buffer++ = (UCHAR) ((((Number >> Bits) & 0xF) > 9) ? ((Number >> Bits) & 0xF) - 10 + 'A' : ((Number >> Bits) & 0xF) + '0'); } *Buffer++ = '.'; *Buffer++ = '\n'; *Buffer++ = '\0'; } UCHAR HalpUpperCase(UCHAR c) { if (c >= 'a' && c <= 'z') c -= 'a'-'A'; return c; } // // Routine Description: // // This routine is a helper routine for parameter parsing. It compares // String1 to String2. // // Return Value // // TRUE if strings match; otherwise FALSE // MatchLen - the number of characters correctly matched. // // #define HalpStrCmp(String1, String2) ( strcmp(String1, String2) == 0) BOOLEAN HalpStrCmp( char *String0, char *String1 ) { char *tmp0, *tmp1; tmp0 = String0; tmp1 = String1; while( (*tmp0 = toupper( *tmp0 )) && (*tmp1 = toupper( *tmp1 )) ) { tmp0++; tmp1++; } return( strcmp(String0, String1) == 0 ); } typedef struct tagEAGLEA8 { union { struct { ULONG CF_L2_MP : 2; ULONG SPECULATIVE_PCI : 1; ULONG CF_APARK : 1; ULONG CF_LOOP_SNOOP : 1; ULONG LITTLE_ENDIAN : 1; ULONG STORE_GATHERING : 1; ULONG NO_PORTS_REG : 1; ULONG Reserved1 : 1; ULONG CF_DPARK : 1; ULONG TEA_EN : 1; ULONG MCP_EN : 1; ULONG FLASH_WR_EN : 1; ULONG CF_LBA_EN : 1; ULONG Reserved2 : 1; ULONG CF_MP_ID : 1; ULONG ADDRESS_MAP : 1; ULONG PROC_TYPE : 2; ULONG DISCONTIGOUS_IO : 1; ULONG ROM_CS : 1; ULONG CF_CACHE_1G : 1; ULONG CF_BREAD_WS : 2; ULONG CF_CBA_MASK : 8; } EagleA8; ULONG AsUlong; } u; } EAGLEA8; typedef struct tagEAGLEAC { union { struct { ULONG CF_WDATA : 1; ULONG CF_DOE : 1; ULONG CF_APHASE : 2; ULONG CF_L2_SIZE : 2; ULONG CF_TOE_WIDTH : 1; ULONG CF_FAST_CASTOUT : 1; ULONG CF_BURST_RATE : 1; ULONG CF_L2_HIT_DELAY : 2; ULONG reserved1 : 1; ULONG CF_INV_MODE : 1; ULONG CF_HOLD : 1; ULONG CF_ADDR_ONLY : 1; ULONG reserved2 : 1; ULONG CF_HIT_HIGH : 1; ULONG CF_MOD_HIGH : 1; ULONG CF_SNOOP_WS : 2; ULONG CF_WMODE : 2; ULONG CF_DATA_RAM_TYP : 2; ULONG CF_FAST_L2_MODE : 1; ULONG CF_BYTE_DECODE : 1; ULONG reserved3 : 2; ULONG CF_FLUSH_L2 : 1; ULONG reserved4 : 1; ULONG L2_ENABLE : 1; ULONG L2_UPDATE_EN : 1; } EagleAC; ULONG AsUlong; } u; } EAGLEAC; typedef struct tagEAGLEC0 { union { struct { UCHAR LOCAL_BUS : 1; UCHAR PCI_MASTER_ABORT : 1; UCHAR MEM_READ_PARITY : 1; UCHAR Reserved : 1; UCHAR MASTER_PERR : 1; UCHAR MEM_SELECT_ERROR : 1; UCHAR SLAVE_PERR : 1; UCHAR PCI_TARGET_ABORT : 1; } EagleC0; UCHAR AsUchar; } u; } EAGLEC0; typedef enum { MPC601 = 1, MPC603 = 3, MPC603e = 6, MPC604 = 4, MPC604e = 9 } CPU_TYPE; // Parity Enable for memory interface #define PCKEN 0x10000 // Machine Check Enable #define MCP_EN 0x800 // Memory Read Parity Enable #define MRPE 0x04 typedef enum { WriteThrough, WriteBack } L2MODE; // Oem Output Display function filter noise if OEM or quite VOID OemDisplayString(PUCHAR String) { UCHAR CharBuffer[BUF_LEN]; if(HalGetEnvironmentVariable("HALREPORT",sizeof(CharBuffer),&CharBuffer[0]) == ESUCCESS) { if(HalpStrCmp("YES", CharBuffer)) { HalDisplayString(String); } } else { if(HalGetEnvironmentVariable("MOT-OEM-ID",sizeof(CharBuffer),&CharBuffer[0]) != ESUCCESS) { HalDisplayString(String); } } } char * MyStrtok ( char * string, const char * control ) { unsigned char *str; const unsigned char *ctrl = control; unsigned char map[32]; int count; static char *nextoken; /* Clear control map */ for (count = 0; count < 32; count++) map[count] = 0; /* Set bits in delimiter table */ do { map[*ctrl >> 3] |= (1 << (*ctrl & 7)); } while (*ctrl++); /* Initialize str. If string is NULL, set str to the saved * pointer (i.e., continue breaking tokens out of the string * from the last strtok call) */ if (string) str = string; else str = nextoken; /* Find beginning of token (skip over leading delimiters). Note that * there is no token iff this loop sets str to point to the terminal * null (*str == '\0') */ while ( (map[*str >> 3] & (1 << (*str & 7))) && *str ) str++; string = str; /* Find the end of the token. If it is not the end of the string, * put a null there. */ for ( ; *str ; str++ ) if ( map[*str >> 3] & (1 << (*str & 7)) ) { *str++ = '\0'; break; } /* Update nextoken (or the corresponding field in the per-thread data * structure */ nextoken = str; /* Determine if a token has been found. */ if ( string == str ) return NULL; else return string; } VOID HalpEnableL2Cache() { EAGLEAC EagleRegAC; EAGLEA8 EagleRegA8; USHORT CpuRevision; CPU_TYPE CpuType; BOOLEAN SynchronousSRAMs, Negate; UCHAR EagleRevision; L2MODE Mode; int i; UCHAR CharBuffer[BUF_LEN], *Value, c1, c2; UCHAR L2_Parameter[BUF_LEN]; long BridgeChipId; BridgeChipId = HalpReadEagleUshort(0x80000002); // // For non-EAGLE chips, firmware has already enabled the L2 cache. // No further action is necessary, return. // if (BridgeChipId != EAGLECHIPID) return; EagleRevision = HalpReadEagleUchar(0x80000008); // // Set some fields in Eagle Register 0xA8 // EagleRegA8.u.AsUlong = HalpReadEagleUlong(0x800000A8); EagleRegA8.u.EagleA8.TEA_EN = 1; // Enable TEA CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF); CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16); EagleRegA8.u.EagleA8.CF_BREAD_WS = 0; // works for 601 & 604 switch (CpuType) { case MPC601: EagleRegA8.u.EagleA8.PROC_TYPE = 0; break; case MPC603: case MPC603e: EagleRegA8.u.EagleA8.PROC_TYPE = 2; EagleRegA8.u.EagleA8.CF_BREAD_WS = 1; // assumes DRTRY mode !!! break; case MPC604: case MPC604e: EagleRegA8.u.EagleA8.PROC_TYPE = 3; break; } // // Set the default L2 cache timing. // The timing will be platform dependent. // If the L2 is already on (via firmware), just return. // EagleRegAC.u.AsUlong = HalpReadEagleUlong(0x800000AC); if (EagleRegAC.u.EagleAC.L2_ENABLE) return; EagleRegAC.u.EagleAC.CF_WMODE = 3; EagleRegAC.u.EagleAC.CF_MOD_HIGH = 1; EagleRegAC.u.EagleAC.CF_ADDR_ONLY = 1; EagleRegAC.u.EagleAC.CF_APHASE = 1; EagleRegAC.u.EagleAC.CF_DOE = 1; EagleRegAC.u.EagleAC.CF_WDATA = 1; EagleRegAC.u.EagleAC.L2_UPDATE_EN = 1; EagleRegAC.u.EagleAC.L2_ENABLE = 1; switch (HalpSystemType) { case MOTOROLA_BIG_BEND: case MOTOROLA_POWERSTACK: default: SynchronousSRAMs = TRUE; break; } if (SynchronousSRAMs) { EagleRegAC.u.EagleAC.CF_DATA_RAM_TYP = 0; EagleRegAC.u.EagleAC.CF_HOLD = 0; EagleRegAC.u.EagleAC.CF_BURST_RATE = 0; } else { EagleRegAC.u.EagleAC.CF_HOLD = 1; EagleRegAC.u.EagleAC.CF_BURST_RATE = 1; if (EagleRevision == 0x21) EagleRegAC.u.EagleAC.CF_DOE = 0; } // // Set up the default L2 cache mode. // Default to WRITE-THROUGH prior to Eagle 2.4, else WRITE-BACK // Mode = WriteThrough; if (EagleRevision >= 0x24) { Mode = WriteBack; EagleRegA8.u.EagleA8.CF_LOOP_SNOOP = 1; EagleRegA8.u.EagleA8.CF_CBA_MASK = 0x3f; } if (HalpSystemType == MOTOROLA_BIG_BEND) { EagleRegAC.u.EagleAC.CF_SNOOP_WS = 3; EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY = 1; EagleRegAC.u.EagleAC.CF_TOE_WIDTH = 1; } else { EagleRegAC.u.EagleAC.CF_SNOOP_WS = 2; EagleRegAC.u.EagleAC.CF_FAST_CASTOUT = 1; EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY = 2; } // // There are IBM 604 parts (Revision 3.3 and earlier) that cannot burst // at the fastest rate in WRITE-BACK mode. // if ((Mode == WriteBack) && (CpuType == MPC604) && (CpuRevision < 0x0304)) EagleRegAC.u.EagleAC.CF_BURST_RATE = 1; // -2-2-2 // // Parse the environment variable "L2" // if (HalGetEnvironmentVariable("L2", BUF_LEN, &CharBuffer[0]) == ESUCCESS) { // Copy L2 environment variable i = 0; while (L2_Parameter[i] = CharBuffer[i]) { i++; } for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, " :;,") ) { if (*Value == NEGATECHAR) { Value++; Negate = TRUE; } else Negate = FALSE; // Check for L2 = "OFF" if (HalpStrCmp( "OFF", Value )) { OemDisplayString("HAL: L2 cache is disabled via environment variable L2\n"); HalpFlushAndDisableL2(); PCR->SecondLevelDcacheSize = PCR->SecondLevelIcacheSize = 0; return; } // Check for WriteBack else if ( HalpStrCmp( "WB", Value ) ) { if (Negate) { Value--; goto ParseError; } Mode = WriteBack; EagleRegA8.u.EagleA8.CF_LOOP_SNOOP = 1; EagleRegA8.u.EagleA8.CF_CBA_MASK = 0x3f; } // Check for WriteThrough else if ( HalpStrCmp( "WT", Value ) ) { if (Negate) { Value--; goto ParseError; } Mode = WriteThrough; EagleRegA8.u.EagleA8.CF_LOOP_SNOOP = 0; EagleRegA8.u.EagleA8.CF_CBA_MASK = 0x00; } else if (SynchronousSRAMs && HalpStrCmp("FAST_CASTOUT", Value)) { if (Negate) { EagleRegAC.u.EagleAC.CF_FAST_CASTOUT = 0; } else EagleRegAC.u.EagleAC.CF_FAST_CASTOUT = 1; } else if ( HalpStrCmp( "FAST_MODE", Value ) ) { if (Negate) { EagleRegAC.u.EagleAC.CF_FAST_L2_MODE = 0; } else EagleRegAC.u.EagleAC.CF_FAST_L2_MODE = 1; } // Check for cache timings else if ( ( HalpStrCmp( "3-1-1-1", Value ) ) || ( HalpStrCmp( "4-1-1-1", Value ) ) || ( HalpStrCmp( "5-1-1-1", Value ) ) ) { if (Negate) { Value--; goto ParseError; } EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY = *Value - '2'; // HIT_DELAY is where it samples HIT if =1, then 3-1-1-1 is fastest. // CF_DOE_DELAY adds 1 more delay to # cycles, but doesn't change where // HIT is sampled. If 66MHz or greater, then DOE_DELAY should be set. // same thing with WRITE_DELAY. EagleRegAC.u.EagleAC.CF_SNOOP_WS = *Value - '2'; if( SynchronousSRAMs ) // Asynchronous SRAMs can't do -1-1-1 EagleRegAC.u.EagleAC.CF_BURST_RATE = 0; } else if ( ( HalpStrCmp( "3-2-2-2", Value ) ) || ( HalpStrCmp( "4-2-2-2", Value ) ) || ( HalpStrCmp( "5-2-2-2", Value ) ) ) { if (Negate) { Value--; goto ParseError; } EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY = *Value - '2'; EagleRegAC.u.EagleAC.CF_SNOOP_WS = *Value - '2'; EagleRegAC.u.EagleAC.CF_BURST_RATE = 1; } else { ParseError: HalDisplayString("HAL: Error in L2 environment variable: "); HalDisplayString(L2_Parameter); HalDisplayString("\n illegal parameter begins here "); for (i = 0; i < Value - CharBuffer; i++) HalDisplayString("\304"); HalDisplayString("^\n"); break; } } // End for } // End If // // Enable L2 cache // OemDisplayString("HAL: L2 cache is "); if (L2_Cache_Size == 0) { OemDisplayString("not installed.\n"); return; } if (Mode == WriteThrough) EagleRegA8.u.EagleA8.CF_L2_MP = 1; else EagleRegA8.u.EagleA8.CF_L2_MP = 2; HalpWriteEagleUlong(0x800000A8, EagleRegA8.u.AsUlong); HalpWriteEagleUlong(0x800000AC, EagleRegAC.u.AsUlong); switch (L2_Cache_Size) { case 256: OemDisplayString("256 KB"); break; case 512: OemDisplayString("512 KB"); break; case 1024: OemDisplayString("1 MB"); break; default: OemDisplayString("an invalid configuration. Pattern = "); HalpDisplayHex32(L2_Cache_Size, CharBuffer); OemDisplayString(CharBuffer); PCR->SecondLevelDcacheSize = PCR->SecondLevelDcacheSize = 0; return; } // // Display cache mode and timing // if (Mode == WriteBack) OemDisplayString(" (write-back "); else OemDisplayString(" (write-through "); CharBuffer[0] = (UCHAR) EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY + '2'; CharBuffer[1] = '\0'; OemDisplayString(CharBuffer); if (EagleRegAC.u.EagleAC.CF_BURST_RATE) OemDisplayString("-2-2-2)\n"); else OemDisplayString("-1-1-1)\n"); return; } ULONG HalpSizeL2Cache() { EAGLEAC EagleRegAC; EAGLEA8 EagleRegA8; CPU_TYPE CpuType; long BridgeChipId; BridgeChipId = HalpReadEagleUshort(0x80000002); // // For non-EAGLE chips, firmware has set up the L2 cache size in // the config block and NT Kernel has copied this info into PCR // structure. So, no work needs to be done, retrieve the size from PCR // if (BridgeChipId != EAGLECHIPID) return( (PCR->SecondLevelIcacheSize >> 10) ); // // Set some fields in Eagle Register 0xA8 // EagleRegA8.u.AsUlong = HalpReadEagleUlong(0x800000A8); CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16); switch (CpuType) { case MPC603: case MPC603e: EagleRegA8.u.EagleA8.PROC_TYPE = 2; EagleRegA8.u.EagleA8.CF_BREAD_WS = 1; break; case MPC604: case MPC604e: EagleRegA8.u.EagleA8.PROC_TYPE = 3; EagleRegA8.u.EagleA8.CF_BREAD_WS = 0; break; default: return 0; // This HAL doesn't work with this processor } HalpWriteEagleUlong(0x800000A8, EagleRegA8.u.AsUlong); EagleRegAC.u.AsUlong = HalpReadEagleUlong(0x800000AC); EagleRegAC.u.EagleAC.CF_MOD_HIGH = 1; HalpWriteEagleUlong(0x800000AC, EagleRegAC.u.AsUlong); return ( HalpSizeL2()); } BOOLEAN HalpInitPlanar ( VOID ) { ULONG j; USHORT CpuRevision; CPU_TYPE CpuType; UCHAR EagleRevision, c; UCHAR CharBuffer[20], i; long BridgeChipId; switch (HalpSystemType) { case MOTOROLA_BIG_BEND: HalDisplayString("\nHAL: Motorola Big Bend System"); break; case MOTOROLA_POWERSTACK: // HalDisplayString("\nHAL: Motorola PowerStack System"); break; case SYSTEM_UNKNOWN: default: HalDisplayString("\nHAL: WARNING : UNKNOWN SYSTEM TYPE\n"); break; } OemDisplayString("\nHAL: Version 2.37 5/24/96."); CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16); CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF); OemDisplayString("\nHAL: Processor is a 60"); i = 0; switch (CpuType) { case MPC601: case MPC603: case MPC604: CharBuffer[i++] = (UCHAR)(CpuType) + '0'; break; case MPC603e: CharBuffer[i++] = '3'; CharBuffer[i++] = 'e'; break; case MPC604e: CharBuffer[i++] = '4'; CharBuffer[i++] = 'e'; break; default: CharBuffer[i++] = '?'; break; } CharBuffer[i] = '\0'; OemDisplayString(CharBuffer); OemDisplayString(" revision "); i = 0; c = (UCHAR)((CpuRevision >> 8) & 0xf); CharBuffer[i++] = c + '0'; CharBuffer[i++] = '.'; if (c = (UCHAR)((CpuRevision >> 4) & 0xf)) CharBuffer[i++] = c + '0'; c = (UCHAR)(CpuRevision & 0xf); if (CpuType == MPC604 && c == 0) { // 604 v3.01 CharBuffer[i++] = '0'; CharBuffer[i++] = '1'; } else { CharBuffer[i++] = c + '0'; } CharBuffer[i] = '\0'; OemDisplayString(CharBuffer); BridgeChipId = HalpReadEagleUshort(0x80000002); if (BridgeChipId == EAGLECHIPID) OemDisplayString("\nHAL: Eagle Revision"); else OemDisplayString("\nHAL: Bridge Chip Revision"); i = 0; EagleRevision = HalpReadEagleUchar(0x80000008); CharBuffer[i++] = ' '; CharBuffer[i++] = (UCHAR) (EagleRevision >> 4) + '0'; CharBuffer[i++] = '.'; CharBuffer[i++] = (UCHAR) (EagleRevision & 0x0F) + '0'; CharBuffer[i++] = '\n'; CharBuffer[i] = '\0'; OemDisplayString(CharBuffer); return TRUE; } BOOLEAN HalpMapPlanarSpace ( VOID ) /*++ Routine Description: This routine maps the interrupt acknowledge and error address spaces for a PowerPC system. Arguments: None. Return Value: If the initialization is successfully completed, then a value of TRUE is returned. Otherwise, a value of FALSE is returned. --*/ { PHYSICAL_ADDRESS physicalAddress; // // Map interrupt control space. // physicalAddress.HighPart = 0; physicalAddress.LowPart = INTERRUPT_PHYSICAL_BASE; HalpInterruptBase = MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE); if (HalpInterruptBase == NULL) return FALSE; else return TRUE; } BOOLEAN HalpMapBusConfigSpace ( VOID ) /*++ Routine Description: This routine maps the HAL PCI config spaces for a PowerPC system. Arguments: None. Return Value: If the initialization is successfully completed, then a value of TRUE is returned. Otherwise, a value of FALSE is returned. --*/ { PHYSICAL_ADDRESS physicalAddress; // // Map the PCI config space. // physicalAddress.LowPart = PCI_CONFIG_PHYSICAL_BASE; HalpPciConfigBase = MmMapIoSpace(physicalAddress, HalpPciConfigSize, FALSE); if (HalpPciConfigBase == NULL) return FALSE; else return TRUE; } VOID HalpHandleMemoryError( VOID ) { UCHAR StatusByte; ULONG ErrorAddress; UCHAR TextAddress[11]; USHORT EagleRegister, Byte; EagleRegister = HalpReadEagleUshort(0x80000006); if (EagleRegister & 0x8100) HalDisplayString("\nEAGLE Status Register: PARITY Error Detected."); if (EagleRegister & 0x4000) HalDisplayString("\nEAGLE Status Register: SERR asserted."); // MOTKJR 08/22/95 - Don't check for the following bit. // It is always set when NT scans the slots on the PCI bus. // if (EagleRegister & 0x2000) // HalDisplayString("\nEAGLE Status Register: Transaction terminated with master-abort."); if (EagleRegister & 0x1000) HalDisplayString("\nEAGLE Status Register: Transaction terminated by target-abort while master."); if (EagleRegister & 0x0800) HalDisplayString("\nEAGLE Status Register: Transaction terminated by target-abort while slave."); // // Check Memory Error Detection Register 2 // StatusByte = HalpReadEagleUchar(0x800000C5); if (StatusByte & 0x10) { HalDisplayString ("\nEAGLE Error Detection Register 2: L2 Parity Error Detected"); } if (StatusByte & 0x80) { // HalDisplayString ("\nEAGLE Error Detection Register 2: Invalid Error Address"); #if DBG // // We have had a catastrophic hardware malfunction. // Dump the state of the Eagle and HID 0 registers. // HalDisplayString("\n"); HalpDumpHardwareState(); #endif return; } // // Read the error address register first // ErrorAddress = HalpReadEagleUlong(0x800000C8); // // Convert error address to HEX characters // HalpDisplayHex32(ErrorAddress, TextAddress); TextAddress[ 8] = '.'; TextAddress[ 9] = '\0'; TextAddress[10] = '\0'; // // Check Memory Error Detection Register 1 // StatusByte = HalpReadEagleUchar(0x800000C1); if (StatusByte & 0x08) { HalDisplayString("\nEAGLE: PCI initiated Cycle."); } else { HalDisplayString("\nEAGLE: CPU initiated Cycle."); } if (StatusByte & 0xC0) { HalDisplayString ("\nEAGLE: PCI "); if (StatusByte & 0x80) HalDisplayString ("SERR"); else HalDisplayString ("target PERR"); HalDisplayString (" signaled at address "); HalDisplayString (TextAddress); } if (StatusByte & 0x24) { HalDisplayString ("\nEAGLE: Memory "); if (StatusByte & 0x20) HalDisplayString ("Select"); else HalDisplayString ("Read Parity"); HalDisplayString (" error at address "); HalDisplayString (TextAddress); } #if DBG // // We have had a catastrophic hardware malfunction. // Dump the state of the Eagle and HID 0 registers. // HalDisplayString("\n"); HalpDumpHardwareState(); #endif } VOID HalpEnableEagleSettings(VOID) { ULONG EagleRegister, UseFirmwareSettings; volatile ULONG FakeVectorFetch; USHORT CpuRevision; EAGLEC0 ErrorEnable1; CPU_TYPE CpuType; UCHAR EagleRevision; UCHAR CharBuffer[BUF_LEN], *Value; BOOLEAN Negate; long BridgeChipId; #define SetEagleUcharC0( Clear, Val ) \ SetEagleReg(Clear, 0x800000C0, Val, HalpReadEagleRegC0, HalpWriteEagleUchar); #define SetEagleUchar( Clear, Offset, Val ) \ SetEagleReg(Clear, Offset, Val, HalpReadEagleUchar, HalpWriteEagleUchar); #define SetEagleUshort( Clear, Offset, Val ) \ SetEagleReg(Clear, Offset, Val, HalpReadEagleUshort, HalpWriteEagleUshort); #define SetEagleUlong( Clear, Offset, Val ) \ SetEagleReg(Clear, Offset, Val, HalpReadEagleUlong, HalpWriteEagleUlong); #define SetEagleReg( Clear, Offset, Val, GetReg, SetReg) \ { \ if (Clear) { \ SetReg(Offset, GetReg(Offset) & ~Val); \ } else { \ SetReg(Offset, GetReg(Offset) | Val); \ } \ } CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16); CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF); EagleRevision = HalpReadEagleUchar(0x80000008); UseFirmwareSettings = FALSE; // // Adjust default settings for any known chip bugs or anomalies here. // Eagle revision 2.1 has funny bits in Register C0. // // // If the bridge chip is not Eagle then set the revision number to 0x24 // Currently the sister chip grackle is the only one supported by this // code and it is equivalent to Eagle revision 0x24 // BridgeChipId = HalpReadEagleUshort(0x80000002); if (BridgeChipId != EAGLECHIPID) EagleRevision = 0x24; if (EagleRevision == 0x21) HalpReadEagleRegC0 = HalpReadEagleC0; else HalpReadEagleRegC0 = HalpReadEagleUchar; // // Set Address and Data Park bits in Eagle. // These particular bits are not "parity" related. // HalpWriteEagleUlong(0x800000A8, HalpReadEagleUlong(0x800000A8) | 0x208); // // Setup and initialize the default EAGLE Parity Checking. // This default is platform dependent. // switch (HalpSystemType) { case MOTOROLA_POWERSTACK: // // PowerStack Systems will initialize EAGLE Parity Checking // settings at the Boot ROM or ARC Firmware level. Use these // EAGLE settings if they are present, otherwise use defaults. // UseFirmwareSettings = ((HalpReadEagleUlong(0x800000F0) & PCKEN) && (HalpReadEagleRegC0(0x800000C0) & MRPE)); if (UseFirmwareSettings) break; HalpWriteEagleUchar(0x800000C4, 0x10); // Enable L2 Parity Checking. // fall-through to default default: // // Enable parity checking in Eagle chip // ErrorEnable1.u.AsUchar = 0; ErrorEnable1.u.EagleC0.PCI_TARGET_ABORT = 1; ErrorEnable1.u.EagleC0.MEM_SELECT_ERROR = 1; ErrorEnable1.u.EagleC0.MEM_READ_PARITY = 1; HalpWriteEagleUchar(0x800000C0, ErrorEnable1.u.AsUchar); if (EagleRevision >= 0x22) { // // NT must be loaded with the PCKEN bit enabled. Check PCKEN to make // sure it is enabled. If it is not enabled, then don't enable parity // checking since parity errors will be found all over memory. // EagleRegister = HalpReadEagleUlong(0x800000F0); if (EagleRegister & PCKEN) { // // Enable parity checking in Eagle chip // ErrorEnable1.u.EagleC0.LOCAL_BUS = 1; HalpWriteEagleUchar(0x800000C0, ErrorEnable1.u.AsUchar); // // Enable SERR checking in the Command register. // EagleRegister = HalpReadEagleUshort(0x80000004); HalpWriteEagleUshort(0x80000004, (USHORT)(EagleRegister | 0x100)); // SERR only. // // Conditionally enable Machine Check in the Eagle. // Systems with IBM 604 revision 3.2 & 3.3 parts have problems // with parity. Motorola parts are OK. It would be great if we // could tell them apart (one from the other), but we can't. So, // don't enable internal Cache parity on this (or earlier) parts. // if ((CpuType != MPC604) || (CpuRevision >= 0x0304)) { EagleRegister = HalpReadEagleUlong(0x800000A8); HalpWriteEagleUlong(0x800000A8, EagleRegister | MCP_EN); } } } } // // The environment variable "EAGLESETTINGS" is defined as: // Matching a string serves to enable that feature while a tilde (~) // immediately before the parameter string indicates that it is to be disabled. // if ( HalGetEnvironmentVariable("EAGLESETTINGS", BUF_LEN, &CharBuffer[0]) == ESUCCESS ) { for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, ":;,") ) { Negate = FALSE; if (*Value == NEGATECHAR) { Value++; Negate = TRUE; } if (HalpStrCmp("MCP_EN", Value) || HalpStrCmp("MCP", Value)) { SetEagleUlong( Negate, 0x800000A8, MCP_EN ); } else if (HalpStrCmp("TEA_EN", Value) || HalpStrCmp("TEA", Value)) { SetEagleUlong( Negate, 0x800000A8, 0x400 ); } else if (HalpStrCmp("DPARK", Value) || HalpStrCmp("CF_DPARK", Value)) { SetEagleUlong( Negate, 0x800000A8, 0x200 ); } else if (HalpStrCmp("GATHERING", Value)) { SetEagleUlong( Negate, 0x800000A8, 0x040 ); } else if (HalpStrCmp("CF_LOOP_SNOOP", Value)) { SetEagleUlong( Negate, 0x800000A8, 0x010 ); } else if (HalpStrCmp("APARK", Value) || HalpStrCmp("CF_APARK", Value)) { SetEagleUlong( Negate, 0x800000A8, 0x008 ); } else if (HalpStrCmp("SPECULATIVE", Value)) { SetEagleUlong( Negate, 0x800000A8, 0x004 ); } else if (HalpStrCmp("L2_PARITY", Value) || HalpStrCmp("L2", Value)) { SetEagleUchar( Negate, 0x800000C4, 0x10 ); } else if (HalpStrCmp("PCKEN", Value)) { SetEagleUlong( Negate, 0x800000F0, PCKEN ); } else if (HalpStrCmp("SERR", Value)) { SetEagleUshort( Negate, 0x80000004, 0x100 ); } else if (HalpStrCmp("RX_SERR_EN", Value) || HalpStrCmp("RX_SERR", Value)) { SetEagleUchar( Negate, 0x800000BA, 0x20 ); } else if (HalpStrCmp("TARGET_ABORT", Value)) { SetEagleUcharC0( Negate, 0x80 ); } else if (HalpStrCmp("SLAVE_PERR", Value)) { SetEagleUcharC0( Negate, 0x40 ); SetEagleUshort( Negate, 0x80000004, 0x040 ); } else if (HalpStrCmp("SELECT_ERROR", Value) || HalpStrCmp("SELECT", Value)) { SetEagleUcharC0( Negate, 0x20 ); } else if (HalpStrCmp("MASTER_PERR", Value)) { SetEagleUcharC0( Negate, 0x10 ); SetEagleUshort( Negate, 0x80000004, 0x040 ); } else if (HalpStrCmp("DRAM", Value) || HalpStrCmp("READ", Value) || HalpStrCmp("MEMORY", Value)) { SetEagleUcharC0( Negate, MRPE ); } else if (HalpStrCmp("MASTER_ABORT", Value)) { SetEagleUcharC0( Negate, 0x02 ); } else if (HalpStrCmp("LOCAL_ERROR", Value) || HalpStrCmp("LOCAL", Value)) { SetEagleUcharC0( Negate, 0x01 ); // // Enabling (or disabling) EAGLE parity by listing // all of the individual bits was too complicated. // For simplicity, we will define one pseudo-bit // called "PARITY". This will set (or clear) all // of the individual parity bits for EAGLE platforms. // } else if (HalpStrCmp("PARITY", Value)) { // Conditionally turn on L2 checking. if (HalpSystemType == MOTOROLA_POWERSTACK) { SetEagleReg( Negate, 0x800000C4, 0x10, HalpReadEagleUchar, HalpWriteEagleUchar ); } // Set or Clear the PCKEN bit. SetEagleReg( Negate, 0x800000F0, PCKEN, HalpReadEagleUlong, HalpWriteEagleUlong ); // Set or Clear parity checking in Eagle chip SetEagleUcharC0( Negate, 0xA5 ); // Set or Clear the SERR bit in the Command register. SetEagleReg( Negate, 0x80000004, 0x100, HalpReadEagleUshort, HalpWriteEagleUshort ); // Set or Clear the MCP_EN last. SetEagleReg( Negate, 0x800000A8, MCP_EN, HalpReadEagleUlong, HalpWriteEagleUlong ); } else if (HalpStrCmp("CF_ADDR_ONLY_DISABLE", Value)) { SetEagleUlong( Negate, 0x800000AC, 0x4000); } else if (HalpStrCmp("CF_BURST_RATE", Value)) { SetEagleUlong( Negate, 0x800000AC, 0x0100); } else if (HalpStrCmp("CF_FAST_CASTOUT", Value)) { SetEagleUlong( Negate, 0x800000AC, 0x0080); } else if (HalpStrCmp("CF_TOE_WIDTH", Value)) { SetEagleUlong( Negate, 0x800000AC, 0x0040); } else if (HalpStrCmp("CF_DOE", Value)) { SetEagleUlong( Negate, 0x800000AC, 0x0002); } else if (HalpStrCmp("CF_WDATA", Value)) { SetEagleUlong( Negate, 0x800000AC, 0x0001); } else { HalDisplayString( "HAL: Error in EAGLESETTINGS environment variable: "); HalDisplayString(CharBuffer); HalDisplayString("^\n"); } } // End for } // End If // // Initialize the PowerPC HID0 register here, // before we clear the detection bits in the EAGLE. // Otherwise we can miss the MCP pin signal transition. // HalpEnable_HID0_Settings(UseFirmwareSettings); // // Clear any detection bits that may have been set while enabling L2 cache. // The Eagle does not clear the MCP_ signal until it sees a fetch from // the Machine Check vector. So, we must simulate a vector fetch. // FakeVectorFetch = *((volatile PULONG)(0x80000200)); // Clear the EAGLE MCP_ signal if it is set. HalpWriteEagleUchar(0x800000C1, 0xFF); // Clear Error Detection Register 1. HalpWriteEagleUchar(0x800000C5, 0xFF); // Clear Error Detection Register 2. EagleRegister = HalpReadEagleUshort(0x80000006); // Get any Un-documented Status bits. HalpWriteEagleUshort(0x80000006, 0xF900 | (USHORT)(EagleRegister)); // Clear Status Register Bits. FakeVectorFetch = *((volatile PULONG)(0x80000200)); // Clear the EAGLE MCP_ signal if it is set. // // Print this message last to confirm everything is working. // } VOID HalpEnable_HID0_Settings(ULONG UseDefaultsHidSettings) { ULONG EagleRegister; USHORT CpuRevision; CPU_TYPE CpuType; UCHAR EagleRevision; UCHAR CharBuffer[BUF_LEN], *Value; ULONG HidEnable, HidDisable, CurrentHID0; BOOLEAN Negate; long BridgeChipId; #define HID0_MCP (0x80000000) #define HID0_CACHE (0x40000000) #define HID0_ADDRESS (0x20000000) #define HID0_DATA (0x10000000) #define HID0_PAR (0x01000000) #define HID0_DPM (0x00100000) #define HID0_ILOCK (0x00002000) #define HID0_DLOCK (0x00001000) #define HID0_FBIOB (0x00000010) #define HID0_BHT (0x00000004) #define SetCPUMask( Disable, Val ) \ { \ if (Disable) \ HidDisable |= Val; \ else \ HidEnable |= Val; \ } CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16); CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF); EagleRevision = HalpReadEagleUchar(0x80000008); // // If the bridge chip is not Eagle then set the revision number to 0x24 // Currently the sister chip grackle is the only one supported by this // code and it is equivalent to Eagle revision 0x24 // BridgeChipId = HalpReadEagleUshort(0x80000002); if (BridgeChipId != EAGLECHIPID) EagleRevision = 0x24; HidEnable = 0; HidDisable = 0; CurrentHID0 = HalpGetHID0(); switch (CpuType) { case MPC603e: if (CpuRevision <= 0x102) { // // Disable Dynamic Power Management on 603e revisions 1.1 & 1.2 // 603e revisions 1.1 and 1.2 have errata w.r.t DPM. // CurrentHID0 &= ~HID0_DPM; break; } // else fall through to 603 case MPC603: // // Enable Dynamic Power Management // CurrentHID0 |= HID0_DPM; } // // Set the default CPU Parity Checking. // This default is platform dependent. // switch (HalpSystemType) { case MOTOROLA_POWERSTACK: // // PowerStack Systems will initialize HID0 Parity Checking // settings at the Boot ROM or ARC Firmware level. Use these // HID0 settings if they are present, otherwise use defaults. // if (UseDefaultsHidSettings) { // Just enable the Machine Check Pin. // Hopefully, everything else has been setup. CurrentHID0 |= (HID0_MCP); break; } // fall-through to default default: CurrentHID0 &= ~(HID0_MCP | HID0_DATA | HID0_CACHE | HID0_ADDRESS); // // Systems with IBM 604 revision 3.3 & 3.2 parts have problems with // L1 parity checking. Motorola parts are OK, but we can't tell // Motorola parts from IBM. So, don't enable L1 cache parity checking // on 604 v3.3 or v3.2 parts. switch (CpuType) { case MPC604: if (CpuRevision == 0x303 || CpuRevision == 0x302) break; // else fall through and enable Cache Parity case MPC604e: CurrentHID0 |= (HID0_CACHE); // fall through default: break; } // // Set up the default Parity Checking. No checking prior to Eagle 2.2. // NT must be loaded with the PCKEN bit enabled. Check PCKEN to make // sure it is enabled. If it is not enabled, then don't enable parity // checking since parity errors will be found all over memory. // EagleRegister = HalpReadEagleUlong(0x800000F0); if ((EagleRevision >= 0x22) && (EagleRegister & PCKEN)) { // // Systems with IBM 604 revision 3.3 parts have problems with // parity generation. Motorola parts are OK. It would be great // if we could tell them apart (one from the other), but we can't. // So don't enable data parity checking on this (or earlier) parts. // if ((CpuType != MPC604) || (CpuRevision >= 0x0304)) CurrentHID0 |= (HID0_MCP | HID0_DATA); } break; } // // The environment variable "HID0SETTINGS" is defined either as: // "CACHE", "ADDRESS", "DATA", "MCP", "DPM" with either blank or semi-colon // characters used as separators. Matching a string serves to enable // that feature while a tilde (~) immediately before the parameter // string indicates that it is to be disabled. // if (HalGetEnvironmentVariable("HID0SETTINGS", BUF_LEN, &CharBuffer[0]) == ESUCCESS) { for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, ":;,") ) { Negate = FALSE; if (*Value == NEGATECHAR) { Value++; Negate = TRUE; } if (HalpStrCmp("MCP", Value)) { SetCPUMask(Negate, HID0_MCP); } else if (HalpStrCmp("ADDRESS", Value)) { SetCPUMask(Negate, HID0_ADDRESS); } else if (HalpStrCmp("DATA", Value)) { SetCPUMask(Negate, HID0_DATA); } else if (HalpStrCmp("PAR", Value)) { SetCPUMask(Negate, HID0_PAR); } else if (HalpStrCmp("ILOCK", Value)) { SetCPUMask(Negate, HID0_ILOCK); } else if (HalpStrCmp("DLOCK", Value)) { SetCPUMask(Negate, HID0_DLOCK); } else { switch (CpuType) { case MPC604: case MPC604e: if (HalpStrCmp("BHT", Value)) { SetCPUMask(Negate, HID0_BHT); continue; } if (HalpStrCmp("CACHE", Value)) { SetCPUMask(Negate, HID0_CACHE); continue; } break; case MPC603: case MPC603e: if (HalpStrCmp("DPM", Value)) { SetCPUMask(Negate, HID0_DPM); continue; } if (HalpStrCmp("FBIOB", Value)) { SetCPUMask(Negate, HID0_FBIOB); continue; } break; } // End switch HalDisplayString("HAL: Error in HID0SETTINGS environment variable: "); HalDisplayString(CharBuffer); HalDisplayString("\n"); } // End else } // End for } // End if // // Check for inconsistencies in HID0SETTINGS // if (HidEnable & HidDisable) { HalDisplayString("HAL: Inconsistent settings in HID0SETTINGS environment variable.\n"); HalDisplayString(" Disable setting will override enable setting.\n"); // // Enforce DISABLE override ENABLE // HidEnable &= ~HidDisable; } // // Disable and Enable the bits in the HID0 register. // CurrentHID0 &= ~HidDisable; // Disable bits first. HalpSetHID0(CurrentHID0); CurrentHID0 |= HidEnable; // Enable Bits last. HalpSetHID0(CurrentHID0); // // Print this message last to confirm everything is working. // } VOID HalpCheckHardwareRevisionLevels(VOID) { ULONG EagleRegister, i; USHORT CpuRevision; CPU_TYPE CpuType; UCHAR EagleRevision; ARC_STATUS Status; UCHAR Buffer[10]; long BridgeChipId; i = HalpGetProcessorVersion(); CpuType = (CPU_TYPE)(i >> 16); CpuRevision = (USHORT)(i & 0xFFFF); EagleRevision = HalpReadEagleUchar(0x80000008); // // Minimum hardware requirements: // Eagle: v2.1 or greater // 603 or 604: v3.2 or greater // 603e or 604e: any CPU revision // // // If the bridge chip is not Eagle then set the revision number to 0x24 // Currently the sister chip grackle is the only one supported by this // code and it is equivalent to Eagle revision 0x24 // BridgeChipId = HalpReadEagleUshort(0x80000002); if (BridgeChipId != EAGLECHIPID) EagleRevision = 0x24; if (EagleRevision >= 0x21) { switch (CpuType) { case MPC603: case MPC604: if (CpuRevision >= 0x0302) return; else break; default: return; } } // If the environment variable BOOTOLDHARDWARE exists (value is // a don't care), then try to boot anyway. Status = HalGetEnvironmentVariable("BOOTOLDHARDWARE", 5, Buffer); if (Status == ESUCCESS || Status == ENOMEM) return; HalDisplayString("\nHAL: Unsupported CPU and/or EAGLE revision level. Set the\n"); HalDisplayString(" environment variable BOOTOLDHARDWARE to any value to boot anyway."); // // Bug check - after stalling to allow // any information printed on the screen // to be read and seen by the user. // HalDisplayString("\n"); for (i=0; i<12; i++) { HalDisplayString("."); KeStallExecutionProcessor(1000000); } KeBugCheck(HAL_INITIALIZATION_FAILED); return; } VOID HalpDumpHardwareState(VOID) { ULONG EagleRegister, HID0; UCHAR CharBuffer[12]; #if DBG if ( HalGetEnvironmentVariable("DBG_HAL", BUF_LEN, &CharBuffer[0]) == ESUCCESS ) { EagleRegister = HalpReadEagleUshort(0x80000004); HalDisplayString("HAL: Eagle register 04 = 0x"); HalpDisplayHex16(EagleRegister, CharBuffer ); HalDisplayString(CharBuffer); EagleRegister = HalpReadEagleUshort(0x80000006); HalDisplayString("HAL: Eagle register 06 = 0x"); HalpDisplayHex16(EagleRegister, CharBuffer ); HalDisplayString(CharBuffer); EagleRegister = HalpReadEagleUlong(0x800000A8); HalDisplayString("HAL: Eagle register A8 = 0x"); HalpDisplayHex32(EagleRegister, CharBuffer ); HalDisplayString(CharBuffer); EagleRegister = HalpReadEagleUlong(0x800000AC); HalDisplayString("HAL: Eagle register AC = 0x"); HalpDisplayHex32(EagleRegister, CharBuffer ); HalDisplayString(CharBuffer); EagleRegister = HalpReadEagleUchar(0x800000C0); HalDisplayString("HAL: Eagle register C0 = 0x"); HalpDisplayHex8(EagleRegister, CharBuffer ); HalDisplayString(CharBuffer); EagleRegister = HalpReadEagleUchar(0x800000C1); HalDisplayString("HAL: Eagle register C1 = 0x"); HalpDisplayHex8(EagleRegister, CharBuffer ); HalDisplayString(CharBuffer); EagleRegister = HalpReadEagleUchar(0x800000C3); HalDisplayString("HAL: Eagle register C3 = 0x"); HalpDisplayHex8(EagleRegister, CharBuffer ); HalDisplayString(CharBuffer); EagleRegister = HalpReadEagleUchar(0x800000C4); HalDisplayString("HAL: Eagle register C4 = 0x"); HalpDisplayHex8(EagleRegister, CharBuffer ); HalDisplayString(CharBuffer); EagleRegister = HalpReadEagleUchar(0x800000C5); HalDisplayString("HAL: Eagle register C5 = 0x"); HalpDisplayHex8(EagleRegister, CharBuffer ); HalDisplayString(CharBuffer); EagleRegister = HalpReadEagleUchar(0x800000C7); HalDisplayString("HAL: Eagle register C7 = 0x"); HalpDisplayHex8(EagleRegister, CharBuffer ); HalDisplayString(CharBuffer); EagleRegister = HalpReadEagleUlong(0x800000C8); HalDisplayString("HAL: Eagle register C8 = 0x"); HalpDisplayHex32(EagleRegister, CharBuffer ); HalDisplayString(CharBuffer); HID0 = HalpGetHID0(); HalDisplayString("HAL: PowerPC Register HID0 = 0x"); HalpDisplayHex32(HID0, CharBuffer ); HalDisplayString(CharBuffer); } #endif }