summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halfire
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/halfire')
-rw-r--r--private/ntos/nthals/halfire/hal.rc11
-rw-r--r--private/ntos/nthals/halfire/makefile6
-rw-r--r--private/ntos/nthals/halfire/makefile.inc22
-rw-r--r--private/ntos/nthals/halfire/ppc/ctrlops.c471
-rw-r--r--private/ntos/nthals/halfire/ppc/fp82091.c120
-rw-r--r--private/ntos/nthals/halfire/ppc/fp82091.h426
-rw-r--r--private/ntos/nthals/halfire/ppc/fparch.h46
-rw-r--r--private/ntos/nthals/halfire/ppc/fpbat.c346
-rw-r--r--private/ntos/nthals/halfire/ppc/fpbat.h20
-rw-r--r--private/ntos/nthals/halfire/ppc/fpbt445.c413
-rw-r--r--private/ntos/nthals/halfire/ppc/fpbt445.h180
-rw-r--r--private/ntos/nthals/halfire/ppc/fpcpu.h179
-rw-r--r--private/ntos/nthals/halfire/ppc/fpcpu.s387
-rw-r--r--private/ntos/nthals/halfire/ppc/fpdcc.c226
-rw-r--r--private/ntos/nthals/halfire/ppc/fpdcc.h142
-rw-r--r--private/ntos/nthals/halfire/ppc/fpdebug.h171
-rw-r--r--private/ntos/nthals/halfire/ppc/fpds1385.c372
-rw-r--r--private/ntos/nthals/halfire/ppc/fpds1385.h213
-rw-r--r--private/ntos/nthals/halfire/ppc/fpi2c.c1016
-rw-r--r--private/ntos/nthals/halfire/ppc/fpi2c.h39
-rw-r--r--private/ntos/nthals/halfire/ppc/fpi2csup.h232
-rw-r--r--private/ntos/nthals/halfire/ppc/fpints.c292
-rw-r--r--private/ntos/nthals/halfire/ppc/fpio.h230
-rw-r--r--private/ntos/nthals/halfire/ppc/fplibc.c114
-rw-r--r--private/ntos/nthals/halfire/ppc/fpnvram.h105
-rw-r--r--private/ntos/nthals/halfire/ppc/fppci.h189
-rw-r--r--private/ntos/nthals/halfire/ppc/fppcisup.c1101
-rw-r--r--private/ntos/nthals/halfire/ppc/fppcisup.h142
-rw-r--r--private/ntos/nthals/halfire/ppc/fpproto.h17
-rw-r--r--private/ntos/nthals/halfire/ppc/fpreg.h422
-rw-r--r--private/ntos/nthals/halfire/ppc/fprgstry.c871
-rw-r--r--private/ntos/nthals/halfire/ppc/halp.h267
-rw-r--r--private/ntos/nthals/halfire/ppc/pcibios.c1084
-rw-r--r--private/ntos/nthals/halfire/ppc/pcibios.h58
-rw-r--r--private/ntos/nthals/halfire/ppc/pcip.h249
-rw-r--r--private/ntos/nthals/halfire/ppc/phcalls.c120
-rw-r--r--private/ntos/nthals/halfire/ppc/phprods.c794
-rw-r--r--private/ntos/nthals/halfire/ppc/phsystem.h270
-rw-r--r--private/ntos/nthals/halfire/ppc/phsystem.s487
-rw-r--r--private/ntos/nthals/halfire/ppc/phvrsion.c433
-rw-r--r--private/ntos/nthals/halfire/ppc/pxbeep.c144
-rw-r--r--private/ntos/nthals/halfire/ppc/pxbusdat.c207
-rw-r--r--private/ntos/nthals/halfire/ppc/pxcache.s1105
-rw-r--r--private/ntos/nthals/halfire/ppc/pxcalstl.c150
-rw-r--r--private/ntos/nthals/halfire/ppc/pxcirrus.h234
-rw-r--r--private/ntos/nthals/halfire/ppc/pxclksup.s163
-rw-r--r--private/ntos/nthals/halfire/ppc/pxclock.c287
-rw-r--r--private/ntos/nthals/halfire/ppc/pxdat.c113
-rw-r--r--private/ntos/nthals/halfire/ppc/pxdisp.c2907
-rw-r--r--private/ntos/nthals/halfire/ppc/pxenviro.c729
-rw-r--r--private/ntos/nthals/halfire/ppc/pxflshbf.s159
-rw-r--r--private/ntos/nthals/halfire/ppc/pxflshio.c195
-rw-r--r--private/ntos/nthals/halfire/ppc/pxhalp.h291
-rw-r--r--private/ntos/nthals/halfire/ppc/pxhwsup.c2212
-rw-r--r--private/ntos/nthals/halfire/ppc/pxidaho.h149
-rw-r--r--private/ntos/nthals/halfire/ppc/pxidle.c77
-rw-r--r--private/ntos/nthals/halfire/ppc/pxinithl.c1114
-rw-r--r--private/ntos/nthals/halfire/ppc/pxintsup.s121
-rw-r--r--private/ntos/nthals/halfire/ppc/pxirql.c182
-rw-r--r--private/ntos/nthals/halfire/ppc/pxisabus.c576
-rw-r--r--private/ntos/nthals/halfire/ppc/pxmapio.c134
-rw-r--r--private/ntos/nthals/halfire/ppc/pxmemctl.c243
-rw-r--r--private/ntos/nthals/halfire/ppc/pxmemctl.h68
-rw-r--r--private/ntos/nthals/halfire/ppc/pxmisc.s282
-rw-r--r--private/ntos/nthals/halfire/ppc/pxnatsup.c90
-rw-r--r--private/ntos/nthals/halfire/ppc/pxnatsup.h67
-rw-r--r--private/ntos/nthals/halfire/ppc/pxnvrsup.h35
-rw-r--r--private/ntos/nthals/halfire/ppc/pxpcibus.c2327
-rw-r--r--private/ntos/nthals/halfire/ppc/pxpciint.c398
-rw-r--r--private/ntos/nthals/halfire/ppc/pxpcisup.c267
-rw-r--r--private/ntos/nthals/halfire/ppc/pxpcisup.h66
-rw-r--r--private/ntos/nthals/halfire/ppc/pxport.c855
-rw-r--r--private/ntos/nthals/halfire/ppc/pxproc.c250
-rw-r--r--private/ntos/nthals/halfire/ppc/pxprof.c277
-rw-r--r--private/ntos/nthals/halfire/ppc/pxreturn.c223
-rw-r--r--private/ntos/nthals/halfire/ppc/pxrtcsup.h37
-rw-r--r--private/ntos/nthals/halfire/ppc/pxs3.h770
-rw-r--r--private/ntos/nthals/halfire/ppc/pxsiosup.c1866
-rw-r--r--private/ntos/nthals/halfire/ppc/pxsiosup.h231
-rw-r--r--private/ntos/nthals/halfire/ppc/pxstall.s390
-rw-r--r--private/ntos/nthals/halfire/ppc/pxsysbus.c298
-rw-r--r--private/ntos/nthals/halfire/ppc/pxsysint.c243
-rw-r--r--private/ntos/nthals/halfire/ppc/pxtime.c340
-rw-r--r--private/ntos/nthals/halfire/ppc/pxusage.c512
-rw-r--r--private/ntos/nthals/halfire/ppc/sysbios.c73
-rw-r--r--private/ntos/nthals/halfire/ppc/sysbios.h31
-rw-r--r--private/ntos/nthals/halfire/ppc/txtpalet.h107
-rw-r--r--private/ntos/nthals/halfire/ppc/x86bios.c1201
-rw-r--r--private/ntos/nthals/halfire/ppc/x86bios.h24
-rw-r--r--private/ntos/nthals/halfire/sources235
90 files changed, 35338 insertions, 0 deletions
diff --git a/private/ntos/nthals/halfire/hal.rc b/private/ntos/nthals/halfire/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halfire/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halfire/makefile b/private/ntos/nthals/halfire/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halfire/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halfire/makefile.inc b/private/ntos/nthals/halfire/makefile.inc
new file mode 100644
index 000000000..c0a760ce7
--- /dev/null
+++ b/private/ntos/nthals/halfire/makefile.inc
@@ -0,0 +1,22 @@
+ppc\phvrsion.c: $(FIREPOWER_SOURCES)
+
+!IFDEF DDKBUILDENV
+
+!IFDEF VERBOSE
+
+$(TARGETPATH)\$(DESTINATION_DIR)\hal.lib: FRC $(TARGETPATH)\$(DESTINATION_DIR)\halfire.lib
+ copy $** $@
+
+!ELSE
+
+$(TARGETPATH)\$(DESTINATION_DIR)\hal.lib: $(TARGETPATH)\$(DESTINATION_DIR)\halfire.lib
+ copy $** $@
+
+!ENDIF
+
+FRC:
+ echo ======================= environment vars ==========================
+ set
+ echo ======================= environment vars ==========================
+
+!ENDIF
diff --git a/private/ntos/nthals/halfire/ppc/ctrlops.c b/private/ntos/nthals/halfire/ppc/ctrlops.c
new file mode 100644
index 000000000..f921d2ed6
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/ctrlops.c
@@ -0,0 +1,471 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ ctrlops.c
+
+Abstract:
+
+ This module implements the code to emulate call, retunr, and various
+ control operations.
+
+Author:
+
+ David N. Cutler (davec) 10-Nov-1994
+
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Scott Geranen 5-Mar-1996 Added hooks for System BIOS emulation
+
+--*/
+
+#include "nthal.h"
+#include "emulate.h"
+#include "sysbios.h"
+
+VOID
+XmCallOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a call opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Target;
+ ULONG Source;
+
+ //
+ // Save the target address, push the current segment, if required, and
+ // push the current IP, set the destination segment, if required, and
+ // set the new IP.
+ //
+
+ Target = P->DstValue.Long;
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ if ((P->CurrentOpcode == 0x9a) || (P->FunctionIndex != X86_CALL_OP)) {
+ XmPushStack(P, P->SegmentRegister[CS]);
+ XmPushStack(P, P->Eip);
+ P->SegmentRegister[CS] = P->DstSegment;
+
+ } else {
+ XmPushStack(P, P->Eip);
+ }
+
+ P->Eip = Target;
+ XmTraceJumps(P);
+ return;
+}
+
+VOID
+XmEnterOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an enter opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Allocate;
+ ULONG Frame;
+ ULONG Number;
+
+ //
+ // set the number of bytes to allocate on the stack and the number
+ // of nesting levels.
+ //
+
+ Allocate = P->SrcValue.Long;
+ Number = P->DstValue.Long;
+
+ //
+ // Set the data type and save the frame pointer on the stack.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+ XmPushStack(P, P->Gpr[EBP].Exx);
+ Frame = P->Gpr[ESP].Exx;
+
+ } else {
+ P->DataType = WORD_DATA;
+ XmPushStack(P, P->Gpr[BP].Xx);
+ Frame = P->Gpr[SP].Xx;
+ }
+
+ //
+ // Save the current stack pointer and push parameters on the stack.
+ //
+
+ if (Number != 0) {
+
+ //
+ // If the level number is not one, then raise an exception.
+ //
+ // N.B. Level numbers greater than one are not supported.
+ //
+
+ if (Number != 1) {
+ longjmp(&P->JumpBuffer[0], XM_ILLEGAL_LEVEL_NUMBER);
+ }
+
+ XmPushStack(P, Frame);
+ }
+
+ //
+ // Allocate local storage on stack.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->Gpr[EBP].Exx = Frame;
+ P->Gpr[ESP].Exx = P->Gpr[ESP].Exx - Allocate;
+
+ } else {
+ P->Gpr[BP].Xx = (USHORT)Frame;
+ P->Gpr[SP].Xx = (USHORT)(P->Gpr[SP].Xx - Allocate);
+ }
+
+ return;
+}
+
+VOID
+XmHltOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a hlt opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Halt instructions are not supported by the emulator.
+ //
+
+ longjmp(&P->JumpBuffer[0], XM_HALT_INSTRUCTION);
+ return;
+}
+
+VOID
+XmIntOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an int opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Number;
+ PULONG Vector;
+
+ //
+ // If the int instruction is an int 3, then set the interrupt vector
+ // to 3. Otherwise, if the int instruction is an into, then set the
+ // vector to 4 if OF is set. use the source interrupt vector.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ if (P->CurrentOpcode == 0xcc) {
+ Number = 3;
+
+ } else if (P->CurrentOpcode == 0xce) {
+ if (P->Eflags.OF == 0) {
+ return;
+ }
+
+ Number = 4;
+
+ } else {
+ Number = P->SrcValue.Byte;
+ }
+
+ //
+ // If the vector number is 0x42, then nop the interrupt. This is the
+ // standard EGA video driver entry point in a PC's motherboard BIOS
+ // for which there is no code.
+ //
+
+#if !defined(_PURE_EMULATION_)
+
+ if (Number == 0x42) {
+ return;
+ }
+
+#endif
+
+ //
+ // Try to emulate a system BIOS call first.
+ //
+ if (!HalpEmulateSystemBios(P, Number)) {
+
+ //
+ // Either it isn't a BIOS call or it isn't supported.
+ // Emulate the x86 stream instead. Note that this
+ // doesn't support chained handlers.
+
+ //
+ // Push the current flags, code segment, and EIP on the stack.
+ //
+
+ XmPushStack(P, P->AllFlags);
+ XmPushStack(P, P->SegmentRegister[CS]);
+ XmPushStack(P, P->Eip);
+
+ //
+ // Set the new coded segment and IP from the specified interrupt
+ // vector.
+ //
+
+ Vector = (PULONG)(P->TranslateAddress)(0, 0);
+ P->SegmentRegister[CS] = (USHORT)(Vector[Number] >> 16);
+ P->Eip = (USHORT)(Vector[Number] & 0xffff);
+ XmTraceJumps(P);
+ }
+
+ return;
+}
+
+VOID
+XmIretOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates an iret opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the data type and restore the return address, code segment,
+ // and flags.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ P->Eip = XmPopStack(P);
+ P->SegmentRegister[CS] = (USHORT)XmPopStack(P);
+ P->AllFlags = XmPopStack(P);
+ XmTraceJumps(P);
+
+ //
+ // Check for emulator exit conditions.
+ //
+
+ if ((P->Eip == 0xffff) && (P->SegmentRegister[CS] == 0xffff)) {
+ longjmp(&P->JumpBuffer[0], XM_SUCCESS);
+ }
+
+ return;
+}
+
+VOID
+XmLeaveOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a leave opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the data type, restore the stack pointer, and restore the frame
+ // pointer.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+ P->Gpr[ESP].Exx = P->Gpr[EBP].Exx;
+ P->Gpr[EBP].Exx = XmPopStack(P);
+
+ } else {
+ P->DataType = WORD_DATA;
+ P->Gpr[SP].Xx = P->Gpr[BP].Xx;
+ P->Gpr[BP].Xx = (USHORT)XmPopStack(P);
+ }
+
+ return;
+}
+
+VOID
+XmRetOp (
+ PRXM_CONTEXT P
+ )
+
+/*++
+
+Routine Description:
+
+ This function emulates a ret opcode.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Adjust;
+
+ //
+ // Compute the number of bytes that are to be removed from the stack
+ // after having removed the return address and optionally the new CS
+ // segment value.
+ //
+
+ if ((P->CurrentOpcode & 0x1) == 0) {
+ Adjust = XmGetWordImmediate(P);
+
+ } else {
+ Adjust = 0;
+ }
+
+ //
+ // Remove the return address from the stack and set the new IP.
+ //
+
+ if (P->OpsizePrefixActive != FALSE) {
+ P->DataType = LONG_DATA;
+
+ } else {
+ P->DataType = WORD_DATA;
+ }
+
+ P->Eip = XmPopStack(P);
+
+ //
+ // If the current opcode is a far return, then remove the new CS segment
+ // value from the stack.
+ //
+
+ if ((P->CurrentOpcode & 0x8) != 0) {
+ P->SegmentRegister[CS] = (USHORT)XmPopStack(P);
+ }
+
+ //
+ // Remove the specified number of bytes from the stack.
+ //
+
+ P->Gpr[ESP].Exx += Adjust;
+ XmTraceJumps(P);
+
+ //
+ // Check for emulator exit conditions.
+ //
+
+ if ((P->Eip == 0xffff) && (P->SegmentRegister[CS] == 0xffff)) {
+ longjmp(&P->JumpBuffer[0], XM_SUCCESS);
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halfire/ppc/fp82091.c b/private/ntos/nthals/halfire/ppc/fp82091.c
new file mode 100644
index 000000000..b9b353158
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fp82091.c
@@ -0,0 +1,120 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1994 FirePower Systems, Inc.
+
+Module Name:
+
+ fp82091.c
+
+Abstract:
+
+ The module provides the Intel AIP (82091AA) support for Power PC.
+
+Author:
+
+
+Revision History:
+
+
+
+--*/
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fp82091.c $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/16 20:45:10 $
+ * $Locker: $
+ */
+
+#include "halp.h"
+#include "fpreg.h"
+#include "fpio.h"
+#include "fp82091.h"
+
+
+
+BOOLEAN
+HalpInitIntelAIP (
+ VOID
+ )
+
+
+{
+
+ //
+ // AIP configuration
+ //
+
+ rIndexAIP1 = AIPCFG1;
+ rTargetAIP1 = CLOCK_POWERED_ON |
+ PRIMARY_ADDRESS_CONFIG |
+ SOFTWARE_MOTHERBOARD;
+ FireSyncRegister();
+
+ rIndexAIP1 = AIPCFG2;
+ //
+ // Active High Mode is ISA-Compatible
+ //
+ rTargetAIP1 = IRQ3_ACTIVE_HIGH |
+ IRQ4_ACTIVE_HIGH |
+ IRQ5_ACTIVE_HIGH |
+ IRQ6_ACTIVE_HIGH |
+ IRQ7_ACTIVE_HIGH;
+ FireSyncRegister();
+
+ rIndexAIP1 = FCFG1;
+ rTargetAIP1 = FDC_ENABLE |
+ PRIMARY_FDC_ADDRESS |
+ TWO_DISK_DRIVES;
+ FireSyncRegister();
+
+ rIndexAIP1 = FCFG2;
+ rTargetAIP1 = 0x00; // No Powerdown control,
+ // no reset
+ FireSyncRegister();
+
+
+ rIndexAIP1 = PCFG1;
+ rTargetAIP1 = PP_ENABLE |
+ PP_ADDRESS_SELECT_2 | // Parallel Port1 (3BC-3BE)
+ PP_IRQ7 |
+ PP_FIFO_THRSEL_8;
+ FireSyncRegister();
+
+ rIndexAIP1 = PCFG2;
+ rTargetAIP1 = 0x00; // No Powerdown control,
+ // no reset
+ FireSyncRegister();
+
+ rIndexAIP1 = SACFG1;
+ rTargetAIP1 = PORTA_ENABLE |
+ PORTA_ADDRESS_SELECT_0 | // Serial Port1 (3F8-3FF
+ PORTA_IRQ4;
+ FireSyncRegister();
+
+ rIndexAIP1 = SACFG2;
+ rTargetAIP1 = 0x00; // No Powerdown control,
+ // no reset, no test mode
+ FireSyncRegister();
+
+ rIndexAIP1 = SBCFG1;
+ rTargetAIP1 = PORTB_ENABLE |
+ PORTB_ADDRESS_SELECT_1 | // Serial Port2 (2F8-2FF)
+ PORTB_IRQ3;
+ FireSyncRegister();
+
+ rIndexAIP1 = SACFG2;
+ rTargetAIP1 = 0x00; // No Powerdown control,
+ // no reset, no test mode
+ FireSyncRegister();
+
+ rIndexAIP1 = IDECFG;
+ rTargetAIP1 = IDE_INTERFACE_ENABLE; // IDE interface enable
+ FireSyncRegister();
+
+ return TRUE;
+
+}
diff --git a/private/ntos/nthals/halfire/ppc/fp82091.h b/private/ntos/nthals/halfire/ppc/fp82091.h
new file mode 100644
index 000000000..5fed59a86
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fp82091.h
@@ -0,0 +1,426 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+Copyright (c) 1994 FirePower Systems, Inc.
+
+Module Name:
+
+ pxaipsup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the
+ AIP (Intel 82091AA) Advanced Integrated Peripheral chip.
+
+Author:
+
+
+Revision History:
+
+
+--*/
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fp82091.h $
+ * $Revision: 1.5 $
+ * $Date: 1996/05/14 02:32:08 $
+ * $Locker: $
+ */
+
+// AIP configuration registers
+
+
+//
+// Index register select
+//
+
+#define AIPID 0x00 // Product Identification
+#define AIPREV 0x01 // Revision Identification
+#define AIPCFG1 0x02 // AIP Configuration 1
+#define AIPCFG2 0x03 // AIP Configuration 2
+#define FCFG1 0x10 // FDC Configuration
+#define FCFG2 0x11 // FDC Power Management and
+ /* Status */
+#define PCFG1 0x20 // Parallel Port Configuration
+#define PCFG2 0x21 // Parallel Port Power Management
+ /* and Status */
+#define SACFG1 0x30 // Serial Port A Configuration
+#define SACFG2 0x31 // Serail Port A Power Management
+ /* and Status */
+#define SBCFG1 0x40 // Serial Port B Configuration
+#define SBCFG2 0x41 // Serial Port B Power Management
+ /* and Status */
+#define IDECFG 0x50 // IDE Configuration
+
+/*+++
+
+ AIPID: RO
+ 7-0 Product Identification Number
+
+
+ AIPREV: RO
+ 7-4 Step Number
+ 3-0 Dash Number
+
+ AIPCFG1: R/W
+ 7 Not Used
+ 6 Supply Voltage (RO)
+ 0: 5.0V
+ 1: 3.3V
+ 4-5 Configuration Mode Select (R/W)
+ 0x00 Software Motherboard
+ 0x01 Software Add-in
+ 0x10 Extended Hardware
+ 0x11 Basic Hardware
+ 3 Configuration Address Select (RO)
+ 0: Secondary Address
+ 1: Primary Address
+ 2-1 Reserved
+ 0 Clock Off (R/W)
+ 0: AIP powered on
+ 1: AIP powered off
+
+ AIPCFG2: R/W
+ 7 IRQ7 Mode Select (R/W)
+ 0: Active High
+ 1: Active Low
+ 6 IRQ6 Mode Select (R/W)
+ 0: Active High
+ 1: Active Low
+ 5 IRQ5 Mode Select (R/W)
+ 0: Active High
+ 1: Active Low
+ 4 IRQ4 Mode Select (R/W)
+ 0: Active High
+ 1: Active Low
+ 3 IRQ3 Mode Select (R/W)
+ 0: Active High
+ 1: Active Low
+ 2-0 Reserved
+
+ FCFG1: R/W
+ 7 Floppy Disk Drive Quantity (R/W)
+ 0: Two
+ 1: Four
+ 6-2 Reserved
+ 1 FDC Address Select (R/W)
+ 0: Primary (3F0-3F7)
+ 1: Secondary (370-377)
+ 0 FDC Enable (R/W)
+ 0: Disable
+ 1: Enable
+
+ FCFG2: R/W
+ 7-4 Reserved
+ 3 FDC Auto Powerdown Enable (R/W)
+ 0: Disable
+ 1: Enable, 0: Disable
+ 2 FDC Reset (R/W)
+ 0: No FDC Module Reset
+ 1: Reset FDC Module, 0: No FDC Module Reset
+ 1 FDC Idle Status (RO)
+ 0: Active
+ 1: Idle, 0: Active
+ 0 FDC Direct Powerdown Control (R/W)
+ 0: Not in Direct Powerdown
+ 1: Powerdown, 0: Not in Direct Powerdown
+
+ PCFG1: R/W
+ 7 PP FIFO Threshold Select (R/W)
+ 0: 8 (forward and reverse)
+ 1: 1 (forward), 15(reverse)
+ 6-5 PP Hardware Mode Select (R/W)
+ 00: ISA-Compatible (read), ISA-Compatible (write)
+ 01: PS/2-Compatible (read), PS/2-Compatible (write)
+ 10: EPP (read) , EPP (write)
+ 11: ECP (read), Reserved (do not write)
+ 4 Reserved
+ 3 PP Interrupt Select (R/W)
+ 0: IRQ5
+ 1: IRQ7
+ 2-1 PP Address Select (R/W)
+ 00: 378-37F
+ 01: 278-27F
+ 10: 3BC-3BE
+ 11: Reserved
+ 0 PP Enable (R/W)
+ 0: Disable
+ 1: Enable
+ PCFG2: R/W
+ 7-6 Reserved
+ 5 PP FIFO Error Status (RO)
+ 0: No Underrun or Overrun
+ 1: Underrun or Overrun
+ 4 Reserved
+ 3 PP Auto Powerdown Enable (R/W)
+ 0: Disable
+ 1: Enable
+ 2 PP Reset (R/W)
+ 0: Inactive
+ 1: Active
+ 1 PP Idle Status (RO)
+ 0: Avtive
+ 1: Idle
+ 0 PP Port Direct Powerdown (R/W)
+ 0: Disabled
+ 1: Enabled
+
+ SACFG1: R/W
+ 7 MIDI Clock Enable for Serial Port A (R/W)
+ 0: 1.8642 MHz Clock
+ 1: 2MHz Clock
+ 6-5 Reserved
+ 4 Serial Port A IRQ Select (R/W)
+ 0: IRQ3
+ 1: IRQ4
+ 3-1 Serial Port A Address Select (R/W)
+ 000: 3F8-3FF
+ 001: 2F8-2FF
+ 010: 220-227
+ 011: 228-22F
+ 100: 238-23F
+ 101: 2E8-2EF
+ 110: 338-33F
+ 111: 3E8-3EF
+ 0 Serial Port A Enable (R/W)
+ 0: Disable
+ 1: Enable
+
+ SACFG2: R/W
+ 0: to Disable
+ 1: to Enable
+ -------------------------------------------------------------
+ 7-5 Reserved
+ 4 Serial Port A Test Mode (R/W)
+ 3 Serial Port A Auto Powerdown Enable (R/W)
+ 2 Serial Port A Reset (R/W)
+ 1 Serial Port A Idle Status (RO)
+ 0 Serial Port A Direct Powerdown Control (R/W)
+
+
+ SBCFG1: R/W
+ -------------------------------------------------------------
+ 7 MIDI Clock Enable for Serial Port B (R/W)
+ 0: 1.8642 MHz Clock
+ 1: 2MHz Clock
+ 6-5 Reserved
+ 4 Serial Port B IRQ Select (R/W)
+ 0: IRQ3
+ 1: IRQ4
+ 3-1 Serial Port B Address Select (R/W)
+ 000: 3F8-3FF
+ 001: 2F8-2FF
+ 010: 220-227
+ 011: 228-22F
+ 100: 238-23F
+ 101: 2E8-2EF
+ 110: 338-33F
+ 111: 3E8-3EF
+ 0 Serial Port B Enable (R/W)
+ 0: Disable
+ 1: Enable
+
+ SBCFG2: R/W
+ -------------------------------------------------------------
+ 7-5 Reserved
+ 4 Serial Port B Test Mode (R/W)
+ 0: Disable
+ 1: Enable
+ 3 Serial Port B Auto Powerdown Enable (R/W)
+ 0: Disable
+ 1: Enable
+ 2 Serial Port B Reset (R/W)
+ 0: Reset Inactive
+ 1: Reset Active
+ 1 Serial Port B Idle Status (RO)
+ 0: Active
+ 1: Idle
+ 0 Serial Port B Direct Powerdown Control (R/W)
+ 0: Disable
+ 1: Enable
+
+ IDECFG: R/W
+ 7-3 Reserved
+ 2 IDE Dual Interface Select (R/W)
+ 1: Primary and Secondary Address Selected
+ 0: Dual Interface Disabled
+ 1 IDE Address Select (R/W)
+ 0: Primary (1F0-1F7,3F6,3F7)
+ 1: Secondary (170-17F,376,377)
+ 0 IDE Interface Enable (R/W)
+ 0: Disable
+ 1: Enable, 0: Disable
+
+---*/
+
+
+//
+// Data register values
+//
+
+//
+// AIPCFG1
+//
+
+#define CLOCK_POWERED_ON 0x00
+#define CLOCK_POWERED_OFF 0x01
+#define PRIMARY_ADDRESS_CONFIG 0x00
+#define SECONDARY_ADDRESS_CONFIG 0x08
+#define SOFTWARE_MOTHERBOARD 0x00
+#define SOFTWARE_ADDIN 0x10
+#define EXTENDED_HARDWARE 0x20
+#define BASIC_HARDWARE 0x30
+#define SUPPLY_VOLTAGE_33V 0x40
+
+//
+// AIPCFG2
+//
+
+#define IRQ3_ACTIVE_LOW 0x08
+#define IRQ3_ACTIVE_HIGH 0x00
+#define IRQ4_ACTIVE_LOW 0x10
+#define IRQ4_ACTIVE_HIGH 0x00
+#define IRQ5_ACTIVE_LOW 0x20
+#define IRQ5_ACTIVE_HIGH 0x00
+#define IRQ6_ACTIVE_LOW 0x40
+#define IRQ6_ACTIVE_HIGH 0x00
+#define IRQ7_ACTIVE_LOW 0x80
+#define IRQ7_ACTIVE_HIGH 0x00
+#define AIPCFG2_MASK 0xF8
+
+//
+// FCFG1
+//
+
+#define FDC_ENABLE 0x01
+#define PRIMARY_FDC_ADDRESS 0x00
+#define SECONDARY_FDC_ADDRESS 0x02
+#define TWO_DISK_DRIVES 0x00
+#define FOUR_DISK_DRIVES 0x80
+#define FCFG1_MASK 0x83
+
+//
+// FCFG2
+//
+
+#define FDC_DIRECT_POWERDOWN 0x01
+#define FDC_IDLE 0x02 /* read-only */
+#define RESET_FDC_MODULE 0x04
+#define FDC_AUTO_POWERDOWN_ENABLE 0x08
+#define FCFG2_MASK 0x0F
+
+//
+// PCFG1
+//
+
+#define PP_ENABLE 0x01
+#define PP_ADDRESS_SELECT_0 0x00 /* 378-37F */
+#define PP_ADDRESS_SELECT_1 0x02 /* 278-27F */
+#define PP_ADDRESS_SELECT_2 0x04 /* 3BC-3BE */
+#define PP_IRQ7 0x08
+#define PP_IRQ5 0x00
+#define PP_HWMODE_ISA_COMPAT 0x00
+#define PP_HWMODE_PS2_COMPAT 0x20
+#define PP_HWMODE_EPP 0x40
+#define PP_HWMODE_ECP 0x60 /* read-only */
+#define PP_FIFO_THRSEL_1 0x80
+#define PP_FIFO_THRSEL_8 0x00
+#define PCFG1_MASK 0xEF
+
+
+//
+// PCFG2
+//
+
+#define PP_DIRECT_POWERDOWN 0x01
+#define PP_IDLE 0x02 /* read-only */
+#define PP_RESET 0x04
+#define PP_AUTO_POWERDOWN_ENABLE 0x08
+#define PP_FIFO_UNDERRUN_OR_OVERRUN 0x20
+#define PCFG2_MASK 0x2F
+
+//
+// SACFG1
+//
+
+#define PORTA_ENABLE 0x01
+#define PORTA_ADDRESS_SELECT_0 0x00 /* 3F8-3FF */
+#define PORTA_ADDRESS_SELECT_1 0x02 /* 2F8-2FF */
+#define PORTA_ADDRESS_SELECT_2 0x04 /* 220-227 */
+#define PORTA_ADDRESS_SELECT_3 0x06 /* 228-22F */
+#define PORTA_ADDRESS_SELECT_4 0x08 /* 238-23F */
+#define PORTA_ADDRESS_SELECT_5 0x0A /* 2E8-2EF */
+#define PORTA_ADDRESS_SELECT_6 0x0C /* 338-33F */
+#define PORTA_ADDRESS_SELECT_7 0x0D /* 3E8-3EF */
+#define PORTA_IRQ4 0x10
+#define PORTA_IRQ3 0x00
+#define PORTA_MIDI_CLOCK_2000KHZ 0x80
+#define PORTA_MIDI_CLOCK_1846KHZ 0x00
+#define SACFG1_MASK 0x9F
+
+
+//
+// SACFG2
+//
+
+#define PORTA_DIRECT_POWERDOWN 0x01
+#define PORTA_IDLE 0x02 /* read-only */
+#define PORTA_RESET 0x04
+#define PORTA_AUTO_POWERDOWN_ENABLE 0x08
+#define PORTA_TEST_MODE_ENABLE 0x10
+#define SACFG2_MASK 0x1F
+
+//
+// SBCFG1
+//
+
+#define PORTB_ENABLE 0x01
+#define PORTB_ADDRESS_SELECT_0 0x00 /* 3F8-3FF */
+#define PORTB_ADDRESS_SELECT_1 0x02 /* 2F8-2FF */
+#define PORTB_ADDRESS_SELECT_2 0x04 /* 220-227 */
+#define PORTB_ADDRESS_SELECT_3 0x06 /* 228-22F */
+#define PORTB_ADDRESS_SELECT_4 0x08 /* 238-23F */
+#define PORTB_ADDRESS_SELECT_5 0x0A /* 2E8-2EF */
+#define PORTB_ADDRESS_SELECT_6 0x0C /* 338-33F */
+#define PORTB_ADDRESS_SELECT_7 0x0D /* 3E8-3EF */
+#define PORTB_IRQ4 0x10
+#define PORTB_IRQ3 0x00
+#define PORTB_MIDI_CLOCK_2000KHZ 0x80
+#define PORTB_MIDI_CLOCK_1846KHZ 0x00
+#define SBCFG1_MASK 0x9F
+
+
+//
+// SBCFG2
+//
+
+#define PORTB_DIRECT_POWERDOWN 0x01
+#define PORTB_IDLE 0x02 /* read-only */
+#define PORTB_RESET 0x04
+#define PORTB_AUTO_POWERDOWN_ENABLE 0x08
+#define PORTB_TEST_MODE_ENABLE 0x10
+#define SBCFG2_MASK 0x1F
+
+//
+// IDECFG
+//
+
+#define IDE_INTERFACE_ENABLE 0x01
+#define PRIMARY_IDE_ADDRESS 0x00
+#define SECONDARY_IDE_ADDRESS 0x02
+#define IDE_DUAL_INTERFACE 0x04
+#define IDECFG_MASK 0x07
+
+
+typedef struct _INTEL_AIP_CONTROL {
+ UCHAR Reserved1[0x22];
+ UCHAR AIPConfigIndexRegister; // Offset 0x22
+ UCHAR AIPConfigTargetRegister; // Offset 0x23
+// UCHAR Reserved1[0x26E];
+// UCHAR AIPConfigIndexRegister; // Offset 0x26E
+// UCHAR AIPConfigTargetRegister; // Offset 0x26F
+} INTEL_AIP_CONTROL, *PINTEL_AIP_CONTROL;
+
diff --git a/private/ntos/nthals/halfire/ppc/fparch.h b/private/ntos/nthals/halfire/ppc/fparch.h
new file mode 100644
index 000000000..99c9685fd
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fparch.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1995. FirePower Systems, Inc.
+ * (Do Not Distribute without permission)
+ *
+ * $RCSfile: fparch.h $
+ * $Revision: 1.4 $
+ * $Date: 1996/01/11 07:05:05 $
+ * $Locker: $
+ *
+ */
+
+#ifndef _FPARCH_H
+#define _FPARCH_H
+//
+// These names are not sacrosanct, and should be revised upon input from Susan,
+// Jim, and anyone else interested.
+//
+enum scope_use {
+ ENG,
+ MFG,
+ TEST,
+ CUST
+ };
+
+enum rel_state {
+ GENERAL,
+ OFFICIAL,
+ TESTING,
+ CONTROLLED,
+ LAB
+ };
+
+
+typedef struct _TheBigRev {
+ CHAR Org[80]; // originating organization, ( i.e.
+ // who built it )
+ enum scope_use Scope; // release status from the releasing org
+ CHAR BuildDate[16]; // time of year, date, day, hour, min,
+ CHAR BuildTime[16]; // time of year, date, day, hour, min,
+ // sec it was built
+ UCHAR Major; // the Major revision of this item
+ UCHAR Minor; // Minor rev of this item:
+ enum rel_state State; // the release status of this item
+} RelInfo;
+
+#endif // _FPARCH_H
diff --git a/private/ntos/nthals/halfire/ppc/fpbat.c b/private/ntos/nthals/halfire/ppc/fpbat.c
new file mode 100644
index 000000000..cdebbf049
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpbat.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpbat.c $
+ * $Revision: 1.7 $
+ * $Date: 1996/05/14 02:32:13 $
+ * $Locker: $
+ */
+
+/*++
+
+Module Name:
+
+fpbat.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a Sandalfoot PowerPC system using either an S3 or Weitek P9000
+ video adapter.
+
+Author:
+
+ Roger Lanser February 1995
+ Bill Rees May 1995
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Roger Lanser 02-23-95: Added FirePower Video and INT10, nuc'd others
+
+--*/
+
+#include "halp.h"
+#include "string.h"
+#include "fpbat.h"
+#include "arccodes.h"
+#include "phsystem.h"
+#include "pxmemctl.h"
+#include "fpdcc.h"
+#include "fpcpu.h"
+#include "fpdebug.h"
+#include "phsystem.h"
+#include "x86bios.h"
+#include "pxpcisup.h"
+
+#define MAX_DBATS 4
+
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+#if defined(ALLOC_PRAGMA)
+#pragma alloc_text(INIT, HalpInitializeVRAM)
+#if DBG
+#pragma alloc_text(INIT, HalpDisplayBatForVRAM)
+#endif
+#endif
+
+extern ULONG TmpVramBase;
+extern ULONG TmpDbatNum;
+extern ULONG TmpDbatVal;
+extern BOOLEAN HalpDisplayOwnedByHal; // make sure is false: [breeze:1/27/95]
+
+
+extern PUCHAR HalpVideoMemoryBase;
+extern ULONG HalpVideoMemorySize;
+extern BOOLEAN HalpDisplayTypeUnknown;
+
+#define MEM1MB 0x00100000
+#define MEM2MB 0x00200000
+#define MEM4MB 0x00400000
+
+//
+// Define OEM font variables.
+//
+
+
+
+/*++
+
+Routine Description: PVOID HalpMarkDbatForVRAM ()
+
+ This function Marks the VRAM DBAT cacheable and if it's on an
+ mp system marks the DBAT with the memory coherence attribute
+ according to the architecture manual.
+
+Arguments:
+
+ VramBase - The base of VRAM to map.
+
+ VramSize - The size of VRAM to map (output).
+
+Return Value:
+
+ Mapped virtual address.
+
+--*/
+
+VOID
+HalpMarkDbatForVRAM (
+ IN PVOID /* PHYSICAL_ADDRESS */ VramBase,
+ IN OUT PULONG VramSize
+ )
+{
+ ULONG i, low, hi;
+ //
+ // find the bat register used for the display memory and make
+ // it cacheable
+ //
+ for (i = 0; i < MAX_DBATS; i++) {
+ low = HalpGetLowerDBAT(i);
+ if ((low & 0xfffe0000) == (ULONG) VramBase) {
+ //
+ // Turn cache bit on.
+ //
+ hi = HalpGetUpperDBAT(i);
+ hi &= 0xfffe0000; // Clear BL, Vs, Vp bit
+ low &= 0xffffff87; // Clear W, I, M, & G bits -
+ // assuming PP is set to 10
+ switch (*VramSize) {
+ case MEM1MB:
+ hi |= 0x1f; // Set 1MB block size with Vs & Vp bits on
+ break;
+ case MEM2MB:
+ hi |= 0x3f; // Set 2MB block size with Vs & Vp bits on
+ break;
+ case MEM4MB:
+ default:
+ hi |= 0x7f; // Set 4MB block size with Vs & Vp bits on
+ break;
+ }
+
+ //
+ // Gives us a flag to turn off cached VRAM during debug
+ // sessions. Makes the display more trust worthy.
+ //
+ HDBG(DBG_DISPNOCACHE, low |= CACHE_INHIBIT;);
+
+ //
+ // Flag to turn on MEMORY COHERENCE, i.e. make it a global
+ // attribute so the processor will through the proper signals
+ // onto the bus to allow other cpus to snoop and act on it.
+ //
+ HDBG(DBG_DISPMEMCOHERE, low |= MEMORY_COHRNCY;);
+ HalpSetUpperDBAT(i, hi);
+ if ((SystemType == SYS_POWERTOP) || (SystemType == SYS_POWERSLICE)
+ || (SystemType == SYS_POWERSERVE)) {
+ low |= MEMORY_COHRNCY;
+ }
+ HalpSetLowerDBAT(i, low);
+ break;
+ }
+ }
+
+}
+/*++
+
+Routine Description: PVOID HalpInitializeVRAM ()
+
+ This function maps the VRAM DBAT and marks it cacheable.
+
+Arguments:
+
+ VramBase - The base of VRAM to map.
+
+ VramSize - The size of VRAM to map (output).
+
+Return Value:
+
+ Mapped virtual address.
+
+--*/
+
+PVOID
+HalpInitializeVRAM (
+ IN PVOID /* PHYSICAL_ADDRESS */ VramBase,
+ IN OUT PULONG VramSize,
+ OUT PULONG VramWidth
+ )
+{
+ PVOID va = NULL;
+ ULONG hi, low, detect_reg;
+ LONG i;
+
+ switch (SystemType) {
+ case SYS_POWERPRO:
+ /*
+ * Read VRAM presence detect register SIMM01
+ */
+ detect_reg = READ_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase)+0x0890);
+ if ((detect_reg & 0xf0) == 0xf0 ) {
+ *VramSize = MEM1MB;
+ *VramWidth = VRAM_32BIT;
+ } else {
+ *VramSize = MEM2MB;
+ *VramWidth = VRAM_64BIT;
+ }
+ break;
+ case SYS_POWERTOP:
+ /*
+ * Read VRAM presence detect register SIMM23
+ */
+ detect_reg = READ_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase)+0x08C0);
+ //
+ // if either of the vram simms in slot 2 or 3 appears missing ( i.e.
+ // reports it's nibble is an 'f' ), set the vram size to 2 meg.
+ //
+ if (((detect_reg & 0xf0) == 0xf0) || ((detect_reg & 0x0f) == 0x0f)) {
+ *VramSize = MEM2MB;
+ *VramWidth = VRAM_64BIT;
+ } else {
+ *VramSize = MEM4MB;
+ *VramWidth = VRAM_128BIT;
+ }
+ break;
+ case SYS_POWERSERVE:
+ case SYS_UNKNOWN:
+ default:
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ break;
+ }
+
+ //
+ // Map a BAT.
+ //
+
+ va = KePhase0MapIo(VramBase, *VramSize);
+
+ if (!va) {
+ //
+ // Bad news, the map failed. Look for the DBAT that has the
+ // memory space mapping and use it.
+ //
+ for (i = 0; i < MAX_DBATS; i++) {
+ low = HalpGetLowerDBAT(i);
+ if (IO_MEMORY_PHYSICAL_BASE == (low &= 0xfffe0000)) {
+ low |= IO_MEMORY_PHYSICAL_BASE;
+ HalpSetLowerDBAT(i, low);
+ hi = HalpGetUpperDBAT(i);
+ va = (PVOID)(hi & 0xfffe0000); // Get va
+ break;
+ }
+ }
+ //
+ // Give up...
+ //
+ if (!va) {
+ return va;
+ }
+ }
+
+ //
+ // find the bat register used for the display memory and make
+ // it cacheable
+ //
+ for (i = 0; i < MAX_DBATS; i++) {
+ low = HalpGetLowerDBAT(i);
+ if ((low & 0xfffe0000) == (ULONG) VramBase) {
+ //
+ // Turn cache bit on.
+ //
+ hi = HalpGetUpperDBAT(i);
+ hi &= 0xfffe0000; // Clear BL, Vs, Vp bit
+ low &= 0xffffff87; // Clear W, I, M, & G bits -
+ // assuming PP is set to 10
+ switch (*VramSize) {
+ case MEM1MB:
+ hi |= 0x1f; // Set 1MB block size with Vs & Vp bits on
+ break;
+ case MEM2MB:
+ hi |= 0x3f; // Set 2MB block size with Vs & Vp bits on
+ break;
+ case MEM4MB:
+ default:
+ hi |= 0x7f; // Set 4MB block size with Vs & Vp bits on
+ break;
+ }
+
+ //
+ // Gives us a flag to turn off cached VRAM during debug
+ // sessions. Makes the display more trust worthy.
+ //
+ // HDBG(DBG_DISPNOCACHE, low |= CACHE_INHIBIT;);
+
+ //
+ // Flag to turn on MEMORY COHERENCE, i.e. make it a global
+ // attribute so the processor will through the proper signals
+ // onto the bus to allow other cpus to snoop and act on it.
+ //
+ // HDBG(DBG_DISPMEMCOHERE, low |= MEMORY_COHRNCY;);
+ HalpSetUpperDBAT(i, hi);
+ if ( SystemDescription[SystemType].Flags & SYS_MPFOREAL) {
+ low |= MEMORY_COHRNCY;
+ }
+ HalpSetLowerDBAT(i, low);
+ break;
+ }
+ }
+ return va;
+}
+
+#if DBG
+/*++
+
+ Routine Description: VOID HalpDisplayBatForVRAM ()
+
+ This function displays the VRAM BAT.
+
+Arguments:
+
+
+Return Value:
+
+ none
+
+--*/
+
+VOID
+HalpDisplayBatForVRAM (
+ void
+ )
+{
+ ULONG hi, low;
+ LONG i;
+
+ //
+ // Look for the DBAT mapped to the VRAM
+ //
+ for (i = 0; i < 4; i++) {
+ low = HalpGetLowerDBAT(i);
+ if ((low & 0xfffe0000) == (ULONG)DISPLAY_MEMORY_BASE) {
+ hi = HalpGetUpperDBAT(i);
+ HalpDebugPrint("HalpDisplayBatForVRAM: (%d): U(0x%08x) L(0x%08x)\n", i, hi, low);
+ break;
+ }
+ }
+}
+#endif // DBG
diff --git a/private/ntos/nthals/halfire/ppc/fpbat.h b/private/ntos/nthals/halfire/ppc/fpbat.h
new file mode 100644
index 000000000..bb9266092
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpbat.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpbat.h $
+ * $Revision: 1.2 $
+ * $Date: 1996/01/11 07:05:18 $
+ * $Locker: $
+ */
+
+#ifndef _FPBAT_H
+#define _FPBAT_H
+
+PVOID HalpInitializeVRAM ( PVOID , PULONG, PULONG );
+
+#if DBG
+VOID HalpDisplayBatForVRAM ( void );
+#endif
+
+#endif // _FPBAT_H
diff --git a/private/ntos/nthals/halfire/ppc/fpbt445.c b/private/ntos/nthals/halfire/ppc/fpbt445.c
new file mode 100644
index 000000000..514a81778
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpbt445.c
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpbt445.c $
+ * $Revision: 1.9 $
+ * $Date: 1996/05/14 02:32:18 $
+ * $Locker: $
+ *
+ * This file contains references to registers in the display controller chip
+ * known as the DCC. This chip control's vram setup and works in conjunction
+ * with the ram dac which, in this case is a Brooktree Bt485.
+ *
+ */
+
+#include "halp.h"
+#include "phsystem.h"
+#include "fpio.h"
+#include "fpDcc.h"
+#include "fpBt445.h"
+
+VOID
+HalpSetupBt445(
+ ULONG Mode,
+ ULONG VramWidth
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the display hardware for 640x480 in preparation
+ for HalDisplayString(). This means that either we are booting up or
+ dealing with the blue screen of death. We should really change this to
+ a higher resolution ASAP. [ged]
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG i;
+ ULONG modeIndex;
+
+
+ //
+ // BT445 Mask value
+ //
+ // The order of entries must match btTab
+ //
+ UCHAR btMask[30][3] = {
+ {6,0x05,0x3f},
+ {6,0x06,0xcf},
+ {6,0x07,0x00},
+ {2,0x06,0x7f},
+ {6,0x0a,0xbb},
+ {6,0x0d,0x00},
+ {5,0x00,0x00},
+ {5,0x08,0x00},
+ {5,0x10,0x00},
+ {6,0x09,0x00},
+ {6,0x01,0xdf},
+ {6,0x02,0xbf},
+ {5,0x1a,0x0f},
+ {5,0x22,0x03},
+ {6,0x0f,0x00},
+ {6,0x03,0x3f},
+ {6,0x0b,0x3f},
+ {5,0x01,0x00},
+ {5,0x09,0x00},
+ {5,0x11,0x00},
+ {2,0x05,0x00},
+ {2,0x04,0x00},
+ {5,0x18,0x00},
+ {5,0x19,0x00},
+ {5,0x1b,0x0f},
+ {5,0x20,0x00},
+ {5,0x21,0x00},
+ {5,0x23,0x03},
+ {6,0x0e,0x00},
+ {6,0x08,0x1c}
+ };
+
+ // BT445 Address register
+ // address (index)
+ // register
+ // 2 = BT445 Group 0 Register
+ // 5 = BT445 Config Register
+ // 6 = BT445 Group 1 Register
+ // value
+ typedef struct {
+ UCHAR reg;
+ UCHAR addr;
+ UCHAR value;
+ } BTTAB; // [rdl:01.03.95]
+
+ // [rdl:01.03.95]
+ BTTAB btTab[3 /* 32/64/128 bit vram */][2 /* mode 0 or 15 */][30] = {
+ // 32 bit VRAM width
+ {
+ // Mode 0 - 640X480 8 bit 72Hz
+ {
+ {6,0x05,0x2c},
+ {6,0x06,0x84},
+ {6,0x07,0x84},
+ {2,0x06,0x00},
+ {6,0x0a,0x00},
+ {6,0x0d,0x08},
+ {5,0x00,0x07},
+ {5,0x08,0x07},
+ {5,0x10,0x07},
+ {6,0x09,0x40},
+ {6,0x01,0x40},
+ {6,0x02,0x00},
+ {5,0x1a,0x00},
+ {5,0x22,0x00},
+ {6,0x0f,0x01},
+ {6,0x03,0x03},
+ {6,0x0b,0x03},
+ {5,0x01,0x08},
+ {5,0x09,0x08},
+ {5,0x11,0x08},
+ {2,0x05,0x00},
+ {2,0x04,0xff},
+ {5,0x18,0x00},
+ {5,0x19,0x01},
+ {5,0x1b,0x00},
+ {5,0x20,0x00},
+ {5,0x21,0x01},
+ {5,0x23,0x00},
+ {6,0x0e,0x00},
+ {6,0x08,0x04}
+ },
+
+ // Mode 15 - 1024X768 8 bit 60Hz
+ {
+ {6,0x05,0x37},
+ {6,0x06,0x45},
+ {6,0x07,0x84},
+ {2,0x06,0x00},
+ {6,0x0a,0x00},
+ {6,0x0d,0x08},
+ {5,0x00,0x07},
+ {5,0x08,0x07},
+ {5,0x10,0x07},
+ {6,0x09,0x40},
+ {6,0x01,0x40},
+ {6,0x02,0x00},
+ {5,0x1a,0x00},
+ {5,0x22,0x00},
+ {6,0x0f,0x01},
+ {6,0x03,0x03},
+ {6,0x0b,0x03},
+ {5,0x01,0x08},
+ {5,0x09,0x08},
+ {5,0x11,0x08},
+ {2,0x05,0x00},
+ {2,0x04,0xff},
+ {5,0x18,0x00},
+ {5,0x19,0x01},
+ {5,0x1b,0x00},
+ {5,0x20,0x00},
+ {5,0x21,0x01},
+ {5,0x23,0x00},
+ {6,0x0e,0x00},
+ {6,0x08,0x04}
+ }
+ },
+ // 64 bit VRAM width
+ {
+ // Mode 0 - 640X480 8 bit 72Hz
+ {
+ {6,0x05,0x2c},
+ {6,0x06,0x84},
+ {6,0x07,0x84},
+ {2,0x06,0x00},
+ {6,0x0a,0x80},
+ {6,0x0d,0x08},
+ {5,0x00,0x07},
+ {5,0x08,0x07},
+ {5,0x10,0x07},
+ {6,0x09,0x00},
+ {6,0x01,0x40},
+ {6,0x02,0x00},
+ {5,0x1a,0x00},
+ {5,0x22,0x00},
+ {6,0x0f,0x01},
+ {6,0x03,0x07},
+ {6,0x0b,0x07},
+ {5,0x01,0x08},
+ {5,0x09,0x08},
+ {5,0x11,0x08},
+ {2,0x05,0x00},
+ {2,0x04,0xff},
+ {5,0x18,0x00},
+ {5,0x19,0x01},
+ {5,0x1b,0x00},
+ {5,0x20,0x00},
+ {5,0x21,0x01},
+ {5,0x23,0x00},
+ {6,0x0e,0x00},
+ {6,0x08,0x04}
+ },
+
+ // Mode 15 - 1024X768 8 bit 60Hz
+ {
+ {6,0x05,0x37},
+ {6,0x06,0x45},
+ {6,0x07,0x84},
+ {2,0x06,0x00},
+ {6,0x0a,0x80},
+ {6,0x0d,0x08},
+ {5,0x00,0x07},
+ {5,0x08,0x07},
+ {5,0x10,0x07},
+ {6,0x09,0x00},
+ {6,0x01,0x40},
+ {6,0x02,0x00},
+ {5,0x1a,0x00},
+ {5,0x22,0x00},
+ {6,0x0f,0x01},
+ {6,0x03,0x07},
+ {6,0x0b,0x07},
+ {5,0x01,0x08},
+ {5,0x09,0x08},
+ {5,0x11,0x08},
+ {2,0x05,0x00},
+ {2,0x04,0xff},
+ {5,0x18,0x00},
+ {5,0x19,0x01},
+ {5,0x1b,0x00},
+ {5,0x20,0x00},
+ {5,0x21,0x01},
+ {5,0x23,0x00},
+ {6,0x0e,0x00},
+ {6,0x08,0x04}
+ }
+ },
+ // 128 bit VRAM width
+ {
+ // Mode 0 - 640X480 8 bit 72Hz
+ {
+ {6,0x05,0x2c},
+ {6,0x06,0x84},
+ {6,0x07,0x84},
+ {2,0x06,0x00},
+ {6,0x0a,0x80},
+ {6,0x0d,0x08},
+ {5,0x00,0x07},
+ {5,0x08,0x07},
+ {5,0x10,0x07},
+ {6,0x09,0x00},
+ {6,0x01,0x40},
+ {6,0x02,0x00},
+ {5,0x1a,0x00},
+ {5,0x22,0x00},
+ {6,0x0f,0x01},
+ {6,0x03,0x07},
+ {6,0x0b,0x07},
+ {5,0x01,0x08},
+ {5,0x09,0x08},
+ {5,0x11,0x08},
+ {2,0x05,0x00},
+ {2,0x04,0xff},
+ {5,0x18,0x00},
+ {5,0x19,0x01},
+ {5,0x1b,0x00},
+ {5,0x20,0x00},
+ {5,0x21,0x01},
+ {5,0x23,0x00},
+ {6,0x0e,0x00},
+ {6,0x08,0x04}
+ },
+
+ // Mode 15 - 1024X768 8 bit 60Hz
+ {
+ {6,0x05,0x37},
+ {6,0x06,0x45},
+ {6,0x07,0x84},
+ {2,0x06,0x00},
+ {6,0x0a,0x80},
+ {6,0x0d,0x08},
+ {5,0x00,0x07},
+ {5,0x08,0x07},
+ {5,0x10,0x07},
+ {6,0x09,0x00},
+ {6,0x01,0x40},
+ {6,0x02,0x00},
+ {5,0x1a,0x00},
+ {5,0x22,0x00},
+ {6,0x0f,0x01},
+ {6,0x03,0x07},
+ {6,0x0b,0x07},
+ {5,0x01,0x08},
+ {5,0x09,0x08},
+ {5,0x11,0x08},
+ {2,0x05,0x00},
+ {2,0x04,0xff},
+ {5,0x18,0x00},
+ {5,0x19,0x01},
+ {5,0x1b,0x00},
+ {5,0x20,0x00},
+ {5,0x21,0x01},
+ {5,0x23,0x00},
+ {6,0x0e,0x00},
+ {6,0x08,0x04}
+ }
+ }
+ };
+
+
+
+ //
+ // Setup the RAMDAC (Bt445)
+ //
+ // go table driven [rdl:01.03.95]
+ //
+ modeIndex = (Mode) ? 1 : 0; // if not mode 0, then make it mode 15.
+ for (i = 0; i < sizeof(btTab[0][0])/sizeof(BTTAB); i++) {
+ BTTAB tab = btTab[VramWidth][modeIndex][i];
+ UCHAR value = tab.value;
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpIoControlBase + BT445_ADDRESS, tab.addr);
+ FireSyncRegister();
+
+ if (tab.reg == btMask[i][0] && tab.addr == btMask[i][1]) {
+ if (btMask[i][2]) {
+ value = READ_REGISTER_UCHAR((PUCHAR)HalpIoControlBase + BT445_ADDRESS + tab.reg);
+ value &= ~btMask[i][2];
+ value |= btMask[i][2] & tab.value;
+ }
+ } else {
+ //
+ // btMask is out of order with respect to btTab
+ //
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpIoControlBase + BT445_ADDRESS + tab.reg, value);
+ FireSyncRegister();
+ }
+
+ //
+ // ...and program the color lookup table with "NT" colors
+ // starting pixel address for loading RGB values:
+ //
+ rRamDacAddr = 0;
+ FireSyncRegister();
+
+ //
+ // load the red, green, and blue data for pixel 0:
+ //
+ rDacPrimeLut = 0x00;
+ FireSyncRegister();
+ rDacPrimeLut = 0x00;
+ FireSyncRegister();
+ rDacPrimeLut = 0x00;
+ FireSyncRegister();
+
+ //
+ // load the red, green, and blue data for pixel 1: ( this gives NT
+ // the characteristice BLUE screen for booting )
+ //
+ rDacPrimeLut = 0x00;
+ FireSyncRegister();
+ rDacPrimeLut = 0x00;
+ FireSyncRegister();
+ rDacPrimeLut = 0xff;
+ FireSyncRegister();
+
+ for (i=2; i<=0xff; i++) {
+ /* A grey ramp with entry 255 white */
+ rDacPrimeLut = (UCHAR) i;
+ rDacPrimeLut = (UCHAR) i;
+ rDacPrimeLut = (UCHAR) i;
+ FireSyncRegister();
+ }
+
+ return;
+} // Init Vram
+
+ULONG
+HalpSetPixelColorMap( ULONG Color, ULONG Pixel )
+{
+ UCHAR Red, Green, Blue, Control;
+ //
+ // set the display to red while in phase 0:
+ //
+ rRamDacAddr = (UCHAR) ( Pixel & 0x000000ff);
+ FireSyncRegister();
+
+ Control = (UCHAR) ( ( Color >> 24 ) & 0x000000ff );
+ Red = (UCHAR) ( ( Color >> 16 ) & 0x000000ff );
+ Green = (UCHAR) ( ( Color >> 8 ) & 0x000000ff );
+ Blue = (UCHAR) ( Color & 0x000000ff );
+ //
+ // load the red, green, and blue data for pixel 1:
+ // ( this is the normal NT BLUE boot screen )
+ //
+ rDacPrimeLut = Red; // set this pixel to no red ...
+ FireSyncRegister();
+ rDacPrimeLut = Green; // set this pixel to no green ...
+ FireSyncRegister();
+ rDacPrimeLut = Blue; // set this pixel to max blue.
+ FireSyncRegister();
+ return(0);
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/fpbt445.h b/private/ntos/nthals/halfire/ppc/fpbt445.h
new file mode 100644
index 000000000..3b2d721f6
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpbt445.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpbt445.h $
+ * $Revision: 1.7 $
+ * $Date: 1996/01/11 07:05:32 $
+ * $Locker: $
+ *
+ * This file contains references to registers in the BrookTree Bt445 RamDac.
+ *
+ */
+
+#ifndef FPBT445_H
+#define FPBT445_H
+/*
+** The Bt445 organizes it's registers into a complex index based arrangement.
+** The final data registers are actually accessed via some control bits which
+** show up memory mapped. However, since each control address can access
+** several registers, the register desired must be specified through the Bt445
+** index register. For example, if you want to read the ID value of the chip,
+** you must write the id register value ( 0x00 ) to the Bt445 address ( index ).
+** Then you must read the address that corresponds to control register 2.
+**
+*/
+
+//
+// defines for access to control register 0 ( c bits = 000 )
+// Use rRamDacAddr to access the Bt445 address register
+//
+#define BT_Address 0x00 // index register into the Bt445.
+
+//
+// defines for access to control register 1 ( c bits = 001 )
+// Use rDacPrimeLut to access the primary color palette register
+// NOTE: This register requires MODULO 3 loading and reading
+//
+
+
+//
+// defines for access to control register 2 ( c bits = 010 )
+// use rRamDacCntl to access
+//
+#define DAC_ID_REG 0x00 //
+#define DAC_REVISION_REG 0x01
+#define DAC_READ_ENABLE 0x04
+#define DAC_BLINK_ENABLE 0x05
+#define DAC_COMMAND_REG0 0x06
+#define DAC_TEST_REG0 0x07
+
+//
+// defines for access to control register 3 ( c bits = 011 )
+// use rDacOvlayLut to access the overlay color palette
+// NOTE: This register requires MODULO 3 loading and reading
+//
+
+
+//
+// defines for access to control register 5 ( c bits = 101 )
+// use rDacPixelBit to access the rgb pixel layout register
+//
+#define RED_MSB_POSITION 0x00
+#define RED_WIDTH_CNTL 0x01
+#define RED_DISPLAY_ENBL 0x02
+#define RED_BLINK_ENBL 0x03
+
+#define GREEN_MSB_POSITION 0x08
+#define GREEN_WIDTH_CNTL 0x09
+#define GREEN_DISPLAY_ENBL 0x0A
+#define GREEN_BLINK_ENBL 0x0B
+
+#define BLUE_MSB_POSITION 0x10
+#define BLUE_WIDTH_CNTL 0x11
+#define BLUE_DISPLAY_ENBL 0x12
+#define BLUE_BLINK_ENBL 0x13
+
+#define OVRLY_MSB_POSITION 0x18
+#define OVRLY_WIDTH_CNTL 0x19
+#define OVRLY_DISPLAY_ENBL 0x1A
+#define OVRLY_BLINK_ENBL 0x1B
+
+#define CURSOR_MSB_POSITION 0x20
+#define CURSOR_WIDTH_CNTL 0x21
+#define CURSOR_DISPLAY_ENBL 0x22
+#define CURSOR_BLINK_ENBL 0x23
+
+
+
+//
+// defines for access to control register 6 ( c bits = 110 )
+// use rDacPixelClks to access
+//
+#define TEST_REG1 0x00
+#define COMMAND_REG1 0x01
+#define DIGI_OUT_CNTL 0x02
+#define VIDCLK_CYCLE 0x03
+#define PIXEL_PLL_RATE0 0x05
+#define PIXEL_PLL_RATE1 0x06
+#define PLL_CONTROL 0x07
+#define PIXEL_LOAD_CNTL 0x08
+#define PIXEL_PORT_START 0x09
+#define PIXEL_FORMAT_CNTL 0x0A
+#define MPX_RATE_REG 0x0B
+#define SIG_ANLYS_REG 0x0C
+#define PIXEL_DEPTH_CNTL 0x0D
+#define PALETTE_BYPASS_POS 0x0E
+#define PALETTE_BYPASS_WIDTH 0x0F
+
+//
+// defines for access to control register 7 ( c bits = 111 )
+// use rRamDacCursor to access the cursor color register
+// NOTE: This register requires MODULO 3 loading and reading
+//
+#define CURSOR_CLR0 0x00
+#define CURSOR_CLR1 0x01
+#define CURSOR_CLR2 0x02
+#define CURSOR_CLR3 0x03
+
+/*
+**
+**.................... Bit Field Definitions........................
+**
+*/
+
+//
+// Command Register 0 bit masks:
+//
+#define USE_PALETTE 0x40 // use color palette not overlay color 0
+//
+// These defines cover TWO bits: bit positions 4 and 5
+//
+#define BLINK_16ON_48OFF 0x00
+#define BLINK_16ON_16OFF 0x10
+#define BLINK_32ON_32OFF 0x20
+#define BLINK_64ON_64OFF 0x30
+#define ENBL_OVRLY0_BLINK 0x04
+#define ENBL_OVRLY1_BLINK 0x08
+#define ENBL_OVRLY0_DSPLY 0x02
+#define ENBL_OVRLY1_DSPLY 0x01
+
+//
+// COMMAND_REG1: Bit fields
+//
+#define ENABLE_GREEN_SYNC 0x80 // generate sync on the IOG output
+#define IRE75_PEDESTAL 0x40 // generate a blank pedestal of 7.5 IRE
+#define NORMAL_POWER_OP 0x00 // normal operations ( i.e. no pwr dwn )
+#define PWR_OFF_DACS 0x08 // Turn off DACs. functionally still ops
+#define DAC_RAM_OFF 0x10 // Dac and Ram off: no functions out
+#define DAC_RAM_CLKS_OFF 0x18 // turn off clocks too
+#define RIGHT_JSTFY_PIXBITS 0x04 // right justify pixels and zero extend
+#define ENABLE_SIG_ANLYS 0x02 // turn on SAR
+#define RESET_PIPE_DEPTH 0x01
+
+// Pixel Timing Register: Field definitions:
+//
+
+/*
+** Pixel Format Control Fields ( PIXEL_FORMAT_CNTL register )
+**
+*/
+#define UNPACK_LSB_FIRST 0x80
+#define ENABLE_CURSOR 0x20
+#define ENABLE_CURSOR_COLOR0 0x10
+#define ENABLE_OVERLAY 0x08
+#define USE_COLOR_PALETTE 0x00
+#define BYPASS_COLOR_PALETTE 0x01
+#define USE_INPUT_PIXEL_FIELD 0x02
+
+/*
+** Pixel PLL Rate Register 0
+*/
+
+//
+// Prototype Declarations
+//
+
+VOID HalpSetupBt445( ULONG, ULONG );
+ULONG HalpSetPixelColorMap( ULONG Color, ULONG Pixel );
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fpcpu.h b/private/ntos/nthals/halfire/ppc/fpcpu.h
new file mode 100644
index 000000000..9a18fbdaa
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpcpu.h
@@ -0,0 +1,179 @@
+
+/*
+ * Copyright (c) 1995. FirePower Systems, Inc.
+ * (Do Not Distribute without permission)
+ *
+ * $RCSfile: fpcpu.h $
+ * $Revision: 1.8 $
+ * $Date: 1996/05/14 02:32:23 $
+ * $Locker: $
+ *
+ */
+
+#ifndef FPCPU_h
+#define FPCPU_h
+
+//
+// These defines setup access to the power pc chip itself. Reliance upon the
+// defines will isolate code from power pc chip variations and ease migration
+// to new cpus
+//
+
+
+
+//
+// Since the documentation refers to the bit positions of the cpu fields in
+// IBM relative format, handle the conversion of IBM bit position to shift
+// arguments
+//
+#define WORD(x) (( 1 ) << ( 31 - x ))
+
+
+/*
+************************************************************************
+**
+** Machine State Register
+**
+************************************************************************
+*/
+//
+// pull a bit out of the MSR: this is based on IBM bit ordering as shown in
+// the powerpc books ( 0 == MSB )
+//
+
+// #define MSR(x) ( ( HalpReadMsr() >> ( 31 - x ) ) & 0x01 )
+#define MSR(x) ( ( __builtin_get_msr() >> ( 31 - x ) ) & 0x01 )
+
+#define POW 13 // Power Management Enable
+#define TGPR 14 // Temporary GPR remapping
+#define ILE 15 // Exception Little-endian mode
+#define EE 16 // External interrupt enable
+#define PR 17 // Privilege Level
+#define FP 18 // Floating Point Enable
+#define ME 19 // Machine Check Enable
+#define FE0 20 // Floating Point Exception mode 0
+#define SE 21 // single step trace enable
+#define BE 22 // Branch Trace Enable
+#define FE1 23 // floating point exception mode 1
+#define IP 25 // Exception Prefix ( exception vector is 0xff... ?
+#define IR 26 // Instruction Address Translation
+#define DR 27 // Data Address Translation
+#define RI 30 // Recoverable Exception
+#define LE 31 // Endian bit (little or big )
+
+//
+// setup Flags to go along with the MSR bits
+//
+#define ENABLE_PWR_MGMT WORD( POW )
+#define ENABLE_GPR_REMAP WORD( TGPR )
+#define EXCEPTION_LE WORD( ILE )
+#define ENABLE_EXTERNAL_INTS WORD( EE )
+#define EXEC_AT_USER_LEVEL WORD( PR )
+#define FLOAT_PT_AVAIL WORD( FP )
+#define ENABLE_MACHINE_CHK WORD( ME )
+#define FLOAT_EXCPT_MODE0 WORD( FE0 )
+#define ENABLE_SGL_STP_TRCE WORD( SE )
+#define ENABLE_BRNCH_TRCE WORD( BE )
+#define FLOAT_EXCPT_MODE1 WORD( FE1 )
+#define EXCPT_PREFX_0xFFF WORD( IP )
+#define ENABLE_INSTR_TRANS WORD( IR )
+#define ENABLE_DATA_TRANS WORD( DR )
+#define EXCPTION_IS_RECOVBL WORD( RI )
+#define RUN_LITTLE_ENDIAN WORD( LE )
+
+
+/*
+************************************************************************
+**
+** Processor Version Register
+**
+************************************************************************
+*/
+#define CPU_VERSION ( ( ( HalpReadProcessorRev ) & 0xffff0000 ) >> 16 )
+#define CPU_REVISION ( ( ( HalpReadProcessorRev ) & 0x0000ffff ) )
+
+
+/*
+************************************************************************
+**
+** Block Address Translation registers
+**
+************************************************************************
+*/
+//
+// Here are defines for the UPPER 32 bit bat register:
+//
+#define PAGE_INDEX_BITS 0xfffe0000
+#define BLK_EFF_PI(x) ( x & PAGE_INDEX_BITS )
+
+#define A_128K_BLOCK_SIZE 0x00000000
+#define A_256K_BLOCK_SIZE 0x00000004
+#define A_512K_BLOCK_SIZE 0x0000000c
+#define A_1MEG_BLOCK_SIZE 0x0000001c
+#define A_2MEG_BLOCK_SIZE 0x0000003c
+#define A_4MEG_BLOCK_SIZE 0x0000007c
+#define A_8MEG_BLOCK_SIZE 0x000000fc
+#define A_16MB_BLOCK_SIZE 0x000001fc
+#define A_32MB_BLOCK_SIZE 0x000003fc
+#define A_64MB_BLOCK_SIZE 0x000007fc
+#define A_128M_BLOCK_SIZE 0x00000ffc
+#define A_256M_BLOCK_SIZE 0x00001ffc
+
+#define SUPERVISOR_ONLY 0x00000002
+#define USER_ACCESS_VALID 0x00000001
+
+//
+// The Lower BAT Register
+//
+#define BLOCK_REAL_PAGE_NUMBER(x) ( (x >> 8) & REAL_BITS)
+
+//
+// WIMG: VIMVENDERS BITS:
+//
+#define WRITE_THROUGH 0x00000040
+#define CACHE_INHIBIT 0x00000020
+#define MEMORY_COHRNCY 0x00000010
+#define GUARDED_BLOCK 0x00000008 // for IBAT use only....
+
+#define PAGE_RW_ACCESS 0x00000002
+#define PAGE_RO_ACCESS 0x00000001
+#define PAGE_UNAVAILBL 0x00000000
+
+
+/*
+************************************************************************
+**
+** Hardware Implementation Register 0 ( HID0 )
+**
+************************************************************************
+*/
+
+#define EMCP 0 // Enable Machine Check Pin
+#define EBA 2 // Enable Bus Address Parity Checking
+#define EBD 3 // Enable Bus Data Parity Checking
+#define SBCLK 4 // selct bus clock for test clock pin
+#define EICE 5 // Enable ISE outputs: pipeline tracking support
+#define ECLK 6 // Enable external test clock pin
+#define PAR 7 // Disable precharge of ARTRY_L and shared signals
+#define DOZE 8 // Doze mode: pll, time base, and snooping active
+#define NAP 9 // Nap Mode: pll and time base active
+#define SLEEP 10 // Sleep mode: no external clock required
+#define DPM 11 // Enable Dynamic power management
+#define RISEG 12 // Reserved for test
+#define ICE 16 // Instruction cache enable
+#define DCE 17 // Data cache enable
+#define ILOCK 18 // lock instruction cache
+#define DLOCK 19 // lock data cache
+#define ICFI 20 // instruction cache flash invalidate
+#define DCI 21 // Data cache flash invalidate
+#define FBIOB 27 // Force branch indirect on bus
+#define NOOPTI 31 // No-op touch instructions
+
+#define ENABLE_ICACHE WORD( ICE )
+#define ENABLE_DCACHE WORD( DCE )
+#define LOCK_ICACHE WORD( ILOCK )
+#define LOCK_DCACHE WORD( DLOCK )
+#define INVLIDAT_ICACHE WORD( ICFI )
+#define INVLIDAT_DCACHE WORD( DCI )
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fpcpu.s b/private/ntos/nthals/halfire/ppc/fpcpu.s
new file mode 100644
index 000000000..c052c9787
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpcpu.s
@@ -0,0 +1,387 @@
+//++
+//
+// 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:
+//
+// pxsystem.s
+//
+// Abstract:
+//
+// This module implements the routines to handle system functions:
+// Provides system specific info.
+// Currently provides processor version type
+//
+// Author:
+// breeze@firepower.com
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpcpu.s $
+ * $Revision: 1.12 $
+ * $Date: 1996/01/11 07:05:51 $
+ * $Locker: $
+ */
+
+#include "kxppc.h"
+#include "fpcpu.h"
+
+ .set BatValue, r.3
+//++
+//
+// Routine Description:
+//
+//
+// Arguments:
+// None
+//
+//
+// Return Value:
+// Processor Version register value
+//
+//
+//--
+
+
+ LEAF_ENTRY(HalpReadProcessorRev)
+ mfpvr r.3 // get processor version
+ LEAF_EXIT(HalpReadProcessorRev)
+
+
+
+//++
+//
+// Routine Description:
+//
+//
+// Arguments:
+// None
+//
+//
+// Return Value:
+// Machine State register value
+//
+//
+//--
+
+
+ LEAF_ENTRY(HalpGetStack)
+ or r3, r1, r1 // get stack value
+ LEAF_EXIT(HalpGetStack)
+
+
+//++
+//
+// Routine Description:
+//
+//
+// Arguments:
+// None
+//
+//
+// Return Value:
+// Machine State register value
+//
+//
+//--
+
+
+ LEAF_ENTRY(HalpReadMSR)
+ mfmsr r.3 // get processor version
+ LEAF_EXIT(HalpReadMSR)
+
+/*****************************************************************************
+ Synopsis:
+ ULONG HalpReadIbatUpper(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit upper instruction BAT value
+ for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit upper BAT value.
+*****************************************************************************/
+
+ .set BatNumber, r.3
+
+ LEAF_ENTRY(HalpReadIbatUpper)
+
+ cmpli 0,0,BatNumber,0
+ bne NotUI0
+ mfibatu BatNumber,0
+ b ExitUI
+NotUI0:
+ cmpli 0,0,BatNumber,1
+ bne NotUI1
+ mfibatu BatNumber,1
+ b ExitUI
+NotUI1:
+ cmpli 0,0,BatNumber,2
+ bne NotUI2
+ mfibatu BatNumber,2
+ b ExitUI
+NotUI2:
+ mfibatu BatNumber,3 // OK, it's three by default
+
+ExitUI:
+
+ LEAF_EXIT(HalpReadIbatUpper)
+
+/*****************************************************************************
+ Synopsis:
+ ULONG HalpReadIbatLower(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit lower instruction BAT value for given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit lower BAT value.
+*****************************************************************************/
+
+ LEAF_ENTRY(HalpReadIbatLower)
+
+ cmpli 0,0,BatNumber,0
+ bne NotLI0
+ mfibatl BatNumber,0
+ b ExitLI
+NotLI0:
+ cmpli 0,0,BatNumber,1
+ bne NotLI1
+ mfibatl BatNumber,1
+ b ExitLI
+NotLI1:
+ cmpli 0,0,BatNumber,2
+ bne NotLI2
+ mfibatl BatNumber,2
+ b ExitLI
+NotLI2:
+ mfibatl BatNumber,3 // OK, it's three by default
+
+ExitLI:
+
+ LEAF_EXIT(HalpReadIbatLower)
+
+/*****************************************************************************
+ Synopsis:
+ ULONG HalpReadDbatUpper(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit upper data BAT value for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit upper BAT value.
+*****************************************************************************/
+
+ LEAF_ENTRY(HalpReadDbatUpper)
+
+ cmpli 0,0,BatNumber,0
+ bne NotUD0
+ mfdbatu BatNumber,0
+ b ExitUD
+NotUD0:
+ cmpli 0,0,BatNumber,1
+ bne NotUD1
+ mfdbatu BatNumber,1
+ b ExitUD
+NotUD1:
+ cmpli 0,0,BatNumber,2
+ bne NotUD2
+ mfdbatu BatNumber,2
+ b ExitUD
+NotUD2:
+ mfdbatu BatNumber,3 // OK, it's three by default
+
+ExitUD:
+
+ LEAF_EXIT(HalpReadDbatUpper)
+
+/*****************************************************************************
+ Synopsis:
+ ULONG HalpReadDbatLower(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit lower data BAT value for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit lower BAT value.
+*****************************************************************************/
+
+ LEAF_ENTRY(HalpReadDbatLower)
+
+ cmpli 0,0,BatNumber,0
+ bne NotLD0
+ mfdbatl BatNumber,0
+ b ExitLD
+NotLD0:
+ cmpli 0,0,BatNumber,1
+ bne NotLD1
+ mfdbatl BatNumber,1
+ b ExitLD
+NotLD1:
+ cmpli 0,0,BatNumber,2
+ bne NotLD2
+ mfdbatl BatNumber,2
+ b ExitLD
+NotLD2:
+ mfdbatl BatNumber,3 // OK, it's three by default
+
+ExitLD:
+
+ LEAF_EXIT(HalpReadDbatLower)
+
+/*****************************************************************************
+ Synopsis:
+ VOID HalpSetDbat3Lower(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit lower data BAT value <BatValue> to DBAT3.
+
+ Returns:
+ Nothing
+*****************************************************************************/
+
+
+ LEAF_ENTRY(HalpSetDbat3Lower)
+
+ mtdbatl 3,BatValue
+
+ LEAF_EXIT(HalpSetDbat3Lower)
+
+/*****************************************************************************
+ Synopsis:
+ VOID HalpSetDbat3Lower(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit lower data BAT value <BatValue> to DBAT1.
+
+ Returns:
+ Nothing
+*****************************************************************************/
+
+ LEAF_ENTRY(HalpSetDbat2Lower)
+
+ mtdbatl 2,BatValue
+
+ LEAF_EXIT(HalpSetDbat2Lower)
+
+/*****************************************************************************
+ Synopsis:
+ VOID HalpSetDbat3Lower(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit lower data BAT value <BatValue> to DBAT1.
+
+ Returns:
+ Nothing
+*****************************************************************************/
+
+ LEAF_ENTRY(HalpSetDbat1Lower)
+
+ mtdbatl 1,BatValue
+
+ LEAF_EXIT(HalpSetDbat1Lower)
+
+/*****************************************************************************
+ Synopsis:
+ VOID HalpSetDbat3Lower(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit lower data BAT value <BatValue> to DBAT1.
+
+ Returns:
+ Nothing
+*****************************************************************************/
+
+ LEAF_ENTRY(HalpSetDbat0Lower)
+
+ mtdbatl 0,BatValue
+
+ LEAF_EXIT(HalpSetDbat0Lower)
+
+
+/*****************************************************************************
+ Synopsis:
+ VOID HalpGetInstructionTimes()
+
+ Purpose:
+ run a 1024 instructions measure how long the cpu needs to
+ execute them ( measured by time base value which is 1/4 bus speed )
+
+ Algorithm:
+ string together 8 instructions so that they are dependent on their
+ preceding neighbor and loop through this set of 8 instructions 128
+ times. Compare the lower time base register's value before and after
+ this instruction run.
+
+ To guarentee correct timing, this routine waits for the lower time base
+ register to 'flip' to the new value and then start running the test
+ instructions. The run is done three times to make sure the entire
+ sequence is in L1 cache.
+
+ The Time Base runs at 1/4 bus speed so the number of instructions
+ that the cpu executes for a given amount of time is measured as
+ the amount of time required to run 1024 instructions. If the time
+ base changes by 256 'ticks' then the cpu is running at bus speed.
+
+ Returns: the incremental change in the time base lower register
+
+*****************************************************************************/
+
+ //.set LOOPCOUNT, 0x400 // 8 * real loop count (8 * 0x80 ).
+ .set LOOPCOUNT, 0x780 // 8 * real loop count (8 * 0x80 ).
+ LEAF_ENTRY(HalpGetInstructionTimes)
+
+ sync
+ andi. r10,r9,0 // zero r10: holds the current loop count
+ andi. r8,r9,0 // zero r8: holds the do again flag.
+ andi. r7,r9,0 // zero r7: execution time within each loop through
+ andi. r3,r9,0 // zero r3: maintain summation of execution times
+ andi. r9,r9,0 // zero r9: holds the current loop count
+ sync
+START: mftb r6 // save off the starting value of lower time
+ // base register
+CHECK: mftb r5 // check the time base again and see if it's just
+ // changed....
+ cmp 0,0,r5,r6
+ beq CHECK // wait for a new time period to start...
+
+ //
+ // Run through some single cycle instructions. In order to defeat
+ // the double issue pipes of the ppc, create a dependency between
+ // an instruction and the preceding instruction. This will more
+ // accurately reflect the amount of time the cpu uses to execute
+ // an instruction in a stream relative to the bus frequency.
+ //
+TIMES: addi r9,r9,1
+ addi r9,r9,1
+ addi r9,r9,1
+ addi r9,r9,1
+ addi r9,r9,1
+ addi r9,r9,1
+ addi r9,r9,1
+ addi r9,r9,1
+
+ cmpi 0,0,r9,LOOPCOUNT
+ bne TIMES // bc 4,2,TIMES
+ mftb r6 // save off ending value of lower time base register
+ sync
+ andi. r9,r9,0 // zero r9: in preparation for another pass
+ addi r8,r8,1 // increment the flag
+ cmpli 0,0,r8,2 // compare the flag to '2'. Ensure the last pass
+ // through is fully out of L1 cache.
+ blt START // to make sure we're in cache, branch back.
+ subf r3,r5,r6 // subtract r5 from r6 and store in r3 and return.
+
+ LEAF_EXIT(HalpGetInstructionTimes)
diff --git a/private/ntos/nthals/halfire/ppc/fpdcc.c b/private/ntos/nthals/halfire/ppc/fpdcc.c
new file mode 100644
index 000000000..33b5a175b
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpdcc.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpdcc.c $
+ * $Revision: 1.12 $
+ * $Date: 1996/01/11 07:06:05 $
+ * $Locker: $
+ *
+ * This file contains references to registers in the display controller chip
+ * known as the DCC. This chip control's vram setup and works in conjunction
+ * with the ram dac which, in this case is a Brooktree Bt485.
+ *
+ */
+
+#include "halp.h"
+#include "phsystem.h"
+#include "fpio.h"
+#include "fpDcc.h"
+#include "fpbt445.h"
+
+VOID
+HalpSetupDCC(
+ ULONG Mode,
+ ULONG VramWidth
+ );
+/*++
+
+Routine Description: VOID HalpSetupDCC()
+
+ This routine initializes the display hardware for 640x480 in preparation
+ for HalDisplayString(). This means that either we are booting up or
+ dealing with the blue screen of death. We should really change this to
+ a higher resolution ASAP. [ged]
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpSetupDCC(
+ ULONG Mode,
+ ULONG VramWidth
+ )
+{
+ LONG modeIndex;
+ LONG i;
+
+ //
+ // DCC Config A
+ //
+ UCHAR configA[NUMBER_OF_VRAM_WIDTH_TYPES] = {
+ A_1to1_64BitDac | HSYNC_ENABLE | VSYNC_ENABLE | CSYNC_ENABLE,
+ A_1to1_64BitDac | HSYNC_ENABLE | VSYNC_ENABLE | CSYNC_ENABLE,
+ A_2to1_64BitDac | HSYNC_ENABLE | VSYNC_ENABLE | CSYNC_ENABLE
+ };
+
+ // [rdl:01.03.95]
+ typedef struct {
+ UCHAR reg;
+ UCHAR value;
+ } DCCTAB;
+
+ // [rdl:01.03.95]
+ DCCTAB DCCtab[3 /* 32/64/128 bit vram */][2 /* mode 0 or 15 */][13] = {
+ // 32 bit VRAM width
+ {
+ // [0] Mode 0 - 640X480 8 bit 72Hz
+ {
+ {HZNTL_COUNT_L,0xcf},
+ {HZNTL_COUNT_H,0x00},
+ {VERT_COUNT_L,0x07},
+ {VERT_COUNT_H,0x02},
+ {HZNTL_SYNC_STOP,0x09},
+ {HZNTL_BLK_STP_L,0x29},
+ {HZNTL_BLK_STP_H,0x00},
+ {HZNTL_DTA_STP_L,0xc9},
+ {HZNTL_DTA_STP_H,0x00},
+ {VERT_SYNC_STOP,0x02},
+ {VERT_BLK_STOP,0x1e},
+ {VERT_DTA_STP_L,0xfe},
+ {VERT_DTA_STP_H,0x01}
+ },
+ // [1] Mode 15 - 1024X768 8 bit 60Hz
+ {
+ {HZNTL_COUNT_L,0x4f},
+ {HZNTL_COUNT_H,0x01},
+ {VERT_COUNT_L,0x25},
+ {VERT_COUNT_H,0x03},
+ {HZNTL_SYNC_STOP,0x21},
+ {HZNTL_BLK_STP_L,0x49},
+ {HZNTL_BLK_STP_H,0x00},
+ {HZNTL_DTA_STP_L,0x49},
+ {HZNTL_DTA_STP_H,0x01},
+ {VERT_SYNC_STOP,0x05},
+ {VERT_BLK_STOP,0x22},
+ {VERT_DTA_STP_L,0x22},
+ {VERT_DTA_STP_H,0x03},
+ }
+ },
+ // 64 bit VRAM width
+ {
+ // [0] Mode 0 - 640X480 8 bit 72Hz
+ {
+ {HZNTL_COUNT_L,0x67},
+ {HZNTL_COUNT_H,0x00},
+ {VERT_COUNT_L,0x07},
+ {VERT_COUNT_H,0x02},
+ {HZNTL_SYNC_STOP,0x04},
+ {HZNTL_BLK_STP_L,0x14},
+ {HZNTL_BLK_STP_H,0x00},
+ {HZNTL_DTA_STP_L,0x64},
+ {HZNTL_DTA_STP_H,0x00},
+ {VERT_SYNC_STOP,0x02},
+ {VERT_BLK_STOP,0x1e},
+ {VERT_DTA_STP_L,0xfe},
+ {VERT_DTA_STP_H,0x01}
+ },
+ // [1] Mode 15 - 1024X768 8 bit 60Hz
+ {
+ {HZNTL_COUNT_L,0xa7},
+ {HZNTL_COUNT_H,0x00},
+ {VERT_COUNT_L,0x25},
+ {VERT_COUNT_H,0x03},
+ {HZNTL_SYNC_STOP,0x10},
+ {HZNTL_BLK_STP_L,0x24},
+ {HZNTL_BLK_STP_H,0x00},
+ {HZNTL_DTA_STP_L,0xa4},
+ {HZNTL_DTA_STP_H,0x00},
+ {VERT_SYNC_STOP,0x05},
+ {VERT_BLK_STOP,0x22},
+ {VERT_DTA_STP_L,0x22},
+ {VERT_DTA_STP_H,0x03},
+ }
+ },
+ // 128 bit VRAM width
+ {
+ // [0] Mode 0 - 640X480 8 bit 72Hz
+ {
+ {HZNTL_COUNT_L,0x67},
+ {HZNTL_COUNT_H,0x00},
+ {VERT_COUNT_L,0x07},
+ {VERT_COUNT_H,0x02},
+ {HZNTL_SYNC_STOP,0x04},
+ {HZNTL_BLK_STP_L,0x14},
+ {HZNTL_BLK_STP_H,0x00},
+ {HZNTL_DTA_STP_L,0x64},
+ {HZNTL_DTA_STP_H,0x00},
+ {VERT_SYNC_STOP,0x02},
+ {VERT_BLK_STOP,0x1e},
+ {VERT_DTA_STP_L,0xfe},
+ {VERT_DTA_STP_H,0x01}
+ },
+ // [1] Mode 15 - 1024X768 8 bit 60Hz
+ {
+ {HZNTL_COUNT_L,0xa7},
+ {HZNTL_COUNT_H,0x00},
+ {VERT_COUNT_L,0x25},
+ {VERT_COUNT_H,0x03},
+ {HZNTL_SYNC_STOP,0x10},
+ {HZNTL_BLK_STP_L,0x24},
+ {HZNTL_BLK_STP_H,0x00},
+ {HZNTL_DTA_STP_L,0xa4},
+ {HZNTL_DTA_STP_H,0x00},
+ {VERT_SYNC_STOP,0x05},
+ {VERT_BLK_STOP,0x22},
+ {VERT_DTA_STP_L,0x22},
+ {VERT_DTA_STP_H,0x03},
+ }
+ }
+ };
+
+
+ //
+ // Disable all counters and state machines before we go messing around.
+ //
+ rDccIndex = dccConfigB;
+ FireSyncRegister();
+ rDccData = DCC_HALT_CLK;
+ FireSyncRegister();
+
+ HalpSetupBt445(Mode, VramWidth);
+
+ //
+ // Setup the DCC
+ //
+ rDccIndex = dccIntReg;
+ FireSyncRegister();
+ rDccData = 0x00; // Clear the interrupt bit ( bit 0 )
+ FireSyncRegister();
+
+ rDccIndex = dccTimingA;
+ FireSyncRegister();
+ rDccData = 0x07; // delay syncs by 7 DispClk cycles
+ FireSyncRegister();
+
+ rDccIndex = dccConfigA;
+ FireSyncRegister();
+ rDccData = configA[VramWidth];
+ FireSyncRegister();
+
+#define DCC_STORE(reg,val) { \
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpIoControlBase + DCC_INDEX, reg); \
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpIoControlBase + DCC_DATA, val); \
+}
+
+ // go table driven [rdl:01.03.95]
+ modeIndex = (Mode) ? 1 : 0; // if not mode 0, then make it mode 15.
+ for (i = 0; i < sizeof(DCCtab[0][0])/sizeof(DCCTAB); i++) {
+ DCCTAB tab = DCCtab[VramWidth][modeIndex][i];
+ DCC_STORE(tab.reg, tab.value);
+ }
+
+ rDccIndex = dccConfigB; // Turn on counters, *DO LAST*
+ FireSyncRegister();
+ rDccData = 0x00;
+ FireSyncRegister();
+
+ return;
+} // HalpSetupDCC
diff --git a/private/ntos/nthals/halfire/ppc/fpdcc.h b/private/ntos/nthals/halfire/ppc/fpdcc.h
new file mode 100644
index 000000000..09a27bc11
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpdcc.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * (Do Not Distribute without permission)
+ *
+ * $RCSfile: fpdcc.h $
+ * $Revision: 1.11 $
+ * $Date: 1996/01/11 07:06:16 $
+ * $Locker: $
+ *
+ * This file contains references to registers in the display controller chip
+ * known as the DCC. This chip control's vram setup and works in conjunction
+ * with the ram dac which, in this case is a Brooktree Bt445.
+ *
+ */
+
+#ifndef FPDCC_H
+#define FPDCC_H
+
+//
+// Prototype declarations for routines in fpDcc.c
+
+
+// The dcc registers are not memory mapped but are indexed map through the
+// dcc Index register. To access any dcc specific register, write the register
+// value to the index register and either read or write data through the data
+// register. See fpio.h for the macros to write to these registers
+//
+// register and address offset
+//-----------------------------
+//
+#define dccIndex DCC_INDEX
+
+#define dccID 0x00 // ID register
+#define dccMonId 0x01 // Monitor and Panel ID
+#define dccGpioA 0x02 // General Purpose I/O register A
+#define dccIntReg 0x03 // Interrupt Status
+#define dccPLL 0x04 // PLL Interface Register
+#define dccTimingA 0x05 // Timing Register A
+#define dccConfigA 0x06 // Configuration Register A
+#define dccConfigB 0x07 // Configuration Register B
+#define dccHCntLow 0x08 // Hoizontal Count Low
+#define dccHCntHigh 0x09 // Hoizontal Count High
+#define dccVCntLow 0x0A // Vertical Count Low
+#define dccVCntHigh 0x0B // Vertical Count High
+#define dccHSyncStop 0x0C // Hoizontal Sync Stop
+#define dccHBlankStopLow 0x0D // Horizontal Blank Stop low
+#define dccHBlankStopHigh 0x0E // Horizontal Blank Stop High
+#define dccHDataStopLow 0x0F // Horizontal Data Stop Low
+#define dccHDataStopHigh 0x10 // Horizontal Data Stop High
+#define dccVSyncStop 0x11 // Vertical Sync Stop
+#define dccVBlankStop 0x12 // Vertical Blank Stop
+#define dccVDataStopLow 0x13 // Vertical Data Stop Low
+#define dccVDataStopHigh 0x14 // Vertical Data Stop High
+#define dccCSynicStartLow 0x15 // Composite Sync Start Low
+#define dccCSyncStartHigh 0x16 // Composite Sync Start High
+#define dccLineStart 0x17 // Line Start
+#define dccLineStop 0x18 // Line Stop
+#define dccFrameStart 0x19 // Frame Start
+#define dccFrameStop 0x1a // Frame Stop
+#define dccIntTriggerLow 0x1B // Interrupt Trigger Low
+#define dccIntTriggerHigh 0x1C // Interrupt Trigger High
+#define dccTimingB 0x1D // Timing Register B
+#define dccGpioB 0x1E // General Purpose I/O register B
+
+//
+// 0x1E - 0x3F reserved;
+//
+
+//
+// Inidividual bit mappings for register use:
+
+#define INT_BIT 0x01 // LSB of Interrupt Register: dccIntReg
+
+#define PLL_CLK 0x01 // PLL clock bit in Pll Interface: dccPLL
+#define PLL_DATA 0x02 // Data Bit for the PLL port.
+#define PLL_WnotR 0x04 // this bit activates the Pll data driver.
+
+#define HV_SYNC_DELAY 0x0f
+#define CSYNC_DELAY 0xf0
+
+//
+// Configuration Register A
+//
+#define HSYNC_ENABLE 0x01 // enable Horizontal Sync pulse
+#define VSYNC_ENABLE 0x02 // enable Vertical Sync pulse
+#define CSYNC_ENABLE 0x04 // enable Composite Sync pulse
+#define FRAME_ENABLE 0x08 // enable Frame pulse
+#define LINE_ENABLE 0x10 // enable Line pulse
+
+#define A_1to1_32BitDac 0x00 // 1:1 mux mode, frequency = DispClk
+#define AB_2to1_32BitDac 0x20 // 2:1 mux mode, frequency = 1/2DispClk
+#define A_1to1_64BitDac 0x80 // 1:1 mux, 64 bit Data width, f=DispClk
+#define A_2to1_32BitDac 0xA0 // 2:1 mux, 32 bit width, f=1/2(DispClk)
+#define A_2to1_64BitDac 0xC0 // 2:1 mux, 64 bit width, f=1/2(DispClk)
+#define A_4to1_32BitDac 0xE0 // 4:1 mux, 32 bit width, f=1/4(DispClk)
+
+//
+// Configuration Register B
+//
+#define HSYNC_ACTV_HIGH 0x01 // Active High state for Horizontal Sync
+#define VSYNC_ACTV_HIGH 0x02 // Active High state for Vertical Sync
+#define CSYNC_ACTV_HIGH 0x04 // Active High state for Composite Sync
+#define FRAME_ACTV_HIGH 0x08 // Active High state for Frame Pulse
+#define LINE_ACTV_HIGH 0x10 // Active High state for Line Pulse
+#define BLANK_ACTV_HIGH 0x20 // Active High state for Blanking Pulse
+#define DCC_HALT_CLK 0x80 // Disables and Resets all counters and state
+ // machines. Xbus interface is still active.
+
+// DCC Definitions
+#define INT_STATUS 0x03
+#define PLL_INTERFACE 0x04
+#define TIMING_A 0x05
+#define CONFIG_A 0x06
+#define CONFIG_B 0x07
+#define HZNTL_COUNT_L 0x08
+#define HZNTL_COUNT_H 0x09
+#define VERT_COUNT_L 0x0a
+#define VERT_COUNT_H 0x0b
+#define HZNTL_SYNC_STOP 0x0c
+#define HZNTL_BLK_STP_L 0x0d
+#define HZNTL_BLK_STP_H 0x0e
+#define HZNTL_DTA_STP_L 0x0f
+#define HZNTL_DTA_STP_H 0x10
+#define VERT_SYNC_STOP 0x11
+#define VERT_BLK_STOP 0x12
+#define VERT_DTA_STP_L 0x13
+#define VERT_DTA_STP_H 0x14
+#define GPIO_B 0x1e
+
+
+//
+// VRAM width list.
+//
+
+typedef enum _DCC_VRAM_WIDTH {
+ VRAM_32BIT = 0,
+ VRAM_64BIT,
+ VRAM_128BIT,
+ NUMBER_OF_VRAM_WIDTH_TYPES
+} DCC_VRAM_WIDTH;
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fpdebug.h b/private/ntos/nthals/halfire/ppc/fpdebug.h
new file mode 100644
index 000000000..b39899b86
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpdebug.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpdebug.h $
+ * $Revision: 1.30 $
+ * $Date: 1996/01/11 07:06:23 $
+ * $Locker: $
+ */
+
+#ifndef _FPDEBUG_H
+#define _FPDEBUG_H
+
+#include "fpdcc.h" // to cover the led writing macro.....
+
+//
+// This file provides an interface that allows individual debug printfs
+// to be turned on and off in the HAL based on an environment variable.
+// It also provides a means for turning on/off debug functionality
+// (like auto stopping at a break point).
+//
+
+//
+// Externs for global variables stuffed at run-time
+// Default values are provided in sources files
+//
+#if defined(HALDEBUG_ON)
+extern int HalpDebugValue;
+#endif
+
+//
+// Macros used in C code to access the debug funcationality
+//
+
+//
+// Since DBG is always defined ( at least as of 2/6/95 ), must change the test
+// to look at the value of DBG
+//
+// #if !defined(DBG)
+// #if DBG != 1
+#if !defined(HALDEBUG_ON)
+#define HDBG(_value, _str)
+#define RDBG(_value, _str)
+#else
+#define DBGSET(_value) ((_value)&(HalpDebugValue))
+
+#define HDBG(_value, _str) \
+ { \
+ if (DBGSET(_value)) { \
+ _str; \
+ } \
+ }
+
+#endif
+
+//
+// Defines used in the C code for each of the values,
+// so someone can tell what bits to turn on.
+//
+// Note: behavioral changes are at the top portion of the word and
+// simple informational ones are at the bottom portion of the word.
+//
+#define DBG_GENERAL 0x00000001
+#define DBG_EXTERNAL 0x00000002
+#define DBG_INTERNAL 0x00000004
+#define DBG_INTERRUPTS 0x00000008
+#define DBG_DUMPTREE 0x00000010
+#define DBG_IPI 0x00000020
+#define DBG_DBAT 0x00000040
+#define DBG_REGISTRY 0x00000080
+#define DBG_DMA 0x00000100
+#define DBG_ISA 0x00000200
+#define DBG_MPINTS 0x00000400
+#define DBG_PCI 0x00000800
+#define DBG_DISPLAY 0x00001000
+#define DBG_I2C 0x00002000
+#define DBG_TIME 0x00004000
+
+#define DBG_BUS 0x04000000
+#define DBG_DISPMEMCOHERE 0x08000000
+#define DBG_DISPNOCACHE 0x10000000
+#define DBG_COLORS 0x20000000
+#define DBG_BREAK 0x40000000
+#define DBG_PROC1DBG 0x80000000
+
+#define PRNTGENRL(_str) HDBG(DBG_GENERAL, _str)
+#define PRNTINTR(_str) HDBG(DBG_INTERRUPTS, _str)
+#define PRNTPCI(_str) HDBG(DBG_PCI, _str)
+#define PRNTREE(_str) HDBG(DBG_DUMPTREE, _str)
+#define PRNTDISP(_str) HDBG(DBG_DISPLAY, _str)
+#define PRNTI2C(_str) HDBG(DBG_I2C, _str)
+#define PRNTTIME(_str) HDBG(DBG_TIME, _str)
+
+
+//
+// Assert macro definitions for the HAL - Checked/Debug Builds only
+//
+#if defined(HALDEBUG_ON)
+#define _assert_begin(_exp) \
+ ULONG holdit,ee,CpuId; \
+ ee = MSR(EE); \
+ HalpDisableInterrupts(); \
+ rScratchPad2 = 0xdeadbeef; \
+ FireSyncRegister(); \
+ CpuId = GetCpuId(); \
+ holdit = RInterruptMask(CpuId); \
+ RInterruptMask(CpuId) = 0x0; \
+ WaitForRInterruptMask(CpuId); \
+ HalpDebugPrint("HAssertion Failure at line %d in file %s\n", \
+ __LINE__, __FILE__); \
+ HalpDebugPrint("HAssertion: " #_exp "\n");
+
+
+#define _assert_end \
+ HalpDebugPrint("Calling Debugger\n"); \
+ DbgBreakPoint(); \
+ RInterruptMask(CpuId) = holdit; \
+ if (ee) { \
+ HalpEnableInterrupts(); \
+ } \
+
+#define HASSERT(_exp) \
+ if (!(_exp)) { \
+ _assert_begin(_exp); \
+ _assert_end; \
+ }
+
+
+#define HASSERTMSG(_exp, _msg) \
+ if (!(_exp)) { \
+ _assert_begin(_exp); \
+ HalpDebugPrint("HAssertion Message: %s\n", _msg); \
+ _assert_end; \
+ }
+
+#define HASSERTEXEC(_exp, _exec) \
+ if (!(_exp)) { \
+ _assert_begin(_exp); \
+ { \
+ _exec; \
+ } \
+ _assert_end; \
+ }
+
+
+#define SET_LEDS(DATA) \
+ rDccIndex = dccGpioA; \
+ FireSyncRegister(); \
+ rDccData = DATA; \
+ FireSyncRegister();
+
+#define GET_LEDS(DATA) \
+ rDccIndex = dccGpioA; \
+ FireSyncRegister(); \
+ DATA = rDccData;
+
+#define TURN_ON(x,y) \
+ GET_LEDS(x); \
+ SET_LEDS((x | 0xf0 ) & ~(x));
+
+#else // Free/Non-Debug Builds
+
+#define HASSERT(_exp)
+#define HASSERTEXEC(_exp, _msg)
+#define HASSERTMSG(_exp, _exec)
+#define SET_LEDS(DATA)
+#define GET_LEDS(DATA)
+#define TURN_ON(x,y)
+#endif // HALDEBUG_ON
+
+#endif // _FPDEBUG_H
diff --git a/private/ntos/nthals/halfire/ppc/fpds1385.c b/private/ntos/nthals/halfire/ppc/fpds1385.c
new file mode 100644
index 000000000..06cac0749
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpds1385.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpds1385.c $
+ * $Revision: 1.14 $
+ * $Date: 1996/05/20 22:35:57 $
+ * $Locker: $
+ *
+ * fpds1385.c: set of routines to init, and maintain the DS1385
+ *
+ */
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "phsystem.h"
+#include "fpreg.h"
+#include "fpio.h" // pick up the io space register access macros
+#include "fpds1385.h" // defines specific to the dallas 1385
+
+#define DS1385_BAILOUT_COUNT 10
+
+UCHAR OriginalA; // storage location for rtc data in control reg a
+UCHAR OriginalB; // storage location for rtc data in control reg b
+BOOLEAN RtcBinaryMode = FALSE;
+ // Flag to indicate if RTC is programmed in BINHEX or
+ // BCD format
+
+BOOLEAN RtcFailure = FALSE;
+ // Flag to indicate if the RTC was read correctly
+BOOLEAN NvramFailure = FALSE;
+ // Flag to indicate if the NVRAM was read correctly
+ULONG TotalDs1385Failures = 0;
+ // Keep track of failures to read the DS1385
+/*
+ * HalpInitFireRTC:
+ *
+ * Make sure the dallas 1385 chip is correctly setup. This means that
+ * all the configuration bits are in place. If the chip is not correctly
+ * setup, save the time off, fix the bits, recalculate the time if needed,
+ * and restore the time. Particularly, if the "DataMode" or "24/12 hour"
+ * bits are changed the time will need to be recalculated.
+ */
+BOOLEAN
+HalpInitFirePowerRTC( VOID )
+{
+ TIME_FIELDS TimeFields;
+ UCHAR tval;
+ BOOLEAN Status = FALSE;
+ UCHAR ds1385Data;
+
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpInitFirePowerRTC: begin \n"););
+ if ( !(HalQueryRealTimeClock( &TimeFields )) ) {
+ HalDisplayString("Not sure RTC is initted \n");
+ }
+
+ //
+ // Make sure the time is valid before worrying about any of the bits.
+ //
+ ds1385Data = HalpDS1385ReadReg(RTC_CONTROL_REGISTERD);
+ if ( ds1385Data & RTC_VRT ) {
+
+ //
+ // Verify that the DataMode is BCD
+ // the time style is 24 hour,
+ // that Daylight Savings is NOT enabled,
+ // that the square wave output is enabled.
+ //
+ tval = HalpDS1385ReadReg(RTC_CONTROL_REGISTERB);
+ OriginalB = tval;
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpInitFirePowerRTC: register b is %x \n",
+ OriginalB););
+
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERB,
+ RTC_24_HR |
+ //
+ // for consistency with firmware, setup the RTC
+ // to maintain the time in BCD format rather
+ // than binary
+ //
+ // RTC_BIN_MODE |
+ RTC_SQWE|
+ RTC_UIE |
+ RTC_PIE);
+
+ RtcBinaryMode = FALSE;
+ tval = HalpDS1385ReadReg(RTC_CONTROL_REGISTERA);
+ OriginalA = tval;
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpInitFirePowerRTC: register a is %x\n",
+ OriginalA););
+
+ //
+ // Ensure the Oscillator is running and updating, not either
+ // stopped or counting but not updating.
+ //
+ if ((tval & ( RTC_DV1 | RTC_DV2 | RTC_DV0 )) != RTC_DV1 ) {
+ tval = RTC_DV1;
+ }
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERA, (UCHAR)(tval | RTC_4096_HZ));
+
+ //
+ // Clear the interrupt flag bits
+ //
+ tval = HalpDS1385ReadReg(RTC_CONTROL_REGISTERC);
+
+ //
+ // Finally, restore the time: HalSetRealTimeClock will take
+ // care of any BCD=BIN conversion necessary.
+ //
+ if ( HalSetRealTimeClock ( &TimeFields)) {
+ Status=TRUE;
+ }
+
+ } else {
+
+ HalDisplayString("RTC Time is invalid: battery is dead?\n");
+ }
+ HDBG(DBG_INTERNAL,
+ HalpDebugPrint("HalpInitFirePowerRTC: end \n"););
+ return(Status);
+}
+
+
+//
+// write a byte to the specified DS1385 register.
+// First acquire the spin lock to make sure something else is not
+// trying to access the DS1385 (RTC or NVRAM). Then do the write
+// Finally, release the spinlock.
+//
+VOID
+HalpDS1385WriteReg(UCHAR reg, UCHAR value)
+{
+ KIRQL OldIrql;
+ UCHAR data0, data1, data2;
+ ULONG failureCount = 0;
+
+ KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
+
+ // We have a problem accessing the DS1385 correctly. To get around this,
+ // we use the Dave Stewart method; after writing the DS1385 regiser, we
+ // read it back 3 times - if
+ // one of the three values compares with the value written, we are
+ // done. If we do not get a comparison, throw all three values away and
+ // try the write
+ // again. If, after 10 interations we cannot read a consistent pair,
+ // we assert a failure flag; the routine calling us must decide what
+ // to do with the flag.
+ while (failureCount < DS1385_BAILOUT_COUNT) {
+ // Write the register
+ rIndexRTC = reg;
+ FireSyncRegister();
+ rDataRTC = value;
+ // make sure access to the chip is complete before releasing
+ // the spin lock
+ FireSyncRegister();
+
+ // Read it three times
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data0 = rDataRTC;
+
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data1 = rDataRTC;
+
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data2 = rDataRTC;
+
+ if ((data0 == value) || (data1 == value) || (data2 == value)) {
+ break;
+ }
+ failureCount++;
+ }
+
+ if (failureCount == DS1385_BAILOUT_COUNT) {
+ RtcFailure = TRUE;
+ }
+
+ TotalDs1385Failures += failureCount;
+ KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
+}
+
+//
+// read a byte from the specified DS1385 register.
+// First acquire the spin lock to make sure something else is not
+// trying to access the DS1385 (RTC or NVRAM). Then do the read
+// Finally, release the spinlock.
+//
+UCHAR
+HalpDS1385ReadReg(UCHAR reg)
+{
+ KIRQL OldIrql;
+ UCHAR result = 0xff;
+ UCHAR data0, data1, data2;
+ ULONG failureCount = 0;
+
+ KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
+
+ // We have a problem accessing the DS1385 correctly. To get around this,
+ // we use the Dave Stewart method; read the DS1385 register 3 times - if
+ // one of the three values compares with either of the other two, return
+ // it. If we do not get a comparison, throw all three values away and try
+ // again. If, after 10 interations we cannot read a consistent pair,
+ // we assert a failure flag; the routine calling us must decide what
+ // to do with the flag.
+ while (failureCount < DS1385_BAILOUT_COUNT) {
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data0 = rDataRTC;
+
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data1 = rDataRTC;
+
+ rIndexRTC = reg;
+ FireSyncRegister();
+ data2 = rDataRTC;
+
+ if ((data0 == data1) || (data0 == data2)) {
+ result = data0;
+ break;
+ }
+ if (data1 == data2) {
+ result = data1;
+ break;
+ }
+ failureCount++;
+ }
+
+ if (failureCount == DS1385_BAILOUT_COUNT) {
+ RtcFailure = TRUE;
+ }
+
+ TotalDs1385Failures += failureCount;
+ KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
+ return result;
+}
+
+//
+// write a byte to the specified address in the DS1385 NVRAM.
+// First acquire the spin lock to make sure something else is not
+// trying to access the DS1385 (RTC or NVRAM). Then do the write
+// Finally, release the spinlock.
+//
+VOID
+HalpDS1385WriteNVRAM(USHORT addr, UCHAR value)
+{
+ KIRQL OldIrql;
+ UCHAR data0, data1, data2;
+ ULONG failureCount = 0;
+
+ KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
+
+ // We have a problem accessing the DS1385 correctly. To get around this,
+ // we use the Dave Stewart method; after writing the DS1385 regiser, we
+ // read it back 3 times - if
+ // one of the three values compares with the value written, we are
+ // done. If we do not get a comparison, throw all three values away and
+ // try the write
+ // again. If, after 10 interations we cannot read a consistent pair,
+ // we assert a failure flag; the routine calling us must decide what
+ // to do with the flag.
+ while (failureCount < DS1385_BAILOUT_COUNT) {
+ // Write the register
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ rNvramData = value;
+ // make sure access to the chip is complete before releasing
+ // the spin lock
+ FireSyncRegister();
+
+ // Read the register three times
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data0 = rNvramData;
+
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data1 = rNvramData;
+
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data2 = rNvramData;
+
+ if ((data0 == value) || (data1 == value) || (data2 == value)) {
+ break;
+ }
+ failureCount++;
+ }
+
+ if (failureCount == DS1385_BAILOUT_COUNT) {
+ NvramFailure = TRUE;
+ }
+
+ TotalDs1385Failures += failureCount;
+ KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
+}
+
+
+//
+// read a byte from the specified address in the DS1385 NVRAM.
+// First acquire the spin lock to make sure something else is not
+// trying to access the DS1385 (RTC or NVRAM). Then do the read
+// Finally, release the spinlock.
+//
+UCHAR
+HalpDS1385ReadNVRAM(USHORT addr)
+{
+ KIRQL OldIrql;
+ UCHAR data0, data1, data2;
+ UCHAR result = 0xff;
+ ULONG failureCount = 0;
+
+ KeAcquireSpinLock(&HalpDS1385Lock, &OldIrql);
+
+ // We have a problem accessing the DS1385 correctly. To get around this,
+ // we use the Dave Stewart method; read the DS1385 register 3 times - if
+ // one of the three values compares with either of the other two, return
+ // it. If we do not get a comparison, throw all three values away and try
+ // again. If, after 10 interations we cannot read a consistent pair,
+ // we assert a failure flag; the routine calling us must decide what
+ // to do with the flag.
+ while (failureCount < DS1385_BAILOUT_COUNT) {
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data0 = rNvramData;
+
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data1 = rNvramData;
+
+ rNvramAddr0 = addr & 0xff;
+ FireSyncRegister();
+ rNvramAddr1 = addr >> 8;
+ FireSyncRegister();
+ data2 = rNvramData;
+
+ if ((data0 == data1) || (data0 == data2)) {
+ result = data0;
+ break;
+ }
+ if (data1 == data2) {
+ result = data1;
+ break;
+ }
+ failureCount++;
+ }
+
+ if (failureCount == DS1385_BAILOUT_COUNT) {
+ NvramFailure = TRUE;
+ }
+
+ TotalDs1385Failures += failureCount;
+ KeReleaseSpinLock(&HalpDS1385Lock, OldIrql);
+ return result;
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/fpds1385.h b/private/ntos/nthals/halfire/ppc/fpds1385.h
new file mode 100644
index 000000000..6c41e0e63
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpds1385.h
@@ -0,0 +1,213 @@
+/*
+** fpds1385.h header file definitions for the dallas 1385 chip.
+** This chip is functionally equivalent to the 1387.
+**
+**
+** 1385 features:
+** counts seconds, miniutes, hours, days, day of the week, date, month
+** and year with leap year compensation
+**
+** Binary or BCD representation of time, calendar, and alarm
+**
+** 12 or 24 hour clock with AM and PM in 12 hour mode
+**
+** daylight savings time op[tino
+**
+** selectable between motorola and intel bus timing
+**
+** programmable square wave output
+**
+** bus compatible interrupt signals ( ~IRQ )
+**
+** three interrupts are separately software maskable and testable:
+** time of day alarm ( once/second to once/day )
+** periodic rates from 122 uA to 500 ms
+** end of clock update cycle
+**
+** 4k X 8 NVRAM ( nonvolatile over 10 years ).
+**
+**
+** note: this file created with tab stops of 8 spaces
+** c.f. Dallas data book for 1992-1993, pp 6-129, 6-147
+*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpds1385.h $
+ * $Revision: 1.8 $
+ * $Date: 1996/05/14 02:32:34 $
+ * $Locker: $
+ */
+
+
+#ifndef FPDS1385
+#define FPDS1385
+
+typedef struct _RTC_CONTROL {
+ UCHAR Reserved0[0x71];
+ UCHAR RtcData; // Offset 0x71
+} RTC_CONTROL, *PRTC_CONTROL;
+
+typedef struct _NVRAM_CONTROL {
+ UCHAR Reserved0[0x72];
+ UCHAR NvramIndexLo; // Offset 0x72
+ UCHAR Reserved1[2];
+ UCHAR NvramIndexHi; // Offset 0x75
+ UCHAR Reserved2[1];
+ UCHAR NvramData; // Offset 0x77
+} NVRAM_CONTROL, *PNVRAM_CONTROL;
+//
+// Define Realtime Clock register numbers.
+//
+
+#define RTC_SECOND 0 // second of minute [0..59]
+#define RTC_SECOND_ALARM 1 // seconds to alarm
+#define RTC_MINUTE 2 // minute of hour [0..59]
+#define RTC_MINUTE_ALARM 3 // minutes to alarm
+#define RTC_HOUR 4 // hour of day [0..23]
+#define RTC_HOUR_ALARM 5 // hours to alarm
+#define RTC_DAY_OF_WEEK 6 // day of week [1..7]
+#define RTC_DAY_OF_MONTH 7 // day of month [1..31]
+#define RTC_MONTH 8 // month of year [1..12]
+#define RTC_YEAR 9 // year [00..99]
+#define RTC_CONTROL_REGISTERA 10 // control register A
+#define RTC_CONTROL_REGISTERB 11 // control register B
+#define RTC_CONTROL_REGISTERC 12 // control register C
+#define RTC_CONTROL_REGISTERD 13 // control register D
+#define RTC_BATTERY_BACKED_UP_RAM 14 // battery backed up RAM [0..49]
+
+
+/*
+ ***********************************************************************
+**
+** The registers used for the indexing:
+**
+*/
+
+//
+// time....
+//
+#define SECONDS 0x00
+#define MINUTES 0x02
+#define HOURS 0x04
+
+//
+// calendar....
+//
+#define DAY_O_WEEK 0x06
+#define DAY_O_MONTH 0x07
+#define MONTH 0x08
+#define YEAR 0x09
+
+//
+// and the alarm bits
+//
+#define ALARM_secs 0x01
+#define ALARM_mins 0x03
+#define ALARM_hrs 0x05
+
+//
+// registers
+//
+#define RegA 0x0A
+#define RegB 0x0B
+#define RegC 0x0C
+#define RegD 0x0D
+
+/*
+ ***********************************************************************
+**
+** Register BIT definitions
+**
+*/
+
+//
+// Register A
+//
+#define RTC_UIP 0x80
+#define RTC_DV2 0x40
+#define RTC_DV1 0x20
+#define RTC_DV0 0x10
+
+//
+// these defines spec a set of 4 bits at a time. Each set defines an output
+// frequency
+//
+// Period in ms Frequency in hz
+#define RTC_DC__ 0x00 // no output wave
+#define A_0256_HZ 0x01 // 3.90625 256 dup
+#define A_0128_HZ 0x02 // 7.8125 128 dup
+#define RTC_8192_HZ 0x03 // .122070 8192
+#define RTC_4096_HZ 0x04 // .244141 4096
+#define RTC_2048_HZ 0x05 // .488281 2048
+#define RTC_1024_HZ 0x06 // .9765625 1024
+#define RTC_0512_HZ 0x07 // 1.953125 512
+#define RTC_0256_HZ 0x08 // 3.90625 256
+#define RTC_0128_HZ 0x09 // 7.8125 128
+#define RTC_0064_HZ 0x0A // 15.625 64
+#define RTC_0032_HZ 0x0B // 31.25 32
+#define RTC_0016_HZ 0x0C // 62.5 16
+#define RTC_0008_HZ 0x0D // 125 8
+#define RTC_0004_HZ 0x0E // 250 4
+#define RTC_0002_HZ 0x0F // 500 2
+
+
+//
+// Register B
+//
+#define RTC_SET 0x80 // set bit: 0=> allow update, 1=> block update
+#define RTC_PIE 0x40 // periodic interrupt enable
+#define RTC_AIE 0x20 // alarm interrupt enable
+#define RTC_UIE 0x10 // update ended interrupt enable
+#define RTC_SQWE 0x08 // sqaure wave enable
+#define RTC_BIN_MODE 0x04 // data mode set to Binary ( Not Coded Decimal )
+#define RTC_24_HR 0x02 // 24 or 12 hour mode
+#define RTC_DSE 0x01 // daylight savings enable
+
+//
+// Register C ( bits [3:0] are reserved by dallas, read as 0 )
+//
+
+#define RTC_IRQF 0x80 // interrupt request flag
+#define RTC_PF 0x40 // periodic interrupt flag
+#define RTC_AF 0x20 // alarm interrupt flag
+#define RTC_UF 0x10 // update endend interrupt flag
+
+
+//
+// Register D: ( only bit 7 is defined at present )
+//
+
+#define RTC_VRT 0x80 // valid ram and time
+
+
+//
+// the ds1385 chip requires multiple accesses to read or write
+// information. To make sure tose accesses are done atomically,
+// the following spinlock must be held. It is initialized in
+// pxinithl.c
+extern KSPIN_LOCK HalpDS1385Lock;
+//
+// Reading and Writing the time to the RTC takes several accesses
+// to the chip to synchronize those actions, the following spin
+// lock must be held. Using the chip's spin lock above is not
+// necessary because accesses to the chip's registers can be
+// intermixed with the chip's nvram. This lock is initialized in
+// pxinithl.c
+extern KSPIN_LOCK HalpRTCLock;
+/*
+**
+** PROTOTYPE declarations for the c-code
+**
+*/
+
+BOOLEAN HalpInitFirePowerRTC( VOID );
+
+VOID HalpDS1385WriteReg(UCHAR reg, UCHAR value);
+UCHAR HalpDS1385ReadReg(UCHAR reg);
+VOID HalpDS1385WriteNVRAM(USHORT addr, UCHAR value);
+UCHAR HalpDS1385ReadNVRAM(USHORT addr);
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fpi2c.c b/private/ntos/nthals/halfire/ppc/fpi2c.c
new file mode 100644
index 000000000..d352d93f0
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpi2c.c
@@ -0,0 +1,1016 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpi2c.c $
+ * $Revision: 1.21 $
+ * $Date: 1996/03/05 02:15:54 $
+ * $Locker: $
+ */
+/* fpi2c.c - FirePower I2C (I squared C) */
+#include "halp.h"
+#include "phsystem.h"
+#include "pxmemctl.h"
+#include "fpdebug.h"
+#include "fpio.h"
+#include "phsystem.h"
+#include "fpi2csup.h"
+#include "pxpcisup.h"
+#include "fpcpu.h"
+
+extern VOID
+HalpSetValueKeyString(HANDLE key, PCHAR nameBuffer, PCHAR dataBuffer);
+
+/* defines */
+
+#define I2CBUS_TIMEOUT 1000
+#define I2CBUS_MAXROMSIZE 0x80
+#define I2CBUS_CONTROLLER 0x8E0
+#define I2C8584S0 0x8E0
+#define I2C8584S1 0x8E1
+#define rI2C8584S0 _IOREG( I2CBUS_CONTROLLER )
+#define rI2C8584S1 _IOREG( I2CBUS_CONTROLLER + 1)
+
+#define SLAVE_ADDRESS_WRITE(address) (UCHAR)(0xa0|(address << 1))
+#define SLAVE_ADDRESS_READ(address) (UCHAR)(0xa1|(address << 1))
+
+/* control register S1 */
+#define S1_PIN 0x80
+#define S1_ES0 0x40
+#define S1_ES1 0x20
+#define S1_ES2 0x10
+#define S1_ENI 0x08
+#define S1_STA 0x04
+#define S1_STO 0x02
+#define S1_ACK 0x01
+
+/* status register S1 */
+#define S1_STS 0x20
+#define S1_BER 0x10
+#define S1_LRB 0x08
+#define S1_AAS 0x04
+#define S1_LAB 0x02
+#define S1_BB 0x01
+
+// Interrupt Info from the IIC
+struct PAIRS IntPairTable[MAXIMUM_PCI_SLOTS];
+extern UCHAR PciDevicePrimaryInts[];
+
+extern ULONG CpuClockMultiplier;
+extern ULONG ProcessorBusFrequency;
+
+/* prototypes */
+static VOID Write8584S0(UCHAR byte);
+static VOID Write8584S1(UCHAR byte);
+
+static UCHAR Read8584S0(VOID);
+static UCHAR Read8583S1(VOID);
+
+/* HAL does not initialize I2C. Firmware does it
+BOOLEAN
+HalpInitializeI2C()
+{
+}
+*/
+
+static VOID i2c_delay(VOID)
+{
+ UCHAR byte;
+// KeStallExecutionProcessor(1000); /* 1000 us */
+ // Chip Select Signal must be changed.
+ byte = 0x00;
+ WRITE_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase) + 0x80, byte);
+}
+
+static VOID Write8584S0(UCHAR byte)
+{
+ WRITE_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase) + I2C8584S0, byte);
+ i2c_delay();
+}
+
+static VOID Write8584S1(UCHAR byte)
+{
+ WRITE_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase) + I2C8584S1, byte);
+ i2c_delay();
+}
+
+static UCHAR Read8584S0(VOID)
+{
+ UCHAR byte;
+ byte = READ_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase) + I2C8584S0);
+ i2c_delay();
+ return byte;
+}
+
+static UCHAR Read8584S1(VOID)
+{
+ UCHAR byte;
+ byte = READ_REGISTER_UCHAR(((PUCHAR)HalpIoControlBase) + I2C8584S1);
+ i2c_delay();
+ return byte;
+}
+
+BOOLEAN I2CWaitForPin(VOID)
+{
+ UCHAR byte;
+ int timeout = I2CBUS_TIMEOUT;
+
+ //PRNTI2C(HalpDebugPrint("I2CWaitForPin starts...\n"));
+
+ while (timeout-- > 0) {
+ if (((byte = Read8584S1()) & S1_PIN) == 0x00) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+BOOLEAN I2CWaitForAck(VOID)
+{
+ UCHAR byte;
+ int timeout = I2CBUS_TIMEOUT;
+
+ //PRNTI2C(HalpDebugPrint("I2CWaitForAck starts...\n"));
+ while (timeout-- > 0) {
+ if (((byte = Read8584S1()) & S1_PIN) == 0x00) {
+ break;
+ }
+ }
+ if (timeout <= 0) return FALSE;
+ if (byte & S1_LRB) return FALSE;
+ else return TRUE;
+}
+
+BOOLEAN I2CWaitWhileBusBusy(VOID)
+{
+ int timeout = I2CBUS_TIMEOUT;
+ UCHAR byte;
+
+ //PRNTI2C(HalpDebugPrint("I2CWaitWhileBusBusy starts...\n"));
+ while (timeout-- > 0) {
+ if (((byte = Read8584S1()) & S1_BB) != 0x00)
+ break;
+ }
+ if (timeout <= 0) return FALSE;
+ return TRUE;
+}
+
+VOID I2CStart(VOID)
+{
+ Write8584S1(0xc5);
+}
+
+VOID I2CRestart(VOID)
+{
+ Write8584S1(0x45);
+}
+
+VOID I2CPutByte(UCHAR byte)
+{
+ Write8584S0(byte);
+}
+
+VOID I2CDummyRead(VOID)
+{
+ UCHAR dummy;
+ dummy = Read8584S0();
+}
+
+UCHAR I2CGetByte(VOID)
+{
+ return Read8584S0();
+}
+
+VOID I2CStop(VOID)
+{
+ Write8584S1(0xc3);
+}
+
+VOID I2CNotAck(VOID)
+{
+ Write8584S1(0x40);
+}
+
+BOOLEAN HalpI2CPutByte(UCHAR address, UCHAR index, UCHAR byte)
+{
+ BOOLEAN bResult;
+
+ bResult = I2CWaitWhileBusBusy();
+ if (bResult == FALSE) return FALSE;
+
+ I2CPutByte(SLAVE_ADDRESS_WRITE(address)); // to write slave address and index
+ I2CStart();
+ if (I2CWaitForAck() == FALSE) {
+ I2CStop();
+ //KeStallExecutionProcessor(10000); /* 10 ms */
+ return FALSE;
+ }
+
+ I2CPutByte(index);
+ if (I2CWaitForAck() == FALSE) {
+ I2CStop();
+ //KeStallExecutionProcessor(10000); /* 10 ms */
+ return FALSE;
+ }
+ I2CPutByte(byte);
+ I2CWaitForPin();
+ I2CStop();
+ KeStallExecutionProcessor(10000); /* 10 ms */
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetByte(UCHAR address, UCHAR index, PUCHAR buf)
+{
+ BOOLEAN bResult;
+
+ bResult = I2CWaitWhileBusBusy();
+ if (bResult == FALSE) return FALSE;
+
+ I2CPutByte(SLAVE_ADDRESS_WRITE(address)); // to write slave address and index
+ I2CStart();
+ if (I2CWaitForAck() == FALSE) {
+ I2CStop();
+ I2CDummyRead();
+ return FALSE;
+ }
+
+ I2CPutByte(index);
+ if (I2CWaitForAck() == FALSE) {
+ I2CStop();
+ I2CDummyRead();
+ return FALSE;
+ }
+
+ I2CRestart();
+ I2CPutByte(SLAVE_ADDRESS_READ(address)); // to read
+ if (I2CWaitForAck() == FALSE) {
+ I2CStop();
+ I2CDummyRead();
+ return FALSE;
+ }
+
+ I2CDummyRead();
+ I2CWaitForPin();
+ I2CNotAck();
+ *buf = I2CGetByte();
+ I2CWaitForPin();
+ I2CStop();
+ I2CDummyRead();
+ return TRUE;
+}
+
+VOID
+HalpDumpI2CEEPROM(VOID)
+{
+ UCHAR address = 0;
+ UCHAR i;
+ static UCHAR uc;
+ BOOLEAN bResult;
+
+ PRNTI2C(DbgPrint("HalpDumpI2CEEPROM starts...&I2C8584S0=0x%x &I2C8584S1=0x%x\n",
+ ((PUCHAR)HalpIoControlBase) + I2C8584S0,
+ ((PUCHAR)HalpIoControlBase) + I2C8584S1));
+ PRNTI2C(DbgPrint("--- I2C address 0 -----------------------------\n"));
+ PRNTI2C(DbgPrint("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"));
+ PRNTI2C(DbgPrint("-----------------------------------------------\n"));
+
+ for (i = 0; i < 128; i++) {
+ bResult = HalpI2CGetByte(address, i, &uc);
+ if (bResult == FALSE) {
+ PRNTI2C(DbgPrint("HalpI2CGetByte(%d) failed.\n", i));
+ } else {
+ PRNTI2C(DbgPrint("%02x", uc));
+ }
+ if ((i%16) == 15) {
+ PRNTI2C(DbgPrint("\n"));
+ } else {
+ PRNTI2C(DbgPrint(" "));
+ }
+ }
+
+ PRNTI2C(DbgPrint("--- I2C address 1 -----------------------------\n"));
+ PRNTI2C(DbgPrint("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n"));
+ PRNTI2C(DbgPrint("-----------------------------------------------\n"));
+
+ address = 1;
+ for (i = 0; i < 128; i++) {
+ bResult = HalpI2CGetByte(address, i, &uc);
+ if (bResult == FALSE) {
+ PRNTI2C(DbgPrint("HalpI2CGetByte(%d) failed.\n", i));
+ } else {
+ PRNTI2C(DbgPrint("%02x", uc));
+ }
+ if ((i%16) == 15) {
+ PRNTI2C(DbgPrint("\n"));
+ } else {
+ PRNTI2C(DbgPrint(" "));
+ }
+ }
+}
+
+BOOLEAN HalpGetI2CSignature(PULONG pSignature)
+{
+ ULONG ul;
+ PUCHAR p = (PUCHAR)&ul;
+ UCHAR address = 0;
+ UCHAR index = 0;
+
+ HalpI2CGetByte(address, index++, p++);
+ HalpI2CGetByte(address, index++, p++);
+ HalpI2CGetByte(address, index++, p++);
+ HalpI2CGetByte(address, index, p);
+
+ *pSignature = ul;
+ return TRUE;
+}
+
+BOOLEAN HalpGetI2CItemDescriptor(PUCHAR p)
+{
+ UCHAR address = 0;
+ UCHAR index = sizeof(META);
+
+ PRNTI2C(HalpDebugPrint("index=%d 0x%x ", index, index));
+
+ HalpI2CGetByte(address, index++, p++);
+ HalpI2CGetByte(address, index++, p++);
+ *p = 0x00;
+
+ return TRUE;
+}
+
+BOOLEAN HalpGetI2CBoardRev(PUCHAR p)
+{
+ UCHAR address = 0;
+ UCHAR index = sizeof(META) + 2*sizeof(UCHAR);
+
+
+ PRNTI2C(HalpDebugPrint("index=%d 0x%x ", index, index));
+
+ HalpI2CGetByte(address, index++, p++);
+ HalpI2CGetByte(address, index++, p++);
+ *p = 0x00;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetUshort(UCHAR address, UCHAR index, PUSHORT pus)
+{
+ BOOLEAN bResult = FALSE;
+ PUCHAR p = (PUCHAR)pus;
+
+ bResult = HalpI2CGetByte(address, index++, p++);
+ if (bResult == FALSE) return FALSE;
+ bResult = HalpI2CGetByte(address, index++, p++);
+ if (bResult == FALSE) return FALSE;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetUlong(UCHAR address, UCHAR index, PULONG pul)
+{
+ BOOLEAN bResult = FALSE;
+ PUCHAR p = (PUCHAR)pul;
+
+ bResult = HalpI2CGetByte(address, index++, p++);
+ if (bResult == FALSE) return FALSE;
+ bResult = HalpI2CGetByte(address, index++, p++);
+ if (bResult == FALSE) return FALSE;
+ bResult = HalpI2CGetByte(address, index++, p++);
+ if (bResult == FALSE) return FALSE;
+ bResult = HalpI2CGetByte(address, index, p);
+ if (bResult == FALSE) return FALSE;
+ return TRUE;
+}
+
+// OR together the sturcture types for this IIC address and return it as a
+// flag. NOTA BENA: we intercept known non-IIC platforms and return a special
+// cased result.
+ULONG FindDataTypes(UCHAR address, SYSTEM_TYPE System)
+{
+ int index = 0;
+ ULONG datatype;
+ ULONG FoundTypes = 0;
+ UCHAR offset;
+ BOOLEAN bResult = FALSE;
+
+ // The ES and MX (non-IIC) platforms are special cased
+ if ((System == SYS_POWERTOP) || (System == SYS_POWERPRO)) {
+ if (address == 0) {
+ FoundTypes = SYS_DATA;
+ }
+ return FoundTypes;
+ }
+
+ while (index < I2CBUS_MAXROMSIZE) {
+ bResult = HalpI2CGetUlong(address, (UCHAR)index, &datatype);
+ if ((bResult == FALSE) || (datatype == EMPTY_DATA)) {
+ break;
+ }
+ FoundTypes |= datatype;
+ HalpI2CGetByte(address, (UCHAR)(index+sizeof(ULONG)), &offset);
+ if (offset == 0) {
+ break;
+ }
+ index += offset;
+ }
+
+ return FoundTypes;
+}
+
+UCHAR I2CFindIndexOf(UCHAR address, ULONG datatype_wanted)
+{
+ int index = 0;
+ ULONG datatype;
+ UCHAR offset;
+ BOOLEAN bResult = FALSE;
+
+ while (index < I2CBUS_MAXROMSIZE) {
+ bResult = HalpI2CGetUlong(address, (UCHAR)index, &datatype);
+ if (bResult == FALSE) {
+ //DbgPrint("FindIndexOf failed\n");
+ return 0;
+ }
+ //DbgPrint("I2CFindIndexOf: address=%d datatype_wanted=0x%08x index=0x%02x datatype=0x%08x\n", address, datatype_wanted, index, datatype);
+ if (datatype == datatype_wanted) return index;
+ if (datatype == EMPTY_DATA) return 0;
+
+ HalpI2CGetByte(address, (UCHAR)(index+sizeof(ULONG)), &offset);
+ if (offset == 0) return 0;
+ index += offset;
+ }
+ //DbgPrint("FindIndexOf could not find key (0x%08x).\n", datatype_wanted);
+ return 0;
+}
+
+BOOLEAN HalpDoesI2CExist(UCHAR address)
+{
+ ULONG ul;
+ UCHAR index = 5;
+ BOOLEAN bResult = FALSE;
+
+#if DBG
+{
+ static BOOLEAN firsttime = TRUE;
+ if (firsttime) {
+ HalpDumpI2CEEPROM();
+ firsttime = FALSE;
+ }
+}
+#endif
+ bResult = HalpI2CGetUlong(address, index, &ul);
+ if (bResult == FALSE) return FALSE;
+
+ if (ul == CURRENT_SIGNATURE) return TRUE;
+ return FALSE;
+}
+
+BOOLEAN HalpI2CGetSystem(SYSTEM_TYPE *psystemtype)
+{
+ UCHAR address = 0;
+ UCHAR index;
+ UCHAR system;
+
+ PRNTI2C(DbgPrint("HalpI2CGetSystem starts...\n"));
+ if (HalpDoesI2CExist(address) == FALSE) {
+ PRNTI2C(DbgPrint("HalpDoesI2CExist returned FALSE.\n"));
+ *psystemtype = SYS_UNKNOWN;
+ return FALSE;
+ }
+ if ((index = I2CFindIndexOf(address, SYS_DATA)) == 0) {
+ *psystemtype = SYS_UNKNOWN;
+ return FALSE;
+ }
+ index += sizeof(ULONG) + sizeof(UCHAR);
+ HalpI2CGetByte(address, index, &system);
+ if (system == LX_SYSTEM) {
+ *psystemtype = SYS_POWERSLICE;
+ return TRUE;
+ }
+ if (system == MX_SYSTEM) {
+ *psystemtype = SYS_POWERTOP;
+ return TRUE;
+ }
+ if (system == TX_SYSTEM) {
+ *psystemtype = SYS_POWERSERVE;
+ return TRUE;
+ }
+ if (system == TX_PROTO) {
+ *psystemtype = SYS_POWERSERVE;
+ return TRUE;
+ }
+
+ // We found a system type so we need to return TRUE; since we do not
+ // recognize it, make it unknown.
+ *psystemtype = SYS_UNKNOWN;
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetBoard(UCHAR address, BOARD *pb)
+{
+ UCHAR index;
+ UCHAR uc;
+ USHORT us;
+ ULONG ul;
+
+ if ((index = I2CFindIndexOf(address, BOARD_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ HalpI2CGetByte(address, index, &uc);
+ pb->PartType[0] = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ pb->PartType[1] = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ pb->PartRev[0] = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ pb->PartRev[1] = uc;
+ index++;
+
+ HalpI2CGetUlong(address, index, &ul);
+ pb->BoardNumber = ul;
+ index += 4;
+
+ HalpI2CGetUshort(address, index, &us);
+ pb->Version = us;
+ index += 2;
+
+ {
+ int i;
+ for (i = 0; i < 8; i++) {
+ HalpI2CGetByte(address, index, &uc);
+ pb->SerialNumber[i] = uc;
+ index++;
+ }
+ }
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetProcessor(UCHAR address, PROCESSOR *p)
+{
+ UCHAR index;
+ UCHAR uc;
+
+ if ((index = I2CFindIndexOf(address, CPU_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->Total = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->BusFrequency = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->TenXFactor = uc;
+ index++;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetCache(UCHAR address, CACHE *p)
+{
+ UCHAR index;
+ UCHAR uc;
+ USHORT us;
+ ULONG ul;
+
+ if ((index = I2CFindIndexOf(address, CACHE_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->MaxSets = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->Bytes2Line = uc;
+ index++;
+
+ HalpI2CGetUshort(address, index, &us);
+ p->Lines2Set = us;
+ index += 2;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->SramBanks = uc;
+ index++;
+
+ HalpI2CGetUlong(address, index, &ul);
+ p->Performance = ul;
+ index += 4;
+
+ HalpI2CGetUlong(address, index, &ul);
+ p->MaxSize = ul;
+ index += 4;
+
+ HalpI2CGetUlong(address, index, &ul);
+ p->Properties = ul;
+ index += 4;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetDRAM(UCHAR address, MEMORY *p)
+{
+ UCHAR index;
+ UCHAR uc;
+ USHORT us;
+ ULONG ul;
+
+ if ((index = I2CFindIndexOf(address, DRAM_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ HalpI2CGetUlong(address, index, &ul);
+ p->BaseAddress = ul;
+ index += 4;
+
+ HalpI2CGetUshort(address, index, &us);
+ p->MaxBankSize = us;
+ index += 2;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->MaxNumBanks = uc;
+ index ++;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetBus(UCHAR address, BUS *p)
+{
+ UCHAR index;
+ UCHAR uc;
+ ULONG ul;
+
+ if ((index = I2CFindIndexOf(address, BUS_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->NumIoBus = uc;
+ index++;
+
+ HalpI2CGetUlong(address, index, &ul);
+ p->ConfigAddr = ul;
+ index += 4;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetIntsTotal(UCHAR address, UCHAR *p)
+{
+ UCHAR index;
+ UCHAR uc;
+
+ if ((index = I2CFindIndexOf(address, INT_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ HalpI2CGetByte(address, index, &uc);
+ *p = uc;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetIntsAPair(UCHAR address, UCHAR i, struct PAIRS *p)
+{
+ UCHAR index;
+ UCHAR uc;
+
+ if ((index = I2CFindIndexOf(address, INT_DATA)) == 0) {
+ return FALSE;
+ }
+ index += 5;
+
+ index += sizeof(UCHAR) + i * (sizeof(UCHAR)*2);
+
+ HalpI2CGetByte(address, index, &uc);
+ p->Int = uc;
+ index++;
+
+ HalpI2CGetByte(address, index, &uc);
+ p->SlotNumber = uc;
+ index++;
+
+ return TRUE;
+}
+
+BOOLEAN HalpI2CGetInterrupt()
+{
+ UCHAR address = 0; // Id of the MLB I2c
+ UCHAR size;
+ UCHAR entry;
+ struct PAIRS *IntPairs = &IntPairTable[0];
+ UCHAR slot;
+
+ // Does the MLB I2C exist?
+ if (HalpDoesI2CExist(address) == FALSE) {
+ return FALSE;
+ }
+
+ // Is there an interrupt structure on the MLB?
+ if (HalpI2CGetIntsTotal(address, &size) == FALSE) {
+ return FALSE;
+ }
+
+ // Initialize the interrupt pairs table
+ for (entry = 0; entry < MAXIMUM_PCI_SLOTS; entry++) {
+ IntPairTable[entry].Int = INVALID_INT;
+ IntPairTable[entry].SlotNumber = INVALID_SLOTNUMBER;
+ }
+
+ // Now fill up the IntPair table from the IIC upto MaxSize entries;
+ // should size > MaxSize be an error?
+ if (size > MAXIMUM_PCI_SLOTS) size = MAXIMUM_PCI_SLOTS;
+ if (size == 0) return FALSE;
+
+ for (entry = 0; entry < size; entry++) {
+ if (HalpI2CGetIntsAPair(address, entry, IntPairs) == FALSE) {
+ return FALSE;
+ }
+ IntPairs++;
+ }
+
+ for (entry = 0; entry < size; entry++) {
+ slot = IntPairTable[entry].SlotNumber;
+ if (slot < MAXIMUM_PCI_SLOTS) {
+ PciDevicePrimaryInts[slot] = IntPairTable[entry].Int;
+ }
+ }
+
+ return TRUE;
+}
+
+// Fill in the registry info for the IIC at the passed in address.
+// NOTE BENA: we intercept non-IIC platforms and special case the data.
+BOOLEAN HalpFillUpRegistryForIIC(HANDLE key, UCHAR address, SYSTEM_TYPE System)
+{
+ BOOLEAN bStatus;
+ BOARD board;
+ PROCESSOR cpu;
+ MEMORY memory;
+ BUS bus;
+ UCHAR numInts;
+ struct PAIRS DefaultPair[4];
+ BOOLEAN NonIIC = FALSE;
+ CCHAR buffer[64];
+
+ // Set up default values for all of the structures to assist in filling
+ // out the registry for non-IIC platforms
+ board.PartType[0] = 'N';
+ board.PartType[1] = 'A';
+ board.PartRev[0] = 'N';
+ board.PartRev[1] = 'A';
+ board.BoardNumber = 0;
+ board.Version = 0;
+ board.SerialNumber[0] = '-';
+ board.SerialNumber[1] = '-';
+ board.SerialNumber[2] = ' ';
+ board.SerialNumber[3] = 'N';
+ board.SerialNumber[4] = 'A';
+ board.SerialNumber[5] = ' ';
+ board.SerialNumber[6] = '-';
+ board.SerialNumber[7] = '-';
+
+ cpu.Total = (UCHAR)HalpProcessorCount();
+ cpu.TenXFactor = (UCHAR)CpuClockMultiplier;
+ cpu.BusFrequency = (UCHAR)(ProcessorBusFrequency/1000000);
+
+ memory.BaseAddress = 0x0;
+ memory.MaxBankSize = 0x40;
+ memory.MaxNumBanks = (System == SYS_POWERPRO)?2:4;
+
+ bus.NumIoBus = 1;
+ bus.ConfigAddr = 0x80800800;
+
+ numInts = 4;
+
+ DefaultPair[0].Int = 25;
+ DefaultPair[0].SlotNumber = 1;
+ DefaultPair[1].Int = 22;
+ DefaultPair[1].SlotNumber = 2;
+ DefaultPair[2].Int = 23;
+ DefaultPair[2].SlotNumber = 3;
+ DefaultPair[3].Int = 26;
+ DefaultPair[3].SlotNumber = 4;
+
+ // The ES and MX (non-IIC) platforms are special cased
+ if ((System == SYS_POWERTOP) || (System == SYS_POWERPRO)) {
+ NonIIC = TRUE;
+ }
+
+ if ((NonIIC == TRUE) || (HalpI2CGetBoard(address, &board) == TRUE)) {
+ sprintf(buffer, "%c%c", board.PartType[0], board.PartType[1]);
+ HalpSetValueKeyString(key, "Board - Part Type", buffer);
+ sprintf(buffer, "%c%c", board.PartRev[0], board.PartRev[1]);
+ HalpSetValueKeyString(key, "Board - Part Rev", buffer);
+ sprintf(buffer, "%x", board.BoardNumber);
+ HalpSetValueKeyString(key, "Board - Number", buffer);
+ sprintf(buffer, "%x", board.Version);
+ HalpSetValueKeyString(key, "Board - Version", buffer);
+ sprintf(buffer, "%c%c%c%c%c%c%c%c",
+ board.SerialNumber[0], board.SerialNumber[1],
+ board.SerialNumber[2], board.SerialNumber[3],
+ board.SerialNumber[4], board.SerialNumber[5],
+ board.SerialNumber[6], board.SerialNumber[7]);
+ HalpSetValueKeyString(key, "Board - Serial Number", buffer);
+ }
+
+ if ((NonIIC == TRUE) || (HalpI2CGetProcessor(address, &cpu) == TRUE)) {
+ sprintf(buffer, "%d", cpu.Total);
+ HalpSetValueKeyString(key, "CPU - Total Number of CPUs", buffer);
+ sprintf(buffer, "%d", cpu.BusFrequency);
+ if ((cpu.BusFrequency == 66) || (cpu.BusFrequency == 33)) {
+ sprintf(buffer, "%d.%d", cpu.BusFrequency, cpu.BusFrequency);
+ }
+ else {
+ sprintf(buffer, "%d", cpu.BusFrequency);
+ }
+ HalpSetValueKeyString(key, "CPU - Bus Frequency", buffer);
+ sprintf(buffer, "%d", cpu.TenXFactor);
+ HalpSetValueKeyString(key, "CPU - 10 Times Factor", buffer);
+ }
+
+ if ((NonIIC == TRUE) || (HalpI2CGetDRAM(address, &memory) == TRUE)) {
+ sprintf(buffer, "0x%08x", memory.BaseAddress);
+ HalpSetValueKeyString(key, "Memory - Base Address", buffer);
+ sprintf(buffer, "0x%08x", memory.MaxBankSize);
+ HalpSetValueKeyString(key, "Memory - Max Bank Size", buffer);
+ sprintf(buffer, "%d", memory.MaxNumBanks);
+ HalpSetValueKeyString(key, "Memory - Max # of Banks", buffer);
+ }
+
+ if ((NonIIC == TRUE) || (HalpI2CGetBus(address, &bus) == TRUE)) {
+ sprintf(buffer, "%d", bus.NumIoBus);
+ HalpSetValueKeyString(key, "Bus - Number of Buses", buffer);
+ sprintf(buffer, "0x%08x", bus.ConfigAddr);
+ HalpSetValueKeyString(key, "Bus - Configration Address", buffer);
+ }
+
+ if ((NonIIC == TRUE) || (HalpI2CGetIntsTotal(address, &numInts) == TRUE)) {
+ char keyName[32];
+ UCHAR i = 0;
+ struct PAIRS *pair;
+
+ sprintf(buffer, "%d", numInts);
+ HalpSetValueKeyString(key,
+ "Ints - Number of Primary PCI Interrupts", buffer);
+
+ while (numInts-- > 0) {
+ sprintf(keyName, "Ints - Primary PCI Entry %d", i);
+ if (NonIIC == TRUE) {
+ pair = &DefaultPair[i];
+ }
+ else {
+ pair = &DefaultPair[0];
+ }
+ bStatus = HalpI2CGetIntsAPair(address, i++, pair);
+ if ((NonIIC == FALSE) && (bStatus == FALSE)) break;
+ sprintf(buffer, "Vector#%d Slot#%d", pair->Int, pair->SlotNumber);
+ HalpSetValueKeyString(key, keyName, buffer);
+ }
+ }
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpCreateNode(CCHAR * pszNodeName, UCHAR address, HANDLE * phNode)
+{
+ OBJECT_ATTRIBUTES objectAttributes;
+ NTSTATUS status;
+ HANDLE hNode;
+ ULONG disposition;
+ STRING strNodeName;
+ UNICODE_STRING ucNodeName;
+
+ *phNode = NULL;
+
+ RtlInitString (&strNodeName, pszNodeName);
+ status = RtlAnsiStringToUnicodeString(
+ &ucNodeName,
+ &strNodeName,
+ TRUE);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY, HalpDebugPrint("Could not create unicode strings: (0x%x) \n",
+ status));
+ return FALSE;
+ }
+
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &ucNodeName,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL
+ );
+
+ status = ZwCreateKey(&hNode,
+ KEY_READ,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_VOLATILE,
+ &disposition );
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY, HalpDebugPrint("Did not create key: (0x%x) \n", status););
+ RtlFreeUnicodeString(&ucNodeName);
+ return FALSE;
+ }
+
+ *phNode = hNode;
+ RtlFreeUnicodeString(&ucNodeName);
+ return TRUE;
+}
+
+BOOLEAN
+HalpSetUpRegistryForI2C(SYSTEM_TYPE System)
+{
+ HANDLE hNode;
+ BOOLEAN bStatus = FALSE;
+#if defined(HALDEBUG_ON)
+ BOOLEAN SystemTypeFound = FALSE;
+#endif
+ UCHAR address;
+ ULONG StructureTypes;
+
+ CCHAR szCPU[256];
+ CCHAR szMEM[256];
+ CCHAR szSystem[] = "\\Registry\\Machine\\Hardware\\Powerized\\System";
+ CHAR CpuCardLabel[] =
+ "\\Registry\\Machine\\Hardware\\Powerized\\Cpu Card";
+ SHORT CpuCardNo = 0;
+ CHAR MemCardLabel[] =
+ "\\Registry\\Machine\\Hardware\\Powerized\\Memory Card";
+ SHORT MemCardNo = 0;
+
+ address = 0;
+ // Loop through all possible IIC addresses
+ while (address < 16) {
+ // Since all of the structure type flags are mutually exclusive
+ // bits, we can lump together into one mask.
+ StructureTypes = FindDataTypes(address, System);
+
+ // Determine what identifying structures are present and create
+ // nodes corresponding to them.
+ // - an IIC with a SYS_DATA structure is a System board; there must
+ // be ONE and only ONE system board on a system
+ // - an IIC with a CPU_DATA structure and no SYS_DATA structure is
+ // a Cpu Card; there may be multiple Cpu Cards in a system.
+ // - an IIC with a MEM_DATA structure and no CPU or SYS_DATA structure
+ // is a Memory Card; there may be multiple Memory Cards in a system
+ if ((StructureTypes & SYS_DATA) != 0) {
+ bStatus = HalpCreateNode(szSystem, address, &hNode);
+ if (hNode != NULL) {
+ HalpFillUpRegistryForIIC(hNode, address, System);
+ ZwClose(hNode);
+ }
+#if defined(HALDEBUG_ON)
+ SystemTypeFound = TRUE;
+#endif
+ }
+ else if ((StructureTypes & CPU_DATA) != 0) {
+ sprintf(szCPU, "%s %d", CpuCardLabel, CpuCardNo);
+ bStatus = HalpCreateNode(szCPU, address, &hNode);
+ if (hNode != NULL) {
+ HalpFillUpRegistryForIIC(hNode, address, System);
+ ZwClose(hNode);
+ CpuCardNo++;
+ }
+ }
+ else if ((StructureTypes &
+ (DRAM_DATA|SRAM_DATA|VRAM_DATA|EDORAM_DATA) ) != 0) {
+ sprintf(szMEM, "%s %d", MemCardLabel, MemCardNo);
+ bStatus = HalpCreateNode(szMEM, address, &hNode);
+ if (hNode != NULL) {
+ HalpFillUpRegistryForIIC(hNode, address, System);
+ ZwClose(hNode);
+ MemCardNo++;
+ }
+ }
+ address++;
+ }
+#if defined(HALDEBUG_ON)
+ if (SystemTypeFound == FALSE) {
+ HalpDebugPrint ("HalpSetUpRegistryForI2C: no MLB IIC found.\n");
+ }
+#endif
+
+ return bStatus;
+}
+
+/* end of fpi2c.c */
diff --git a/private/ntos/nthals/halfire/ppc/fpi2c.h b/private/ntos/nthals/halfire/ppc/fpi2c.h
new file mode 100644
index 000000000..e3c5e1a18
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpi2c.h
@@ -0,0 +1,39 @@
+/* fpi2c.h */
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpi2c.h $
+ * $Revision: 1.5 $
+ * $Date: 1996/02/06 02:20:28 $
+ * $Locker: $
+ *
+/*
+ system board ROM data (I2C address 0x00)
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 0x00: 26 59 41 31 10 26 59 41 31 ?? ?? 02 01 80 00 00 Meta
+ 0x10: 00 04 00 00 20 42 41 41 44 00 93 73 00 03 01 00 Board
+ 0x20: 04 01 00
+ 0x30: 01 00 00 00 10 01 00 System
+ 0x40: 08 00 00 00 10 00 00 00 00 08 00 04 Memory
+ 0x50: 40 00 00 00 10 01 08 80 80 Bus
+ 0x60: 80 00 00 00 00 05 26 04 25 01 23 03 22 02 21 05 Ints
+
+ * typical CPU card ROM data for LX (I2C address 0x01)
+ 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+ 0x00: 26 59 41 31 10 26 59 41 31 ?? ?? 02 01 80 00 00 Meta
+ 0x10: 00 04 00 00 20 42 41 41 44 00 03 75 00 03 01 09 Board
+ 0x20: 00 01 00
+ 0x30: 02 00 00 00 10 02 42 14 Processor
+ 0x40: 04 00 00 00 00 02 20 00 20 02 11 31 00 00 00 00 Cache
+ 0x50: 08 00 00 00 00 00
+
+ */
+
+extern BOOLEAN HalpI2CGetSystem(SYSTEM_TYPE *psystemtype);
+extern BOOLEAN HalpSetUpRegistryForI2C(SYSTEM_TYPE System);
+extern BOOLEAN HalpDoesI2CExist(UCHAR address);
+extern BOOLEAN HalpI2CGetInterrupt();
+
+/* end of fpi2c.h */
+
diff --git a/private/ntos/nthals/halfire/ppc/fpi2csup.h b/private/ntos/nthals/halfire/ppc/fpi2csup.h
new file mode 100644
index 000000000..861821621
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpi2csup.h
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpi2csup.h $
+ * $Revision: 1.6 $
+ * $Date: 1996/02/19 23:54:29 $
+ * $Locker: $
+ */
+#ifndef FPI2CSUP_H
+#define FPI2CSUP_H
+// C4103 : "used #pragma pack to change alignment"
+//#pragma warning(disable:4103) // disable C4103 warning
+//#pragma pack(1)
+
+/* This is an implementation according to 1.5 specification */
+/*
+ *
+ * Each data structure has in common a STRUCT_HEADER which holds clues
+ * about the 'DataType' of the structure and it's 'OffSet'. The data
+ * type tells software what data is in the structure hence how to
+ * interpret the data. The OffSet indicates how far to the next
+ * data structure, or, if the value is 0, whether there is another data
+ * structure. return to index
+ *
+ */
+
+#define EMPTY_DATA 0x00000000 // indicates there is no data.
+#define SYS_DATA 0x00000001 // general system registers
+#define CPU_DATA 0x00000002 // processor
+#define CACHE_DATA 0x00000004 // cache control
+#define DRAM_DATA 0x00000008 // memory control
+#define SRAM_DATA 0x00000010 // memory control
+#define VRAM_DATA 0x00000020 // memory control
+#define EDORAM_DATA 0x00000040 // memory control
+#define INT_DATA 0x00000080 // int control, not initialization.
+#define BUS_DATA 0x00000400 // I O control, mainly configuration and
+// initialization.
+#define DMA_DATA 0x00000100
+#define DISPLAY_DATA 0x00000200
+// mogawa
+#define BOARD_DATA 0x40000000
+#define META_DATA 0x80000000
+
+#define STRUCT_HEADER \
+ULONG DataType; UCHAR OffSet
+ // The type of data contained in the structure
+ // The Offset to the next data structure, relative
+ // the beginning of this structure. Typically, it's
+ // value is set as the length of the structure, but
+ // is set to zero if no more structures exist.
+
+/*
+ *
+ *
+ * Meta data effectively describes the structure of the IIC rom data.
+ * The size of the total rom is given, along with pointers to the beginning of
+ * the other data areas. Finally, there is a major/minor version numbering
+ * system to provide some means of evaluating what data the rom contains.
+ * return to index
+ *
+ */
+#define CURRENT_META_REV 0x0103 // this is in the form of: USHORT 0x0101
+#define CURRENT_SIGNATURE 0x31415926 // numbers of PI: e is (27182818) next
+
+
+typedef struct _Meta_ {
+ STRUCT_HEADER;
+ ULONG Signature;
+ USHORT ChkSum; // a sum of byte pairs (USHORT) in little endian
+ // order.
+ USHORT Revision;
+ UCHAR Size; // in bytes, the size of the entire rom.
+} META;
+
+
+/*
+ *
+ * Manufacturing's part number is built out of four pieces: a two letter
+ * description of the item ( BA for board assembly ), a five digit part
+ * designator, a two digit board version, and a two letter board turn
+ * identifier ( as in AA, AB, AC, AD ... ).
+ *
+ * E.G. BA-007393-01-AD is an LX series Board Assembly (BA) whose board
+ * variation is 01, and board revision is "AD."
+ *
+ */
+
+#define BOARD_REV_MASK 0x000000ff // the manufacturing number's rev bits
+#define BOARD_PART_MSK 0xffffff00 // the 6 digits used as the part number
+ // ( 4 digits actually )
+/*
+ *
+ *
+ * The general board data contains data fields common to all boards. A version
+ * to correlate this structure with the meta data structure, along with
+ * the type of board, cpu or mlu, the board system, lx or tx, the board family
+ * as in PREP, CHRP or something else, return to index
+ *
+ */
+
+typedef struct _Board_ {
+ STRUCT_HEADER;
+ UCHAR PartType[2]; // Currently a two ascii value 'B''A' that stands
+ // for Board Assembly.
+ UCHAR PartRev[2]; // Colloquially the Board Rev. E.G. Mx has this as
+ // 'A''D' for the Rev AD board.
+ ULONG BoardNumber; // Board ID consists of two parts: Rev fields
+ // which are the least two significant nibbles,
+ // and Part Number field which is the 6 most
+ // nificant nibbles. The digits are stored
+ // in "BCD" format as in one decimal digit per
+ // nibble, in little endian order.
+
+ USHORT Version; // major/minor versioning value of this board.
+ UCHAR SerialNumber[8]; // board serial number. Format TBD....
+} BOARD;
+
+
+
+/*
+ * :
+ * System data structure: Mainly a catch all for data needed but not readily
+ * associated with any one hardware function. for instance, we use it here to
+ * say whether the system is TX, LX, MX or whatever. return * to index
+ *
+ */
+
+#define DEV_SYS 0x0000
+#define LX_SYSTEM 0x0001
+#define MX_SYSTEM 0x0002
+#define TX_SYSTEM 0x0003
+#define TX_PROTO 0x0004
+
+typedef struct _SYSTEM_ {
+ STRUCT_HEADER;
+ USHORT type; // what kind of system is this: This is a value field
+ // rather than a bit map....
+} SYSTEM;
+
+/*
+ * For the board specific information, there is a specific structure. This
+ * allows for varying data requirements of different boards such as a changing
+ * sense of where some registers may sit.
+ *
+ */
+
+typedef struct _Processor_ {
+ STRUCT_HEADER;
+ UCHAR Total; // total number of cpus on this board.
+ UCHAR BusFrequency; // frequency of the bus serving the cpu(s)
+ UCHAR TenXFactor; // 10 times the bus frequency multiplier for the cpu.
+ // This allows fractional multipliers as in 3/2
+ // (becomes 15) or 5/2 ( becomes 25 ).
+} PROCESSOR;
+
+
+#define LOOKASIDE_L2 0x00000001 // this cache is a look aside cache
+#define INLINE_L2 0x00000002 // this cache is an inline cache
+#define PIPELINED_L2 0x00010000 // pipelined cache
+
+typedef struct _Cache_ {
+ STRUCT_HEADER;
+ UCHAR MaxSets; // Maximum number of "sets" available for this cache.
+ // direct mapped, then there is only 1.
+ UCHAR Bytes2Line; // line size in bytes: i.e. number of bytes per set.
+ USHORT Lines2Set; // number of lines per set.
+ UCHAR SramBanks; // # of memory banks: indicates both cache
+ // size and max set associativity.
+ ULONG Performance; // 3-1-1-1, 2-1-1-1 or some other cycle latency.
+ // the data is stored in BCD format.
+ ULONG MaxSize; // size of cache in bytes.
+ ULONG Properties; // properties of the cache's behavior: pipelined
+ // or not, lookaside or not...
+} CACHE;
+
+typedef struct _Memory_Device_ {
+ STRUCT_HEADER;
+ ULONG BaseAddress; // the base physical address for this memory.
+ USHORT MaxBankSize; // Maximum size of banks in Megabytes
+ UCHAR MaxNumBanks; // Maximum number of memory banks on this board;
+} MEMORY;
+
+
+/*
+ *
+ *
+ * Describe any busses on the system. Current plans account only
+ * for the pci bus but will expand to allow for complete bus typing.
+ * return to index
+ *
+ */
+typedef struct _BUS_ {
+ STRUCT_HEADER;
+ UCHAR NumIoBus; // number of io busses on main logic board.
+ ULONG ConfigAddr; // the location of the config space. Zero
+ // means there is no config space. This value
+ // points to the first device's address, and is
+ // assumed to be device 0.
+} BUS;
+
+
+/*
+ *
+ * The INT structure describes some set of interrupts on the system that
+ * software needs knowledge of. In this case software needs to know what
+ * pci config addresses map to what interrupts.
+ * In a later implementation, this should fully describe the system's
+ * interrupt space. return to index
+ *
+ */
+struct PAIRS {
+ UCHAR Int;
+ UCHAR SlotNumber;
+};
+
+typedef struct _INTS_ {
+ STRUCT_HEADER;
+ UCHAR Total; // how many interrupts are we talking about here?
+ struct PAIRS Pairs[0]; // pairs of numbers in the form: int, slot number:
+ // for ints on config addresses on a secondary
+ // bus, the slot number will be greater than 10
+ // where the more significant nibble describes
+ // bus number as seen from a low to high descending
+ // bus probe.
+
+} INTS;
+
+//#pragma warning(enable:4103) // disable C4103 warning
+//#pragma pack
+
+#endif // FPI2CSUP_H
diff --git a/private/ntos/nthals/halfire/ppc/fpints.c b/private/ntos/nthals/halfire/ppc/fpints.c
new file mode 100644
index 000000000..e69c09813
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpints.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpints.c $
+ * $Revision: 1.13 $
+ * $Date: 1996/07/13 01:15:58 $
+ * $Locker: $
+ */
+
+// TITLE("Manipulate Interrupt Request Level")
+//++
+//
+// Module Name:
+//
+// FPINTS.C
+//
+// Abstract:
+//
+// This module implements the arrays required to handle interrupt
+// priorities including generation of the arrays, and anything else
+// that is hardware specific interrupt oriented. This is not intended,
+// in it's original incarnation, to be an OS policy file, merely a hw one.
+//
+// The theory of ops is given a set of interrupts ordered by priority,
+// that is for any occurance of an interrupt, only those interrupts pre-
+// ceding it in the list may now occur. So, if int 5 is the highest
+// priority then when it occurrs, no other interrupt will be visible. Any
+// lesser interrupt may be interruptable by an int 5. And so on.
+//
+// Author:
+//
+// Bill Rees ( FirePOWER )
+// Sol Kavy ( FirePOWER )
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 16-Jul-95 Created
+//
+//--
+#include "fpdebug.h"
+#include "halp.h"
+#include "phsystem.h"
+#include "fppci.h"
+#include "pxpcisup.h"
+extern ULONG atoi(PCHAR);
+
+#define MAX_IRQL_NUM 32
+#define MAX_VECTORS 32
+
+//
+// Note: this is declared poorly in pxsiosup.c and should be
+// moved to PCR.
+//
+extern ULONG registeredInts[];
+
+//
+// This array spec's which interrupts go with which devices
+// on the host-pci bus ( bus 0, i.e. primary bus ).
+// NOTE: 0xff => no device interrupt provided.
+//
+UCHAR PciDevicePrimaryInts[MAXIMUM_PCI_SLOTS];
+
+/*
+ * Given an IRQL, provide a register mask that sets allowable interrupts
+ * and blocks all ints that are set at "lower" priority.
+ *
+ * This array is automatically generated from the Vector2Irql array by the
+ * HalpSetIntPriorityMask() call in fpints.c. For each entry in the V2I array
+ * that sits at an IRQL or above, it's interrupt bit is or'd into the Irql2Mask
+ * value. For example, at irql 0, almost every entry in the V2I array has an
+ * irql greater than 0 ( except for the reserved interrupts ) so the mask value
+ * in the Irql2Mask array has nearly every bit turned on. Conversely, at IRQL
+ * 24, only a few interrupts have irql values above 21 ( ints 0, 1, 22, 23,
+ * 28, 29, 30, 31 )
+ *
+ */
+ULONG Irql2Mask[MAX_IRQL_NUM];
+
+/*
+ * This array matches an IRQL to an Interrupt Vector. Since the array is
+ * indexed by interrupt vector, there can be a many interrupts to single IRQL
+ * mapping allowing interrupts to share IRQL settings. IRQLs determine
+ * relative operational order such that any code operating at any irql, will
+ * block code from a lower priority from occuring and in turn this same code
+ * can be interrupted by code trying to run at a higher priority.
+ *
+ * So this array becomes a prioritization of interrupts, determining which
+ * interrupts will block each other or not block each other. In this case,
+ * a higher number means higher priority hence blocking more interrupts.
+ *
+ * explanation on how this array is used is above the Irql2Mask[] declaration.
+ *
+ */
+ULONG Vector2Irql[MAX_VECTORS] = {
+ 26, // int 0 (Timer) is IRQL 26 so it blocks most other interrupts:
+ 25, // int 1 (KEYBD) blocks all other ISA devices except RTC.
+
+ 24, // int 2 is the cascade bit so all interrupts on the cascaded
+ // interrupt controller ( 8259 ) are higher priority than the
+ // rest of the interrupts on the master interrupt controller.
+
+ 15, // int 3 (COM2) is on the master but after the slave ints, so it
+ // blocks only those ints left on the master chip.
+
+ 14, // int 4 (COM1) is lower priority than com 2.
+ 13, // int 5 Display:
+ 12, // int 6 Floppy:
+ 11, // int 7 Parallel:
+ 23, // int 8 (RTC): First int on Slave: only ints 0,1,2 are higher pri.
+ 22, // int 9:
+ 21, // int 10 (AUDIO).
+ 20, // int 11:
+ 19, // int 12 Mouse int. Lower than keyboard.
+ 18, // int 13 old scsi
+ 17, // int 14 old enet:
+ 16, // int 15:
+ 00, // reserved: hence lowest priority
+ 00, // reserved: hence lowest priority
+ 00, // reserved: hence lowest priority
+ 00, // reserved: hence lowest priority
+ 00, // int 20 |
+ 00, // int 21 |
+ 00, // int 22 |
+ 00, // int 23 - PCI interrupts configured dynamically from the I2C
+ 00, // int 24 |
+ 00, // int 25 |
+ 00, // int 26 |
+ 00, // reserved: hence lowest priority
+ 28, // int 28(CPU) Set CPU Bus error IRQL to IPI_LEVEL
+ 28, // int 29(PCI) Set PCI Bus error IRQL to IPI_LEVEL
+ 28, // int 30(MEM/VID) Set MEMORY error IRQL to IPI_LEVEL
+ 29 // int 31(IPI) this is the cpu message level: > clock
+};
+
+ULONG LX_Vector2Irql[MAX_VECTORS] = {
+ 26, // int 0 (Timer) is IRQL 26 so it blocks most other interrupts:
+ 25, // int 1 (KEYBD) blocks all other ISA devices except RTC.
+
+ 24, // int 2 is the cascade bit so all interrupts on the cascaded
+ // interrupt controller ( 8259 ) are higher priority than the
+ // rest of the interrupts on the master interrupt controller.
+
+ 15, // int 3 (COM2) is on the master but after the slave ints, so it
+ // blocks only those ints left on the master chip.
+
+ 14, // int 4 (COM1) is lower priority than com 2.
+ 13, // int 5 Display:
+ 12, // int 6 Floppy:
+ 11, // int 7 Parallel:
+ 23, // int 8 (RTC): First int on Slave: only ints 0,1,2 are higher pri.
+ 22, // int 9:
+ 21, // int 10 (AUDIO).
+ 20, // int 11:
+ 19, // int 12 Mouse int. Lower than keyboard.
+ 18, // int 13 old scsi
+ 17, // int 14 old enet:
+ 16, // int 15:
+ 00, // reserved: hence lowest priority
+ 00, // reserved: hence lowest priority
+ 00, // reserved: hence lowest priority
+ 00, // reserved: hence lowest priority
+ 23, // int 20 LX: rsrvd ; TX: PCI slot 3
+ 22, // int 21 LX: IDE A ; TX: PCI slot 2
+ 21, // int 22 LX: IDE A ; TX: PCI slot 1
+ 20, // int 23 pci slot 3 IRQL
+ 19, // int 24 pci slot 2 IRQL
+ 18, // int 25 pci slot 1 IRQL scsi
+ 17, // int 26 pci slot 0 IRQL network
+ 00, // reserved: hence lowest priority
+ 28, // int 28(CPU) Set CPU Bus error IRQL to IPI_LEVEL
+ 28, // int 29(PCI) Set PCI Bus error IRQL to IPI_LEVEL
+ 28, // int 30(MEM/VID) Set MEMORY error IRQL to IPI_LEVEL
+ 29 // int 31(IPI) this is the cpu message level: > clock
+};
+
+// TX_PROTO & LX_PROTO: must reorder the IRQL table
+VOID HalpInitializeVector2Irql(VOID)
+{
+ ULONG irql = 17; // Start the PCI interrupts at irql 17
+ UCHAR slot;
+ UCHAR intNum;
+
+ for (slot = 1; slot < MAXIMUM_PCI_SLOTS; slot++) {
+ intNum = PciDevicePrimaryInts[slot];
+ if ((intNum != INVALID_INT) && (intNum < MAX_VECTORS)) {
+ Vector2Irql[intNum] = irql;
+ irql++;
+ }
+ }
+}
+
+HalpSetIntPriorityMask(VOID)
+{
+ ULONG irql, vec, Value=0;
+
+ //
+ // for each irql, search the Vector2Irql array and generate
+ // a mask suitable for writing to the mask register to block
+ // interrupts at the given irql.
+ //
+ for (irql = 0; irql < MAX_IRQL_NUM; irql++) {
+ Irql2Mask[irql] = 0;
+ for (vec = 0; vec < MAX_VECTORS; vec++) {
+ //
+ // Turn on bits for interrupts that are still allowed.
+ //
+ if (Vector2Irql[vec] > irql) {
+ Irql2Mask[irql] |= (1 << vec);
+ }
+ }
+ }
+ PRNTINTR(HalpDebugPrint("HalpSetIntPriorityMask: Irql2Mask: 0x%x\n",
+ &Irql2Mask[0]));
+ return(1);
+}
+
+
+//
+// THis array gives the processor affinity for the given interrupt
+// vector. Then NT will handle the interrupt on that processor.
+//
+
+ULONG Vector2Affinity[MAX_VECTORS];
+
+
+//
+/*++
+
+Routine Description: void HalpInitProcAffinity ()
+ This function sets the processor affinity for the given interrupt
+ in the Vector2Affinity array. If the values are wrong, cpu 0 is
+ set.
+
+Arguments:
+
+ pProcnInts - pointer to the PROCNINTS nvram variable.
+ numProc - number of processors in the system.
+
+
+Return Value:
+
+ void
+
+--*/
+
+void
+HalpInitProcAffinity(PCHAR pProcnInts, ULONG NumProc)
+{
+ ULONG vec,proc;
+ CHAR delim = ';';
+
+ if ( NumProc == 1 ) {
+ for(vec=0; vec < MAX_VECTORS; vec++) {
+ Vector2Affinity[vec] = 1; // cpu 0 always
+ }
+ HDBG(DBG_MPINTS,
+ HalpDebugPrint("Affinity set to 1 for all vectors\n"););
+ return;
+ }
+ HDBG(DBG_MPINTS,HalpDebugPrint("vector affinity\n"););
+ // multiprocessor but no PROCNINTS given
+ // distribute on all processors round robin fashion
+ if ( pProcnInts == 0 ) {
+ for(vec=0; vec < MAX_VECTORS; vec++) {
+ Vector2Affinity[vec] = 1 << (vec%NumProc); // next cpu gets next vec
+ HDBG(DBG_MPINTS,
+ HalpDebugPrint("%6d %6d\n",vec,Vector2Affinity[vec]););
+ }
+ return;
+ }
+ // otherwise go with the env variable PROCNINTS in pProcnInts
+ for(vec=0; vec < MAX_VECTORS; vec++) {
+ if ( *pProcnInts == 0 || *pProcnInts == delim )
+ proc = 0;
+ else
+ proc = atoi(pProcnInts);
+ if ( proc >= NumProc )
+ proc = (proc % NumProc);
+ Vector2Affinity[vec] = 1 << proc;
+ while(*pProcnInts && *pProcnInts != ';')
+ pProcnInts++; // skip current affinity
+ if (*pProcnInts == ';')
+ pProcnInts++; // skip delimiter
+ HDBG(DBG_MPINTS,
+ HalpDebugPrint("%6d %6d\n",vec,Vector2Affinity[vec]););
+ }
+ return;
+}
diff --git a/private/ntos/nthals/halfire/ppc/fpio.h b/private/ntos/nthals/halfire/ppc/fpio.h
new file mode 100644
index 000000000..e06763e14
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpio.h
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpio.h $
+ * $Revision: 1.9 $
+ * $Date: 1996/01/11 07:06:50 $
+ * $Locker: $
+ *
+ * This file contains references to registers in I/O space only. That is any
+ * access to the ISA or PCI space ( or any future additions ) are contained in
+ * this file. Access to device registers that do not lie in I/O space should
+ * be defined in the file fpreg.h
+ *
+ */
+
+#ifndef FPIO_H
+#define FPIO_H
+
+//
+// Define macros for handling accesses to io-space:
+//
+
+// HalpIoControlBase is extern'd in pxhalp.h which is included by halp.h
+
+#define _IOBASE ((PUCHAR)HalpIoControlBase)
+#define _IOREG(_OFFSET) (*(volatile UCHAR * const)((_IOBASE + (_OFFSET))))
+#define _IOADDR(_OFFSET) ((_IOBASE + (_OFFSET)))
+
+#define _PCIOBASE ((PUCHAR)HalpPciConfigBase)
+#define _PCIOREG(_OFFSET) (*(volatile UCHAR * const)((_PCIOBASE + (_OFFSET))))
+#define _PCIOADDR(_OFFSET) ((_PCIOBASE + (_OFFSET)))
+
+//
+// The Physical IO Space for generation one machines starts at 0x8000_0000.
+// All IO external devices in either ISA space or PCI space live within
+// this domain. This also includes the on-board ethernet and scsi drivers,
+// the ISA bus interrupt controllers, display control.
+//
+
+//
+// PCI Configuration Space:
+//
+//
+// device cpu relative Address Config space address
+// ------ -------------------- ----------------
+//
+// 82378 ( SIO ) 0x8080_0800 - 0x8080_08ff 0x80_0800 - 0x80_08ff
+// scsi (79c974) 0x8080_1000 - 0x8080_10ff 0x80_1000 - 0x80_10ff
+// pci slot A 0x8080_2000 - 0x8080_20ff 0x80_2000 - 0x80_20ff
+// pci slot B 0x8080_4000 - 0x8080_40ff 0x80_4000 - 0x80_40ff
+// enet (79c974) 0x8080_8000 - 0x8080_80ff 0x80_8000 - 0x80_80ff
+
+#define RPciConfig(Slot,Offset) \
+ (*(volatile ULONG * const)(_PCIOBASE + (HalpPciConfigSlot[Slot] + Offset)) )
+
+#define RPciVendor(Slot) \
+ (*(volatile ULONG * const)(_PCIOBASE + (UCHAR)(HalpPciConfigSlot[Slot])) )
+
+#define RPciVendorId(Slot) \
+ (*(volatile ULONG * const) (_PCIOBASE + (HalpPciConfigSlot[Slot])) )
+ //(*(volatile ULONG * const) (_PCIOBASE + (0x800 << Slot) ) )
+
+//
+// I/O Device Addresses
+//
+
+// Device Registers IO Space Cpu Space
+// ---------------- -------- ---------
+//
+// Dma 1 registers, control 0x0000 - 0x000f 0x8000_0000 - _000f
+
+// 8259 interrupt 1 control 0x0020 0x8000_0020
+// 8259 interrupt 1 mask 0x0021 0x8000_0021
+#define MasterIntPort0 0x0020
+#define MasterIntPort1 0x0021
+
+//
+// AIP Primary xbus index 0x0022
+// AIP Primary Xbus target 0x0023
+// AIP Secondary Xbus
+// target 0x0024
+// AIP Secondary xbus
+// index 0x0025
+//
+#define AIP_PRIMARY_XBUS_INDEX 0x0022
+#define AIP_PRIMARY_XBUS_TARGET 0x0023
+#define AIP_SECONDARY_XBUS_INDEX 0x0024
+#define AIP_SECONDARY_XBUS_TARGET 0x0025
+
+
+
+// keyboard cs, Reset 0x0060
+// ( xbus irq 12 )
+// nmi status and control 0x0061
+// keyboard cs 0x0062
+// keyboard cs 0x0064
+// keyboard cs 0x0066
+
+/*
+** *******************************************
+**
+** Dallas 1385 Real Time Clock : System macros
+** dallas specific macros are in pxds1585.h
+*/
+// RTC address 0x0070
+// RTC read/writ 0x0071
+// NVRAM addr strobe 0 0x0072
+// NVRAM addr strobe 1 0x0075
+// NVRAM Read/Write 0x0077
+// RTC and NVRAM 0x0070 - 0077
+
+#define RTC_INDEX 0x0070 // index register
+#define RTC_DATA 0x0071 // data register
+#define NVRAM_ADDR0 0x0072 // address strobe 0
+#define NVRAM_ADDR1 0x0075 // address strobe 1
+#define NVRAM_RW 0x0077 // read write nvram?
+
+
+// Timer 0x0078 - 007f
+// DMA Page Registers 0x0080 - 0090
+// Port 92 Register 0x0080 - 0092
+// DMA Page Registers 0x0094 - 009f
+
+// 8259 interrupt 2 control 0x00A0 0x8000_00A0
+// 8259 interrupt 2 mask 0x00A1 0x8000_00A1
+#define SlaveIntPort0 0x00A0
+#define SlaveIntPort1 0x00A1
+
+// DMA 2 registers and
+// control 0x00c0 - 00df
+
+
+// AIP Configuration
+// Registers 0x026e - 026f
+// ( primary addr block )
+#define AIP_PRIMARY_CONFIG_INDEX_REG 0x026e
+#define AIP_PRIMARY_CNFG_DATA_REG 0x026f
+
+
+// Parallel Port 3 0x0278 - 027d
+// serial port2 0x02f8 - 02ff
+// secondary floppy
+// controller 0x0370 - 0377
+// parallel port 2 0x0378 - 037d
+
+
+// AIP Configuraiton Registers 0x0398 - 0399
+// ( secondary addr blck )
+#define AIP_SECOND_CONFIG_INDEX_REG 0x0398
+#define AIP_SECOND_CNFG_DATA_REG 0x0399
+
+
+// parallel port 1 0x03bc - 03bf
+// pcmcia config registers 0x03e0 - 03e3
+// primary floppy controller 0x03f0 - 03f7
+// serial port 1 0x03f8 - 03ff
+// dma 1 extended
+// mode regsiter 0x040b
+// dma scatter/gather
+// command status 0x0410 - 041f
+// dma scatter/gather
+// Dscrptr ( channel 0-3 ) 0x0420 - 042f
+// dma scatter/gather
+// Dscrptr ( channel 5-7 ) 0x0434 - 043f
+// dma high page registers 0x0481 - 0483
+// dma high page registers 0x0487
+// dma high page registers 0x0489
+// dma high page registers 0x048a - 048b
+// dma 2 extended mode
+// register 0x04d6
+// business audio control,
+// status, data registers 0x0830 - 0833
+
+
+// video asic registers 0x0840 - 0841
+#define DCC_INDEX 0x0840
+#define DCC_DATA 0x0841
+
+
+// bt445 ramdac registers 0x0860 - 086f
+#define BT445_ADDRESS 0x0860
+#define ADDRESS_REGISTER 0x0860 // same as the BT445_ADDR
+#define PRIMARY_PALETTE 0x0861 // Primary Color Palette address
+#define CHIP_CONTROL 0x0862 // function control register
+#define OVERLAY_PALETTE 0x0863 // Overlay Color Palette
+#define RGB_PIXEL_CONFIG 0x0865 // RGB configuration and control
+#define TIMING_PIXEL_CONFIG 0x0866 // pixel timing, configuration, control
+#define CURSOR_COLOR 0x0867 // cursor color
+
+// dram simm presence
+// detect register 0x0880
+// vram simm presence
+// detect register 0x0890
+// epxansion presence
+// detect register 0x08a0
+//
+
+//
+// Defines for Register Access:
+//
+#define rIndexRTC _IOREG( RTC_INDEX )
+#define rDataRTC _IOREG( RTC_DATA )
+#define rNvramData _IOREG( NVRAM_RW )
+#define rNvramAddr0 _IOREG( NVRAM_ADDR0 )
+#define rNvramAddr1 _IOREG( NVRAM_ADDR1 )
+#define rMasterIntPort0 _IOREG( MasterIntPort0 )
+#define rMasterIntPort1 _IOREG( MasterIntPort1 )
+#define rSlaveIntPort0 _IOREG( SlaveIntPort0 )
+#define rSlaveIntPort1 _IOREG( SlaveIntPort1 )
+
+#define rIndexAIP1 _IOREG( AIP_PRIMARY_XBUS_INDEX )
+#define rTargetAIP1 _IOREG( AIP_PRIMARY_XBUS_TARGET )
+#define rIndexAIP2 _IOREG( AIP_SECONDARY_XBUS_INDEX )
+#define rTargetAIP2 _IOREG( AIP_SECONDARY_XBUS_TARGET )
+
+
+#define rDccIndex _IOREG( DCC_INDEX )
+#define rDccData _IOREG( DCC_DATA )
+
+#define rRamDacAddr _IOREG( BT445_ADDRESS )
+#define rDacPrimeLut _IOREG( PRIMARY_PALETTE )
+#define rRamDacCntl _IOREG( CHIP_CONTROL )
+#define rDacOvlayLut _IOREG( OVERLAY_PALETTE )
+#define rDacPixelBit _IOREG( RGB_PIXEL_CONFIG )
+#define rDacPixelClks _IOREG( TIMING_PIXEL_CONFIG )
+#define rRamDacCursor _IOREG( CURSOR_COLOR )
+
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fplibc.c b/private/ntos/nthals/halfire/ppc/fplibc.c
new file mode 100644
index 000000000..b3461e904
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fplibc.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fplibc.c $
+ * $Revision: 1.3 $
+ * $Date: 1996/04/30 23:25:53 $
+ * $Locker: $
+ */
+
+/*
+ * This file contains libc support routines that the kernel/hal do
+ * not include but that the HAL wants to use, so we have created
+ * our own.
+ */
+
+#include "fpproto.h"
+
+int
+atoi(char *s)
+{
+ int temp = 0, base = 10;
+
+ if (*s == '0') {
+ ++s;
+ if (*s == 'x') {
+ ++s;
+ base = 16;
+ } else {
+ base = 8;
+ }
+ }
+ while (*s) {
+ switch (*s) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ temp = (temp * base) + (*s++ - '0');
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ temp = (temp * base) + (*s++ - 'a' + 10);
+ break;
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ temp = (temp * base) + (*s++ - 'A' + 10);
+ break;
+ default:
+ return (temp);
+ }
+ }
+ return (temp);
+}
+
+char *
+FpStrtok (
+ 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 '\0';
+ } else {
+ return string;
+ }
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/fpnvram.h b/private/ntos/nthals/halfire/ppc/fpnvram.h
new file mode 100644
index 000000000..a4a0c03b4
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpnvram.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpnvram.h $
+ * $Revision: 1.4 $
+ * $Date: 1996/01/11 07:07:03 $
+ * $Locker: $
+ */
+#ifndef _PREPNVRM_H
+#define _PREPNVRM_H
+//
+// This header describes the NVRAM definition for PREP
+//
+typedef struct _SECURITY {
+ ULONG BootErrCnt; // Count of boot password errors
+ ULONG ConfigErrCnt; // Count of config password errors
+ ULONG BootErrorDT[2]; // Date&Time from RTC of last error in pw
+ ULONG ConfigErrorDT[2]; // Date&Time from RTC of last error in pw
+ ULONG BootCorrectDT[2]; // Date&Time from RTC of last correct pw
+ ULONG ConfigCorrectDT[2]; // Date&Time from RTC of last correct pw
+ ULONG BootSetDT[2]; // Date&Time from RTC of last set of pw
+ ULONG ConfigSetDT[2]; // Date&Time from RTC of last set of pw
+ UCHAR Serial[16]; // Box serial Number
+} SECURITY;
+
+typedef enum _OS_ID {
+ Unknown = 0,
+ Firmware = 1,
+ AIX = 2,
+ NT = 3,
+ MKOS2 = 4,
+ MKAIX = 5,
+ Taligent = 6,
+ Solaris = 7,
+ MK = 12
+} OS_ID;
+
+typedef struct _ERROR_LOG {
+ UCHAR ErrorLogEntry[40];
+} ERROR_LOG;
+
+typedef enum _NVRAM_BOOT_STATUS {
+ BootStarted = 0x001,
+ BootFinished = 0x002,
+ RestartStarted = 0x004,
+ RestartFinished = 0x008,
+ PowerFailStarted = 0x010,
+ PowerFailFinished = 0x020,
+ ProcessorReady = 0x040,
+ ProcessorRunning = 0x080,
+ ProcessorStart = 0x100
+} NVRAM_BOOT_STATUS;
+
+typedef struct _NVRAM_RESTART_BLOCK {
+ USHORT Version;
+ USHORT Revision;
+ ULONG ResumeReserved[2];
+ volatile ULONG BootStatus;
+ ULONG CheckSum;
+ void * RestartAddress;
+ void * SaveAreaAddr;
+ ULONG SaveAreaLength;
+} NVRAM_RESTART_BLOCK;
+
+typedef enum _OSAREA_USAGE {
+ Empty = 0,
+ Used = 1
+} OSAREA_USAGE;
+
+typedef enum _PM_MODE {
+ Suspend = 0x80,
+ Normal = 0x00
+} PMMode;
+
+typedef struct _HEADER {
+ USHORT Size; // NVRAM size in K
+ UCHAR Version; // Structure map different
+ UCHAR Revision; // Structure map same - may be new values in old fields
+ USHORT Crc1;
+ USHORT Crc2;
+ UCHAR LastOS; // OS_ID
+ UCHAR Endian; // B if big endian, L if little endian
+ UCHAR OSAreaUsage;
+ UCHAR PMMode; // Power Management shutdown mode
+ NVRAM_RESTART_BLOCK Restart;
+ SECURITY Security;
+ ERROR_LOG ErrorLog[2];
+
+ PVOID GEAddress;
+ ULONG GELength;
+ ULONG GELastWriteDT[2]; // Date&Time from RTC of last change to Global
+
+ PVOID ConfigAddress;
+ ULONG ConfigLength;
+ ULONG ConfigLastWriteDT[2]; // Date&Time from RTC of last change to Config
+ ULONG ConfigCount; // Count of entries in Configuration
+
+ PVOID OSAreaAddress;
+ ULONG OSAreaLength;
+ ULONG OSAreaLastWriteDT[2]; // Date&Time from RTC of last change to Var
+
+} HEADER, *PHEADER;
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fppci.h b/private/ntos/nthals/halfire/ppc/fppci.h
new file mode 100644
index 000000000..f11095fb4
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fppci.h
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fppci.h $
+ * $Revision: 1.7 $
+ * $Date: 1996/01/25 01:11:27 $
+ * $Locker: $
+ *
+ * Herein are the definitions used to interact with PCI based devices. The
+ * information is specific to the PCI spec as interpreted by FirePOWER and
+ * not specific to the hardware ( or at the least minimally relavent to hw).
+ *
+ * Please look in FPIO.H for system specific information relevant to the IO
+ * system such as memory maps or register read/write specifics.
+ *
+ */
+
+#ifndef FPPCI_H
+#define FPPCI_H
+
+#ifdef HALDEBUG_ON
+#define PRINTBRIDGE(x) \
+ if ( HalpDebugValue&DBG_PCI ) { \
+ PULONG j; \
+ ULONG i; \
+ HalpDebugPrint("\nVendor: 0x%x, Dev: 0x%x, Cmd: 0x%x, Stat: 0x%x\n",\
+ x->VendorID, x->DeviceID, x->Command, x->Status); \
+ HalpDebugPrint("PrimaryBus: 0x%02x, SecondaryBus: 0x%02x", \
+ x->u.type1.PrimaryBus, \
+ x->u.type1.SecondaryBus); \
+ HalpDebugPrint(" SubBus: 0x%02x, IOBase: 0x%02x, IOLimit:0x%02x\n", \
+ x->u.type1.SubordinateBus,\
+ x->u.type1.IOBase, \
+ x->u.type1.IOLimit); \
+ HalpDebugPrint("Secnd Status: 0x%04x, MemBase 0x%04x, MemLimit 0x%04x",\
+ x->u.type1.SecondaryStatus, x->u.type1.MemoryBase, \
+ x->u.type1.MemoryLimit ); \
+ HalpDebugPrint(" IntLine: 0x%02x, IntPin: 0x%02x, BrdgeCntl: 0x%04x\n",\
+ x->u.type1.InterruptLine, x->u.type1.InterruptPin, \
+ x->u.type1.BridgeControl); \
+ j=(PULONG)x; \
+ for(i=0; i<(PCI_COMMON_HDR_LENGTH/4); j+=4, i+=4){ \
+ HalpDebugPrint("%s 0x%08x, 0x%08x, 0x%08x, 0x%08x \n", \
+ TBS, *j, *(j+1), *(j+2), *(j+3) ); \
+ } \
+ }
+#else
+#define PRINTBRIDGE(x)
+#endif //haldebug_on
+
+//
+// Hardware Specific Defines for FirePOWER:
+//
+#define TYPE1_ACCESS 0x1 // configuration space access is of Standard type 1
+#define TYPE2_ACCESS 0x2 // configuration space access is of Standard type 2
+#define BRIDGED_ACCESS 0x3 // FirePOWER specific access: modified type 1.
+
+/*
+ * PCI Register config read/write macros: dependent on defines
+ * in FPIO.H which must be included in the c file before this
+ * file is included ( not included here to avoid multiple
+ * includes of the file in any io specific file).
+ *
+ */
+
+//
+// type - what type of data access: uchar, ushort, or ulong:
+// (UCHAR) bus - what pci bus ( up to 256 )
+// (UCHAR) Device - Which physical board: = physical slot. ( max of 32 )
+// (UCHAR) Fn - Which function on the board ( Max of 8 )
+// (UCHAR) Offset - The offset into the config header ( one of 64 words )
+//
+
+#define SLOT(DEV, FN ) (ULONG) ((ULONG)( (DEV & 0x1f) << 11 ) | \
+ (ULONG)( (FN & 0x07) << 8 ) )
+#define CONFIG(BUSNUM, DEV, FN, OFFSET ) \
+ (ULONG)( BUSNUM << 16 ) | SLOT(DEV, FN) | (ULONG)( OFFSET & 0xfc)
+
+#define RPciBusConfig(TYPE, BUSNUM, DEV, FN, OFFSET ) \
+ (*(volatile type * const) (_PCIOBASE + \
+ (ULONG)( CONFIG(BUSNUM, DEV, FN, OFFSET) ) ) )
+// (*(volatile type * const) (_PCIOBASE + (ULONG)( (0x800 << Slot) ) ) )
+//(*(volatile ULONG * const)(_PCIOBASE + (HalpPciConfigSlot[Slot] + Offset)))
+
+/*
+ * Pci Configuration Header Defines:
+ * These defines are in conjunction with what's in ntos\inc\pci.h.
+ *
+ */
+
+//
+// Major Classes ( also called BaseClasses ) of devices.....
+//
+#define PRE_REV2_CLASS 0x00
+#define MASS_STORAGE_CLASS 0x01
+#define NETWORK_CTLR_CLASS 0x02
+#define DISPLAY_CTLR_CLASS 0x03
+#define MULTIMEDIA_CLASS 0x04
+#define MEMORY_CTLR_CLASS 0x05
+#define BRIDGE_CLASS 0x06
+
+//
+// SubClasses and Programming interfaces....
+//
+
+// REV2 CLASS
+//
+#define NON_VGA_SUBCLASS 0x00
+#define NON_VGA_PROGIF 0x00
+#define VGA_SUB_CLASS 0x01
+#define VGA_PROGIF 0x01
+
+// Mass Storage Classes
+//
+#define SCSI_SUBCLASS 0x00
+#define SCSI_PROGIF 0x00
+#define IDE_SUBCLASS 0x01
+#define IDE_PROGIF 0x00
+#define FLOPPY_SUBCLASS 0x02
+#define FLOPPY_PROGIF 0x00
+#define IPI_SUBCLASS 0x03
+#define IPI_PROGIF 0x00
+#define OTHER_SUBCLASS 0x80
+#define OTHER_PROGIF 0x00
+
+// Network Controller Classes
+//
+#define ENET_SUBCLASS 0x00
+#define ENET_PROGIF 0x00
+#define TKNRING_SUBCLASS 0x01
+#define TKNRING_PROGIF 0x00
+#define FDDI_SUBCLASS 0x02
+#define FDDI_PROGIF 0x00
+#define OTHR_NTWK_SUBCLASS 0x80
+#define OTHR_PROGIF 0x00
+
+// Display Controller Classes
+//
+#define VGA_SUBCLASS 0x00
+#define VGA_CTLR_PROGIF 0x00
+#define XGA_SUBCLASS 0x01
+#define XGA_PROGIF 0x00
+#define OTHR_DSPLY_SUBCLASS 0x80
+#define OTHR_DISPLY_PROGIF 0x00
+
+// Multimedia Device Classes
+//
+#define VIDEO_SUBCLASS 0x00
+#define VIDEO_PROGIF 0x00
+#define AUDIO_SUBCLASS 0x01
+#define AUDIO_PROGIF 0x00
+#define OTHR_MLTIMDIA_SUBCLASS 0x80
+#define OTHR_MLTIMDIA_PROGIF 0x00
+
+// Memory Controller Classes
+//
+#define RAM_SUBCLASS 0x00
+#define RAM_PROGIF 0x00
+#define FLASH_SUBCLASS 0x01
+#define FLASH_PROGIF 0x00
+#define OTHR_MEM_SUBCLASS 0x80
+#define OTHR_MEM_PROGIF 0x00
+
+// Bridge Device Classes
+//
+#define HOST_PCI_SUBCLASS 0x00
+#define HOST_PCI_PROGIF 0x00
+#define PCI_ISA_SUBCLASS 0x01
+#define PCI_ISA_PROGIF 0x00
+#define PCI_EISA_SUBCLASS 0x02
+#define PCI_EISA_PROGIF 0x00
+#define PCI_MCHANL_SUBCLASS 0x03
+#define PCI_MCHANL_PROGIF 0x00
+#define PCI_PCI_SUBCLASS 0x04
+#define PCI_PCI_PROGIF 0x00
+#define PCI_PCMCIA_SUBCLASS 0x05
+#define PCI_PCMCIA_PROGIF 0x00
+#define OTHER_BRIDGE_SUBCLASS 0x80
+#define OTHER_BRIDGE_PROGIF 0x00
+
+#define VENDOR_DIGITAL 0x1011
+#define DEVICE_21050 0x1
+#define PCI_ISA_IO_PHYSICAL_BASE 0x80000000
+#define PCI_IO_PHYSICAL_BASE 0x81000000
+#define PCI_IO_ADDRESS 0x00000001
+#define PCI_MEMORY_ADDRESS 0x00000000
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/fppcisup.c b/private/ntos/nthals/halfire/ppc/fppcisup.c
new file mode 100644
index 000000000..379c03ef0
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fppcisup.c
@@ -0,0 +1,1101 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fppcisup.c $
+ * $Revision: 1.33 $
+ * $Date: 1996/07/02 02:26:11 $
+ * $Locker: $
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <arccodes.h>
+#include "fpdebug.h"
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxpcisup.h"
+#include "phsystem.h"
+#include "fpio.h"
+#include "fppci.h"
+#include "fppcisup.h"
+
+#define DEC_BRIDGE_CHIP (0x1011) // Dec Bridge Chip VendorID
+
+extern KSPIN_LOCK HalpPCIConfigLock;
+extern UCHAR PciDevicePrimaryInts[];
+PUCHAR ClassNames[] = {
+ "Pre rev 2.0 ",
+ "Mass Storage",
+ "Network",
+ "Display",
+ "MultiMedia",
+ "Memory",
+ "Bridge",
+ "UnkNown",
+ "UnkNown",
+ "UnkNown",
+ "UnkNown",
+ "UnkNown",
+ "UnkNown"
+ };
+
+//
+// scan the bus depth first, then pop back out and catch all the siblings
+// on the way back.
+//
+ULONG
+HalpScanPciBus( ULONG HwType, ULONG BusNo, PBUS_HANDLER ParentBus )
+{
+ ULONG devs, fns, Stat=0, ValidDevs=0,BusDepth=0, BusLimits;
+ PUCHAR Buffer;
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG *PciData;
+ PBUS_HANDLER CurrentBus, ChildBus;
+ PFPHAL_BUSNODE FpBusData;
+ ULONG slot;
+ char buf[128];
+
+ //
+ // Added by Keith Son to support peer level bridge.
+ //
+ ULONG Bus_Current_Number, Bus_Next_Number, Bus_Child_Number=0;
+
+
+ HDBG(DBG_GENERAL, HalpDebugPrint("HalpScanPciBus: 0x%x, 0x%0x, 0x%08x\n",
+ HwType, BusNo, ParentBus ););
+
+ // ENGINEERING DEVELOPMENT: allow optional toggle of Bridge mode
+ // in the IO ASIC.
+ if (HalGetEnvironmentVariable("BRIDGEMODE", sizeof(buf), buf)
+ == ESUCCESS) {
+ if (_stricmp(buf, "true") == 0) {
+ PRNTPCI(HalpDebugPrint(
+ "HalpScanPciBus: BRIDGEMODE enabled\n"));
+ rTscControl |= 0x20000000;
+ rPIOPendingCount |= 0x80;
+ FireSyncRegister();
+ }
+ else {
+ PRNTPCI(HalpDebugPrint(
+ "HalpScanPciBus: BRIDGEMODE disabled\n"));
+ rTscControl &= ~0x20000000;
+ rPIOPendingCount &= ~0x80;
+ FireSyncRegister();
+ }
+ }
+
+ //
+ // Added by Keith Son.
+ // This variable is needed to keep track of the number of buses in the
+ // system.
+ //
+ Bus_Next_Number = BusNo;
+
+
+
+ if ((CurrentBus = HalpAllocateAndInitPciBusHandler(HwType, BusNo, TRUE))
+ == (PBUS_HANDLER) NULL ) {
+ HalpDebugPrint("\nHalpInitIoBuses: DID NOT ALLOCATE BUS HANDLER: \n");
+ return 1; // add in status on return later...
+ }
+
+ FpBusData = (PFPHAL_BUSNODE)CurrentBus->BusData;
+
+ if (ParentBus) {
+ //
+ // Setup bus defaults for heirarchical buses.
+ //
+ Bus_Current_Number = BusNo;
+ FpBusData->Bus.MaxDevice = PCI_MAX_DEVICES;
+ BusLimits = PCI_MAX_DEVICES;
+ FpBusData->Bus.ParentBus = (UCHAR) ParentBus->BusNumber;
+
+ slot = FpBusData->Bus.CommonData.ParentSlot.u.bits.DeviceNumber;
+ if (slot > MAXIMUM_PCI_SLOTS) {
+ HalpDebugPrint("HalpScanPciBus: child %d ILLEGAL PARENT SLOT %d\n",
+ BusNo, slot);
+ return 1; // add in status on return later...
+ }
+ // It doesn't matter if the BusInt is an INVALID_INT here
+ FpBusData->BusInt = PciDevicePrimaryInts[slot];
+ FpBusData->BusMax = (UCHAR)BusNo;
+ FpBusData->Bus.CommonData.ParentSlot.u.AsULONG =
+ ((PFPHAL_BUSNODE)ParentBus->BusData)->SlotNumber.u.AsULONG;
+ FpBusData->SlotNumber.u.AsULONG =
+ ((PFPHAL_BUSNODE)ParentBus->BusData)->SlotNumber.u.AsULONG;
+
+
+
+ if (!(FpBusData->Bus.CommonData.ParentSlot.u.AsULONG)) {
+ PRNTPCI(
+ HalpDebugPrint("HalpScanPciBus: Child (0x%x): no ParentSlot\n",
+ BusNo));
+ FpBusData->Bus.CommonData.ParentSlot.u.AsULONG = 0xffffffff;
+
+
+ }
+ } else {
+ //
+ // This must be the host-pci bus handler, so setup the supported
+ // interrupts this bus will support...
+ //
+ BusLimits = MAXIMUM_PCI_SLOTS;
+ FpBusData->MemBase = 0;
+ FpBusData->MemTop = 0xffffffff;
+ FpBusData->IoBase = 0;
+ FpBusData->IoTop = 0xffffffff;
+ FpBusData->Bus.CommonData.ParentSlot.u.AsULONG = 0xffffffff;
+ //
+ // Keith Son.
+ // Added to support peer bridge. Keeping track the number of bridge in the scan process.
+ //
+ Bus_Current_Number = BusNo;
+
+
+
+ }
+ //
+ // setup general data areas for use...
+ //
+ Buffer = ExAllocatePool (PagedPool, 1024);
+ PciData = (PPCI_COMMON_CONFIG) Buffer;
+ FpBusData->ValidDevs = 0xffffffff; // init valid dev structure
+
+ HDBG(DBG_BREAK,DbgBreakPoint(););
+
+ //
+ // Now scan this bus for contents...
+ //
+ SlotNumber.u.AsULONG = 0; // init structure to a known value..
+ for (devs =0; devs < BusLimits; devs++) {
+ SlotNumber.u.bits.DeviceNumber = devs;
+ PRNTPCI(HalpDebugPrint("%s%x devs; %x",TBS,CurrentBus->BusNumber,devs));
+
+ for (fns =0; fns <PCI_MAX_FUNCTION; fns++) {
+ HDBG(DBG_PCI, HalpDebugPrint(" fns = %x \n",fns ););
+ SlotNumber.u.bits.FunctionNumber = fns;
+
+ HalpReadPCIConfig(
+ CurrentBus, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+
+ PRNTPCI(HalpDebugPrint("\tSlot %x: Vendor: 0x%x, Device: 0x%x\n",
+ SlotNumber.u.AsULONG, PciData->VendorID, PciData->DeviceID));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ){
+ //
+ // checking for invalid device status, and if
+ // there is no device on this slot then turn off
+ // the valid bit and break out of this loop
+ //
+ FpBusData->ValidDevs &= ~(1 << devs);
+ PRNTPCI(HalpDebugPrint("\t\tValidDevs now set to: 0x%08x\n",
+ FpBusData->ValidDevs) );
+ break;
+ }
+
+ PRNTPCI(HalpDebugPrint("\t\tDev is class type %s(%x)\n",
+ ClassNames[PciData->BaseClass], PciData->BaseClass));
+
+ //
+ // Check if this device is a bridge chip. Add in checking for
+ // what Type of bridge chip it is and tailor the configuration
+ // appropriately.
+ //
+ if (PciData->BaseClass == 0x6) {
+ //
+ // Set this bridge's primary bus number and pass it into
+ // the configuration routine. The config routine will set
+ // up the secondary bus fields and other required fields,
+ // write the config data out to the bridge, and return.
+ //
+ FpBusData->SlotNumber.u.AsULONG = SlotNumber.u.AsULONG;
+ //
+ // Keith Son.
+ // Needed to pass the bus no. to the next level of bridge.
+ //
+ PciData->u.type1.PrimaryBus = (UCHAR) Bus_Next_Number;
+
+
+
+ switch (PciData->SubClass) {
+ case HOST_PCI_SUBCLASS: Stat =0;
+ break;
+
+ case PCI_PCI_SUBCLASS:
+ Stat = HalpInitPciBridgeConfig( BusNo,
+ PciData,
+ CurrentBus);
+ break;
+
+ case PCI_PCMCIA_SUBCLASS:
+ Stat = HalpConfigurePcmciaBridge(BusNo);
+ break;
+ default:
+ break;
+ };
+
+ //
+ // Now setup a bus and scan the secondary bus on this
+ // bridge chip. If it also contains a bridge, recurse.
+ // When we come back out, need to make sure the subordinate
+ // bus fields are setup correctly.
+ //
+ if (Stat) {
+ //
+ // If the bridge was successfully initted, then
+ // descend through the bridge and scan it's bus
+ //
+ FpBusData->BusLevel++;
+ HDBG(DBG_PCI, HalpDebugPrint("-------- Bus %x ---------\n",
+ FpBusData->BusLevel););
+
+
+ //
+ // Keith Son.
+ // Keep updating the maximun bus variable and the value for the recursive scan.
+ //
+ if (Bus_Next_Number > FpBusData->BusMax)
+ FpBusData->BusMax = (UCHAR)Bus_Next_Number;
+
+ //
+ // Keith Son.
+ // Bus_Next_Number is the place holder for counting number of buses.
+ //
+
+ Bus_Next_Number = HalpScanPciBus( BRIDGED_ACCESS,
+ FpBusData->BusMax+1,
+ CurrentBus);
+
+
+ HDBG(DBG_PCI, HalpDebugPrint("-------- Bus_Next_Number %x ---------\n",
+ Bus_Next_Number););
+
+ //
+ // Keith Son.
+ // Update the secondary bus value after scanning the sub-bus.
+ // This is very important because bridge controller only forward acces based on
+ // the secondary and Subordinate.
+ //
+ PRINTBRIDGE(PciData);
+ PciData->u.type1.SecondaryBus = (UCHAR)Bus_Next_Number;
+ PciData->u.type1.SubordinateBus = (UCHAR)Bus_Next_Number;
+ // for now, prune on way back..
+
+ PRINTBRIDGE(PciData);
+
+ HalpWritePCIConfig (CurrentBus, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Keith Son.
+ //
+
+
+ ChildBus = HalpHandlerForBus(PCIBus, Bus_Next_Number );
+
+ if (ChildBus) {
+ PFPHAL_BUSNODE ChildData;
+ ChildData = (PFPHAL_BUSNODE)ChildBus->BusData;
+ ChildBus->ParentHandler = CurrentBus;
+ FpBusData->BusMax = ChildData->BusMax;
+/*
+#pragma NOTE("fixup memory/port assignments");
+should probably assign parent's fields first, then tell the child
+what range he can use.
+*/
+ //
+ // setup the memory and port limits for this bridge:
+ // since the bridge itself uses the limit registers to
+ // effectively pick the last page ( for port addresses )
+ // or last megabyte ( for memory ) rather than the last
+ // byte, we need to reflect that by translating the
+ // page ( or megabyte ) count to a byte count: hence the
+ // shift left and 'or' in of 'f's.
+ //
+ ChildData->MemBase =
+ (ULONG)PciData->u.type1.MemoryBase<<16;
+ ChildData->MemTop =
+ (ULONG)(PciData->u.type1.MemoryLimit<<16 | 0xfffff);
+
+ ChildData->IoBase = (ULONG)PciData->u.type1.IOBase<<8;
+ ChildData->IoTop =
+ (ULONG)PciData->u.type1.IOLimit << 8 | 0xfff;
+
+ HDBG(DBG_PCI,
+ HalpDebugPrint("ChildData->MemBase=%x MemTop=%x IoBase=%x IoTop=%x\n",
+ ChildData->MemBase, ChildData->MemTop, ChildData->IoBase, ChildData->IoTop););
+
+
+ //
+ // Skim the memory from the parents list..
+ //
+ FpBusData->MemTop = ChildData->MemBase -1;
+ FpBusData->IoTop = ChildData->IoBase -1;
+
+ //
+ // Remind the child what slot he uses on the parent's
+ // bus. This allows someone, given the child's bus,
+ // to not only grab it's parent's bus handler but to
+ // know where the child bus is so memory and io address
+ // assignments can be dynamically altered.
+ //
+ ChildData->Bus.CommonData.ParentSlot =
+ FpBusData->SlotNumber;
+
+ HDBG(DBG_PCI,
+ HalpDebugPrint("FpBusData->SlotNumber %x\n", FpBusData->SlotNumber););
+
+
+ //FpBusData->Bus.CommonData.ParentSlot;
+ }else{
+ HalpDebugPrint("Could Not find handler for bus %x\n",
+ BusNo+1);
+ }
+
+ //clear out any pending ints due to child bus scanning...
+ //
+ rPCIBusErrorCause = 0xffffffff;
+ FireSyncRegister();
+
+ HDBG(DBG_PCI,
+ HalpDebugPrint("--------------------------\n"););
+ } else {
+ HDBG(DBG_PCI,
+ HalpDebugPrint(" Don't go into bridge\n"););
+ }
+ }
+
+ if (PciData->BaseClass != 0x6) {
+ //
+ // this is not a bridge card so go ahead and fix the interrupt
+ // value for this device:
+ //
+ if ( CurrentBus->BusNumber != 0 ) {
+ PciData->u.type0.InterruptLine=(UCHAR)FpBusData->BusInt;
+ HalpWritePCIConfig(CurrentBus, // bus type
+ SlotNumber, // "Slot"
+ PciData, // data buffer,
+ 0, // Offset,
+ PCI_COMMON_HDR_LENGTH); // read first 64 bytes..
+
+ //
+ // Read it back in and make sure it is valid.
+ //
+ HalpReadPCIConfig(CurrentBus, // bus type
+ SlotNumber, // "Slot"
+ PciData, // data buffer,
+ 0, // Offset,
+ PCI_COMMON_HDR_LENGTH); // read first 64 bytes..
+
+ if ( PciData->u.type0.InterruptLine != FpBusData->BusInt ){
+ HalpDebugPrint("HalpScanPciBus: Line=%x, BusInt=%x\n",
+ PciData->u.type0.InterruptLine, FpBusData->BusInt );
+ }
+ }
+ }
+ if ( !(PciData->HeaderType & PCI_MULTIFUNCTION) ) {
+ //
+ // get out of here...
+ //
+ break;
+ }
+ } // .....for fns loop
+ } // .....for devs loop
+
+ ExFreePool(Buffer);
+
+ //
+ // Keith Son.
+ // Keep track the highest bus in the system.
+ //
+
+ return (Bus_Next_Number);
+}
+
+VOID HalpPCISynchronizeBridged (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Now block interruptions and make this transaction appear
+ // atomic with respect to any one else trying to access this
+ // bus and device (especially any other cpu ).
+ //
+ KeRaiseIrql (PROFILE_LEVEL, Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+
+ //
+ // Initialize PciCfg1
+ //
+
+ //
+ // The Bus Number must share the 8 bits with a bit of config address
+ // space. Namely, the physical address to access config space requires
+ // 9 bits. This means that only buses whose numbers are less than 128
+ // are available which shouldn't be a problem.
+ //
+ PciCfg1->u.AsULONG = 0;
+ //
+ // Limit bus totals to less than 128 buses:
+ PciCfg1->u.bits.BusNumber = ( (0x7f) & BusHandler->BusNumber);
+ PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PRNTPCI(HalpDebugPrint("HalpPCISynchronizeBridged: u.AsULONG: 0x%08x",
+ PciCfg1->u.AsULONG));
+
+ //
+ // add in base offset of pci config space's virtual address:
+ //
+ PciCfg1->u.AsULONG += (ULONG) HalpPciConfigBase;
+
+ //
+ // Setup the config space address for access...
+ //
+ RInterruptMask(GetCpuId()) &= ~(PCI_ERROR_INT); // block pci error ints.
+ WaitForRInterruptMask(GetCpuId());
+
+ PRNTPCI(HalpDebugPrint(" ->u.AsULONG: 0x%08x\n", PciCfg1->u.AsULONG));
+
+}
+
+VOID HalpPCIReleaseSynchronzationBridged (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ //rPCIStatus = 0xffff; // clear out any latent interrutps at bus
+ rPCIBusErrorCause = 0xffffffff; //clear out ints at the pending register...
+ FireSyncRegister();
+
+ RInterruptPending(GetCpuId()) |= PCI_ERROR_INT; // clear any pending ints.
+ RInterruptMask(GetCpuId()) |= PCI_ERROR_INT; // turn pci ints back on.
+ WaitForRInterruptMask(GetCpuId());
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+ //HalSweepIcache();
+ HalSweepDcache();
+
+}
+
+
+ULONG
+HalpPCIReadUcharBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ //PciCfg1->u.bits.Reserved1 = 0x1; // turn access into config cycle
+ rPCIConfigType |= PCI_TYPE1_CYCLE; // tell the system this is a type 1
+ // configuration access cycle.
+
+ FireSyncRegister();
+ *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfg1->u.AsULONG + i));
+ rPCIConfigType &= ~(PCI_TYPE1_CYCLE); // tell the system this is a type 1
+ FireSyncRegister();
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ //PciCfg1->u.bits.Reserved1 = 0x1; // turn access into config cycle
+ rPCIConfigType |= PCI_TYPE1_CYCLE; // tell the system this is a type 1
+ // configuration access cycle.
+
+ FireSyncRegister();
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT)(PciCfg1->u.AsULONG + i));
+ rPCIConfigType &= ~(PCI_TYPE1_CYCLE); // tell the system this is a type 1
+ FireSyncRegister();
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+
+ rPCIConfigType |= PCI_TYPE1_CYCLE; // tell the system pci config cycles
+ // will now be type 1 cycles.
+ FireSyncRegister();
+
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfg1->u.AsULONG));
+
+ rPCIConfigType &= ~(PCI_TYPE1_CYCLE); // tell the system config cycles
+ // will now be type 0 cycles.
+ FireSyncRegister();
+
+ return sizeof (ULONG);
+}
+
+ULONG
+HalpPCIWriteUcharBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ rPCIConfigType |= PCI_TYPE1_CYCLE; // tell the system this is a type 1
+ // configuration access cycle.
+ FireSyncRegister();
+
+ WRITE_PORT_UCHAR (PciCfg1->u.AsULONG + i, *Buffer );
+ rPCIConfigType &= ~(PCI_TYPE1_CYCLE); // tell the system this is a type 1
+ FireSyncRegister();
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ //PciCfg1->u.bits.Reserved1 = 0x1; // turn access into config cycle
+ rPCIConfigType |= PCI_TYPE1_CYCLE; // tell the system this is a type 1
+ // configuration access cycle.
+ FireSyncRegister();
+
+ WRITE_PORT_USHORT (PciCfg1->u.AsULONG + i, *((PUSHORT) Buffer) );
+ rPCIConfigType &= ~(PCI_TYPE1_CYCLE); // tell the system this is a type 1
+ FireSyncRegister();
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ rPCIConfigType |= PCI_TYPE1_CYCLE; // tell the system this is a type 1
+ // configuration access cycle.
+ FireSyncRegister();
+
+ WRITE_PORT_ULONG (PciCfg1->u.AsULONG, *((PULONG) Buffer) );
+ rPCIConfigType &= ~(PCI_TYPE1_CYCLE); // tell the system this is a type 1
+ FireSyncRegister();
+ return sizeof (ULONG);
+}
+
+VOID
+HalpInitIoBuses (
+ VOID
+ )
+{
+ ULONG BusNum, HwType;
+
+ //
+ // Initialize bus handling structures for the primary PCI bus in
+ // the system. We know the bus is there if this system is a top
+ // or pro. When other buses are added, a peer pci for example,
+ // there will need to be a search done on the config tree to find
+ // the first available one, hopefully I can tell which one is the
+ // boot pci path.
+ //
+ BusNum = 0;
+ HwType = 1; // our system most closely resembles the Type1
+ // config access model.
+
+ if ( HalpScanPciBus( HwType, BusNum, (PBUS_HANDLER) NULL ) ) {
+// HalpDebugPrint("HalpInitIoBuses: ScanPciBus returned non-zero: \n");
+ }
+
+}
+
+/*--
+ Routine: HalpAdjustBridge( PBUS_HANDLER, PPCI_COMMON_CONFIG )
+
+ Description:
+
+ Given the child bus and a device on that bus, make sure
+ the bridge servicing the bus is adequately setup. This means
+ checking the memory and io base and limit registers, the command
+ and status registers.
+
+ ChildBus This is the bus on the child's side of the bridge. It
+ should hold the parent slot so the bridge may be found
+ and read from or written to.
+
+ PrivData Private Data to the device under resource control. This
+ provides the data to figure out how the bridge should be
+ adjusted.
+--*/
+
+ULONG
+HalpAdjustBridge(PBUS_HANDLER ChildBus,
+ PPCI_COMMON_CONFIG PrivData,
+ PCM_RESOURCE_LIST CmList
+ )
+{
+ PFPHAL_BUSNODE FpBusData;
+ ULONG BaseAddress=0, DCount, Range, TopAddr=0, i;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR TmpDescr;
+ ULONG PciCommandFlag=0;
+ PCI_COMMON_CONFIG Buffer, *BridgeData;
+
+ BridgeData = &Buffer;
+
+ //
+ // Pull out the resources that should describe the device under assignment.
+ //
+ TmpDescr = CmList->List[0].PartialResourceList.PartialDescriptors;
+ DCount = CmList->List[0].PartialResourceList.Count;
+
+ //
+ // Find the device's memory needs
+ //
+ for (i=0; i<DCount; i++, TmpDescr++ ) {
+ switch (TmpDescr->Type) {
+ case CmResourceTypeMaximum:
+ i = DCount;
+ break;
+ case CmResourceTypeMemory:
+ PciCommandFlag |= PCI_ENABLE_MEMORY_SPACE;
+ if (BaseAddress == 0 ) {
+ Range = TmpDescr->u.Memory.Length;
+ BaseAddress = TmpDescr->u.Memory.Start.LowPart;
+ TopAddr = BaseAddress + TmpDescr->u.Memory.Length;
+ }
+ if (BaseAddress > TmpDescr->u.Memory.Start.LowPart) {
+ //
+ // set baseaddress to new low address
+ BaseAddress = TmpDescr->u.Memory.Start.LowPart;
+ }
+
+ //
+ // check that the new descriptor's range lies within
+ // the current TopAddr.
+ //
+ if ( (TmpDescr->u.Memory.Start.LowPart +
+ TmpDescr->u.Memory.Length ) > TopAddr ) {
+ TopAddr = TmpDescr->u.Memory.Start.LowPart +
+ TmpDescr->u.Memory.Length;
+ }
+ break;
+
+ case CmResourceTypePort:
+ PciCommandFlag |= PCI_ENABLE_IO_SPACE;
+ break;
+ case CmResourceTypeDeviceSpecific:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeDma:
+ default:
+ break;
+ }
+ }
+
+
+ //
+ // now read the bridges base and limit registers and compare
+ // the devices memory needs with the bridge's abilities to
+ // properly decode and pass through the proper memory ranges
+ //
+ FpBusData = (PFPHAL_BUSNODE) ChildBus->BusData;
+ if (FpBusData->Bus.CommonData.ParentSlot.u.AsULONG) {
+ HalpReadPCIConfig(ChildBus->ParentHandler, // bus type
+ FpBusData->Bus.CommonData.ParentSlot,
+ BridgeData, // data buffer,
+ 0, // Offset,
+ PCI_COMMON_HDR_LENGTH); // read first 64 words..
+ }
+
+ //
+ // If the bridge does not sufficiently cover the devices needs,
+ // adjust the limits and make sure the command register is properly
+ // set.
+
+ //
+ // Now write out the bridge's new data if any has changed.
+ //
+ return 0;
+}
+
+/*--
+ Routine: HalpInitPciBridgeConfig( ULONG )
+
+ Description:
+ To perform enough initialization of the bridge to allow
+ configuration scanning along the secondary bus to proceed. Ideally
+ setup bridge's config registers with initial state that will be
+ "pruned" by a call to HalpSetPciBridgeConfig.
+
+--*/
+
+ULONG
+HalpInitPciBridgeConfig( IN ULONG PrimaryBusNo,
+ IN OUT PPCI_COMMON_CONFIG PciData,
+ IN OUT PBUS_HANDLER PrimaryBus )
+{
+ PCI_SLOT_NUMBER Slot;
+ PFPHAL_BUSNODE FpNode=(PFPHAL_BUSNODE)PrimaryBus->BusData;
+ PPCI_COMMON_CONFIG TmpPciData;
+ PUCHAR Buffer;
+ ULONG slotNum;
+ BOOLEAN DecBridgeChip = FALSE;
+ BOOLEAN BridgeReconfig = FALSE;
+ ULONG DeviceSpecificSize = 0;
+ ULONG ChipConfigReg = 0;
+ ULONG TimerConfigReg = 0;
+ char buf[128];
+#if HALDEBUG_ON
+ ULONG i;
+#endif
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpInitPciBridgeConfig: 0x%x, 0x%08x, 0x%08x\n",
+ PrimaryBusNo, PciData, PrimaryBus););
+ //
+ // Print out the incoming common config data...
+ PRINTBRIDGE(PciData);
+
+ // We have been passed the PciData for a bridge chip; before we go any
+ // further, determine if it is DEC bridge, because we need to do some
+ // fix-ups if it is.
+ if( PciData->VendorID == DEC_BRIDGE_CHIP) {
+ DecBridgeChip = TRUE;
+ DeviceSpecificSize = 8;
+ // On POWERSERVE (TX platform) we MUST disable write posting from
+ // the DEC bridge.
+ if (SystemType == SYS_POWERSERVE) {
+ BridgeReconfig = TRUE;
+ ChipConfigReg = 0x00000006;
+ }
+ // Check for NVRAM reconfig values
+ if (HalGetEnvironmentVariable("DECCHIPCONFIGREG", sizeof(buf), buf)
+ == ESUCCESS) {
+ BridgeReconfig = TRUE;
+ ChipConfigReg = atoi(buf);
+ }
+ if (HalGetEnvironmentVariable("DECTIMERCONFIGREG", sizeof(buf), buf)
+ == ESUCCESS) {
+ BridgeReconfig = TRUE;
+ TimerConfigReg = atoi(buf);
+ }
+ }
+
+ Buffer = ExAllocatePool (PagedPool, 1024);
+ TmpPciData = (PPCI_COMMON_CONFIG) Buffer;
+ TmpPciData->VendorID = 0xffff;
+ TmpPciData->u.type1.InterruptLine = 0xff;
+
+ Slot.u.AsULONG=FpNode->SlotNumber.u.AsULONG;
+
+#if HALDEBUG_ON
+ PRNTPCI(HalpDebugPrint("%s ", TBS));
+ for (i=0; i<DeviceSpecificSize - 4; i += 4) {
+ PRNTPCI(HalpDebugPrint("0x%08x, ", PciData->DeviceSpecific[i]));
+ }
+ PRNTPCI(HalpDebugPrint("0x%08x\n", PciData->DeviceSpecific[i]));
+#endif
+
+ //
+ // Enable commands in the command register address in first 64 bytes.
+ // For example, turn on bus mastering,
+ //
+ PciData->Command = PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+
+ //
+ // Keith Son.
+ // Please do not change the order of assignment.
+ // I am using the PrimaryBus variable as a passed in value.
+ // The value is the parent bus number.
+ //
+ PciData->u.type1.SecondaryBus = PciData->u.type1.PrimaryBus + 1;
+ PciData->u.type1.PrimaryBus = (UCHAR) PrimaryBusNo;
+ PciData->u.type1.SubordinateBus = 0xff; // for now, prune on way back..
+ PciData->u.type1.SecondaryStatus = 0xff;
+ PciData->Status = 0xff;
+ slotNum = Slot.u.bits.DeviceNumber;
+ if (slotNum > MAXIMUM_PCI_SLOTS) {
+ HalpDebugPrint("HalpInitPciBridgeConfig:");
+ HalpDebugPrint(" ILLEGAL SLOT NUMBER %d\n", slotNum);
+ return 0; // add in status on return later...
+ }
+ // This can be INVALID_INT
+ PciData->u.type1.InterruptLine = PciDevicePrimaryInts[slotNum];
+ PRNTPCI(HalpDebugPrint("slot=%x\n",
+ Slot.u.bits.DeviceNumber));
+
+
+ //
+ // Keith Son.
+ // Right now we are support four peer level.
+ // Split the resource even for peer level.
+ //
+ if ( PciData->u.type1.SecondaryBus == 4 )
+ {
+ PciData->u.type1.MemoryBase = 0x2000; // for now!!
+ PciData->u.type1.MemoryLimit= 0x2050; // for now!!
+ PciData->u.type1.IOBase = 0xa0; // for now!!
+ PciData->u.type1.IOLimit= 0xa0; // for now!!
+
+ }
+ else if ( PciData->u.type1.SecondaryBus ==3)
+ {
+ PciData->u.type1.MemoryBase = 0x2060; // for now!!
+ PciData->u.type1.MemoryLimit= 0x2bf0; // for now!!
+ PciData->u.type1.IOBase = 0xb0; // for now!!
+ PciData->u.type1.IOLimit= 0xb0; // for now!!
+
+ }
+
+
+ else if ( PciData->u.type1.SecondaryBus == 2)
+ {
+ PciData->u.type1.MemoryBase = 0x2c00; // for now!!
+ PciData->u.type1.MemoryLimit= 0x31f0; // for now!!
+ PciData->u.type1.IOBase = 0xe0; // for now!!
+ PciData->u.type1.IOLimit= 0xe0; // for now!!
+
+ }
+
+ else
+ {
+ PciData->u.type1.MemoryBase = 0x3200; // for now!!
+ PciData->u.type1.MemoryLimit= 0x3800; // for now!!
+ PciData->u.type1.IOBase = 0xc0; // for now!!
+ PciData->u.type1.IOLimit= 0xc0; // for now!!
+
+ }
+
+
+ //PciData->Command = 0; // this disables everything?!
+ PciData->u.type1.BridgeControl = 0; // this disables bridge activity!
+
+ //
+ // Print out the modified common config data...
+ PRINTBRIDGE(PciData);
+
+ HalpWritePCIConfig (PrimaryBus, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET;
+ HalpWritePCIConfig (PrimaryBus, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ KeStallExecutionProcessor(100); // wait for 100 microseconds
+
+ PciData->u.type1.BridgeControl = 0x0000;
+
+ //
+ // Write out new config parameters, and read back in to do some sanity
+ // checking....
+ //
+ HalpWritePCIConfig (PrimaryBus, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ if ((DecBridgeChip == TRUE) && (BridgeReconfig == TRUE)) {
+ PULONG ptr;
+ // Re-program the DEC device specific registers
+ HalpReadPCIConfig (PrimaryBus, Slot, TmpPciData, 0,
+ PCI_COMMON_HDR_LENGTH+DeviceSpecificSize);
+ ptr = (PULONG)&PciData->DeviceSpecific[0];
+ *ptr++ = ChipConfigReg;
+ *ptr = TimerConfigReg;
+ HalpWritePCIConfig (PrimaryBus, Slot, PciData, 0,
+ PCI_COMMON_HDR_LENGTH+DeviceSpecificSize);
+ }
+
+ HalpReadPCIConfig (PrimaryBus, Slot, TmpPciData, 0,
+ PCI_COMMON_HDR_LENGTH+DeviceSpecificSize);
+ if ( TmpPciData->u.type1.SecondaryBus != PciData->u.type1.SecondaryBus ){
+ HalpDebugPrint("HalpInitPciBridgeConfig: Read no matchee Write!!\n");
+ }
+ //
+ // Print out the New common config data...
+ PRINTBRIDGE(TmpPciData);
+#if HALDEBUG_ON
+ PRNTPCI(HalpDebugPrint("%s ", TBS));
+ for (i=0; i<DeviceSpecificSize - 4; i += 4) {
+ PRNTPCI(HalpDebugPrint("0x%08x, ", PciData->DeviceSpecific[i]));
+ }
+ PRNTPCI(HalpDebugPrint("0x%08x\n", PciData->DeviceSpecific[i]));
+#endif
+
+ ExFreePool(Buffer);
+
+ return 1;
+
+}
+
+ULONG
+HalpConfigurePcmciaBridge(ULONG ParentBusNo )
+{
+ PRNTGENRL(HalpDebugPrint("HalpConfigurePcmciaBridge: 0x%x\n",ParentBusNo));
+
+ return 0;
+}
+
+/*++
+ Routine: ULONG HalpGetPciInterruptSlot(PBUS_HANDlER , PCI_SLOT )
+
+ Description:
+
+ Given a bus ( bus handler ) and a slot on the bus, find the slot value
+ directly connected to a system interrupt ( I.E. a slot without an inter-
+ vening bridge ).
+
+ Return:
+ Returns a slot value disguised as a ULONG.
+
+--*/
+
+ULONG
+HalpGetPciInterruptSlot(PBUS_HANDLER BusHandler, PCI_SLOT_NUMBER PciSlot )
+{
+ PFPHAL_BUSNODE FpNode;
+ PBUS_HANDLER TmpBus=0;
+
+
+ FpNode = (PFPHAL_BUSNODE)BusHandler->BusData;
+ TmpBus = BusHandler;
+
+
+ //
+ // Keith Son.
+ // Rewrote this function to support peer level buses.
+ // Find the root bus and return the bridge slot on the root bus level.
+ //
+
+ PRNTPCI(HalpDebugPrint("parent busnumber = 0x%x, \n",FpNode->Bus.ParentBus));
+
+
+ PRNTPCI(HalpDebugPrint("BusHandler = 0x%x, slot = %x\n", BusHandler, PciSlot));
+
+
+ TmpBus = BusHandler->ParentHandler ;
+
+ PRNTPCI(HalpDebugPrint("BusNumber = 0x%x, \n",TmpBus->BusNumber));
+
+ PRNTPCI(HalpDebugPrint("aslong = 0x%x, \n",FpNode->Bus.CommonData.ParentSlot.u.AsULONG));
+
+
+ while( (TmpBus) && ( TmpBus->BusNumber != 0)) {
+ PRNTPCI(HalpDebugPrint("aslong = 0x%x, \n",FpNode->Bus.CommonData.ParentSlot.u.AsULONG));
+
+ FpNode = (PFPHAL_BUSNODE)TmpBus->BusData;
+ TmpBus = TmpBus->ParentHandler;
+
+ }
+
+ return (FpNode->SlotNumber.u.AsULONG);
+
+
+}
+
+/*++
+ Routine: HalpStatSlot()
+
+ Description:
+
+ Given a known device ( slot ), "stat" the slot to discover
+ particular information such as memory/io space requirements,
+ vendor/device ids, device types, etc.
+
+ Also, create a range description of this device to pass back
+ to the bus scan routine for inclusion into the bus resource
+ description.
+
+
+--*/
+
+ULONG
+HalpStatSlot(
+ IN PPCI_COMMON_CONFIG StatData,
+ IN PBUS_HANDLER ThisBus,
+ IN PCI_SLOT_NUMBER Slot,
+ OUT PSUPPORTED_RANGES pRanges
+ )
+{
+ PPCI_COMMON_CONFIG NewData;
+ PUCHAR Buffer;
+ ULONG Addr, Length, Limit, Index;
+
+ Buffer = ExAllocatePool (PagedPool, 1024);
+ NewData = (PPCI_COMMON_CONFIG) Buffer;
+ RtlCopyMemory((PVOID)NewData, (PVOID)StatData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // setup the NewData to probe memory and io space requirements for the
+ // device. Write those registers to all 'f's and read back resource needs.
+ //
+ for( Addr=0; Addr < PCI_TYPE0_ADDRESSES; Addr++ ) {
+ NewData->u.type0.BaseAddresses[Addr] = 0xffffffff;
+ }
+
+ NewData->u.type0.ROMBaseAddress = 0xffffffff & ~(PCI_ROMADDRESS_ENABLED);
+ NewData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+
+ HalpWritePCIConfig( ThisBus, Slot, NewData, 0, PCI_COMMON_HDR_LENGTH );
+ HalpReadPCIConfig( ThisBus, Slot, NewData, 0, PCI_COMMON_HDR_LENGTH );
+
+ for( Index=0; Index < PCI_TYPE0_ADDRESSES; Index++ ) {
+
+ Addr = NewData->u.type0.BaseAddresses[Index];
+ Length = ( Addr & ( ~(Addr & 0xfffffff0) << 1 ));
+ Limit = ( Addr & ( 0x80000000 | (~(Addr & 0xfffffff0) >> 1 )));
+
+ switch( Addr & 0x00000003 ) {
+
+ case PCI_IO_ADDRESS:
+ ThisBus->BusAddresses->NoIO++;
+ break;
+
+ default:
+ ThisBus->BusAddresses->NoMemory++;
+ break;
+ }
+ }
+
+
+ // HalpCreateRangeFromPciData();
+
+ //
+ // Restore the device to it's original settings.
+ //
+ HalpWritePCIConfig( ThisBus, Slot, StatData, 0, PCI_COMMON_HDR_LENGTH );
+
+ return 1;
+}
diff --git a/private/ntos/nthals/halfire/ppc/fppcisup.h b/private/ntos/nthals/halfire/ppc/fppcisup.h
new file mode 100644
index 000000000..fb15495ae
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fppcisup.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fppcisup.h $
+ * $Revision: 1.2 $
+ * $Date: 1996/01/11 08:38:36 $
+ * $Locker: $
+ *
+ */
+
+#define TBS " "
+
+ULONG
+HalpStatSlot(
+ IN PPCI_COMMON_CONFIG StatData,
+ IN PBUS_HANDLER ThisBus,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ OUT PSUPPORTED_RANGES pRanges
+ );
+
+ULONG
+HalpAdjustBridge(
+ PBUS_HANDLER ChildBus,
+ PPCI_COMMON_CONFIG PrivData,
+ PCM_RESOURCE_LIST CmList
+ );
+
+ULONG
+HalpConfigurePcmciaBridge(
+ IN ULONG ParentBusNo
+ );
+
+ULONG
+HalpInitPciBridgeConfig(
+ IN ULONG ParentBusNo,
+ IN OUT PPCI_COMMON_CONFIG,
+ IN OUT PBUS_HANDLER ParentBus
+ );
+
+VOID
+HalpInitIoBuses (
+ VOID
+ );
+
+VOID HalpPCISynchronizeBridged (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationBridged (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortBridged (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpGetPciInterruptSlot(
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER PciSlot
+ );
+
+PCI_CONFIG_HANDLER PCIConfigHandlerBridged = {
+ HalpPCISynchronizeBridged,
+ HalpPCIReleaseSynchronzationBridged,
+ {
+ HalpPCIReadUlongBridged, // 0
+ HalpPCIReadUcharBridged, // 1
+ HalpPCIReadUshortBridged // 2
+ },
+ {
+ HalpPCIWriteUlongBridged, // 0
+ HalpPCIWriteUcharBridged, // 1
+ HalpPCIWriteUshortBridged // 2
+ }
+};
+
+
+typedef struct ABusInfo {
+ struct ABusInfo *ParentBus;
+ struct ABusInfo *ChildBus;
+ struct ABusInfo *PeerBus;
+ ULONG PeerCount;
+ ULONG ChildCount;
+} BUSINFO, PBUSINFO;
+
+extern KSPIN_LOCK HalpPCIConfigLock;
+
+//
+// scan within a bus for devices, accumulating info. Keep track of
+// devices on current bus, how deep you are, who the parents are.
+//
+ULONG HalpScanPciBus(ULONG HwType, ULONG BusNo, PBUS_HANDLER ParentBus);
+
+
+//
+// Once a bus is fully known, then setup all the devs on the bus:
+//
+ULONG HalpInitPciBus(ULONG BusNo, PULONG ParentBus, PULONG CurrentBus);
+
diff --git a/private/ntos/nthals/halfire/ppc/fpproto.h b/private/ntos/nthals/halfire/ppc/fpproto.h
new file mode 100644
index 000000000..90f7ae0c2
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpproto.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpproto.h $
+ * $Revision: 1.1 $
+ * $Date: 1996/04/30 23:25:58 $
+ * $Locker: $
+ */
+
+
+#ifndef FPPROTO_H
+#define FPPROTO_H
+
+char * FpStrtok ( char * string, const char * control );
+
+#endif //FPPROTO_H
diff --git a/private/ntos/nthals/halfire/ppc/fpreg.h b/private/ntos/nthals/halfire/ppc/fpreg.h
new file mode 100644
index 000000000..70af4feb3
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fpreg.h
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fpreg.h $
+ * $Revision: 1.19 $
+ * $Date: 1996/05/14 02:32:57 $
+ * $Locker: $
+ */
+
+#ifndef FPREG_H
+#define FPREG_H
+
+#define MAX_SYSTEM_CPU_NUM 2
+//
+// This file contains all of the definitions for the FirePower Control
+// registers. C code needing to access these registers should include this
+// file. If future boards differ from these definitions, we should move
+// the contents of this file into a board specific file, but still
+// have c code include fpreg.h
+//
+
+//
+// This is a variable that when set contains the virtual address of
+// where the system registers were mapped
+//
+extern PVOID HalpSystemRegisterBase;
+
+//
+// Code to write to a safe place (generate external bus cycle to work
+// around the TSC bug).
+//
+extern ULONG SafePlace;
+#define WriteSafePlace() \
+ SafePlace = 0x0; \
+ HalSweepDcacheRange(&SafePlace, 8);
+
+//
+// The following routine should be called whenever the order of writes
+// to a control register needs to be guaranteed.
+//
+#define FireSyncRegister() \
+ __builtin_eieio() ;
+ // __builtin_sync();
+
+//
+// After all writes to the Tsc registers, the system needs to
+// generate an off chip write request.
+//
+#define FireTscSyncRegister() \
+ WriteSafePlace(); \
+ KeFlushWriteBuffer();
+
+//
+// The following macro handles the conversion from BigEndian to LittleEndian
+// This is current setup as a compile time handling but could easily be'
+// made dynamic.
+//
+// Note: The following is the proper definition for Endianess but
+// it causes the Motorola Compiler to go nuts.
+//
+// #ifdef BIGENDIAN
+// #define _BE 1
+// #else
+// #define _BE 0
+// #endif
+//
+// #define _ENDIAN(_X) ((int)(_X) + (int)((_BE)?0:4))
+#ifdef BIGENDIAN
+#define _ENDIAN(_X) ((ULONG)_X + 0)
+#else
+// the NT is running in little endian mode.
+// The following conversion macro can be used only with
+// the addresses at double word boundary and in ASIC.
+// It is not required for the memory accesses.
+#define _ENDIAN(_X) ((ULONG)_X + 4)
+#endif
+
+//
+// These defines provide the mapping to turn an offset into
+// a pointer to the 32 bit register.
+//
+
+#define _SYSBASE ((PUCHAR)HalpSystemRegisterBase)
+#define _REG(_OFFSET) (*(volatile ULONG * const)(_ENDIAN(_SYSBASE + (_OFFSET))))
+#define _ADDR(_OFFSET) (_ENDIAN(_SYSBASE + (_OFFSET)))
+
+//
+// Register definitions with appropriate bit field defintions below.
+// Defines are used because not all of the compilers can be trusted
+// to treat bit field definitions correctly for this architecture.
+//
+#define rInterruptRequest _REG( 0x000000 )
+#define rInterruptRequestSet _REG( 0x000008 )
+#define rInterruptMask0 _REG( 0x000100 )
+#define rInterruptMask1 _REG( 0x000108 )
+#define rInterruptMask2 _REG( 0x000110 )
+#define rInterruptMask3 _REG( 0x000118 )
+#define rInterruptPending0 _REG( 0x000200 )
+#define rInterruptPending1 _REG( 0x000208 )
+#define rInterruptPending2 _REG( 0x000210 )
+#define rInterruptPending3 _REG( 0x000218 )
+#define rCPUMessageInterrupt _REG( 0x000300 )
+#define rCPUMessageInterruptSet _REG( 0x000308 )
+#define rPCIBusErrorCause _REG( 0x000400 )
+#define rPCIBusErrorCauseSet _REG( 0x000408 )
+#define rPCIBusErrorAddressRegister _REG( 0x000410 )
+#define rCPUBusErrorCause _REG( 0x000800 )
+#define rCPUBusErrorCauseSet _REG( 0x000808 )
+#define rCPUBusErrorAddressRegister _REG( 0x000810 )
+#define rErrorStatus0 _REG( 0x001000 )
+#define rErrorStatus0Set _REG( 0x001008 )
+#define rErrorMask _REG( 0x001010 )
+#define rErrorAddr0 _REG( 0x001120 )
+#define rErrorAddr1 _REG( 0x001128 )
+#define rErrorAddr2 _REG( 0x001130 )
+#define rErrorAddr3 _REG( 0x001138 )
+#define rVidInt _REG( 0x001140 )
+#define rVidIntSet _REG( 0x001148 )
+#define rVidIntMask _REG( 0x001150 )
+#define rTscControl _REG( 0x100000 )
+#define rFbControl _REG( 0x100008 )
+#define rEsccControl _REG( 0x100010 )
+#define rEsccL2FLush _REG( 0x100018 )
+#define rScratchPad0 _REG( 0x100020 )
+#define rScratchPad1 _REG( 0x100028 )
+#define rScratchPad2 _REG( 0x100030 )
+#define rLowPowerControl _REG( 0x100080 )
+#define rRomControl _REG( 0x100100 )
+#define rTscStatus0 _REG( 0x100200 )
+#define rTscRevision _REG( 0x100300 )
+#define rMemBank0Config _REG( 0x100400 )
+#define rMemBank1Config _REG( 0x100408 )
+#define rMemBank2Config _REG( 0x100410 )
+#define rMemBank3Config _REG( 0x100418 )
+#define rMemBank4Config _REG( 0x100420 )
+#define rMemBank5Config _REG( 0x100428 )
+#define rMemBank6Config _REG( 0x100430 )
+#define rMemBank7Config _REG( 0x100438 )
+#define rMemDramTiming _REG( 0x100500 )
+#define rMemVramTiming _REG( 0x100508 )
+#define rMemRefresh _REG( 0x100510 )
+#define rVidControl _REG( 0x100518 )
+#define rVidPixelsPerLineLo _REG( 0x100520 )
+#define rVidPixelsPerLineHi _REG( 0x100528 )
+#define rIOControl _REG( 0x101000 )
+#define rPCIConfigType _REG( 0x101100 )
+#define rPIOPendingCount _REG( 0x101200 )
+#define rDMAPendingCount _REG( 0x101300 )
+#define rPCIVendorID _REG( 0x400100 )
+#define rPCIDeviceID _REG( 0x400108 )
+#define rPCICommand _REG( 0x400110 )
+#define rPCIStatus _REG( 0x400118 )
+#define rPCIRevisionID _REG( 0x400120 )
+#define rPCIClassCode _REG( 0x400128 )
+#define rPCIHeaderType _REG( 0x400140 )
+
+
+//
+// Addrs non-dereferenced register declarations
+//
+#define rInterruptMask _ADDR(0x000100)
+#define rInterruptPending _ADDR(0x000200)
+//#define memCpuMailBox _ENDIAN(0x80002F80)
+#define memCpuMailBox 0x80002F80
+//
+// Use the value of the last defines register
+//
+#define NBPG 4096
+#define roundup(_X, _Y) (((_X) + ((_Y)-1)) / (_Y))
+#define btorp(_X) (roundup((_X), NBPG) )
+#define REGISTER_PAGES (btorp(0x400140))
+
+
+//
+// Place Macros/Masks/Bit Definitions in this area for each of the
+// control registers.
+//
+
+// rInterruptRequest
+// rInterruptRequestSet
+
+// rInterruptMask0
+// rInterruptMask1
+// rInterruptMask2
+// rInterruptMask3
+
+#define RInterruptMask(_CPU) \
+ (*(volatile ULONG * const)(rInterruptMask + (ULONG)((_CPU) << 3)))
+ //(*(volatile ULONG * const)(rInterruptMask + ((_CPU) * 8)))
+
+#define RInterruptPending(_CPU) \
+ (*(volatile ULONG * const)(rInterruptPending + ((_CPU) * 8)))
+
+//
+// To guarantee that the Mask write is complete we must insure that:
+// a) the ordering does not change and b) the all pending reads are
+// complete before we continue. Since we are reading the address
+// we write, the processor will not re-order the read/write. We
+// must use a "sync" to guarantee that the EE bit is not set
+// until after the data from the read of RInterruptMask returns.
+//
+#define WaitForRInterruptMask(_CPU) \
+ { \
+ volatile ULONG dummyVar; \
+ FireSyncRegister(); \
+ dummyVar = RInterruptMask(_CPU);\
+ __builtin_sync(); \
+ }
+
+
+#define MemSetCpuAddr(_CPU) \
+ (*(volatile ULONG * const)( memCpuMailBox + ( (( _CPU ) * 8 ) + 0x4 )))
+
+#define MemStartCpu(_CPU) \
+ (*(volatile ULONG * const)( memCpuMailBox + (( _CPU ) * 8 )))
+
+#define ALL_INTS_OFF 0x00000000
+#define ALL_INTS_ON 0xffffffff
+
+#define CPU_MESSAGE_NUM 31
+#define MEMORY_ERROR_VIDEO_NUM 30
+#define PCI_ERROR_NUM 29
+#define CPU_BUS_ERROR_NUM 28
+#define SIO_NMI_NUM 27
+
+#define LX_PCI_SLOT_0_NUM 26
+#define LX_PCI_SLOT_1_NUM 25
+#define LX_PCI_SLOT_2_NUM 24
+#define LX_PCI_SLOT_3_NUM 23
+#define LX_PCI_IDE_INTA_NUM 22
+#define LX_PCI_IDE_INTB_NUM 21
+
+#define ENET_NUM 26
+#define SCSI_NUM 25
+#define PCI_SLOT_1_NUM 23
+#define PCI_SLOT_0_NUM 22
+#define SOFTWARE0_NUM 19
+#define SOFTWARE1_NUM 18
+#define SOFTWARE2_NUM 17
+#define SOFTWARE3_NUM 16
+#define ISA_PIND06_NUM 15
+#define ISA_PIND07_NUM 14
+#define MOUSE_NUM 12
+#define ISA_PIND04_NUM 11
+#define AUDIO_NUM 10
+#define ISA_PINB04_NUM 9
+#define RTC_NUM 8
+#define PARALLEL_NUM 7
+#define FLOPPY_NUM 6
+#define DISPLAY_NUM 5
+#define SERIAL1_NUM 4
+#define SERIAL2_NUM 3
+#define KEYBOARD_NUM 1
+#define TIMER_NUM 0
+
+#define NUM_2_INT(x) (1 << x )
+
+#define CPU_MESSAGE_INT NUM_2_INT( CPU_MESSAGE_NUM )
+#define MEMORY_ERROR_VIDEO_INT NUM_2_INT( MEMORY_ERROR_VIDEO_NUM )
+#define PCI_ERROR_INT NUM_2_INT( PCI_ERROR_NUM )
+#define CPU_BUS_ERROR_INT NUM_2_INT( CPU_BUS_ERROR_NUM )
+#define SIO_NMI_INT NUM_2_INT( SIO_NMI_NUM )
+
+#define LX_PCI_SLOT_0_INT NUM_2_INT( LX_PCI_SLOT_0_NUM )
+#define LX_PCI_SLOT_1_INT NUM_2_INT( LX_PCI_SLOT_1_NUM )
+#define LX_PCI_SLOT_2_INT NUM_2_INT( LX_PCI_SLOT_2_NUM )
+#define LX_PCI_SLOT_3_INT NUM_2_INT( LX_PCI_SLOT_3_NUM )
+#define LX_PCI_IDE_INTA_INT NUM_2_INT( LX_PCI_IDE_INTA_NUM )
+#define LX_PCI_IDE_INTB_INT NUM_2_INT( LX_PCI_IDE_INTB_NUM )
+
+#define ENET_INT NUM_2_INT( ENET_NUM )
+#define SCSI_INT NUM_2_INT( SCSI_NUM )
+#define PCI_SLOT_1_INT NUM_2_INT( PCI_SLOT_1_NUM )
+#define PCI_SLOT_0_INT NUM_2_INT( PCI_SLOT_0_NUM )
+#define SOFTWARE0_INT NUM_2_INT( SOFTWARE0_NUM )
+#define SOFTWARE1_INT NUM_2_INT( SOFTWARE1_NUM )
+#define SOFTWARE2_INT NUM_2_INT( SOFTWARE2_NUM )
+#define SOFTWARE3_INT NUM_2_INT( SOFTWARE3_NUM )
+#define ISA_PIND06_INT NUM_2_INT( ISA_PIND06_NUM )
+#define ISA_PIND07_INT NUM_2_INT( ISA_PIND07_NUM )
+#define MOUSE_INT NUM_2_INT( MOUSE_NUM )
+#define ISA_PIND04_INT NUM_2_INT( ISA_PIND04_NUM )
+#define AUDIO_INT NUM_2_INT( AUDIO_NUM )
+#define ISA_PINB04_INT NUM_2_INT( ISA_PINB04_NUM )
+#define RTC_INT NUM_2_INT( RTC_NUM )
+#define PARALLEL_INT NUM_2_INT( PARALLEL_NUM )
+#define FLOPPY_INT NUM_2_INT( FLOPPY_NUM )
+#define DISPLAY_INT NUM_2_INT( DISPLAY_NUM )
+#define SERIAL1_INT NUM_2_INT( SERIAL1_NUM )
+#define SERIAL2_INT NUM_2_INT( SERIAL2_NUM )
+#define KEYBOARD_INT NUM_2_INT( KEYBOARD_NUM )
+#define TIMER_INT NUM_2_INT( TIMER_NUM )
+
+
+#define ALL_BITS_CLEAR 0xffffffff
+#define ENABLE_EISA_MASK 0x0000ffff
+#define SET_INTS_CLEAR 0xffffffff
+#define EISA_INTS_ON 0xffff0000
+#define SCSI_EISA_INT 0x00002000
+
+
+
+// rInterruptPending0
+// rInterruptPending1
+// rInterruptPending2
+// rInterruptPending3
+// rCPUMessageInterrupt
+// rCPUMessageInterruptSet
+
+
+// rPCIBusErrorCause
+// rPCIBusErrorCauseSet
+#define PCI_ERROR_SIGNALED_SYS 0x00000001
+#define PCI_ERROR_DATA_PARITY 0x00000002
+#define PCI_ERROR_DEV_TIMEOUT 0x00000004
+#define PCI_ERROR_TARGET_ABORT 0x00000008
+
+// rPCIBusErrorAddressRegister
+// rCPUBusErrorCause
+#define CPU_ERROR_ILLEGAL_SAACC 0x00000001
+#define CPU_ERROR_ADDR_PARITY 0x00000002
+#define CPU_ERROR_DISCONTIG_ISA 0x00000004
+
+// rCPUBusErrorCauseSet
+// rCPUBusErrorAddressRegister
+// rErrorStatus0
+#define ERROR_ECC_CORRECTED 0x02000000
+#define ERROR_ECC_FAILED 0x04000000
+#define ERROR_ADDR_PARITY 0x08000000
+#define ERROR_DATA_PARITY 0x10000000
+#define ERROR_MEM_PARITY 0x20000000
+#define ERROR_INVALID_XACT 0x40000000
+
+// rErrorStatus0Set
+// rErrorMask
+#define ECC_CORRECTED 0x02000000
+#define ECC_FAILED 0x04000000
+#define ADDRESS_PARITY_ERROR 0x08000000
+#define DATA_PARITY_ERROR 0x10000000
+#define MEM_PARITY_ERROR 0x20000000
+#define INVALID_XACT 0x40000000
+
+// rErrorAddr0
+// rErrorAddr1
+// rErrorAddr2
+// rErrorAddr3
+// rVidInt
+// rVidIntSet
+// rVidIntMask
+// rTscControl
+#define L2_PRESENT 0x01000000
+#define MP_CONFIG 0x04000000
+#define ECC_ENABLE 0x08000000
+#define LITTLE_ENDIAN 0x10000000
+#define BRIDGE_MODE 0x20000000
+
+// rFbControl
+#define CPU_VRAM_SWAP_BYTES 0x01000000
+#define CPU_VRAM_ADDR_MUNGE 0x02000000
+#define CPU_INVERT_FB_ADDR_LSB 0x04000000
+#define PCI_VRAM_SWAP_BYTES 0x08000000
+#define PCI_VRAM_SWAP_ENABLES 0x10000000
+#define PCI_INVERT_FB_ADDR2 0x20000000
+
+// rEsccControl
+// rEsccL2FLush
+// rScratchPad0
+// rScratchPad1
+// rScratchPad2
+// rLowPowerControl
+// rRomControl
+// rTscStatus0
+#define ROM_BUSY 0x00000001
+#define WRQ_FULL 0x00000002
+#define I2Q_FULL 0x00000004
+#define WRQ_EMPTY 0x00000008
+#define I2Q_EMPTY 0x00000010
+//#define CPU_MASK 0x000000c0
+#define CPU_MASK 0xc0000000
+#define GetCpuId() ((rTscStatus0 & CPU_MASK) >> 30)
+
+// rTscRevision
+// rMemBank0Config
+// rMemBank1Config
+// rMemBank2Config
+// rMemBank3Config
+// rMemBank4Config
+// rMemBank5Config
+// rMemBank6Config
+// rMemBank7Config
+// rMemDramTiming
+// rMemVramTiming
+// rMemRefresh
+// rVidControl
+// rVidPixelsPerLineLo
+// rVidPixelsPerLineHi
+// rIOControl
+// rPCIConfigType
+#define PCI_TYPE1_CYCLE 0x00000001
+
+// rPIOPendingCount
+#define PENDING_COUNTMASK 0x0000007f
+#define PCI_BRIDGE_MODE 0x00000080
+
+// rDMAPendingCount
+// rPCIVendorID
+// rPCIDeviceID
+// rPCICommand
+// rPCIStatus
+#define PCI_DATA_PARITY_ERROR 0x00008000
+#define PCI_SIGNLD_SYSTEM_ERR 0x00004000
+#define PCI_RCVD_MASTER_ABORT 0x00002000
+#define PCI_RCVD_TARGET_ABORT 0x00001000
+#define PCI_SGNLD_TARGET_ABORT 0x00000800
+#define PCI_DATA_PARITY_DETECT 0x00000100
+
+// rPCIRevisionID
+// rPCIClassCode
+// rPCIHeaderType
+
+#endif // FPREG_H
diff --git a/private/ntos/nthals/halfire/ppc/fprgstry.c b/private/ntos/nthals/halfire/ppc/fprgstry.c
new file mode 100644
index 000000000..846ecb301
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/fprgstry.c
@@ -0,0 +1,871 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: fprgstry.c $
+ * $Revision: 1.40 $
+ * $Date: 1996/05/14 02:33:02 $
+ * $Locker: $
+ */
+
+/* mogawa
+ * HalpInitializeRegistry fails if it is put in HalInitSystem().
+ * So I moved it in HalReportResourceUsage(VOID) in pxpro.c.
+ * Still L"\\Registry\\Machine\\Software\\FirePower" can not be used.
+ * L"\\Registry\\Machine\\Hardware\\FirePower" can be created successfully.
+ */
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxpcisup.h"
+#include "phsystem.h"
+#include "stdio.h"
+#include "string.h"
+#include "fpdebug.h"
+#include "fparch.h"
+#include "fpi2c.h"
+#include "fpcpu.h"
+
+#define TBS " "
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+extern WCHAR rgzSystem[];
+extern WCHAR rgzSoftwareDescriptor[];
+extern WCHAR rgzFirePOWERNode[];
+extern WCHAR rgzCpuNode[];
+extern WCHAR rgzHalNode[];
+extern WCHAR rgzVeneerNode[];
+extern WCHAR rgzFirmwareNode[];
+extern NTSTATUS RtlCharToInteger ( PCSZ String, ULONG Base, PULONG Value );
+extern ULONG CpuClockMultiplier;
+extern ULONG ProcessorBusFrequency;
+extern ULONG TimeBaseCount;
+extern ULONG HalpPerformanceFrequency;
+
+
+BOOLEAN HalpInitializeRegistry (IN PLOADER_PARAMETER_BLOCK LoaderBlock);
+VOID HalpTranslateSystemSpecificData ( VOID );
+VOID HalpSetUpFirePowerRegistry(VOID);
+VOID HalpSetUpSystemBiosKeys( VOID );
+
+/* unfortunately the following data must be stored somewhere
+ * because it is not possible to get these data except when HalinitSystem.
+ * Registry does not exist when HalInitSystem.
+ */
+#define FIRMWARE_BUF_SIZE 64
+static char firmwareBuf[FIRMWARE_BUF_SIZE];
+static char veneerBuf[64];
+static ULONG FirstLevelIcacheSize;
+static ULONG FirstLevelDcacheSize;
+static ULONG SecondLevelCacheSize;
+
+VOID
+HalpTranslateSystemSpecificData ( VOID)
+{
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status = STATUS_SEVERITY_INFORMATIONAL;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ WCHAR wstr[8];
+ ULONG i, junk;
+ PPCI_REGISTRY_INFO PCIRegInfo = NULL;
+
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+
+ //
+ // Search the hardware description looking for the cpu node:
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzCpuNode);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY, HalpDebugPrint("HalpTranslateSystemSpecificData: ");
+ HalpDebugPrint("ZwOpenKey returned !NT_SUCCESS \n"));
+ return;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ //
+ // Now that we have a handler for the node, look for all instances of this
+ // type. I.E.: Instances are ordinally enumerated 0,1,...
+ //
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Cpu entries:
+ //
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("Out of CentralProcessor Entries \n"););
+ break;
+ }
+
+ //
+ // The first CPU entry has the CM_SYSTEM_GENERAL_DATA structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ //
+ // Set Desc to point to the classes at the proscribed offset. Since
+ // we're looking at a configuration_descriptor, all the data will be
+ // after the header, at the offset...
+ //
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR)
+ ((PUCHAR)ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ ((PUCHAR)Desc->PartialResourceList.PartialDescriptors);
+
+ while (PDesc->Type != CmResourceTypeDeviceSpecific) {
+ //PDesc+= (PCM_PARTIAL_RESOURCE_DESCRIPTOR)1;
+ PDesc += 1;
+ }
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+ ZwClose (hMFunc);
+}
+
+/*---------------------------------------------------------------------------*/
+VOID
+HalpSetValueKeyString(
+ HANDLE key,
+ PCHAR nameBuffer,
+ PCHAR dataBuffer
+ )
+{
+ UNICODE_STRING nameUnicodeString;
+ UNICODE_STRING dataUnicodeString;
+ ANSI_STRING nameString, dataString;
+ NTSTATUS status;
+ PCHAR junkPtr;
+
+ if (NULL == dataBuffer) return;
+
+ RtlInitString (&nameString,
+ nameBuffer
+ );
+ status = RtlAnsiStringToUnicodeString(
+ &nameUnicodeString,
+ &nameString,
+ TRUE);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpSetValueKeyString: RtlAnsiStringToUnicodeString failed. '%s': (0x%x) \n", nameBuffer, status));
+ return;
+ }
+
+ dataString.MaximumLength = 256;
+ dataString.Buffer = dataBuffer;
+
+ junkPtr = memchr(
+ &dataString.Buffer[0],
+ 0x00,
+ dataString.MaximumLength
+ );
+
+ if (!junkPtr) {
+ dataString.Length = dataString.MaximumLength;
+ } else {
+ dataString.Length = junkPtr - &dataString.Buffer[0];
+ }
+
+ status = RtlAnsiStringToUnicodeString(
+ &dataUnicodeString,
+ &dataString,
+ TRUE
+ );
+ if (NT_SUCCESS(status)) {
+ status = ZwSetValueKey(
+ key,
+ &nameUnicodeString,
+ 0,
+ REG_SZ,
+ dataUnicodeString.Buffer,
+ dataUnicodeString.Length + sizeof(wchar_t));
+
+ RtlFreeUnicodeString(&dataUnicodeString);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("ZwSetValueKey failed. (0x%x) \n", status));
+ }
+ }
+ RtlFreeUnicodeString(&nameUnicodeString);
+}
+
+
+/*---------------------------------------------------------------------------*/
+VOID
+HalpSetValueKeyMultiString(
+ HANDLE key,
+ PCHAR nameBuffer,
+ PCHAR dataBuffer
+ )
+{
+ UNICODE_STRING nameUnicodeString;
+ UNICODE_STRING dataUnicodeString;
+ ANSI_STRING nameString, dataString;
+ NTSTATUS status;
+ PCHAR junkPtr;
+
+ if (NULL == dataBuffer) return;
+
+ RtlInitString (&nameString,
+ nameBuffer
+ );
+ status = RtlAnsiStringToUnicodeString(
+ &nameUnicodeString,
+ &nameString,
+ TRUE);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpSetValueKeyString: RtlAnsiStringToUnicodeString failed. '%s': (0x%x) \n", nameBuffer, status));
+ return;
+ }
+
+ dataString.MaximumLength = 256;
+ dataString.Buffer = dataBuffer;
+
+ junkPtr = memchr(
+ &dataString.Buffer[0],
+ 0x00,
+ dataString.MaximumLength
+ );
+
+ if (!junkPtr) {
+ dataString.Length = dataString.MaximumLength;
+ } else {
+ dataString.Length = junkPtr - &dataString.Buffer[0];
+ }
+
+ status = RtlAnsiStringToUnicodeString(
+ &dataUnicodeString,
+ &dataString,
+ TRUE
+ );
+ if (NT_SUCCESS(status)) {
+ status = ZwSetValueKey(
+ key,
+ &nameUnicodeString,
+ 0,
+ REG_MULTI_SZ,
+ dataUnicodeString.Buffer,
+ dataUnicodeString.Length + sizeof(wchar_t));
+
+ RtlFreeUnicodeString(&dataUnicodeString);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("ZwSetValueKey failed. (0x%x) \n", status));
+ }
+ }
+ RtlFreeUnicodeString(&nameUnicodeString);
+}
+
+
+VOID
+HalpSetValueKeyUlong(
+ HANDLE key,
+ PCHAR str,
+ ULONG version
+ )
+{
+ CHAR buffer[16+1];
+
+ sprintf(buffer, "%08x", version);
+ HalpSetValueKeyString(key, str, buffer);
+}
+
+ULONG
+HalpVersionSystemInRegistry(SYSTEM_TYPE System, HANDLE key)
+{
+ ULONG TscRevision=0;
+ ULONG PciRevision=0;
+ ULONG ProcessorVersion, ProcessorRevision, ProcHertz;
+ PCHAR debugStr;
+ CCHAR buffer[256];
+ extern RelInfo ThisOne;
+ extern ULONG HalpVideoMemorySize; // pxdisp.c
+
+
+ switch(System) {
+
+ case SYS_POWERTOP :
+ case SYS_POWERSLICE:
+ case SYS_POWERSERVE:
+ TscRevision = (rTscRevision & 0xff000000) >> 24; // bits 7:0
+ PciRevision = (rPCIRevisionID & 0xff000000) >> 24; // bits 7:0
+
+ sprintf(buffer, "%d", TscRevision);
+ HalpSetValueKeyString(key, "TSC Revision", buffer);
+ sprintf(buffer, "%d", PciRevision);
+ HalpSetValueKeyString(key, "TIO Revision", buffer);
+ break;
+
+ case SYS_POWERPRO :
+ PciRevision = (rPCIRevisionID & 0xff000000) >> 24; // bits 7:0
+ sprintf(buffer, "%d", PciRevision);
+ HalpSetValueKeyString(key, "ESCC Revision", buffer);
+ break;
+
+ case SYS_UNKNOWN :
+ HalpDebugPrint("Unknown system type \n");
+ break;
+
+ default: // unknown stuff? should never get here
+ break;
+ }
+#if DBG==1
+ debugStr = "(DEBUG)";
+#else
+ debugStr = "";
+#endif
+ sprintf(buffer, "%d.%d %s %s, %s",
+ (ULONG)ThisOne.Major, (ULONG)ThisOne.Minor, debugStr,
+ ThisOne.BuildDate, ThisOne.BuildTime);
+
+ HalpSetValueKeyString(key, "HAL Version", buffer);
+
+ ProcessorVersion = HalpGetProcessorVersion();
+ ProcessorRevision = ProcessorVersion & 0x0000ffff;
+ ProcessorVersion = ProcessorVersion >> 16;
+
+ sprintf(buffer, "%d", 600+ProcessorVersion);
+ HalpSetValueKeyString(key, "Processor", buffer);
+ sprintf(buffer, "%d.%d", ProcessorRevision/256, ProcessorRevision%256);
+ HalpSetValueKeyString(key, "Processor Revision", buffer);
+
+ //
+ // Display the Model Number and our company name
+ //
+ ProcHertz = HalpGetCycleTime();
+ sprintf(buffer, "%d MHz", ProcHertz);
+ HalpSetValueKeyString(key, "Processor Clock Frequency", buffer);
+
+ //
+ // Display the Frequency Multiplier for the Cpu:
+ // two digits are enough. bug 5182
+ //
+ sprintf(buffer, "%d.%02d MHz",ProcessorBusFrequency/1000000,
+ (ProcessorBusFrequency -
+ ((ProcessorBusFrequency / 1000000) * 1000000))/ 10000);
+ HalpSetValueKeyString(key, "Processor Bus Frequency", buffer);
+
+ //
+ // Now figure out what the clock multiplier should look like
+ // in the registery:
+ //
+ if ((CpuClockMultiplier == 25) || (CpuClockMultiplier==15)) {
+ sprintf(buffer, "%d.5", CpuClockMultiplier/10);
+ } else {
+ sprintf(buffer, "%d", CpuClockMultiplier/10);
+ }
+ HalpSetValueKeyString(key, "Processor Clock Multiplier", buffer);
+
+ //
+ // For debug HALs, enable registry storage of timing calculations.
+ //
+ HDBG(DBG_TIME, sprintf(buffer, "%d",TimeBaseCount ));
+ HDBG(DBG_TIME,
+ HalpSetValueKeyString(key, "SYSTEM DEBUG: TimeBaseCount", buffer));
+ HDBG(DBG_TIME,sprintf(buffer, "%d",HalpPerformanceFrequency ));
+ HDBG(DBG_TIME,
+ HalpSetValueKeyString(key, "SYSTEM DEBUG: HalpPerformanceFrequency",
+ buffer));
+
+#if DBG==1
+ sprintf(buffer, "0x%08x",HalpDebugValue );
+ HalpSetValueKeyString(key, "DEBUG HALDEBUG", buffer);
+#endif
+
+ sprintf(buffer, "Powerized %s", SystemDescription[SystemType].SystemName);
+
+ HalpSetValueKeyString(key, "Hardware", buffer);
+ HalpSetValueKeyString(key, "IEEE 1275 Firmware Version", firmwareBuf);
+ HalpSetValueKeyString(key, "ARC Veneer Version", veneerBuf);
+ sprintf(buffer, "%dK bytes", FirstLevelIcacheSize/1024);
+ HalpSetValueKeyString(key, "First Level Icache Size", buffer);
+ sprintf(buffer, "%dK bytes", FirstLevelDcacheSize/1024);
+ HalpSetValueKeyString(key, "First Level Dcache Size", buffer);
+ sprintf(buffer, "%dK bytes per CPU", SecondLevelCacheSize/1024);
+ HalpSetValueKeyString(key, "Second Level Cache Size", buffer);
+
+ if (HalpVideoMemorySize < 0x100000) {
+ sprintf(buffer, "%dK bytes", HalpVideoMemorySize/1024);
+ } else {
+ sprintf(buffer, "%dM bytes", HalpVideoMemorySize/0x100000);
+ }
+ if ((System == SYS_POWERPRO) || (System == SYS_POWERTOP)) {
+ HalpSetValueKeyString(key, "MLU VRAM", buffer);
+ }
+ // ALL platforms fill in the registry information, even if they have
+ // no IIC
+ HalpSetUpRegistryForI2C(System);
+
+ return(1); // success, true, good, ...
+}
+
+NTSTATUS
+HalpCreateKey(HANDLE *pNode, PWCHAR rgzKey)
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ NTSTATUS status;
+ ULONG disposition;
+
+ RtlInitUnicodeString (&unicodeString,
+ rgzKey
+ );
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL
+ );
+
+ status = ZwCreateKey(pNode,
+ KEY_READ,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_VOLATILE,
+ &disposition );
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("Did not create key: (0x%x) \n", status));
+ } else {
+ HDBG(DBG_REGISTRY, HalpDebugPrint("Did create key: (0x%x) \n", status));
+ }
+ return status;
+}
+
+/* called from HalReportResourceUsage(VOID) in pxproc. */
+VOID
+HalpSetUpFirePowerRegistry(
+ VOID
+ )
+{
+ OBJECT_ATTRIBUTES objectAttributes;
+ NTSTATUS status;
+ HANDLE hNode;
+ ULONG disposition;
+
+ static CCHAR szFirePower[] =
+ "\\Registry\\Machine\\Hardware\\Powerized"; //mogawa
+ STRING strFirePower;
+ UNICODE_STRING ucFirePower;
+ //
+ // Open up the FirePOWER entry in the registry, create it if it's not there:
+ // Actually, just create it since create will default to open if the entry
+ // is already present.
+ //
+ RtlInitString (&strFirePower,
+ szFirePower
+ );
+ status = RtlAnsiStringToUnicodeString(
+ &ucFirePower,
+ &strFirePower,
+ TRUE);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("Could not create unicode strings: (0x%x) \n",
+ status));
+ return;
+ }
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &ucFirePower,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL
+ );
+
+ status = ZwCreateKey(&hNode,
+ KEY_READ,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_VOLATILE,
+ &disposition );
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("Did not create key: (0x%x) \n", status););
+ RtlFreeUnicodeString(&ucFirePower);
+ return;
+ }
+ //ZwFlushKey(hNode);
+ HalpVersionSystemInRegistry(SystemType, hNode);
+ if (NULL != hNode) {
+ ZwClose (hNode);
+ }
+ RtlFreeUnicodeString(&ucFirePower);
+ HalpSetUpSystemBiosKeys();
+ return;
+}
+
+
+/* called from HalReportResourceUsage(VOID) in pxproc. */
+VOID
+HalpSetUpSystemBiosKeys(
+ VOID
+ )
+{
+ OBJECT_ATTRIBUTES objectAttributes;
+ NTSTATUS status;
+ HANDLE hNode;
+ CCHAR versionString[256];
+ PUCHAR pDateString = "";
+ ULONG disposition;
+ ULONG i;
+ BOOLEAN DateStringFound = FALSE;
+
+ static CCHAR szFirePower[] =
+ "\\Registry\\Machine\\Hardware\\Description\\System";
+ STRING strFirePower;
+ UNICODE_STRING ucFirePower;
+ //
+ // Open up the FirePOWER entry in the registry, create it if it's not there:
+ // Actually, just create it since create will default to open if the entry
+ // is already present.
+ //
+ RtlInitString (&strFirePower,
+ szFirePower
+ );
+ status = RtlAnsiStringToUnicodeString(
+ &ucFirePower,
+ &strFirePower,
+ TRUE);
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("Could not create unicode strings: (0x%x) \n",
+ status));
+ return;
+ }
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &ucFirePower,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL
+ );
+
+ status = ZwCreateKey(&hNode,
+ KEY_READ,
+ &objectAttributes,
+ 0,
+ (PUNICODE_STRING) NULL,
+ REG_OPTION_VOLATILE,
+ &disposition );
+
+ if (!NT_SUCCESS(status)) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("Did not create key: (0x%x) \n", status););
+ RtlFreeUnicodeString(&ucFirePower);
+ return;
+ }
+ //ZwFlushKey(hNode);
+
+ // Seperate the version and date strings in the firmwareBuf identifier
+ // ASSUMES that the month is the first item of the date and it starts
+ // with an uppercase letter.
+ for (i=0; i < FIRMWARE_BUF_SIZE; i++) {
+ if (firmwareBuf[i] >= 'A' && firmwareBuf[i] <= 'Z') {
+ pDateString = &firmwareBuf[i];
+ versionString[i] = '\0';
+ DateStringFound = TRUE;
+ break;
+ }
+ versionString[i] = firmwareBuf[i];
+ }
+
+ HASSERT(DateStringFound);
+
+ HalpSetValueKeyString(hNode, "SystemBiosDate", pDateString);
+ HalpSetValueKeyString(hNode, "SystemBiosVersion", versionString);
+ HalpSetValueKeyString(hNode, "VideoBiosDate", "");
+ HalpSetValueKeyString(hNode, "VideoBiosVersion", "");
+ if (NULL != hNode) {
+ ZwClose (hNode);
+ }
+ RtlFreeUnicodeString(&ucFirePower);
+ return;
+}
+
+/*----------------------------------------------------------------------------*/
+
+static VOID HalpAppendSprintf(
+ PCHAR buffer,
+ PCHAR format,
+ ...
+ )
+{
+ va_list arglist;
+ ULONG length;
+ UCHAR tempBuf[256];
+
+ va_start(arglist, format);
+ length = vsprintf(tempBuf, format, arglist);
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpAppendSprintf: tempBuf='%s'\n", tempBuf));
+ if (length) {
+ strcat(buffer, tempBuf);
+ } else {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpAppendSprintf: vsprintf returned length=%n\n",
+ length));
+ }
+}
+
+static PCHAR
+gettoken(PCHAR token, PCHAR buf, CHAR delim)
+{
+ CHAR c;
+ while (c = *buf) {
+ if (c == delim) {
+ buf++;
+ break;
+ } else {
+ *token++ = c;
+ buf++;
+ }
+ }
+ *token = '\0';
+ return buf;
+}
+
+static VOID
+HalpSetVersionData( IN PCHAR VersionData
+ )
+{
+
+ while (*VersionData) {
+ enum {Firmware = 0, Veneer = 1, Nada};
+ ULONG type;
+ PCHAR typeStr[2] = {"Firmware", "Veneer"};
+ CHAR token[64];
+ PCHAR tok = VersionData;
+ PCHAR buffer;
+ CHAR buf[80];
+ buffer = (PCHAR)0; // to satisfy warnings
+
+ VersionData += strlen(VersionData)+1;
+
+ if (strstr(tok, typeStr[Firmware])) {
+ type = Firmware;
+ buffer = firmwareBuf;
+ buffer[0] = '\0';
+ } else {
+ if (strstr(tok, typeStr[Veneer])) {
+ type = Veneer;
+ buffer = veneerBuf;
+ buffer[0] = '\0';
+ } else {
+ type = Nada;
+ }
+ }
+ if (Nada == type) {
+ continue;
+ }
+ /* else */
+
+ if (*VersionData) {
+ LONG n;
+
+ tok = VersionData;
+ VersionData += strlen(VersionData)+1;
+ n = 0;
+ tok = gettoken(token, tok, ',');
+
+ while (*token) {
+ switch (n++) {
+ case 2:
+ strcpy(buf, token);
+ strcat(buf, "\0");
+ if (strlen(buf) < 7) {
+ HalpAppendSprintf(buffer, "%-7s", buf);
+ } else {
+ HalpAppendSprintf(buffer, "%s ", buf);
+ }
+ break;
+ case 3:
+ //
+ // Put date in Mmm dd yyyy format if in yyyy-mm-dd
+ // No unicode here :-).
+ // isdigit() causes too many link hassles.
+ // We CANNOT change the case of the first letter of the
+ // month without changing HalpSetUpSystemBiosKeys
+ //
+ if (type == Firmware && *token >= '0' && *token <= '9') {
+ PCHAR day;
+ PCHAR month;
+ PCHAR year;
+ PCHAR Mmm[12] = {
+ "Jan", "Feb", "Mar", "Apr",
+ "May", "Jun", "Jul", "Aug",
+ "Sep", "Oct", "Nov", "Dec",
+ };
+
+ strcpy(buf, token);
+ if (day = strrchr(buf, '-')) {
+ *day++ = '\0';
+ if (month = strrchr(buf, '-')) {
+ ULONG i;
+ *month++ = '\0';
+ RtlCharToInteger(month, 10, &i);
+ if (i > 12 || i < 1) {
+ HalpAppendSprintf(buffer, "%s, ", token);
+ } else {
+ year = buf;
+ //
+ // Decrement the month by one to align with
+ // zero based nature of the Mmm array.
+ //
+ HalpAppendSprintf(buffer, "%s %s %s, ",
+ Mmm[i-1], day, year);
+ }
+ }
+ } else {
+ HalpAppendSprintf(buffer, "%s, ", token);
+ }
+ } else {
+ HalpAppendSprintf(buffer, "%s, ", token);
+ }
+ break;
+ case 4:
+ HalpAppendSprintf(buffer, "%s", token);
+ break;
+ } // end of switch......
+ tok = gettoken(token, tok, ',');
+
+ }
+ }
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpSetVersionData: %s\n", buffer);
+ );
+
+ } /* while */
+}
+
+/* called in HalInitSystem phase 1 in pxinithl.c */
+BOOLEAN
+HalpInitializeRegistry ( IN PLOADER_PARAMETER_BLOCK LoaderBlock )
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey;
+ PCHAR versionData;
+ extern PCHAR HalpGetVersionData( IN PLOADER_PARAMETER_BLOCK );
+
+
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: FirstLevelDcacheSize=0x%08x\n",
+ LoaderBlock->u.Ppc.FirstLevelDcacheSize));
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: FirstLevelIcacheSize=0x%08x\n",
+ LoaderBlock->u.Ppc.FirstLevelDcacheSize));
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: SecondLevelDcacheSize=0x%08x\n",
+ LoaderBlock->u.Ppc.SecondLevelDcacheSize));
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: SecondLevelIcacheSize=0x%08x\n",
+ LoaderBlock->u.Ppc.SecondLevelIcacheSize));
+ FirstLevelIcacheSize = LoaderBlock->u.Ppc.FirstLevelIcacheSize;
+ FirstLevelDcacheSize = LoaderBlock->u.Ppc.FirstLevelDcacheSize;
+ SecondLevelCacheSize = LoaderBlock->u.Ppc.SecondLevelDcacheSize;
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ CacheClass,
+ PrimaryIcache,
+ &MatchKey);
+ if (ConfigurationEntry) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: PrimaryIcache Key=0x%08x\n",
+ ConfigurationEntry->ComponentEntry.Key););
+
+ } else {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: KeFindConfigurationEntry PrimaryICache failed\n"));
+ }
+
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ CacheClass,
+ PrimaryDcache,
+ &MatchKey);
+
+ if (ConfigurationEntry) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: PrimaryDcache Key=0x%08x\n",
+ ConfigurationEntry->ComponentEntry.Key));
+ } else {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: KeFindConfigurationEntry PrimaryDcache failed\n"););
+ }
+
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ CacheClass,
+ SecondaryCache,
+ &MatchKey);
+ if (ConfigurationEntry) {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: SecondaryCache Key=0x%x\n",
+ ConfigurationEntry->ComponentEntry.Key));
+ } else {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: KeFindConfigurationEntry SecondaryCache failed\n"));
+ }
+
+ if ( versionData = HalpGetVersionData(LoaderBlock) ) {
+ HalpSetVersionData(versionData);
+ } else {
+ HDBG(DBG_REGISTRY,
+ HalpDebugPrint("HalpInitializeRegistry: HalpGetVersionData failed.\n"));
+ }
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halfire/ppc/halp.h b/private/ntos/nthals/halfire/ppc/halp.h
new file mode 100644
index 000000000..14862b25e
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/halp.h
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: halp.h $
+ * $Revision: 1.20 $
+ * $Date: 1996/05/14 02:33:08 $
+ * $Locker: $
+ */
+
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Added PPC specific includes
+ Changed paramaters to HalpProfileInterrupt
+ Added function prototype for HalpWriteCompareRegisterAndClear()
+ Added include for ppcdef.h
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#if defined(NT_UP)
+
+#undef NT_UP
+
+#endif
+
+#include "nthal.h"
+
+
+#include "ppcdef.h"
+
+#include "hal.h"
+#include "pxhalp.h"
+
+
+
+
+// Debug prints. see pxdisp.c
+#include <stdarg.h>
+
+VOID HalpDebugPrint( PCHAR Format, ... );
+VOID HalpForceDisplay( PCHAR Format, ... );
+
+//
+// Resource usage information
+//
+
+#define MAXIMUM_IDTVECTOR 255
+
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ USHORT Length;
+ } Element[];
+} ADDRESS_USAGE;
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
+#define HalpGetProcessorVersion() KeGetPvr()
+
+#define HalpEnableInterrupts() _enable()
+#define HalpDisableInterrupts() _disable()
+
+#define KeFlushWriteBuffer() __builtin_eieio()
+
+//
+// Bus handlers
+//
+
+
+PBUS_HANDLER HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN BUS_DATA_TYPE ParentBusDataType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+
+#define HalpAllocateConfigSpace HalpAllocateBusHandler
+
+#define HalpHandlerForBus HaliHandlerForBus
+
+#define SPRANGEPOOL NonPagedPool // for now, until crashdump is fixed
+//
+// Define function prototypes.
+//
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+
+BOOLEAN
+HalpCalibrateTimingValues (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpInitPciIsaBridge (
+ VOID
+ );
+
+VOID
+HalpHandleIoError (
+ VOID
+ );
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ );
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ );
+
+BOOLEAN
+HalpHandleProfileInterrupt (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+
+BOOLEAN
+HalpInitSuperIo(
+ VOID
+ );
+
+BOOLEAN
+HalpEnableInterruptHandler (
+ IN PKINTERRUPT Interrupt,
+ IN PKSERVICE_ROUTINE ServiceRoutine,
+ IN PVOID ServiceContext,
+ IN PKSPIN_LOCK SpinLock OPTIONAL,
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KIRQL SynchronizeIrql,
+ IN KINTERRUPT_MODE InterruptMode,
+ IN BOOLEAN ShareVector,
+ IN CCHAR ProcessorNumber,
+ IN BOOLEAN FloatingSave,
+ IN UCHAR ReportFlags,
+ IN KIRQL BusVector
+ );
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ );
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+
+NTSTATUS
+HalpAdjustResourceListLimits (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN ULONG MinimumMemoryAddress,
+ IN ULONG MaximumMemoryAddress,
+ IN ULONG MinimumPrefetchMemoryAddress,
+ IN ULONG MaximumPrefetchMemoryAddress,
+ IN BOOLEAN LimitedIOSupport,
+ IN ULONG MinimumPortAddress,
+ IN ULONG MaximumPortAddress,
+ IN PUCHAR IrqTable,
+ IN ULONG IrqTableLength,
+ IN ULONG MinimumDmaChannel,
+ IN ULONG MaximumDmaChannel
+ );
+
+
+//
+// Define external references.
+//
+
+extern KSPIN_LOCK HalpBeepLock;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+extern KAFFINITY HalpIsaBusAffinity;
+extern ULONG HalpProfileCount;
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+
+
+#define IRQ_VALID 0x01
+#define IRQ_PREFERRED 0x02
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halfire/ppc/pcibios.c b/private/ntos/nthals/halfire/ppc/pcibios.c
new file mode 100644
index 000000000..a6ec9a959
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pcibios.c
@@ -0,0 +1,1084 @@
+/*++
+
+
+Copyright (C) 1996 Motorola Inc.
+
+Module Name:
+
+ pcibios.c
+
+Abstract:
+
+ Emulate PCI BIOS functions.
+
+ Note that the HAL bus functions (HalGetBusData, etc.) are not
+ available at this phase of initialization, all of the work has
+ to be done here.
+
+Author:
+
+ Scott Geranen
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+#include "pxmemctl.h"
+#include "pxpcisup.h"
+
+#include "emulate.h"
+#include "pcibios.h"
+
+UCHAR SBReadConfigByte(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ );
+
+USHORT SBReadConfigWord(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ );
+
+ULONG SBReadConfigDword(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ );
+
+VOID SBWriteConfigByte(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN UCHAR Data
+ );
+
+VOID SBWriteConfigWord(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN USHORT Data
+ );
+
+VOID SBWriteConfigDword(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN ULONG Data
+ );
+
+//
+// Last PCI bus in the system.
+//
+extern UCHAR HalpLastPciBus;
+
+//
+// Ports to be used to access config space.
+//
+#define CONFIG_ADDR_PORT (0x00000CF8)
+#define CONFIG_DATA_PORT (0x00000CFC)
+
+ULONG
+x86BiosReadIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber
+ );
+
+
+VOID
+x86BiosWriteIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber,
+ IN ULONG Value
+ );
+
+BOOLEAN
+HalpEmulatePciBios(
+ IN OUT PRXM_CONTEXT P
+ )
+/*++
+
+Routine Description:
+
+ This function emulates the PCI BIOS Specification, revision 2.1. The
+ specification is available from the PCI Special Interest Group.
+
+ This function assumes that it is being called during phase 0 initialization.
+ The PCI bus functions are not available at this point, e.g. HalGetBusData.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+
+Return Value:
+
+ TRUE (PCI BIOS was emulated)
+
+--*/
+{
+#if DBG
+ VOID TestPciBios(int flag);
+
+ TestPciBios(0);
+#endif
+
+ switch (P->Gpr[EAX].Xl) {
+
+ case PCIBIOS_PCI_BIOS_PRESENT: // Installation Check
+
+ KdPrint(("PCI_BIOS_PRESENT\n"));
+
+ P->Gpr[EDX].Exx = 0x20494350; // "PCI "
+
+ P->Gpr[EAX].Xh = 0x00; // 00 == BIOS present
+ P->Gpr[EAX].Xl = 0x11; // PCI Hardware Characteristics (mech #1)
+
+ P->Gpr[EBX].Xh = 0x02; // PCI Interface Level Major Version
+ P->Gpr[EBX].Xl = 0x10; // PCI Interface Level (BCD)
+
+ P->Gpr[ECX].Xl = HalpLastPciBus; // Last PCI bus number
+
+ P->Eflags.CF = 0; // reset == PCI BIOS present
+
+ break;
+
+ case PCIBIOS_FIND_PCI_DEVICE:
+ {
+ USHORT DevID = P->Gpr[ECX].Xx;
+ USHORT VenID = P->Gpr[EDX].Xx;
+ USHORT DevIndex = P->Gpr[ESI].Xx;
+
+ UCHAR Bus, Device, Function, Header, NumFunctions;
+ BOOLEAN Found = FALSE;
+
+ KdPrint(("Looking for instance %d of 0x%X, 0x%X\n", DevIndex, DevID, VenID));
+
+ if (VenID == 0xFFFF) {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_VENDOR_ID;
+ P->Eflags.CF = 1; // set == error
+
+ } else {
+
+ for (Bus = 0; Bus <= HalpLastPciBus; Bus++) {
+ for (Device = 0; Device < PCI_MAX_DEVICES; Device++) {
+
+ if (SBReadConfigWord(Bus, Device, 0,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID)) == 0xFFFF) {
+
+ continue; // no device here
+
+ }
+
+ Header = SBReadConfigByte(
+ Bus, Device, 0,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType));
+
+ NumFunctions = Header & PCI_MULTIFUNCTION ? 8 : 1;
+
+ for (Function = 0; Function < NumFunctions; Function++) {
+
+ if (SBReadConfigWord(Bus, Device, Function,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID)) == VenID) {
+
+ if (SBReadConfigWord(Bus, Device, Function,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, DeviceID)) == DevID) {
+
+ Found = (DevIndex == 0);
+ DevIndex--;
+ }
+ }
+ if (Found) break; // function
+ }
+ if (Found) break; // device
+ }
+ if (Found) break; // bus
+ }
+
+ if (Found) {
+
+ KdPrint(("Found at %d, %d, %d\n", Bus, Device, Function));
+
+ P->Gpr[EBX].Xh = Bus;
+ P->Gpr[EBX].Xl = (Device << 3) + Function;
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+
+ P->Eflags.CF = 0; // clear == success
+
+ } else {
+
+ KdPrint(("Not found\n"));
+
+ P->Gpr[EAX].Xh = PCIBIOS_DEVICE_NOT_FOUND;
+
+ P->Eflags.CF = 1; // set == error
+ }
+
+ }
+ }
+ break;
+
+
+ case PCIBIOS_FIND_PCI_CLASS_CODE:
+ {
+ ULONG ClassCode = (P->Gpr[ECX].Exx) << 8; // see comments below
+ USHORT DevIndex = P->Gpr[ESI].Xx;
+
+ UCHAR Bus, Device, Function, Header, NumFunctions;
+ BOOLEAN Found = FALSE;
+
+ KdPrint(("Looking for class instance %d of 0x%X\n", DevIndex, P->Gpr[ECX].Exx));
+
+ for (Bus = 0; Bus <= HalpLastPciBus; Bus++) {
+ for (Device = 0; Device < PCI_MAX_DEVICES; Device++) {
+
+ if (SBReadConfigWord(Bus, Device, 0,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID)) == 0xFFFF) {
+
+ continue; // no device here
+
+ }
+
+ Header = SBReadConfigByte(
+ Bus, Device, 0,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType));
+
+ NumFunctions = Header & PCI_MULTIFUNCTION ? 8 : 1;
+
+ for (Function = 0; Function < NumFunctions; Function++) {
+
+ //
+ // The class code bytes are in the same Dword as
+ // the revision id:
+ //
+ // Byte
+ // 3 2 1 0
+ // +-------------------+--------+
+ // | class code | Rev id |
+ // +-------------------+--------+
+ //
+ // Read the Dword and mask off the revision id.
+ // The class code we are looking for has been
+ // shifted up already above.
+ //
+ if ((SBReadConfigDword(Bus, Device, Function,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, RevisionID))
+ & 0xFFFFFF00) == ClassCode) {
+
+ Found = (DevIndex == 0);
+ DevIndex--;
+ }
+ if (Found) break; // function
+ }
+ if (Found) break; // device
+ }
+ if (Found) break; // bus
+ }
+
+ if (Found) {
+
+ KdPrint(("Found at %d, %d, %d\n", Bus, Device, Function));
+
+ P->Gpr[EBX].Xh = Bus;
+ P->Gpr[EBX].Xl = (Device << 3) + Function;
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+
+ P->Eflags.CF = 0; // clear == success
+
+ } else {
+
+ KdPrint(("Not found\n"));
+
+ P->Gpr[EAX].Xh = PCIBIOS_DEVICE_NOT_FOUND;
+
+ P->Eflags.CF = 1; // set == error
+ }
+ }
+ break;
+
+ case PCIBIOS_READ_CONFIG_BYTE:
+
+ KdPrint(("read byte %d, %d, %d, %d\n",
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ P->Gpr[ECX].Xl = SBReadConfigByte(
+ P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl); // Register
+
+ KdPrint(("Data = 0x%X\n", P->Gpr[ECX].Xl));
+
+ break;
+
+ case PCIBIOS_READ_CONFIG_WORD:
+
+ KdPrint(("read word %d, %d, %d, %d\n",
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ if ((P->Gpr[EDI].Xl & 1) == 0) {
+
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ P->Gpr[ECX].Xx = SBReadConfigWord(
+ P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl); // Register
+ } else {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER;
+ P->Eflags.CF = 1; // set == error
+ }
+
+ KdPrint(("Data = 0x%X\n", P->Gpr[ECX].Xx));
+
+ break;
+
+ case PCIBIOS_READ_CONFIG_DWORD:
+
+ KdPrint(("read Dword %d, %d, %d, %d\n",
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ if ((P->Gpr[EDI].Xl & 3) == 0) {
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ P->Gpr[ECX].Exx = SBReadConfigDword(
+ P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl); // Register
+ } else {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER;
+ P->Eflags.CF = 1; // set == error
+ }
+
+ KdPrint(("Data = 0x%X\n", P->Gpr[ECX].Exx));
+
+ break;
+
+ case PCIBIOS_WRITE_CONFIG_BYTE:
+
+ KdPrint(("Write byte 0x%X to %d, %d, %d, %d\n",
+ P->Gpr[ECX].Xl, // Value
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ SBWriteConfigByte( P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl, // Register
+ P->Gpr[ECX].Xl); // Value
+ break;
+
+ case PCIBIOS_WRITE_CONFIG_WORD:
+
+ KdPrint(("Write word 0x%X to %d, %d, %d, %d\n",
+ P->Gpr[ECX].Xx, // Value
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ if ((P->Gpr[EDI].Xl & 1) == 0) {
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ SBWriteConfigWord( P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl, // Register
+ P->Gpr[ECX].Xx); // Value
+ } else {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER;
+ P->Eflags.CF = 1; // set == error
+ }
+
+ break;
+
+ case PCIBIOS_WRITE_CONFIG_DWORD:
+
+ KdPrint(("Write Dword 0x%X to %d, %d, %d, %d\n",
+ P->Gpr[ECX].Exx, // Value
+ P->Gpr[EBX].Xh, // Bus
+ (P->Gpr[EBX].Xl >> 3), // Device
+ (P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl)); // Register
+
+ if ((P->Gpr[EDI].Xl & 3) == 0) {
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+
+ SBWriteConfigDword( P->Gpr[EBX].Xh, // Bus
+ (UCHAR)(P->Gpr[EBX].Xl >> 3), // Device
+ (UCHAR)(P->Gpr[EBX].Xl & 0x07), // Function
+ P->Gpr[EDI].Xl, // Register
+ P->Gpr[ECX].Exx); // Value
+ } else {
+
+ P->Gpr[EAX].Xh = PCIBIOS_BAD_REGISTER_NUMBER;
+ P->Eflags.CF = 1; // set == error
+ }
+
+ break;
+
+ case PCIBIOS_GENERATE_SPECIAL_CYCLE:
+ {
+ PCI_TYPE1_CFG_BITS Addr;
+
+ KdPrint(("Generate Special cycle %d, 0x%X\n",
+ P->Gpr[EBX].Xh, // Bus
+ P->Gpr[ECX].Exx)); // Value
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = P->Gpr[EBX].Xh;
+ Addr.u.bits.DeviceNumber = 0x1f;
+ Addr.u.bits.FunctionNumber = 7;
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_DATA_PORT, P->Gpr[EDX].Exx);
+
+
+ P->Gpr[EAX].Xh = PCIBIOS_SUCCESSFUL;
+ P->Eflags.CF = 0; // clear == success
+ }
+
+ break;
+
+
+ case PCIBIOS_GET_IRQ_ROUTING_OPTIONS: // not supported
+ case PCIBIOS_SET_IRQ_ROUTING_OPTIONS: // not supported
+ default:
+
+ KdPrint(("PCI BIOS: function %x not supported\n", P->Gpr[EAX].Xl));
+
+ P->Gpr[EAX].Xh = PCIBIOS_FUNC_NOT_SUPPORTED;
+
+ P->Eflags.CF = 1; // set == error
+
+ break;
+ }
+
+ return TRUE;
+}
+
+UCHAR
+SBReadConfigByte(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ )
+{
+ ULONG ByteInRegister;
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ ByteInRegister = Register % sizeof(ULONG);
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+ return((UCHAR)x86BiosReadIoSpace (BYTE_DATA, (USHORT)(CONFIG_DATA_PORT + ByteInRegister)));
+
+}
+
+USHORT
+SBReadConfigWord(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ )
+{
+ ULONG WordInRegister;
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ WordInRegister = Register % sizeof(ULONG);
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+ return((USHORT)x86BiosReadIoSpace (WORD_DATA, (USHORT)(CONFIG_DATA_PORT + WordInRegister)));
+
+}
+
+ULONG
+SBReadConfigDword(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register
+ )
+{
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+ return(x86BiosReadIoSpace (LONG_DATA, (USHORT)CONFIG_DATA_PORT));
+
+}
+
+VOID
+SBWriteConfigByte(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN UCHAR Data
+ )
+{
+ ULONG ByteInRegister;
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ ByteInRegister = Register % sizeof(ULONG);
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+
+ x86BiosWriteIoSpace (
+ BYTE_DATA,
+ (USHORT)(CONFIG_DATA_PORT + ByteInRegister),
+ Data
+ );
+
+}
+
+VOID
+SBWriteConfigWord(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN USHORT Data
+ )
+{
+ ULONG WordInRegister;
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ WordInRegister = Register % sizeof(ULONG);
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+
+ x86BiosWriteIoSpace (
+ WORD_DATA,
+ (USHORT)(CONFIG_DATA_PORT + WordInRegister),
+ Data
+ );
+
+}
+
+VOID
+SBWriteConfigDword(
+ IN UCHAR Bus,
+ IN UCHAR Device,
+ IN UCHAR Function,
+ IN UCHAR Register,
+ IN ULONG Data
+ )
+{
+ PCI_TYPE1_CFG_BITS Addr;
+
+ Addr.u.AsULONG = 0; // initialize reserved bits
+
+ Addr.u.bits.Enable = TRUE;
+
+ Addr.u.bits.BusNumber = Bus;
+ Addr.u.bits.DeviceNumber = Device;
+ Addr.u.bits.FunctionNumber = Function;
+
+ Addr.u.bits.RegisterNumber = Register / sizeof(ULONG);
+
+ x86BiosWriteIoSpace (LONG_DATA, CONFIG_ADDR_PORT, Addr.u.AsULONG);
+
+ x86BiosWriteIoSpace (
+ LONG_DATA,
+ CONFIG_DATA_PORT,
+ Data
+ );
+
+}
+
+
+#if DBG
+
+// Modify this code to match your particular HW configuration
+//
+// Use the debugger to force flag to 1.
+
+VOID
+initregs(PRXM_CONTEXT P)
+{
+ P->Gpr[EAX].Exx = 0x1234B100;
+ P->Gpr[EBX].Exx = 0x23456789;
+ P->Gpr[ECX].Exx = 0x3456789A;
+ P->Gpr[EDX].Exx = 0x456789AB;
+ P->Gpr[ESP].Exx = 0x87654321;
+ P->Gpr[EBP].Exx = 0x98765432;
+ P->Gpr[ESI].Exx = 0xA9876543;
+ P->Gpr[EDI].Exx = 0xBA987654;
+
+ P->Eflags.CF = 1;
+}
+
+VOID
+dumpregs(PRXM_CONTEXT P)
+{
+ DbgPrint("Carry = %d\n", P->Eflags.CF);
+
+ DbgPrint("EAX = %X, EBX = %X, ECX = %X, EDX = %X\n",
+ P->Gpr[EAX], P->Gpr[EBX], P->Gpr[ECX], P->Gpr[EDX]);
+
+ DbgPrint("ESP = %X, EBP = %X, ESI = %X, EDI = %X\n",
+ P->Gpr[ESP], P->Gpr[EBP], P->Gpr[ESI], P->Gpr[EDI]);
+}
+
+
+VOID
+TestPciBios(int flag)
+{
+int i;
+XM_CONTEXT Context;
+PRXM_CONTEXT P = &Context;
+
+ if (flag == 0) return;
+
+ DbgBreakPoint();
+ initregs(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ P->Gpr[EAX].Xl = 1; // bios present
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0xffff;
+ P->Gpr[EDX].Xx = 0xffff;
+ P->Gpr[ESI].Xx = 0;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0x0453;
+ P->Gpr[EDX].Xx = 0x8086;
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0x0002;
+ P->Gpr[EDX].Xx = 0x1011; // DEC ethernet
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0x7278;
+ P->Gpr[EDX].Xx = 0x9004; // adaptec
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 2; // find device
+ P->Gpr[ECX].Xx = 0x1234;
+ P->Gpr[EDX].Xx = 0x5678;
+ P->Gpr[ESI].Xx = 0;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 3; // find class code
+ P->Gpr[ECX].Exx = 0x030000; // vga
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 3; // find class code
+ P->Gpr[ECX].Exx = 0x020000; // ethernet
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ for (P->Eflags.CF = 0, i = 0; P->Eflags.CF == 0; i++)
+ {
+ initregs(P);
+ P->Gpr[EAX].Xl = 3; // find class code
+ P->Gpr[ECX].Exx = 0x010000; // scsi
+ P->Gpr[ESI].Xx = i;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+ }
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 3; // find class code
+ P->Gpr[ECX].Exx = 0xABCDEF; // not found
+ P->Gpr[ESI].Xx = 0;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 6; // generate special cycle
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EDX].Exx = 0x00000002; // x86 specific
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xE; // get irq routing
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xF; // set irq routing
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 8; // read byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (2 << 3) + 0; // non-existent
+ P->Gpr[EDI].Xx = 1;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 8; // read byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 1;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 8; // read byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 1; // non-existent function
+ P->Gpr[EDI].Xx = 1;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 8; // read byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 4; // existent function
+ P->Gpr[EDI].Xx = 1;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 1; // bad register number
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (2 << 3) + 0; // non-existent
+ P->Gpr[EDI].Xx = 2;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 2;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 1; // non-existent function
+ P->Gpr[EDI].Xx = 2;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 9; // read word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 4; // existent function
+ P->Gpr[EDI].Xx = 2;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 2; // bad register number
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (2 << 3) + 0; // non-existent
+ P->Gpr[EDI].Xx = 4;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 4;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 1; // non-existent function
+ P->Gpr[EDI].Xx = 4;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 4; // existent function
+ P->Gpr[EDI].Xx = 4;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (17 << 3) + 0;
+ P->Gpr[EDI].Xx = 2; // bad register number
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3C;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xB; // write byte
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3C;
+ P->Gpr[ECX].Xl = 0xAB;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3C;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xC; // write word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3F; // bad register
+ P->Gpr[ECX].Xl = 0xAB;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xC; // write word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ P->Gpr[ECX].Xx = 0xFFFF;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xD; // write Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x3F; // bad register
+ P->Gpr[ECX].Xl = 0xAB;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xD; // write word
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ P->Gpr[ECX].Exx = 0xFFFFFFFF;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ initregs(P);
+ P->Gpr[EAX].Xl = 0xA; // read Dword
+ P->Gpr[EBX].Xh = 0;
+ P->Gpr[EBX].Xl = (16 << 3) + 0;
+ P->Gpr[EDI].Xx = 0x30;
+ HalpEmulatePciBios(P);
+ dumpregs(P);
+ DbgBreakPoint();
+
+ DbgPrint("All done!\n");
+ DbgBreakPoint();
+}
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/pcibios.h b/private/ntos/nthals/halfire/ppc/pcibios.h
new file mode 100644
index 000000000..2e47f6b23
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pcibios.h
@@ -0,0 +1,58 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1996 Motorola Inc.
+
+Module Name:
+
+ pcibios.h
+
+Abstract:
+
+ This module contains the private header file for the PCI bios
+ emulation.
+
+Author:
+
+ Scott Geranen (3-4-96)
+
+Revision History:
+
+--*/
+
+#ifndef _PCIBIOS_
+#define _PCIBIOS_
+
+
+BOOLEAN HalpEmulatePciBios(
+ IN OUT PRXM_CONTEXT P
+ );
+
+//
+// PCI BIOS v2.1 functions
+//
+#define PCIBIOS_PCI_FUNCTION_ID 0xB1
+#define PCIBIOS_PCI_BIOS_PRESENT 0x01
+#define PCIBIOS_FIND_PCI_DEVICE 0x02
+#define PCIBIOS_FIND_PCI_CLASS_CODE 0x03
+#define PCIBIOS_GENERATE_SPECIAL_CYCLE 0x06
+#define PCIBIOS_READ_CONFIG_BYTE 0x08
+#define PCIBIOS_READ_CONFIG_WORD 0x09
+#define PCIBIOS_READ_CONFIG_DWORD 0x0A
+#define PCIBIOS_WRITE_CONFIG_BYTE 0x0B
+#define PCIBIOS_WRITE_CONFIG_WORD 0x0C
+#define PCIBIOS_WRITE_CONFIG_DWORD 0x0D
+#define PCIBIOS_GET_IRQ_ROUTING_OPTIONS 0x0E
+#define PCIBIOS_SET_IRQ_ROUTING_OPTIONS 0x0F
+
+//
+// PCI BIOS v2.1 status codes:
+//
+#define PCIBIOS_SUCCESSFUL 0x00
+#define PCIBIOS_FUNC_NOT_SUPPORTED 0x81
+#define PCIBIOS_BAD_VENDOR_ID 0x83
+#define PCIBIOS_DEVICE_NOT_FOUND 0x86
+#define PCIBIOS_BAD_REGISTER_NUMBER 0x87
+#define PCIBIOS_SET_FAILED 0x88
+#define PCIBIOS_BUFFER_TOO_SMALL 0x89
+
+#endif // _PCIBIOS_
diff --git a/private/ntos/nthals/halfire/ppc/pcip.h b/private/ntos/nthals/halfire/ppc/pcip.h
new file mode 100644
index 000000000..262a4393e
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pcip.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pcip.h $
+ * $Revision: 1.17 $
+ * $Date: 1996/05/14 02:33:13 $
+ * $Locker: $
+ */
+
+//
+// Hal specific PCI bus structures
+//
+
+typedef NTSTATUS
+(*PciIrqTable) (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ );
+
+typedef struct tagPCIPBUSDATA {
+ //
+ // Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Implementation specific data
+ //
+
+ union {
+ struct {
+ PULONG Address;
+ ULONG Data;
+ } Type1;
+ struct {
+ PUCHAR CSE;
+ PUCHAR Forward;
+ ULONG Base;
+ } Type2;
+ } Config;
+
+ ULONG MaxDevice;
+ PciIrqTable GetIrqTable;
+
+ BOOLEAN BridgeConfigRead;
+ UCHAR ParentBus;
+ BOOLEAN LimitedIO;
+ UCHAR reserved;
+ UCHAR SwizzleIn[4];
+
+ ULONG IOBase;
+ ULONG IOLimit;
+ ULONG MemoryBase;
+ ULONG MemoryLimit;
+ ULONG PFMemoryBase;
+ ULONG PFMemoryLimit;
+
+ RTL_BITMAP DeviceConfigured;
+ ULONG ConfiguredBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+} PCIPBUSDATA, *PPCIPBUSDATA;
+
+#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev);
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+
+
+//
+// Prototypes for functions in ixpcibus.c
+//
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ );
+
+
+//
+// Prototypes for functions in ixpciint.c
+//
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+NTSTATUS
+HalpTranslatePCIBusAddress (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ );
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ );
+
+//
+// Prototypes for functions in ixpcibrd.c
+//
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ );
+
+
+
+
+
+typedef ULONG (*FncConfigIO) (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+typedef VOID (*FncSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+typedef VOID (*FncReleaseSync) (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+typedef struct _PCI_CONFIG_HANDLER {
+ FncSync Synchronize;
+ FncReleaseSync ReleaseSynchronzation;
+ FncConfigIO ConfigRead[3];
+ FncConfigIO ConfigWrite[3];
+} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
+
+
+//
+// This is a "container" for pci private data that needs
+// to be known per bus and for the set of functions that
+// each bus uses to access data.
+// There is also a couple of extra pci private data needs
+// namely the configuration type of the config data accesses.
+//
+
+typedef struct _BUS_NODE {
+
+ //
+ // The standard bus data for pci buses
+ //
+ PCIPBUSDATA Bus;
+
+ //
+ // Some extra data not part of PCIPBUSDATA:
+ //
+ ULONG HwType; // What HW config access type to use.
+ PPCI_CONFIG_HANDLER ThisNode; // used to point to the "Node"
+ PCI_SLOT_NUMBER SlotNumber;
+ UCHAR BusOrder, BusLevel, BusMax;
+ ULONG BusInt; // bit map of allowable interrupts...
+ ULONG ValidDevs; // bit map of valid DEVICES on this bus.
+ ULONG MemBase, MemTop, IoBase, IoTop;
+
+ //
+ // set of bus specific functions to handle
+ // bus reading, writing, locking, unlocking.
+ //
+ PCI_CONFIG_HANDLER Node;
+
+} FPHAL_BUSNODE, *PFPHAL_BUSNODE;
+
+
diff --git a/private/ntos/nthals/halfire/ppc/phcalls.c b/private/ntos/nthals/halfire/ppc/phcalls.c
new file mode 100644
index 000000000..63dbfec4e
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/phcalls.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: phcalls.c $
+ * $Revision: 1.14 $
+ * $Date: 1996/01/11 07:08:05 $
+ * $Locker: $
+ */
+
+#include "nthal.h"
+#include "halp.h"
+#include "phsystem.h"
+#include "fpio.h"
+#include "fpdcc.h"
+#include "stdio.h"
+#include "string.h"
+#include "fparch.h"
+
+PUCHAR Types[] = {
+ "ArcSystem",
+ "CentralProcessor",
+ "FloatingPointProcessor",
+ "PrimaryIcache",
+ "PrimaryDcache",
+ "SecondaryIcache",
+ "SecondaryDcache",
+ "SecondaryCache",
+ "EisaAdapter",
+ "TcAdapter",
+ "ScsiAdapter",
+ "DtiAdapter",
+ "MultiFunctionAdapter",
+ "DiskController",
+ "TapeController",
+ "CdromController",
+ "WormController",
+ "SerialController",
+ "NetworkController",
+ "DisplayController",
+ "ParallelController",
+ "PointerController",
+ "KeyboardController",
+ "AudioController",
+ "OtherController",
+ "DiskPeripheral",
+ "FloppyDiskPeripheral",
+ "TapePeripheral",
+ "ModemPeripheral",
+ "MonitorPeripheral",
+ "PrinterPeripheral",
+ "PointerPeripheral",
+ "KeyboardPeripheral",
+ "TerminalPeripheral",
+ "OtherPeripheral",
+ "LinePeripheral",
+ "NetworkPeripheral",
+ "SystemMemory",
+ "MaximumType"
+};
+
+PUCHAR Classes[] = {
+ "SystemClass",
+ "ProcessorClass",
+ "CacheClass",
+ "AdapterClass",
+ "ControllerClass",
+ "PeripheralClass",
+ "MemoryClass",
+ "MaximumClass"
+};
+
+/*
+** PHalDumpTree
+**
+**
+**
+*/
+
+VOID
+PHalpDumpLoaderBlock (
+ PLOADER_PARAMETER_BLOCK lpb
+ )
+{
+ DbgPrint("\nlpb is %x\n",lpb);
+ DbgPrint("Kernel stack: %x \n",lpb->KernelStack);
+ DbgPrint("ArcBootDeviceName: %s \n",lpb->ArcBootDeviceName);
+ DbgPrint("ArcHalDeviceName: %s \n",lpb->ArcHalDeviceName);
+ DbgPrint("NtBootPathName: %s \n",lpb->NtBootPathName);
+ DbgPrint("NtHalPathName: %s \n",lpb->NtHalPathName);
+ DbgPrint("Loader Options : %s \n",lpb->LoadOptions);
+ DbgPrint("ArcDiskInformation: %x \n",lpb->ArcDiskInformation);
+ DbgPrint("\nPArcDiskinfo: %x \n",lpb->ArcDiskInformation);
+}
+
+VOID
+PHalpDumpConfigData (
+ PCONFIGURATION_COMPONENT_DATA ConfigurationNode,
+ PULONG depth
+ )
+{
+ PCONFIGURATION_COMPONENT_DATA current=NULL, next=NULL;
+
+ DbgPrint("\n======================================\n");
+ for (next = ConfigurationNode; next; next = next->Child) {
+ current = next;
+ DbgPrint("\nNode address = 0x%8.8x, Parent = 0x%8.8x, Sibling = 0x%8.8x, Child = 0x%8.8x\n", current, current->Parent, current->Sibling, current->Child);
+ DbgPrint("\tComponent Class %d, Type %d", current->ComponentEntry.Class, current->ComponentEntry.Type);
+ DbgPrint(", Identifier = '%s' (Length = %d)\n", current->ComponentEntry.Identifier, current->ComponentEntry.IdentifierLength);
+ DbgPrint("\n\tComponent Class %s, Type %s\n", Classes[current->ComponentEntry.Class], Types[current->ComponentEntry.Type]);
+ }
+
+ for ( ; current && !current->Sibling; current = current->Parent) ;
+
+ if (current) {
+ current = current->Sibling;
+ PHalpDumpConfigData(current, &*depth++);
+ }
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/phprods.c b/private/ntos/nthals/halfire/ppc/phprods.c
new file mode 100644
index 000000000..cc09923f2
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/phprods.c
@@ -0,0 +1,794 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: phprods.c $
+ * $Revision: 1.66 $
+ * $Date: 1996/05/14 02:33:18 $
+ * $Locker: $
+ */
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "eisa.h"
+#include "pxsiosup.h"
+#include "pxpcisup.h"
+#include "pxmemctl.h"
+#include "bugcodes.h"
+
+#include "phsystem.h"
+#include "fpio.h"
+#include "fpcpu.h"
+#include <pci.h>
+#include "pcip.h"
+#include <arccodes.h> // for ESUCCESS
+
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PVOID ServiceContext,
+ PVOID TrapFrame
+ );
+
+VOID HalpHandleDecrementerInterrupt1( PKINTERRUPT , PVOID , PVOID );
+
+HalState Dispatch;
+
+
+extern BOOLEAN HalpHandleMachineCheck(PKINTERRUPT, PVOID);
+extern KINTERRUPT HalpMachineCheckInterrupt;
+extern ULONG HalpSetIntPriorityMask( VOID );
+extern ULONG Irql2Mask[];
+
+KINTERRUPT HalpPciErrorInt;
+KINTERRUPT HalpBusErrorInt;
+KINTERRUPT HalpMemoryErrorInt;
+
+KINTERRUPT HalpHandleClockInterrruptOnOther;
+
+
+
+extern ULONG registeredInts[];
+
+extern VOID KiDispatchSoftwareInterrupt( VOID);
+extern BOOLEAN HalAcknowledgeIpi (VOID);
+ULONG HalpGetHighVector(ULONG);
+
+
+extern ULONG HalpSpuriousInterruptCount;
+extern UCHAR HalpSioInterrupt1Mask,HalpSioInterrupt2Mask;
+extern UCHAR HalpSioInterrupt1Level, HalpSioInterrupt2Level;
+extern ULONG Vector2Irql[];
+ULONG HalpSpuriousInts = 0;
+
+
+/*
+ * HalpHandleExternalInterrupt
+ *
+ * Description:
+ *
+ * This is the main external interrupt handler. It is called whenever
+ * an external interrupt occurs. It interfaces to the ASICs that
+ * cause the external interrupt and vectors to the corresponding
+ * interrupt handling routine.
+ *
+ * Issues:
+ *
+ * Not implemented Yet (sfk 8/26/95).
+ * The returnValue of the driver should be checked and if the driver
+ * did not handle the interrupt, we should consider clearing the interrupt
+ * and broadcasting an interrupt error message.
+ */
+BOOLEAN
+HalpHandleExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+ PSECONDARY_DISPATCH SioHandler;
+ PKINTERRUPT SioInterrupt;
+ ULONG TmpSysVector;
+ USHORT interruptVector;
+ BOOLEAN returnValue;
+ KIRQL OldIrql;
+ ULONG OldMask;
+ UCHAR Irql, i;
+ register UCHAR CpuId;
+
+ //
+ // Assert that interrupts are disabled (or just disable them for now)
+ //
+ HASSERT(!MSR(EE));
+
+ //
+ // Use a local variable for CPU.
+ //
+ CpuId = (UCHAR) GetCpuId();
+
+ //
+ // indicate are in interrupt handler...
+ //
+ SET_LEDS(0xf0 & ~(LED_1));
+
+ //
+ // Get the value out of the (ESCC/TIO) register
+ // Compute interrupt vector number.
+ //
+ TmpSysVector = RInterruptPending(CpuId);
+ if (TmpSysVector == 0) {
+ // For a spurious interrupt, simply return
+#if defined(HALDEBUG_ON)
+ HalpDebugPrint("HalpHandleExternalInterrupt: Spurious Interrupt");
+#endif
+ return FALSE;
+ }
+ //
+ // We must now find the highest priority interrupt to service.
+ // Since the Pending register is not ordered in correct
+ // priority order, we muse "find" the highest priority
+ // interrupt. Servicing a lower priority interrupt will cause us
+ // to nest too deeply on the interrupt stack and panic.
+ //
+ for (i = HIGH_LEVEL; i > DISPATCH_LEVEL; i--) {
+ if ((Irql2Mask[i] & TmpSysVector) != 0) {
+ break;
+ }
+ }
+ HASSERT(i >= PCR->CurrentIrql);
+ TmpSysVector &= Irql2Mask[i];
+
+ //
+ // Now find any single bit of the bits left.
+ //
+ interruptVector = (USHORT) HalpGetHighVector(TmpSysVector);
+
+ //
+ // Turns off ASIC Interrupts (ESCC/TIO).
+ // Need more protection than KeRaisIrql currently provides.
+ //
+ OldIrql = PCR->CurrentIrql;
+ Irql = (UCHAR) Vector2Irql[interruptVector];
+ HASSERT(Irql > i);
+ PCR->CurrentIrql = Irql;
+ OldMask = RInterruptMask(CpuId);
+
+ //
+ // Mask Handling has varied over time based on how well
+ // nesting works. The proper answer is to mask off all of the
+ // interrupts that are a lesser priority than the one
+ // we are currently handling. Using the same code as KeRaiseIrql
+ // does.
+ //
+ RInterruptMask(CpuId) = (Irql2Mask[Irql]&registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+ HASSERT((RInterruptMask(CpuId) & (1 << interruptVector)) == 0);
+
+ //
+ // Clear the interrupt out of the request register by writing a one
+ // for the handled interrupt.
+ //
+ rInterruptRequest = (1 << interruptVector);
+ FireSyncRegister();
+
+ //
+ // if the new IRQL level is lower than clock2_level, restore
+ // system interrupts to allow decrementer interrupts:
+ // Restoring the interrupt bit in the MSR here allows the
+ // debugger to break into this routine (or a driver ISR) if
+ // the system hangs
+ //
+ if (Irql < CLOCK2_LEVEL) {
+ HalpEnableInterrupts();
+ }
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+ SioHandler = (PSECONDARY_DISPATCH)
+ PCR->InterruptRoutine[DEVICE_VECTORS + interruptVector];
+
+ //
+ // A small bit of hack logic. We need a way to make sure that a
+ // "valid" registration has occured for this interrupt. We compare
+ // the handler with the "known" Unexpected interrupt handler routine.
+ // Use location 255 to get it.
+ //
+ if (SioHandler == (PSECONDARY_DISPATCH) PCR->InterruptRoutine[255]) {
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpHandleExternalInterrupt: %d not registered\n",
+ interruptVector););
+ returnValue = FALSE;
+ } else {
+ SioInterrupt = CONTAINING_RECORD(SioHandler,
+ KINTERRUPT, DispatchCode[0]);
+ returnValue = SioHandler(SioInterrupt,
+ SioInterrupt->ServiceContext,
+ TrapFrame);
+ }
+
+ //
+ // Now disable the PowerPC interrupts to provide protection
+ // for the exit portion of the interrupt handling.
+ //
+ HalpDisableInterrupts();
+
+ //
+ // indicate are exiting the interrupt handler...
+ //
+ SET_LEDS(0xf0 & ~(0x1));
+
+ //
+ // Now lower the IRQL
+ //
+ PCR->CurrentIrql = OldIrql;
+ RInterruptMask(CpuId) = OldMask;
+ WaitForRInterruptMask(CpuId);
+ HASSERT(RInterruptMask(CpuId) ==
+ (Irql2Mask[PCR->CurrentIrql] & registeredInts[CpuId]));
+ return(returnValue);
+}
+
+/*
+ * HalpHandleIpiInterrupt
+ *
+ * Clear the IPI and call the kernel's handler
+ */
+BOOLEAN
+HalpHandleIpiInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+ if (HalAcknowledgeIpi()) {
+ KeIpiInterrupt(TrapFrame);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+int
+PHalpInterruptSetup( VOID )
+{
+ UCHAR DataByte,Isr;
+
+ HalpSetIntPriorityMask();
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ rMasterIntPort0 = DataByte;
+ rSlaveIntPort0 = DataByte;
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+ rMasterIntPort1 = DataByte;
+ FireSyncRegister();
+
+ DataByte = 0x08;
+ rSlaveIntPort1 = DataByte;
+ FireSyncRegister();
+
+ //
+ // The third initialization control word set the slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a number.
+ //
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+ rMasterIntPort1 = DataByte;
+ FireSyncRegister();
+
+ DataByte = SLAVE_IRQL_LEVEL;
+ rSlaveIntPort1 = DataByte;
+ FireSyncRegister();
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ //
+ // setup for auto end of interrupt mode in case of firepower
+ //
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->AutoEndOfInterruptMode = 1;
+
+
+ rMasterIntPort1 = DataByte;
+ rSlaveIntPort1 = DataByte;
+ FireSyncRegister();
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpSioInterrupt1Mask = (UCHAR)~(1 << SLAVE_IRQL_LEVEL);
+
+ rMasterIntPort1 = DataByte;
+
+ HalpSioInterrupt2Mask = 0xFF;
+
+ rSlaveIntPort1 = DataByte;
+
+// define priority specifically IRQ 7 is set to priority 15, while IRQ 0 is set
+// to 1. So, tell the SIO to affix the lowest priority to IRQ 7: 110 00 111
+// should do it: this sets the command to "set priority" and says IRQ 7 is
+// the lowest priority [ 111 ].
+
+ DataByte=0xc7;
+ rMasterIntPort0 = DataByte;
+ rSlaveIntPort0 = DataByte;
+
+// Read the IRR:
+ DataByte=0x0a;
+ rMasterIntPort0 = DataByte;
+ Isr = rMasterIntPort0;
+ HDBG(DBG_GENERAL, HalpDebugPrint("Master: IRR is %x .. ",Isr););
+
+// Read the ISR
+ DataByte=0x0b;
+ rMasterIntPort0 = DataByte;
+ Isr = rMasterIntPort0;
+ HDBG(DBG_GENERAL, HalpDebugPrint("ISR is %x .. \n",Isr););
+
+ //
+ // Set up the system error registers for use: Mask off Video ints, clear
+ // anything pending:
+ //
+
+ //
+ // Clear the PCI Bus error cause register and mask-enable pci error ints
+ //
+ rPCIBusErrorCauseSet = 0x0;
+ rPCIBusErrorCause = 0xffffffff;
+ FireSyncRegister();
+
+ //
+ // Clear the Memory Bus error cause register and mask-enable memory
+ // error ints. Note: (breeze 3/6/95 ) I removed the earlier comments.
+ //
+ rErrorStatus0Set = 0x0;
+ rErrorStatus0 = 0xffffffff;
+ rErrorMask =
+ (ECC_CORRECTED|ECC_FAILED|ADDRESS_PARITY_ERROR|DATA_PARITY_ERROR|
+ MEM_PARITY_ERROR|INVALID_XACT);
+
+ //
+ // IBM 604 Processors (revision 3.3) have parity problems. For these
+ // processors we unset DATA_PARITY to avoid dying from a false
+ // parity error. ES machines only used the Motorola processors
+ // so check for PowerTOP.
+ //
+ if ((SystemType == SYS_POWERTOP) && (ProcessorType == PPC_604)) {
+ if (HalpGetProcessorVersion() == 0x00040303) {
+ rErrorMask &= ~DATA_PARITY_ERROR;
+ }
+ }
+ FireSyncRegister();
+
+ //
+ // Clear the Video error register and disable video ints
+ //
+ rVidInt = 0xffffffff;
+ rVidIntMask = 0x00000000;
+ FireSyncRegister();
+
+ if (!HalpEnableInterruptHandler(&HalpPciErrorInt,
+ (PKSERVICE_ROUTINE) HalpMemoryHandler,
+ NULL,
+ NULL,
+ DEVICE_VECTORS + PCI_ERROR_NUM,
+ 28,
+ 28,
+ Latched,
+ FALSE,
+ 0, // Processor Number
+ FALSE,
+ InternalUsage,
+ DEVICE_VECTORS + PCI_ERROR_NUM)) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+ if (!HalpEnableInterruptHandler(&HalpBusErrorInt,
+ (PKSERVICE_ROUTINE) HalpMemoryHandler,
+ NULL,
+ NULL,
+ DEVICE_VECTORS + CPU_BUS_ERROR_NUM,
+ 28,
+ 28,
+ Latched,
+ FALSE,
+ 0, // Processor Number
+ FALSE,
+ InternalUsage,
+ DEVICE_VECTORS + CPU_BUS_ERROR_NUM)) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ if (SystemType == SYS_POWERPRO) {
+ if (!HalpEnableInterruptHandler(&HalpMemoryErrorInt,
+ (PKSERVICE_ROUTINE) HalpMemoryHandler,
+ NULL,
+ NULL,
+ DEVICE_VECTORS + MEMORY_ERROR_VIDEO_NUM,
+ 28,
+ 28,
+ Latched,
+ TRUE, // share with the video-in ISR...
+ // FALSE,
+ 0, // Processor Number
+ FALSE,
+ InternalUsage,
+ DEVICE_VECTORS +
+ MEMORY_ERROR_VIDEO_NUM)) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+ }
+
+ return(0);
+}
+
+
+
+//
+// Initialize interrupts on processors other than the main (boot) processor.
+//
+//
+ULONG
+HalpInitInts( ULONG ProcessorNumber )
+{
+
+ ULONG Mask;
+
+ HDBG(DBG_INTERNAL,
+ HalpDebugPrint("HalpInitInts: entered Cpu (%d)\n", ProcessorNumber));
+
+ //
+ // Make sure all the interrupts are masked off and any potential
+ // interrupts are cleared from the pending register. This is a percpu
+ // action and makes sure that this cpu starts off with a known
+ // interrupt state.
+ //
+ HalpDisableInterrupts();
+ RInterruptMask(GetCpuId()) = ALL_INTS_OFF;
+ WaitForRInterruptMask(GetCpuId());
+
+ //
+ // Connect the external interrupt handler first, then the other
+ // handlers for external events may be installed....
+ //
+
+ PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ (PKINTERRUPT_ROUTINE) HalpHandleExternalInterrupt;
+
+ //
+ // register the interrupt vector with the HAL
+ //
+
+ HalpRegisterVector(InternalUsage,
+ EXTERNAL_INTERRUPT_VECTOR,
+ EXTERNAL_INTERRUPT_VECTOR,
+ HIGH_LEVEL);
+
+ //
+ // Connect the IPI interrupt handler directly to the CPU dispatch table
+ // without registering with the kernel. The IPI interrupt has
+ // already been registered with the HAL by CPU 0 in HalpCreateSioStructures
+ // so we don't need to do it again here.
+ //
+
+ PCR->InterruptRoutine[DEVICE_VECTORS + 31] =
+ (PKINTERRUPT_ROUTINE) HalpHandleIpiInterrupt;
+
+ //
+ // Now enable the IPI interrupt on this CPU; the HAL must do this
+ // directly since we did not register with the kernel.
+ // It should be alright to call this routine directly rather than
+ // HalEnableSystemInterrupt because interrupts are disabled.
+ //
+ HalpEnableSioInterrupt(DEVICE_VECTORS + 31, Latched);
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpInitInts: Enabled IPI handler \n"););
+
+ //
+ // Initialize the Machine Check interrupt handler
+ //
+ if (HalpEnableInterruptHandler(&HalpMachineCheckInterrupt,
+ HalpHandleMachineCheck,
+ NULL,
+ NULL,
+ MACHINE_CHECK_VECTOR,
+ MACHINE_CHECK_LEVEL,
+ MACHINE_CHECK_LEVEL,
+ Latched,
+ FALSE,
+ (CCHAR) ProcessorNumber,
+ FALSE,
+ InternalUsage,
+ MACHINE_CHECK_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ // Connect directly to the decrementer handler. This is done
+ // directly rather than thru HalpEnableInterruptHandler due to
+ // special handling required because the handler calls KdPollBreakIn().
+ //
+
+
+ PCR->InterruptRoutine[DECREMENT_VECTOR] =
+ (PKINTERRUPT_ROUTINE) HalpHandleDecrementerInterrupt1;
+
+ HalpUpdateDecrementer(1000); // Get those decrementer ticks going
+
+ //
+ // Make sure the mask is set correctly at the mask register for this cpu:
+ //
+ Mask = RInterruptMask(GetCpuId());
+ if (Mask != CPU_MESSAGE_INT) {
+ HalpDebugPrint("HalpInitInts: no CPU_MESSAGE_INT\n");
+ }
+
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpInitInts: exit\n"););
+ return (0);
+}
+
+//
+// Some quick code for handling memory bus errors
+//
+BOOLEAN
+HalpMemoryHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+ ULONG causeValue;
+
+ //
+ // Proper handling of Memory, CPU and PCI errors.
+ //
+ switch ((Interrupt->Vector - DEVICE_VECTORS)) {
+ case MEMORY_ERROR_VIDEO_NUM: {
+ ULONG addr;
+
+ //
+ // Read the register so that we can see it on a logic analyzer
+ //
+ causeValue = rErrorStatus0;
+
+ //
+ // check for valid video-in interrupt if on a powertop system. If
+ // there is a valid video-in interrupt AND no valid cause other than
+ // a memory int, then return false and let the video driver handle
+ // this.
+ // If there is a cause, then handle the memory error cause
+ // regardless of the video-in case:
+ //
+ if ( causeValue == 0x0 ) {
+ return FALSE; // return false in any case since no
+ // cause was found!!
+ }
+
+ //
+ // This is not a true error, just record it in the registry
+ // (recording in registry not implemented yet - sfk 2/20/95 - XXX)
+ //
+ // Don't bother checking for video-in interrupt here. If there is
+ // a video interrupt awaiting action, it should be picked up when
+ // the hal returns from interrupt since the uncleared int will be
+ // automatically re-asserted when cpu ints are re-enabled via the
+ // MSR(EE) action.
+ //
+ if (causeValue&ERROR_ECC_CORRECTED) {
+ ULONG rc;
+ ULONG count = 0, total = 0;
+ const PCHAR varname = "PARITY_ERROR";
+ CHAR buf[80];
+
+ rErrorStatus0 |= ERROR_ECC_CORRECTED;
+ FireSyncRegister();
+
+ //
+ // record the error count to NVRAM as:
+ // # errors this boot, # errors forever
+ //
+ MemoryParityErrorsThisBoot++;
+ MemoryParityErrorsForever++;
+ sprintf(buf, "%d,%d",
+ MemoryParityErrorsThisBoot,
+ MemoryParityErrorsForever
+ );
+ rc = HalSetEnvironmentVariable(MemoryParityErrorsVarName, buf);
+ if (ESUCCESS != rc) {
+ // what to do?
+ }
+ return TRUE;
+ }
+ //
+ // Now we panic: Make sure that in the process we don't fall
+ // into a loop of parity errors, so turn off memory parity errors,
+ // and the other errors as well:
+ //
+ rErrorMask &= ~(MEM_PARITY_ERROR |
+ INVALID_XACT
+ );
+
+ addr = (rErrorAddr0 & 0xff000000);
+ addr |= ((rErrorAddr1 & 0xff000000) >> 8);
+ addr |= ((rErrorAddr2 & 0xff000000) >> 16);
+ addr |= ((rErrorAddr3 & 0xff000000) >> 24);
+
+ //
+ // Show the user what happened before we die
+ //
+ HalpForceDisplay("MEMORY_ERROR cause(0x%08x) at 0x%08x\n",
+ causeValue&0xff000000, addr);
+
+ //
+ // Decode the cause into ascii strings for the user impatiently
+ // waiting for enlightenment from the dead machine: Before
+ // reincarnation, what major transgression did we commit?
+ //
+
+ if( causeValue&ERROR_DATA_PARITY) {
+ HalpForceDisplay("DATA PARITY");
+ }
+ if (causeValue&ERROR_MEM_PARITY) {
+ HalpForceDisplay(", MEMORY PARITY");
+ }
+ if (causeValue&ERROR_ECC_FAILED) {
+ HalpForceDisplay(", ECC FAILED");
+ }
+ if (causeValue&ERROR_INVALID_XACT) {
+ HalpForceDisplay(", Bad bus transaction: burst access to rom or io space?");
+ }
+ HalpForceDisplay("\n\n");
+
+ //
+ // Clear the Memory Error. Since we only want one error
+ // of each type (max.), we mask off the error we just
+ // received.
+ //
+ rErrorMask &= ~causeValue;
+ rErrorStatus0 = causeValue;
+ FireSyncRegister();
+ break;
+
+ }
+
+ case PCI_ERROR_NUM:
+ //
+ // Read the register so that we can see it on a logic analyzer
+ //
+ causeValue = rPCIBusErrorCause;
+
+ //
+ // This is not a true error, just record it in the registry
+ // (recording in registry not implemented yet - sfk 2/20/95 - XXX)
+ //
+ if (causeValue&PCI_ERROR_DEV_TIMEOUT) {
+ rPCIBusErrorCause = PCI_ERROR_DEV_TIMEOUT;
+ FireSyncRegister();
+ return TRUE;
+ }
+
+ // This also may not be a true error; we must check the Pci status
+ // registers
+ if( causeValue& PCI_ERROR_TARGET_ABORT) {
+ // Scan the Primary Pci status registers
+ ULONG devs;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ for (devs = 0; devs < MAXIMUM_PCI_SLOTS; devs++) {
+ HalGetBusData (
+ PCIConfiguration,
+ 0,
+ devs,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ continue;
+ }
+
+ if (PciData->Status & PCI_STATUS_SIGNALED_TARGET_ABORT) {
+ // We can ignore this one; clear the error bits
+ rPCIBusErrorCause = PCI_ERROR_TARGET_ABORT;
+ PciData->Status = PCI_STATUS_SIGNALED_TARGET_ABORT;
+ HalSetBusDataByOffset(
+ PCIConfiguration,
+ 0,
+ devs,
+ &PciData->Status,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ Status),
+ 1);
+ FireSyncRegister();
+ return TRUE;
+ }
+ }
+ }
+
+ //
+ // Show the user what happened before we die
+ //
+ HalpForceDisplay("\nPCI_ERROR cause(0x%08x) at 0x%08x\n",
+ causeValue, rPCIBusErrorAddressRegister);
+
+ if( causeValue& PCI_ERROR_SIGNALED_SYS) {
+ HalpForceDisplay("Address parity error on PCI bus\n");
+ }
+ if( causeValue& PCI_ERROR_DATA_PARITY) {
+ HalpForceDisplay("Data parity error on PCI bus\n");
+ }
+ if( causeValue& PCI_ERROR_DEV_TIMEOUT) {
+ HalpForceDisplay("Device Timeout: Master Aborted\n");
+ }
+ if( causeValue& PCI_ERROR_TARGET_ABORT) {
+ HalpForceDisplay("Target Aborted or Master experienced a fatal error\n");
+ }
+ HalpForceDisplay("\n\n");
+
+ //
+ // Clear the PCI Error
+ //
+ rPCIBusErrorCause = causeValue;
+ FireSyncRegister();
+ break;
+
+ case CPU_BUS_ERROR_NUM:
+ //
+ // Read the register so that we can see it on a logic analyzer
+ //
+ causeValue = rCPUBusErrorCause;
+
+ //
+ // Show the user what happened before we die
+ //
+ HalpForceDisplay("CPU_ERROR cause(0x%08x) at 0x%08x\n",
+ causeValue, rCPUBusErrorAddressRegister);
+
+ //
+ // Clear the Bus Error
+ //
+ rCPUBusErrorCause = causeValue;
+ FireSyncRegister();
+ break;
+
+ default:
+ //
+ // We should not be here, bug check because things are not sane
+ // if we got this far.
+ //
+ HalpForceDisplay("Unknown Bus Error (%d)\n",
+ (Interrupt->Vector - DEVICE_VECTORS));
+ break;
+
+ } // end of switch statement.....
+
+ //
+ // If we make it to here, we just stop the system (cold).
+ //
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+ //
+ // This should never return but just in case
+ //
+ HalpDisableInterrupts();
+here:
+ goto here;
+
+}
diff --git a/private/ntos/nthals/halfire/ppc/phsystem.h b/private/ntos/nthals/halfire/ppc/phsystem.h
new file mode 100644
index 000000000..03b211f40
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/phsystem.h
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 1995 Firepower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: phsystem.h $
+ * $Revision: 1.28 $
+ * $Date: 1996/05/14 02:33:25 $
+ * $Locker: $
+ */
+
+#ifndef PHSYSTEM_H
+#define PHSYSTEM_H
+
+//
+// (sfk 11/3/94)
+// Should this be placed here or directly included?
+//
+#include "fpreg.h"
+#include "stdio.h"
+#include "ntverp.h"
+
+// defined 'special' address space for system memory [rdl:01.04.95]
+#define MEMORY_ADDRESS_SPACE 0
+#define IO_ADDRESS_SPACE 1
+#define SYSTEM_ADDRESS_SPACE 2
+
+BOOLEAN HalpInitializeDisplay1(PLOADER_PARAMETER_BLOCK);
+ULONG HalpInitInts( ULONG CpuNumber );
+VOID HalpInitPciBusEarly( PLOADER_PARAMETER_BLOCK );
+int PHalTriggerEvent( ULONG returndata );
+int PHalSetupGpio( ULONG LEDFLAGS );
+VOID PHalBlinkLeds( UCHAR LEDS, ULONG Rate, ULONG LEDFLAGS );
+int PHalpInterruptSetup( VOID );
+BOOLEAN PHalpHandleIpi( PKINTERRUPT , PVOID , PVOID );
+VOID PHalpDumpLoaderBlock ( PLOADER_PARAMETER_BLOCK );
+VOID PHalpDumpConfigData ( PCONFIGURATION_COMPONENT_DATA, PULONG );
+VOID PHalDumpTree ( PCONFIGURATION_COMPONENT_DATA );
+BOOLEAN PHalpEisaDispatch( PKINTERRUPT , PVOID , PVOID );
+int PH_HalVersion( VOID );
+ULONG HalpCheckString( PCHAR , PCHAR );
+ULONG HalpSetPixelColorMap( ULONG , ULONG );
+BOOLEAN HalpInitIntelAIP ( VOID );
+VOID PH_HalVersionInternal( VOID );
+VOID PH_HalVersionExternal( VOID );
+VOID HalpResetByKeyboard(VOID);
+VOID HalpSetupDCC(ULONG, ULONG);
+
+BOOLEAN HalpMemoryHandler(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame);
+
+BOOLEAN HalpHandleExternalInterrupt( IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+ULONG HalpGetProcessorRev( VOID);
+
+// define the start address for system register space, apart
+// from eisa/pci specific registers
+//
+// PVOID HalpSysBase = (PVOID) 0xff000000;
+// PVOID HalpSysBase = (PVOID) 0x8000ff00;
+
+extern PVOID HalpSystemSpace;
+extern PVOID HalpIoControl;
+extern PVOID HalpVideMemoryBase;
+extern PVOID HalpSystemControlBase;
+extern BOOLEAN HalpInitializeRegistry (IN PLOADER_PARAMETER_BLOCK LoaderBlock);
+extern ULONG HalpGetCycleTime(VOID);
+extern ULONG HalpProcessorCount(VOID);
+extern ULONG HalpGetCycleTime(VOID);
+
+#define LED_0 0x01 // led 0
+#define LED_1 0x02 // led 1
+#define LED_2 0x04 // led 2
+#define LED_3 0x08 // led 3
+#define LED_EMIT 0xf0 // led direction bits in gpio register
+
+#define LED_ON 0xffffffff
+#define LED_OFF 0x00000000
+//#define DCC_INDX 0x840
+//#define DCC_DATA 0x841
+#define GPIOA 0x2
+// #define WAIT_TIME 0xf000000
+#define WAIT_TIME 0x800000
+
+typedef struct _DCC_CONTROL {
+ UCHAR space[0x840];
+ UCHAR DccIndxReg; // this should show up at address base + 840
+ UCHAR DccDataReg; // this should show up at address base + 841
+ UCHAR DccTestAddr; // this is for test purposes....
+} DCC_CONTROL, *P_DCC_CONTROL;
+
+typedef struct _Address_Map {
+ ULONG System;
+ ULONG IO;
+ ULONG General;
+} Address_Map, *PAddress_Map;
+
+
+typedef struct {
+ ULONG EntryCounter;
+ ULONG ExitCounter;
+ ULONG Flags; // keep track of where in the routine you are..
+ ULONG Isr;
+ ULONG TmpMask;
+ ULONG MasksDifferFlag;
+ ULONG SysInterruptVector;
+ ULONG Intbucket; // bit map each int type seen
+ ULONG CompareMask;
+ ULONG BusyCount;
+ ULONG Bloob;
+ ULONG LastCount;
+} HalState, *PHalState;
+
+//
+// System Descriptions:
+// Hold a description of the system for the hal to use
+// to determine what form it should take.
+
+//
+// Declare an enumerated type for asking which processor the
+// system is currently running on.
+//
+typedef struct {
+ ULONG Flags;
+ ULONG HashSize;
+ PCHAR ProcessorName;
+ PCHAR ProductNumber;
+} PROCESSOR_DESCRIPTION;
+
+//
+// Flags for defining the capabilities of the cpu,
+// and the enumerated labels for marking what
+// cpu we're on.
+//
+#define PROC_NOSUPP 0x00000000
+#define PROC_SUPP 0x00000001
+#define PROC_HASHTABLE 0x00000002
+#define PROC_MPCAPABLE 0x00000004
+
+typedef enum {
+ PPC_UNKNOWN = 0,
+ PPC_601 = 1,
+ PPC_602 = 2,
+ PPC_603 = 3,
+ PPC_604 = 4,
+ PPC_605 = 5,
+ PPC_606 = 6,
+ PPC_607 = 7,
+ PPC_608 = 8,
+ PPC_609 = 9,
+ nPROCESSOR_TYPE
+} PROCESSOR_TYPE;
+
+extern PROCESSOR_DESCRIPTION ProcessorDescription[];
+extern PROCESSOR_TYPE ProcessorType;
+
+//
+// System IDENT Values:
+//
+#define ESCC_IDENT 0x60730000 // chip only in pro
+#define TSC_IDENT 0x60370000 // chip only in top ( currently )
+
+
+//
+// Flags to label the capabilities of the system as a whole:
+//
+#define SYS_NOSUPP 0x00000000 // system is not supported by this hal.
+#define SYS_SUPP 0x00000001 // system is supported by this hal.
+#define SYS_MPCAPABLE 0x00000002 // system is able to support more than one cpu.
+#define SYS_MPFOREAL 0x00000004 // system is able to have more than one cpu.
+
+typedef enum {
+ SYS_UNKNOWN = 0,
+ SYS_POWERPRO = 1, // 0x60730000
+ SYS_POWERTOP = 2, // 0x60370000
+ SYS_POWERSERVE = 3, // 0x60370000 ???? don't know yet
+ SYS_POWERSLICE = 4,
+ nSYSTEM_TYPE
+} SYSTEM_TYPE ;
+
+typedef struct {
+ ULONG Flags;
+ PCHAR SystemName;
+} SYSTEM_DESCRIPTION, PSYSTEM_DESCRIPTION;
+
+typedef struct _HW_DESCRIPTION {
+ ULONG HwFlags;
+ ULONG Spare;
+}HARDWARE_DESCRIPTION;
+extern SYSTEM_DESCRIPTION SystemDescription[];
+extern SYSTEM_TYPE SystemType;
+extern VOID HalpInitIoBuses ( VOID );
+
+#define IRQ0 1
+
+extern ULONG PciDeviceIDs[4][256];
+extern ULONG PciClassInfo[4][256];
+
+
+//
+// these values show up in the lower byte of the interrupt word read out of
+// the system register...
+//
+#define VEC_Timer 0x0001
+#define VEC_Keyboard 0x0002
+#define VEC_Cascade 0x0004
+#define VEC_Serial2 0x0008
+#define VEC_Serial1 0x0010
+#define VEC_Display 0x0020
+#define VEC_Floppy 0x0040
+#define VEC_Parallel1 0x0080
+//
+// these values show up in the secondary next byte
+// of the SIO
+//
+#define VEC_RTC 0x0100
+#define VEC_Open9 0x0200
+#define VEC_Audio 0x0400
+#define VEC_PCI 0x0800
+#define VEC_Mouse 0x1000
+#define VEC_Scsi 0x2000
+#define VEC_Enet 0x4000
+#define VEC_Open15 0x8000
+
+#define HalPrint HalpDebugPrint
+#define HalpPrint HalpDebugPrint
+
+#define HalBreak(x)
+#define SEE_DEFINES A_DEFINES
+#define SET_STRING(x) #x
+
+//
+//Declare The BAT Support Routines [ged]
+//
+ULONG HalpGetUpperIBAT(ULONG);
+ULONG HalpGetLowerIBAT(ULONG);
+ULONG HalpGetUpperDBAT(ULONG);
+ULONG HalpGetLowerDBAT(ULONG);
+VOID HalpSetLowerDBAT1(ULONG);
+VOID HalpSetUpperDBAT1(ULONG);
+// Add more BAT Support Routines [rdl:01.03.95]
+VOID HalpSetUpperDBAT(ULONG,ULONG);
+VOID HalpSetLowerDBAT(ULONG,ULONG);
+
+//
+// Memory parity error variables
+//
+
+#define MemoryParityErrorsVarName "MEMORY_PARITY_ERRORS"
+extern ULONG MemoryParityErrorsThisBoot;
+extern ULONG MemoryParityErrorsForever;
+
+//
+// Useful macros for pragma message, ie. #pragma message(REVIEW "some text")
+//
+#define QUOTE(x) #x
+#define IQUOTE(x) QUOTE(x)
+#define REVIEW __FILE__ "(" IQUOTE(__LINE__) ") : REVIEW -> "
+
+
+#define NOTE(x) message(REVIEW IQUOTE(x) )
+
+#define PAUSE for(;;) { \
+ }
+
+
+#endif // PHSYSTEM_H
diff --git a/private/ntos/nthals/halfire/ppc/phsystem.s b/private/ntos/nthals/halfire/ppc/phsystem.s
new file mode 100644
index 000000000..b3ce390b9
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/phsystem.s
@@ -0,0 +1,487 @@
+//++
+//
+// Copyright (c) 1994 FirePower Systems INC.
+//
+// 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:
+//
+// pxsystem.s
+//
+// Abstract:
+//
+// This module implements the routines to handle system functions:
+// Provides system specific info.
+// Currently provides processor version type
+//
+// Author:
+// breeze@firepower.com
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: phsystem.s $
+ * $Revision: 1.7 $
+ * $Date: 1996/01/11 07:08:26 $
+ * $Locker: $
+ */
+
+#include "kxppc.h"
+
+//++
+//
+// Routine Description:
+//
+//
+// Arguments:
+// HalProcessorRev, in r3
+//
+//
+// Return Value:
+// Processor Version register value
+//
+//
+//--
+
+
+ LEAF_ENTRY(HalpGetProcessorRev)
+ mfpvr r.3 // get processor version
+ LEAF_EXIT(HalpGetProcessorRev)
+
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpGetUpperIBAT(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit upper instruction BAT value for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit upper BAT value.
+******************************************************************************/
+
+ .set BatNumber, r.3
+
+ LEAF_ENTRY(HalpGetUpperIBAT)
+
+ cmpli 0,0,BatNumber,0
+ bne NotUI0
+ mfibatu BatNumber,0
+ b ExitUI
+NotUI0:
+ cmpli 0,0,BatNumber,1
+ bne NotUI1
+ mfibatu BatNumber,1
+ b ExitUI
+NotUI1:
+ cmpli 0,0,BatNumber,2
+ bne NotUI2
+ mfibatu BatNumber,2
+ b ExitUI
+NotUI2:
+ mfibatu BatNumber,3 // OK, it's three by default
+
+ExitUI:
+
+ LEAF_EXIT(HalpGetUpperIBAT)
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpGetLowerIBAT(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit lower instruction BAT value for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit lower BAT value.
+******************************************************************************/
+
+ LEAF_ENTRY(HalpGetLowerIBAT)
+
+ cmpli 0,0,BatNumber,0
+ bne NotLI0
+ mfibatl BatNumber,0
+ b ExitLI
+NotLI0:
+ cmpli 0,0,BatNumber,1
+ bne NotLI1
+ mfibatl BatNumber,1
+ b ExitLI
+NotLI1:
+ cmpli 0,0,BatNumber,2
+ bne NotLI2
+ mfibatl BatNumber,2
+ b ExitLI
+NotLI2:
+ mfibatl BatNumber,3 // OK, it's three by default
+
+ExitLI:
+
+ LEAF_EXIT(HalpGetLowerIBAT)
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpGetUpperDBAT(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit upper data BAT value for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit upper BAT value.
+******************************************************************************/
+
+ LEAF_ENTRY(HalpGetUpperDBAT)
+
+ cmpli 0,0,BatNumber,0
+ bne NotUD0
+ mfdbatu BatNumber,0
+ b ExitUD
+NotUD0:
+ cmpli 0,0,BatNumber,1
+ bne NotUD1
+ mfdbatu BatNumber,1
+ b ExitUD
+NotUD1:
+ cmpli 0,0,BatNumber,2
+ bne NotUD2
+ mfdbatu BatNumber,2
+ b ExitUD
+NotUD2:
+ mfdbatu BatNumber,3 // OK, it's three by default
+
+ExitUD:
+
+ LEAF_EXIT(HalpGetUpperDBAT)
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpGetLowerDBAT(ULONG BatNumber) [ged]
+
+ Purpose:
+ Supplies the 32-bit lower data BAT value for a given <BatNumber>.
+
+ Returns:
+ Returns the 32-bit lower BAT value.
+******************************************************************************/
+
+ LEAF_ENTRY(HalpGetLowerDBAT)
+
+ cmpli 0,0,BatNumber,0
+ bne NotLD0
+ mfdbatl BatNumber,0
+ b ExitLD
+NotLD0:
+ cmpli 0,0,BatNumber,1
+ bne NotLD1
+ mfdbatl BatNumber,1
+ b ExitLD
+NotLD1:
+ cmpli 0,0,BatNumber,2
+ bne NotLD2
+ mfdbatl BatNumber,2
+ b ExitLD
+NotLD2:
+ mfdbatl BatNumber,3 // OK, it's three by default
+
+ExitLD:
+
+ LEAF_EXIT(HalpGetLowerDBAT)
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpSetUpperDBAT(ULONG BatNumber) [rdl]
+
+ Purpose:
+ Stores the 32-bit upper data BAT value for a given <BatNumber>.
+
+ Returns:
+ N/A
+******************************************************************************/
+
+ .set BatValueToSet, r.4
+
+ LEAF_ENTRY(HalpSetUpperDBAT)
+
+ cmpli 0,0,BatNumber,0
+ bne NotSetUD0
+ mtdbatu 0,BatValueToSet
+ b ExitSetUD
+NotSetUD0:
+ cmpli 0,0,BatNumber,1
+ bne NotSetUD1
+ mtdbatu 1,BatValueToSet
+ b ExitSetUD
+NotSetUD1:
+ cmpli 0,0,BatNumber,2
+ bne NotSetUD2
+ mtdbatu 2,BatValueToSet
+ b ExitSetUD
+NotSetUD2:
+ mtdbatu 3,BatValueToSet // OK, it's three by default
+
+ExitSetUD:
+
+ LEAF_EXIT(HalpSetUpperDBAT)
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpSetLowerDBAT(ULONG BatNumber) [rdl]
+
+ Purpose:
+ Stores the 32-bit lower data BAT value for a given <BatNumber>.
+
+ Returns:
+ N/A
+******************************************************************************/
+
+ LEAF_ENTRY(HalpSetLowerDBAT)
+
+ cmpli 0,0,BatNumber,0
+ bne NotSetLD0
+ mtdbatl 0,BatValueToSet
+ b ExitSetLD
+NotSetLD0:
+ cmpli 0,0,BatNumber,1
+ bne NotSetLD1
+ mtdbatl 1,BatValueToSet
+ b ExitSetLD
+NotSetLD1:
+ cmpli 0,0,BatNumber,2
+ bne NotSetLD2
+ mtdbatl 2,BatValueToSet
+ b ExitSetLD
+NotSetLD2:
+ mtdbatl 3,BatValueToSet // OK, it's three by default
+
+ExitSetLD:
+
+ LEAF_EXIT(HalpSetLowerDBAT)
+
+/******************************************************************************
+ Synopsis:
+ VOID HalpSetLowerDBAT3(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit lower data BAT value <BatValue> to DBAT3.
+
+ Returns:
+ Nothing
+******************************************************************************/
+
+ .set BatValue, r.3
+
+ LEAF_ENTRY(HalpSetLowerDBAT3)
+
+ mtdbatl 3,BatValue
+
+ LEAF_EXIT(HalpSetLowerDBAT3)
+
+/******************************************************************************
+ Synopsis:
+ VOID HalpSetLowerDBAT1(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit lower data BAT value <BatValue> to DBAT1.
+
+ Returns:
+ Nothing
+******************************************************************************/
+
+ LEAF_ENTRY(HalpSetLowerDBAT1)
+
+ mtdbatl 1,BatValue
+
+ LEAF_EXIT(HalpSetLowerDBAT1)
+
+/******************************************************************************
+ Synopsis:
+ VOID HalpSetUpperDBAT1(ULONG BatValue) [ged]
+
+ Purpose:
+ Writes the 32-bit upper data BAT value <BatValue> to DBAT1.
+
+ Returns:
+ Nothing
+******************************************************************************/
+
+ LEAF_ENTRY(HalpSetUpperDBAT1)
+
+ mtdbatu 1,BatValue
+
+ LEAF_EXIT(HalpSetUpperDBAT1)
+
+/******************************************************************************
+
+ Synopsis:
+ VOID HalpDisableDCache()
+******************************************************************************/
+
+ LEAF_ENTRY(HalpDisableDCache)
+
+ .set HID0, 1008
+
+ mtspr HID0, r3
+
+ LEAF_EXIT(HalpDisableDCache)
+
+
+//++
+//
+// void
+// KiSetDbat
+//
+// Routine Description:
+//
+// Writes a set of values to DBAT n
+//
+// No validation of parameters is done. Protection is set for kernel
+// mode access only.
+//
+// Arguments:
+//
+// r.3 Number of DBAT
+// r.4 Physical address
+// r.5 Virtual Address
+// r.6 Length (in bytes)
+// r.7 Coherence Requirements (WIM)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY (KiSetDbat)
+
+ mfpvr r.9 // different format for
+ // 601 vs other 6xx processors
+ cmpwi cr.5, r.3, 1
+ cmpwi cr.6, r.3, 2
+ cmpwi cr.7, r.3, 3
+
+ rlwinm. r.10, r.9, 0, 0xfffe0000// Check for 601
+
+ // calculate mask (ie BSM) If we knew the number passed in was
+ // always a power of two we could just subtract 1 and shift right
+ // 17 bits. But to be sure we will use a slightly more complex
+ // algorithm than will always generate a correct mask.
+ //
+ // the mask is given by
+ //
+ // ( 1 << ( 32 - 17 - cntlzw(Length - 1) ) ) - 1
+ // == ( 1 << ( 15 - cntlzw(Length - 1) ) ) - 1
+
+ addi r.6, r.6, -1
+ oris r.6, r.6, 1 // ensure min length 128KB
+ ori r.6, r.6, 0xffff
+ cntlzw r.6, r.6
+ subfic r.6, r.6, 15
+ li r.10, 1
+ slw r.6, r.10, r.6
+ addi r.6, r.6, -1
+
+ beq cr.0, KiSetDbat601
+
+ // processor is not a 601.
+
+ rlwinm r.7, r.7, 3, 0x38 // position WIM (G = 0)
+ rlwinm r.6, r.6, 2, 0x1ffc // restrict BAT maximum (non 601)
+ // after left shifting by 2.
+ ori r.6, r.6, 0x2 // Valid (bit) in supervisor state only
+ ori r.7, r.7, 2 // PP = 0x2
+ or r.5, r.5, r.6 // = Virt addr | BL | Vs | Vp
+ or r.4, r.4, r.7 // = Phys addr | WIMG | 0 | PP
+
+ beq cr.5, KiSetDbat1
+ beq cr.6, KiSetDbat2
+ beq cr.7, KiSetDbat3
+
+KiSetDbat0:
+ mtdbatl 0, r.4
+ mtdbatu 0, r.5
+ ALTERNATE_EXIT(KiSetDbat)
+
+KiSetDbat1:
+ mtdbatl 1, r.4
+ mtdbatu 1, r.5
+ ALTERNATE_EXIT(KiSetDbat)
+
+KiSetDbat2:
+ mtdbatl 2, r.4
+ mtdbatu 2, r.5
+ ALTERNATE_EXIT(KiSetDbat)
+
+KiSetDbat3:
+ mtdbatl 3, r.4
+ mtdbatu 3, r.5
+ ALTERNATE_EXIT(KiSetDbat)
+
+ // 601 has different format BAT registers and actually only has
+ // one set unlike other PowerPC processors which have seperate
+ // Instruction and Data BATs. The 601 BAT registers are set
+ // with the mtibat[u|l] instructions.
+
+KiSetDbat601:
+
+ rlwinm r.7, r.7, 3, 0x70 // position WIMG (601 has no G bit)
+ rlwinm r.6, r.6, 0, 0x3f // restrict BAT maximum (601 = 8MB)
+ ori r.6, r.6, 0x40 // Valid bit
+ ori r.7, r.7, 4 // Ks = 0 | Ku = 1 | PP = 0b00
+ or r.4, r.4, r.6 // = Phys addr | Valid | BL
+ or r.5, r.5, r.7 // = Virt addr | WIM | Ks | Ku | PP
+
+ beq cr.5, KiSet601Bat1
+ beq cr.6, KiSet601Bat2
+ beq cr.7, KiSet601Bat3
+
+KiSet601Bat0:
+ mtibatl 0, r.4
+ mtibatu 0, r.5
+ ALTERNATE_EXIT(KiSet601Bat)
+
+KiSet601Bat1:
+ mtibatl 1, r.4
+ mtibatu 1, r.5
+ ALTERNATE_EXIT(KiSet601Bat)
+
+KiSet601Bat2:
+ mtibatl 2, r.4
+ mtibatu 2, r.5
+ ALTERNATE_EXIT(KiSet601Bat)
+
+KiSet601Bat3:
+ mtibatl 3, r.4
+ mtibatu 3, r.5
+
+ LEAF_EXIT(KiSetDbat)
+
+/******************************************************************************
+ Synopsis:
+ ULONG HalpGetHighVector(ULONG IntValue)
+
+ Purpose:
+ Find the highest bit turned on and return the bit order
+
+ Returns:
+ Number of leading zeroes
+******************************************************************************/
+
+ .set IntValue, r.3
+
+ LEAF_ENTRY(HalpGetHighVector)
+
+ cntlzw IntValue, IntValue
+ subfic IntValue, IntValue, 0x1f
+
+ LEAF_EXIT(HalpGetHighVector)
diff --git a/private/ntos/nthals/halfire/ppc/phvrsion.c b/private/ntos/nthals/halfire/ppc/phvrsion.c
new file mode 100644
index 000000000..81f79d3b9
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/phvrsion.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 1995,1996 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: phvrsion.c $
+ * $Revision: 1.47 $
+ * $Date: 1996/06/25 16:06:34 $
+ * $Locker: $
+ */
+
+#include "halp.h"
+#include "phsystem.h"
+#include "fparch.h"
+#include "ntverp.h"
+#include "string.h"
+
+typedef CHAR Names[20];
+
+ LONG i=0;
+ Names ScopeList[] = {
+ "Engineering",
+ "Manufacturing",
+ "Testing",
+ "Customer",
+ };
+ Names RelList[] = {
+ "General",
+ "OfficiaL",
+ "Testing",
+ "Controlled",
+ "Lab use"
+ };
+
+//
+// to avoid cascading headers
+//
+NTSYSAPI
+NTSTATUS
+NTAPI
+RtlCharToInteger (
+ PCSZ String,
+ ULONG Base,
+ PULONG Value
+ );
+
+#define HAL_DISPLAY_DEFINES(a) \
+ if (state == 3) { \
+ HalDisplayString("\n"); \
+ state = 0; \
+ } \
+ HalDisplayString(" "); \
+ HalDisplayString(a); \
+ state++;
+
+#define ORG IQUOTE(BUILTBY)
+// #define REVIEW __FILE__ "(" IQUOTE(__LINE__) ") : REVIEW -> "
+
+ULONG
+HalpVersionSystem(
+ SYSTEM_TYPE
+) ;
+VOID
+HalpVersionExternal(
+ IN RelInfo *,
+ IN PLOADER_PARAMETER_BLOCK
+) ;
+PCHAR
+HalpGetVersionData(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+) ;
+VOID
+HalpDisplayVersionData(
+ IN PCHAR VersionData
+) ;
+BOOLEAN
+HalpSetRevs(
+ RelInfo *
+) ;
+
+// int HalpProcessorCount();
+
+#pragma alloc_text(INIT,HalpVersionSystem)
+#pragma alloc_text(INIT,HalpVersionExternal)
+#pragma alloc_text(INIT,HalpGetVersionData)
+#pragma alloc_text(INIT,HalpDisplayVersionData)
+#pragma alloc_text(INIT,HalpSetRevs)
+
+extern ULONG HalpGetCycleTime(VOID);
+extern ULONG HalpGetInstructionTimes( VOID );
+extern ULONG HalpPerformanceFrequency;
+
+
+#if DBG == 1
+VOID
+HalpVersionInternal( VOID )
+{
+
+ int state = 0;
+
+ HalpDebugPrint("\nWelcome to the %s (%s) Party\n",
+ SystemDescription[SystemType].SystemName,
+ ProcessorDescription[ProcessorType].ProcessorName);
+ HalpDebugPrint("HalpVersionInternal: Raw Processor Value (0x%x)\n",
+ HalpGetProcessorVersion());
+ HalpDebugPrint("Hal compiled on %s at %s with the following defines:\n",
+ __DATE__, __TIME__);
+
+ HalDisplayString("\n");
+ HalpDebugPrint(" Hal Build Base: %d \n",VER_PRODUCTBUILD);
+ HalpVersionSystem(SystemType);
+}
+#endif // DBG
+
+/*
+ * Routine Description: ULONG HalpVersionSystem(SYSTEM_TYPE System)
+ *
+ * Extract as much version information out of the mother board as possible:
+ *
+ */
+
+ULONG
+HalpVersionSystem(SYSTEM_TYPE System)
+{
+ ULONG TscVersion=0;
+ ULONG PciVersion=0;
+
+ TscVersion = rTscRevision;
+ PciVersion = rPCIRevisionID;
+
+ switch(System) {
+
+ case SYS_POWERSLICE:
+ HalpDebugPrint("TSC version: 0x%x \n", TscVersion );
+ break;
+
+ case SYS_POWERTOP : HalpDebugPrint("TSC version: 0x%x \n", TscVersion );
+ break;
+
+ case SYS_POWERPRO : HalpDebugPrint("Escc version: IS NOT DESIGNED IN!@!");
+ break;
+
+ case SYS_POWERSERVE : HalpDebugPrint("WHOOOAA pahdna, just what are you trying to pull here?\n");
+ break;
+
+ case SYS_UNKNOWN : HalpDebugPrint("Unknown system type \n");
+
+ default: // unknown stuff? should never get here
+ break;
+ }
+ HalpDebugPrint("\n===========================================================================\n");
+ HalpDebugPrint("PCI revision id: 0x%x \n", PciVersion );
+ HalpDebugPrint("TSC Control register: 0x%08x\n",rTscControl);
+ HalpDebugPrint("PioPending count: 0x%08x\n",rPIOPendingCount);
+ HalpDebugPrint("\n===========================================================================\n");
+
+ return(1); // success, true, good, ...
+}
+static PCHAR
+gettoken(PCHAR token, PCHAR buf, CHAR delim)
+{
+ CHAR c;
+ while (c = *buf) {
+ if (c == delim) {
+ buf++;
+ break;
+ } else {
+ *token++ = c;
+ buf++;
+ }
+ }
+ *token = '\0';
+ return buf;
+}
+
+VOID
+HalpDisplayVersionData( IN PCHAR VersionData )
+{
+
+ while (*VersionData) {
+ enum {Firmware = 0, Veneer = 1, Nada};
+ ULONG type;
+ PCHAR typeStr[2] = {"Firmware", "Veneer"};
+ CHAR token[64];
+ PCHAR tok = VersionData;
+ VersionData += strlen(VersionData)+1;
+
+ if (strstr(tok, typeStr[Firmware])) {
+ type = Firmware;
+ } else if (strstr(tok, typeStr[Veneer])) {
+ type = Veneer;
+ } else {
+ type = Nada;
+ }
+ if (Nada != type) {
+ CHAR buf[80];
+ strcpy(buf, typeStr[type]);
+ strcat(buf, ":");
+ if (strlen(buf) < 10) {
+ HalpDebugPrint("%-10s", buf);
+ } else {
+ HalpDebugPrint("%s: ", buf);
+ }
+ if (*VersionData) {
+ LONG n;
+
+ tok = VersionData;
+ VersionData += strlen(VersionData)+1;
+ n = 0;
+ tok = gettoken(token, tok, ',');
+ while (token[0]) {
+ switch (n++) {
+ case 2:
+ strcpy(buf, token);
+ strcat(buf, ",");
+ if (strlen(buf) < 7) {
+ HalpDebugPrint("%-7s", buf);
+ } else {
+ HalpDebugPrint("%s ", buf);
+ }
+ break;
+ case 3:
+ //
+ // Put date in Mmm dd yyyy format if in yyyy-mm-dd
+ // No unicode here :-).
+ // isdigit() causes too many link hassles.
+ //
+ if (type == Firmware && *token >= '0' && *token <= '9') {
+ PCHAR day;
+ PCHAR month;
+ PCHAR year;
+ PCHAR Mmm[12] = {
+ "Jan", "Feb", "Mar", "Apr",
+ "May", "Jun", "Jul", "Aug",
+ "Sep", "Oct", "Nov", "Dec",
+ };
+
+ strcpy(buf, token);
+ if (day = strrchr(buf, '-')) {
+ *day++ = '\0';
+ if (month = strrchr(buf, '-')) {
+ ULONG i;
+ *month++ = '\0';
+ RtlCharToInteger(month, 10, &i);
+ if (i > 12 || i < 1) {
+ HalpDebugPrint("%s, ", token);
+ } else {
+ year = buf;
+ //
+ // Decrement the month by one to align with
+ // zero based nature of the Mmm array.
+ //
+ HalpDebugPrint("%s %s %s, ", Mmm[i-1], day, year);
+ }
+ }
+ } else {
+ HalpDebugPrint("%s, ", token);
+ }
+ } else {
+ HalpDebugPrint("%s, ", token);
+ }
+ break;
+ case 4:
+ HalpDebugPrint("%s", token);
+ break;
+ }
+ tok = gettoken(token, tok, ',');
+ }
+ HalpDebugPrint("\n");
+ }
+ }
+ }
+}
+
+PCHAR
+HalpGetVersionData( IN PLOADER_PARAMETER_BLOCK LoaderBlock )
+{
+ PCHAR versionData = NULL;
+
+ //
+ // Read the Registry entry to get the Firmware and Veneer version info.
+ //
+
+ if (LoaderBlock) {
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+
+ ConfigurationEntry = KeFindConfigurationEntry (
+ LoaderBlock->ConfigurationRoot,
+ SystemClass,
+ ArcSystem,
+ NULL
+ );
+
+ if (ConfigurationEntry) {
+ if (ConfigurationEntry->ComponentEntry.ConfigurationDataLength) {
+ PCM_PARTIAL_RESOURCE_LIST List;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ LONG count;
+
+ List = (PCM_PARTIAL_RESOURCE_LIST) ConfigurationEntry->ConfigurationData;
+ Descriptor = List->PartialDescriptors;
+ for (count = List->Count; count > 0; count--) {
+ if (CmResourceTypeDeviceSpecific == Descriptor->Type) {
+ if (Descriptor->u.DeviceSpecificData.DataSize) {
+ //
+ // Finally, got the device specific data!
+ //
+
+ versionData = (PCHAR) Descriptor + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ return versionData;
+}
+
+VOID
+HalpVersionExternal( IN RelInfo *yahoo, IN PLOADER_PARAMETER_BLOCK LoaderBlock )
+{
+ PCHAR versionData;
+ CHAR debugStr[50];
+ CHAR buf[BUFSIZ];
+
+
+ // --> Make it look like this <--
+ //
+ // FirePower (TM) Systems, Inc. Powerized (TM) MX4100/2
+ // Copyright (C) 1994-1996 FirePower Systems, Inc.
+ // All rights reserved.
+ //
+ // Firmware: 00.23, Apr 27 1995, 14:42:21
+ // Veneer: 1.0, May 13 1995, 18:59:56
+ // Hal: 0,0, May 16 1995, 18:00:42
+
+ //
+ // Display the Model Number and our company name
+ //
+ HalpDebugPrint("\nFirePower (TM) Systems, Inc. Powerized_%s\n",
+ SystemDescription[SystemType].SystemName);
+ HalpDebugPrint("Copyright (C) 1994-1996 FirePower Systems, Inc.\n");
+ HalpDebugPrint("All rights reserved.\n\n");
+
+ //
+ // Display Version Data from firmware/veneer
+ //
+
+ if ( versionData = HalpGetVersionData(LoaderBlock) ) {
+ HalpDisplayVersionData(versionData);
+ }
+
+ //
+ // Display HAL Version Data
+ //
+
+ sprintf(buf, "%d.%d,", yahoo->Major, yahoo->Minor);
+#if DBG
+#if HALFIRE_EVAL
+ sprintf(debugStr, "DEBUG %s", HALFIRE_EVAL);
+#else
+ strcpy(debugStr, "DEBUG");
+#endif
+#else
+#if HALFIRE_EVAL
+ sprintf(debugStr, "%s", HALFIRE_EVAL);
+#else
+ strcpy(debugStr, "");
+#endif
+#endif
+ if (strlen(buf) < 7) {
+ HalpDebugPrint("HAL: %-7s%s, %s %s\n\n", buf,
+ yahoo->BuildDate, yahoo->BuildTime, debugStr);
+ } else {
+ HalpDebugPrint("HAL: %s %s, %s %s\n\n", buf,
+ yahoo->BuildDate, yahoo->BuildTime, debugStr);
+ }
+}
+
+/*
+*/
+BOOLEAN
+HalpSetRevs( RelInfo *yahoo )
+{
+ CHAR *ads;
+ LONG i=0;
+
+ ads = ORG;
+ while( *ads ) {
+ yahoo->Org[i] = *ads++;
+ i++;
+ }
+ yahoo->Scope = ENG;
+ i=0;
+ ads=__DATE__;
+ while( *ads ) {
+ yahoo->BuildDate[i] = *ads++;
+ i++;
+ }
+ i=0;
+ ads=__TIME__;
+ while( *ads ) {
+ yahoo->BuildTime[i] = *ads++;
+ i++;
+ }
+ yahoo->Major = HAL_MAJOR;
+ yahoo->Minor = HAL_MINOR;
+ yahoo->State = LAB;
+ return TRUE;
+}
+
+#if DBG
+/*
+ * Routine Description: BOOLEAN HalpPrintRevs()
+ *
+ * args:
+ * RelInfo
+ */
+
+BOOLEAN
+HalpPrintRevs( RelInfo *yahoo )
+{
+
+ HalpDebugPrint("Hal version-[%x.%x] \n",yahoo->Major, yahoo->Minor);
+ HalpDebugPrint("%s: ", yahoo->Org );
+ HalpDebugPrint("%s: ", ScopeList[yahoo->Scope]);
+ HalpDebugPrint("%s: ",yahoo->BuildDate);
+ HalpDebugPrint("%s: ",yahoo->BuildTime);
+ HalpDebugPrint("%s: ", RelList[yahoo->State]);
+
+ return TRUE;
+}
+#endif // DBG
diff --git a/private/ntos/nthals/halfire/ppc/pxbeep.c b/private/ntos/nthals/halfire/ppc/pxbeep.c
new file mode 100644
index 000000000..201b01d11
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxbeep.c
@@ -0,0 +1,144 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ pxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a Power PC
+ system.
+
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxbeep.c $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:08:52 $
+ * $Locker: $
+ */
+
+#include "halp.h"
+#include "eisa.h"
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase = HalpIoControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+ return Result;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxbusdat.c b/private/ntos/nthals/halfire/ppc/pxbusdat.c
new file mode 100644
index 000000000..a72ecf450
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxbusdat.c
@@ -0,0 +1,207 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Environment:
+
+ Kernel mode
+
+
+--*/
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxbusdat.c $
+ * $Revision: 1.10 $
+ * $Date: 1996/05/14 02:33:37 $
+ * $Locker: $
+ */
+
+
+#include "halp.h"
+#include "fpdebug.h"
+
+
+VOID HalpInitOtherBuses (VOID);
+
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+
+
+//
+// Prototype for system bus handlers
+//
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetIsaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+ Bus = HalpAllocateBusHandler (Internal, -1, 0, -1, 0, 0);
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus 0
+
+ Bus = HalpAllocateBusHandler (Isa, -1, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->GetInterruptVector = HalpGetIsaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+
+ HalpInitOtherBuses ();
+}
+
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ )
+/*++
+
+Routine Description:
+
+ Stub function to map old style code into new HalRegisterBusHandler code.
+
+ Note we can add our specific bus handler functions after this bus
+ handler structure has been added since this is being done during
+ hal initialization.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+ NTSTATUS status;
+
+
+ //
+ // Create bus handler - new style
+ //
+
+ status = HaliRegisterBusHandler (
+ InterfaceType,
+ BusDataType,
+ BusNumber,
+ ParentBusInterfaceType,
+ ParentBusNumber,
+ BusSpecificData,
+ NULL,
+ &Bus
+ );
+
+ if( !NT_SUCCESS(status) ) {
+ HalDisplayString("HalpAllocateBusHandler: unable to HaliRegister \n");
+ }
+
+ if (InterfaceType != InterfaceTypeUndefined) {
+ Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL,
+ sizeof (SUPPORTED_RANGES));
+ RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES));
+ Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
+ Bus->BusAddresses->Dma.Limit = 7;
+ Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF;
+ Bus->BusAddresses->Memory.SystemAddressSpace = 0;
+ Bus->BusAddresses->Memory.SystemBase = PCI_MEMORY_PHYSICAL_BASE;
+ Bus->BusAddresses->IO.SystemBase = 0x80000000;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0;
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+ }
+
+
+ return Bus;
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/pxcache.s b/private/ntos/nthals/halfire/ppc/pxcache.s
new file mode 100644
index 000000000..5c20d501e
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxcache.s
@@ -0,0 +1,1105 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxcache.s $
+ * $Revision: 1.12 $
+ * $Date: 1996/03/05 02:16:01 $
+ * $Locker: $
+ */
+
+//++
+//
+// Copyright (c) 1993, 1994, 1995 IBM 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:
+//
+// pxcache.s
+//
+// Abstract:
+//
+// This module implements the routines to flush cache on the PowerPC.
+//
+// Author:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) September 1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 27-Dec-93 plj Added 603 support.
+// 13-Mar-94 plj Fixed problem introduced during switch to pas,
+// added 604 support.
+// 18-Jan-95 plj Add 603+, 604+ and 620 support.
+//
+//--
+
+#include "kxppc.h"
+
+ .set HID0, 1008 // H/W Implementation Dependent reg 0
+
+//
+// Define various known processor types.
+//
+
+ .set PV601, 1 // 601
+ .set PV603, 3 // 603
+ .set PV603P, 6 // 603 plus
+ .set PV604, 4 // 604
+ .set PV604P, 9 // 604 plus
+ .set PV620, 20 // 620
+
+//
+// Note, in the following, the 603's "I-Cache Flash Invalidate"
+// and the 604's "I-Cache Invalidate All" basically perform the
+// same function although the usage is slightly different.
+// In the 603 case, ICFI must be cleared under program control
+// after it is set. In the 604 the bit clears automatically.
+// The 620's ICEFI behaves in the same way as the 604's ICIA.
+//
+
+ .set H0_603_ICFI, 0x0800 // I-Cache Flash Invalidate
+ .set H0_604_ICIA, 0x0800 // I-Cache Invalidate All
+ .set H0_620_ICEFI,0x0800 // I-Cache Edge Flash Invalidate
+
+//
+// Cache layout
+//
+// Processor | Size (bytes) | Line Size | Block Size | PVR Processor
+// | I-Cache | D-Cache | | | Version
+// ----------------------------------------------------------------------
+// 601 | 32KB Unified | 64 bytes | 32 bytes | 0x0001xxxx
+// 603 | 8KB | 8KB | 32 | 32 | 0x0003xxxx
+// 603+ | 16KB | 16KB | 32 | 32 | 0x0006xxxx
+// 604 | 16KB | 16KB | 32 | 32 | 0x0004xxxx
+// 604+ | 32KB | 32KB | 32 | 32 | 0x0009xxxx
+// 620 | 32KB | 32KB | 64 | 64 | 0x0014xxxx
+//
+
+ .set DCLSZ601, 64 // 601 cache line size
+ .set DCBSZ601, 32 // 601 cache block size
+ .set DCL601, 32 * 1024 / DCLSZ601 // 601 num cache lines
+ .set DCBSZL2601, 5 // 601 log2(block size)
+
+ .set DCBSZ603, 32 // 603 cache block size
+ .set DCB603, 8 * 1024 / DCBSZ603 // 603 num cache blocks
+ .set DCBSZL2603, 5 // 603 log2(block size)
+
+ .set DCB603P, 16 * 1024 / DCBSZ603 // 603+ num cache blocks
+
+ .set DCBSZ604, 32 // 604 cache block size
+ .set DCB604, 16 * 1024 / DCBSZ604 // 604 num cache blocks
+ .set DCBSZL2604, 5 // 604 log2(block size)
+
+ .set DCB604P, 32 * 1024 / DCBSZ604 // 604+ num cache blocks
+
+ .set DCBSZ620, 64 // 620 cache block size
+ .set DCB620, 32 * 1024 / DCBSZ620 // 620 num cache blocks
+ .set DCBSZL2620, 6 // 620 log2(block size)
+
+//
+// The following variables are declared locally so their addresses
+// will appear in the TOC. During initialization, we overwrite
+// the TOC entries with the entry points for the cache flushing
+// routines appropriate for the processor we are running on.
+//
+// It is done this way rather than filling in a table to reduce the
+// number of access required to get the address at runtime.
+// (This is known as "Data in TOC" which is not very much used in
+// NT at this time).
+//
+
+ .data
+ .globl HalpSweepDcache
+HalpSweepDcache: .long 0
+ .globl HalpSweepIcache
+HalpSweepIcache: .long 0
+ .globl HalpSweepDcacheRange
+HalpSweepDcacheRange: .long 0
+ .globl HalpSweepIcacheRange
+HalpSweepIcacheRange: .long 0
+
+//++
+//
+// Routine Description:
+//
+// HalpCacheSweepSetup
+//
+// This routine is called during HAL initialization. Its function
+// is to set the branch tables for cache flushing routines according
+// to the processor type.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(HalpCacheSweepSetup)
+
+ mfpvr r.3 // get processor type
+ rlwinm r.3, r.3, 16, 0xffff // remove version
+ cmpwi r.3, PV603P // binary search for the right code
+ lwz r.4, [toc].data(r.toc) // get address of local data section
+ bge hcss.high // jif 603+ or greater
+ cmpwi r.3, PV603
+ beq hcss.603 // jif 603
+ bgt hcss.604 // > 603, < 603+ must be 604
+
+//
+// processor is a 601
+//
+
+ lwz r.5, [toc]HalpSweepDcache601(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange601(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange601(r.toc)
+ mr r.6, r.5 // 601 icache use dcache routine
+ b hcss.done
+
+//
+// processor is a 603
+//
+
+hcss.603:
+
+ lwz r.5, [toc]HalpSweepDcache603(r.toc)
+ lwz r.6, [toc]HalpSweepIcache603(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange603(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange603(r.toc)
+ b hcss.done
+
+//
+// processor is a 604
+//
+
+hcss.604:
+
+ lwz r.5, [toc]HalpSweepDcache604(r.toc)
+ lwz r.6, [toc]HalpSweepIcache604(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange604(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange604(r.toc)
+ b hcss.done
+
+//
+// Processor type >= 603+, continue isolation of processor type.
+//
+
+hcss.high:
+
+ beq hcss.603p // jif 603 plus
+ cmpwi cr.0, r.3, PV604P
+ cmpwi cr.1, r.3, PV620
+ beq cr.0, hcss.604p // jif 604 plus
+ beq cr.1, hcss.620 // jif 620
+
+//
+// If we got here we are running on a processor whose cache characteristics
+// are not known. Return non-zero for error.
+//
+
+ li r.3, 1
+ blr
+
+//
+// processor is a 603 plus
+//
+
+hcss.603p:
+
+ lwz r.5, [toc]HalpSweepDcache603p(r.toc)
+ lwz r.6, [toc]HalpSweepIcache603p(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange603p(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange603p(r.toc)
+ b hcss.done
+
+//
+// processor is a 604 plus
+//
+
+hcss.604p:
+
+ lwz r.5, [toc]HalpSweepDcache604p(r.toc)
+ lwz r.6, [toc]HalpSweepIcache604p(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange604p(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange604p(r.toc)
+ b hcss.done
+
+//
+// processor is a 620
+//
+
+hcss.620:
+
+ lwz r.5, [toc]HalpSweepDcache620(r.toc)
+ lwz r.6, [toc]HalpSweepIcache620(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange620(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange620(r.toc)
+ b hcss.done
+
+
+hcss.done:
+
+//
+// r.5 thru r.9 contain the address of the function descriptors
+// for the routines we really want to use. Dereference them to
+// get at the entry point addresses.
+//
+ lwz r.5, 0(r.5)
+ lwz r.6, 0(r.6)
+ lwz r.7, 0(r.7)
+ lwz r.8, 0(r.8)
+
+//
+// Store the entry point addresses directly into the TOC.
+// This is so direct linkage from within the HAL to the
+// generic cache flushing routines can get to the desired
+// routines for this processor.
+//
+
+ stw r.5, [toc]HalpSweepDcache(r.toc)
+ stw r.6, [toc]HalpSweepIcache(r.toc)
+ stw r.7, [toc]HalpSweepDcacheRange(r.toc)
+ stw r.8, [toc]HalpSweepIcacheRange(r.toc)
+
+//
+// Modify the Function Descriptors for the generic routines to
+// point directly at the target routines so that linkage from
+// other executables (eg the kernel) will be direct rather
+// than via the generic routines.
+//
+
+ lwz r.3, [toc]HalSweepDcache(r.toc)
+ lwz r.4, [toc]HalSweepIcache(r.toc)
+ stw r.5, 0(r.3)
+ stw r.6, 0(r.4)
+ lwz r.3, [toc]HalSweepDcacheRange(r.toc)
+ lwz r.4, [toc]HalSweepIcacheRange(r.toc)
+ stw r.7, 0(r.3)
+ stw r.8, 0(r.4)
+
+ li r.3, 0 // return code = success
+
+ LEAF_EXIT(HalpCacheSweepSetup)
+
+//++
+//
+// Routines HalSweepDcache
+// HalSweepIcache
+// HalSweepDcacheRange
+// HalSweepIcacheRange
+//
+// are simply dispatch points for the appropriate routine for
+// the processor being used.
+//
+//--
+
+
+ LEAF_ENTRY(HalSweepDcache)
+
+ lwz r.12, [toc]HalpSweepDcache(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepDcache)
+
+
+
+ LEAF_ENTRY(HalSweepIcache)
+
+ lwz r.12, [toc]HalpSweepIcache(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepIcache)
+
+
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+ lwz r.12, [toc]HalpSweepDcacheRange(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepDcacheRange)
+
+
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+ lwz r.12, [toc]HalpSweepIcacheRange(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepIcacheRange)
+
+
+
+
+//++
+//
+// 601 Cache Flushing Routines
+//
+// The 601 has a unified instruction/data cache. For this reason
+// we need only two routines, one to sweep the entire cache and
+// another to sweep a given range.
+//
+//
+//
+//
+// HalpSweepDcache601
+//
+// Sweep the entire instruction/data cache. This is accomplished
+// by loading the cache with data corresponding to a known address
+// range and then ensuring that each block in the cache is not dirty.
+//
+// Note that the 601 line size is 64 bytes and its block size is 32
+// bytes. When we load any byte within a line, both blocks in that
+// line are loaded into the cache (if not already present). We must
+// clean each block individually.
+//
+// In an effort to maximize the possibilities that (a) the addressed
+// data is already in the cache and (b) there is some use in having
+// this data in the cache, we use the lower end of the hashed page
+// table as the data to be loaded and we use dcbst rather than dcbf
+// to force the block to memory (and leave it valid in the cache as
+// well).
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcache601)
+
+ mfsdr1 r.3 // fill the D cache from memory
+ // allocated to the hashed page
+ // table (it's something useful).
+ li r.4, DCL601 // size of cache in cache lines
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ sync
+ oris r.3, r.3, 0x8000 // get VA of hashed page table
+ subi r.5, r.3, DCBSZ601 // dec addr prior to inc
+hsd601.ld:
+ lbzu r.8, DCLSZ601(r.5)
+ bdnz hsd601.ld
+ ENABLE_INTERRUPTS(r.10)
+
+ LEAF_EXIT(HalpSweepDcache601)
+
+
+
+
+//++
+//
+// HalpSweepDcacheRange601
+//
+// HalpSweepDcacheRange603
+//
+// HalpSweepDcacheRange603p
+//
+// HalpSweepDcacheRange604
+//
+// HalpSweepDcacheRange604p
+//
+// Force data in a given address range to memory.
+//
+// Because this routine works on a range of blocks and block size
+// is the same on 601, 603, 603+, 604 and 604+ we can use the same
+// code for each of them.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheRange601)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange603)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange603p)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange604)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange604p)
+
+ rlwinm r.5, r.3, 0, DCBSZ601-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ601-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2601 // number of blocks
+ mtctr r.4
+ sync
+hsdr601.fl:
+ dcbst 0, r.3 // flush block
+ addi r.3, r.3, DCBSZ601 // bump address
+ bdnz hsdr601.fl
+
+ LEAF_EXIT(HalpSweepDcacheRange601)
+
+
+
+
+//++
+//
+// HalpSweepIcacheRange601
+//
+// Due to the unified cache, this routine is meaningless on a 601.
+// The reason for flushing a range of instruction address is because
+// of code modification (eg breakpoints) in which case the nature
+// of the unified cache is that the *right* code is in the cache,
+// or because of a transfer of a code page in which case the unified
+// snooping cache will have done the right thing.
+//
+// Therefore this routine simply returns.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange601)
+
+ // return
+
+ LEAF_EXIT(HalpSweepIcacheRange601)
+
+//++
+//
+// 603, 603+ Cache Flushing Routines
+//
+// The 603 has seperate instruction and data caches of 8 KB each.
+// The 603+ has seperate instruction and data caches of 16 KB each.
+// Line size = Block size = 32 bytes.
+//
+// The mechanics of cache manipulation are the same for the 603 and
+// 603+.
+//
+//
+//
+// HalpSweepDcache603 HalpSweepDcache603p
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// The 603 does not have a hashed page table so we can't use the
+// hashed page table as the data range. Instead use the start of
+// KSEG0.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcache603p)
+
+ li r.4, DCB603P // size of 603+ cache in blocks
+ b hsd603
+
+ DUMMY_EXIT(HalpSweepDcache603p)
+
+
+
+ LEAF_ENTRY(HalpSweepDcache603)
+
+ li r.4, DCB603 // size of 603 cache in blocks
+hsd603:
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ sync // ensure ALL previous stores completed
+ LWI(r.3,0x80000000) // known usable virtual address
+ subi r.5, r.3, DCBSZ603 // dec addr prior to inc
+hsd603.ld:
+ lbzu r.8, DCBSZ603(r.5)
+ bdnz hsd603.ld
+ ENABLE_INTERRUPTS(r.10)
+
+ mtctr r.4
+hsd603.fl:
+ dcbst 0, r.3 // ensure block is in memory
+ addi r.3, r.3, DCBSZ603 // bump address
+ bdnz hsd603.fl
+
+ LEAF_EXIT(HalpSweepDcache603)
+
+
+
+
+//++
+//
+// HalpSweepIcache603 HalpSweepIcache603p
+//
+// Sweep the entire instruction cache. The instruction cache (by
+// definition) can never contain modified code (hence there are no
+// icbf or icbst instructions). Therefore what we really need to do
+// here is simply invalidate every block in the cache. This can be
+// done by toggling the Instruction Cache Flash Invalidate (ICFI) bit
+// in the 603's HID0 register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcache603)
+
+ ALTERNATE_ENTRY(HalpSweepIcache603p)
+
+ mfspr r.3, HID0 // 603, use Instruction
+ ori r.4, r.3, H0_603_ICFI // Cache Flash Invalidate
+
+ isync
+ mtspr HID0, r.4 // invalidate I-Cache
+ mtspr HID0, r.3 // re-enable
+
+ LEAF_EXIT(HalpSweepIcache603)
+
+
+
+//++
+//
+// HalpSweepIcacheRange603 HalpSweepIcacheRange603p
+//
+// Remove a range of instructions from the instruction cache.
+//
+// Note that if this is going to take a long time we flash
+// invalidate the I cache instead. Currently I define a
+// "long time" as greater than 4096 bytes which amounts to
+// 128 trips thru this loop (which should run in 256 clocks).
+// This number was selected without bias or forethought from
+// thin air - plj. I chose this number because gut feel tells
+// me that it will cost me more than 256 clocks in cache misses
+// trying to get back to the function that requested the cache
+// flush in the first place.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange603)
+
+ ALTERNATE_ENTRY(HalpSweepIcacheRange603p)
+
+ cmpwi r.4, 4096 // if range > 4096 bytes, flush
+ bgt- ..HalpSweepIcache603 // entire I cache
+
+ rlwinm r.5, r.3, 0, DCBSZ603-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ603-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2603 // number of blocks
+ mtctr r.4
+hsir603.fl:
+ icbi 0, r.3 // invalidate block in I cache
+ addi r.3, r.3, DCBSZ603 // bump address
+ bdnz hsir603.fl
+
+ LEAF_EXIT(HalpSweepIcacheRange603)
+
+
+//++
+//
+// 604 Cache Flushing Routines
+//
+// The 604 has seperate instruction and data caches of 16 KB each.
+// The 604+ has seperate instruction and data caches of 32 KB each.
+// Line size = Block size = 32 bytes.
+//
+//
+//
+// HalpSweepDcache604 HalpSweepDcache604p
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// As in the 601 case, we use the Hashed Page Table for the data
+// in an effort to minimize performance lost by force feeding the
+// cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpSweepDcache604p)
+
+ li r.4, DCB604P // size of 604+ cache in blocks
+ b hsd604
+
+ DUMMY_EXIT(HalpSweepDcache604p)
+
+
+
+ LEAF_ENTRY(HalpSweepDcache604)
+
+ li r.4, DCB604 // size of cache in cache blocks
+hsd604:
+ mfsdr1 r.3 // fill the D cache from memory
+ // allocated to the hashed page
+ // table (it's something useful).
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ sync // ensure ALL previous stores completed
+ oris r.3, r.3, 0x8000 // get VA of hashed page table
+ subi r.5, r.3, DCBSZ604 // dec addr prior to inc
+hsd604.ld:
+ lbzu r.8, DCBSZ604(r.5)
+ bdnz hsd604.ld
+ ENABLE_INTERRUPTS(r.10)
+
+ LEAF_EXIT(HalpSweepDcache604)
+
+
+
+
+//++
+//
+// HalpSweepIcache604 HalpSweepIcache604p
+//
+// Sweep the entire instruction cache. This routine is functionally
+// similar to the 603 version except that on the 604 the bit in HID0
+// (coincidentally the *same* bit) is called Instruction Cache Invali-
+// sate All (ICIA) and it clears automatically after being set.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcache604)
+
+ ALTERNATE_ENTRY(HalpSweepIcache604p)
+
+ mfspr r.3, HID0 // 604, use Instruction
+ ori r.3, r.3, H0_604_ICIA // Cache Invalidate All
+ isync
+ mtspr HID0, r.3 // invalidate I-Cache
+
+ LEAF_EXIT(HalpSweepIcache604)
+
+
+
+
+//++
+//
+// HalpSweepIcacheRange604 HalpSweepIcacheRange604p
+//
+// Remove a range of instructions from the instruction cache.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange604)
+
+ ALTERNATE_ENTRY(HalpSweepIcacheRange604p)
+
+ rlwinm r.5, r.3, 0, DCBSZ604-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ604-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2604 // number of blocks
+ mtctr r.4
+hsir604.fl:
+ icbi 0, r.3 // invalidate block in I cache
+ addi r.3, r.3, DCBSZ604 // bump address
+ bdnz hsir604.fl
+
+ LEAF_EXIT(HalpSweepIcacheRange604)
+
+//++
+//
+// 620 Cache Flushing Routines
+//
+// The 620 has seperate instruction and data caches of 32 KB each.
+// Line size = Block size = 64 bytes.
+//
+//
+//
+// HalpSweepDcache620
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// As in the 601 case, we use the Hashed Page Table for the data
+// in an effort to minimize performance lost by force feeding the
+// cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpSweepDcache620)
+
+ li r.4, DCB620 // size of cache in cache blocks
+hsd620:
+ mfsdr1 r.3 // fill the D cache from memory
+ // allocated to the hashed page
+ // table (it's something useful).
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ sync
+ oris r.3, r.3, 0x8000 // get VA of hashed page table
+ subi r.5, r.3, DCBSZ620 // dec addr prior to inc
+hsd620.ld:
+ lbzu r.8, DCBSZ620(r.5)
+ bdnz hsd620.ld
+ ENABLE_INTERRUPTS(r.10)
+
+ LEAF_EXIT(HalpSweepDcache620)
+
+
+
+
+//++
+//
+// HalpSweepIcache620
+//
+// Sweep the entire instruction cache. This routine is functionally
+// identical to the 604 version except that on the 620 the bit in HID0
+// (coincidentally the *same* bit) is called Instruction Cache Edge
+// Flash Invalidate (ICEFI).
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcache620)
+
+ mfspr r.3, HID0 // 620, use Instruction
+ ori r.3, r.3, H0_620_ICEFI // Cache Edge Flash Invalidate
+ isync
+ mtspr HID0, r.3 // invalidate I-Cache
+
+ LEAF_EXIT(HalpSweepIcache620)
+
+
+
+
+//++
+//
+// HalpSweepIcacheRange620
+//
+// Remove a range of instructions from the instruction cache.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange620)
+
+ rlwinm r.5, r.3, 0, DCBSZ620-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ620-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2620 // number of blocks
+ mtctr r.4
+hsir620.fl:
+ icbi 0, r.3 // invalidate block in I cache
+ addi r.3, r.3, DCBSZ620 // bump address
+ bdnz hsir620.fl
+
+ LEAF_EXIT(HalpSweepIcacheRange620)
+
+
+
+
+//++
+//
+// HalpSweepDcacheRange620
+//
+// Force data in a given address range to memory.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheRange620)
+
+ rlwinm r.5, r.3, 0, DCBSZ620-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ620-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2620 // number of blocks
+ mtctr r.4
+ sync
+hsdr620.fl:
+ dcbst 0, r.3 // flush block
+ addi r.3, r.3, DCBSZ620 // bump address
+ bdnz hsdr620.fl
+
+ LEAF_EXIT(HalpSweepDcacheRange620)
+
+
+//++
+//
+// HalpSweepPhysicalRangeInBothCaches
+//
+// Force data in a given PHYSICAL address range to memory and
+// invalidate from the block in the instruction cache.
+//
+// This implementation assumes a block size of 32 bytes. It
+// will still work on the 620.
+//
+// Arguments:
+//
+// r.3 Start physical PAGE number.
+// r.4 Starting offset within page. Cache block ALIGNED.
+// r.5 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .set PAGE_SHIFT, 12
+
+
+ LEAF_ENTRY(HalpSweepPhysicalRangeInBothCaches)
+
+//
+// Starting physical address = (PageNumber << PAGE_SHIFT) | Offset
+//
+
+ rlwimi r.4, r.3, PAGE_SHIFT, 0xfffff000
+
+ addi r.5, r.5, 31 // bump length by block size - 1
+ srwi r.5, r.5, 5 // get number of blocks
+ mflr r.0 // save return address
+ mtctr r.5 // set loop count
+
+//
+// Interrupts MUST be disabled for the duration of this function as
+// we use srr0 and srr1 which will be destroyed by any exception or
+// interrupt.
+//
+
+ DISABLE_INTERRUPTS(r.12,r.11) // r.11 <- disabled MSR
+ // r.12 <- previous MSR
+//
+// Find ourselves in memory. This is needed as we must disable
+// both instruction and data translation. We do this while
+// interrupts are disabled only to try to avoid changing the
+// Link Register when an unwind might/could occur.
+//
+// The HAL is known to be in KSEG0 so its physical address is
+// its effective address with the top bit stripped off.
+//
+
+ bl hspribc
+hspribc:
+
+ mflr r.6 // r.6 <- &hspribc
+ rlwinm r.6, r.6, 0, 0x7fffffff // r.6 &= 0x7fffffff
+ addi r.6, r.6, hspribc.real - hspribc
+ // r.6 = real &hspribc.real
+
+ sync // ensure all previous loads and
+ // stores are complete.
+
+ mtsrr0 r.6 // address in real space
+
+ rlwinm r.11, r.11, 0, ~0x30 // turn off Data and Instr relocation
+ mtsrr1 r.11
+ rfi // leap to next instruction
+
+hspribc.real:
+ mtsrr0 r.0 // set return address
+ mtsrr1 r.12 // set old MSR value
+
+hspribc.loop:
+ dcbst 0, r.4 // flush data block to memory
+ icbi 0, r.4 // invalidate i-cache
+ addi r.4, r.4, 32 // point to next block
+ bdnz hspribc.loop // jif more to do
+
+ sync // ensure all translations complete
+ isync // don't even *think* about getting
+ // ahead.
+ rfi // return to caller and translated
+ // mode
+
+ DUMMY_EXIT(HalpSweepPhysicalRangeInBothCaches)
+
+//++
+//
+// HalpSweepPhysicalIcacheRange
+//
+// Invalidate a given PHYSICAL address range from the instruction
+// cache.
+//
+// This implementation assumes a block size of 32 bytes. It
+// will still work on the 620.
+//
+// Arguments:
+//
+// r.3 Start physical PAGE number.
+// r.4 Starting offset within page. Cache block ALIGNED.
+// r.5 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpSweepPhysicalIcacheRange)
+
+//
+// Starting physical address = (PageNumber << PAGE_SHIFT) | Offset
+//
+
+ rlwimi r.4, r.3, PAGE_SHIFT, 0xfffff000
+
+ addi r.5, r.5, 31 // bump length by block size - 1
+ srwi r.5, r.5, 5 // get number of blocks
+ mflr r.0 // save return address
+ mtctr r.5 // set loop count
+
+//
+// Interrupts MUST be disabled for the duration of this function as
+// we use srr0 and srr1 which will be destroyed by any exception or
+// interrupt.
+//
+
+ DISABLE_INTERRUPTS(r.12,r.11) // r.11 <- disabled MSR
+ // r.12 <- previous MSR
+//
+// Find ourselves in memory. This is needed as we must disable
+// both instruction and data translation. We do this while
+// interrupts are disabled only to try to avoid changing the
+// Link Register when an unwind might/could occur.
+//
+// The HAL is known to be in KSEG0 so its physical address is
+// its effective address with the top bit stripped off.
+//
+
+ bl hspir
+hspir:
+
+ mflr r.6 // r.6 <- &hspribc
+ rlwinm r.6, r.6, 0, 0x7fffffff // r.6 &= 0x7fffffff
+ addi r.6, r.6, hspir.real - hspir
+ // r.6 = real &hspribc.real
+
+ sync // ensure all previous loads and
+ // stores are complete.
+
+ mtsrr0 r.6 // address in real space
+
+//
+// N.B. It may not be required that Data Relocation be disabled here.
+// I can't tell from my Arch spec if ICBI works on a Data or
+// Instruction address. I believe it is probably a Data
+// address even though it would be sensible for it to be an
+// instruction address,....
+//
+
+ rlwinm r.11, r.11, 0, ~0x30 // turn off Data and Instr relocation
+ mtsrr1 r.11
+ rfi // leap to next instruction
+
+hspir.real:
+ mtsrr0 r.0 // set return address
+ mtsrr1 r.12 // set old MSR value
+
+hspir.loop:
+ icbi 0, r.4 // invalidate i-cache
+ addi r.4, r.4, 32 // point to next block
+ bdnz hspir.loop // jif more to do
+
+ sync // ensure all translations complete
+ isync // don't even *think* about getting
+ // ahead.
+ rfi // return to caller and translated
+ // mode
+
+ DUMMY_EXIT(HalpSweepPhysicalIcacheRange)
diff --git a/private/ntos/nthals/halfire/ppc/pxcalstl.c b/private/ntos/nthals/halfire/ppc/pxcalstl.c
new file mode 100644
index 000000000..bc75249d0
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxcalstl.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxcalstl.c $
+ * $Revision: 1.13 $
+ * $Date: 1996/01/11 07:09:11 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+ Copyright 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:
+
+ pxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service for a PowerPC system.
+
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+ Jim Wooldridge
+ Steve Johns (Motorola)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "fpdebug.h"
+#include "halp.h"
+
+//
+// KeQueryPerformanceCounter & KeStallExecutionProcessor are called
+// before Phase 0 initialization, so initialize it to a reasonable value.
+//
+ULONG HalpPerformanceFrequency = 80000000/16;
+ULONG CpuFrequency;
+ULONG ProcessorBusFrequency;
+ULONG HalpGetCycleTime(VOID);
+extern ULONG CpuClockMultiplier;
+extern ULONG HalpClockCount;
+extern ULONG HalpFullTickClockCount;
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateTimingValues)
+
+#endif
+
+
+/*++
+
+Routine Description: BOOLEAN HalpCalibrateTimingValues ( VOID )
+
+ This function calibrates the stall execution HAL service.
+
+ N.B. This routine is only called during phase 1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+BOOLEAN
+HalpCalibrateTimingValues (
+ VOID
+ )
+{
+ ULONG TmpCpuHertz;
+
+ //
+ // Set initial scale factor
+ //
+ PCR->StallScaleFactor = 1;
+
+ //
+ // Compute the clock frequency of the Time Base & Decrementer
+ //
+ HalpPerformanceFrequency = HalpCalibrateTB();
+ // HalpPerformanceFrequency = (HalpPerformanceFrequency / 1000) * 1000;
+
+ //
+ // Since the TimeBase ticks once for every four bus clock cycles, multiply
+ // the HalpPerformanceFrequency by 4. This is the bus speed in Hertz. Now
+ // apply the cpu chip clock multiplier calculated back in
+ // HalpInitializeProcessor and perform rounding converting to MegaHertz.
+ //
+ ProcessorBusFrequency = (4 * HalpPerformanceFrequency);
+
+ //
+ // Since the CpuClockMultiplier is really 10 times the true multiplier,
+ // add one more order of magnitude to the divisor when converting to
+ // megahertz
+ //
+ TmpCpuHertz = (CpuClockMultiplier * ProcessorBusFrequency)/1000000;
+ CpuFrequency = TmpCpuHertz/10;
+
+ //
+ // check to see if the sub megahertz residual of the frequency
+ // calculations are large enough to round up to the next megahertz.
+ //
+ if ((TmpCpuHertz - ((TmpCpuHertz/10)*10)) >= 5) {
+ CpuFrequency++; // round up to the next Megahertz.
+ }
+
+ //
+ // Initialize the system clock variable
+ //
+ HalpClockCount =
+ (HalpPerformanceFrequency * (MAXIMUM_INCREMENT/10000)) / 1000;
+ HalpFullTickClockCount = HalpClockCount;
+
+ return TRUE;
+}
+
+ULONG
+HalpGetCycleTime()
+{
+ HDBG(DBG_TIME,
+ HalpDebugPrint("HalpGetCycleTime: PerfFreq(%d), ClockCount(%d)\n",
+ HalpPerformanceFrequency, HalpClockCount););
+ return( CpuFrequency );
+
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxcirrus.h b/private/ntos/nthals/halfire/ppc/pxcirrus.h
new file mode 100644
index 000000000..32aee24df
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxcirrus.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxcirrus.h $
+ * $Revision: 1.2 $
+ * $Date: 1996/01/11 07:09:18 $
+ * $Locker: $
+ */
+
+/*
+ * pxcirrus.h
+ *
+ * Defines for cirrus HAL support
+ */
+
+#define CIRRUS_VIDEO_MEMORY_BASE 0xc0000000
+#define CIRRUS_VENDOR_ID 0x1013
+#define CIRRUS_COMMAND_MASK 0x03
+
+#define CIRRUS_TEXT_MEM 0xb8000
+#define CIRRUS_FONT_MEM 0xa0000
+
+
+#define WRITE_CIRRUS_UCHAR(port,data) \
+ *(volatile unsigned char *) \
+ ((ULONG)HalpIoControlBase+(port))=(UCHAR)(data), \
+ KeFlushWriteBuffer()
+
+#define WRITE_CIRRUS_VRAM(port,data) \
+ *((PUCHAR)((ULONG) HalpVideoMemoryBase + (port))) = (UCHAR) (data), \
+ KeFlushWriteBuffer()
+
+#define WRITE_CIRRUS_USHORT(port,data) \
+ *(volatile unsigned short*) \
+ ((ULONG)HalpIoControlBase+(port))=(USHORT)(data), \
+ KeFlushWriteBuffer()
+
+#define READ_CIRRUS_VRAM(port) \
+ *(HalpVideoMemoryBase + (port))
+
+#define READ_CIRRUS_UCHAR(port) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port))
+
+#define setreg(port,index,data) \
+ WRITE_CIRRUS_UCHAR(port,index), \
+ WRITE_CIRRUS_UCHAR(port+1,data)
+
+#define outportb(port,data) \
+ WRITE_CIRRUS_UCHAR(port,data)
+
+#define outp(port,data) outportb(port,data)
+
+#define inp(port) \
+ READ_CIRRUS_UCHAR(port)
+
+#define INSTATUS_1 (PVOID) ((ULONG)((int)HalpIoControlBase + (int)0x03DA))
+
+
+
+
+//
+// Attributes Registers
+//
+
+static unsigned char attr3[] =
+{
+ 0x00, // AR0-ARF: Attribute Controller
+ 0x01, // Palette Registers
+ 0x02,
+ 0x03,
+ 0x04,
+ 0x05,
+ 0x14,
+ 0x07,
+ 0x38,
+ 0x39,
+ 0x3a,
+ 0x3b,
+ 0x3c,
+ 0x3d,
+ 0x3e,
+ 0x3f,
+ 0x0c, // AR10: Attribute Controller Mode
+ // Blink Enable
+ // Line Graphics Enable
+ 0x00, // AR11: Overscan (Border) color
+ 0x0f, // AR12: Color Plane Enable
+ // All planes enabled
+ 0x08, // AR13: Pixel Panning
+ 0x00 // AR14: Color Select
+};
+
+//
+// CRT control
+//
+
+static unsigned char crtc3[] =
+{
+ 0x5f, // CR0: Horizontal Total
+ 0x4f, // CR1: Horizontal Display End
+ 0x50, // CR2: Start Horizontal Blinking
+ 0x82, // CR3: End Horizontal Blanking
+ 0x55, // CR4: Start Horizontal Retrace Pulse
+ 0x81, // CR5: End Horizontal Retrace Pulse
+ 0xbf, // CR6: Vertical Total
+ 0x1f, // CR7: Overflow
+ 0x00, // CR8: Row Scan
+ 0x4f, // CR9: Character Cell Height (16)
+ 0x0d, // CRa: Text Cursor Start Register
+ 0x0e, // CRb: Text Cursor End Register
+ 0x00, // CRc: Screen Start High
+ 0x00, // CRd: Screen Start Low
+ 0x00, // CRe: Text Cursor Location High
+ 0x00, // CRf: Text Cursor Location Low
+ 0x9c, // CR10: Vertical Sync Start
+ 0xae, // CR11: Vertical Sync End
+ 0x8f, // CR12: Vertical Display End
+ 0x28, // CR13: Offset
+ 0x1f, // CR14: Underline Row Scanline
+ 0x96, // CR15: Vertical Blank Start
+ 0xb9, // CR16: Vertical Blank End
+ 0xa3, // CR17: Mode Control
+ 0xff, // CR18: Line Compare
+ 0x00, // CR19: Interlace End
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
+
+
+//
+// Graphics Registers
+//
+
+static unsigned char graph3[] =
+{
+ 0x00, // GR0: Set/Reset Register
+ 0x00, // GR1: Set/Reset Enable Register
+ 0x00, // GR2: Color Compare
+ 0x00, // GR3: Data Rotate Register
+ 0x00, // GR4: Read Map Select Register
+ 0x10, // GR5: Mode Register (Odd/Even On)
+
+ 0x0e, // GR6: Miscellaneous Register
+ // Memory Map b800:0
+ // Chain Odd Maps to Even
+ 0x00, // GR7: Color Don't Care register
+ 0xff // GR8: Bit Mask Register
+};
+
+//
+// Sequencer Registers
+//
+
+static unsigned char seq3[] =
+{
+ 0x03, // SR0: Reset Register
+ // Asynchronous and Synchronous reset
+ 0x00, // SR1: Clocking Mode
+ 0x03, // SR2: Plane Mask Register
+ // Map 0 and 1 Enable
+ 0x00, // SR3: Character Map Select Register
+ 0x02, // SR4: Memory Mode
+ // Extended Memory
+};
+
+//
+// Extended Sequencer Registers
+//
+
+static unsigned char eseq3[] =
+{
+ 0x6,0x12, // SR6: Unlock All Extensions
+ 0x7,0x00, // SR7: Extended Sequencer Mode
+ 0x8,0x40, // SR8: EEPROM Control
+// tsa 0x8,0x00, // SR8: EEPROM Control
+ 0xb,0x4a, // SRb: VCLK 0 Numerator Register
+ 0xc,0x5b, // SRc: VCLK 1 Numerator Register
+ 0xd,0x42, // SRd: VCLK 2 Numerator Register
+ 0xe,0x6e, // SRe: VCLK 3 Numerator Register
+//tsa x 0xe,0x7e, // SRe: VCLK 3 Numerator Register
+ 0xf,0x1d, // SRf: DRAM control
+ 0x12,0x00, // SR12: Cursor Attributes
+ 0x16,0x71, // SR16: Performance Tuning
+ 0x18,0x00, // SR18: Signature Generator Control
+ 0x1b,0x2b, // SR1b: VCLK Denominator and Post-Scalar
+ 0x1c,0x2f,
+ 0x1d,0x1f,
+ 0x1e,0x2a,
+//tsa x 0x1e,0x33,
+ 0x1f,0x1c,
+ 0xff
+};
+
+//
+// Extended CRTC Registers
+//
+
+static unsigned char ecrtc3[] =
+{
+ 0x19,0x00, // CR19: Inerlace End
+ 0x1a,0x00, // CR1a: Miscellaneous
+ 0x1b,0x00, // CR1b: Extended Display Controlls
+ 0xff
+};
+
+//
+// Extended Graphics Registers
+//
+
+static unsigned char egraph3[] =
+{
+ 0x9,0x00, // GR9: Offset Register 0
+ 0xa,0x00, // GRa: Offset Register 1
+ 0xb,0x00, // GRb: Graphics Controller Mode Extnsions
+ 0xc,0xff, // GRc: Color Key Compare
+ 0xd,0x00, // GRd: Color Key Compare Mask
+ 0x10,0x00, // GR10: Background Color Byte 1
+ 0x11,0x00, // GR11: Foreground Color Byte 1
+ 0xff
+};
+
+//
+// Extended Attribute Registers
+//
+
+static unsigned char eattr3[] =
+{
+ 0xff
+};
diff --git a/private/ntos/nthals/halfire/ppc/pxclksup.s b/private/ntos/nthals/halfire/ppc/pxclksup.s
new file mode 100644
index 000000000..2a3c37e99
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxclksup.s
@@ -0,0 +1,163 @@
+/***********************************************************************
+
+ Copyright 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.
+
+ File Name:
+ PXCLKSUP.S
+
+ Globals:
+ none
+
+ Functions:
+ HalpUpdateDecrementer
+ KeQueryPerformanceCounter
+
+ History:
+ 11-Feb-1994 Steve Johns
+ Original Version
+ 23-Jun-1994 Steve Johns (sjohns@pets.sps.mot.com)
+ Fixed HalpZeroPerformanceCounter. Was writing to RTCU & RTCL.
+ Writes should go to SPR 20 & 21.
+***********************************************************************/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxclksup.s $
+ * $Revision: 1.7 $
+ * $Date: 1996/05/14 02:33:44 $
+ * $Locker: $
+ */
+
+#include <halppc.h>
+#define ERRATA603 TRUE
+
+
+
+
+ LEAF_ENTRY(HalpUpdateDecrementer)
+
+
+ mfpvr r.6 // Read Processor Version Register
+ rlwinm r.6,r.6,16,16,31
+ cmpli 0,0,r.6,1 // Is it an MPC601 ?
+ bne Not_601
+ rlwinm r.3,r.3,7,0,24 // Yes, Count *= 128
+Not_601:
+//
+// Read the DECREMENTER to get the interrupt latency and bias Count by
+// that amount. Otherwise, the latencies would accumulate and the time
+// of day would run slow.
+//
+ mfdec r.7 // Read the DECREMENTER
+ add r.4,r.3,r.7 // + Count
+//
+// We expect that the DECREMENTER should be near 0xFFFFFFxx, so R4 should
+// be less than r.3. If not, we don't want to cause an excessively long
+// clock tick, so just ignore the latency and use Count.
+//
+ cmpl 0,0,r.4,r.3
+ ble SetDecr
+ mr r.4,r.3
+SetDecr:
+
+ mtdec r.4 // Write to the DECREMENTER
+#if ERRATA603
+ isync
+#endif
+
+// Undocumented return value: the latency in servicing this interrupt
+ neg r.3,r.7
+
+
+ LEAF_EXIT(HalpUpdateDecrementer)
+
+
+
+ .extern HalpPerformanceFrequency
+ .extern ..HalpGetTimerRoutine
+
+
+/***********************************************************************
+ Synopsis:
+ ULARGE_INTEGER KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
+
+ Purpose:
+ Supplies a 64-bit realtime counter for use in evaluating performance
+ of routines.
+
+ Returns:
+ This routine returns current 64-bit performance counter and,
+ optionally, the frequency of the Performance Counter.
+
+ Global Variables Referenced:
+ HalpPerformanceFrequency
+
+***********************************************************************/
+
+//
+// Register Definitions
+//
+ .set RetPtr, r.3
+ .set Freq, r.4
+ .set TimerLo, r.6 // MUST be same as defined in PXSTALL.S
+ .set TimerHi, r.7 // MUST be same as defined in PXSTALL.S
+ .set Temp, r.8
+
+ .set RTCU, 4
+ .set RTCL, 5
+ .set TB, 284
+ .set TBU, 285
+
+
+ LEAF_ENTRY(KeQueryPerformanceCounter)
+
+ mflr r.0 // Save Link Register
+
+ cmpli 0,0,Freq,0 // Was PerformanceFrequency passed ?
+ beq GetCpuVersion
+
+ lwz Temp,[toc]HalpPerformanceFrequency(r.toc)
+ lwz Temp,0(Temp) // PerformanceFrequency.LowPart =
+ stw Temp,0(Freq) // HalpPerformanceFrequency;
+ li Temp,0 // PerformanceFrequency.HighPart = 0;
+ stw Temp,4(Freq)
+
+GetCpuVersion:
+ bl ..HalpGetTimerRoutine
+
+ bctrl // ReadPerformanceCounter();
+
+ stw TimerLo,0(RetPtr)
+ stw TimerHi,4(RetPtr)
+ mtlr r.0 // Restore Link Register
+
+ LEAF_EXIT(KeQueryPerformanceCounter)
+
+
+ LEAF_ENTRY(HalpZeroPerformanceCounter)
+
+
+ mfpvr r.4 // Read Processor Version Register
+ li r.3, 0
+ rlwinm r.4,r.4,16,16,31
+ cmpli 0,0,r.4,1 // Are we running on an MPC601 ?
+ beq ZeroRTC // Branch if yes
+
+ mtspr TB,r.3
+ mtspr TBU,r.3
+
+ blr
+
+ZeroRTC:
+ mtspr 20,r.3 // Zero the RTC registers
+ mtspr 21,r.3
+
+
+ LEAF_EXIT(HalpZeroPerformanceCounter)
+
+
diff --git a/private/ntos/nthals/halfire/ppc/pxclock.c b/private/ntos/nthals/halfire/ppc/pxclock.c
new file mode 100644
index 000000000..8d34efa28
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxclock.c
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxclock.c $
+ * $Revision: 1.19 $
+ * $Date: 1996/05/14 02:33:49 $
+ * $Locker: $
+ */
+
+/*****************************************************************************
+
+ Copyright 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:
+
+ PXCLOCK.C
+
+Abstract:
+
+ This module contains the system clock interrupt handler.
+ The DECREMENTER is used to implement the system clock. The
+ handler resets the DECREMENTER to SYSTEM_TIME (accounting
+ for interrupt latency), and updates the system time.
+
+
+Author:
+
+ Steve Johns 10-Feb-1994
+
+Revision History:
+
+******************************************************************************/
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "phsystem.h"
+#include "fpreg.h"
+#include "fpcpu.h"
+
+extern ULONG HalpPerformanceFrequency;
+extern ULONG Irql2Mask[];
+extern ULONG registeredInts[];
+
+BOOLEAN KdPollBreakIn (VOID);
+
+ULONG HalpClockCount;
+ULONG HalpFullTickClockCount;
+ULONG HalpUpdateDecrementer();
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNewTimeIncrement;
+
+// VOID KeUpdateRunTime(PVOID);
+
+/*++
+Routine Description:
+
+ Clock interrupt handler for processor 0.
+
+Arguments:
+
+ Interrupt
+
+ ServiceContext
+
+ TrapFrame
+
+Return Value:
+
+ TRUE
+
+--*/
+BOOLEAN
+HalpHandleDecrementerInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+ KIRQL OldIrql;
+ static int recurse = FALSE;
+ ULONG CpuId;
+
+ HASSERT(!MSR(EE));
+
+ CpuId = GetCpuId();
+
+ //
+ // Raise irql via updating the PCR
+ //
+ OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = CLOCK2_LEVEL;
+ RInterruptMask(CpuId) = (Irql2Mask[CLOCK2_LEVEL] & registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+
+ //
+ // Reset DECREMENTER, accounting for interrupt latency.
+ //
+ HalpUpdateDecrementer(HalpClockCount);
+
+ //
+ // Call the kernel to update system time
+ //
+ KeUpdateSystemTime(TrapFrame,HalpCurrentTimeIncrement);
+ HalpCurrentTimeIncrement = HalpNewTimeIncrement;
+
+ if (!recurse) {
+ //
+ // In some circumstances the KdPollBreakIn can
+ // take longer than a decrementer interrupt
+ // to complete. This is do to a conflict
+ // between DMA and PIO. For now, just avoid
+ // recursing into the debugger check.
+ //
+ recurse = TRUE;
+ if (KdDebuggerEnabled && KdPollBreakIn()) {
+ HalpEnableInterrupts();
+ DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
+ HalpDisableInterrupts();
+ }
+ recurse = FALSE;
+ }
+
+ //
+ // Lower Irql to original value and enable interrupts
+ //
+ PCR->CurrentIrql = OldIrql;
+ RInterruptMask(CpuId) = (Irql2Mask[OldIrql] & registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+ return (TRUE);
+}
+
+/*++
+
+Routine Description:
+
+ Clock interrupt handler for processors other than 0.
+
+Arguments:
+
+ Interrupt
+
+ ServiceContext
+
+ TrapFrame
+
+Return Value:
+
+ TRUE
+
+--*/
+BOOLEAN
+HalpHandleDecrementerInterrupt1(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+ KIRQL OldIrql;
+ ULONG CpuId;
+
+ HASSERT(!MSR(EE));
+
+ CpuId = GetCpuId();
+
+ //
+ // Raise irql via updating the PCR
+ //
+ OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = CLOCK2_LEVEL;
+ RInterruptMask(CpuId) = (Irql2Mask[CLOCK2_LEVEL] & registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+
+ //
+ // Reset DECREMENTER (no account for latency)
+ //
+ HalpUpdateDecrementer(HalpFullTickClockCount);
+
+ //
+ // Call the kernel to update run time for this thread and process.
+ //
+ KeUpdateRunTime(TrapFrame);
+
+ HDBG(DBG_PROC1DBG,
+ {
+ //
+ // Check for the debugger BreakIn only every minute or so.
+ // (decrementer is interms of ms so we multiple by 10,000
+ // on the order of a minute).
+ //
+ static Count = 0;
+ if (++Count > 10000) {
+ Count = 0;
+ if (KdDebuggerEnabled && KdPollBreakIn()) {
+ HalpEnableInterrupts();
+ DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
+ HalpDisableInterrupts();
+ }
+ }
+ }
+ );
+
+ //
+ // Lower Irql to original value
+ //
+ PCR->CurrentIrql = OldIrql;
+ RInterruptMask(CpuId) = (Irql2Mask[OldIrql] & registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+{
+
+ ULONG NewTimeIncrement;
+ ULONG NextIntervalCount;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // HalpPerformanceFrequence is the number of times the decrementer
+ // ticks in 1 second. MINIMUM_INCREMENT is the number of 100 is the
+ // number of 100ns units in 1 ms.
+ // Therefore, DesiredIncrement/MINUMUM_INCREMENT is the number of
+ // ms desired. This multiplied by the number of decrementer ticks
+ // in 1 second, divided by 1000 gives the number of ticks in the
+ // desired number of milliseconds. This value will go into the
+ // decrementer.
+ //
+
+ NextIntervalCount = (HalpPerformanceFrequency *
+ (DesiredIncrement/MINIMUM_INCREMENT)) / 1000;
+
+ //
+ // Calculate the number of 100ns units to report to the kernel every
+ // time the decrementer fires with this new period. Note, for small
+ // values of DesiredIncrement (min being 10000, ie 1ms), truncation
+ // in the above may result in a small decrement in the 5th decimal
+ // place. As we are effectively dealing with a 4 digit number, eg
+ // 10000 becomes 9999.something, we really can't do any better than
+ // the following.
+ //
+
+ NewTimeIncrement = DesiredIncrement/MINIMUM_INCREMENT * MINIMUM_INCREMENT;
+ HalpClockCount = NextIntervalCount;
+ HalpNewTimeIncrement = NewTimeIncrement;
+ KeLowerIrql(OldIrql);
+ return NewTimeIncrement;
+}
+
+
diff --git a/private/ntos/nthals/halfire/ppc/pxdat.c b/private/ntos/nthals/halfire/ppc/pxdat.c
new file mode 100644
index 000000000..6b220977a
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxdat.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxdat.c $
+ * $Revision: 1.9 $
+ * $Date: 1996/05/14 02:33:54 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("INIT")
+#endif
+
+//
+// The following data is only valid during system initialiation
+// and the memory will be re-claimed by the system afterwards
+//
+
+ADDRESS_USAGE HalpDefaultIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0x000, 0x10, // SIO DMA
+ 0x0C0, 0x20, // SIO DMA
+ 0x080, 0x10, // SIO DMA
+ 0x400, 0x40, // SIO DMA
+ 0x480, 0x10, // SIO DMA
+ 0x4D6, 0x2, // SIO DMA
+
+ 0x020, 0x2, // PIC
+ 0x0A0, 0x2, // Cascaded PIC
+
+ 0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+
+ 0x061, 0x1, // NMI (system control port B)
+ 0x092, 0x1, // system control port A
+
+ 0x070, 0x2, // Cmos/NMI enable
+
+ 0x074, 0x4, // NVRAM
+
+ 0x0F0, 0x10, // coprocessor ports
+ 0,0
+ }
+};
+
+
+//
+// From usage.c
+//
+
+ADDRESS_USAGE *HalpAddressUsageList = 0;
+
+//
+// Misc hal stuff in the registry
+//
+
+WCHAR rgzHALentry[] = L"\\Registry\\Machine\\Hardware\\ResourceMap\\Hardware Abstraction Layer\\Powerized HAL";
+
+
+//
+// From ixpcibus.c
+//
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzSystem[] = L"\\Registry\\Machine\\Hardware\\Description\\System";
+WCHAR rgzSoftwareDescriptor[] = L"\\Registry\\Machine\\Software";
+WCHAR rgzFirePOWERNode[] = L"\\Registry\\Machine\\Software\\FirePOWER";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+WCHAR rgzCpuNode[] = L"Registry\\Machine\\Hardware\\Description\\System\\CentralProcessor";
+WCHAR rgzHalNode[] = L"\\HardwareAbstractionLayer";
+WCHAR rgzVeneerNode[] = L"\\Veneer";
+WCHAR rgzFirmwareNode[] = L"\\OpenFIRMWARE";
+
+
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg()
+#endif
+
+//
+// IDT vector usage info
+//
+
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
diff --git a/private/ntos/nthals/halfire/ppc/pxdisp.c b/private/ntos/nthals/halfire/ppc/pxdisp.c
new file mode 100644
index 000000000..aa06f64db
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxdisp.c
@@ -0,0 +1,2907 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxdisp.c $
+ * $Revision: 1.44 $
+ * $Date: 1996/07/02 04:58:11 $
+ * $Locker: $
+ */
+
+/*++
+
+ Copyright (c) 1994 International Business Machines 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:
+
+ pxdisp.c
+
+ Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a Sandalfoot PowerPC system using either an S3 or Weitek P9000
+ video adapter.
+
+ Author:
+
+ Jim Wooldridge Sept 1994 - Ported to PowerPC Initial Version
+
+ Environment:
+
+ Kernel mode
+
+ Revision History:
+
+ Jess Botts S3 support in text mode Oct-1993
+ Lee Nolan Added Weitek P9000 support Feb-1994
+ Mike Haskell Added Weitek P9100 support Oct-1994
+ Roger Lanser 02-23-95: Added FirePower Video and INT10, nuc'd others
+
+ --*/
+
+#include "halp.h"
+#include "pxs3.h" // BUGBUG: generic output?
+#include "string.h"
+#include "fpbat.h"
+#include "arccodes.h"
+#include "phsystem.h"
+#include "pxmemctl.h"
+#include "fpdcc.h"
+#include "fpcpu.h"
+#include "fpdebug.h"
+#include "phsystem.h"
+#include "x86bios.h"
+#include "pxpcisup.h"
+#include "pxcirrus.h"
+
+#define MAX_DBATS 4
+
+// for test only
+NTSYSAPI
+NTSTATUS
+NTAPI
+RtlCharToInteger (
+ PCSZ String,
+ ULONG Base,
+ PULONG Value
+ );
+
+//=============================================================================
+//
+// IBMBJB added include to get text mode values for the Brooktree 485 DAC's
+// palette registers, removed definition of HDAL and added address
+// definitions for PowerPC
+
+#include "txtpalet.h"
+#include "pci.h"
+
+// PCI Vendor ID & Device ID
+#define PCI_VENDOR_ID_WEITEK 0x100e
+#define PCI_DEVICE_ID_WEITEK_P9000 0x9001
+#define PCI_DEVICE_ID_WEITEK_P9100 0x9100
+#define PCI_VENDOR_ID_S3 0x5333
+#define PCI_DEVICE_ID_S3_864_1 0x88c0
+#define PCI_DEVICE_ID_S3_864_2 0x88c1
+
+#if defined(_PPC_)
+
+#define MEMORY_PHYSICAL_BASE VIDEO_MEMORY_BASE
+#define CONTROL_PHYSICAL_BASE VIDEO_CONTROL_BASE
+
+#endif
+
+#define ROWS 25
+#define COLS 80
+#define TAB_SIZE 4
+#define ONE_LINE (80*2)
+#define TWENTY_FOUR_LINES 24*ONE_LINE
+#define TWENTY_FIVE_LINES 25*ONE_LINE
+#define TEXT_ATTR 0x1F
+
+//PHYSICAL ADDRESS of WEITEK P9100 video ram
+#define P91_VIDEO_MEMORY_BASE 0xC1800000
+//PHYSICAL ADDRESS of S3 video ram
+#define S3_VIDEO_MEMORY_BASE 0xC0000000
+
+#if DBG
+extern VOID HalpDisplayBatForVRAM ( void );
+# define TRACE Trace
+#else
+# define TRACE
+#endif
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+//
+// Define forward referenced procedure prototypes.
+//
+BOOLEAN HalpDisplayINT10Setup (VOID);
+VOID HalpOutputCharacterINT10 (IN UCHAR Character );
+VOID HalpScrollINT10 (IN UCHAR line);
+VOID HalpDisplayCharacterVGA (IN UCHAR Character );
+VOID HalpDisplayCharacterVgaViaBios (IN UCHAR Character);
+VOID HalpOutputCharacterVgaViaBios (IN UCHAR AsciiChar);
+BOOLEAN HalpDisplaySetupVgaViaBios (VOID);
+
+
+BOOLEAN HalpDisplayPowerizedGrapicsSetup (ULONG);
+BOOLEAN HalpDisplayPowerizedGraphicsSetup (VOID);
+VOID HalpDisplayCharacterPowerizedGraphics (IN UCHAR Character);
+VOID HalpOutputCharacterPowerizedGraphics (IN PUCHAR Glyph);
+BOOLEAN HalpInitializeDisplay (IN PLOADER_PARAMETER_BLOCK LoaderBlock);
+
+
+VOID HalpOutputCharacterS3 (IN UCHAR AsciiChar);
+BOOLEAN HalpDisplayPpcS3Setup (VOID);
+VOID HalpScrollS3(IN UCHAR line);
+BOOLEAN HalpDisplayPpcP91Setup (VOID);
+VOID HalpDisplayCharacterP91 (IN UCHAR Character);
+VOID HalpOutputCharacterP91(IN PUCHAR Glyph);
+BOOLEAN HalpDisplayPpcP91BlankScreen (VOID);
+VOID HalpDisplayCharacterCirrus(IN UCHAR Character);
+VOID HalpOutputCharacterCirrus(IN UCHAR AsciiChar);
+BOOLEAN HalpDisplayPpcCirrusSetup(VOID);
+VOID HalpScrollCirrus(IN UCHAR line);
+
+static void updattr(IN int rg,IN unsigned char val);
+static void set_ext_regs(IN int reg,IN unsigned char *p);
+static void clear_text(VOID);
+static void load8x16(VOID);
+static void load_ramdac();
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+#if defined(ALLOC_PRAGMA)
+#pragma alloc_text(INIT, HalpInitializeDisplay)
+#pragma alloc_text(INIT, HalpInitializeVRAM)
+#if DBG
+#pragma alloc_text(INIT, HalpDisplayBatForVRAM)
+#endif
+#endif
+
+#if !defined(NT_UP)
+ULONG HalpDisplayLock;
+#endif // !defined(NT_UP)
+
+
+typedef VOID (*PHALP_SCROLL_SCREEN) (UCHAR);
+typedef VOID (*PHALP_OUTPUT_CHARACTER) (UCHAR);
+typedef BOOLEAN (*PHALP_CONTROLLER_SETUP) (VOID);
+typedef VOID (*PHALP_DISPLAY_CHARACTER) (UCHAR);
+
+//
+// Define global data.
+//
+ULONG HalpVideoMemorySize = (ULONG)DISPLAY_MEMORY_SIZE;
+PUCHAR HalpVideoMemoryBase = (PUCHAR)NULL;
+
+//
+// Define static data.
+//
+
+static ULONG PowerizedGraphicsDisplayMode = 0; // default 640x480
+static PVOID HalpVideoConfigBase = NULL;
+static BOOLEAN HalpDisplayOwnedByHal = FALSE; // make sure is false: [breeze:1/27/95]
+static PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+static PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL;
+static PHALP_OUTPUT_CHARACTER HalpOutputCharacter = NULL;
+static PHALP_SCROLL_SCREEN HalpScrollScreen = NULL;
+
+//
+// Define OEM font variables.
+//
+
+USHORT HalpBytesPerRow;
+USHORT HalpCharacterHeight;
+USHORT HalpCharacterWidth;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+//
+// Define display variables.
+//
+ULONG HalpColumn;
+ULONG HalpRow;
+USHORT HalpHorizontalResolution;
+USHORT HalpVerticalResolution;
+USHORT HalpScreenStart = 0; // for cirrus
+
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+
+POEM_FONT_FILE_HEADER HalpFontHeader;
+
+extern ULONG HalpEnableInt10Calls;
+#define PCI_DISPLAY_CONTROLLER 0x03
+#define PCI_PRE_REV_2 0x0
+#define DISPLAY_CLASS 0x03
+
+/*----------------------------------------------------------------------------*/
+#if DBG
+static VOID
+Trace(PCHAR Format, ...)
+
+{
+ va_list arglist;
+ UCHAR Buffer[256];
+ ULONG Length;
+ if (HalpDebugValue & DBG_DISPLAY) {
+ va_start(arglist, Format);
+ Length = vsprintf(Buffer, Format, arglist);
+ DbgPrint(Buffer);
+ }
+}
+#endif
+/*----------------------------------------------------------------------------*/
+#define SEQ_CLKMODE_INDEX 0x01
+#define SEQ_MISC_INDEX 0x11
+#define SEQ_OUTPUT_CTL_INDEX 0x12 /* Vendor specific */
+
+VOID ScreenOn(VOID)
+{
+ UCHAR DataByte;
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ WRITE_S3_UCHAR(Seq_Index, CLOCKING_MODE);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte = DataByte & 0xdf;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ return;
+}
+
+VOID ScreenOff(VOID)
+{
+ UCHAR DataByte;
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ WRITE_S3_UCHAR(Seq_Index, CLOCKING_MODE);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte = DataByte | 0x20;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ return;
+}
+
+#undef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#undef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define CRYSTAL_FREQUENCY (14318180 * 2)
+#define MIN_VCO_FREQUENCY 50000000
+#define MAX_NUMERATOR 130
+#define MAX_DENOMINATOR MIN(129, CRYSTAL_FREQUENCY / 400000)
+#define MIN_DENOMINATOR MAX(3, CRYSTAL_FREQUENCY / 2000000)
+
+#define CLOCK(x) WRITE_S3_UCHAR(MiscOutW, (UCHAR)(iotemp | (x)))
+#define C_DATA 0x0c
+#define C_CLK 0x04
+#define C_BOTH 0x08
+#define C_NONE 0x00
+
+long vclk_range[16] = {
+ 0, // should be MIN_VCO_FREQUENCY, but that causes problems.
+ 51000000,
+ 53200000,
+ 58500000,
+ 60700000,
+ 64400000,
+ 66800000,
+ 73500000,
+ 75600000,
+ 80900000,
+ 83200000,
+ 91500000,
+ 100000000,
+ 120000000,
+ 285000000,
+ 0,
+};
+/******************************************************************************
+ * Number theoretic function - GCD (Greatest Common Divisor)
+ *****************************************************************************/
+static long gcd(a, b)
+register long a, b;
+{
+ register long c = a % b;
+ while (c)
+ a = b, b = c, c = a % b;
+ return b;
+}
+/****************************************************************************
+ * calc_clock
+ *
+ * Usage: clock frequency [set]
+ * frequency is specified in MHz
+ *
+ ***************************************************************************/
+static long calc_clock(frequency, select)
+
+register long frequency; /* in Hz */
+int select;
+{
+ register long index;
+ long temp;
+ long min_m, min_n, min_diff;
+ long diff;
+
+ int clock_m;
+ int clock_n;
+ int clock_p;
+
+ min_diff = 0xFFFFFFF;
+ min_n = 1;
+ min_m = 1;
+
+ /* Calculate 18 bit clock value */
+
+ clock_p = 0;
+ if (frequency < MIN_VCO_FREQUENCY)
+ clock_p = 1;
+ if (frequency < MIN_VCO_FREQUENCY / 2)
+ clock_p = 2;
+ if (frequency < MIN_VCO_FREQUENCY / 4)
+ clock_p = 3;
+
+ frequency <<= clock_p;
+
+ for (clock_n = 4; clock_n <= MAX_NUMERATOR; clock_n++)
+ {
+ index = CRYSTAL_FREQUENCY / (frequency / clock_n);
+
+ if (index > MAX_DENOMINATOR)
+ index = MAX_DENOMINATOR;
+ if (index < MIN_DENOMINATOR)
+ index = MIN_DENOMINATOR;
+
+ for (clock_m = index - 3; clock_m < index + 4; clock_m++)
+ if (clock_m >= MIN_DENOMINATOR && clock_m <= MAX_DENOMINATOR)
+ {
+ diff = (CRYSTAL_FREQUENCY / clock_m) * clock_n - frequency;
+
+ if (diff < 0)
+ diff = -diff;
+
+ if (min_m * gcd(clock_m, clock_n) / gcd(min_m, min_n) == clock_m &&
+ min_n * gcd(clock_m, clock_n) / gcd(min_m, min_n) == clock_n)
+
+ if (diff > min_diff)
+ diff = min_diff;
+
+ if (diff <= min_diff)
+ {
+ min_diff = diff;
+ min_m = clock_m;
+ min_n = clock_n;
+ }
+ }
+ }
+
+ clock_m = min_m;
+ clock_n = min_n;
+
+ /* Calculate the index */
+
+ temp = (((CRYSTAL_FREQUENCY / 2) * clock_n) / clock_m) << 1;
+ for (index = 0; vclk_range[index + 1] < temp && index < 15; index++)
+ ;
+
+ /* Pack the clock value for the frequency snthesizer */
+
+ temp = (((long)clock_n - 3) << 11) + ((clock_m - 2) << 1)
+ + (clock_p << 8) + (index << 18) + ((long)select << 22);
+
+ return temp;
+
+}
+static VOID SetICD2061AClock(LONG clock_value) /* 7bits M, 7bits N, 2bits P */
+{
+ register long index;
+ register char iotemp;
+ int select;
+
+ select = (clock_value >> 22) & 3;
+
+ /* Shut off screen */
+ ScreenOff();
+
+ iotemp = READ_S3_UCHAR(MiscOutR);
+
+ /* Program the IC Designs 2061A frequency generator */
+
+ CLOCK(C_NONE);
+
+ /* Unlock sequence */
+
+ CLOCK(C_DATA);
+ for (index = 0; index < 6; index++)
+ {
+ CLOCK(C_BOTH);
+ CLOCK(C_DATA);
+ }
+ CLOCK(C_NONE);
+ CLOCK(C_CLK);
+ CLOCK(C_NONE);
+ CLOCK(C_CLK);
+
+ /* Program the 24 bit value into REG0 */
+
+ for (index = 0; index < 24; index++)
+ {
+ /* Clock in the next bit */
+ clock_value >>= 1;
+ if (clock_value & 1)
+ {
+ CLOCK(C_CLK);
+ CLOCK(C_NONE);
+ CLOCK(C_DATA);
+ CLOCK(C_BOTH);
+ }
+ else
+ {
+ CLOCK(C_BOTH);
+ CLOCK(C_DATA);
+ CLOCK(C_NONE);
+ CLOCK(C_CLK);
+ }
+ }
+
+ CLOCK(C_BOTH);
+ CLOCK(C_DATA);
+ CLOCK(C_BOTH);
+
+ /* If necessary, reprogram other ICD2061A registers to defaults */
+
+ /* Select the CLOCK in the frequency synthesizer */
+
+ TRACE("select=%d\n", select);
+ CLOCK(C_NONE | select);
+
+ /* Turn screen back on */
+ ScreenOn();
+}
+
+static VOID EnableMemoryAndIO(PCI_CONFIG configBase)
+{
+ USHORT Cmd;
+ // Enable Memory & I/O spaces in command register. Firmware does not always set this.
+ Cmd = READ_REGISTER_USHORT(&configBase->Command);
+ //TRACE("Cmd=0x%x->", Cmd);
+ Cmd = Cmd | 3;
+ //TRACE("0x%x\n", Cmd);
+ WRITE_REGISTER_USHORT(&configBase->Command, Cmd);
+}
+
+static VOID MakeP9100VGA(PVOID pConfigBase)
+{
+ UCHAR DataByte;
+
+ //TRACE("MakeP9100VGA: starting\n");
+ /* Disable the P9000 and enable VGA.*/
+ /* unlocking the 5186/5286 registers */
+ WRITE_S3_UCHAR(Seq_Index, SEQ_MISC_INDEX);
+ DataByte = READ_S3_UCHAR(Seq_Data); /* Read misc register */
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+ WRITE_S3_UCHAR(Seq_Data, DataByte); /* Write back twice */
+ DataByte = READ_S3_UCHAR(Seq_Data); /* Read misc register again */
+ WRITE_S3_UCHAR(Seq_Data, DataByte & ~0x20); /* Clear bit 5 */
+
+ DataByte = READ_REGISTER_UCHAR(((PCHAR)pConfigBase)+65);
+ TRACE("HalpVideoConfigBase+65 DataByte=0x%02x->", DataByte);
+ DataByte = DataByte | 0x0e; // bit 1 VGA emulation
+ DataByte = 0xe2;
+ WRITE_REGISTER_UCHAR(((PCHAR)pConfigBase)+65, DataByte); // this makes display blank
+ DataByte = READ_REGISTER_UCHAR(((PCHAR)pConfigBase)+65);
+ TRACE("0x%02x\n", DataByte);
+
+ {
+ ULONG ul;
+ ULONG clock_numbers;
+
+ ul = 25175000;
+ clock_numbers = calc_clock(ul, 2);
+ SetICD2061AClock(clock_numbers);
+ }
+}
+
+static BOOLEAN
+WorkAroundBeforeInitBIOS()
+{
+ USHORT vendorID = 0;
+ USHORT deviceID = 0;
+ UCHAR revisionID = 0;
+ UCHAR Class;
+ UCHAR SubClass;
+ int i;
+ BOOLEAN Found = FALSE;
+
+ for (i = 1 /* skip SIO */; ((i < MAXIMUM_PCI_SLOTS) && (Found == FALSE)); i++) {
+ HalpVideoConfigBase = (PVOID) ((ULONG) HalpPciConfigBase + HalpPciConfigSlot[i]);
+
+ Class = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[2]);
+ SubClass = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[1]);
+ if ((Class == DISPLAY_CLASS && (SubClass == 0)) ||
+ (Class == 0x00 && SubClass == 0x01)) { // pre-rev 2.0 display card
+
+ vendorID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->VendorID);
+ deviceID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->DeviceID);
+ revisionID = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->RevisionID);
+ TRACE("vendorID=0x%04x deviceID=0x%04x revisionID=0x%02x\n", vendorID, deviceID, revisionID);
+
+ if ((vendorID == PCI_VENDOR_ID_WEITEK) && (deviceID == PCI_DEVICE_ID_WEITEK_P9100)) { //viper Pro
+ EnableMemoryAndIO(HalpVideoConfigBase);
+ MakeP9100VGA(HalpVideoConfigBase); // let BIOS initialize chip
+ }
+ }
+ }
+ return Found;
+}
+
+/* firmware gives 'VGA' even when S3 card is in. */
+static BOOLEAN
+WorkAroundAfterInitBIOS()
+{
+ USHORT vendorID = 0;
+ USHORT deviceID = 0;
+ UCHAR revisionID = 0;
+ UCHAR Class;
+ UCHAR SubClass;
+ int i;
+ BOOLEAN Found = FALSE;
+
+ TRACE("WorkAroundAfterInitBIOS starting.\n");
+
+ for (i = 1; ((i < MAXIMUM_PCI_SLOTS) && (Found == FALSE)); i++) {
+ HalpVideoConfigBase = (PVOID) ((ULONG) HalpPciConfigBase + HalpPciConfigSlot[i]);
+
+ Class = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[2]);
+ SubClass = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[1]);
+ TRACE("ClassID=0x%02x SubClass=0x%02x\n", Class, SubClass);
+
+ if ((Class == DISPLAY_CLASS && (SubClass == 0)) ||
+ (Class == 0x00 && SubClass == 0x01)) { // pre-rev 2.0 display card
+
+ vendorID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->VendorID);
+ deviceID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->DeviceID);
+ revisionID = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->RevisionID);
+ TRACE("vendorID=0x%04x deviceID=0x%04x revisionID=0x%02x\n", vendorID, deviceID, revisionID);
+
+ if (vendorID == PCI_VENDOR_ID_S3) {
+ EnableMemoryAndIO(HalpVideoConfigBase);
+ HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpOutputCharacter = HalpOutputCharacterS3;
+ HalpScrollScreen = HalpScrollS3;
+ Found = TRUE;
+ }
+ }
+ }
+ return Found;
+}
+
+/*++
+
+ Routine Description: BOOLEAN HalpInitializeDisplay ()
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+ Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+ --*/
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey;
+ BOOLEAN Found = FALSE;
+ CHAR buf[BUFSIZ];
+ BOOLEAN bUseVGA = TRUE; // TRUE: scan SVGA cards. FALSE: ignore SVGA cards.
+
+ //IBMLAN Use font file from OS Loader
+ //
+ // For the Weitek P9000, set the address of the font file header.
+ // Display variables are computed later in HalpDisplayPpcP9Setup.
+ //
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+
+ //
+ // Read the Registry entry to find out which video adapter the system
+ // is configured for. This code depends on the OSLoader to put the
+ // correct value in the Registry.
+ //
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+
+ if (NULL == ConfigurationEntry) {
+ TRACE("ConfigurationEntry is NULL.\n");
+ return FALSE;
+ }
+
+ if (HalGetEnvironmentVariable("DISPLAY", sizeof(buf), buf) == ESUCCESS) {
+ TRACE("DISPLAY='%s'\n", buf);
+ bUseVGA = FALSE;
+ }
+ TRACE("HalpInitializeDisplay: ConfigurationEntry->ComponentEntry.Identifier='%s'\n", ConfigurationEntry->ComponentEntry.Identifier);
+
+ while ((TRUE == bUseVGA) && (FALSE == Found)) {
+ Found = WorkAroundBeforeInitBIOS();
+ if (TRUE == Found) break;
+
+ //
+ // Don't look for a PCI video adapter if the environment
+ // variable "DISPLAY" is defined.
+ //
+ if (HalpPciConfigBase) {
+ TRACE("HalpIoMemoryBase = 0x%08x\n", HalpIoMemoryBase);
+ TRACE("HalpPciConfigBase = 0x%08x\n", HalpPciConfigBase);
+ TRACE("HalpIoControlBase = 0x%08x\n", HalpIoControlBase);
+
+ if (HalpInitializeX86DisplayAdapter(LoaderBlock)) {
+ TRACE("HalpInitializeX86DisplayAdapter() succeeded.\n");
+ HalpDisplayControllerSetup = HalpDisplayINT10Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpOutputCharacter = HalpOutputCharacterINT10;
+ HalpScrollScreen = HalpScrollINT10;
+ Found = TRUE;
+ } else {
+ TRACE("HalpInitializeX86DisplayAdapter() failed.\n");
+ }
+ }
+ if (TRUE == Found) break;
+
+ Found = WorkAroundAfterInitBIOS();
+ if (TRUE == Found) break;
+
+ if (!_stricmp(ConfigurationEntry->ComponentEntry.Identifier,"P9100")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcP91Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterP91;
+ Found = TRUE;
+ } else if (!_stricmp(ConfigurationEntry->ComponentEntry.Identifier,"S3")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpOutputCharacter = HalpOutputCharacterS3;
+ HalpScrollScreen = HalpScrollS3;
+ Found = TRUE;
+ } else {
+ // Unsupported VGA display identifier or probably Powerized Graphics.
+ bUseVGA = FALSE;
+ }
+ } /* while */
+
+ while (FALSE == Found) {
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"Powerized Graphics")) {
+ HalpDisplayControllerSetup = HalpDisplayPowerizedGraphicsSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterPowerizedGraphics;
+ //
+ // Set mode 15 which is 1024x768 60 Hz
+ //
+ PowerizedGraphicsDisplayMode = 15;
+ if (HalGetEnvironmentVariable("DISPLAY", sizeof(buf), buf) == ESUCCESS) {
+ if (!_stricmp(buf, "VGA")) {
+ //
+ // Just in case someone wants mode 0 (VGA)
+ //
+ PowerizedGraphicsDisplayMode = 0;
+ }
+ }
+ Found = TRUE;
+ } else if (!_stricmp(ConfigurationEntry->ComponentEntry.Identifier,"VGA")) {
+ //
+ // This is where the INT10 could go if the firmware were
+ // to be trusted.
+ // Just put the framebuffer in VGA mode for now.
+ //
+ HalpDisplayControllerSetup = HalpDisplayPowerizedGraphicsSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterPowerizedGraphics;
+ //
+ // Set mode 0 which is 640x480 60 Hz
+ //
+ PowerizedGraphicsDisplayMode = 0;
+ Found = TRUE;
+ } else {
+ HalDisplayString("can't happen\n");
+ return FALSE;
+ }
+ }
+ //===========end=IBMLAN===============================================
+
+ //
+ // Initialize the display controller.
+ //
+
+ if (HalpDisplayControllerSetup != NULL) {
+ return HalpDisplayControllerSetup();
+ }
+
+ return FALSE;
+}
+
+
+/*++
+
+ Routine Description: VOID HalAcquireDisplayOwnership ()
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+
+
+/*++
+
+ Routine Description: VOID HalDisplayString ()
+
+ This routine displays a character string on the display screen.
+
+ Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, flush the TB, and map the display
+ // frame buffer into the address space of the current process.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayControllerSetup != NULL) {
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+ HalpDisplayControllerSetup();
+ }
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+ }
+
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // and lower IRQL to its previous level.
+ //
+ KeLowerIrql(OldIrql);
+ return;
+
+} /* end of HalpDisplayString() */
+
+
+/*++
+
+ Routine Description: VOID HalQueryDisplayParameters ()
+
+ This routine return information about the display area and current
+ cursor position.
+
+ Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+ *WidthInCharacters = HalpDisplayWidth; //IBMLAN
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+ return;
+}
+
+
+/*++
+
+ Routine Description: VOID HalSetDisplayParameters ()
+
+ This routine set the current cursor position on the display area.
+
+ Arguments:
+
+ CursorColumn - Supplies the new display column position.
+ CursorRow - Supplies a the new display row position.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+ if (CursorColumn > HalpDisplayWidth) { //IBMLAN
+ CursorColumn = HalpDisplayWidth; //IBMLAN
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+ return;
+}
+
+/*++
+
+ Routine Description: BOOLEAN HalpDisplaySetupVgaViaBios ()
+
+ This routine initializes a vga controller via bios reset.
+ Arguments:
+ None.
+ Return Value:
+ None.
+
+ --*/
+
+BOOLEAN
+HalpDisplaySetupVgaViaBios (
+ VOID
+ )
+{
+ //
+ // Routine Description:
+ //
+ //
+
+ ULONG DataLong;
+
+ HalpResetX86DisplayAdapter();
+
+ //
+ // Set screen into blue
+ //
+
+ for (DataLong = 0xB8000; DataLong < 0xB8FA0; DataLong += 2) {
+ WRITE_S3_VRAM(DataLong, 0x20);
+ WRITE_S3_VRAM(DataLong+1, 0x1F);
+ }
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ HalpScrollLine = 160;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayOwnedByHal = TRUE;
+
+ return TRUE;
+}
+
+VOID
+WaitForVSync (VOID)
+{
+ UCHAR DataByte;
+ BOOLEAN test;
+
+ //
+ // Determine 3Dx or 3Bx
+ //
+
+ DataByte = READ_S3_UCHAR(MiscOutR);
+ ColorMonitor = DataByte & 0x01 ? TRUE : FALSE;
+
+ // Unlock S3 ( S3R8 )
+ // UnLockS3();
+
+ //
+ // Test Chip ID = '81h' ?
+ //
+
+ // For standard VGA text mode this action is not necessary.
+ // WRITE_S3_UCHAR(S3_3D4_Index, S3R0);
+ // if ((DataByte = READ_S3_UCHAR(S3_3D5_Data)) == 0x81) {
+ //
+ // Wait For Verttical Retrace
+ //
+
+ test = TRUE;
+ while (test) {
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+
+ test = READ_S3_UCHAR(Stat1_In) & 0x08 ? FALSE : TRUE;
+ }
+
+ // Wait for H/V blanking
+ test = TRUE;
+ while (test) {
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+
+ test = READ_S3_UCHAR(Stat1_In) & 0x01 ? TRUE : FALSE;
+ }
+ // }
+
+ // Lock S3 ( S3R8 )
+ // LockS3();
+
+ return;
+} /* end of WaitForVsync() */
+
+VOID
+Scroll_Screen(IN UCHAR line)
+{
+ UCHAR i, DataByte;
+ ULONG target;
+
+ for (i = 0; i < line; i ++) {
+ //=======================================================================
+ //
+ // IBMBJB added wait for vertical sync to make scroll smooth
+
+ WaitForVSync();
+
+ //=======================================================================
+
+ for (target = 0xB8000; target < 0xB8F00; target += 2) {
+ DataByte = READ_S3_VRAM(target+0xA0);
+ WRITE_S3_VRAM(target, DataByte);
+ }
+ for (target = 0xB8F00; target < 0xB8FA0; target += 2) {
+ WRITE_S3_VRAM(target, 0x20 );
+ }
+ }
+}
+
+
+/*++
+ Routine Description: VOID HalpDisplayCharacterVgaViaBios ()
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalpDisplayCharacterVgaViaBios (
+ IN UCHAR Character
+ )
+{
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ Scroll_Screen(1);
+ }
+ }
+
+ //=========================================================================
+ //
+ // IBMBJB added tab processing
+ //
+
+ else if( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= 80 ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ Scroll_Screen( 1 ); // scroll the screen up
+ else
+ ++HalpRow;
+ }
+ }
+
+ //=========================================================================
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpOutputCharacterVgaViaBios(0);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ } else if (Character >= 0x20) {
+ // Auto wrap for 80 columns per line
+ if (HalpColumn >= 80) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ Scroll_Screen(1);
+ }
+ }
+ HalpOutputCharacterVgaViaBios(Character);
+ } else /* skip the nonprintable character */
+ ;
+
+ return;
+
+}
+
+/*++
+
+ Routine Description: VOID HalpOutputCharacterVgaViaBios ()
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the x cursor position is at the end of the line,
+ then no pixels are inserted in the display.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalpOutputCharacterVgaViaBios (
+ IN UCHAR AsciiChar
+ )
+{
+ ULONG I;
+
+ //
+ // If the current x cursor position is within the current line, then insert
+ // the specified pixels into the last line of the text area and update the
+ // x cursor position.
+ //
+ if (HalpColumn < 80) {
+ I = (HalpRow*HalpScrollLine+HalpColumn*2);
+ WRITE_S3_VRAM(0xb8000 + I, AsciiChar);
+
+ HalpColumn += 1;
+ } else // could expand to automatic wrap line. 9/9/92 By Andrew
+ ;
+
+ return;
+}
+
+/*************************************************************************/
+/* Following code (to EOF) added for PowerPro HAL Display Support [ged]. */
+/*************************************************************************/
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ PVOID fontheader;
+
+ // Use font file from OS Loader
+ //
+ // During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from
+ // the OS Loader heap into pool.
+ //
+
+ fontheader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize );
+ if(fontheader == NULL ) {
+ return FALSE;
+ }
+
+ RtlMoveMemory(fontheader, HalpFontHeader, HalpFontHeader->FileSize );
+ HalpFontHeader = (POEM_FONT_FILE_HEADER) fontheader;
+
+ return TRUE;
+}
+
+/*++
+
+ Routine Description: BOOLEAN HalpDisplayPowerizedGraphicsSetup ()
+
+ This routine initializes the FirePower 'Powerized Graphics' frame buffer.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+ --*/
+
+BOOLEAN
+HalpDisplayPowerizedGraphicsSetup (
+ VOID
+ )
+{
+ PULONG buffer;
+ ULONG limit, index;
+ static ULONG vramWidth; // mogawa BUG3449
+ static BOOLEAN onetime = TRUE;
+
+
+ /* NOTE: The following line remaps the virtual to physical mapping */
+ /* of DBAT3 to the physical address of PowerPro's frame */
+ /* buffer. This overrides the Kernel's mapping to PCI memory. */
+ /* If Motorola changes this, we need to revisit it! [ged] */
+ /* NOTE2: For speed, we may want to make this region cacheable. */
+
+ // Moved dbat mapping to init routines to remove it from normal code
+ // path [breeze-7.15.94]
+ //
+ // Moved mapping back here so various adapters can be supported,
+ // without getting the frame buffer init'd in the mainline init.
+ // [rlanser-02.06.95]
+
+
+ if (onetime) {
+
+ onetime = FALSE;
+
+ HalpVideoMemoryBase =
+ HalpInitializeVRAM( (PVOID)DISPLAY_MEMORY_BASE, &HalpVideoMemorySize, &vramWidth);
+
+ //
+ // Set FrameBuffer Control Register
+ //
+ // Use a mask value of 7
+ //
+
+ {
+ ULONG ul = rFbControl;
+ ul &= ~0x07000000;
+ ul |= 0x07000000 & (vramWidth ? 0x0 : 0x03000000);
+ rFbControl = ul;
+ FireSyncRegister();
+ }
+
+ if (!HalpVideoMemoryBase) {
+ HalpDebugPrint("HalpVideoMemoryBase did not map...%x,%x\n",
+ HalpVideoMemoryBase,HalpVideoMemorySize);
+ HDBG(DBG_BREAK, DbgBreakPoint(););
+ return FALSE;
+ }
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpVideoMemoryBase is: 0x%x\n",
+ HalpVideoMemoryBase););
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalpIoControlBase = 0x%x\n",
+ HalpIoControlBase););
+ }
+
+ if (15 == PowerizedGraphicsDisplayMode) {
+ HalpSetupDCC(15, vramWidth); // mode 15 - 1024x768 8 bit 60Hz
+ HalpHorizontalResolution = 1024;
+ HalpVerticalResolution = 768;
+ } else {
+ HalpSetupDCC(0, vramWidth); // mode 0 - 640x480 8 bit 60Hz
+ HalpHorizontalResolution = 640;
+ HalpVerticalResolution = 480;
+ }
+
+ HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = HalpFontHeader->PixelHeight;
+ HalpCharacterWidth = HalpFontHeader->PixelWidth;
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpVerticalResolution / HalpCharacterHeight;
+
+ HalpScrollLine =
+ HalpHorizontalResolution * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpHorizontalResolution / HalpCharacterWidth;
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ buffer = (PULONG)HalpVideoMemoryBase;
+ limit = (HalpHorizontalResolution *
+ HalpVerticalResolution) / sizeof(ULONG);
+
+ for (index = 0; index < limit; index += 1) {
+ *buffer++ = 0x01010101;
+ }
+
+ //
+ // Since we use a cached Video Controler sweep the video memory
+ // range.
+ //
+ HalSweepDcacheRange(HalpVideoMemoryBase, HalpVideoMemorySize);
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+
+ return TRUE;
+
+} /* HalpDisplayPowerizedGraphicsSetup */
+
+
+/*++
+
+ Routine Description: VOID HalpDisplayCharacterPowerizedGraphics ()
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encountered, the frame buffer is
+ scrolled. If characters extend beyond the end of line, they are not
+ displayed.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalpDisplayCharacterPowerizedGraphics (
+ IN UCHAR Character
+ )
+{
+
+ PUCHAR Destination;
+ PUCHAR Source;
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ //RtlMoveMemory((PVOID)PRO_VIDEO_MEMORY_BASE,
+ // (PVOID)(PRO_VIDEO_MEMORY_BASE + HalpScrollLine),
+ // HalpScrollLength);
+
+ // Scroll up one line
+ Destination = HalpVideoMemoryBase;
+ Source = (PUCHAR) HalpVideoMemoryBase + HalpScrollLine;
+ for (Index = 0; Index < HalpScrollLength; Index++) {
+ *Destination++ = *Source++;
+ }
+ // Blue the bottom line
+ Destination = HalpVideoMemoryBase + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+ } else if( Character == '\t' ) { // tab?
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ // tab beyond end of screen?
+ if (HalpColumn >= HalpDisplayWidth) {
+ // next tab stop is 1st column of next line
+ HalpColumn = 0;
+
+ if( HalpRow >= (HalpDisplayText - 1) ) {
+ HalpDisplayCharacterPowerizedGraphics('\n');
+ } else {
+ HalpRow++;
+ }
+ }
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn--;
+ HalpDisplayCharacterPowerizedGraphics(' ');
+ HalpColumn--;
+ }
+
+ } else if (Character >= 0x20) {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterPowerizedGraphics((PUCHAR)HalpFontHeader + \
+ HalpFontHeader->Map[Character].Offset);
+ } /* else skip the nonprintable character */
+
+ return;
+} /* HalpDisplayCharacterPowerizedGraphics */
+
+
+
+/*++
+
+ Routine Description: VOID HalpOutputCharacterPowerizedGraphics()
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+VOID
+HalpOutputCharacterPowerizedGraphics(
+ IN PUCHAR Glyph
+ )
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn >= HalpDisplayWidth) {
+ HalpDisplayCharacterPowerizedGraphics('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(HalpVideoMemoryBase +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ if (FontValue >> 31 != 0) {
+ *Destination = 0xFF; //Make this pixel white
+ } else {
+ *Destination = 0x01; //Make this pixel blue
+ }
+ HalSweepDcacheRange(Destination, 1); // Push it out
+ Destination++;
+ //*Destination++ = (FontValue >> 31) ^ 1;
+ FontValue <<= 1;
+ }
+
+ Destination +=
+ (HalpHorizontalResolution - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+
+ return;
+
+} /* HalpOutputCharacterPowerizedGraphics */
+
+
+///
+/// Debug
+///
+
+VOID
+HalpDebugPrint(
+
+ PCHAR Format,
+ ...
+ )
+
+{
+ va_list arglist;
+ UCHAR Buffer[256];
+ ULONG Length;
+
+ //
+ // Format the output into a buffer and then print it.
+ //
+
+ va_start(arglist, Format);
+ Length = vsprintf(Buffer, Format, arglist);
+ if (HalpDisplayOwnedByHal) {
+ HalDisplayString(Buffer);
+ }
+ DbgPrint(Buffer);
+}
+
+VOID
+HalpForceDisplay(
+ PCHAR Format,
+ ...
+ )
+{
+ va_list arglist;
+ UCHAR Buffer[256];
+ ULONG Length;
+
+ //
+ // Format the output into a buffer and then display it.
+ //
+ va_start(arglist, Format);
+ Length = vsprintf(Buffer, Format, arglist);
+ HalDisplayString(Buffer);
+}
+
+/*-----------------------------------------------------------------------------------------*/
+VOID
+HalpDisplayCharacterVGA (
+ IN UCHAR Character
+ )
+
+/*++
+ Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+{
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ HalpScrollScreen(1);
+ }
+ }
+
+ //=========================================================================
+ //
+ // IBMBJB added tab processing
+ //
+
+ else if( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= 80 ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ HalpScrollScreen( 1 ); // scroll the screen up
+ else
+ ++HalpRow;
+ }
+ }
+
+ //=========================================================================
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpOutputCharacter(0);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ } else if (Character >= 0x20) {
+ // Auto wrap for 80 columns per line
+ if (HalpColumn >= 80) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ HalpScrollScreen(1);
+ }
+ }
+ HalpOutputCharacter(Character);
+ } else /* skip the nonprintable character */
+ ;
+
+ return;
+
+} /* end of HalpDisplayCharacterVGA() */
+
+VOID HalpOutputCharacterINT10 (
+ IN UCHAR Character)
+{ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ Eax = 2 << 8; // AH = 2
+ Ebx = 0; // BH = page number
+ Edx = (HalpRow << 8) + HalpColumn;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ Eax = (0x0A << 8) + Character; // AH = 0xA AL = character
+ Ebx = 0;
+ Ecx = 1;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ HalpColumn += 1;
+
+}
+
+
+VOID HalpScrollINT10 (
+ IN UCHAR LinesToScroll)
+
+{ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ Eax = 6 << 8; // AH = 6 (scroll up)
+ Eax |= LinesToScroll; // AL = lines to scroll
+ Ebx = TEXT_ATTR << 8; // BH = attribute to fill blank line(s)
+ Ecx = 0; // CH,CL = upper left
+ Edx = (24 << 8) + 79; // DH,DL = lower right
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+}
+
+BOOLEAN HalpDisplayINT10Setup (VOID)
+{ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ HalpScrollLine = 160;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayOwnedByHal = TRUE;
+
+ //
+ // Set cursor to (0,0)
+ //
+ Eax = 0x02 << 8; // AH = 2
+ Ebx = 0; // BH = page Number
+ Edx = 0; // DH = row DL = column
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ //
+ // Make screen white on blue by scrolling entire screen
+ //
+ Eax = 0x06 << 8; // AH = 6 AL = 0
+ Ebx = TEXT_ATTR << 8; // BH = attribute
+ Ecx = 0; // (x,y) upper left
+ Edx = ((HalpDisplayText-1) << 8); // (x,y) lower right
+ Edx += HalpScrollLine/2;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ return TRUE;
+}
+/*------------------------------------------------------------------------*/
+
+BOOLEAN
+HalpDisplayPpcS3Setup (
+ VOID
+ )
+/*++
+
+ Routine Description:
+ This routine initializes the S3 display controller chip.
+ Arguments:
+ None.
+ Return Value:
+ TRUE if finished successfully
+
+ --*/
+{
+//
+// Routine Description:
+//
+// This is the initialization routine for S3 86C911. This routine initializes
+// the S3 86C911 chip in the sequence of VGA BIOS for AT.
+//
+ ULONG DataLong;
+ USHORT i,j;
+ UCHAR DataByte;
+ UCHAR Index;
+// PVOID Index_3x4, Data_3x5;
+ ULONG MemBase;
+
+
+ if (HalpVideoMemoryBase == NULL) {
+ TRACE("HalpDisplayPpcS3Setup: calling KePhase0MapIo(S3_VIDEO_MEMORY_BASE,0x400000).\n");
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo((PVOID)S3_VIDEO_MEMORY_BASE,
+ 0x400000); // 4 MB
+ }
+
+ // Enable Video Subsystem
+ // Accordint to chapter 5.4.2 regular VGA setup sequence
+ TRACE("HalpDisplayPpcS3Setup: starting.\n");
+
+ //=========================================================================
+ //
+ // IBMBJB changed from writing 0x10 and then 0x08 to writing 0x18
+ // because the second write will wipe out the first one, the
+ // second write was originally done after the write to Setup_OP
+ //
+ // WRITE_S3_UCHAR(SUBSYS_ENB, 0x10);
+ // WRITE_S3_UCHAR(SUBSYS_ENB, 0x08);
+
+ WRITE_S3_UCHAR(SUBSYS_ENB, 0x18);
+
+ //=========================================================================
+
+ TRACE(" Subsystem Enable = 0x10...\n");
+ WRITE_S3_UCHAR(Setup_OP, 0x01);
+
+
+ WRITE_S3_UCHAR(DAC_Mask, 0x0); // Set screen into blank
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ WRITE_S3_UCHAR(Seq_Data, 0x21);
+
+ //=========================================================================
+ //
+ // IBMBJB removed this section because it is not currently used, this
+ // was left commented out instead of deleting it in case we use
+ // a monochrome monitor in the future
+ //
+ // // Check monitor type to decide index address (currently not use)
+ // DataByte = READ_S3_UCHAR(MiscOutR);
+ // ColorMonitor = DataByte & 0x01 ? TRUE : FALSE;
+ //
+ // if (ColorMonitor) {
+ // Index_3x4 = (PVOID)S3_3D4_Index;
+ // Data_3x5 = (PVOID)S3_3D5_Data;
+ // } else {
+ // Index_3x4 = (PVOID)Mono_3B4;
+ // Data_3x5 = (PVOID)Mono_3B5;
+ // }
+ //
+ //=========================================================================
+
+ //
+ // -- Initialization Process Begin --
+ // According to appendix B-4 "ADVANCED PROGRAMMER'S GUIDE TO THE EGA/VGA"
+ // to set the default values to VGA +3 mode.
+ //
+ WRITE_S3_UCHAR(VSub_EnB,VideoParam[0]);
+ // Note: Synchronous reset must be done before MISC_OUT write operation
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ // For ATI card(0x63) we may want to change the frequence
+ WRITE_S3_UCHAR(MiscOutW,VideoParam[1]);
+
+ // Note: Synchronous reset must be done before CLOCKING MODE register is
+ // modified
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ // Sequencer Register
+ for (Index = 1; Index < 5; Index++) {
+ WRITE_S3_UCHAR(Seq_Index, Index);
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+Index]);
+ }
+
+
+ // Set CRT Controller
+ // out 3D4, 0x11, 00 (bit 7 must be 0 to unprotect CRT R0-R7)
+ // UnLockCR0_7();
+ WRITE_S3_UCHAR(S3_3D4_Index, VERTICAL_RETRACE_END);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte = DataByte & 0x7f;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // CRTC controller CR0 - CR18
+ for (Index = 0; Index < 25; Index++) {
+ WRITE_S3_UCHAR(S3_3D4_Index, Index);
+ WRITE_S3_UCHAR(S3_3D5_Data, VideoParam[CRT_OFFSET+Index]);
+ }
+
+ // attribute write
+ // program palettes and mode register
+ TRACE(" Program palettes ...\n");
+ for (Index = 0; Index < 21; Index++) {
+ WaitForVSync();
+
+ DataByte = READ_S3_UCHAR(Stat1_In); // Initialize Attr. F/F
+ WRITE_S3_UCHAR(Attr_Index,Index);
+ KeStallExecutionProcessor(5);
+
+ WRITE_S3_UCHAR(Attr_Data,VideoParam[ATTR_OFFSET+Index]);
+ KeStallExecutionProcessor(5);
+
+ WRITE_S3_UCHAR(Attr_Index,0x20); // Set into normal operation
+ }
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ // graphics controller
+ TRACE(" Graphics controller...\n");
+ for (Index = 0; Index < 9; Index++) {
+ WRITE_S3_UCHAR(GC_Index, Index);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+Index]);
+ }
+
+ // turn off the text mode cursor
+ WRITE_S3_UCHAR(S3_3D4_Index, CURSOR_START);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x2D);
+
+ // Unlock S3 specific registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x48);
+
+ // Unlock S3 SC registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0xa0);
+
+ // Disable enhanced mode
+ WRITE_S3_UCHAR(ADVFUNC_CNTL, 0x02);
+
+ // Turn off H/W Graphic Cursor
+ WRITE_S3_UCHAR(S3_3D4_Index, SC5);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ //=========================================================================
+ //
+ // IBMBJB S3 errata sheet says that CR40 can not be read correctly after
+ // power up until it has been written to, suggested workaround is
+ // to use the power on default (0xA4) Since the intent of the
+ // existing code was to reset bit 0, 0xA4 will be used to reset
+ // the bit. The other bits that are reset select the desired
+ // default configuration.
+ //
+ // If this register is written by the firmware then this fix is
+ // unneccessary. If future modifications of the firmware were to
+ // remove all writes to this register then this fix would have to
+ // be added here. This is being added now to protect this code
+ // from possible firmware changes.
+ //
+ // // Disable enhanced mode registers access
+ // WRITE_S3_UCHAR(S3_3D4_Index, SC0);
+ // DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ // DataByte &= 0xfe;
+ // DataByte ^= 0x0;
+ //
+ // WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+ //
+
+ WRITE_S3_UCHAR( S3_3D4_Index, SC0 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0xA4 );
+
+ //=========================================================================
+
+ // Set Misc 1 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R0A);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0xc7;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Set S3R1 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R1);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0x80;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Set S3R2 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R2);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Set S3R4 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R4);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0xec;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ //=========================================================================
+ //
+ // IBMBJB added this section to eliminate the DAC hardware cursor, this
+ // is done before setting registers 0x50 - 0x62 to default states
+ // so that R55's default state will not be undone.
+ //
+ // this sequence zeros the 2 least signifigant bits in command
+ // register 2 on the DAC
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // set RS[3:2] to 10
+ DataByte = READ_S3_UCHAR( S3_3D5_Data );
+ DataByte &= 0xfc;
+ DataByte |= 0x02;
+ WRITE_S3_UCHAR( S3_3D5_Data, DataByte );
+
+ DataByte = READ_S3_UCHAR( DAC_Data );
+ DataByte &= 0xfc; // zero CR21,20 in DAC command
+ WRITE_S3_UCHAR( DAC_Data, DataByte ); // register 2
+
+ //=========================================================================
+ //
+ // IBMBJB Added code to configure for 18 bit color mode and reload the
+ // palette registers because the firmware configures for 24 bit
+ // color. If this is done when the system driver initializes for
+ // graphics mode then the text mode colors can not be changed
+ // properly.
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // RS[3:2] = 01B to address
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x01 ); // DAC command register 0
+
+ DataByte = READ_S3_UCHAR( DAC_Mask ); // reset bit 1 in DAC command
+ DataByte &= 0xfd; // register 0 to select 6 bit
+ WRITE_S3_UCHAR( DAC_Mask, DataByte ); // operation (18 bit color)
+
+ // IBMBJB added write to SDAC PLL control register to make sure CLK0
+ // is correct if we have to reinitialize after graphics mode
+ // initialization, this does not bother the 928/Bt485 card
+ // because the Bt485 DAC looks very much like the SDAC
+
+ WRITE_S3_UCHAR( DAC_WIndex, 0x0e ); // select SDAC PLL control reg
+ WRITE_S3_UCHAR( DAC_Data, 0x00 ); // select SDAC CLK0
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // select DAC color palette
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 ); // registers
+
+ WRITE_S3_UCHAR( DAC_WIndex, 0 ); // start load in register 0
+
+ for( i = 0, j = 0; i < 256; ++i ) // load all color registers
+ {
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // red intensity
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // green intensity
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // blue intensity
+ }
+
+ //=========================================================================
+ //
+ // IBMBJB added writes to registers 0x50 - 0x62 to set them to a known
+ // state because some of them are set by the firmware and are
+ // not correct for our use
+ //
+ // NOTE: there are some writes to the DAC registers in code that
+ // executes later that depend on R55[1:0] being 00B, if the
+ // default state of R55 is changed make sure that these bits
+ // are not changed
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x50 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x51 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x52 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x53 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x54 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x56 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x57 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x58 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x59 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5a );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x0a );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5B );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5C );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5D );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5E );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5F );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ // IBMBJB changed value written from 0 to 1 for an S3 864 based card to
+ // clear up bad display caused by 864->SDAC FIFO underrun
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x60 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x01 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x61 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x62 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ //=========================================================================
+ //
+ // IBMBJB added setting bits 7 and 6 of CR65, errata sheet fix for split
+ // transfer problem in parallel and continuous addressing modes
+ // Note: side effect of setting bit 7 was a garbled firmware screen after
+ // shutdown.
+
+ // Set SR65 bits 7 and 6
+ WRITE_S3_UCHAR(S3_3D4_Index, 0x65);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte |= 0x40;
+// DataByte |= 0xc0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Lock S3 SC registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Lock S3 specific registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Load character fonts into plane 2 (A0000-AFFFF)
+ TRACE(" Load Fonts into Plane2 ...\n");
+ WRITE_S3_UCHAR(Seq_Index,0x02); // Enable Write Plane reg
+ WRITE_S3_UCHAR(Seq_Data,0x04); // select plane 2
+
+ WRITE_S3_UCHAR(Seq_Index,0x04); // Memory Mode Control reg
+ WRITE_S3_UCHAR(Seq_Data,0x06); // access to all planes,
+
+ WRITE_S3_UCHAR(GC_Index,0x05); // Graphic, Control Mode reg
+ WRITE_S3_UCHAR(GC_Data,0x00);
+
+ WRITE_S3_UCHAR(GC_Index,0x06);
+ WRITE_S3_UCHAR(GC_Data,0x04);
+
+ WRITE_S3_UCHAR(GC_Index,0x04);
+ WRITE_S3_UCHAR(GC_Data,0x02);
+
+ MemBase = 0xA0000;
+ for (i = 0; i < 256; i++) {
+ for (j = 0; j < 16; j++) {
+ WRITE_S3_VRAM(MemBase, VGAFont8x16[i*16+j]);
+ MemBase++;
+ }
+ // 32 bytes each character font
+ for (j = 16; j < 32; j++) {
+ WRITE_S3_VRAM(MemBase, 0 );
+ MemBase++;
+ }
+ }
+
+ // turn on screen
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte &= 0xdf;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WaitForVSync();
+
+ // Enable all the planes through the DAC
+ WRITE_S3_UCHAR(DAC_Mask, 0xff);
+
+ // select plane 0, 1
+ WRITE_S3_UCHAR(Seq_Index, 0x02); // Enable Write Plane reg
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x02]);
+
+ // access to planes 0, 1.
+ WRITE_S3_UCHAR(Seq_Index, 0x04); // Memory Mode Control reg
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x04]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x05); // Graphic, Control Mode reg
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x05]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x04);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x04]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x06);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x06]);
+
+ //
+ // Set screen into blue
+ //
+ TRACE(" Set Screen into Blue ...\n");
+ for (DataLong = 0xB8000;
+ DataLong < 0xB8000+TWENTY_FIVE_LINES;
+ DataLong += 2) {
+ WRITE_S3_VRAM(DataLong, ' ');
+ WRITE_S3_VRAM(DataLong+1, TEXT_ATTR);
+ }
+ // End of initialize S3 standard VGA +3 mode
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ //IBMLAN===============================================================
+ // Added the following so that HalQueryDisplayParameters() and
+ // HalSetDisplayParameters() work with either S3 or P9.
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ HalpScrollLine = 160;
+ HalpScrollLength =
+ HalpScrollLine * (HalpDisplayText - 1);
+
+ //end IBMLAN===========================================================
+ HalpDisplayOwnedByHal = TRUE;
+
+ return TRUE;
+} /* end of HalpDisplayPpcS3Setup() */
+
+VOID
+HalpOutputCharacterS3 (
+ IN UCHAR AsciiChar
+ )
+
+/*++
+
+ Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the x cursor position is at the end of the line,
+ then no pixels are inserted in the display.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+{
+ ULONG I;
+
+ //
+ // If the current x cursor position is within the current line, then insert
+ // the specified pixels into the last line of the text area and update the
+ // x cursor position.
+ //
+ if (HalpColumn < 80) {
+ I = (HalpRow*HalpScrollLine+HalpColumn*2);
+ WRITE_S3_VRAM(0xb8000 + I, AsciiChar);
+
+ HalpColumn += 1;
+ } else // could expand to automatic wrap line. 9/9/92 By Andrew
+ ;
+
+ return;
+} /* end of HalpOutputCharacterS3() */
+
+
+
+VOID
+HalpScrollS3(IN UCHAR line)
+{
+ UCHAR i, DataByte;
+ ULONG target;
+
+ for (i = 0; i < line; i ++) {
+ //=======================================================================
+ //
+ // IBMBJB added wait for vertical sync to make scroll smooth
+
+ WaitForVSync();
+
+ //=======================================================================
+
+ for (target = 0xB8000;
+ target < 0xB8000+TWENTY_FOUR_LINES;
+ target += 2) {
+ DataByte = READ_S3_VRAM(target+ONE_LINE);
+ WRITE_S3_VRAM(target, DataByte);
+ }
+ for (target = 0xB8000+TWENTY_FOUR_LINES;
+ target < 0xB8000+TWENTY_FIVE_LINES;
+ target += 2) {
+ WRITE_S3_VRAM(target, ' ' );
+ }
+ }
+}
+/*------------------------------------------------------------------------*/
+static PUCHAR HalpP91VideoMemoryBase = (PUCHAR)0;
+
+BOOLEAN
+HalpDisplayPpcP91Setup (
+ VOID
+ )
+/*++
+
+ Routine Description:
+
+ This routine initializes the Weitek P9100 display contoller chip.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+ --*/
+{
+ PULONG buffer;
+ ULONG limit, index;
+ TRACE("HalpDisplayPpcP91Setup: starting...\n");
+ // For now I'll leave the P9100 in the same state that the firmware
+ // left it in. This should be 640x480.
+
+ HalpHorizontalResolution = 640;
+ HalpVerticalResolution = 480;
+
+ if (HalpP91VideoMemoryBase == NULL) {
+
+ HalpP91VideoMemoryBase = (PUCHAR)KePhase0MapIo((PVOID)P91_VIDEO_MEMORY_BASE,
+ 0x800000); // 8 MB
+ }
+
+ //IBMLAN Use font file from OS Loader
+ //
+ // Compute display variables using using HalpFontHeader which is
+ // initialized in HalpInitializeDisplay().
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+ //FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ //HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = HalpFontHeader->PixelHeight;
+ HalpCharacterWidth = HalpFontHeader->PixelWidth;
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpVerticalResolution / HalpCharacterHeight;
+
+ HalpScrollLine =
+ HalpHorizontalResolution * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpHorizontalResolution / HalpCharacterWidth;
+
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ buffer = (PULONG)HalpP91VideoMemoryBase;
+ limit = (HalpHorizontalResolution *
+ HalpVerticalResolution) / sizeof(ULONG);
+
+ limit = 0x100000/sizeof(ULONG); // mogawa
+ for (index = 0; index < limit; index += 1) {
+ *buffer++ = 0x01010101;
+ }
+
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return TRUE;
+
+} //end of HalpDisplayPpcP91Setup
+
+VOID
+HalpDisplayCharacterP91 (
+ IN UCHAR Character
+ )
+/*++
+
+ Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encountered, the frame buffer is
+ scrolled. If characters extend below the end of line, they are not
+ displayed.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+{
+
+ PUCHAR Destination;
+ PUCHAR Source;
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+ if (Character == '\n') {
+ UCHAR DataByte;
+ DataByte = READ_REGISTER_UCHAR(((PCHAR)HalpVideoConfigBase)+65);
+ TRACE("Config[65]=0x%02x\n", DataByte);
+
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ //RtlMoveMemory((PVOID)P91_VIDEO_MEMORY_BASE,
+ // (PVOID)(P91_VIDEO_MEMORY_BASE + HalpScrollLineP9),
+ // HalpScrollLengthP9);
+
+ // Scroll up one line
+ Destination = HalpP91VideoMemoryBase;
+ Source = (PUCHAR) HalpP91VideoMemoryBase + HalpScrollLine;
+ for (Index = 0; Index < HalpScrollLength; Index++) {
+ *Destination++ = *Source++;
+ }
+ // Blue the bottom line
+ Destination = HalpP91VideoMemoryBase + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ } else {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterP91((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalpOutputCharacterP91(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+ Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+ Arguments:
+
+ Character - Supplies a character to be displayed.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ //ULONG tmp;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacterP91('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(HalpP91VideoMemoryBase +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ if (FontValue >> 31 != 0) {
+ *Destination = 0xFF; //Make this pixel white
+ HalSweepDcacheRange(Destination, 1); // Push it out
+ }
+ Destination++;
+ //*Destination++ = (FontValue >> 31) ^ 1;
+ FontValue <<= 1;
+ }
+
+ Destination +=
+ (HalpHorizontalResolution - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+ return;
+}
+
+BOOLEAN
+HalpDisplayPpcP91BlankScreen (
+ VOID
+ )
+{
+ PULONG buffer;
+ ULONG limit, index;
+
+ if (HalpP91VideoMemoryBase == NULL) {
+ return FALSE;
+ }
+
+ buffer = (PULONG)HalpP91VideoMemoryBase;
+ limit = (HalpHorizontalResolution *
+ HalpVerticalResolution) / sizeof(ULONG);
+
+ limit = 0x100000/sizeof(ULONG); // mogawa
+ for (index = 0; index < limit; index += 1) {
+ *buffer++ = 0x00000000;
+ }
+ return TRUE;
+}
+
+
+/*------------------------------------------------------------------------*/
+//
+// Cirrus Device Driver
+//
+
+// Routine Description:
+//
+// This routine displays a character at the current x and y positions in
+// the frame buffer. If a newline is encounter, then the frame buffer is
+// scrolled. If characters extend below the end of line, then they are not
+// displayed.
+//
+// Arguments:
+//
+// Character - Supplies a character to be displayed.
+//
+// Return Value:
+//
+// None.
+//
+
+VOID
+HalpDisplayCharacterCirrus (
+ IN UCHAR Character
+ )
+{
+
+//
+// If the character is a newline, then scroll the screen up, blank the
+// bottom line, and reset the x position.
+//
+
+ if (Character == '\n')
+ {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1))
+ {
+ HalpRow += 1;
+ }
+ else
+ { // need to scroll up the screen
+ HalpScrollScreen(1);
+ }
+ }
+
+//
+// added tab processing
+//
+
+ else if ( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if ( HalpColumn >= COLS ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column
+ // of next line
+
+ if ( HalpRow >= (HalpDisplayText - 1) )
+ HalpScrollScreen( 1 );
+ else ++HalpRow;
+ }
+ }
+ else if (Character == '\r')
+ {
+ HalpColumn = 0;
+ }
+ else if (Character == 0x7f)
+ { // DEL character
+ if (HalpColumn != 0)
+ {
+ HalpColumn -= 1;
+ HalpOutputCharacterCirrus(0);
+ HalpColumn -= 1;
+ }
+ else // do nothing
+ ;
+ }
+ else if (Character >= 0x20)
+ {
+ // Auto wrap for 80 columns
+ // per line
+ if (HalpColumn >= COLS)
+ {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1))
+ {
+ HalpRow += 1;
+ }
+ else
+ { // need to scroll up the screen
+ HalpScrollScreen(1);
+ }
+ }
+ HalpOutputCharacterCirrus(Character);
+ }
+ // skip the nonprintable character
+}
+
+
+//
+//
+// Routine Description:
+//
+// This routine insert a set of pixels into the display at the current x
+// cursor position. If the x cursor position is at the end of the line,
+// then no pixels are inserted in the display.
+//
+// Arguments:
+//
+// Character - Supplies a character to be displayed.
+//
+// Return Value:
+//
+// None.
+//
+
+
+VOID
+HalpOutputCharacterCirrus (
+ IN UCHAR AsciiChar
+ )
+{
+ PUCHAR Destination;
+ ULONG I;
+
+//
+// If the current x cursor position is within the current line, then insert
+// the specified pixels into the last line of the text area and update the
+// x cursor position.
+//
+
+ if (HalpColumn < COLS)
+ {
+ I = (HalpRow*HalpScrollLine+HalpColumn*2);
+ Destination = (PUCHAR)(CIRRUS_TEXT_MEM + I + HalpScreenStart);
+ WRITE_CIRRUS_VRAM(Destination, AsciiChar);
+ HalpColumn += 1;
+ }
+}
+
+
+//
+// Routine Description:
+//
+// This routine initializes the Cirrus CL-GD5430 graphics controller chip
+//
+
+static void updattr(IN int rg,IN unsigned char val)
+{
+ inp(0x3da);
+ outportb(0x3c0,rg);
+ outportb(0x3c0,val);
+ outportb(0x3c0,((unsigned char)(rg | 0x20)));
+}
+
+
+static void set_ext_regs(IN int reg,IN unsigned char *p)
+{
+ unsigned char index, data;
+
+ while (*p != 0xff)
+ {
+ index= *p++;
+ data= *p++;
+ setreg(reg,index,data);
+ }
+}
+
+
+BOOLEAN
+HalpDisplayPpcCirrusSetup (
+ VOID
+ )
+{
+ int i;
+
+ //DbgBreakPoint();
+ TRACE("HalpDisplayPpcCirrusSetup: starting.\n");
+ if (HalpVideoMemoryBase == NULL) {
+ TRACE("HalpDisplayPpcCirrusSetup: calling KePhase0MapIo(CIRRUS_VIDEO_MEMORY_BASE,0x400000).\n");
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo((PVOID)CIRRUS_VIDEO_MEMORY_BASE, 0x400000); // 4 MB
+ } else {
+ TRACE("HalpVideoMemoryBase=0x%08x\n", HalpVideoMemoryBase);
+ }
+
+//
+// Assert synchronous reset while setting the clock mode
+//
+
+ setreg(0x3c4,0,1); // assert synchronous reset
+
+ outportb(0x3c2,0x67);
+
+ for ( i = 0; i < 21; i++ ) updattr(i,attr3[i]);
+
+ setreg(0x3d4,0x11,0x20);
+ for ( i = 0; i < 32; i++ ) setreg(0x3d4,i,crtc3[i]);
+
+ for ( i = 0x00;i < 9; i++ ) setreg(0x3ce,i,graph3[i]);
+
+ for ( i = 0; i < 5; i++ ) setreg(0x3c4,i,seq3[i]);
+
+ set_ext_regs (0x3c4,eseq3);
+ set_ext_regs (0x3d4,ecrtc3);
+ set_ext_regs (0x3ce,egraph3);
+ set_ext_regs (0x3c0,eattr3);
+
+//
+// Load 8x16 font
+//
+
+ load8x16();
+
+//
+// Load color palette
+//
+
+ load_ramdac();
+
+ outportb(0x3c6,0xff);
+
+//
+// Reset Hidden color register
+//
+
+// inp(0x3c6);
+// inp(0x3c6);
+// inp(0x3c6);
+// inp(0x3c6);
+// outp(0x3c6,0x00);
+
+//
+// Screen blank
+//
+
+ clear_text();
+
+//
+// Initialize the current display column, row, and ownership values.
+//
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = COLS;
+ HalpDisplayText = ROWS;
+ HalpScrollLine = ONE_LINE;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+ HalpDisplayOwnedByHal = TRUE;
+ HalpScreenStart = 0;
+ return TRUE;
+}
+
+VOID HalpScrollCirrus(
+ IN UCHAR line
+ )
+{
+ ULONG LogicalTarget, PhysicalTarget;
+ int i;
+
+ for (i=0; i < line; i++) {
+
+ HalpScreenStart = HalpScreenStart + ONE_LINE;
+ setreg(0x3d4,0xC, (UCHAR) (HalpScreenStart >> 9));
+ setreg(0x3d4,0xD, (UCHAR) ((HalpScreenStart >> 1) & 0xFF));
+
+ for (LogicalTarget = TWENTY_FOUR_LINES;
+ LogicalTarget < TWENTY_FIVE_LINES;
+ LogicalTarget += 2) {
+ PhysicalTarget = LogicalTarget + HalpScreenStart + CIRRUS_TEXT_MEM;
+ WRITE_CIRRUS_VRAM(PhysicalTarget, ' ' );
+ WRITE_CIRRUS_VRAM(PhysicalTarget+1, TEXT_ATTR );
+ }
+ }
+}
+
+static void clear_text(VOID)
+{
+ unsigned long p;
+
+//
+// fill plane 0 and 1 with 0x20 and 0x1f
+//
+
+ for (p = CIRRUS_TEXT_MEM;
+ p < CIRRUS_TEXT_MEM+TWENTY_FIVE_LINES;
+ p += 2)
+ {
+ WRITE_CIRRUS_VRAM(p, ' ');
+ WRITE_CIRRUS_VRAM(p+1, TEXT_ATTR);
+ }
+}
+
+static void load8x16(VOID)
+{
+ int i, j;
+ PUCHAR address;
+
+//
+// load 8x16 font into plane 2
+//
+
+ setreg(0x3c4,0x04,(seq3[4] | 0x04));
+
+//
+// disable video and enable all to cpu to enable maximum video
+// memory access
+//
+
+ setreg(0x3c4,0x01,seq3[1] | 0x20);
+ setreg(0x3c4,2,4);
+
+ setreg(0x3ce,0x05,graph3[5] & 0xef);
+ setreg(0x3ce,0x06,0x05);
+
+
+//
+// fill plane 2 with 8x16 font
+
+ address = (void *) (CIRRUS_FONT_MEM);
+ for ( i = 0; i < 256; i++ )
+ {
+ for ( j = 0; j < 16; j++ )
+ {
+ WRITE_CIRRUS_VRAM(address,VGAFont8x16[i*16+j]);
+ address++;
+ }
+
+ for ( j = 16; j < 32; j++ )
+ {
+ WRITE_CIRRUS_VRAM(address,0);
+ address++;
+ }
+ }
+
+ setreg(0x3c4,0x01,seq3[1]);
+ setreg(0x3c4,0x04,seq3[4]);
+ setreg(0x3c4,2,seq3[2]);
+
+ setreg(0x3ce,0x06,graph3[6]);
+ setreg(0x3ce,0x05,graph3[5]);
+}
+
+
+static void load_ramdac()
+{
+ int ix,j;
+
+ for ( ix = 0,j = 0; j <= 0x0FF ; ix = ix+3,j++ )
+ {
+ outp(0x3c8,(unsigned char)j); // write ramdac index
+ outp(0x3c9,TextPalette[ix]); // write red
+ outp(0x3c9,TextPalette[ix+1]); // write green
+ outp(0x3c9,TextPalette[ix+2]); // write blue
+ }
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/pxenviro.c b/private/ntos/nthals/halfire/ppc/pxenviro.c
new file mode 100644
index 000000000..55c3677b3
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxenviro.c
@@ -0,0 +1,729 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxenviro.c $
+ * $Revision: 1.12 $
+ * $Date: 1996/05/18 00:28:50 $
+ * $Locker: $
+ */
+
+/***********************************************************************
+
+
+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.
+
+ File Name:
+ PXENVIRO.C
+
+ Purpose:
+ Provides the interface to the PowerPC ARC firmware.
+
+ Globals:
+ none
+
+ Functions:
+ ULONG HalGetEnvironmentVariable();
+ ULONG HalSetEnvironmentVariable();
+
+ History:
+ 27-Jul-1993 Steve Johns
+ Original version
+ 31-Jan-1994 Steve Johns
+ Added checksum logic
+ 08-Jul-1994 Steve Johns
+ Made Environment variable routines PReP compliant
+ 12-20-94
+ Heavly re-written by Sol Kavy at FirePower to
+ clean-up the code and properly suppor the Prep spec.
+
+
+NOTES:
+
+ The fields in the NVRAM structure follow Big-Endian byte ordering.
+
+ Each environment variable is stored as an zero-terminated ASCII string:
+
+ <name>=<value>,0
+
+***********************************************************************/
+
+
+#define USE_SPINLOCKS FALSE
+
+#include "halp.h"
+//#include "fpdebug.h"
+#include "arccodes.h"
+#include "eisa.h"
+#include "pxnvrsup.h"
+#include "fpnvram.h"
+
+USHORT HalpComputeCrc(VOID);
+
+//
+// Debug Define (first paramter is a place holder for future
+// level handling: 1 = Calls, 2 = Routine Info).
+//
+#define NDBG(_lvl, _print)
+
+PKSPIN_LOCK NVRAM_Spinlock;
+
+#define NVSIZE 4096
+
+//
+// Location of the NVRAM registers
+//
+// #include "phsystem.h"
+// extern PVOID HalpIoControlBase;
+#define NVRAM ((PNVRAM_CONTROL) (HalpIoControlBase))
+// #define NVRAM ((PNVRAM_CONTROL) 0xb1000000)
+
+//
+// Dummy pointer used to byte get offset information
+//
+PVOID NvramPtr=0;
+#define NVMAP ((PHEADER) NvramPtr)
+
+extern BOOLEAN NvramFailure;
+
+//
+// Use the routine from fpds1385.c to access the nvram chip. These
+// routines protect their accesses with the appropriate spin locks
+// to make sure the actions are atomic
+//
+
+USHORT
+HalpReadNvramUshort(USHORT Index)
+{
+ return (HalpDS1385ReadNVRAM(Index) << 8) +
+ HalpDS1385ReadNVRAM((USHORT)(Index+1));
+}
+
+
+ULONG
+HalpReadNvramUlong(USHORT Index)
+{
+ ULONG ReturnValue;
+
+ //
+ // Read Big-Endian ULONG value & convert to Little-Endian
+ //
+ ReturnValue = ((ULONG) HalpReadNvramUshort(Index) << 16) +
+ (ULONG) HalpReadNvramUshort((USHORT)(Index+2));
+
+ return ReturnValue;
+}
+
+VOID
+HalpWriteNvramUshort(USHORT Index,
+ USHORT Value)
+{
+ //
+ // Write USHORT value in Big-Endian
+ //
+ HalpDS1385WriteNVRAM(Index, (UCHAR) (Value >> 8));
+ HalpDS1385WriteNVRAM((USHORT)(Index+1),(UCHAR) Value);
+}
+
+
+VOID HalpWriteNvramUlong(
+ USHORT Index,
+ ULONG Value)
+{
+ //
+ // Write ULONG value in Big-Endian
+ //
+ HalpWriteNvramUshort(Index, (USHORT) (Value >> 16));
+ HalpWriteNvramUshort((USHORT)(Index+2),(USHORT) Value);
+}
+
+//
+// DumpNVRAM
+//
+// Description:
+// Used during bring-up to ensure that NVRAM is being handled
+// correctly. Nothing more than a bunch of DbgPrint of NVRAM
+//
+VOID
+DumpNVRAM()
+{
+ DbgPrint("HalpIoControlBase is at 0x%x\n", HalpIoControlBase);
+ DbgPrint("NVRAM is at 0x%x\n", NVRAM);
+ DbgPrint("NvramIndexLo is at 0x%x\n", &(NVRAM->NvramIndexLo));
+ DbgPrint("NvramIndexHi is at 0x%x\n", &(NVRAM->NvramIndexHi));
+ DbgPrint("NvramData is at 0x%x\n", &(NVRAM->NvramData));
+ DbgPrint("NVRAM USHORT Size(%d): %d\n",
+ (USHORT)&NVMAP->Size,
+ HalpReadNvramUshort((USHORT)&NVMAP->Size));
+ DbgPrint("NVRAM UCHAR Version(%d): %d\n",
+ (USHORT)&NVMAP->Version,
+ HalpDS1385ReadNVRAM((USHORT)&NVMAP->Version));
+ DbgPrint("NVRAM UCHAR Revision(%d): %d\n",
+ (USHORT)&NVMAP->Revision,
+ HalpDS1385ReadNVRAM((USHORT)&NVMAP->Revision));
+ DbgPrint("NVRAM USHORT Crc1(%d): 0x%x\n",
+ (USHORT)&NVMAP->Crc1,
+ HalpReadNvramUshort((USHORT)&NVMAP->Crc1));
+ DbgPrint("NVRAM USHORT Crc2(%d): 0x%x\n",
+ (USHORT)&NVMAP->Crc2,
+ HalpReadNvramUshort((USHORT)&NVMAP->Crc2));
+ DbgPrint("NVRAM UCHAR LastOS(%d): %d\n",
+ (USHORT)&NVMAP->LastOS,
+ HalpDS1385ReadNVRAM((USHORT)&NVMAP->LastOS));
+ DbgPrint("NVRAM UCHAR Endian(%d): %d\n",
+ (USHORT)&NVMAP->Endian,
+ HalpDS1385ReadNVRAM((USHORT)&NVMAP->Endian));
+ DbgPrint("NVRAM UCHAR OSAreaUsage(%d): %d\n",
+ (USHORT)&NVMAP->OSAreaUsage,
+ HalpDS1385ReadNVRAM((USHORT)&NVMAP->OSAreaUsage));
+ DbgPrint("NVRAM UCHAR PMMode(%d): %d\n",
+ (USHORT)&NVMAP->PMMode,
+ HalpDS1385ReadNVRAM((USHORT)&NVMAP->PMMode));
+ DbgPrint("NVRAM ULONG GEAddress(%d): %d\n",
+ (USHORT)&NVMAP->GEAddress,
+ HalpReadNvramUlong((USHORT)&NVMAP->GEAddress));
+ DbgPrint("NVRAM ULONG GELength(%d): %d\n",
+ (USHORT)&NVMAP->GELength,
+ HalpReadNvramUlong((USHORT)&NVMAP->GELength));
+ {
+ USHORT StartIndex, LastIndex, Index;
+ UCHAR NvramChar;
+ BOOLEAN LastNull = TRUE; // Assume it
+
+ DbgPrint("NVRAM Global Environment Area:\n");
+
+ StartIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GEAddress));
+ LastIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GELength));
+ LastIndex += StartIndex - 1;
+ for (Index = StartIndex; Index <= LastIndex; Index++) {
+ NvramChar = HalpDS1385ReadNVRAM(Index);
+ if (NvramChar == '\0') {
+ LastNull = TRUE;
+ } else {
+ if (LastNull == TRUE) {
+ DbgPrint("\n[%d]: ", Index);
+ }
+ DbgPrint("%c", NvramChar);
+ LastNull = FALSE;
+ }
+ }
+ DbgPrint("\n");
+ }
+
+ DbgPrint("Checking Our version of CRC");
+ DbgPrint("Compute CRC returns 0x%x\n", HalpComputeCrc());
+}
+
+UCHAR
+HalpGetEnvironmentInfo(
+ OPTIONAL PUSHORT TotalSize,
+ OPTIONAL PUSHORT FreeSize,
+ OPTIONAL PULONG pCrc)
+{
+ USHORT Index;
+ USHORT InUse, TotalLength;
+ UCHAR DataByte1, DataByte2;
+
+ NDBG(1, DbgPrint("HalpGetEnvironmentInfo: called\n"););
+
+ TotalLength = (USHORT) HalpReadNvramUlong((USHORT) &NVMAP->GELength);
+ if (TotalSize != NULL)
+ *TotalSize = TotalLength;
+
+ if (FreeSize != NULL) {
+ //
+ // Compute how much NVRAM is in use
+ //
+ InUse = 0;
+ Index = (USHORT)HalpReadNvramUlong ((USHORT) &NVMAP->GEAddress);
+ DataByte1 = HalpDS1385ReadNVRAM(Index++);
+ DataByte2 = DataByte1;
+ while (DataByte1 | DataByte2) {
+ DataByte1 = DataByte2;
+ DataByte2 = HalpDS1385ReadNVRAM(Index++);
+ InUse++;
+ }
+ *FreeSize = TotalLength - InUse;
+ }
+
+ if (pCrc != NULL) {
+ *pCrc = HalpReadNvramUshort((USHORT) &NVMAP->Crc1);
+ }
+ return(HalpDS1385ReadNVRAM((USHORT) &NVMAP->Version));
+}
+
+//
+// HalpAddByteCrc
+//
+// Description:
+// Use the X^16 + X^12 + X^5 + 1, Polynomial for CRC
+//
+// Input:
+// Stored in NVRAM
+//
+// Output:
+// New Crc Value
+//
+USHORT
+HalpAddByteCrc(USHORT CurrentCrc, USHORT Index)
+{
+ UCHAR Byte;
+ UCHAR CrcLo, CrcHi;
+ USHORT x,y,z;
+
+
+ Byte = HalpDS1385ReadNVRAM(Index);
+ CrcLo = CurrentCrc &0xff;
+ CrcHi = CurrentCrc >> 8;
+ x = (CrcLo << 8) | (CrcHi^Byte);
+ y = (CrcHi^Byte) << 8;
+ z = ((y >> 12) | (y << 4)) & 0xf00f;
+ x = x^z;
+ z = ((y << 13) | (y >> 3)) & 0x1fe0;
+ x = x^z;
+ z = y&0xf000;
+ x = x^z;
+ z = ((y<<9) | (y>>7)) & 0x1e0;
+ x = x^z;
+ return(x);
+}
+
+//
+// HalpComputeCrc
+//
+// Description:
+// Find the parts that are part of the crc and compute the
+// crc against them.
+//
+// Input:
+// Stored in NVRAM
+//
+// Output:
+//
+USHORT
+HalpComputeCrc(VOID)
+{
+ USHORT CurrentCrc = 0xffff;
+ USHORT Index, EndIndex;
+
+ //
+ // Loop through different parts computing CRC
+ // This is from Size to Revision inclusive
+ //
+ for (Index = 0; Index <= 3; Index++) {
+ CurrentCrc = HalpAddByteCrc(CurrentCrc, Index);
+ }
+
+ //
+ // Compute ending offset
+ //
+ EndIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->OSAreaAddress));
+
+ //
+ // Loop through second half
+ // This is from LastOS to OSArea (Note: 9 should be 8; however,
+ // IBM screwed up and we are all just going along with it).
+ //
+ for (Index = 9; Index < EndIndex; Index++) {
+ CurrentCrc = HalpAddByteCrc(CurrentCrc, Index);
+ }
+ return(CurrentCrc);
+}
+
+
+//
+// HalpUpdateCrc
+//
+// Description:
+// Compute the required Crc value and update the Header. This
+// code only updates crc1.
+//
+VOID
+HalpUpdateCrc()
+{
+ ULONG Crc;
+
+ NDBG(1, DbgPrint("HalpUpdateCrc: called\n"););
+ Crc = HalpComputeCrc();
+ HalpWriteNvramUshort((USHORT) &NVMAP->Crc1, (USHORT) Crc);
+}
+
+//
+// Returns the number of bytes removed
+//
+USHORT
+HalpCompressEnvironmentSpace(IN USHORT StartIndex)
+{
+ USHORT Index, BytesRemoved;
+ UCHAR PreviousChar, NvramChar;
+
+ Index = StartIndex+1;
+ while(HalpDS1385ReadNVRAM(Index++) != '=') {
+ /* Do Nothing */
+ }
+ while(HalpDS1385ReadNVRAM(Index++) != 0) {
+ /* Do Nothing */
+ }
+ BytesRemoved = Index - StartIndex; // Adjust amount of free space
+
+ NvramChar = 0;
+ //
+ // Copy subsequent variables
+ //
+ do {
+ PreviousChar = NvramChar;
+ NvramChar = HalpDS1385ReadNVRAM(Index++);
+ HalpDS1385WriteNVRAM(StartIndex++, NvramChar);
+ } while (PreviousChar | NvramChar);
+
+ //
+ // Make sure unused NVRAM area is zeroed
+ //
+ for (Index=0; Index <BytesRemoved; Index++) {
+ if (Index+StartIndex >= NVSIZE) {
+ break;
+ }
+ HalpDS1385WriteNVRAM((USHORT)(Index+StartIndex), 0);
+ }
+ return(BytesRemoved);
+}
+
+//
+//HalpFindEnviroVar
+// Description:
+// Searches the NVRAM for an environment variable.
+//
+// Parameters:
+// Variable - ptr to the variable to search for.
+//
+// Return value:
+// The NVRAM index where the environment variable's VALUE is stored.
+// Returns 0 if the variable was not found.
+//
+// Assumes NVRAM_Spinlock has already been acquired by the caller.
+//
+USHORT
+HalpFindEnviroVar(IN CHAR *Variable)
+{
+ USHORT Index, StartIndex, LastIndex;
+ CHAR *VariablePtr, UserChar, NvramChar;
+
+ NDBG(1, DbgPrint("HalpFindEnviroVar: called for %s\n", Variable););
+
+ StartIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GEAddress));
+ LastIndex = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GELength));
+ LastIndex += StartIndex - 1;
+
+
+ //
+ // Search the NVRAM for the variable.
+ //
+ VariablePtr = Variable;
+ for (Index = StartIndex ; Index <= LastIndex; ) {
+ //
+ // Get a character from the NVRAM
+ //
+ NvramChar = HalpDS1385ReadNVRAM(Index++);
+ if (NvramChar == 0) {
+ break;
+ }
+
+ //
+ // Are we at the end of the variable name in both the
+ // input string and the NVRAM ?
+ // If so, then it is an exact match. Return the NVRAM index.
+ //
+ UserChar = *VariablePtr++;
+ if (UserChar == 0 && NvramChar == '=') {
+ NDBG(2, DbgPrint("HalpFindEnviroVar: found %s at %d\n",
+ Variable, Index););
+ return(Index);
+ }
+
+ //
+ // Convert variable to UPPER case
+ //
+ UserChar = (UserChar >= 'a' && UserChar <= 'z') ?
+ UserChar-0x20 : UserChar;
+
+ //
+ // Is there a match on this character ?
+ //
+
+ if (UserChar != NvramChar) {
+ //
+ // No, then skip over this variable in NVRAM and begin
+ // search again at start of variable NAME.
+ //
+ VariablePtr = Variable;
+ while (Index <= LastIndex) {
+ NvramChar = HalpDS1385ReadNVRAM(Index++);
+ if (NvramChar == '=')
+ break;
+ }
+ while (Index <= LastIndex) {
+ NvramChar = HalpDS1385ReadNVRAM(Index++);
+ if (NvramChar == 0) {
+ break;
+ }
+ }
+ }
+ }
+
+ //
+ // The variable was not found
+ //
+ NDBG(2, DbgPrint("HalpFindEnviroVar: %s not found\n", Variable););
+ return(0);
+}
+
+//
+// HalGetEnvironmentVariable
+//
+// Parameters:
+//
+// Variables:
+// Supplies a pointer to the zero-terminated, case ASCII string that contains
+// the name of the environment variable to be returned.
+// Length - Supplies the length of the buffer in bytes.
+// Buffer - Supplies a pointer to a buffer that receives the variable value.
+//
+// Return Value:
+// If the variable, the function returns the value ESUCCESS and its
+// value in Buffer. Otherwise, ENOENT is returned.
+//
+ULONG
+HalGetEnvironmentVariable(IN CHAR *Variable,
+ IN USHORT Length,
+ OUT CHAR *Buffer)
+{
+ USHORT Index;
+ static DumpNVRAMOnce = FALSE;
+ ULONG retVal = ENOENT
+
+
+ NDBG(1, DbgPrint("HalpGetEnvironmentVariable: called\n"););
+
+ //
+ // Check input parameters
+ //
+ if (!Variable) {
+ if (*Variable == 0 || Length < 1 || Buffer == NULL) {
+ NDBG(2, DbgPrint("HalpGetEnvironmentVariable: return ENOENT\n"););
+ return(retVal);
+ }
+ }
+
+ if (!DumpNVRAMOnce) {
+ NDBG(2, DumpNVRAM(););
+ DumpNVRAMOnce = TRUE;
+ }
+
+ //
+ // Grab control of NVRAM
+ //
+#if USE_SPINLOCKS
+ KIRQL Irql;
+ KeAcquireSpinLock(NVRAM_Spinlock, &Irql);
+#endif
+ NvramFailure = FALSE;
+
+ //
+ // Get NVRAM index of environment variable
+ //
+ Index = HalpFindEnviroVar(Variable);
+ if (Index == 0) {
+ //
+ // Environment variable was not found
+ //
+#if USE_SPINLOCKS
+ KeReleaseSpinLock(NVRAM_Spinlock, Irql);
+#endif
+ return(retVal);
+ }
+
+ //
+ // Copy the environment variable's value to Buffer
+ //
+ do {
+ *Buffer = HalpDS1385ReadNVRAM(Index++);
+ if (*Buffer++ == 0) {
+ if (NvramFailure == TRUE) {
+ retVal = ENOMEM;
+ } else {
+ retVal = ESUCCESS;
+ }
+#if USE_SPINLOCKS
+ KeReleaseSpinLock(NVRAM_Spinlock, Irql);
+#endif
+ return(retVal);
+ }
+ } while (--Length);
+
+ //
+ // Truncate the returned string. The buffer was too short.
+ //
+ *--Buffer = 0;
+#if USE_SPINLOCKS
+ KeReleaseSpinLock(NVRAM_Spinlock, Irql);
+#endif
+ return(ENOMEM);
+}
+
+//
+// HalSetEnvironmentVariable
+//
+// Parameters:
+// Variable
+// Supplies a pointer to the zero-terminated ASCII string that contains
+// the name of the environment variable to be returned. The string is
+// converted to UPPER CASE.
+//
+// Value
+// Supplies a pointer to the zero-terminated string that contains the new
+// value of the environment variable.
+//
+// There are 4 cases:
+// 1) The environment variable is deleted if Value is a null string.
+// 2) The environment variable does not currently exist. It is appended
+// if there is enough NVRAM available.
+// 3) The environment variable already exists, and the new Value is
+// shorter than the old value.
+// 4) The environment variable already exists, and the new Value is longer than
+// the old value.
+//
+// In all cases the environment space will be compressed after
+// insertion/deletion.
+//
+ULONG
+HalSetEnvironmentVariable(
+ IN CHAR *Variable,
+ IN CHAR *Value)
+{
+ USHORT TotalSize, FreeSize, Index;
+ USHORT OldLength, NewLength;
+ USHORT StartIndex;
+ USHORT i;
+ USHORT NameLength, ValueLength;
+ CHAR *VariablePtr, *ValuePtr, Char;
+ ARC_STATUS ReturnValue;
+
+
+ NDBG(1, DbgPrint("HalSetEnvironmentVariable: called set %s to %s\n",
+ Variable, Value););
+
+ if (Value == NULL) {
+ NDBG(2, DbgPrint("HalSetEnvironmentVariable: returning ENOENT\n"););
+ return(ENOENT);
+ }
+
+ //
+ // Compute length of environment NAME
+ //
+ VariablePtr = Variable;
+ NameLength = 0;
+ while (*VariablePtr != 0) {
+ NameLength++;
+ VariablePtr++;
+ }
+
+ //
+ // Compute length of environment VALUE
+ //
+ ValuePtr = Value;
+ ValueLength = 0;
+ while (*ValuePtr != 0) {
+ ValueLength++;
+ ValuePtr++;
+ }
+#if USE_SPINLOCKS
+ KIRQL Irql;
+ KeAcquireSpinLock(NVRAM_Spinlock, &Irql); // Grab control of NVRAM
+#endif
+ NvramFailure = FALSE;
+
+ HalpGetEnvironmentInfo(&TotalSize, &FreeSize, NULL);
+
+
+ // Get index of environment variable
+ Index = HalpFindEnviroVar(Variable);
+
+ ReturnValue = ESUCCESS;
+ // Index to start of NAME
+ StartIndex = Index-NameLength-1;
+
+ // DELETE environment variable
+ if (ValueLength == 0) {
+ if (Index != 0) {
+ HalpCompressEnvironmentSpace(StartIndex);
+ }
+ } else {
+ // ADD or REPLACE environment variable
+ // Compute # bytes needed to store variable
+ NewLength = ValueLength + NameLength + 2;
+
+
+ // REPLACE environment variable.
+ // First we see if there is room. If so, delete the current
+ // variable & fall through to the code that ADDs a new variable.
+ if (Index != 0) {
+ // Compute current length of variable
+ OldLength = 0;
+ i = Index;
+ do {
+ OldLength++;
+ } while (HalpDS1385ReadNVRAM(i++) != 0);
+
+ // Is there room for the new variable ?
+ if (FreeSize-NewLength+OldLength >= 0)
+ FreeSize += HalpCompressEnvironmentSpace(StartIndex);
+ }
+ //
+ // ADD environment variable
+ //
+
+ if ((FreeSize-NewLength) >= 0) { // Room for new
+
+ Index = (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GEAddress));
+ Index += (USHORT) HalpReadNvramUlong((USHORT) (&NVMAP->GELength));
+ Index -= FreeSize;
+
+ //
+ // Write Variable NVRAM. Convert to UPPER case first.
+ //
+ while (*Variable != 0) {
+ Char = *Variable++;
+ //
+ // Convert Variable to UPPER case
+ //
+ Char = (Char >= 'a' && Char <= 'z') ? Char-0x20 : Char;
+ HalpDS1385WriteNVRAM(Index++,Char);
+ }
+
+ HalpDS1385WriteNVRAM(Index++,'='); // Write a "="
+
+ do {
+ // Write VALUE to NVRAM
+ HalpDS1385WriteNVRAM(Index++,*Value);
+ } while (*Value++ != 0);
+
+ ReturnValue = ESUCCESS;
+ }
+ }
+
+ //
+ // Update NVRAM checksum
+ //
+ HalpUpdateCrc();
+ if (NvramFailure == TRUE) {
+ ReturnValue = ENOMEM;
+ }
+#if USE_SPINLOCKS
+ KeReleaseSpinLock(NVRAM_Spinlock, Irql);
+#endif
+ return(ReturnValue);
+}
+
+
diff --git a/private/ntos/nthals/halfire/ppc/pxflshbf.s b/private/ntos/nthals/halfire/ppc/pxflshbf.s
new file mode 100644
index 000000000..c4cdad4fd
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxflshbf.s
@@ -0,0 +1,159 @@
+#if defined(_PPC_)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991 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:
+//
+// pxflshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a Power PC
+// system.
+//
+//
+//
+// Author:
+//
+// David N. Cutler (davec) 24-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+//
+// Used PowerPC eieio instruction to flush writes
+//
+//--
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxflshbf.s $
+ * $Revision: 1.7 $
+ * $Date: 1996/05/14 02:34:14 $
+ * $Locker: $
+ */
+
+#include "kxppc.h"
+
+// SBTTL("Flush Write Buffer")
+//
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ eieio
+
+
+ LEAF_EXIT(KeFlushWriteBuffer)
+
+
+
+//
+//++
+//
+// NTSTATUS
+// HalpSynchronizeExecution()
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSynchronizeExecution)
+
+ sync // synchronize
+
+ LEAF_EXIT(HalpSynchronizeExecution)
+
+
+//
+//++
+//
+// NTSTATUS
+// HalpGetProcessorVersion()
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function gets the processor version of the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpGetProcessorVersion)
+
+ mfpvr r.3 // get processor version
+
+ LEAF_EXIT(HalpGetProcessorVersion)
+
+//
+//++
+//
+// VOID
+// SetSDR1(
+// ULONG HashedPageTableBase,
+// ULONG HashedPageTableSize
+// )
+//
+
+ LEAF_ENTRY(SetSDR1)
+
+ subi r.4,r.4,1
+ rlwimi r.3,r.4,16,0x1ff
+ mtsdr1 r.3
+
+ LEAF_EXIT(SetSDR1)
+
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/pxflshio.c b/private/ntos/nthals/halfire/ppc/pxflshio.c
new file mode 100644
index 000000000..c73638505
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxflshio.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxflshio.c $
+ * $Revision: 1.11 $
+ * $Date: 1996/05/14 02:34:19 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+ Copyright 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:
+
+ psflshio.c
+
+Abstract:
+
+ This module implements miscellaneous PowerPC HAL functions.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.ibm.com)
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+
+
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return 1;
+}
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Length;
+ ULONG PartialLength;
+ ULONG Offset;
+ PULONG Page;
+ BOOLEAN DoDcache = FALSE;
+
+ //
+ // check for 601, it has a combined I and D cache that bus snoops
+ //
+ //
+
+ if ((HalpGetProcessorVersion() >> 16) != 1) {
+
+ Length = Mdl->ByteCount;
+
+ if ( !Length ) {
+ return;
+ }
+ //
+ // If the I/O operation is not a DMA operation,
+ // and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the data cache.
+ //
+ if (((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ DoDcache = TRUE;
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the range from the cache. Note it is not reasonable to sweep
+ // the entire cache on an MP system as "Flash Invalidate" doesn't
+ // broadcast the invalidate to other processors.
+ //
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+
+ Offset = Mdl->ByteOffset;
+ PartialLength = PAGE_SIZE - Offset;
+ if (PartialLength > Length) {
+ PartialLength = Length;
+ }
+
+ Page = (PULONG)(Mdl + 1);
+
+ if (DoDcache == TRUE) {
+ HalpSweepPhysicalRangeInBothCaches(
+ *Page++,
+ Offset,
+ PartialLength
+ );
+ Length -= PartialLength;
+ if (Length) {
+ PartialLength = PAGE_SIZE;
+ do {
+ if (PartialLength > Length) {
+ PartialLength = Length;
+ }
+ HalpSweepPhysicalRangeInBothCaches(
+ *Page++,
+ 0,
+ PartialLength
+ );
+ Length -= PartialLength;
+ } while (Length != 0);
+ }
+ } else {
+ HalpSweepPhysicalIcacheRange(
+ *Page++,
+ Offset,
+ PartialLength
+ );
+ Length -= PartialLength;
+ if (Length) {
+ PartialLength = PAGE_SIZE;
+ do {
+ if (PartialLength > Length) {
+ PartialLength = Length;
+ }
+ HalpSweepPhysicalIcacheRange(
+ *Page++,
+ 0,
+ PartialLength
+ );
+ Length -= PartialLength;
+ } while (Length != 0);
+ }
+ }
+ }
+ }
+ return;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxhalp.h b/private/ntos/nthals/halfire/ppc/pxhalp.h
new file mode 100644
index 000000000..ee880dedf
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxhalp.h
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxhalp.h $
+ * $Revision: 1.15 $
+ * $Date: 1996/05/15 00:06:21 $
+ * $Locker: $
+ */
+
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ PowerPC specific interfaces, defines and structures.
+
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Added externs for HalpInterruptBase,HalpPciConfigBase
+ Added extern for HalpIoControlBase
+ Added prototype for HalpHandleDecrementerInterrupt (was in halp.h)
+ changed adapter object structure to be compatible with the intel HAL
+
+--*/
+
+#ifndef _PXHALP_
+#define _PXHALP_
+
+
+//
+// Define global data used to locate the IO control space, the interrupt
+// acknowlege, and the Pci config base.
+//
+
+extern PVOID HalpIoControlBase;
+extern PVOID HalpIoMemoryBase;
+extern PVOID HalpInterruptBase;
+extern PVOID HalpPciConfigBase;
+extern PVOID HalpErrorAddressRegister;
+extern PVOID HalpPciIsaBridgeConfigBase;
+
+//
+// prototype x86 emulator
+//
+
+extern BOOLEAN HalpInitX86Emulator(VOID);
+
+//
+// Define adapter object structure.
+//
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0x40000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0x30000
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_ISA_MAP_REGISTER 16
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+//
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000
+
+//
+// Define the scatter/gather flag for the Map Register Base.
+//
+
+#define NO_SCATTER_GATHER 0x00000001
+
+//
+// Define the copy buffer flag for the index.
+//
+
+#define COPY_BUFFER 0XFFFFFFFF
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+ BOOLEAN IsaBusMaster;
+ INTERFACE_TYPE InterfaceType; // spec what bus this adapter is on
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ OUT PULONG NumberOfMapRegisters
+ );
+
+BOOLEAN
+HalpCreateSioStructures(
+ VOID
+ );
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpHandleExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpFieldExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpHandleDecrementerInterrupt (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpAllocateMapBuffer(
+ VOID
+ );
+
+ULONG
+HalpUpdateDecrementer(
+ ULONG
+ );
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace(
+ VOID
+ );
+
+VOID
+HalpPhase0UnMapBusConfigSpace(
+ VOID
+ );
+
+ULONG
+HalpPhase0GetPciDataByOffset(
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+ULONG
+HalpPhase0SetPciDataByOffset(
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+PVOID
+KePhase0MapIo(
+ IN PVOID PhysicalMemoryBase,
+ IN ULONG MemorySize
+ );
+
+VOID
+KePhase0DeleteIoMap(
+ IN PVOID PhysicalMemoryBase,
+ IN ULONG MemorySize
+ );
+
+ULONG
+HalpCalibrateTB(
+ VOID
+ );
+
+VOID
+HalpZeroPerformanceCounter(
+ VOID
+ );
+
+VOID
+HalpResetIrqlAfterInterrupt(
+ KIRQL TargetIrql
+ );
+
+VOID
+HalpLockDisplayString(
+ PVOID
+ );
+BOOLEAN
+HalpCacheSweepSetup(
+ VOID
+ );
+
+VOID
+HalpSweepPhysicalRangeInBothCaches(
+ ULONG Page,
+ ULONG Offset,
+ ULONG Length
+ );
+VOID
+HalpSweepPhysicalIcacheRange(
+ ULONG Page,
+ ULONG Offset,
+ ULONG Length
+ );
+#endif // _PXHALP_
diff --git a/private/ntos/nthals/halfire/ppc/pxhwsup.c b/private/ntos/nthals/halfire/ppc/pxhwsup.c
new file mode 100644
index 000000000..a96e4ff23
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxhwsup.c
@@ -0,0 +1,2212 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxhwsup.c $
+ * $Revision: 1.12 $
+ * $Date: 1996/05/14 02:34:25 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1990-1993 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:
+
+ pxhwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Jeff Havens (jhavens) 14-Feb-1990
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC Port
+ Remove support for internal bus and devices
+ Changed HalFreeCommonBuffer to support S-FOOT address inversion
+ Added PCI, PCMCIA, and ISA bus support
+ Removed support for internal DMA controller
+ Change HalTranslateBusAddress to support S-FOOTS memory map
+ Deleted HalpReadEisaBus - this code was specific to EISA buses
+ Changed IoMapTransfer to support S-FOOT address inversion
+ Added support for guaranteed contigous common buffers
+
+
+
+--*/
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+#include "phsystem.h"
+
+#include "pxmemctl.h"
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+//
+// Define map buffer variables
+//
+
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+ULONG HalpMapBufferSize;
+
+
+
+//
+// The DMA controller has a larger number of map registers which may be used
+// by any adapter channel. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+BOOLEAN
+HalpGrowMapBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Amount
+ );
+
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+
+/*++
+
+Routine Description: NTSTATUS HalAllocateAdapterChannel()
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = (ULONG)-1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+ else
+ {
+ HalpPrint("KeInsertDeviceQueue: branch not taken \n");
+ }
+return(STATUS_SUCCESS);
+
+}
+
+/*++
+
+Routine Description: PVOID HalAllocateCommonBuffer()
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+{
+ PVOID virtualAddress;
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Allocate the actual buffer.
+ //
+
+
+ physicalAddress.LowPart = 0xFFFFFFFF;
+ physicalAddress.HighPart = 0;
+
+ virtualAddress = MmAllocateContiguousMemory(
+ Length,
+ physicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+ return(NULL);
+ }
+
+
+
+
+ //
+ // Memory space inverion
+ //
+
+
+
+ *LogicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ if (!AdapterObject->IsaBusMaster) {
+ LogicalAddress->LowPart |= IO_CONTROL_PHYSICAL_BASE;
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+/*++
+
+Routine Description: PVOID HalAllocateCrashDumpRegisters()
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested. If not all of
+ the registers could be allocated this field is updated to show how
+ many were.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+/*++
+
+Routine Description: BOOLEAN HalFlushCommonBuffer()
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+{
+
+ return(TRUE);
+
+}
+
+/*++
+
+Routine Description: VOID HalFreeCommonBuffer()
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+{
+
+
+ UNREFERENCED_PARAMETER( AdapterObject );
+ UNREFERENCED_PARAMETER( Length );
+ UNREFERENCED_PARAMETER( LogicalAddress );
+ UNREFERENCED_PARAMETER( CacheEnabled );
+
+ MmFreeContiguousMemory (VirtualAddress);
+
+ return;
+
+}
+
+/*++
+
+Routine Description: PADAPTER_OBJECT HalGetAdapter()
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Three bus types are supported for the
+ system: PCI, Isa.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+{
+ PADAPTER_OBJECT adapterObject;
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) {
+
+ return(NULL);
+
+ }
+
+
+ //
+ // If the request is for a unsupported bus then return NULL.
+ //
+
+
+ if (DeviceDescription->InterfaceType != Isa &&
+ DeviceDescription->InterfaceType != PCIBus &&
+ DeviceDescription->InterfaceType != PCMCIABus) {
+
+ //
+ // This bus type is unsupported return NULL.
+ //
+
+ return(NULL);
+ }
+
+ //
+ // Create an adapter object.
+ //
+
+ adapterObject = HalpAllocateIsaAdapter( DeviceDescription,
+ NumberOfMapRegisters);
+ return(adapterObject);
+}
+
+
+/*++
+
+Routine Description: PADAPTER_OBJECT HalpAllocateAdapter()
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ phyically contiguous memory pages.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != NULL ) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ NULL,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == NULL) {
+
+ //
+ // Allocate a bit map large enough MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+ AdapterObject->PagePort = NULL;
+ AdapterObject->IsaBusMaster = FALSE;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == NULL ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE )
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+ return AdapterObject;
+
+}
+
+/*++
+
+Routine Description: VOID IoFreeMapRegisters()
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+
+/*++
+
+Routine Description: VOID IoFreeAdapterChannel()
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0
+ );
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+
+/*++
+
+Routine Description: PHYSICAL_ADDRESS IoMapTransfer()
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+{
+
+ ULONG pageOffset;
+ ULONG index;
+ ULONG transferLength;
+ PULONG pageFrame;
+ ULONG logicalAddress;
+ PTRANSLATION_ENTRY translationEntry;
+ BOOLEAN useBuffer;
+ PHYSICAL_ADDRESS returnAddress;
+
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how much of the transfer is contiguous.
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = ((*pageFrame << PAGE_SHIFT) + pageOffset) | IO_CONTROL_PHYSICAL_BASE;
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+
+ }
+
+
+ //
+ // Limit the transferLength to the requested Length.
+ //
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ if (MapRegisterBase != NULL) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+// #pragma message(REVIEW "No Scatter Gather currently: Fix it soon?")
+// #pragma NOTE("No Scatter Gather currently: Fix it soon?")
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length) {
+
+ //
+ // do the memory inversion on the logical address
+ //
+
+ logicalAddress = ( translationEntry->PhysicalAddress + pageOffset)
+ | IO_CONTROL_PHYSICAL_BASE;
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ transferLength = *Length;
+ useBuffer = TRUE;
+
+ } else {
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ useBuffer = FALSE;
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+ }
+
+ //
+ // ISA masters require memory to be at less than 16 MB.
+ // always use map buffers for ISA busmasters
+ //
+
+ if (((logicalAddress+transferLength) & ~IO_CONTROL_PHYSICAL_BASE)
+ >= MAXIMUM_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress +
+ pageOffset | IO_CONTROL_PHYSICAL_BASE;
+
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ if (AdapterObject != NULL) {
+ if (AdapterObject->IsaBusMaster == TRUE) {
+ returnAddress.LowPart = logicalAddress & ~IO_CONTROL_PHYSICAL_BASE;
+ }
+ else {
+ returnAddress.LowPart = logicalAddress;
+ }
+ }
+ else {
+ returnAddress.LowPart = logicalAddress;
+ }
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ } else {
+
+
+ HalpIsaMapTransfer(
+ AdapterObject,
+ logicalAddress,
+ *Length,
+ WriteToDevice
+ );
+ }
+
+
+ return(returnAddress);
+}
+
+
+/*++
+
+Routine Description: BOOLEAN IoFlushAdapterBuffers()
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+{
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ if (MapRegisterBase == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ if (translationEntry->Index == COPY_BUFFER) {
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice
+ );
+
+ }
+
+ } else {
+
+ //
+ // Cycle through the pages of the transfer to determine if there
+ // are any which need to be copied back.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength && *pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+ }
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description: IO_ALLOCATION_ACTION HalpAllocationRoutine ()
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+
+/*++
+
+Routine Description: BOOLEAN HalpHandleMachineCheck()
+
+ This function is called when a PPC Machine Check interrupt occurs.
+ It print the appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Unused
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+{
+ KIRQL OldIrql;
+ //
+ // raise irql to machine check level
+ //
+
+ KeRaiseIrql(MACHINE_CHECK_LEVEL,&OldIrql);
+
+ //
+ // check memory controller machine check sources
+ //
+
+ // do not call this function now.
+ //
+ // HalpHandleMemoryError();
+ //
+ // check Bus NMI sources
+ //
+
+ HalpHandleIoError();
+
+ //
+ // Bug check
+ //
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+ KeLowerIrql(OldIrql);
+
+ return(TRUE);
+}
+
+
+
+/*++
+
+Routine Description: BOOLEAN HalpAllocateMapBuffer()
+
+ This routine allocates the required map buffers.
+
+
+Arguments:
+
+
+Return Value:
+
+ TRUE - success
+ FALSE - failure
+
+--*/
+
+BOOLEAN
+HalpAllocateMapBuffer(
+ VOID
+ )
+{
+
+ PVOID virtualAddress;
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ HalpMapBufferPhysicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS;
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+ virtualAddress = MmAllocateContiguousMemory(
+ HalpMapBufferSize,
+ HalpMapBufferPhysicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ return FALSE;
+
+ }
+
+ HalpMapBufferPhysicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description: VOID HalpCopyBufferMap()
+
+ This routine copies the speicific data between the user's buffer and the
+ map register buffer. First a the user buffer is mapped if necessary, then
+ the data is copied. Finally the user buffer will be unmapped if
+ neccessary.
+
+Arguments:
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ TranslationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+{
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+
+ mapAddress = (PCCHAR) TranslationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Copy the data between the user buffer and map buffer
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, bufferAddress, Length);
+
+ } else {
+
+ RtlMoveMemory(bufferAddress, mapAddress, Length);
+
+ }
+
+}
+/*++
+
+Routine Description: BOOLEAN HalpGrowMapBuffers()
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ ULONG NumberOfPages;
+
+ LONG i;
+ KIRQL Irql;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the addition pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocatation amount to so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+
+ }
+
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocationg a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ TRUE // Cache enable.
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+ }
+
+ } else {
+
+ //
+ // Allocate the map buffers.
+ //
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS - 1;
+ physicalAddress.HighPart = 0;
+ MapBufferVirtualAddress = MmAllocateContiguousMemory(
+ NumberOfPages * PAGE_SIZE,
+ physicalAddress
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ MapBufferPhysicalAddress = MmGetPhysicalAddress(
+ MapBufferVirtualAddress
+ ).LowPart;
+
+ }
+
+ //
+ // Initailize the map registers where memory has been allocated.
+ //
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; (ULONG) i < NumberOfPages; i++) {
+
+ //
+ // Make sure the perivous entry is physically contiguous with the next
+ // entry and that a 64K physical bountry is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress ||
+ (((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this bountry.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxidaho.h b/private/ntos/nthals/halfire/ppc/pxidaho.h
new file mode 100644
index 000000000..19ba01f69
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxidaho.h
@@ -0,0 +1,149 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxidaho.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ for an Idaho memory controller.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxidaho.h $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:10:40 $
+ * $Locker: $
+ */
+
+
+//
+// define structures for the idaho memory controller
+//
+
+
+
+typedef struct _IDAHO_CONTROL {
+ UCHAR Reserved1[0x808]; // Offset 0x000
+ UCHAR HardfileLight; // Offset 0x808
+ UCHAR Reserved2[3];
+ UCHAR EquiptmentPresent; // Offset 0x80C
+ UCHAR Reserved3[3];
+ UCHAR PasswordProtect1; // Offset 0x810
+ UCHAR Reserved4;
+ UCHAR PasswordProtect2; // Offset 0x812
+ UCHAR Reserved5;
+ UCHAR L2Flush; // Offset 0x814
+ UCHAR Reserved6[7];
+ UCHAR SystemControl; // Offset 0x81c
+ UCHAR Reserved9[0x1B];
+ UCHAR Eoi9; // Offset 0x838
+ UCHAR PciInterruptMap1; // Offset 0x839
+ UCHAR Reserved10[2];
+ UCHAR Eoi11; // Offset 0x83C
+ UCHAR PciInterruptMap2; // Offset 0x83D
+ UCHAR AudioSupport; // Offset 0x83E
+ UCHAR Reserved11[0x14];
+ UCHAR Reserved12[0x2C];
+ UCHAR MemorySimmId1; // Offset 0x880
+ UCHAR Reserved13[3];
+ UCHAR MemorySimmId2; // Offset 0x884
+ UCHAR Reserved14[3];
+ UCHAR MemorySimmId3; // Offset 0x888
+ UCHAR Reserved15[3];
+ UCHAR MemorySimmId4; // Offset 0x88C
+ UCHAR Reserved16[0x46B];
+ ULONG ConfigAddress; // Offset 0xcf8
+ ULONG ConfigData; // Offset 0xcfc
+} IDAHO_CONTROL, *PIDAHO_CONTROL;
+
+typedef struct _IDAHO_CONFIG {
+
+ UCHAR VendorId[2]; // Offset 0x00 read-only
+ UCHAR DeviceId[2]; // Offset 0x02 read-only
+ UCHAR Command[2]; // Offset 0x04 unused
+ UCHAR DeviceStatus[2]; // Offset 0x06
+ UCHAR RevisionId; // Offset 0x08 read-only
+ UCHAR Reserved1; // Offset 0x09
+ UCHAR SubclassCode; // Offset 0x0A
+ UCHAR ClassCode; // Offset 0x0B
+ UCHAR Reserved2; // Offset 0x0C
+ UCHAR Reserved3; // Offset 0x0D
+ UCHAR HeaderType; // Offset 0x0E
+ UCHAR BistControl; // Offset 0x0F
+ UCHAR Reserved4[0x2C];
+ UCHAR InterruptLine; // Offset 0x3C
+ UCHAR InterruptPin; // Offset 0x3D
+ UCHAR MinGnt; // Offset 0x3E
+ UCHAR MaxGnt; // Offset 0x3F
+ UCHAR BridgeNumber; // Offset 0x40
+ UCHAR SubordBusNumber; // Offset 0x41
+ UCHAR DisconnectCounter; // Offset 0x42
+ UCHAR ReservedAnger;
+ UCHAR SpecialCycleAddress[2]; // Offset 0x44
+ UCHAR Reserved5[0x3A];
+ UCHAR StartingAddress1; // Offset 0x80
+ UCHAR StartingAddress2; // Offset 0x81
+ UCHAR StartingAddress3; // Offset 0x82
+ UCHAR StartingAddress4; // Offset 0x83
+ UCHAR StartingAddress5; // Offset 0x84
+ UCHAR StartingAddress6; // Offset 0x85
+ UCHAR StartingAddress7; // Offset 0x86
+ UCHAR StartingAddress8; // Offset 0x87
+ UCHAR Reserved6[8];
+ UCHAR EndingAddress1; // Offset 0x90
+ UCHAR EndingAddress2; // Offset 0x91
+ UCHAR EndingAddress3; // Offset 0x92
+ UCHAR EndingAddress4; // Offset 0x93
+ UCHAR EndingAddress5; // Offset 0x94
+ UCHAR EndingAddress6; // Offset 0x95
+ UCHAR EndingAddress7; // Offset 0x96
+ UCHAR EndingAddress8; // Offset 0x97
+ UCHAR Reserved7[8];
+ UCHAR MemoryBankEnable; // Offset 0xA0
+ UCHAR MemoryTiming1; // Offset 0xA1
+ UCHAR MemoryTiming2; // Offset 0xA2
+ UCHAR Reserved8;
+ UCHAR SimmBank1; // Offset 0xA4
+ UCHAR SimmBank2; // Offset 0xA5
+ UCHAR SimmBank3; // Offset 0xA6
+ UCHAR SimmBank4; // Offset 0xA7
+ UCHAR Reserved9[9];
+ UCHAR L2CacheStatus; // Offset 0xB1
+ UCHAR Reserved10[2];
+ UCHAR RefreshCycle; // Offset 0xB4
+ UCHAR RefreshTimer; // Offset 0xB5
+ UCHAR WatchdogTimer; // Offset 0xB6
+ UCHAR BusTimer; // Offset 0xB7
+ UCHAR LocalBusTimer; // Offset 0xB8
+ UCHAR LocalBusIdleTimer; // Offset 0xB9
+ UCHAR Options1; // Offset 0xBA
+ UCHAR Options2; // Offset 0xBB
+ UCHAR Reserved11[4];
+ UCHAR EnableDetection1; // Offset 0xC0
+ UCHAR ErrorDetection1; // Offset 0xC1
+ UCHAR ErrorSimulation1; // Offset 0xC2
+ UCHAR CpuBusErrorStatus; // Offset 0xC3
+ UCHAR EnableDetection2; // Offset 0xC4
+ UCHAR ErrorDetection2; // Offset 0xC5
+ UCHAR ErrorSimulation2; // Offset 0xC6
+ UCHAR PciBusErrorStatus; // Offset 0xC7
+ UCHAR ErrorAddress[4]; // Offset 0xC8
+} IDAHO_CONFIG, *PIDAHO_CONFIG;
+
diff --git a/private/ntos/nthals/halfire/ppc/pxidle.c b/private/ntos/nthals/halfire/ppc/pxidle.c
new file mode 100644
index 000000000..51f1059ef
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxidle.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxidle.c $
+ * $Revision: 1.9 $
+ * $Date: 1996/01/11 07:10:47 $
+ * $Locker: $
+ */
+
+/*++
+TITLE("Processor Idle")
+
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ pxidle.c
+
+abstract:
+
+ This module implements system platform dependent power management
+ support.
+
+Author:
+
+ Jim Wooldridge
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "phsystem.h"
+#include "fpcpu.h"
+ULONG HalpGetStack( VOID );
+extern ULONG registeredInts[];
+
+/*++
+
+ Routine Description: VOID HalProcessorIdle( VOID )
+
+
+ This function is called when the current processor is idle with
+ interrupts disabled. There is no thread active and there are no
+ DPCs to process. Therefore, power can be switched to a standby
+ mode until the the next interrupt occurs on the current processor.
+
+ N.B. This routine is entered with EE in MSR clear. This routine
+ must do any power management enabling necessary, set the EE
+ bit in MSR, then either return or wait for an interrupt.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+
+--*/
+
+VOID
+HalProcessorIdle(VOID)
+{
+ HASSERTMSG(PCR->CurrentIrql <= DISPATCH_LEVEL, "Wrong Dispatch Level");
+ HASSERT(RInterruptMask(GetCpuId()) == registeredInts[GetCpuId()]);
+
+ HalpEnableInterrupts();
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxinithl.c b/private/ntos/nthals/halfire/ppc/pxinithl.c
new file mode 100644
index 000000000..2166d81e4
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxinithl.c
@@ -0,0 +1,1114 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxinithl.c $
+ * $Revision: 1.92 $
+ * $Date: 1996/05/14 02:34:31 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991-1993 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:
+
+ pxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.ibm.com) Initial Power PC port
+
+ Removed call to HalpMapFixedTbEntries, the PPC port
+ maps all memory via calls to MmMapIoSpace().
+ Removed call to HalpInializeInterrupts - 8259 initialized in phase 1
+ Removed Cache error handler - 601 has no cache error interrupt
+ Removed call to HalpCreateDmaSturctures - it supports internal DMA
+ internal DMA contoller.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "halp.h"
+#include "pxmemctl.h"
+#include "fpproto.h"
+#include "phsystem.h"
+#include "fpio.h"
+#include "fpdcc.h"
+#include "fpds1385.h"
+#include "fpcpu.h"
+#include "arccodes.h"
+//#include "arc.h"
+#include "fpdebug.h"
+#include "fparch.h"
+#include "fpi2c.h"
+#include "pxpcisup.h"
+
+ULONG TmpVramBase;
+ULONG TmpDbatNum;
+ULONG TmpDbatVal;
+CHAR SysName[48];
+PCHAR SystemName="Unknown System";
+
+ULONG CpuClockMultiplier=0;
+ULONG MemoryParityErrorsThisBoot = 0;
+ULONG MemoryParityErrorsForever = 0;
+
+extern ADDRESS_USAGE HalpDefaultIoSpace;
+extern ULONG HalpGetInstructionTimes( VOID );
+extern VOID HalpInitializeVector2Irql(VOID);
+extern UCHAR PciDevicePrimaryInts[];
+extern ULONG PciAllowedInts;
+
+VOID
+HalpSynchronizeExecution(
+ VOID
+ );
+
+BOOLEAN
+HalpPhase0MapIo (
+ VOID
+ );
+
+BOOLEAN
+HalpPhase0MapPCIConfig (
+ VOID
+ );
+
+VOID
+HalpInitParityErrorLog (
+ VOID
+ );
+
+extern VOID HalpTranslateSystemSpecificData ( VOID );
+extern ULONG HalpPerformanceFrequency;
+extern BOOLEAN HalpSetRevs( RelInfo * );
+VOID HalpRestoreDBATs(VOID);
+VOID HalpSaveDBATs(VOID);
+#if defined(HALDEBUG_ON)
+VOID HalpDisplayBatForVRAM(void);
+VOID HalpGetDebugValue(VOID);
+extern BOOLEAN HalpPrintRevs( RelInfo * ); // from phvrsion.c
+extern VOID HalpVersionInternal( VOID ); // from phvrsion.c
+#endif
+extern VOID HalpVersionExternal( RelInfo *, PLOADER_PARAMETER_BLOCK ); // from phvrsion.c
+
+ULONG TimeBaseCount=0;
+
+
+//
+// This prototype taken from ntrtl.h.
+// Why not just include ntrtl.h? Well because I would need to include a dozen
+// other files too.
+//
+NTSYSAPI // ntddk ntifs
+NTSTATUS // ntddk ntifs
+NTAPI // ntddk ntifs
+RtlCharToInteger ( // ntddk ntifs
+ PCSZ String, // ntddk ntifs
+ ULONG Base, // ntddk ntifs
+ PULONG Value // ntddk ntifs
+ ); // ntddk ntifs
+
+
+RelInfo ThisOne;
+
+PROCESSOR_DESCRIPTION ProcessorDescription [nPROCESSOR_TYPE] = {
+ // Flags HashSize ProcessorName;
+ {PROC_NOSUPP, 0, "Unknown", "X"},
+ {PROC_SUPP, (64*1024), "601", "1"},
+ {PROC_NOSUPP, 0, "602", "2"},
+ {PROC_SUPP, 0, "603", "3"},
+ {PROC_SUPP |
+ PROC_HASHTABLE |
+ PROC_MPCAPABLE, (64*1024), "604", "4"},
+ {PROC_NOSUPP, 0, "605", "5"},
+ {PROC_SUPP, 0, "606", "3"},
+ {PROC_NOSUPP, 0, "607", "7"},
+ {PROC_NOSUPP, 0, "608", "8"},
+ {PROC_SUPP |
+ PROC_HASHTABLE |
+ PROC_MPCAPABLE, (64*1024), "609", "4"},
+};
+PROCESSOR_TYPE ProcessorType = PPC_UNKNOWN;
+
+SYSTEM_DESCRIPTION SystemDescription [] = {
+ {SYS_NOSUPP, "Unknown System Type"},
+ {SYS_SUPP, "ES"},
+ {SYS_SUPP|
+ SYS_MPCAPABLE, "MX"},
+ {SYS_SUPP|
+ SYS_MPCAPABLE, "TX"},
+ {SYS_SUPP|
+ SYS_MPCAPABLE, "LX"},
+};
+SYSTEM_TYPE SystemType = SYS_UNKNOWN;
+
+PVOID HalpSystemControlBase = NULL;
+PVOID HalpSystemRegisterBase = NULL;
+ULONG SafePlace;
+
+//
+// Define memory allocation structure.
+//
+typedef struct _AVR_MEMORY_DESCRIPTOR {
+ LIST_ENTRY *NextEntry;
+ LIST_ENTRY *PrevEntry;
+ MEMORY_DESCRIPTOR MemoryEntry;
+} AVR_MEMORY_DESCRIPTOR, *PAVR_MEMORY_DESCRIPTOR;
+
+CHAR *MemTypeList[] = {
+ "MemoryExceptionBlock",
+ "MemorySystemBlock",
+ "MemoryFree",
+ "MemoryBad",
+ "MemoryLoadedProgram",
+ "MemoryFirmwareTemporary",
+ "MemoryFirmwarePermanent",
+ "LoaderOsloaderHeap",
+ "LoaderOsloaderStack",
+ "LoaderSystemCode",
+ "LoaderHalCode",
+ "LoaderBootDriver",
+ "LoaderConsoleInDriver",
+ "LoaderConsoleOutDriver",
+ "LoaderStartupDpcStack",
+ "LoaderStartupKernelStack",
+ "LoaderStartupPanicStack",
+ "LoaderStartupPcrPage",
+ "LoaderStartupPdrPage",
+ "LoaderRegistryData",
+ "LoaderMemoryData",
+ "LoaderNlsData",
+ "LoaderSpecialMemory",
+ "LoaderMaximum"
+ };
+
+
+//
+// There are two variables that control debug printouts, HALDEBUG_ON,
+// and HALDEBUGVALUE. HALDEBUGVALUE is used to set a minimum level
+// of printing and debug behavior, and HALDEBUG_ON turns on the
+// environment variable. HALDEBUG_ON may be defined without HALPDEBUGVALUE,
+// but defining HALPDEBUGVALUE should require HALDEBUG_ON also be defined.
+//
+
+#if defined(HALDEBUG_ON)
+ //
+ // set the HalpDebugValue that determines what level of debug printout
+ // occurs. If one is defined on the cmd line, then 'or' it in with
+ // whatever is defined in the environment ( nvram ) area.
+ //
+# if defined(HALPDEBUGVALUE)
+int HalpDebugValue = HALPDEBUGVALUE;
+# else
+int HalpDebugValue = 0;
+# endif // HALPDEBUGVALUE
+#endif // HALPDEBUG_ON
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+#if defined(ALLOC_PRAGMA)
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+#pragma alloc_text(INIT, HalpInitParityErrorLog)
+#endif
+
+PVOID HalpIoControlBase = (PVOID) 0;
+PVOID HalpIoMemoryBase = (PVOID) 0;
+
+VOID
+HalpInitBusHandlers (
+ VOID
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+KSPIN_LOCK HalpDS1385Lock;
+KSPIN_LOCK HalpRTCLock;
+
+
+/*++
+
+Routine Description: BOOLEAN HalInitSystem ()
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+ SYSTEM_TYPE I2CSystemType;
+ UCHAR slot;
+ ULONG *TreeDepth = 0;
+ UCHAR CpuId;
+ KIRQL IrqlIn;
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+ Prcb = PCR->Prcb;
+ IrqlIn = PCR->CurrentIrql;
+ SET_LEDS(0xf7);
+
+ //
+ // The following handles the initialization requirements for
+ // all processors greater than 1.
+ //
+
+ if (Prcb->Number > 0) {
+ HDBG(DBG_INTERNAL,
+ HalpDebugPrint("HalInitSystem: Init of Cpu(%d)\n", GetCpuId()););
+
+ //
+ // Mask interrrupts, clear all of them and then
+ // enable interrupts.
+ //
+ HalpDisableInterrupts();
+ HalpInitInts(Prcb->Number);
+ HalpRestoreDBATs();
+ HalpEnableInterrupts();
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: Cpu (%d) Interrupt Mask (0x%08x)\n",
+ GetCpuId(), RInterruptMask(GetCpuId())););
+ HDBG(DBG_INTERNAL,
+ HalpDebugPrint("HalInitSystem: exit Cpu(%d)\n", GetCpuId()));
+
+ //
+ // Check the current irql level and make sure we exit at the same
+ // irql we entered with:
+ //
+ if( PCR->CurrentIrql >= IrqlIn ) {
+ KeLowerIrql(IrqlIn);
+ } else {
+ KIRQL dummyIrql;
+ KeRaiseIrql(IrqlIn, &dummyIrql);
+ }
+ return TRUE;
+ }
+
+ //
+ // Phase 0 initialization. (Main Processor Only).
+ //
+ ASSERT(Prcb->Number == 0);
+ if (Phase == 0) {
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey = 0;
+
+ HalpInitParityErrorLog();
+
+#if defined(HALDEBUG_ON)
+ //
+ // Get user defined debug variable and 'or' it into the
+ // compiled version of the debug variable.
+ //
+ HalpGetDebugValue();
+#endif
+
+ // moved this from after ConfigurationEntry because HalpGet
+ if (NULL == HalpIoControlBase) {
+ if (!HalpPhase0MapIo() || !HalpPhase0MapPCIConfig()) {
+ return FALSE;
+ }
+ }
+
+ // Initialize the Pci Primary Slot table to be invalid; this table
+ // is filled in on a per system basis.
+ for (slot = 0; slot < MAXIMUM_PCI_SLOTS; slot++) {
+ PciDevicePrimaryInts[slot] = INVALID_INT;
+ }
+
+ ConfigurationEntry =
+ KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ SystemClass,
+ ArcSystem,
+ &MatchKey);
+
+ if (ConfigurationEntry) {
+ //
+ // If configuration entry is not null, then look at the
+ // identifier returned for this arc system name. If its the MP
+ // system, it means we really do have more than one cpu and
+ // will want to set a flag so VRAM is handled
+ // differently, and some extra checking is done.
+ //
+ SystemName = ConfigurationEntry->ComponentEntry.Identifier;
+
+ // Check if I2C is present
+ if (HalpI2CGetSystem(&I2CSystemType) == TRUE) {
+ SystemDescription[SystemType].Flags |= SYS_MPFOREAL;
+ // If I2C is present, determine if we are Slice or Serve
+ SystemType = I2CSystemType;
+ if ((SystemType != SYS_POWERSLICE) &&
+ (SystemType != SYS_POWERSERVE)) {
+ SystemType = SYS_UNKNOWN;
+ }
+ // An I2C is present, find the interrupt table. If there
+ // is no interrupt table, set SystemType back to SYS_UNKNOWN
+ // so that we may die now, since this is an unrecoverable
+ // error.
+ if (HalpI2CGetInterrupt() == FALSE) {
+ SystemType = SYS_UNKNOWN;
+ }
+ }
+ // If I2c is not present, must be either Pro or Top
+ else {
+ if (SystemType == SYS_POWERTOP) {
+ SystemDescription[SystemType].Flags |= SYS_MPFOREAL;
+ }
+ PciDevicePrimaryInts[1] = 0x19;
+ PciDevicePrimaryInts[2] = 0x16;
+ PciDevicePrimaryInts[3] = 0x17;
+ PciDevicePrimaryInts[4] = 0x1a;
+ PciAllowedInts = 0x06c00000;
+ }
+ } else {
+ HalpDebugPrint("ConfigurationEntry is null \n");
+ }
+
+ // Now compute the allowed interrupt mask
+ for (slot = 0; slot < MAXIMUM_PCI_SLOTS; slot++) {
+ if (PciDevicePrimaryInts[slot] != INVALID_INT) {
+ PciAllowedInts |= (1 << PciDevicePrimaryInts[slot]);
+ }
+ }
+ PciAllowedInts |= 0x40000000; // Add the MemErr bit
+
+ // If we are not a valid system type; die a horrible death
+ if (SystemType == SYS_UNKNOWN) {
+ HalpDebugPrint("HalInitSystem: Unknown SystemType\n");
+ DbgBreakPoint();
+ }
+
+ // Once we have the interrupt structure, we can initialize the IRQL
+ // values for the PIO slots.
+ HalpInitializeVector2Irql();
+
+ HDBG(DBG_INTERNAL,
+ HalpDebugPrint("HalInitSystem: phase 0 init (processor 0)\n"););
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: HalpIoControlBase set: 0x%08x\n",
+ HalpIoControlBase););
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: HalpSystemRegisterBase(0x%x)\n",
+ HalpSystemRegisterBase););
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: rInterruptRequest(0x%x)\n",
+ _ADDR(0x0)););
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: PciAllowedInts(0x%x)\n",
+ PciAllowedInts););
+
+ HalpInterruptBase =
+ (PULONG)HalpSystemRegisterBase + INTERRUPT_OFFSET;
+
+ //
+ // clear out all the crap from the system interrupt registers:
+ //
+ RInterruptMask(GetCpuId()) = 0x0;
+ WaitForRInterruptMask(GetCpuId());
+ rInterruptRequest = 0xffffffff;
+ FireSyncRegister();
+
+ //
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Init variables, spin locks, and the display adapter.
+ //
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNewTimeIncrement = MAXIMUM_INCREMENT;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Initialize all spin locks.
+ //
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+ KeInitializeSpinLock(&HalpDS1385Lock);
+ KeInitializeSpinLock(&HalpRTCLock);
+
+ HalpRegisterAddressUsage (&HalpDefaultIoSpace);
+
+ //
+ // Initialize the display adapter.
+ //
+ if (!HalpInitializeDisplay(LoaderBlock)) {
+ HalpDebugPrint("HalInitSystem: did not init display\n");
+ return FALSE;
+ }
+
+ //
+ // set the background red for phase 0
+ //
+ HDBG(DBG_COLORS, HalpSetPixelColorMap( 0x00ff0000, 0x00000001 ););
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("Debug Value is 0x%x\n", HalpDebugValue););
+ HDBG(DBG_DUMPTREE,
+ PHalpDumpConfigData(LoaderBlock->ConfigurationRoot,
+ TreeDepth););
+ HDBG(DBG_DUMPTREE,
+ PHalpDumpLoaderBlock(LoaderBlock););
+
+ //
+ // Check if we should call a break point
+ //
+ HDBG(DBG_BREAK,
+ HalpDebugPrint("HalInitSystem: Calling Break Point\n"));
+ HDBG(DBG_BREAK, DbgBreakPoint());
+
+ //
+ // RTC: check that the RTC is working...
+ //
+ HDBG(DBG_GENERAL, HalpDebugPrint("Checking RTC ....\n"););
+ HalpInitFirePowerRTC();
+
+ //
+ // Calibrate execution stall
+ //
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: Calibrating stall\n"););
+ HalpCalibrateTimingValues();
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: HalpPerformanceFrequency = %d\n",
+ HalpPerformanceFrequency););
+
+ //
+ // InitializeInterrupts
+ //
+ HDBG(DBG_GENERAL, HalpDebugPrint("HalInitSystem: Initting ints\n"););
+ if (!HalpInitializeInterrupts()) {
+ HalpDebugPrint("HalInitSystem: Did not init interrupts ");
+ return FALSE;
+ }
+
+ HDBG(DBG_GENERAL, HalpDisplayBatForVRAM(););
+ HalpSaveDBATs();
+ HDBG(DBG_GENERAL,
+ HalDisplayString("HalInitSystem: done with phase 0 \n"););
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("System Name: %s \n", SystemName ););
+
+ } else {
+ //
+ // Phase 1 initialization.
+ //
+
+ //
+ // set the display to green while in phase 1:
+ //
+ HDBG(DBG_COLORS, HalpSetPixelColorMap(0x00009900, 0x00000001););
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: phase 1 init (processor 0)\n"););
+
+ HalpInitializeDisplay1(LoaderBlock );
+ HalpRegisterInternalBusHandlers ();
+ if (!HalpAllocateMapBuffer()) {
+ HalpDebugPrint("HalInitSystem: Did not allocate map buffer");
+ return FALSE;
+ }
+
+ //
+ // Map I/O space and create ISA data structures.
+ //
+ if (!HalpMapIoSpace()) {
+ HalpDebugPrint("HalInitSystem: Did not map io space");
+ return FALSE;
+ }
+
+
+ //
+ // Setup Io bus handlers ( really only setting up pci bus 0:
+ // the primary one). This needs to be done before the call
+ // to HalpCreateSioStructures so it can find the pci-e/isa
+ // bridge chip.
+ //
+ HalpInitIoBuses();
+
+
+ if (!HalpCreateSioStructures()) {
+ HalpDebugPrint("HalInitSystem: No sio structures created");
+ return FALSE;
+ }
+
+
+ //
+ // At this point, the interrupt handlers are installed so any
+ // interrupts pending are cleared...
+ //
+ if (!HalpInitIntelAIP()) {
+ HalpDebugPrint("HalInitSystem: AIP did not initialize\n");
+ return FALSE;
+ }
+
+ //
+ // Note: GetCpuId can not be called earlier
+ // because the registers are not mapped.
+ //
+ CpuId = (UCHAR) GetCpuId();
+ if (SystemType == SYS_POWERPRO) {
+ CpuId = 0;
+ }
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: Cpu id is: %d\n", CpuId););
+
+ //
+ // Display HAL specific information
+ //
+ HalpSetRevs( &ThisOne );
+ HDBG(DBG_GENERAL, HalpPrintRevs( &ThisOne ););
+ HDBG(DBG_GENERAL, HalpVersionInternal(););
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("CpuClockMultiplier = 0x%x ( %d ) \n",
+ CpuClockMultiplier, CpuClockMultiplier ));
+ HalpVersionExternal(&ThisOne, LoaderBlock);
+
+ //
+ // Before we exit, make sure any device interrupts are masked
+ // off, and all interrupts are cleared. DON'T FORGET: by this
+ // point, several interrupts have gone through a connect call,
+ // they may already exist in the mask. None of the devices are
+ // currently in this set but the cpu message interrupt. DON"T
+ // MESS WITH THE CPU MESSAGE INTERRUPT BIT!!
+ //
+ switch(SystemType) {
+ case SYS_POWERSLICE:
+ RInterruptMask(GetCpuId()) &= ~(ENABLE_EISA_MASK);
+ break;
+
+ case SYS_POWERSERVE:
+ // TX_PROTO: allowable PCI interrupts
+ RInterruptMask(GetCpuId()) &=
+ ~(ENABLE_EISA_MASK|0x06700000);
+ break;
+ case SYS_POWERTOP:
+ case SYS_POWERPRO:
+ RInterruptMask(GetCpuId()) &= ~(ENABLE_EISA_MASK|
+ SCSI_INT|
+ ENET_INT);
+ break;
+ default:
+ break;
+ };
+
+ WaitForRInterruptMask(GetCpuId());
+ rInterruptRequest = SET_INTS_CLEAR;
+ FireSyncRegister();
+
+ //HalpEnableInterrupts();
+ // Turn on interrupts, set the irql, and setup the system int masks:
+ //
+ KeLowerIrql(LOW_LEVEL);
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalInitSystem: Cpu (%d) Interrupt Mask (0x%x)\n",
+ GetCpuId(), RInterruptMask(GetCpuId())));
+
+ //
+ // Make sure the display is now a blue background with
+ // White letters:
+ //
+ HDBG(DBG_COLORS, HalpSetPixelColorMap( 0x00ffffff, 0x000000ff ));
+ HDBG(DBG_COLORS, HalpSetPixelColorMap( 0x000000ff, 0x00000001 ));
+ HalpInitializeRegistry(LoaderBlock); // mogawa
+ HalpTranslateSystemSpecificData ();
+
+ HDBG(DBG_GENERAL, HalpDebugPrint("HalInitSystem: done phase 1\n"););
+ }
+
+ //
+ // Check the current irql level and make sure we exit at the same
+ // irql we entered with:
+ //
+ if( PCR->CurrentIrql >= IrqlIn ) {
+ KeLowerIrql(IrqlIn);
+ } else {
+ KIRQL dummyIrql;
+ KeRaiseIrql(IrqlIn, &dummyIrql);
+ }
+
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description: VOID HalInitializeProcessor ()
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+{
+ PULONG pPCIBase;
+ BOOLEAN newMap;
+ ULONG IcacheSize, DcacheSize;
+ ULONG CacheBlockAlignment;
+
+ //
+ // Initialize the processor type (601, 603, 604, ...)
+ //
+ ProcessorType = (HalpGetProcessorVersion() >> 16);
+
+ //
+ // FireWorks ( FirePOWER and Firmworks ) veneer does not correctly set the
+ // processor cache size and alignment requirements in the loader parameter
+ // block so we forcibly replace the values that were copied from there
+ // into the PCR.
+ //
+ switch( ProcessorType ) {
+ case 1: // 601 processor
+ IcacheSize = 32 * 1024;
+ DcacheSize = 32 * 1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+ case 3: // 603 processor
+ IcacheSize = 8 * 1024;
+ DcacheSize = 8 * 1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+ case 6: // 603+ processor
+ case 4: // 604 processor
+ IcacheSize = 16 * 1024;
+ DcacheSize = 16 * 1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+ case 9: // 604+ processor
+ IcacheSize = 32 * 1024;
+ DcacheSize = 32 * 1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+ default:
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ return;
+ }
+ PCRsprg1->FirstLevelIcacheSize = IcacheSize;
+ PCRsprg1->FirstLevelDcacheSize = DcacheSize;
+ PCRsprg1->DcacheAlignment = CacheBlockAlignment;
+ PCRsprg1->IcacheAlignment = CacheBlockAlignment;
+
+ //
+ // Check what cpu we're on. Return now if this cpu is
+ // not the primary ( first ) cpu.
+ //
+ if (Number != 0) {
+ return; // Nothing to do here, just return
+ }
+
+ //
+ // Initialize the system type register (PowerPro vs PowerTop).
+ // Use the System Register Base address if mapped to access
+ // the control page of the system. If not, map a virtual
+ // address temporarily and unmap it when finished.
+ //
+ if (NULL == HalpIoControlBase) {
+ if (!HalpPhase0MapIo() || !HalpPhase0MapPCIConfig()) {
+ DbgPrint("HalInitializeProcessor: Failed to map dbats\n");
+ return;
+ }
+ }
+
+ if (HalpSystemRegisterBase) {
+ pPCIBase = (PULONG)((PUCHAR)HalpSystemRegisterBase +
+ (SYSTEM_PCI_CONFIG_BASE - SYSTEM_REGISTER_SPACE));
+ newMap = FALSE;
+ } else {
+
+ pPCIBase =
+ (PULONG)KePhase0MapIo((PVOID)SYSTEM_PCI_CONFIG_BASE, 0x1000);
+ newMap = TRUE;
+ }
+
+ if (pPCIBase) {
+ PULONG pDeviceId;
+ // for little endian reasons, add the 1 in.
+ pDeviceId = (PULONG)(pPCIBase + 0x42 + 0x01);
+ switch (*pDeviceId) {
+ case ESCC_IDENT:
+ SystemType = SYS_POWERPRO;
+ break;
+ case TSC_IDENT:
+ SystemType = SYS_POWERTOP;
+ break;
+ default:
+ SystemType = SYS_UNKNOWN;
+ break;
+ }
+ if (newMap) {
+ KePhase0DeleteIoMap((PVOID)SYSTEM_PCI_CONFIG_BASE, 0x1000);
+ }
+ } else {
+ SystemType = SYS_UNKNOWN;
+ }
+
+ //
+ // If this is the first processor, initialize the cache
+ // sweeping routines depending on type of processor.
+ //
+ if (HalpCacheSweepSetup()) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Calculate the cpu clock rate:
+ //
+
+ // Temporary fix until we understand the code
+ if (SystemType == SYS_POWERPRO) {
+ CpuClockMultiplier = 30; // fix it for the moment....
+ } else {
+ if ((SystemType == SYS_POWERSLICE) ||
+ (SystemType == SYS_POWERTOP) ||
+ (SystemType == SYS_POWERSERVE)) {
+ //
+ // The times recorded from HalpGetInstructionTimes range about
+ // 80 to 256.
+ // times: Multiplier:
+ // 85/6 3x BusClock
+ // 128 2x
+ // 170/1 1.5x
+ // 256 1x
+ //
+ // Since there can be a non integer multiple of bus clocks, will
+ // do all integer math at a multiple of 10 and remove the extra
+ // order of magnitude downstream when the value is used
+ //
+ TimeBaseCount = HalpGetInstructionTimes();
+ TimeBaseCount = HalpGetInstructionTimes();
+ CpuClockMultiplier = ((480 * 10) / (10 * (TimeBaseCount/10)));
+ if (CpuClockMultiplier > 50 ) {
+ CpuClockMultiplier = 50; // limit frequency multiples to 5.
+ }
+ }
+ }
+
+ return;
+}
+
+
+#define MAX_DBATS 4
+ULONG DBATUpper[MAX_DBATS];
+ULONG DBATLower[MAX_DBATS];
+
+VOID
+HalpRestoreDBATs()
+{
+ int i;
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpRestoreDBATs: entered\n"););
+ for (i = 0; i < MAX_DBATS; i++) {
+ HDBG(DBG_DBAT,
+ HalpDebugPrint("HalpRestoreDBATs: U(%d):Old(0x%08x) New(0x%08x)\n",
+ i, HalpGetUpperDBAT(i), DBATUpper[i]););
+ HDBG(DBG_DBAT,
+ HalpDebugPrint("HalpRestoreDBATs: L(%d):Old(0x%08x) New(0x%08x)\n",
+ i, HalpGetLowerDBAT(i), DBATLower[i]););
+ HalpSetUpperDBAT(i, DBATUpper[i]);
+ HalpSetLowerDBAT(i, DBATLower[i]);
+ }
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpRestoreDBATs: exit\n"););
+}
+
+
+VOID
+HalpSaveDBATs()
+{
+ int i;
+
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpSaveDBATs: entered\n"););
+ for (i = 0; i < MAX_DBATS; i++) {
+ DBATUpper[i] = HalpGetUpperDBAT(i);
+ DBATLower[i] = HalpGetLowerDBAT(i);
+ HDBG(DBG_DBAT,
+ HalpDebugPrint("HalpSaveDBATs: (%d): U(0x%08x) L(0x%08x)\n",
+ i, DBATUpper[i], DBATLower[i]););
+ }
+}
+
+/*++
+
+ Routine Description: BOOLEAN HalpPhase0MapIo ()
+
+ This function forces a very special DBAT mapping for Phase0.
+ The kernel routine KePhase0DeleteIoMap has a nasty bug, so
+ just map three (the max) DBATS:
+
+ 1) system registers
+ 2) memory (to be reused for VRAM if no INT10 support)
+ 3) I/O control (change the size of its mapping)
+
+ The idea is to let the kernel map the three DBATs.
+ It sets the boundary to 8Mb and maps 8Mb starting at
+ virtual address 0xb0000000. Thus you get the following
+ virtual to physical mappings:
+
+ DBAT2 = 0xb0800000-0xb0ffffff -> 0xff000000-0xffffffff
+ DBAT3 = 0xb1000000-0xb17fffff -> 0x80000000-0x80ffffff
+
+ The I/O control size will be changed (by HalpPhase0MapPCIConfig())
+ to 16Mb so it maps 0x80000000 to 0x80ffffff which covers the PCI
+ config space.
+
+ The mapping of the frame buffer or memory space (for INT10)
+ is left to pxdisp.c which will use DBAT1.
+
+Arguments:
+
+
+Return Value:
+
+ TRUE if success, FALSE if failure
+
+--*/
+
+BOOLEAN
+HalpPhase0MapIo (
+ VOID
+ )
+{
+
+ //
+ // Get access to I/O space.
+ //
+ if (NULL == HalpIoControlBase) {
+ HalpIoControlBase =
+ (PVOID)KePhase0MapIo((PVOID)IO_CONTROL_PHYSICAL_BASE, 0x800000);
+ if (!HalpIoControlBase) {
+ DbgPrint("HalpPhase0MapIo: HalpIoControlBase map failed\n");
+ return FALSE;
+ }
+ }
+
+ //
+ // Get access to System Register space.
+ //
+ if (NULL == HalpSystemRegisterBase) {
+ HalpSystemRegisterBase =
+ (PVOID)KePhase0MapIo((PVOID)SYSTEM_REGISTER_SPACE, 0x800000);
+ if(HalpSystemRegisterBase) {
+ HalpInterruptBase =
+ (PULONG)HalpSystemRegisterBase + INTERRUPT_OFFSET;
+ HalpSystemControlBase =
+ (PULONG)HalpSystemRegisterBase + SYSTEM_CONTROL_OFFSET;
+ } else {
+ DbgPrint("HalpPhase0MapIo: HalpSystemRegisterBase map failed\n");
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/*++
+
+ Routine Description: BOOLEAN HalpPhase0MapPCIConfig ()
+
+ This function extends the map length of I/O Control
+ to include PCI Config space.
+
+Arguments:
+
+
+Return Value:
+
+ TRUE if success, FALSE if failure
+
+--*/
+
+BOOLEAN
+HalpPhase0MapPCIConfig (
+ VOID
+ )
+{
+ ULONG hi, low;
+ LONG i;
+
+
+ //
+ //
+ // Look for the I/O control space DBAT mapping.
+ //
+ for (i = 1; i < MAX_DBATS; i++) {
+ PVOID va = NULL;
+
+ low = HalpGetLowerDBAT(i);
+ if (IO_CONTROL_PHYSICAL_BASE == (low & 0xfffe0000)) {
+ hi = HalpGetUpperDBAT(i);
+ if ((PVOID)(hi & 0xfffe0000) == HalpIoControlBase) {
+ if (3 == i) {
+ //
+ // Change the size to 16Mb.
+ //
+ hi &= ~0x000001fc;
+ hi |= 0x000001fc;
+ HalpSetUpperDBAT(i, hi);
+ hi = HalpGetUpperDBAT(i);
+ if ((hi & 0x00001ffc) == 0x000001fc) {
+ HalpPciConfigBase = (PUCHAR)HalpIoControlBase +
+ ((ULONG)PCI_CONFIG_PHYSICAL_BASE -
+ (ULONG)IO_CONTROL_PHYSICAL_BASE);
+ } else {
+ DbgPrint("HalpPhase0MapPCIConfig: failed, invalid size\n");
+ return FALSE;
+ }
+ } else {
+ DbgPrint("HalpPhase0MapPCIConfig: failed, invalid DBAT\n");
+ }
+ } else {
+ DbgPrint("HalpPhase0MapPCIConfig: failed, invalid virtual address\n");
+ return FALSE;
+ }
+ return TRUE;
+ }
+ }
+
+ DbgPrint("HalpPhase0MapPCIConfig: failed, invalid physical address\n");
+ return FALSE;
+}
+
+
+#if defined(HALDEBUG_ON)
+VOID
+HalpGetDebugValue()
+{
+ CHAR buf[30];
+ int nvramValue;
+
+ //
+ // Get Debug Value from NVRAM and or with compiler version
+ //
+ if (HalGetEnvironmentVariable("HALDEBUG", sizeof(buf), buf) == ESUCCESS) {
+ nvramValue = atoi(buf);
+ HalpDebugValue |= nvramValue;
+ }
+}
+#endif
+
+//
+// Initialize the global variables for parity error count.
+//
+// The initial value for this boot is zero.
+// The initial value forever is read from NVRAM.
+//
+// The NVRAM values are stored in the env variable
+// "MEMORY_PARITY_ERRORS" as:
+// # errors this boot, # errors forever
+//
+//
+VOID
+HalpInitParityErrorLog (
+ VOID
+ )
+{
+ ULONG rc;
+ CHAR buf[80];
+
+ rc = HalGetEnvironmentVariable(MemoryParityErrorsVarName,
+ sizeof(buf), buf);
+ if (ESUCCESS == rc) {
+ PCHAR tok;
+ const PCHAR delimiters = ",; ";
+
+ if (buf && strlen(buf) && (tok = FpStrtok(buf, delimiters))) {
+ rc = RtlCharToInteger(tok, 0, &MemoryParityErrorsThisBoot);
+ if (STATUS_SUCCESS != rc) {
+ MemoryParityErrorsThisBoot = 0;
+ }
+ while ( tok = FpStrtok(NULL, delimiters) ) {
+ if (strlen(tok)) {
+ rc = RtlCharToInteger(tok, 10, &MemoryParityErrorsForever);
+ if (STATUS_SUCCESS != rc) {
+ MemoryParityErrorsForever = 0;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxintsup.s b/private/ntos/nthals/halfire/ppc/pxintsup.s
new file mode 100644
index 000000000..4daf671c9
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxintsup.s
@@ -0,0 +1,121 @@
+// TITLE("Enable and Disable Processor Interrupts")
+//++
+//
+// Copyright (c) 1991 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:
+//
+// pxintsup.s
+//
+// Abstract:
+//
+// This module implements the code necessary to enable and disable
+// interrupts on a PPC system.
+//
+// Author:
+//
+// Jim Wooldridge
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 30-Dec-93 plj Added 603 support.
+//
+//--
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxintsup.s $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:11:07 $
+ * $Locker: $
+ */
+
+#include "halppc.h"
+
+//++
+//
+// Routine Description:
+//
+// Enables interrupts.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpEnableInterrupts)
+
+ mfmsr r.5
+ ori r.5,r.5,MASK_SPR(MSR_EE,1)
+ mtmsr r.5
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+ LEAF_EXIT(HalpEnableInterrupts)
+
+
+//++
+
+//
+// Routine Description:
+//
+// Disables interrupts.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpDisableInterrupts)
+
+ mfmsr r.5
+ rlwinm r.5,r.5,0,~MASK_SPR(MSR_EE,1)
+ mtmsr r.5
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+ LEAF_EXIT(HalpDisableInterrupts)
+
+
+//++
+
+//
+// Routine Description:
+//
+// Disables interrupts.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(KiGetPcr)
+
+ mfsprg r.3,1
+
+ LEAF_EXIT(KiGetPcr)
diff --git a/private/ntos/nthals/halfire/ppc/pxirql.c b/private/ntos/nthals/halfire/ppc/pxirql.c
new file mode 100644
index 000000000..773d892e4
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxirql.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxirql.c $
+ * $Revision: 1.17 $
+ * $Date: 1996/01/11 07:11:13 $
+ * $Locker: $
+ */
+
+// TITLE("Manipulate Interrupt Request Level")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+// Copyright 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:
+//
+// PXIRQL.C
+//
+// Abstract:
+//
+// This module implements the code necessary to lower and raise the current
+// Interrupt Request Level (IRQL).
+//
+//
+// Author:
+//
+// Jim Wooldridge (IBM)
+// Steve Johns (Motorola)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 22-Feb-94 Steve Johns (Motorola)
+// KeRaiseIrql - Disabled interrupts at PIC if IRQL >= DEVICE_LEVEL
+// KeLowerIrql - Enabled interrupts at PIC if IRQL < DEVICE_LEVEL
+// 15-Apr-94 Jim Wooldridge
+// Added irql interrupt mask table and expanded irql range from (0-8)
+// to (0-31).
+//
+// TODO:
+// 1) Fix the forced mask assignments in the KeRaiseIrql and KeLowerIrql
+// routines
+//--
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "eisa.h"
+#include "phsystem.h"
+#include "fpcpu.h"
+
+
+VOID KiDispatchSoftwareInterrupt(VOID);
+
+//
+// Globals accessed.
+//
+extern ULONG registeredInts[];
+extern ULONG Irql2Mask[];
+
+//
+// VOID
+// KeLowerIrql (
+// KIRQL NewIrql
+// )
+//
+// Routine Description:
+//
+// This function lowers the current IRQL to the specified value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// Return Value:
+//
+// None.
+//
+//--
+VOID
+KeLowerIrql(KIRQL NewIrql)
+{
+ KIRQL OldIrql;
+ UCHAR CpuId;
+
+ //
+ // All accesses to the PCR should be guarded by disabling interrupts
+ // in the CPU (MSR register).
+ //
+ HalpDisableInterrupts();
+
+ CpuId = (UCHAR)GetCpuId();
+
+ //
+ // We should no be raising our Irql with lower.
+ //
+ HASSERTEXEC(NewIrql <= PCR->CurrentIrql,
+ HalpDebugPrint("KeLowerIrql: New (0x%x) Current(0x%x)\n",
+ NewIrql, PCR->CurrentIrql));
+
+ //
+ // Switch to the new Irql.
+ //
+ OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+
+ //
+ // Now make the coresponding hardware mask changes.
+ //
+ RInterruptMask(CpuId) = (Irql2Mask[NewIrql] & registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+
+ if (NewIrql < CLOCK2_LEVEL) {
+
+ HalpEnableInterrupts();
+
+ //
+ // check for DPC's
+ //
+ if ((NewIrql < DISPATCH_LEVEL) && PCR->SoftwareInterrupt) {
+ KiDispatchSoftwareInterrupt();
+ }
+ }
+}
+
+//
+// VOID KeRaiseIrql (KIRQL NewIrql, PKIRQL OldIrql)
+//
+// Routine Description:
+//
+// This function raises the current IRQL to the specified value and returns
+// the old IRQL value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// OldIrql - Supplies a pointer to a variable that recieves the old
+// IRQL value.
+//
+
+VOID
+KeRaiseIrql(IN KIRQL NewIrql, OUT PKIRQL OldIrql)
+{
+ UCHAR CpuId;
+
+ //
+ // All accesses to the PCR should be guarded by disabling interrupts
+ // in the CPU (MSR register).
+ //
+ HalpDisableInterrupts();
+
+ CpuId = (UCHAR)GetCpuId();
+
+ //
+ // We should not be raising to a lower level.
+ //
+ HASSERTEXEC(NewIrql >= PCR->CurrentIrql,
+ HalpDebugPrint("KeRaiseIrql: New (0x%x) Current(0x%x)\n",
+ NewIrql, PCR->CurrentIrql));
+
+ //
+ // Switch to the new Irql.
+ //
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+
+ //
+ // Now make the corresponding hardware mask changes.
+ //
+ RInterruptMask(CpuId) = (Irql2Mask[NewIrql] & registeredInts[CpuId]);
+ WaitForRInterruptMask(CpuId);
+
+ if (NewIrql < CLOCK2_LEVEL) {
+ HalpEnableInterrupts();
+ }
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxisabus.c b/private/ntos/nthals/halfire/ppc/pxisabus.c
new file mode 100644
index 000000000..59c62c743
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxisabus.c
@@ -0,0 +1,576 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxisabus.c $
+ * $Revision: 1.21 $
+ * $Date: 1996/05/14 02:34:36 $
+ * $Locker: $
+ */
+
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxisabus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "phsystem.h"
+
+ULONG
+HalpGetIsaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+#define TBS " "
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetIsaInterruptVector)
+#pragma alloc_text(PAGE,HalpAdjustIsaResourceList)
+#pragma alloc_text(PAGE,HalpAdjustResourceListLimits)
+#endif
+
+
+
+/*++
+
+Routine Description: ULONG HalpGetIsaInterruptVector()
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ 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
+HalpGetIsaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+
+ //
+ // irq2 shows up on irq9
+ //
+
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetIsaInterruptVector: 0x%x, 0x%x, 0x%x 0x%x \n",
+ BusInterruptLevel, BusInterruptVector, *Irql, *Affinity ););
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ BusInterruptVector = 9;
+ }
+
+ //
+ // Hack Hack:
+ //
+ // NOTE: NOTE:
+ // The Ethernet driver reports itself as an ISA device but with a
+ // PCI interrupt so need to fixup the interrupt if it looks correct
+ // for the pci bus vector:
+ if (BusInterruptLevel > 15) {
+ return 0;
+ }
+
+ //
+ // There are 4 cases to check here:
+ // A) One of the entries ( BusIntLvl || BusIntVec ) is zero,
+ // B) Both of the entries are the same value,
+ // C) One of the entries is == 5 ( Which is the SPL for external
+ // devices on PowerPC NT )
+ // D) none of the above
+ //
+ switch(BusInterruptLevel) {
+ case 0:
+ if (BusInterruptVector) {
+ BusInterruptLevel = BusInterruptVector;
+ } else {
+ // they're both zero, so hope this is the profile int.
+ }
+ break;
+ case 5:
+ //
+ // In this case, BusInterruptLevel is probably indicating the
+ // system SPL for external ints, so assume the BusInterruptVector
+ // contains the real interrupt info
+ //
+
+ break;
+ default:
+ //
+ // Since BusInterruptLevel is nonzero and not equal to 5, then see
+ // if BusInterruptVector is zero or equal to 5. If it's neither,
+ // then print out the level and vector values and spin since this
+ // is a combination I've never seen before.
+ //
+ if( BusInterruptVector ) {
+ ULONG tmp;
+ if( BusInterruptVector == (BusInterruptLevel + 0x20) ) {
+
+ BusInterruptVector = BusInterruptLevel;
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetISAInt: BusIntVec(0x%x) = BusIntLvl(0x%x) +0x20 \n",
+ BusInterruptVector, BusInterruptLevel ));
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetISAInt: ****** Please Fix Driver to use BusInterruptVector correctly \n"));
+// NOTE("Hack for audio driver to work")
+ }
+ if(( BusInterruptLevel != BusInterruptVector)
+ && ( BusInterruptVector != 5 )) {
+ HalpDebugPrint("Wierd BusIntVec & BusIntLvl (spin now)\n");
+ HalpDebugPrint(" BusIntLvl = 0x%x, BusIntVec = 0x%x\n",
+ BusInterruptLevel, BusInterruptVector );
+ for (;;) {
+ }
+ }
+ //
+ // Here, BusInterruptVector is known to be non-zero, = 5 or
+ // BusLevel. So, assume it's the 5 choice and swap it with
+ // level.
+ //
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("\t\tSwap BusIntLvl & BusIntVec %x, %x...\n",
+ BusInterruptLevel, BusInterruptVector););
+ tmp = BusInterruptLevel;
+ BusInterruptLevel = BusInterruptVector;
+ BusInterruptVector = tmp;
+ //
+ // Now, BusInterruptVector has the interesting value so the
+ // HalpGetSystemInterrupt can correctly key on
+ // BusInterruptVector.
+ //
+ } else {
+ //
+ // since BusInterruptVector is zero
+ //
+ BusInterruptVector = BusInterruptLevel;
+ }
+ }
+
+ //
+ // Get parent's translation from here..
+ //
+ return BusHandler->ParentHandler->GetInterruptVector (
+ BusHandler->ParentHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+ UCHAR Irq[15], c;
+
+ for (c=0; c < 15; c++) {
+ Irq[c] = IRQ_VALID;
+ }
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpAdjustIsaResourceList: called\n"));
+
+ return HalpAdjustResourceListLimits (
+ BusHandler, RootHandler, pResourceList,
+ 0, 0xffffff, // Bus supports up to memory 0xFFFFFF
+ 0, 0, // No special range for prefetch
+ FALSE,
+ 0, 0xffff, // Bus supports up to I/O port 0xFFFF
+ Irq, 15, // Bus supports up to 15 IRQs
+ 0, 7 // Bus supports up to Dma channel 7
+ );
+}
+
+
+NTSTATUS
+HalpAdjustResourceListLimits (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN ULONG MinimumMemoryAddress,
+ IN ULONG MaximumMemoryAddress,
+ IN ULONG MinimumPrefetchMemoryAddress,
+ IN ULONG MaximumPrefetchMemoryAddress,
+ IN BOOLEAN LimitedIOSupport,
+ IN ULONG MinimumPortAddress,
+ IN ULONG MaximumPortAddress,
+ IN PUCHAR IrqTable,
+ IN ULONG IrqTableSize,
+ IN ULONG MinimumDmaChannel,
+ IN ULONG MaximumDmaChannel
+ )
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST InCompleteList, OutCompleteList;
+ PIO_RESOURCE_LIST InResourceList, OutResourceList;
+ PIO_RESOURCE_DESCRIPTOR InDesc, OutDesc, HeadOutDesc;
+ BOOLEAN GotPFRange, FirstDescBuilt;
+ ULONG len, alt, cnt, i;
+ UCHAR LastIrqState, NewIrqState;
+ ULONG PFAddress, icnt, pcnt;
+
+ HDBG(DBG_INTERNAL,
+ HalpDebugPrint("HalpAdjustResourceListLimits: BusHandler=0x%08x, ResList=0x%08x\n",
+ BusHandler, pResourceList););
+
+ InCompleteList = *pResourceList;
+ len = InCompleteList->ListSize;
+ PFAddress =
+ MinimumPrefetchMemoryAddress || MaximumPrefetchMemoryAddress ? 1 : 0;
+ icnt = 0;
+ pcnt = 0;
+
+ //
+ // Worste case, add an extra interrupt descriptor for every different
+ // IRQ range present
+ //
+
+ LastIrqState = 0;
+ for (i=0; i < IrqTableSize; i++) {
+ if (IrqTable[i] != LastIrqState) {
+ icnt += 1;
+ LastIrqState = IrqTable[i];
+ }
+ }
+
+ //
+ // If LimitiedIOSupport, then the supported I/O ranges are
+ // limited to 256bytes on every 1K aligned boundry within the
+ // range specified. Worste case add an extra N descriptors for
+ // every I/O range passed.
+ //
+
+ if (LimitedIOSupport && MaximumPortAddress > MinimumPortAddress) {
+ pcnt = (MaximumPortAddress - MinimumPortAddress) / 1024;
+ }
+
+ //
+ // Scan input list - verify revision #'s, and increase len varible
+ // by amount output list may increase.
+ //
+
+ i = 0;
+ InResourceList = InCompleteList->List;
+ for (alt=0; alt < InCompleteList->AlternativeLists; alt++) {
+ if (InResourceList->Version != 1 || InResourceList->Revision < 1) {
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sVersion is not 1, or revision is < 1.\n",
+ TBS););
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ InDesc = InResourceList->Descriptors;
+ for (cnt = InResourceList->Count; cnt; cnt--) {
+ switch (InDesc->Type) {
+ case CmResourceTypePort: i += pcnt; break;
+ case CmResourceTypeInterrupt: i += icnt; break;
+ case CmResourceTypeMemory: i += PFAddress; break;
+ case CmResourceTypeDma: break;
+ default:
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sINVALID PARAM ..InDesc->Type: 0x%x\n",
+ TBS,InDesc->Type););
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ // Next descriptor
+ InDesc++;
+ }
+
+ // Next Resource List
+ InResourceList = (PIO_RESOURCE_LIST) InDesc;
+ }
+ len += i * sizeof (IO_RESOURCE_DESCRIPTOR);
+
+ //
+ // Allocate output list
+ //
+
+ OutCompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST)
+ ExAllocatePool (PagedPool, len);
+
+ if (!OutCompleteList) {
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sOutCompleteList is null ( No memory? ) \n",TBS););
+ return STATUS_NO_MEMORY;
+ }
+
+ //
+ // Walk each ResourceList and build output structure
+ //
+
+ InResourceList = InCompleteList->List;
+ *OutCompleteList = *InCompleteList;
+ OutResourceList = OutCompleteList->List;
+
+ for (alt=0; alt < InCompleteList->AlternativeLists; alt++) {
+ OutResourceList->Version = 1;
+ OutResourceList->Revision = 1;
+
+ InDesc = InResourceList->Descriptors;
+ OutDesc = OutResourceList->Descriptors;
+ HeadOutDesc = OutDesc;
+
+ for (cnt = InResourceList->Count; cnt; cnt--) {
+
+ //
+ // Copy descriptor
+ //
+
+ *OutDesc = *InDesc;
+
+ //
+ // Limit desctiptor to be with the buses supported ranges
+ //
+
+ switch (OutDesc->Type) {
+ case CmResourceTypePort:
+ if (OutDesc->u.Port.MinimumAddress.QuadPart < MinimumPortAddress) {
+ OutDesc->u.Port.MinimumAddress.QuadPart = MinimumPortAddress;
+ }
+
+ if (OutDesc->u.Port.MaximumAddress.QuadPart > MaximumPortAddress) {
+ OutDesc->u.Port.MaximumAddress.QuadPart = MaximumPortAddress;
+ }
+
+ if (!LimitedIOSupport) {
+ break;
+ }
+
+ // In the case of LimitiedIOSupport the caller will only
+ // pass in 1K aligned values
+
+ FirstDescBuilt = FALSE;
+ for (i = MinimumPortAddress; i < MaximumPortAddress; i += 1024) {
+ if (InDesc->u.Port.MinimumAddress.QuadPart < i) {
+ OutDesc->u.Port.MinimumAddress.QuadPart = i;
+ }
+
+ if (InDesc->u.Port.MaximumAddress.QuadPart > i + 256) {
+ OutDesc->u.Port.MaximumAddress.QuadPart = i + 256;
+ }
+
+ if (OutDesc->u.Port.MinimumAddress.QuadPart <=
+ OutDesc->u.Port.MaximumAddress.QuadPart) {
+
+ //
+ // Valid I/O descriptor build, start another one.
+ //
+
+ FirstDescBuilt = TRUE;
+
+ OutDesc++;
+ *OutDesc = *InDesc;
+ OutDesc->Option |= IO_RESOURCE_ALTERNATIVE;
+ }
+ }
+
+ if (FirstDescBuilt) {
+ OutDesc--;
+ }
+ break;
+
+ case CmResourceTypeInterrupt:
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpAdjustResourceListLimits: new CmResourceTypeInterrupt \n"););
+
+ //
+ // Build a list of interrupt descriptors which are
+ // a subset of the IrqTable and the current descriptor
+ // passed in on the input list.
+ //
+
+ FirstDescBuilt = FALSE;
+ LastIrqState = 0;
+
+ for (i=0; i < IrqTableSize; i++) {
+ NewIrqState = IrqTable[i];
+
+ while (LastIrqState != NewIrqState) {
+ if (LastIrqState) {
+ OutDesc++; // done with last desc
+ LastIrqState = 0; // new state
+ continue;
+ }
+
+ //
+ // Start a new descriptor
+ //
+
+ *OutDesc = *InDesc;
+ OutDesc->u.Interrupt.MinimumVector = i;
+ if (NewIrqState & IRQ_PREFERRED) {
+ OutDesc->Option |= IO_RESOURCE_PREFERRED;
+ }
+
+ if (FirstDescBuilt) {
+ OutDesc->Option |= IO_RESOURCE_ALTERNATIVE;
+ }
+
+ LastIrqState = NewIrqState;
+ FirstDescBuilt = TRUE;
+ }
+
+ OutDesc->u.Interrupt.MaximumVector = i;
+ }
+
+ if (!LastIrqState) {
+ if (!FirstDescBuilt) {
+ OutDesc->u.Interrupt.MinimumVector =
+ IrqTableSize + 1;
+ } else {
+ OutDesc--;
+ }
+ }
+
+ break;
+
+ case CmResourceTypeMemory:
+ if (PFAddress && (OutDesc->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) ) {
+ //
+ // There's a Prefetch range & this resource supports
+ // Prefetching. Build two descriptors - one for the
+ // supported Prefetch range as preferred, and the other
+ // normal memory range.
+ //
+
+ OutDesc->Option |= IO_RESOURCE_PREFERRED;
+
+ if (OutDesc->u.Memory.MinimumAddress.QuadPart < MinimumPrefetchMemoryAddress) {
+ OutDesc->u.Memory.MinimumAddress.QuadPart = MinimumPrefetchMemoryAddress;
+ }
+
+ if (OutDesc->u.Memory.MaximumAddress.QuadPart > MaximumPrefetchMemoryAddress) {
+ OutDesc->u.Memory.MaximumAddress.QuadPart = MaximumPrefetchMemoryAddress;
+ }
+
+ GotPFRange = FALSE;
+ if (OutDesc->u.Memory.MaximumAddress.QuadPart >=
+ OutDesc->u.Memory.MinimumAddress.QuadPart) {
+
+ //
+ // got a valid descriptor in the Prefetch range, keep it,
+ //
+
+ OutDesc++;
+ GotPFRange = TRUE;
+ }
+
+ *OutDesc = *InDesc;
+
+ if (GotPFRange) {
+ // next descriptor is an alternative
+ OutDesc->Option |= IO_RESOURCE_ALTERNATIVE;
+ }
+ }
+
+ //
+ // Fill in memory descriptor for range
+ //
+
+ if (OutDesc->u.Memory.MinimumAddress.QuadPart < MinimumMemoryAddress) {
+ OutDesc->u.Memory.MinimumAddress.QuadPart = MinimumMemoryAddress;
+ }
+
+ if (OutDesc->u.Memory.MaximumAddress.QuadPart > MaximumMemoryAddress) {
+ OutDesc->u.Memory.MaximumAddress.QuadPart = MaximumMemoryAddress;
+ }
+ break;
+
+ case CmResourceTypeDma:
+ if (OutDesc->u.Dma.MinimumChannel < MinimumDmaChannel) {
+ OutDesc->u.Dma.MinimumChannel = MinimumDmaChannel;
+ }
+
+ if (OutDesc->u.Dma.MaximumChannel > MaximumDmaChannel) {
+ OutDesc->u.Dma.MaximumChannel = MaximumDmaChannel;
+ }
+ break;
+
+#if DBG
+ default:
+ DbgPrint ("HalAdjustResourceList: Unkown resource type\n");
+ break;
+#endif
+ }
+
+ //
+ // Next descriptor
+ //
+
+ InDesc++;
+ OutDesc++;
+ }
+
+ OutResourceList->Count = OutDesc - HeadOutDesc;
+
+ //
+ // Next Resource List
+ //
+
+ InResourceList = (PIO_RESOURCE_LIST) InDesc;
+ OutResourceList = (PIO_RESOURCE_LIST) OutDesc;
+ }
+
+ //
+ // Free input list, and return output list
+ //
+
+ ExFreePool (InCompleteList);
+
+ OutCompleteList->ListSize =
+ (ULONG) ((PUCHAR) OutResourceList - (PUCHAR) OutCompleteList);
+ *pResourceList = OutCompleteList;
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxmapio.c b/private/ntos/nthals/halfire/ppc/pxmapio.c
new file mode 100644
index 000000000..383fa1c05
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxmapio.c
@@ -0,0 +1,134 @@
+/*++
+
+Copyright (c) 1991 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:
+
+ pxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space for a POWER PC
+ system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Map interrupt acknowledge base address
+ Map SIO config base address
+ Remove RTC map - S-FOOT mapsthe RTC into the ISA I/O space
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxmapio.c $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:11:27 $
+ * $Locker: $
+ */
+
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapIoSpace)
+
+#endif
+
+
+BOOLEAN
+HalpMapIoControlSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ );
+
+//
+// Define global data used to locate the IO control space and the PCI config
+// space.
+//
+
+PVOID HalpInterruptBase;
+PVOID HalpPciConfigBase;
+PVOID HalpErrorAddressRegister;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O, planar control, and bus configuration
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Map bus/bridge I/O control space
+ //
+
+ if (!HalpMapIoControlSpace())
+ return FALSE;
+
+ //
+ // Map Planar I/O control space
+ //
+
+ if (!HalpMapPlanarSpace())
+ return FALSE;
+
+ //
+ // Map Bus configuration space
+ //
+
+ if (!HalpMapBusConfigSpace())
+ return FALSE;
+
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxmemctl.c b/private/ntos/nthals/halfire/ppc/pxmemctl.c
new file mode 100644
index 000000000..4dc541cad
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxmemctl.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxmemctl.c $
+ * $Revision: 1.16 $
+ * $Date: 1996/05/14 02:34:41 $
+ * $Locker: $
+ */
+
+/*++
+
+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)
+
+
+Revision History:
+
+
+
+--*/
+
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "phsystem.h"
+
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ )
+
+{
+ 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, than 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;
+
+
+ if ( HalpInterruptBase == NULL ) {
+ HalpInterruptBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+ }
+
+ if ( HalpSystemControlBase == NULL ) {
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = SYSTEM_CONTROL_SPACE;
+ HalpSystemControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+ }
+
+ //
+ // Map the error address register
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = ERROR_ADDRESS_REGISTER;
+ HalpErrorAddressRegister = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ if (HalpInterruptBase == NULL || HalpErrorAddressRegister == 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, than 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,
+ PCI_CONFIG_SIZE,
+ FALSE);
+
+ if (HalpPciConfigBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Map the PCI config space.
+ //
+
+ HalpPciConfigBase = (PUCHAR)KePhase0MapIo( (PVOID)PCI_CONFIG_PHYSICAL_BASE, 0x400000);
+
+ if (HalpPciConfigBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+VOID
+HalpPhase0UnMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Unmap the PCI config space and set HalpPciConfigBase to NULL.
+ //
+
+ KePhase0DeleteIoMap( (PVOID)PCI_CONFIG_PHYSICAL_BASE, 0x400000);
+ HalpPciConfigBase = NULL;
+
+}
+
+
diff --git a/private/ntos/nthals/halfire/ppc/pxmemctl.h b/private/ntos/nthals/halfire/ppc/pxmemctl.h
new file mode 100644
index 000000000..691535694
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxmemctl.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxmemctl.h $
+ * $Revision: 1.10 $
+ * $Date: 1996/05/14 02:34:45 $
+ * $Locker: $
+ */
+
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxmemctl.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ on Masters systems.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+--*/
+#ifndef _PXMEMCTL_H
+#define _PXMEMCTL_H
+
+//
+// define physical base addresses of planar
+//
+#define SYSTEM_REGISTER_SPACE 0xff000000 // where the system registers
+ // live
+#define INTERRUPT_PHYSICAL_BASE 0xff000000 // sys interrupt register area
+#define SYSTEM_PCI_CONFIG_BASE 0xff400000 // sys pci config space
+#define ERROR_ADDRESS_REGISTER 0xff000400
+#define ERROR_STATUS_REGISTER 0xff001000
+#define SYSTEM_CONTROL_SPACE 0xff100000 // system control registers
+#define SYSTEM_CONTROL_SIZE 0x2000 // address range covered
+#define DISPLAY_MEMORY_BASE 0x70000000 // display memory start
+#define DISPLAY_MEMORY_SIZE 0x400000 // 4 MB for pro and top
+
+//
+// OFFSETS
+//
+#define INTERRUPT_OFFSET 0x000000 // offset from system base
+#define SYSTEM_CONTROL_OFFSET 0x100000 // offset from system base
+#define IO_MEMORY_PHYSICAL_BASE 0xC0000000 // physical base of IO memory
+
+
+#define IO_CONTROL_PHYSICAL_BASE 0x80000000 // physical base of IO control
+#define SYSTEM_IO_CONTROL_SIZE 0x00008000
+
+#define PCI_CONFIG_PHYSICAL_BASE 0x80800000 // physical base of PCI config space
+// used to be:
+// #define PCI_CONFIG_SIZE PAGE_SIZE * 9 // for FIREPOWER
+// #define PCI_CONFIG_SIZE PAGE_SIZE * 5 // for PPC
+#define PCI_CONFIG_SIZE 0x00800000
+
+#endif // _PXMEMCTL_H
diff --git a/private/ntos/nthals/halfire/ppc/pxmisc.s b/private/ntos/nthals/halfire/ppc/pxmisc.s
new file mode 100644
index 000000000..52ed5c5ec
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxmisc.s
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxmisc.s $
+ * $Revision: 1.7 $
+ * $Date: 1996/01/11 07:11:46 $
+ * $Locker: $
+ */
+
+//++
+//
+// Copyright (c) 1993 IBM 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:
+//
+// pxmisc.s
+//
+// Abstract:
+//
+// This module implements miscellaneous routines on the PowerPC.
+//
+// Author:
+//
+// Steve Johns (sjohns@pets.sps.mot.com) August 1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+
+#include "kxppc.h"
+
+ .set HID0, 1008 // SPR # for HID0
+
+
+ LEAF_ENTRY(HalpGetHID0)
+
+ mfspr r.3, HID0
+
+ LEAF_EXIT(HalpGetHID0)
+
+
+
+
+ LEAF_ENTRY(HalpSetHID0)
+
+ mtspr HID0, r.3
+
+ LEAF_EXIT(HalpSetHID0)
+
+
+ LEAF_ENTRY(HalpSetDecrementer)
+
+ mtdec r.3 // Set the DECREMENTER
+
+ LEAF_EXIT(HalpSetDecrementer)
+
+
+
+
+//
+// HalpLockDisplayString
+//
+// This routine implements a lock on the HalDisplayString function
+// to avoid garbling the display when more than one processor attempts
+// to display a string at the same time.
+//
+// r.3 is the address of the lock.
+//
+
+ LEAF_ENTRY(HalpLockDisplayString)
+
+ li r.5, 1
+ lis r.6, 0x99
+LkDis: lwarx r.4, 0, r.3
+ addic. r.6, r.6, -1
+ beq LkSync
+ cmpwi r.4, 0
+ bne- LkDis // jif lock already held
+ stwcx. r.5, 0, r.3 // attempt to take lock
+ sync
+ beqlr+ // return if all was good
+
+//
+// We lost the reserve, allow the other processor a chance to
+// win this argument.
+//
+
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ sync
+ b LkDis
+
+LkSync:
+ stw r.5, 0(r.3) // Grab the lock anyway
+ LEAF_EXIT(HalpLockDisplayString)
+
+
+
+// ULONG HalpDivide (
+// IN ULARGE_INTEGER Dividend,
+// IN ULONG Divisor)
+//
+// Routine Description:
+//
+// This function divides an unsigned large integer by an unsigned long
+// and returns the resultant quotient and optionally the remainder.
+//
+// N.B. It is assumed that no overflow will occur.
+//
+// Arguments:
+//
+// Dividend (r.3, r.4) - Supplies the dividend value.
+// (High-order bits in r.4, low-order bits in r.3)
+//
+// Divisor (r.5) - Supplies the divisor value.
+//
+// Return Value:
+//
+// The ULONG quotient is returned as the function value.
+//
+//--
+
+
+
+ .set Quotient, r.3
+ .set DividendLo, r.3
+ .set DividendHi, r.4
+ .set Divisor, r.5
+ .set Q1, r.11
+ .set N, r.12
+ .set Q0, N // Use of N & Q0 don't overlap
+
+ LEAF_ENTRY(HalpDivide)
+
+
+ cmplw DividendHi,Divisor
+ bge overflow // catch overflow or division by 0
+ cmplwi DividendHi,0 // test high part for 0
+ bne Divide64Bits
+
+// High 32 bits of Dividend == 0, so use 32 bit division.
+ divwu DividendLo,DividendLo,Divisor // result <- dividend / divisor
+ blr
+
+Divide64Bits:
+
+// Normalize: Shift divisor and dividend left to get rid of leading zeroes
+// in the divisor. Since DividendHi < Divisor, only zeroes are shifted out
+// of the dividend.
+ cntlzw N,Divisor // number of bits to shift (N)
+ slw Divisor,Divisor,N // shift divisor
+ slw DividendHi,DividendHi,N // shift upper part of divisor
+ mr r.8, DividendLo // Save unshifted DividendLo
+ slw DividendLo,DividendLo,N // shift lower part of divisor
+ subfic N,N,32 // 32-N
+ srw N,r.8,N // leftmost N bits of DividendLo, slid right
+ or DividendHi,DividendHi,N // and inserted into low end of DividendHi
+
+// Estimate high-order halfword of quotient. If the dividend is
+// A0 A1 A2 A3 and the divisor is B0 B1 (where each Ai or Bi is a halfword),
+// then the estimate is A0 A1 0000 divided by B0 0000, or A0 A1 divided by B0.
+// (DividendHi holds A0 A1, DividendLo holds A2 A3, and Divisor holds B0 B1.)
+// The estimate may be too high because it does not account for B1; in rare
+// cases, the estimate will not even fit in a halfword. High estimates are
+// corrected for later.
+ srwi r.8,Divisor,16 // r.8 <- B0
+ divwu Q0,DividendHi,r.8 // Q0 <- floor([A0 A1]/B0)
+// Subtract partial quotient times divisor from dividend: If Q0 is the quotient
+// computed above, this means that Q0 0000 times B0 B1 is subtracted from
+// A0 A1 A2 A3. We compute Q0 times B0 B1 and then shift the two-word
+// product left 16 bits.
+ mullw r.9,Q0,Divisor // low word of Q0 times B0 B1
+ mulhwu r.10,Q0,Divisor // high word of Q0 times B0 B1
+ slwi r.10,r.10,16 // shift high word left 16 bits
+ inslwi r.10,r.9,16,16 // move 16 bits from left of low word
+ // to right of high word
+ slwi r.9,r.9,16 // shift low word left 16 bits
+ subfc DividendLo,r.9,DividendLo // low word of difference
+ subfe DividendHi,r.10,DividendHi // high word of difference
+// If the estimate for Q0 was too high, the difference will be negative.
+// While A0 A1 A2 A3 is negative, repeatedly add B0 B1 0000 to A0 A1 A2 A3
+// and decrement Q0 by one to correct for the overestimate.
+ cmpwi DividendHi,0 // A0 A1 A2 A3 is negative iff A0 A1 is
+ bge Q0_okay // no correction needed
+ inslwi r.10,Divisor,16,16 // high word of B0 B1 0000 (= 0000 B0)
+ slwi r.9,Divisor,16 // low word of B0 B1 0000 (= B1 0000)
+adjust_Q0:
+ addc DividendLo,DividendLo,r.9 // add B0 B1 0000 to A0 A1 A2 A3 (low)
+ adde DividendHi,DividendHi,r.10 // add B0 B1 0000 to A0 A1 A2 A3 (high)
+ cmpwi DividendHi,0 // Is A0 A1 A2 A3 now nonnegative?
+ addi Q0,Q0,-1 // decrement Q0
+ blt adjust_Q0 // if A0 A1 A2 A3 still negative, repeat
+Q0_okay:
+// Estimate low-order halfword of quotient. A0 is necessarily 0000 at this
+// point, so if the remaining part of the dividend is A0 A1 A2 A3 then the
+// estimate is A1 A2 0000 divided by B0 0000, or A1 A2 divided by B0.
+// (DividendHi holds A0 A1, DividendLo holds A2 A3, and r.8 holds B0.)
+ slwi r.9,DividendHi,16 // r.9 <- A1 0000
+ inslwi r.9,DividendLo,16,16 // r.9 <- A1 A2
+ divwu Q1,r.9,r.8 // Q1 <- floor([A1 A2]/B0)
+// Subtract partial quotient times divisor from remaining part of dividend:
+// If Q1 is the quotient computed above, this means
+// that Q1 times B0 B1 is subtracted from A0 A1 A2 A3. We compute
+ mullw r.9,Q1,Divisor // low word of Q1 times B0 B1
+ mulhwu r.10,Q1,Divisor // high word of Q1 times B0 B1
+ subfc DividendLo,r.9,DividendLo // low word of difference
+ subfe DividendHi,r.10,DividendHi // high word of difference
+// If the estimate for Q1 was too high, the difference will be negative.
+// While A0 A1 A2 A3 is negative, repeatedly add B0 B1 to A0 A1 A2 A3
+// and decrement Q1 by one to correct for the overestimate.
+ cmpwi DividendHi,0 // A0 A1 A2 A3 is negative iff A0 A1 is
+ bge Q1_okay // no correction needed
+adjust_Q1:
+ addc DividendLo,DividendLo,Divisor // add B0 B1 to A0 A1 A2 A3 (low)
+ addze DividendHi,DividendHi // add B0 B1 to A0 A1 A2 A3 (high)
+ cmpwi DividendHi,0 // Is A0 A1 A2 A3 now nonnegative?
+ addi Q1,Q1,-1 // decrement Q1
+ blt adjust_Q1 // if A0 A1 A2 A3 still negative, repeat
+Q1_okay:
+ slwi Quotient,Q0,16 // Quotient <- Q0 A1
+ or Quotient,Quotient,Q1
+ blr
+
+
+// The error cases:
+overflow:
+ li Quotient, 0 // return(0);
+ LEAF_EXIT(HalpDivide)
+
+
+
+
+// ULARGE_INTEGER HalpMultiply (
+// IN ULONG Multiplicand,
+// IN ULONG Multiplier)
+//
+// Routine Description:
+//
+// This function multiplies two ULONGS and returns a ULARGE_INTEGER product.
+//
+// N.B. It is assumed that no overflow will occur.
+//
+// Arguments:
+//
+// Multiplicand (r.4) - Supplies the multiplicand value.
+//
+// Multiplier (r.5) - Supplies the multiplier value.
+//
+// Return Value:
+//
+// The ULARGE_INTEGER product is returned as the function value.
+//
+
+ .set Multiplicand, r.4
+ .set Multiplier, r.5
+ .set Product, r.3
+
+
+ LEAF_ENTRY(HalpMultiply)
+
+ mullw r.0, Multiplicand, Multiplier // Calculate low 32 bits
+ stw r.0, 0(Product)
+ mulhwu r.0, Multiplicand, Multiplier // Calculate high 32 bits
+ stw r.0, 4(Product)
+
+ LEAF_EXIT(HalpMultiply)
+
diff --git a/private/ntos/nthals/halfire/ppc/pxnatsup.c b/private/ntos/nthals/halfire/ppc/pxnatsup.c
new file mode 100644
index 000000000..94452fcdc
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxnatsup.c
@@ -0,0 +1,90 @@
+
+/*++
+
+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:
+
+ pxnatsup.c
+
+Abstract:
+
+ The module provides the National SuperIO (PC87311) support for Power PC.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxnatsup.c $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:11:59 $
+ * $Locker: $
+ */
+
+#include "halp.h"
+#include "pxnatsup.h"
+
+
+
+BOOLEAN
+HalpInitSuperIo (
+ VOID
+ )
+
+
+{
+
+ //
+ // Initialize the National SuperIO chip
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoIndexRegister,
+ FER_ACCESS);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoDataRegister,
+ FER_PARALLEL_PORT_ENABLE |
+ FER_UART1_ENABLE |
+ FER_UART2_ENABLE |
+ FER_FDC_ENABLE |
+ FER_IDE);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoIndexRegister,
+ FAR_ACCESS);
+
+ //
+ // LPT2 - irq5, uart1-com1, UART2-com2,
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoDataRegister,
+ 0x10);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoIndexRegister,
+ PTR_ACCESS);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoDataRegister,
+ 0x04);
+
+ return TRUE;
+
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxnatsup.h b/private/ntos/nthals/halfire/ppc/pxnatsup.h
new file mode 100644
index 000000000..5c30c5a83
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxnatsup.h
@@ -0,0 +1,67 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxnatsup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the
+ National (PC87311) SuperIO chip set.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxnatsup.h $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:12:05 $
+ * $Locker: $
+ */
+
+//
+// SuperIO configuration registers
+//
+
+//
+//index register select
+//
+
+#define FER_ACCESS 0x00
+#define FAR_ACCESS 0x01
+#define PTR_ACCESS 0x02
+
+//
+//FER register bit fields
+//
+
+#define FER_PARALLEL_PORT_ENABLE 0x01
+#define FER_UART1_ENABLE 0x02
+#define FER_UART2_ENABLE 0x04
+#define FER_FDC_ENABLE 0x08
+#define FER_FDD 0x10
+#define FER_FDC_MODE 0x20
+#define FER_IDE 0x30
+#define FER_IDE_MODE 0x40
+
+//
+// Lay the supio control registers onto the I/O control space
+//
+
+typedef struct _NAT_SUPERIO_CONTROL {
+ UCHAR Reserved1[0x398];
+ UCHAR SuperIoIndexRegister; // Offset 0x398
+ UCHAR SuperIoDataRegister; // Offset 0x399
+} NAT_SUPERIO_CONTROL, *PNAT_SUPERIO_CONTROL;
diff --git a/private/ntos/nthals/halfire/ppc/pxnvrsup.h b/private/ntos/nthals/halfire/ppc/pxnvrsup.h
new file mode 100644
index 000000000..d719b05b5
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxnvrsup.h
@@ -0,0 +1,35 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxnvrsup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the NVRAM support
+ in a PowerPC System.
+
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxnvrsup.h $
+ * $Revision: 1.8 $
+ * $Date: 1996/05/14 02:34:50 $
+ * $Locker: $
+ */
+
+#include "fpds1385.h"
diff --git a/private/ntos/nthals/halfire/ppc/pxpcibus.c b/private/ntos/nthals/halfire/ppc/pxpcibus.c
new file mode 100644
index 000000000..dd578510f
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxpcibus.c
@@ -0,0 +1,2327 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxpcibus.c $
+ * $Revision: 1.32 $
+ * $Date: 1996/05/14 02:34:54 $
+ * $Locker: $
+ */
+
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxpcidat.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+ Jim Wooldridge Port to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxpcisup.h"
+
+#include "pxidaho.h"
+
+#include "phsystem.h"
+#include "fpio.h"
+#include "stdio.h"
+#include "string.h"
+#include "fpdebug.h"
+
+#define TBS " "
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+extern ULONG HalpAdjustBridge(PBUS_HANDLER, PPCI_COMMON_CONFIG, PCM_RESOURCE_LIST );
+
+//
+// Prototypes
+//
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ );
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+//-------------------------------------------------
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+
+PCI_CONFIG_HANDLER PCIConfigHandler;
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType1 = {
+ HalpPCISynchronizeType1,
+ HalpPCIReleaseSynchronzationType1,
+ {
+ HalpPCIReadUlongType1, // 0
+ HalpPCIReadUcharType1, // 1
+ HalpPCIReadUshortType1 // 2
+ },
+ {
+ HalpPCIWriteUlongType1, // 0
+ HalpPCIWriteUcharType1, // 1
+ HalpPCIWriteUshortType1 // 2
+ }
+};
+
+PCI_CONFIG_HANDLER PCIConfigHandlerType2 = {
+ HalpPCISynchronizeType2,
+ HalpPCIReleaseSynchronzationType2,
+ {
+ HalpPCIReadUlongType2, // 0
+ HalpPCIReadUcharType2, // 1
+ HalpPCIReadUshortType2 // 2
+ },
+ {
+ HalpPCIWriteUlongType2, // 0
+ HalpPCIWriteUcharType2, // 1
+ HalpPCIWriteUshortType2 // 2
+ }
+};
+
+extern PCI_CONFIG_HANDLER PCIConfigHandlerBridged;
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ );
+
+#if DBG
+#define DBGMSG(a) HalpPrint(a)
+VOID
+HalpTestPci (
+ ULONG
+ );
+#else
+#define DBGMSG(a)
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePciBus)
+#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
+#pragma alloc_text(INIT,HalpIsValidPCIDevice)
+#endif
+
+VOID
+HalpInitializePciBus (
+ VOID
+ )
+{
+ PCI_REGISTRY_INFO FirePCIRegInfo;
+ PPCI_REGISTRY_INFO PCIRegInfo = NULL;
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status = STATUS_SEVERITY_INFORMATIONAL;
+ UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
+ PWSTR p;
+ WCHAR wstr[8];
+ ULONG i, d, junk, HwType;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PKEY_VALUE_FULL_INFORMATION ValueInfo;
+ PCM_FULL_RESOURCE_DESCRIPTOR Desc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
+
+
+ //
+
+ //
+ // Search the hardware description looking for any reported
+ // PCI bus. The first ARC entry for a PCI bus will contain
+ // the PCI_REGISTRY_INFO.
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL, // handle
+ NULL);
+
+
+ status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ HalDisplayString("HalpInitializePCIBus: ZwOpenKey returned !NT_SUCCESS \n");
+ return;
+ }
+
+ unicodeString.Buffer = wstr;
+ unicodeString.MaximumLength = sizeof (wstr);
+
+ RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
+ RtlInitUnicodeString (&IdentName, rgzIdentifier);
+
+ ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
+
+ for (i=0; TRUE; i++) {
+ RtlIntegerToUnicodeString (i, 10, &unicodeString);
+ InitializeObjectAttributes (
+ &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ hMFunc,
+ NULL);
+
+ status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ //
+ // Out of Multifunction adapter entries...
+ //
+ ZwClose (hMFunc);
+ break;
+ }
+
+ //
+ // Check the Indentifier to see if this is a PCI entry
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &IdentName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ if (!NT_SUCCESS (status)) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
+ if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
+ ZwClose (hBus);
+ continue;
+ }
+
+ //
+ // The first PCI entry has the PCI_REGISTRY_INFO structure
+ // attached to it.
+ //
+
+ status = ZwQueryValueKey (
+ hBus,
+ &ConfigName,
+ KeyValueFullInformation,
+ ValueInfo,
+ sizeof (buffer),
+ &junk
+ );
+
+ ZwClose (hBus);
+ if (!NT_SUCCESS(status)) {
+ continue ;
+ }
+
+ Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ ValueInfo + ValueInfo->DataOffset);
+ PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
+ Desc->PartialResourceList.PartialDescriptors);
+
+ if (PDesc->Type == CmResourceTypeDeviceSpecific) {
+ // got it..
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ break;
+ }
+ }
+
+
+ if(PCIRegInfo == NULL) {
+
+ //
+ // FirePower only has one PCI bus.
+ //
+ PCIRegInfo = &FirePCIRegInfo;
+ PCIRegInfo->NoBuses = 1;
+ PCIRegInfo->HardwareMechanism = 1;
+ }
+
+
+ //
+ // Initialize spinlock for synchronizing access to PCI space
+ //
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+
+
+ //
+ // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
+ //
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+ //
+ // Some AMI bioses claim machines are Type2 configuration when they
+ // are really type1. If this is a Type2 with at least one bus,
+ // try to verify it's not really a type1 bus
+ //
+
+ if (PCIRegInfo->NoBuses && HwType == 2) {
+ HalpDebugPrint("HalpInitializePCIBus: Setting HwType = 2 \n");
+
+ //
+ // Check each slot for a valid device. Which every style configuration
+ // space shows a valid device first will be used
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ SlotNumber.u.bits.FunctionNumber = 0;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ //
+ // First try what the BIOS claims - type 2. Allocate type2
+ // test handle for PCI bus 0.
+ //
+
+ HwType = 2;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ //
+ // Valid device not found on Type2 access for this slot.
+ // Reallocate the bus handler are Type1 and take a look.
+ //
+
+ HwType = 1;
+ BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
+
+ if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
+ break;
+ }
+
+ HwType = 2;
+ }
+
+ //
+ // Reset handler for PCI bus 0 to whatever style config space
+ // was finally decided.
+ //
+
+ HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
+ }
+
+
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+ for (i=0; i < PCIRegInfo->NoBuses; i++) {
+
+
+ //
+ // If handler not already built, do it now
+ //
+ if (!HalpHandlerForBus (PCIBus, i)) {
+ HalpDebugPrint("HalpInitializePciBus: Alloc PCI bus: 0x%0x\n",i);
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ //
+
+
+#if DBG
+ HalpTestPci (0);
+#endif
+ //return;
+}
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+ PFPHAL_BUSNODE FpBusData;
+
+ HDBG(DBG_PCI,
+ HalpDebugPrint("HalpAllocAndInit: HwType=0x%x, BusNo=%x, TestAlloc=%x\n"
+ ,HwType, BusNo, TestAllocation););
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // bus #
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (FPHAL_BUSNODE) // FirePower hal bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+ if (!Bus) {
+ HalpDebugPrint("HalpAllocAndInit: No bus handler ...\n");
+ return (PBUS_HANDLER) NULL;
+ }
+
+ HDBG(DBG_PCI,
+ HalpDebugPrint("HalpAllocateAndInitPciBusHandler:@0x%08x \n", Bus->BusData););
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->TranslateBusAddress = (PTRANSLATEBUSADDRESS) HalpTranslatePCIBusAddress;
+
+ FpBusData = (PFPHAL_BUSNODE) Bus->BusData;
+ BusData = (PPCIPBUSDATA) &(FpBusData->Bus);
+ HDBG(DBG_PCI,
+ HalpDebugPrint("HalpAllocateAndInitPciBusHandler:@0x%08x \n", BusData););
+
+ //
+ // Fill in common PCI data
+ //
+
+ BusData->CommonData.Tag = PCI_DATA_TAG;
+ BusData->CommonData.Version = PCI_DATA_VERSION;
+ BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig;
+ BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig;
+ BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine;
+ BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
+
+ FpBusData->HwType = HwType;
+
+ // set defaults
+ BusData->LimitedIO = FALSE;
+ BusData->IOLimit = 0x3F7FFFFF;
+ BusData->MemoryLimit = 0x3EFFFFFF;
+ BusData->GetIrqTable = (PciIrqTable) HalpGetISAFixedPCIIrq;
+
+ RtlInitializeBitMap (&FpBusData->Bus.DeviceConfigured,
+ FpBusData->Bus.ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 0:
+ //
+ // This case allows the hal to initialize buses without setting
+ // any PCIConfigHandler. The confighandlers can then be setup
+ // elsewhere
+ //
+ HalpDebugPrint(" Case 0:...\n");
+ break;
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ //
+
+ HDBG(DBG_PCI,
+ HalpDebugPrint(" Case 1:...\n"););
+ RtlCopyMemory ( &(FpBusData->Node),
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+ FpBusData->Bus.MaxDevice = MAXIMUM_PCI_SLOTS -1; // 0 based *BJ*
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ //
+
+ RtlCopyMemory ( &(FpBusData->Node),
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+
+
+ //
+ // Early PCI machines didn't decode the last bit of
+ // the device id. Shrink type 2 support max device.
+ //
+ FpBusData->Bus.MaxDevice = MAXIMUM_PCI_SLOTS -1;
+
+ break;
+ case 3:
+ //
+ // Initialize this bus as a bridged bus: I.E. this pci bus goes
+ // through a bridge.
+ //
+
+ RtlCopyMemory ( &(FpBusData->Node),
+ &PCIConfigHandlerBridged,
+ sizeof (PCIConfigHandler));
+ FpBusData->Bus.MaxDevice = MAXIMUM_PCI_SLOTS -1; // 0 based *BJ*
+ break;
+
+ default:
+ // unsupport type
+ DBGMSG ("HAL: Unknown PCI type\n");
+ }
+
+ if (!TestAllocation) {
+ }
+
+ return Bus;
+}
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG i, j;
+
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Read device common header
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Valid device header?
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ return FALSE;
+ }
+
+ //
+ // Check fields for reasonable values
+ //
+
+ if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
+ (PciData->u.type0.InterruptLine & 0x70)) {
+ return FALSE;
+ }
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ j = PciData->u.type0.BaseAddresses[i];
+
+ if (j & PCI_ADDRESS_IO_SPACE) {
+ if (j > 0xffff) {
+ // IO port > 64k?
+ return FALSE;
+ }
+ } else {
+ if (j > 0xf && j < 0x80000) {
+ // Mem address < 0x8000h?
+ return FALSE;
+ }
+ }
+
+ if (Is64BitBaseAddress(j)) {
+ i += 1;
+ }
+ }
+
+ //
+ // Guess it's a valid device..
+ //
+
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description: ULONG HalpGetPCIData ()
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+ BusNumber - Indicates which bus.
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Supplies the starting location within config space for requested
+ data. It's an address relative to the start of the config header.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+ If this PCI slot has never been set, then the configuration information
+ returned is zeroed.
+
+
+--*/
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ PFPHAL_BUSNODE FpNode;
+ ULONG Len;
+#if DBG != 0
+ ULONG i, bit;
+#endif
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ BusData = (PPCIPBUSDATA) &(FpNode->Bus); // ZZZ
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line ((PBUS_HANDLER) BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Has this PCI device been configured?
+ //
+
+#if DBG
+ //
+ // On DBG build, if this PCI device has not yet been configured,
+ // then don't report any current configuration the device may have.
+ //
+
+ bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) {
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ PciData->u.type0.BaseAddresses[i] = 0;
+ }
+
+ PciData->u.type0.ROMBaseAddress = 0;
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ }
+#endif
+
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+/*++
+
+Routine Description: ULONG HalpSetPCIData ()
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ PFPHAL_BUSNODE FpNode;
+ ULONG Len;
+#if DBG != 0
+ ULONG cnt;
+#endif
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ BusData = (PPCIPBUSDATA) &(FpNode->Bus); // ZZZ
+#if DBG
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line ((PBUS_HANDLER) BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->CommonData.Line2Pin ((PBUS_HANDLER) BusHandler, RootHandler, Slot, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ HalpPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ PFPHAL_BUSNODE FpNode;
+
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+ //
+ // Pull the "methods" this bus uses to get and set
+ // data. It's now appended to the bus data
+ //
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ FpNode->Node.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ PFPHAL_BUSNODE FpNode;
+
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ FpNode->Node.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ PFPHAL_BUSNODE FpNode;
+ UCHAR HeaderType;
+ ULONG i;
+
+
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ BusData = (PPCIPBUSDATA) &(FpNode->Bus); // ZZZ
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.DeviceNumber > BusData->MaxDevice) {
+ return FALSE;
+ }
+
+ i = Slot.u.bits.DeviceNumber;
+
+ if ( !((FpNode->ValidDevs) & ( 1 << i )) ) {
+ //
+ // check the valid devs bitmap and see if this slot
+ // is marked.
+ //
+ //PRNTPCI(HalpDebugPrint("HalpValidPCISlot: Invalid dev (0x%08x) @%x\n",
+ // FpNode->ValidDevs, i));
+ return FALSE;
+ }
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Sandalfoot doesn't support Multifunction adapters
+ //
+
+// return FALSE;
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+ PFPHAL_BUSNODE FpNode;
+
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ BusData = (PPCIPBUSDATA) &FpNode->Bus;
+ FpNode->Node.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+
+ i = RPciVendorId(0);
+
+ }
+ FpNode->Node.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Initialize PciCfg1
+ //
+
+// PciCfg1->u.AsULONG = (PUCHAR) HalpPciConfigBase + HalpPciConfigSlot[Slot.u.bits.DeviceNumber];
+ //
+ // The HalpPciConfigBase value just happens to satisfy the requirements of
+ // pci config space addressing: The word written out says this is a write
+ // enabling config space mapping on bus number 1.
+ //
+ // The value pulled out of HalpPciConfigSlot determines the device/function
+ // number and sets the register number ( which of the 32 config space words)
+ // to access
+ //
+ PciCfg1->u.AsULONG = (ULONG) HalpPciConfigBase + HalpPciConfigSlot[Slot.u.bits.DeviceNumber];
+
+}
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+
+}
+
+
+ULONG
+HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfg1->u.AsULONG + i));
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT)(PciCfg1->u.AsULONG + i));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfg1->u.AsULONG));
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_UCHAR (PciCfg1->u.AsULONG + i, *Buffer );
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_USHORT (PciCfg1->u.AsULONG + i, *((PUSHORT) Buffer) );
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (PciCfg1->u.AsULONG, *((PULONG) Buffer) );
+ return sizeof (ULONG);
+}
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = 0;
+ PciCfg1->u.bits.BusNumber = BusHandler->BusNumber;
+ PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber ?
+ Slot.u.bits.DeviceNumber + 10:
+ Slot.u.bits.DeviceNumber ;
+ PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciCfg1->u.bits.Enable = TRUE;
+
+ KeRaiseIrql (PROFILE_LEVEL, Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+
+
+
+}
+
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+}
+
+
+ULONG
+HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ *((PUCHAR) Buffer) = READ_PORT_UCHAR ((PUCHAR)&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigData + i);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUCHAR)&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigData + i);
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigData);
+ return sizeof(ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ WRITE_PORT_UCHAR ((PUCHAR)&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigData + i,*Buffer);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ WRITE_PORT_USHORT ((PUCHAR)&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigData + (USHORT) i,*((PUSHORT)Buffer));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG (&((PIDAHO_CONTROL)HalpIoControlBase)->ConfigData,*((PULONG)Buffer));
+ return sizeof(ULONG);
+}
+
+/*++
+
+Routine Description: NTSTATUS HalpAssignPCISlotResources ()
+
+ Reads the targeted device to determine it's required resources.
+ Calls IoAssignResources to allocate them.
+ Sets the targeted device with it's assigned resoruces
+ and returns the assignments to the caller.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN ULONG Slot,
+ IN OUT PCM_RESOURCE_LIST *pAllocatedResources
+ )
+{
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ PFPHAL_BUSNODE FpNode;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG BusNumber;
+ ULONG i, j, m, length, memtype;
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase;
+
+
+ PRNTPCI(HalpDebugPrint(
+ "HalpAssignPCISlotResources: BusHandler: 0x%x, Slot: 0x%x\n",
+ (ULONG)BusHandler, (ULONG)Slot ));
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+ BusNumber = BusHandler->BusNumber;
+// PRNTPCI(DbgBreakPoint());
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ BusData = (PPCIPBUSDATA) &(FpNode->Bus); // ZZZ
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ (sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2) +
+ PCI_COMMON_HDR_LENGTH * 3;
+ i *= 3;
+
+ //
+ // triple the calculated size just to make sure we don't run out of
+ // space.
+ //
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_NO_MEMORY;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i -
+ PCI_COMMON_HDR_LENGTH * 3);
+ PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i -
+ PCI_COMMON_HDR_LENGTH * 2);
+ PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i -
+ PCI_COMMON_HDR_LENGTH * 1);
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ ExFreePool (WorkingPool);
+ HalpDebugPrint("No such device found\n");
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // Make a copy of the device's current settings
+ //
+
+ RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ switch (PCI_CONFIG_TYPE(PciData)) {
+ case 0 :
+ NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
+ RomIndex = j;
+ break;
+ case 1:
+ NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
+ for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
+ BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
+ OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
+ }
+ BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
+ OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
+ RomIndex = j;
+ break;
+
+ default:
+ HalpDebugPrint("No such device of this type: %x \n",
+ PCI_CONFIG_TYPE(PciData));
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ //
+ // If the BIOS doesn't have the device's ROM enabled, then we won't
+ // enable it either. Remove it from the list.
+ //
+
+ EnableRomBase = TRUE;
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+
+ //
+ // Set resources to all bits on to see what type of resources
+ // are required.
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ *BaseAddress[j] = 0xFFFFFFFF;
+ }
+
+//*BJ* PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+ HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and
+ // InterruptLine
+ //
+ BusData->CommonData.Pin2Line ( (PBUS_HANDLER) BusHandler,
+ RootHandler,
+ PciSlot,
+ PciData
+ );
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = PCIBus;
+ CompleteList->BusNumber = BusNumber;
+ CompleteList->SlotNumber = Slot;
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ CompleteList->List[0].Count++;
+
+ Descriptor->Option = 0;
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ // Fill in any vector here - we'll pick it back up in
+ // HalAdjustResourceList and adjust it to it's allowed settings
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+ Descriptor++;
+ } else {
+ PRNTINTR(HalpDebugPrint("%sDevice(%x,%x) has no interrupt resource\n",
+ TBS, Slot, BusNumber));
+ PRNTINTR(HalpDebugPrint("\t\tPciData: 0x%x\n",PciData));
+ }
+
+ //
+ // Add a memory/port resoruce for each PCI resource
+ //
+
+ // Clear ROM reserved bits
+
+ *BaseAddress[RomIndex] &= ~0x7ff;
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+ PRNTPCI(HalpDebugPrint("PCI: BaseAddress[%d] = %08lx\n", j, i));
+
+ // scan for first set bit, that's the length & alignment
+ length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
+ while (!(i & length) && length) {
+ length <<= 1;
+ }
+
+ // scan for last set bit, that's the maxaddress + 1
+ for (m = length; i & m; m <<= 1) ;
+ m--;
+
+ //
+ // check for hosed PCI configuration requirements:
+ //
+ if (length & ~m) {
+#if DBG
+ HalpPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+ HalpPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
+#endif
+ // the device is in error - punt. don't allow this
+ // resource any option - it either gets set to whatever
+ // bits it was able to return, or it doesn't get set.
+
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m = i & ~0x3;
+ Descriptor->u.Port.MinimumAddress.LowPart = m;
+ } else {
+ m = i & ~0xf;
+ Descriptor->u.Memory.MinimumAddress.LowPart = m;
+ }
+
+ m += length; // max address is min address + length
+ }
+
+ //
+ // Add requested resource
+ //
+
+ Descriptor->Option = 0;
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ memtype = 0;
+
+ if (PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
+
+ //
+ // The IO range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+ PRNTPCI(HalpDebugPrint("FpNode: 0x%x ( %x:%x )\n",
+ FpNode, FpNode->MemBase,m));
+ if( FpNode->IoTop < m ) {
+ Descriptor->u.Port.MinimumAddress.LowPart =
+ FpNode->IoBase;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ FpNode->IoTop | 0xfff;
+ PRNTINTR(HalpDebugPrint("HalpAssignPciSlot........%x, %x\n",
+ Descriptor->u.Port.MinimumAddress.LowPart,
+ Descriptor->u.Port.MaximumAddress.LowPart));
+ }
+
+ } else {
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+ PRNTPCI(HalpDebugPrint("FpNode: 0x%x ( %x:%x )\n",
+ FpNode, FpNode->MemBase,m));
+ if( FpNode->MemTop < m ) {
+ Descriptor->u.Memory.MinimumAddress.LowPart =
+ FpNode->MemBase;
+ Descriptor->u.Memory.MaximumAddress.LowPart =
+ FpNode->MemTop;
+ PRNTPCI(HalpDebugPrint("HalpAssignPciSlot....%x, %x\n",
+ FpNode->MemBase, FpNode->MemTop));
+ }
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+ }
+ }
+
+ CompleteList->ListSize = (ULONG)
+ ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses. This is done in
+ // case HalAdjustResourceList wants to read the current settings
+ // in the device.
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ //
+ // Have the IO system allocate resource assignments
+ //
+
+ status = IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ CompleteList,
+ pAllocatedResources
+ );
+
+ if (!NT_SUCCESS(status)) {
+ HalpDebugPrint("HalpAssignPCISlotResources: Failed IoAssignResources:%x\n",
+ status);
+ goto CleanUp;
+ }
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+ BusData->CommonData.Line2Pin ((PBUS_HANDLER) BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
+ CmDescriptor++;
+ }
+
+ //
+ // Pull out resources in the order they were passed to IoAssignResources
+ //
+
+ m = 0;
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ m |= PCI_ENABLE_IO_SPACE;
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+ } else {
+ m |= PCI_ENABLE_MEMORY_SPACE;
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ CmDescriptor++;
+ }
+ }
+
+ //
+ // Set addresses, but do not turn on decodes
+ //
+
+ HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read configuration back and verify address settings took
+ //
+
+ HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
+ Match = TRUE;
+ if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
+ PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
+ PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
+ Match = FALSE;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
+ i = (ULONG) ~0x3;
+ } else {
+ i = (ULONG) ~0xF;
+ }
+
+ if ((*BaseAddress[j] & i) !=
+ *((PULONG) ((PUCHAR) BaseAddress[j] -
+ (PUCHAR) PciData +
+ (PUCHAR) PciData2)) & i) {
+
+ Match = FALSE;
+ }
+ if (
+ !(*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) &&
+ Is64BitBaseAddress(*BaseAddress[j])
+ ) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+ }
+
+ if (!Match) {
+#if DBG
+ HalpPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+#endif
+ status = STATUS_DEVICE_PROTOCOL_ERROR;
+ goto CleanUp;
+ }
+
+ //
+ // Settings took - turn on the appropiate decodes
+ //
+
+ if (EnableRomBase && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ BaseAddress[RomIndex],
+ (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
+ sizeof (ULONG)
+ );
+ }
+
+ //
+ // Enable IO & Memory decodes (use HalSetBusData since valid settings now set)
+ //
+
+ // Set Bus master bit on for win95 compatibility
+ m |= PCI_ENABLE_BUS_MASTER;
+
+ PciData->Command |= (USHORT) m;
+
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+}
+
+#if DBG
+VOID
+HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Note: This is reading the DeviceSpecific area of
+ // the device's configuration - normally this should
+ // only be done on device for which the caller understands.
+ // I'm doing it here only for debugging.
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalpPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ HalpPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ HalpPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ HalpPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ HalpPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.ProgIf, PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ HalpPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalpPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+
+ if (k) {
+ HalpPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ HalpPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ HalpPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ HalpPrint ("\n%02x: ", j + 0x40);
+ }
+ HalpPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ HalpPrint ("\n");
+ }
+
+
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ HalpPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ HalpPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ HalpPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+
+ //
+ // Next
+ //
+
+ if (k) {
+ HalpPrint ("\n\n");
+ }
+ }
+ }
+ }
+
+}
+#endif
diff --git a/private/ntos/nthals/halfire/ppc/pxpciint.c b/private/ntos/nthals/halfire/ppc/pxpciint.c
new file mode 100644
index 000000000..960569d0e
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxpciint.c
@@ -0,0 +1,398 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxpciint.c $
+ * $Revision: 1.26 $
+ * $Date: 1996/05/15 00:06:27 $
+ * $Locker: $
+ */
+
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpciint.c
+
+Abstract:
+
+ All PCI bus interrupt mapping is in this module, so that a real
+ system which doesn't have all the limitations which PC PCI
+ systems have can replaced this code easly.
+ (bus memory & i/o address mappings can also be fix here)
+
+Author:
+
+ Ken Reneris
+ Jim Wooldridge - Ported to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "phsystem.h"
+#include "pci.h"
+#include "pcip.h"
+#include "stdio.h"
+#include "fpdebug.h"
+
+ULONG PciAllowedInts = 0;
+
+#define PCI_DEVICE_VECTOR 0x10
+#define PCI_IO_ADDRESS_SPACE 0x81000000
+
+
+ULONG HalpGetPciIntVector( PBUS_HANDLER,
+ PBUS_HANDLER,
+ ULONG,
+ ULONG,
+ PKIRQL,
+ PKAFFINITY );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#endif
+
+
+/*
+ * HalpGetPciIntVector:
+ * This routine is a mirror ( but better ) version of HalpGetPCIIntOnISABus
+ *
+ */
+
+ULONG
+HalpGetPciIntVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ // since we can't see who's asking for an interrupt, must rely upon some
+ // known data: First, check to see if there is already one specified out
+ // among the pci devices: ( need to keep in mind some stubborn drivers
+ // that request several times for a particular interrupt i.e. scsi ).
+ //
+ // For now, to deal with a screwed up amd scsi driver, permanently map
+ // any requests for f ( as well as d which is what firmware sets this
+ // device to ) to 0x19, corresponding to the bit in our interrupt word.
+ //
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetPciIntVector: %x, %x \n",
+ BusInterruptLevel, BusInterruptVector ););
+
+#if defined(HALDEBUG_ON)
+ if (DBGSET(DBG_INTERRUPTS)) {
+ switch( BusInterruptVector ) {
+ case 0xd:
+ case 0xf:
+ HalpDebugPrint(" BusIntVec set to 0x%x \n",
+ BusInterruptVector);
+ break;
+ case 0xe:
+ HalpDebugPrint(" BusIntVec set to 0x%x \n",
+ BusInterruptVector);
+ break;
+ default:
+ HalpDebugPrint(" BusIntVec unchanged: \n");
+ break;
+ }
+ }
+#endif
+
+ return HalGetInterruptVector (
+ Internal, 0,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetPCIIntOnIsaBus: 0x%x, 0x%x, %x, %x, %x, %x \n",
+ BusHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ *Irql,
+ *Affinity ););
+ if (BusInterruptLevel < 1) {
+ // bogus bus level
+ return 0;
+ }
+
+ //
+ // Check that the requested interrupt is valid and return 0
+ // if the interrupt is not in the allowed set of interrupts.
+ if (((1 << BusInterruptVector) & PciAllowedInts) == 0) {
+ return 0;
+ }
+
+ //
+ //
+ // For FirePOWER, pci interrupts are not mapped onto the isa bus ( with the
+ // exception of the amd ethernet drive which will always believe it's isa )
+ // so for the moment map their "isa" int values so that they're picked up
+ // correctly by HalpGetSystem...
+ //
+ switch( BusInterruptVector ) {
+ case 0xa:
+ //
+ // For now, map this vector back down to ISA level since the
+ // audio driver is confused, thinking it's on the pci bus.
+ //
+ //BusInterruptVector = 0xa - PCI_DEVICE_VECTOR;
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sVector is not PCI based vector: 0x%x\n",
+ " ", BusInterruptVector ););
+ break;
+ case 0xd:
+ case 0xf:
+ BusInterruptVector = 0xd +0xc ;
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint(" BusIntVect set to 0x19 \n"););
+ break;
+ case 0xe:
+ BusInterruptVector = 0xe +0xc;
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint(" BusIntVect set to 0x1a \n"););
+ break;
+ default:
+ break;
+ }
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sBusInterruptVector set to: 0x%x \n",
+ " ", BusInterruptVector););
+ //BusInterruptVector += PCI_DEVICE_VECTOR;
+ BusInterruptLevel = BusInterruptVector;
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sBusIntVec set to 0x%x \n",
+ " ", BusInterruptVector););
+
+ //
+ // Current PCI buses just map their IRQs ontop of the ISA space,
+ // so foreward this to the isa handler for the isa vector
+ // (the isa vector was saved away at either HalSetBusData or
+ // IoAssignReosurces time - if someone is trying to connect a
+ // PCI interrupt without performing one of those operations first,
+ // they are broken).
+ //
+
+ return HalGetInterruptVector (
+ Internal, 0,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+/*++
+
+// Routine Description: VOID HalpPCIPin2ISALine ()
+//
+// This function maps the device's InterruptPin to an InterruptLine
+// value.
+//
+// On Sandalfoot and Polo machines PCI interrupts are statically routed
+// via slot number. This routine just returns and the static routing
+// is done in HalpGetIsaFixedPCIIrq
+//
+
+--*/
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+{
+
+
+}
+
+
+
+/*++
+ Routine Description: VOID HalpPCIISALine2Pin ()
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+
+--*/
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+{
+}
+
+
+/*++
+
+Routine Description: VOID HalpPCIISALine2Pin ()
+
+ Translate PCI bus address.
+ Verify the address is within the range of the bus.
+
+Arguments:
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+
+NTSTATUS
+HalpTranslatePCIBusAddress (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+{
+ BOOLEAN status;
+ PPCIPBUSDATA BusData;
+
+ if (BusAddress.HighPart) {
+ return FALSE;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ switch (*AddressSpace) {
+ case MEMORY_ADDRESS_SPACE:
+ //
+ // verify memory address is within PCI buses memory limits
+ //
+ status = BusAddress.LowPart >= BusData->MemoryBase &&
+ BusAddress.LowPart <= BusData->MemoryLimit;
+
+ if (!status) {
+ status = BusAddress.LowPart >= BusData->PFMemoryBase &&
+ BusAddress.LowPart <= BusData->PFMemoryLimit;
+ }
+
+ break;
+ //
+ // Everyone should be assumed IO space if not otherwise requested
+ //
+ default:
+ case IO_ADDRESS_SPACE:
+ //
+ // verify memory address is within PCI buses io limits
+ //
+ status = BusAddress.LowPart >= BusData->IOBase &&
+ BusAddress.LowPart <= BusData->IOLimit;
+ break;
+
+ case SYSTEM_ADDRESS_SPACE:
+// #pragma NOTE("SYSTEM_ADDRESS_SPACE, verify?")
+ status = BusAddress.LowPart < BusData->IOBase &&
+ BusAddress.LowPart >= 0;
+ break;
+
+ }
+
+ if (!status) {
+ return FALSE;
+ }
+
+ //
+ // Valid address for this bus - foreward it to the parent bus
+ //
+
+ return BusHandler->ParentHandler->TranslateBusAddress (
+ BusHandler->ParentHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+}
+
+
+/*++
+Routine Description: NTSTATUS HalpAdjustPCIResourceList ()
+ Rewrite the callers requested resource list to fit within
+ the supported ranges of this bus
+--*/
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+ NTSTATUS Status;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER PciSlot;
+ UCHAR IrqTable[255];
+ PFPHAL_BUSNODE FpNode;
+
+ FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
+ // BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ BusData = (PPCIPBUSDATA) &(FpNode->Bus);
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+ // ======= Here's where thePCI interrupts are determined and set as a
+ // result of the call to HalpAdjustResourceListLimits
+
+ RtlZeroMemory(IrqTable, sizeof (IrqTable));
+ Status = BusData->GetIrqTable(BusHandler, RootHandler, PciSlot, IrqTable);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ //
+ // Adjust resources
+ //
+
+ return HalpAdjustResourceListLimits (
+ BusHandler, RootHandler, pResourceList,
+ BusData->MemoryBase, BusData->MemoryLimit,
+ BusData->PFMemoryBase, BusData->PFMemoryLimit,
+ BusData->LimitedIO,
+ BusData->IOBase, BusData->IOLimit,
+ IrqTable, 0xff,
+ 0, 0xffff // dma
+ );
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/pxpcisup.c b/private/ntos/nthals/halfire/ppc/pxpcisup.c
new file mode 100644
index 000000000..eecaa1e35
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxpcisup.c
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxpcisup.c $
+ * $Revision: 1.18 $
+ * $Date: 1996/05/14 02:35:00 $
+ * $Locker: $
+ */
+
+/*++
+
+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)
+
+
+Revision History:
+
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxpcisup.h"
+#include "stdio.h"
+#include "fpdebug.h"
+#include "phsystem.h"
+
+extern PVOID HalpPciConfigBase;
+extern UCHAR PciDevicePrimaryInts[];
+extern ULONG HalpGetPciInterruptSlot( PBUS_HANDLER, PCI_SLOT_NUMBER );
+
+#define LX_PCI_INTERRUPT_ROUTING_SLOT0 25
+#define LX_PCI_INTERRUPT_ROUTING_SLOT1 22
+#define LX_PCI_INTERRUPT_ROUTING_SLOT2 23
+#define LX_PCI_INTERRUPT_ROUTING_SLOT3 26
+#define LX_PCI_INTERRUPT_ROUTING_IDEA 21
+#define LX_PCI_INTERRUPT_ROUTING_IDEB 20
+
+#define PCI_INTERRUPT_ROUTING_SLOT0 0x16 // phys dev# 2, logical 1
+#define PCI_INTERRUPT_ROUTING_SLOT1 0x17 // phys dev# 3, logical 2
+#define PCI_INTERRUPT_ROUTING_SCSI 0x19 // phys dev# 1, logical 3
+#define PCI_INTERRUPT_ROUTING_ETHERNET 0x1a // phys dev# 4, logical 4
+#define IRQ_INVALID 0x0 // goes with IRQ_VALID defines
+
+ULONG HalpPciConfigSlot[] = { 0x0800, // phys dev# 0: SIO chip
+ 0x1000, // phys dev# 1: mobo scsi
+ 0x2000, // phys dev# 2: peripheral plug in
+ 0x4000, // phys dev# 3: peripheral plug in
+ 0x8000 // phys dev# 4: mobo ethernet
+
+ ,0x10000, // IDE_IntA
+ 0x20000 // IDE_IntB
+
+ };
+
+
+
+/*++
+
+Routine Description: ULONG HalpTranslatePciSlotNumber ()
+
+ This routine translate a PCI slot number to a PCI device number.
+ This is a sandalfoot memory map implementation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG BusNumber,
+ ULONG SlotNumber
+ )
+{
+ //
+ // Sandalfoot only has 1 PCI bus so bus number is unused
+ //
+
+ UNREFERENCED_PARAMETER(BusNumber);
+
+ return ((ULONG) ((PUCHAR) HalpPciConfigBase + HalpPciConfigSlot[SlotNumber]));
+
+}
+
+
+
+/*++
+
+Routine Description: ULONG HalpPhase0SetPciDataByOffset ()
+
+ This routine writes to PCI configuration space prior to bus handler installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+ULONG
+HalpPhase0SetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+{
+ PUCHAR to;
+ PUCHAR from;
+ ULONG tmpLength;
+
+ if (SlotNumber < MAXIMUM_PCI_SLOTS) {
+
+ to = (PUCHAR)HalpPciConfigBase + HalpPciConfigSlot[SlotNumber];
+ to += Offset;
+ from = Buffer;
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ *to++ = *from++;
+ tmpLength--;
+ }
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+
+/*++
+
+Routine Description: ULONG HalpPhase0GetPciDataByOffset ()
+
+ This routine reads PCI config space prior to bus handlder installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Amount of data read.
+
+--*/
+
+ULONG
+HalpPhase0GetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+{
+ PUCHAR to;
+ PUCHAR from;
+ ULONG tmpLength;
+
+ if (SlotNumber < MAXIMUM_PCI_SLOTS) {
+
+ from = (PUCHAR)HalpPciConfigBase + HalpPciConfigSlot[SlotNumber];
+ from += Offset;
+ to = Buffer;
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ *to++ = *from++;
+ tmpLength--;
+ }
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+ ULONG slot;
+ ULONG interrupt;
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetISAFixedPCIIrq: %x, %x, %x, %x %x \n",
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH ));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // For Primary PCI slots, the interrupt corresponds to the primary
+ // slot number
+ if ( BusHandler->BusNumber == 0 ) {
+ slot = PciSlot.u.bits.DeviceNumber;
+ }
+ // For Secondary PCI slots, the interrupt corresponds to the slot
+ // number of the primary parent
+ else {
+ slot = HalpGetPciInterruptSlot(BusHandler, PciSlot );
+ }
+
+ // Search the interrupt table for the interrupt corresponding to the slot
+ if (slot < MAXIMUM_PCI_SLOTS) {
+ interrupt = PciDevicePrimaryInts[slot];
+ if (interrupt != INVALID_INT) {
+ IrqTable[interrupt] = IRQ_VALID;
+ } else {
+ return STATUS_UNSUCCESSFUL;
+ }
+ } else {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpGetISAFixedPCIIrq: index = 0x%x \n",
+ PciSlot.u.bits.DeviceNumber););
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxpcisup.h b/private/ntos/nthals/halfire/ppc/pxpcisup.h
new file mode 100644
index 000000000..6fd05f401
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxpcisup.h
@@ -0,0 +1,66 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxpcisup.h
+
+Abstract:
+
+ The module provides the PCI bus interfaces for PowerPC systems.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxpcisup.h $
+ * $Revision: 1.10 $
+ * $Date: 1996/01/25 01:11:57 $
+ * $Locker: $
+ */
+
+extern ULONG HalpPciConfigSlot[];
+
+#include "phsystem.h"
+
+// The Maximum number of (Primary) PCI slots on a Firepower board
+#define MAXIMUM_PCI_SLOTS 7
+
+#define INVALID_INT 0xff
+#define INVALID_SLOTNUMBER 0xff
+
+
+typedef struct {
+ USHORT VendorID;
+ USHORT DeviceID;
+ USHORT Command;
+ USHORT Status;
+ UCHAR RevisionID;
+ UCHAR ClassCode[3];
+ UCHAR CacheLineSize;
+ UCHAR LatencyTimer;
+ UCHAR HeaderType;
+ UCHAR BIST;
+ ULONG BaseAddress1;
+ ULONG BaseAddress2;
+ ULONG BaseAddress3;
+ ULONG BaseAddress4;
+ ULONG BaseAddress5;
+ ULONG BaseAddress6;
+ ULONG reserved1;
+ ULONG reserved2;
+ ULONG ROMbase;
+} *PCI_CONFIG;
+
diff --git a/private/ntos/nthals/halfire/ppc/pxport.c b/private/ntos/nthals/halfire/ppc/pxport.c
new file mode 100644
index 000000000..4149cd107
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxport.c
@@ -0,0 +1,855 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxport.c $
+ * $Revision: 1.13 $
+ * $Date: 1996/05/14 02:35:04 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991 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:
+
+ pxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a PowerPC system.
+
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+ Chuck Bauman 02-Jun-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+ Steve Johns (sjohns@pets.sps.mot.com)
+ - added support for multple baud rates, alternate COM port
+ - implemented KdPortSave & KdPortRestore
+
+--*/
+
+#include "halp.h"
+#include "ppcserp.h"
+#include "pxmemctl.h"
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+ULONG KdCurrentBaudRate= 19200;
+
+extern BOOLEAN HalpPhase0MapIo( VOID );
+ULONG KdCurrentComPort;
+ULONG HalpSavedBaudRate;
+ULONG HalpSavedComPort;
+
+// HalpIoControlBase is extern'd in pxhalp.h which is included in halp.h
+
+//
+// Define serial port read and write addresses.
+//
+
+#define SP_READ ((PSP_READ_REGISTERS)((PUCHAR)HalpIoControlBase + KdCurrentComPort))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)((PUCHAR)HalpIoControlBase + KdCurrentComPort))
+
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+UCHAR HalpBaudRateDivisor = 6;
+
+//
+// Define hardware PTE's that map the serial port used by the debugger.
+//
+
+
+
+/*++
+
+Routine Description: ULONG HalpGetByte ()
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+
+/*++
+
+Routine Description: BOOLEAN KdPortInitialize ()
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameters - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+{
+
+ UCHAR DataByte;
+/*
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ ULONG KdPortEntry;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 800000.
+ //
+
+ BaudClock = 8000000;
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+
+*/
+
+ //
+ // Map I/O space if it has not already been mapped.
+ //
+
+ if (HalpIoControlBase == NULL) {
+ HalpPhase0MapIo();
+ if ( !HalpIoControlBase ) {
+ return FALSE;
+ }
+ }
+
+
+
+ //
+ // Set COM parameters
+ //
+ if (DebugParameters != NULL) {
+ if (DebugParameters->BaudRate == 0)
+ KdCurrentBaudRate = 19200; // default baud rate
+ else
+ KdCurrentBaudRate = DebugParameters->BaudRate;
+
+ if (DebugParameters->CommunicationPort > 2)
+ return (FALSE);
+ KdCurrentComPort = COM1_PORT; // default COM port
+ if (DebugParameters->CommunicationPort == 1)
+ KdCurrentComPort = COM1_PORT;
+ if (DebugParameters->CommunicationPort == 2)
+ KdCurrentComPort = COM2_PORT;
+
+
+ }
+
+ HalpBaudRateDivisor = (UCHAR) ((1843200/16) / KdCurrentBaudRate);
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+
+
+ KdComPortInUse=(PUCHAR)KdCurrentComPort;
+
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate to requested rate.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, HalpBaudRateDivisor);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description: ULONG KdPortGetByte ()
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+
+/*++
+
+Routine Description: ULONG KdPortPollByte ()
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+
+/*++
+
+Routine Description: VOID KdPortPutByte ()
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+{
+
+ UCHAR DataByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = (PSP_MODEM_STATUS) READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+
+/*++
+
+Routine Description: VOID KdPortRestore ()
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+KdPortRestore (
+ VOID
+ )
+{
+DEBUG_PARAMETERS ComParams;
+
+ if (HalpSavedComPort != KdCurrentComPort ||
+ HalpSavedBaudRate != KdCurrentBaudRate) {
+ ComParams.CommunicationPort = HalpSavedComPort;
+ ComParams.BaudRate = HalpSavedBaudRate;
+ KdPortInitialize(&ComParams, NULL, TRUE);
+ }
+}
+
+
+/*++
+
+Routine Description: VOID KdPortSave ()
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+KdPortSave (
+ VOID
+ )
+{
+
+ HalpSavedBaudRate = KdCurrentBaudRate;
+ HalpSavedComPort = KdCurrentComPort;
+ return;
+}
+
+
+/*++
+
+Routine Description: SP_LINE_STATUS KdReadLsr ()
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Supplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+
+
+/*++
+
+Routine Description: VOID HalpGetDivisorFromBaud()
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxproc.c b/private/ntos/nthals/halfire/ppc/pxproc.c
new file mode 100644
index 000000000..ca6d2e3f3
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxproc.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxproc.c $
+ * $Revision: 1.21 $
+ * $Date: 1996/06/25 02:46:32 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "stdio.h"
+#include "string.h"
+#include "stdlib.h"
+#include "arccodes.h"
+#include "fpreg.h"
+#include "phsystem.h"
+
+
+UCHAR HalName[] = "Powerized HAL";
+
+extern VOID HalpInitializePciBus (VOID);
+VOID HalpInitOtherBuses (VOID);
+ULONG HalpProcessorCount(VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalAllProcessorsStarted)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+{
+ PRESTART_BLOCK pRB;
+ ULONG Number;
+ PKPRCB Prcb;
+ char buf[128];
+
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalpStartNextProcessor: called\n"););
+
+
+ //
+ // Check if UNIPROCESSOR is set and ignore all other processors,
+ // this is done in a free HAL so that UP/MP performance measurements
+ // can be taken.
+ //
+ if (HalGetEnvironmentVariable("UNIPROCESSOR", sizeof(buf), buf)
+ == ESUCCESS) {
+ if (_stricmp(buf, "true") == 0) {
+ HalpDebugPrint("HalpStartNextProcessor: UNIPROCESSOR set\n");
+ return FALSE;
+ }
+ }
+
+ //
+ // If there is more than one restart block then this is a multi-
+ // processor system.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+ pRB = SYSTEM_BLOCK->RestartBlock;
+ Number = 0;
+ while (pRB != NULL) {
+ if ((pRB->BootStatus.ProcessorReady == TRUE) &&
+ (pRB->BootStatus.ProcessorStart == FALSE)) {
+
+ //
+ // Assert that we think this is an MP capable machine
+ //
+ if (!(SystemDescription[SystemType].Flags&SYS_MPCAPABLE) ||
+ !(ProcessorDescription[ProcessorType].Flags&PROC_MPCAPABLE)) {
+ HalpDebugPrint("HalStartNextProcessor: HAL/Veneer mismatch\n");
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ RtlZeroMemory(&pRB->u.Ppc, sizeof(PPC_RESTART_STATE));
+
+ //
+ // Set processor start address.
+ //
+ pRB->u.Ppc.Iar = ProcessorState->ContextFrame.Iar;
+ pRB->u.Ppc.Msr = ProcessorState->ContextFrame.Msr;
+
+ //
+ // PowerPC linkage conventions pass parameters in registers
+ // r.3 thru r.10. Set all of them to allow as much flexibility
+ // to the kernel as possible.
+ //
+ pRB->u.Ppc.IntR3 = ProcessorState->ContextFrame.Gpr3;
+ pRB->u.Ppc.IntR4 = ProcessorState->ContextFrame.Gpr4;
+ pRB->u.Ppc.IntR5 = ProcessorState->ContextFrame.Gpr5;
+ pRB->u.Ppc.IntR6 = ProcessorState->ContextFrame.Gpr6;
+ pRB->u.Ppc.IntR7 = ProcessorState->ContextFrame.Gpr7;
+ pRB->u.Ppc.IntR8 = ProcessorState->ContextFrame.Gpr8;
+ pRB->u.Ppc.IntR9 = ProcessorState->ContextFrame.Gpr9;
+ pRB->u.Ppc.IntR10 = ProcessorState->ContextFrame.Gpr10;
+
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = pRB;
+
+ //
+ // ARC interface is waiting for this bit to change
+ // so change it.
+ //
+ pRB->BootStatus.ProcessorStart = TRUE;
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalStartNextProcessor: started Cpu (%d)\n",
+ Number););
+ return TRUE;
+ }
+ Number++;
+ pRB = pRB->NextRestartBlock;
+ }
+ return FALSE;
+}
+
+BOOLEAN
+HalAllProcessorsStarted(VOID)
+{
+ PRESTART_BLOCK pRB;
+ ULONG NumCpu=0;
+
+ HDBG(DBG_INTERNAL, HalpDebugPrint("HalAllProcessorsStarted: called\n"););
+
+ pRB = SYSTEM_BLOCK->RestartBlock;
+ while (pRB != NULL) {
+ if ((pRB->BootStatus.ProcessorReady == TRUE) &&
+ (pRB->BootStatus.ProcessorStart == FALSE))
+ HDBG(DBG_GENERAL,HalpDebugPrint(
+ "HalAllProcessorsStarted: NT disabled processor %d\n",NumCpu););
+ NumCpu++;
+ pRB = pRB->NextRestartBlock;
+ }
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("HalAllProcessorsStarted: return TRUE\n"););
+ return TRUE;
+}
+
+VOID
+HalReportResourceUsage(VOID)
+{
+ extern VOID HalpSetUpFirePowerRegistry(VOID);
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ interfacetype = Internal;
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage(&UHalName, interfacetype);
+
+ interfacetype = Isa;
+ HalpReportResourceUsage (&UHalName, interfacetype);
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+ HalpInitializePciBus ();
+
+
+ HalpSetUpFirePowerRegistry(); // in fprgstry.c
+}
+
+ULONG
+HalpProcessorCount()
+{
+ PRESTART_BLOCK pRB;
+ static ULONG Count = 0;
+
+ if (Count)
+ return(Count);
+
+ pRB = SYSTEM_BLOCK->RestartBlock;
+ while (pRB != NULL) {
+ if ((pRB->BootStatus.ProcessorReady == TRUE) &&
+ (pRB->BootStatus.ProcessorStart == TRUE))
+ Count++;
+ pRB = pRB->NextRestartBlock;
+ }
+ return Count;
+}
+
+VOID
+HalpInitOtherBuses(VOID)
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxprof.c b/private/ntos/nthals/halfire/ppc/pxprof.c
new file mode 100644
index 000000000..ee3ed4532
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxprof.c
@@ -0,0 +1,277 @@
+
+/*****************************************************************************
+
+Copyright (c) 1993 Motorola Inc.
+ Copyright 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:
+
+ PXPROF.C
+
+Abstract:
+
+ This implements the HAL profile functions:
+
+ HalSetProfileInterval
+ HalStartProfileInterrupt
+ HalStopProfileInterrupt
+ HalCalibratePerformanceCounter
+ HalpProfileInterrupt
+
+
+Author:
+
+ Steve Johns 11-Feb-1994
+
+Revision History:
+ Changed from using the DECREMENTER to 8254 Timer 1 10-Feb-94
+
+******************************************************************************/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxprof.c $
+ * $Revision: 1.7 $
+ * $Date: 1996/01/11 07:13:00 $
+ * $Locker: $
+ */
+
+#include "halp.h"
+#include "eisa.h"
+#include "pxsiosup.h"
+
+#define TIMER ((PEISA_CONTROL)HalpIoControlBase)
+#define TIMER0_COMMAND (COMMAND_8254_COUNTER0 + COMMAND_8254_RW_16BIT + COMMAND_8254_MODE2)
+
+ULONG HalpMaxProfileInterval = 540000; // 54 ms maximum
+ULONG HalpMinProfileInterval = 10000; // 1 ms minimum
+ULONG HalpProfileCount;
+BOOLEAN HalpProfilingActive = FALSE;
+ULONG HalpProfileInts = 0;
+
+
+VOID HalStartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine unmasks IRQ0 at the master interrupt controller,
+ enabling the profile interrupt.
+
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding
+ the profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (ProfileSource == ProfileTime) {
+ HalpProfilingActive = TRUE;
+ //
+ // Unmasks IRQ 0 (Timer 1)
+ //
+ HalEnableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL, Latched);
+ }
+
+}
+
+
+
+
+
+
+ULONG HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval, rounded to the nearest 100ns units.
+
+--*/
+
+{
+ ULONG ActualInterval;
+ LARGE_INTEGER BigNumber;
+
+ //
+ // Clamp the requested profile interval between the minimum and
+ // maximum supported values.
+ //
+ if (Interval < HalpMinProfileInterval)
+ Interval = HalpMinProfileInterval;
+ else
+ if (Interval > HalpMaxProfileInterval)
+ Interval = HalpMaxProfileInterval;
+ //
+ // Compute Timer 1 counts for requested interval.
+ //
+ BigNumber.QuadPart = Int32x32To64(Interval, TIMER_CLOCK_IN);
+
+ BigNumber = RtlExtendedLargeIntegerDivide(BigNumber, 10000000, NULL);
+ HalpProfileCount = BigNumber.LowPart;
+
+ //
+ // Program Timer 1 to Mode 2 & program the timer count register.
+ //
+ WRITE_REGISTER_UCHAR (&(TIMER->CommandMode1), TIMER0_COMMAND);
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount & 0xff));
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount >> 8));
+ //
+ // Compute actual interval.
+ //
+ BigNumber.QuadPart = Int32x32To64(HalpProfileCount, 10000000);
+ BigNumber = RtlExtendedLargeIntegerDivide(BigNumber,TIMER_CLOCK_IN, NULL);
+ ActualInterval = BigNumber.LowPart;
+
+ return (ActualInterval);
+}
+
+
+
+
+BOOLEAN HalpHandleProfileInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+
+ if (HalpProfilingActive)
+ KeProfileInterrupt(TrapFrame);
+
+ return (TRUE);
+}
+
+
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+)
+
+/*++
+
+Routine Description:
+
+ This routine masks IRQ 0 (Timer 1) at the interrupt controller, thereby
+ stopping profile interrupts.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ if (ProfileSource == ProfileTime) {
+ HalpProfilingActive = FALSE;
+
+ //
+ // Program Timer 1 to Mode 2 & program the LSB of the timer.
+ // That should keep it from interrupting in case IRQ0 accidently
+ // gets enabled.
+ //
+ WRITE_REGISTER_UCHAR (&(TIMER->CommandMode1), TIMER0_COMMAND);
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount & 0xff));
+
+
+ //
+ // Mask IRQ 0 (Timer 1)
+ //
+ HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
+ }
+
+}
+
+
+
+
+
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KSPIN_LOCK Lock;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and
+ // wait until the number is zero.
+ //
+ KeInitializeSpinLock(&Lock);
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (ExInterlockedDecrementLong(Number, &Lock) != RESULT_ZERO) {
+ do {
+ } while (*Number !=0);
+ }
+
+ //
+ // Zero the Time Base registers
+ //
+
+ HalpZeroPerformanceCounter();
+
+ //
+ // Restore IRQL to its previous value and return.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxreturn.c b/private/ntos/nthals/halfire/ppc/pxreturn.c
new file mode 100644
index 000000000..d9456cf41
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxreturn.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxreturn.c $
+ * $Revision: 1.13 $
+ * $Date: 1996/05/14 02:35:12 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991 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:
+
+ pxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial Power PC port
+
+ Keyboard mapping code was ported to PPC.
+ This function is currently a stub since our firmware is big endian
+
+--*/
+
+#include "halp.h"
+#include "phsystem.h"
+
+//
+// Define keyboard registers structure.
+//
+typedef struct _KBD_REGISTERS {
+ union {
+ UCHAR Output;
+ UCHAR Input;
+ } Data;
+
+ union {
+ UCHAR Status;
+ UCHAR Command;
+ } Control;
+} KBD_REGISTERS;
+
+#define KEYBOARD_CONTROL_SPACE 0x80000000
+#define KBD_DATA_PORT 0x60
+#define KBD_COMMAND_PORT 0x64
+#define KBD_IBF_MASK 2 // input buffer full mask
+#define KBD_OBF_MASK 1 // Output buffer full mask
+
+#define KbdGetStatus() \
+ (READ_REGISTER_UCHAR(ControlSpace + KBD_COMMAND_PORT))
+#define KbdStoreCommand(Byte) \
+ WRITE_REGISTER_UCHAR(ControlSpace + KBD_COMMAND_PORT, Byte)
+#define KbdStoreData(Byte) \
+ WRITE_REGISTER_UCHAR(ControlSpace + KBD_DATA_PORT, Byte)
+#define KbdGetData() \
+ (READ_REGISTER_UCHAR(ControlSpace + KBD_DATA_PORT))
+
+#define KbdWriteSequence(_cmd, _data) { \
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) { \
+ /* Do Nothing */ \
+ } \
+ KbdStoreCommand((_cmd)); \
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) { \
+ /* Do Nothing */ \
+ } \
+ KbdStoreData((_data)); \
+}
+
+#define KbdReadSequence(_cmd, _pdata) { \
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) { \
+ /* Do Nothing */ \
+ } \
+ KbdStoreCommand((_cmd)); \
+ while ((KbdGetStatus() & KBD_OBF_MASK) == 0) { \
+ /* Do Nothing */ \
+ } \
+ (*(_pdata)) = KbdGetData(); \
+}
+
+VOID
+HalpPowerPcReset(
+ VOID
+ );
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+
+ //
+ // Disable Interrupts.
+ //
+ HalpDisableInterrupts();
+
+ //
+ // Perform an appropriate action for each request type
+ //
+ switch (Routine) {
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+ // Reset using 8042 keyboard command
+ HalpResetByKeyboard();
+
+ /* Fall Through to Hang */
+ case HalHaltRoutine:
+ //
+ // Hang looping.
+ //
+ for (;;) {
+ /* Do Nothing */
+ }
+
+ default:
+ HalpDebugPrint("HalReturnToFirmware: invalid argument\n");
+ for (;;) {
+ /* Do Nothing */
+ }
+ }
+}
+
+VOID
+HalpResetByKeyboard( VOID )
+{
+ PHYSICAL_ADDRESS physicalAddress;
+ PUCHAR ControlSpace;
+ UCHAR data;
+
+
+ //
+ // First job is to map the Keyboard registers into a virtual
+ // address.
+ //
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = KEYBOARD_CONTROL_SPACE;
+ ControlSpace = (PUCHAR)MmMapIoSpace(physicalAddress, PAGE_SIZE, FALSE);
+
+ //
+ // Flush Keyboard Output Buffer (throw away data)
+ // Delay Loop (Wait for 8 milliseconds)
+ //
+ KeStallExecutionProcessor(8000);
+ while ((KbdGetStatus() & KBD_OBF_MASK) != 0) {
+ KbdGetData();
+ //
+ // Delay Loop (Wait for 8 milliseconds)
+ //
+ KeStallExecutionProcessor(8000);
+ };
+
+ //
+ // Disable auxillary device
+ //
+ KbdStoreCommand(0xa7);
+
+ //
+ // Disable Keyboard
+ //
+ KbdStoreCommand(0xad);
+
+ //
+ // Disable Chip Level Interrupts for Mouse and Keyboard
+ //
+ KbdReadSequence(0x20, &data);
+ data |= 0x30;
+ data &= 0xfc;
+ KbdWriteSequence(0x60, data);
+
+ //
+ // Request the reset
+ //
+ KbdWriteSequence(0xb8, 0x1e);
+ KbdWriteSequence(0xbd, 0x48);
+ KbdWriteSequence(0xbe, 0x1);
+ KbdWriteSequence(0xca, 0x1);
+
+ //
+ // Now wait forever for the reset to happen
+ //
+ for (;;) {
+ /* Do Nothing */
+ }
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/pxrtcsup.h b/private/ntos/nthals/halfire/ppc/pxrtcsup.h
new file mode 100644
index 000000000..bb8050454
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxrtcsup.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxrtcsup.h $
+ * $Revision: 1.7 $
+ * $Date: 1996/05/14 02:35:17 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxrtcsup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the DALLAS rtc chip.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+#ifndef PXRTCSUP_H
+#define PXRTCSUP_H
+
+#include "fpds1385.h"
+
+#endif // PXRTCSUP_H
diff --git a/private/ntos/nthals/halfire/ppc/pxs3.h b/private/ntos/nthals/halfire/ppc/pxs3.h
new file mode 100644
index 000000000..2b463c359
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxs3.h
@@ -0,0 +1,770 @@
+/*++
+
+Copyright (c) 1992 ACER Labs Inc.
+
+Module Name:
+
+ pxs3.h
+
+Abstract:
+
+ This header file defines the S3 86C911 GUI accelerator registers.
+
+Author:
+
+ Version 1.0 Kevin Chen 2-Apr-1992
+ Version 2.0 Andrew Chou Nov-24-1992
+ Version 3.0 Jess Botts Oct-06-1993 Power PC Initial Version
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxs3.h $
+ * $Revision: 1.6 $
+ * $Date: 1996/01/11 07:13:27 $
+ * $Locker: $
+ */
+
+#define VERTICALRESOLUTION 768
+#define HORIZONTALRESOLUTION 1024
+#define OriginalPoint 0
+#define BLUE 192
+#define WHITE 255
+#define CRT_OFFSET 2
+#define SEQ_OFFSET 27
+#define GRAPH_OFFSET 32
+#define ATTR_OFFSET 41
+
+UCHAR DAC_Table[64] = {
+ // DAC for mode 3
+ 0,16, 4,20, 1,17, 5,21,
+ 32,48,36,52,33,49,37,53,
+ 8,24,12,28, 9,25,13,29,
+ 40,56,44,60,41,57,45,61,
+ 2,18, 6,22, 3,19, 7,23,
+ 34,50,38,54,35,51,39,55,
+ 10,26,14,30,11,27,15,31,
+ 42,58,46,62,43,59,47,63
+ };
+
+UCHAR DAC_Color[4] = {0x00, 0x2a, 0x15, 0x3f};
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+// HalpIoControlBase is extern'd in pxhalp.h which is included by halp.h
+
+//
+// Define S3 register I/O Macros
+//
+
+//=============================================================================
+//
+// IBMBJB Changed the semicolons separating statements in the write macros to
+// commas so that if the macro is used as the only statement in a loop
+// all of the statements in the macro will be part of the loop.
+//
+// Commas were used instead of putting braces around the statements
+// because if the macro is used in the true part of a conditional the
+// braces will cause the compiler to generate a syntax error.
+
+#define WRITE_S3_UCHAR(port,data) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port)) = (UCHAR)(data), \
+ KeFlushWriteBuffer()
+
+#define WRITE_S3_USHORT(port,data) \
+ *(volatile PUSHORT)((ULONG)HalpIoControlBase + (port)) = (USHORT)(data), \
+ KeFlushWriteBuffer()
+
+#define READ_S3_UCHAR(port) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_S3_USHORT(port) \
+ *(volatile unsigned short *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_S3_VRAM(port) \
+ *(HalpVideoMemoryBase + (port))
+
+#define WRITE_S3_VRAM(port,data) \
+ *(HalpVideoMemoryBase + (port)) = (data), \
+ KeFlushWriteBuffer()
+
+//=============================================================================
+
+#define DISPLAY_BITS_PER_PIXEL 8 // display bits per pixel
+#define NUMBER_OF_COLORS 256 // number of colors
+
+#define CURSOR_WIDTH 64 // width of hardware cursor
+#define CURSOR_HEIGHT 64 // height of hardware cursor
+#define CURSOR_BITS_PER_PIXEL 2 // hardware cursor bits per pixel
+
+//
+// S3 86C911 GUI, accelerator Video Controller Definitions.
+//
+// Define video register format.
+//
+#define PosID_LO 0x100 // R/W
+#define PosID_HI 0x101 // R/W
+#define Setup_OP 0x102 // R/W
+#define Chck_Ind 0x105 // R
+#define Mono_3B4 0x3B4 // R/W
+#define Mono_3B5 0x3B5 // R/W
+#define MDA_Mode 0x3B8 // W
+#define HGC_SLPEN 0x3B9 // R/W
+#define Stat1_MonoIn 0x3BA // R
+#define FC_MonoW 0x3BA // W
+#define HGC_CLPEN 0x3BB // W
+#define HGC_Config 0x3BF // W
+#define Attr_Index 0x3C0 // R/W
+#define Attr_Data 0x3C0 // R/W
+#define Stat0_In 0x3C2 // R
+#define MiscOutW 0x3C2 // W
+#define VSub_EnB 0x3C3 // R/W
+#define Seq_Index 0x3C4 // R/W
+#define Seq_Data 0x3C5 // R/W
+#define DAC_Mask 0x3C6 // R/W
+#define DAC_RIndex 0x3C7 // W
+#define DAC_Status 0x3C7 // W
+#define DAC_WIndex 0x3C8 // R/W
+#define DAC_Data 0x3C9 // R/W
+#define FC_Read 0x3CA // R
+#define MiscOutR 0x3CC // R
+#define GC_Index 0x3CE // R/W
+#define GC_Data 0x3CF // R/W
+#define S3_3D4_Index 0x3D4 // R/W
+#define S3_3D5_Data 0x3D5 // R/W
+
+#define CGA_Mode 0x3D8 // W
+#define CGA_Color 0x3D9 // W
+#define Stat1_In 0x3DA // R
+#define FC_Write 0x3DA // W
+#define CLPEN 0x3DB
+#define SLPEN 0x3DC
+
+//
+// Define Enhanced registers for S3_86C911
+//
+
+#define SUBSYS_STAT 0x42E8 // R
+#define SUBSYS_CNTL 0x42E8 // W
+#define SUBSYS_ENB 0x46E8 // R/W
+#define ADVFUNC_CNTL 0x4AE8 // W
+#define CUR_Y 0x82E8 // R/W
+#define CUR_X 0x86E8 // R/W
+#define DESTY 0x8AE8 // W
+#define AXIAL_STEP 0x8AE8 // W
+#define DESTX 0x8EE8 // W
+#define DIAG_STEP 0x8EE8 // W
+#define ERR_TERM 0x92E8 // R
+#define MAJ_AXIS_PCNT 0x96E8 // W
+#define RWIDTH 0x96E8 // W
+#define GP_STAT 0x9AE8 // R
+#define DRAW_CMD 0x9AE8 // W
+#define SHORT_STROKE 0x9EE8 // W
+#define BKGD_COLOR 0xA2E8 // W
+#define FRGD_COLOR 0xA6E8 // W
+#define WRITE_MASK 0xAAE8 // W
+#define READ_MASK 0xAEE8 // W
+#define BKGD_MIX 0xB6E8 // W
+#define FRGD_MIX 0xBAE8 // W
+#define MULTIFUNC_CNTL 0xBEE8 // W
+#define RHEIGHT 0xBEE8 // W
+#define PIX_TRANS 0xE2E8 // W
+
+
+//
+// Define Attribute Controller Indexes : ( out 3C0, Index )
+//
+
+#define PALETTE0 0
+#define PALETTE1 1
+#define PALETTE2 2
+#define PALETTE3 3
+#define PALETTE4 4
+#define PALETTE5 5
+#define PALETTE6 6
+#define PALETTE7 7
+#define PALETTE8 8
+#define PALETTE9 9
+#define PALETTE10 10
+#define PALETTE11 11
+#define PALETTE12 12
+#define PALETTE13 13
+#define PALETTE14 14
+#define PALETTE15 15
+#define ATTR_MODE_CTRL 16
+#define BORDER_COLOR 17
+#define COLOR_PLANE_ENABLE 18
+#define HORI_PIXEL_PANNING 19
+#define PIXEL_PADDING 20
+
+//
+// Define Sequencer Indexes ( out 3C4, Index)
+//
+
+#define RESET 0
+#define CLOCKING_MODE 1
+#define ENABLE_WRITE_PLANE 2
+#define CHARACTER_FONT_SELECT 3
+#define MEMORY_MODE_CONTROL 4
+
+//
+// Define Graphics Controller Index ( out 3CE, Index )
+//
+
+#define SET_RESET 0
+#define ENABLE_SET_RESET 1
+#define COLOR_COMPARE 2
+#define DATA_ROTATE 3
+#define READ_PLANE_SELECT 4
+#define GRAPHICS_CTRL_MODE 5
+#define MEMORY_MAP_MODE 6
+#define COLOR_DONT_CARE 7
+#define BIT_MASK 8
+
+//
+// Define CRTC, VGA S3, SYS_CTRL Index : ( Out 3D4, Index )
+//
+// Define CRTC Controller Indexes
+//
+
+#define HORIZONTAL_TOTAL 0
+#define HORIZONTAL_DISPLAY_END 1
+#define START_HORIZONTAL_BLANK 2
+#define END_HORIZONTAL_BLANK 3
+#define HORIZONTAL_SYNC_POS 4
+#define END_HORIZONTAL_SYNC 5
+#define VERTICAL_TOTAL 6
+#define CRTC_OVERFLOW 7
+#define PRESET_ROW_SCAN 8
+#define MAX_SCAN_LINE 9
+#define CURSOR_START 10
+#define CURSOR_END 11
+#define START_ADDRESS_HIGH 12
+#define START_ADDRESS_LOW 13
+#define CURSOR_LOCATION_HIGH 14
+#define CURSOR_FCOLOR 14
+#define CURSOR_BCOLOR 15
+#define CURSOR_LOCATION_LOW 15
+#define VERTICAL_RETRACE_START 16
+#define VERTICAL_RETRACE_END 17
+#define VERTICAL_DISPLAY_END 18
+#define OFFSET_SCREEN_WIDTH 19
+#define UNDERLINE_LOCATION 20
+#define START_VERTICAL_BLANK 21
+#define END_VERTICAL_BLANK 22
+#define CRT_MODE_CONTROL 23
+#define LINE_COMPARE 24
+#define CPU_LATCH_DATA 34
+#define ATTRIBUTE_INDEX1 36
+#define ATTRIBUTE_INDEX2 38
+
+//
+// Define VGA S3 Indexes
+//
+#define S3R0 0x30
+#define S3R1 0x31
+#define S3R2 0x32
+#define S3R3 0x33
+#define S3R4 0x34
+#define S3R5 0x35
+#define S3R6 0x36
+#define S3R7 0x37
+#define S3R8 0x38
+#define S3R9 0x39
+#define S3R0A 0x3A
+#define S3R0B 0x3B
+#define S3R0C 0x3C
+#define SC0 0x40
+#define SC2 0x42
+#define SC3 0x43
+#define SC5 0x45
+
+//
+// Define System Control Indexes
+//
+#define SYS_CNFG 64
+#define SOFT_STATUS 65
+#define MODE_CTRL 66
+#define EXT_MODE 67
+#define HGC_MODE 69
+#define HGC_ORGX0 70
+#define HGC_ORGX1 71
+#define HGC_ORGY0 72
+#define HGC_ORGY1 73
+#define HGC_YSTART0 76
+#define HGC_YSTART1 77
+#define HGC_DISPX 78
+#define HGC_DISPY 79
+
+#define ENABLE_HARDWARE_CURSOR 1
+#define DISABLE_HARDWARE_CURSOR 0
+
+//
+// define advanced function control register structure
+//
+#define RES_640x480 0
+#define RES_1024x768 1
+#define RES_800x600 1
+
+#define ENABLE_VGA 6
+#define ENABLE_ENHANCED 7
+
+//
+// define draw command register values
+//
+#define NOP_COMMAND 0x0
+#define DRAW_LINE_COMMAND 0x2000
+#define RECTANGLE_FILL_COMMAND 0x4000
+#define BITBLT_COMMAND 0xc000
+#define BYTE_SWAP 0x1000
+#define NO_BYTE_SWAP 0x0
+#define SIXTEEN_BIT_BUS 0x0200
+#define EIGHT_BIT_BUS 0x0
+#define WAIT 0x0100
+#define NO_WAIT 0x0
+#define R0 0x0
+#define R45 0x20
+#define R90 0x40
+#define R135 0x60
+#define R180 0x80
+#define R225 0xa0
+#define R270 0xc0
+#define R315 0xe0
+#define XMAJ 0x0
+#define YMAJ 0x40
+#define XPositive 0x20
+#define YPositive 0x80
+#define XNegative 0x0
+#define YNegative 0x0
+
+#define DRAW_YES 0x10
+#define DRAW_NO 0x0
+#define RADIAL 8
+#define XY_BASE 0
+#define LAST_PIXEL_OFF 4
+#define LAST_PIXEL_ON 0
+#define MULTIPLE_PIXEL 2
+#define SINGLE_PIXEL 0
+#define DRAW_READ 0
+#define DRAW_WRITE 1
+
+#define SSV_DRAW 0x1000
+#define SSV_MOVE 0x0
+
+#define OneEmpty 0x80
+#define TwoEmpty 0x40
+#define ThreeEmpty 0x20
+#define FourEmpty 0x10
+#define FiveEmpty 0x8
+#define SixEmpty 0x4
+#define SevenEmpty 0x2
+#define EightEmpty 0x1
+
+#define BACKGROUND_COLOR 0
+#define FOREGROUND_COLOR 0x20
+#define CPU_DATA 0x40
+#define DISPLAY_MEMORTY 0x60
+#define NOT_SCREEN 0
+#define LOGICAL_ZERO 1
+#define LOGICAL_ONE 2
+#define LEAVE_ALONE 3
+#define NOT_NEW 4
+#define SCREEN_XOR_NEW 5
+#define NOT_SCREEN_XOR_NEW 6
+#define OVERPAINT 7 //( NEW )
+#define NOT_SCREEN_OR_NOT_NEW 8
+#define SCREEN_OR_NOT_NEW 9
+#define NOT_SCREEN_OR_NEW 10
+#define SCREEN_OR_NEW 11
+#define SCREEN_AND_NEW 12
+#define NOT_SCREEN_AND_NEW 13
+#define SCREEN_AND_NOT_NEW 14
+#define NOT_SCREEN_AND_NOT_NEW 15
+
+#define BEE8_1H 1
+#define BEE8_2H 2
+#define BEE8_3H 3
+#define BEE8_4H 4
+#define BEE8_0H 0
+#define L_CLIP 0x1000
+#define R_CLIP 0x2000
+#define B_CLIP 0x3000
+#define T_CLIP 0x4000
+
+#define DATA_EXTENSION 0xa000 // 10100000B
+#define CPU_EXT 0x80
+#define DISPLAY_EXT 0xc0
+#define NO_EXTENSION 0x0
+#define PACK_DATA 0x4
+#define NO_PACK_DATA 0x0
+#define SET_THIS_BIT_TO_ZERO 0;
+
+//
+// Define bits per pixel codes.
+//
+#define ONE_BIT_PER_PIXEL 0 // 1-bit per pixel
+#define TWO_BITS_PER_PIXEL 1 // 2-bits per pixel
+#define FOUR_BITS_PER_PIXEL 2 // 4-bits per pixel
+#define EIGHT_BITS_PER_PIXEL 3 // 8-bits per pixel
+
+//
+// Define address step value.
+//
+#define ADDRESS_STEP_INCREMENT 1 // vram transfer address increment
+
+//
+// Define cross hair thickness values.
+//
+#define ONE_PIXEL_THICK 0x0 // one pixel in thickness
+#define THREE_PIXELS_THICK 0x1 // three pixels in thickness
+#define FIVE_PIXELS_THICK 0x2 // five pixels in thickness
+#define SEVEN_PIXELS_THICK 0x3 // seven pixels in thickness
+
+//
+// Define multiplexer control values.
+//
+#define ONE_TO_ONE 0x0 // 1:1 multiplexing
+#define FOUR_TO_ONE 0x1 // 4:1 multiplexing
+#define FIVE_TO_ONE 0x2 // 5:1 multiplexing
+
+//
+// Define cursor origin values.
+//
+
+#define CURSOR_X_ORIGIN (((2*HORIZONAL_SYNC_VALUE)+BACK_PORCH_VALUE)*4-36)
+#define CURSOR_Y_ORIGIN ((VERTICAL_BLANK_VALUE/2)+24)
+
+ULONG HotspotX, HotspotY;
+
+// Extended VGA BIOS
+#define SUPER_VGA_SUPPORT 4FH
+#define RET_EXT_VGA_INFO 00H
+#define RET_EXT_VGA_MODE_INFO 01H
+#define SET_EXT_VGA_MODE 02H
+#define QUERY_CUR_EXT_VGA_MODE 03H
+
+#define SAVE_RESTORE_FUNCTION 04H
+// Function 04.0 Query Save/Restore Buffer Size
+#define GET_SAVE_BUFFER_SIZE 00H
+// Function 04.1 Save Extended Video state
+#define SAVE_STATE 01H
+// Function 04.2 Restore Extended VGA state
+#define RESTORE_STATE 02H
+
+#define WINDOWS_CONTROL 05H
+// Function 05.0 Set Window Control
+#define SELECT_PAGE_TO_BE_MAPPED 00H
+// fUNCTION 05.1 Get Window Control Setting
+#define GET_PAGE_MAPPED 01H
+
+#define SET_RESET_DUAL_DISPLAY_MODE FFH
+
+BOOLEAN ColorMonitor;
+PVOID S3_3x4, S3_3x5;
+UCHAR VideoParam[62] = {
+// Mode +3 480 Lines
+// External Registers 3C3, 3C2
+0x01,0x67,
+
+//=============================================================================
+//
+// IBMBJB changed value at offset 17 (5th number on second line) from 0x8e
+// to 0xae to disable the vertical retrace interrupt
+
+// CRT Controller Registers 3D4, 3D5
+0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,
+// 0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff,
+ 0x00,0x00,0x00,0x9c,0xae,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff,
+
+//=============================================================================
+
+// Sequencer Registers 3C4, 3C5
+// 0x01,0x01,0x03,0x00,0x02,
+0x01,0x20,0x03,0x00,0x02,
+
+// Graphic Control Registers
+0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0xff,
+
+// Attribute Controller Registers
+0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,
+0x3b,0x3c,0x3d,0x3e,0x3f,0x0c,0x00,0x0f,0x08,0x00};
+
+
+UCHAR VGAFont8x16[4096] = {
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 00
+0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x7E,0xFF,0xFF,0xDB,0xFF,0xFF,0xC3,0xE7,0xFF,0x7E,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // 8
+0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00, // 9
+0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF, // a
+0x00,0x00,0x3E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x30,0x38,0x3C,0x36,0x33,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00, // f
+
+0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00, // 10
+0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00, // 4
+0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 20
+0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // 1
+0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00, // 3
+0x00,0x18,0x18,0x7C,0xC6,0xC2,0x7C,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30,0x60,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, // 30
+0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x60,0x00,0x00, // b
+0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00, // 40
+0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0xC6,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 50
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00, // 1
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00, // d
+0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00, // f
+
+0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 60
+0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00, // 7
+0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // a
+0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0xD6,0xD6,0xD6,0xC6,0xC6,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00, // 70
+0x00,0x00,0x00,0x00,0x00,0x7E,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00, // 1
+0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00, // 80
+0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 1
+0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 4
+0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 5
+0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00, // 7
+0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 9
+0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // c
+0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // d
+0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // e
+0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // f
+
+0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // 90
+0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00, // 2
+0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 4
+0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00, // 8
+0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 9
+0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // a
+0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00, // b
+0x00,0x38,0x6C,0x64,0x60,0xF8,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // d
+0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00, // e
+0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00, // f
+
+0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // a0
+0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 1
+0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // 4
+0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 5
+0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 6
+0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00, // b
+0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00, // c
+0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, // b0
+0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA, // 1
+0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77, // 2
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 3
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 4
+0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 6
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 8
+0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 9
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // a
+0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // b
+0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // f
+
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c0
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 2
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 3
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 6
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 9
+0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // b
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // c
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // e
+0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d0
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 1
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 2
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 3
+0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 6
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 8
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // a
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // c
+0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, // d
+0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // e
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00, // e0
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xFC,0xC6,0xC6,0xC6,0xC6,0xDC,0xC0,0xC0,0x00,0x00, // 1
+0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0xC0,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00, // f0
+0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00, // 3
+0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 4
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00, // b
+0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // f
+ };
diff --git a/private/ntos/nthals/halfire/ppc/pxsiosup.c b/private/ntos/nthals/halfire/ppc/pxsiosup.c
new file mode 100644
index 000000000..39f42166f
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxsiosup.c
@@ -0,0 +1,1866 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxsiosup.c $
+ * $Revision: 1.38 $
+ * $Date: 1996/05/14 02:35:22 $
+ * $Locker: $
+ */
+
+/*++
+
+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:
+
+ pxsiosup.c
+
+Abstract:
+
+ The module provides the PCI ISA bridge support.
+
+Author:
+
+ Jim Wooldridge (jimw@vnet.ibm.com)
+
+
+Revision History:
+
+
+--*/
+
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "eisa.h"
+#include "pxsiosup.h"
+#include "pxpcisup.h"
+#include "pxmemctl.h"
+#include "bugcodes.h"
+#include "phsystem.h"
+#include "fpio.h"
+#include "fpcpu.h"
+
+extern BOOLEAN HalpHandleIpiInterrupt(PKINTERRUPT, PVOID);
+
+//
+// TODO:
+// 1) Move to PCR
+// 2) Put on cache line boundaries for peformance (i.e. don't
+// cache thrash.
+//
+#define MAX_CPU 32
+ULONG registeredInts[MAX_CPU] = {0};
+
+
+#define TBS " "
+#define SioId 0x04848086
+#define AMD_ENET 0x20001022
+#define AMD_SCSI 0x20201022
+#define ESCId 0x04828086
+
+PVOID HalpPciIsaBridgeConfigBase;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+
+extern ULONG BugLvl;
+
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PVOID ServiceContext,
+ PVOID TrapFrame
+ );
+
+//
+// Declare the interrupt structure for profile interrupt
+//
+
+KINTERRUPT HalpProfileInterrupt;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+//
+// Declare the interrupt structure for machine checks
+//
+
+KINTERRUPT HalpMachineCheckInterrupt;
+
+//
+// Declare the interrupt structure for the clock interrupt
+//
+
+KINTERRUPT HalpDecrementerInterrupt;
+
+//
+// Add spurious and bogus interrupt counts
+//
+
+#if DBG
+ULONG HalpSpuriousInterruptCount = 0;
+ULONG HalpBogusInterruptCount = 0;
+#endif
+
+
+//
+// Define Isa bus interrupt affinity.
+//
+
+KAFFINITY HalpIsaBusAffinity;
+
+
+//
+// The following function is called when a machine check occurs.
+//
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for ISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpIsaAdapter[8];
+
+//
+// Define save area for ISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+UCHAR HalpSioInterrupt1Mask = 0xff;
+UCHAR HalpSioInterrupt2Mask = 0xff;
+UCHAR HalpSioInterrupt1Level;
+UCHAR HalpSioInterrupt2Level;
+
+
+
+
+/*++
+
+Routine Description: BOOLEAN HalpInitializeInterrupts ()
+
+ This routine is called from phase 0 initialization, it initializes the
+ 8259 interrupt controller ( currently it masks all 8259 interrupts).
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+
+--*/
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+{
+ ULONG Vector;
+
+ HDBG(DBG_BREAK,
+ HalpDebugPrint("HalpInitializeInterrupts: Calling Break\n"););
+ HDBG(DBG_BREAK, DbgBreakPoint(););
+
+ //
+ // Mask all 8259 interrupts (except the cascade interrupt)
+ //
+ HalpDisableInterrupts();
+ for (Vector=0;Vector<16;Vector++) {
+ if (Vector == 2)
+ continue;
+ HalpDisableSioInterrupt(Vector + DEVICE_VECTORS);
+ }
+
+ //
+ // Reserve the external interrupt vector for exclusive use by the HAL.
+ //
+
+ PCR->ReservedVectors |= (1 << EXTERNAL_INTERRUPT_VECTOR);
+
+ return TRUE;
+
+}
+
+
+
+/*++
+
+Routine Description: BOOLEAN HalpCreateSioStructures ()
+
+ This routine initializes the structures necessary for SIO operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ SIO interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+BOOLEAN
+HalpCreateSioStructures (
+ VOID
+ )
+
+{
+
+ UCHAR DataByte;
+
+ // We have no interrupt handlers setup; make sure interrupts are
+ // disabled. (No need to re-enable them)
+ HalpDisableInterrupts();
+ //
+ // Initialize the IPI for processor zero:
+ // Connect the IPI interrupt handler directly to the CPU dispatch table
+ // without registering with the kernel.
+ //
+ PCR->InterruptRoutine[DEVICE_VECTORS + 31] =
+ (PKINTERRUPT_ROUTINE) HalpHandleIpiInterrupt;
+
+ //
+ // register the interrupt vector with the HAL
+ //
+ HalpRegisterVector(InternalUsage,
+ DEVICE_VECTORS + 31,
+ DEVICE_VECTORS + 31,
+ HIGH_LEVEL);
+
+ //
+ // Now enable the IPI interrupt on this CPU; the HAL must do this
+ // directly since we did not register with the kernel.
+ // We cannot call HalEnableSystemInterrupt because the irql masks have
+ // not been set up. Interrupts are disabled anyway.
+ //
+ HalpEnableSioInterrupt(DEVICE_VECTORS + 31, Latched);
+
+ //
+ // Initialize the Machine Check interrupt handler
+ //
+ if (HalpEnableInterruptHandler(&HalpMachineCheckInterrupt,
+ HalpHandleMachineCheck,
+ NULL,
+ NULL,
+ MACHINE_CHECK_VECTOR,
+ MACHINE_CHECK_LEVEL,
+ MACHINE_CHECK_LEVEL,
+ Latched,
+ FALSE,
+ 0,
+ FALSE,
+ InternalUsage,
+ MACHINE_CHECK_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ //
+ // Enable NMI IOCHK# and PCI SERR#
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus,
+ DataByte & ~DISABLE_IOCHK_NMI & ~DISABLE_PCI_SERR_NMI);
+
+ //
+ // Clear the SIO NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+ //
+ // Connect the external interrupt handler
+ //
+
+ PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ (PKINTERRUPT_ROUTINE) HalpHandleExternalInterrupt;
+ // PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ // HalpFieldExternalInterrupt;
+ // PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ // HalpHandleExternalInterrupt;
+
+ //
+ // register the interrupt vector
+ //
+
+ HalpRegisterVector(InternalUsage,
+ EXTERNAL_INTERRUPT_VECTOR,
+ EXTERNAL_INTERRUPT_VECTOR,
+ HIGH_LEVEL);
+
+
+
+
+ // Connect directly to the decrementer handler. This is done
+ // directly rather than thru HalpEnableInterruptHandler due to
+ // special handling required because the handler calls KdPollBreakIn().
+ //
+
+
+ PCR->InterruptRoutine[DECREMENT_VECTOR] = (PKINTERRUPT_ROUTINE) HalpHandleDecrementerInterrupt;
+
+ //
+ // Initialize and connect the Timer 1 interrupt (IRQ0)
+ //
+
+ if (HalpEnableInterruptHandler( &HalpProfileInterrupt,
+ (PKSERVICE_ROUTINE) HalpHandleProfileInterrupt,
+ (PVOID) NULL,
+ (PKSPIN_LOCK)NULL,
+ PROFILE_VECTOR,
+ PROFILE_LEVEL,
+ PROFILE_LEVEL,
+ Latched,
+ TRUE,
+ 0,
+ FALSE,
+ DeviceUsage,
+ PROFILE_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+
+ //
+ // Disable Timer 1; only used by profiling
+ //
+
+ HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
+
+ //
+ // Set default profile rate
+ //
+
+ HalSetProfileInterval(5000);
+
+ //
+ // Initialize any planar registers
+ //
+
+ HalpInitPlanar();
+
+ //
+ // Initialize the PCI/ISA bridge chip
+ //
+
+ HalpInitPciIsaBridge();
+
+ PHalpInterruptSetup();
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpSioInterrupt1Level = 0;
+ HalpSioInterrupt2Level = 0;
+
+ //
+ // Enable the clock interrupt
+ //
+
+ HalpUpdateDecrementer(1000); // Get those decrementer ticks going
+
+
+ //
+ // Set ISA bus interrupt affinity.
+ //
+
+ HalpIsaBusAffinity = PCR->SetMember;
+
+ //
+ // DMA command - set assert level
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus,
+ DataByte & ~DACK_ASSERT_HIGH & ~DREQ_ASSERT_LOW);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+
+BOOLEAN
+HalpInitPciIsaBridge (
+ VOID
+ )
+
+
+{
+
+ UCHAR DataByte;
+ BOOLEAN Found;
+ ULONG SlotNumber, Tval, bleah;
+ ULONG ChipId=0, DevInt=0, EvInt=0, AChipId=0;
+ UCHAR PCIReg;
+ ULONG BufferLength;
+
+
+ //
+ // Save off the interrupt mask for this cpu and then block all interrupts
+ // from coming through while probing the PCI bus. Decrementer is still
+ // enabled.
+ //
+ Tval = RInterruptMask(GetCpuId());
+ RInterruptMask(GetCpuId()) = 0x0;
+ WaitForRInterruptMask(GetCpuId());
+ rInterruptRequest = 0xffffffff;
+ FireSyncRegister();
+
+ Found = FALSE;
+ SlotNumber = 0;
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("HalpInitPciIsaBridge:.......................\n"););
+ while (!Found && SlotNumber<MAXIMUM_PCI_SLOTS) {
+ BufferLength = HalGetBusData(PCIConfiguration, // bus type
+ 0, // bus number
+ SlotNumber, // "Slot"
+ (PULONG)&ChipId,
+ sizeof(ChipId));
+ switch( ChipId ) {
+ case SioId:
+ PRNTGENRL(HalpDebugPrint(
+ "HalpInitPciIsaBridge: Found the SIO chip...\n"));
+ Found = TRUE;
+ break;
+ // TX_PROTO: to make life interesting, use a different bridge chip
+ case ESCId:
+ PRNTGENRL(HalpDebugPrint(
+ "HalpInitPciIsaBridge: Found the ESC chip...\n"));
+ Found = TRUE;
+ break;
+ case AMD_ENET:
+ DevInt &= 0xffffff00;
+ DevInt |= 0x0000000e;
+ WRITE_REGISTER_ULONG( (
+ ((PUCHAR)HalpPciConfigBase
+ +(0x800 << SlotNumber)) + 0x3c ),
+ DevInt);
+ FireSyncRegister();
+ HalSweepDcache();
+ DevInt = READ_REGISTER_ULONG(
+ ((PUCHAR)HalpPciConfigBase +
+ (0x800 << SlotNumber)) + 0x3c );
+ PRNTINTR(HalpDebugPrint("%sFound Amd Enet: DevInt: 0x%x \n",
+ " ", DevInt ););
+ break;
+ case AMD_SCSI:
+ DevInt &= 0xffffff00;
+ DevInt |= 0x00000016;
+ WRITE_REGISTER_ULONG( (
+ ((PUCHAR)HalpPciConfigBase +
+ (0x800 << SlotNumber)) + 0x3c ),
+ DevInt);
+ FireSyncRegister();
+ HalSweepDcache();
+ DevInt = READ_REGISTER_ULONG(
+ ((PUCHAR)HalpPciConfigBase +
+ (0x800 << SlotNumber)) + 0x3c );
+ HDBG(DBG_INTERRUPTS,
+ HalpDebugPrint("%sFound Amd scsi: DevInt: 0x%x \n",
+ TBS,DevInt ););
+ break;
+ default:
+ PRNTINTR(HalpDebugPrint("%sUnknown Device, ChipId = 0x%08x\n",
+ TBS, ChipId ));
+ break;
+ }
+ SlotNumber++;
+
+
+ }
+
+ //
+ // Clear out any pci bus errors which occurred due to the probing of
+ // non-existent devices:
+ //
+ rPCIBusErrorCause = 0xffffffff;
+ bleah = rTscStatus0;
+ FireSyncRegister();
+
+ //
+ // Restore the mask as we found it on the way into this routine...
+ //
+ RInterruptMask(GetCpuId()) = Tval;
+ WaitForRInterruptMask(GetCpuId());
+
+ HDBG(DBG_GENERAL,
+ HalpDebugPrint("ChipId = %x, SLotNumber = %x \n",ChipId, SlotNumber););
+
+
+ //
+ // Make sure that we found a valid chip id
+ //
+
+ if (!Found) {
+ HalDisplayString("HalpInitPciIsaBridge: sio not found \n");
+ // return FALSE;
+ }
+
+
+
+ //
+ // Define macros for reading and writing to the SIO config space
+ //
+
+#define READ_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalGetBusDataByOffset( \
+ PCIConfiguration, \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+#define WRITE_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalSetBusDataByOffset( \
+ PCIConfiguration, \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+
+
+ //
+ // Enable ISA Master line buffering
+ //
+
+
+
+ // READ_SIO_CONFIG_UCHAR(PciControl,DataByte);
+ // These must be BYTE reads and writes to avoid unintentionally writing
+ // other registers
+ PCIReg = READ_REGISTER_UCHAR(((PUCHAR)HalpPciConfigBase + (0x800)) + 0x40);
+
+ // Setup the PCI Control
+ PCIReg |= ENABLE_PCI_POSTED_WRITE_BUFFER
+ | ENABLE_ISA_MASTER_LINE_BUFFER
+ | EANBLE_DMA_LINE_BUFFER;
+ // WRITE_SIO_CONFIG_UCHAR(PciControl, DataByte );
+ WRITE_REGISTER_UCHAR((((PUCHAR)HalpPciConfigBase + (0x800)) + 0x40),
+ PCIReg);
+ //
+ // Disable Guaranteed Access Time Mode
+ //
+
+ READ_SIO_CONFIG_UCHAR(PciArbiterControl,DataByte);
+
+ DataByte &= ~ENABLE_GAT;
+
+ WRITE_SIO_CONFIG_UCHAR(PciArbiterControl, DataByte);
+
+
+
+
+ //
+ // Initialize SuperIO chip
+ //
+
+ if (!HalpInitSuperIo()) {
+ HalDisplayString("Failed to init SuperIo\n");
+ return FALSE;
+ }
+
+
+
+ //
+ // Utility Bus A chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableA,DataByte);
+
+ DataByte |= ENABLE_RTC | ENABLE_KEYBOARD & ~ENABLE_IDE_DECODE;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableA, DataByte);
+
+ //
+ // Utility Bus B chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableB,DataByte);
+
+ DataByte |= ENABLE_RAM_DECODE | ENABLE_PORT92 | DISABLE_PARALLEL_PORT
+ | DISABLE_SERIAL_PORTA | DISABLE_SERIAL_PORTB;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableB, DataByte);
+
+ return TRUE;
+
+}
+
+
+
+/*++
+
+Routine Description: BOOLEAN HalpMapIoControlSpace ()
+
+ This routine maps the HAL SIO control space 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.
+
+--*/
+
+BOOLEAN
+HalpMapIoControlSpace (
+ VOID
+ )
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map SIO control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = IO_CONTROL_PHYSICAL_BASE;
+ HalpIoControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+
+ if (HalpIoControlBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+
+
+
+/*++
+
+Routine Description: VOID HalpDisableSioInterrupt()
+
+ This function Disables the SIO interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ )
+{
+ UCHAR CpuId;
+
+ // Make sure we've been called with interrupts disabled....
+ //
+ HASSERT(!MSR(EE));
+
+ CpuId = (UCHAR)GetCpuId();
+
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ // Remember which interrupts have been turned on or off
+ //
+ registeredInts[CpuId] &= ~(1 << Vector);
+
+ // Change the Hardware mask to prevent the interrupt from
+ // occuring
+ //
+ RInterruptMask(CpuId) &= ~(1 << Vector);
+ WaitForRInterruptMask(CpuId);
+ if (Vector > 15) {
+
+ // Since this vector has no corollary with the SIO
+ // world, don't do any of the following stuff...
+ //
+ return;
+ }
+
+ if (Vector & 0x08) {
+
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ }
+
+}
+
+/*++
+
+Routine Description: VOID HalpIsaMapTransfer()
+
+ This function programs the SIO DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+{
+
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ KIRQL Irql;
+
+
+ ASSERT(Offset >= IO_CONTROL_PHYSICAL_BASE);
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ BytePtr = (PUCHAR) &Offset;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ Length >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = BytePtr[2];
+ Offset >>= 1;
+ BytePtr[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+}
+
+
+
+/*++
+
+Routine Description: VOID HalpEnableSioInterrupt()
+
+ This function enables the SIO interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+{
+
+ ULONG CpuId = GetCpuId();
+
+ HASSERT(!MSR(EE));
+
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ // Make sure we're protected while we muck with the interrupt masks.
+ // since we asserted interrupts disabled on the way in, we can turn them
+ // off here and not worry about turning them on. If DbgPrint didn't
+ // turn ints off, we wouldn't have to worry about it.
+ //
+ // Remember which interrupts have been turned on or off
+ //
+ registeredInts[CpuId] |= (1 << Vector);
+
+ // Turn on the bit in the hardware to allow the interrupt
+ //
+ RInterruptMask(CpuId) |= (1 << Vector);
+ WaitForRInterruptMask(CpuId);
+
+ if (Vector > 0xf) {
+
+ // 15 is the effective MAX_DEV_VECTORS after the device vector
+ // offset is removed
+ //
+ return;
+
+ // Since this vector has no corollary with the SIO
+ // world, don't do any of the following stuff...
+ //
+ }
+ InterruptMode = Latched;
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2EdgeLevel,
+ HalpSioInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1EdgeLevel,
+ HalpSioInterrupt1Level
+ );
+ }
+
+}
+
+/*++
+
+Routine Description: PADAPTER_OBJECT HalpAllocateIsaAdapter()
+
+ This function allocates an ISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+ NumberofMapRegisters - number of map registers required for the adapter
+ object created
+
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+{
+
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG numberOfMapRegisters;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+
+ //
+ // Determine if the the channel number is important. Master cards
+ // do not use a channel number.
+ //
+
+
+ if ((DeviceDescriptor->Master) && (DeviceDescriptor->InterfaceType != Isa)) {
+
+ useChannel = FALSE;
+
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+
+ if (DeviceDescriptor->ScatterGather &&
+ !(DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->Master)) {
+
+
+ //
+ // Scatter gather not supported in SIO
+ //
+
+ if (!DeviceDescriptor->Master)
+
+ //
+ // one map register will be required when the the SIO supports this
+ //
+ // numberOfMapRegisters = 1;
+
+ return NULL;
+
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // If the device is not a master then it only needs one map register
+ // and does scatter/Gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpIsaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpIsaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpIsaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The specified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is significantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER ) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+
+ }
+
+
+ if (DeviceDescriptor->Master && (DeviceDescriptor->InterfaceType == Isa)) {
+
+ adapterObject->IsaBusMaster = TRUE;
+
+ } else {
+
+ adapterObject->IsaBusMaster = FALSE;
+
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+// *NumberOfMapRegisters = numberOfMapRegisters;
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+
+ //
+ // Initialize the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR) channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+/*++
+
+Routine Description: ULONG HalReadDmaCounter()
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transferred.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still to be transferred.
+
+--*/
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+{
+ ULONG count=0;
+ ULONG high;
+
+ if (AdapterObject->PagePort) {
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ }
+
+ return(count);
+}
+
+
+VOID
+HalpHandleIoError (
+ VOID
+ )
+{
+
+ UCHAR StatusByte;
+
+
+ //
+ // Read NMI status
+ //
+
+ StatusByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiStatus);
+
+ //
+ // Test for PCI bus error
+ //
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: IOCHK\n");
+ }
+
+ //
+ // Test for ISA IOCHK
+ //
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: PCI System Error\n");
+ }
+
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxsiosup.h b/private/ntos/nthals/halfire/ppc/pxsiosup.h
new file mode 100644
index 000000000..beb486488
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxsiosup.h
@@ -0,0 +1,231 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxsiosup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the SIO chip set.
+ The SIO_CONTROL structure is a superset of the EISA_CONTROL stucture.
+ Differences from the Eisa control stucture are marked with comments.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxsiosup.h $
+ * $Revision: 1.5 $
+ * $Date: 1996/01/11 07:13:41 $
+ * $Locker: $
+ */
+
+#ifndef _SIO_
+#define _SIO_
+
+
+
+
+
+BOOLEAN
+HalpInitSMCSuperIo (
+ VOID
+ );
+
+BOOLEAN
+HalpInitNationalSuperIo (
+ VOID
+ );
+
+typedef struct _SIO_CONTROL {
+ DMA1_CONTROL Dma1BasePort; // Offset 0x000
+ UCHAR Reserved0[16];
+ UCHAR Interrupt1ControlPort0; // Offset 0x020
+ UCHAR Interrupt1ControlPort1; // Offset 0x021
+ UCHAR Reserved1[32 - 2];
+ UCHAR Timer1; // Offset 0x40
+ UCHAR RefreshRequest; // Offset 0x41
+ UCHAR SpeakerTone; // Offset 0x42
+ UCHAR CommandMode1; // Offset 0x43
+ UCHAR Reserved14[28];
+ UCHAR ResetUbus; // Offset 0x60
+ UCHAR NmiStatus; // Offset 0x61
+ UCHAR Reserved15[14];
+ UCHAR NmiEnable; // Offset 0x70
+ UCHAR Reserved16[7];
+ UCHAR BiosTimer[4]; // Offset 0x78
+ UCHAR Reserved13[4];
+ DMA_PAGE DmaPageLowPort; // Offset 0x080
+ UCHAR Reserved2;
+ UCHAR AlternateReset; // Offset 0x092
+ UCHAR Reserved17[14];
+ UCHAR Interrupt2ControlPort0; // Offset 0x0a0
+ UCHAR Interrupt2ControlPort1; // Offset 0x0a1
+ UCHAR Reserved3[32-2];
+ DMA2_CONTROL Dma2BasePort; // Offset 0x0c0
+ UCHAR CoprocessorError; // Offset 0x0f0
+ UCHAR Reserved4[0x281];
+ UCHAR SecondaryFloppyOutput; // Offset 0x372
+ UCHAR Reserved18[0x27];
+ UCHAR Reserved21[0x59];
+ UCHAR PrimaryFloppyOutput; // Offset 0x3f2
+ UCHAR Reserved5[19];
+ UCHAR Dma1ExtendedModePort; // Offset 0x40b
+ UCHAR Reserved6[4];
+ UCHAR Channel0ScatterGatherCommand; // Offset 0x410
+ UCHAR Channel1ScatterGatherCommand; // Offset 0x411
+ UCHAR Channel2ScatterGatherCommand; // Offset 0x412
+ UCHAR Channel3ScatterGatherCommand; // Offset 0x413
+ UCHAR Reserved19; // Offset 0x414
+ UCHAR Channel5ScatterGatherCommand; // Offset 0x415
+ UCHAR Channel6ScatterGatherCommand; // Offset 0x416
+ UCHAR Channel7ScatterGatherCommand; // Offset 0x417
+ UCHAR Channel0ScatterGatherStatus; // Offset 0x418
+ UCHAR Channel1ScatterGatherStatus; // Offset 0x419
+ UCHAR Channel2ScatterGatherStatus; // Offset 0x41a
+ UCHAR Channel3ScatterGatherStatus; // Offset 0x41b
+ UCHAR Reserved20; // Offset 0x41c
+ UCHAR Channel5ScatterGatherStatus; // Offset 0x41d
+ UCHAR Channel6ScatterGatherStatus; // Offset 0x41e
+ UCHAR Channel7ScatterGatherStatus; // Offset 0x41f
+ UCHAR Channel0ScatterGatherTable[4]; // Offset 0x420
+ UCHAR Channel1ScatterGatherTable[4]; // Offset 0x424
+ UCHAR Channel2ScatterGatherTable[4]; // Offset 0x428
+ UCHAR Channel3ScatterGatherTable[4]; // Offset 0x42c
+ UCHAR Reserved22[4]; // Offset 0x430
+ UCHAR Channel5ScatterGatherTable[4]; // Offset 0x434
+ UCHAR Channel6ScatterGatherTable[4]; // Offset 0x438
+ UCHAR Channel7ScatterGatherTable[4]; // Offset 0x43c
+ UCHAR Reserved8[0x40];
+ DMA_PAGE DmaPageHighPort; // Offset 0x480
+ UCHAR Reserved10[70];
+ UCHAR Dma2ExtendedModePort; // Offset 0x4d6
+} SIO_CONTROL, *PSIO_CONTROL;
+
+
+
+typedef struct _SIO_CONFIG {
+ UCHAR VendorId[2]; // Offset 0x00 read-only
+ UCHAR DeviceId[2]; // Offset 0x02 read-only
+ UCHAR Command[2]; // Offset 0x04 unused
+ UCHAR DeviceStatus[2]; // Offset 0x06
+ UCHAR RevisionId; // Offset 0x08 read-only
+ UCHAR Reserved1[0x37]; // Offset 0x09
+ UCHAR PciControl; // Offset 0x40
+ UCHAR PciArbiterControl; // Offset 0x41
+ UCHAR PciArbiterPriorityControl; // Offset 0x42
+ UCHAR Reserved2; // Offset 0x43
+ UCHAR MemCsControl; // Offset 0x44
+ UCHAR MemCsBottomOfHole; // Offset 0x45
+ UCHAR MemCsTopOfHole; // Offset 0x46
+ UCHAR MemCsTopOfMemory; // Offset 0x47
+ UCHAR IsaAddressDecoderControl; // Offset 0x48
+ UCHAR IsaAddressDecoderRomEnable; // Offset 0x49
+ UCHAR IsaAddressDecoderBottomOfHole; // Offset 0x4a
+ UCHAR IsaAddressDecoderTopOfHole; // Offset 0x4b
+ UCHAR IsaControllerRecoveryTimer; // Offset 0x4c
+ UCHAR IsaClockDivisor; // Offset 0x4d
+ UCHAR UtilityBusEnableA; // Offset 0x4e
+ UCHAR UtilityBusEnableB; // Offset 0x4f
+ UCHAR Reserved3[4]; // Offset 0x50
+ UCHAR MemCsAttribute1; // Offset 0x54
+ UCHAR MemCsAttribute2; // Offset 0x55
+ UCHAR MemCsAttribute3; // Offset 0x56
+ UCHAR ScatterGatherBaseAddress; // Offset 0x57
+ UCHAR Reserved4[0x8]; // Offset 0x58
+ UCHAR PciIrq0RouteControl; // Offset 0x60
+ UCHAR PciIrq1RouteControl; // Offset 0x61
+ UCHAR PciIrq2RouteControl; // Offset 0x62
+ UCHAR PciIrq3RouteControl; // Offset 0x63
+ UCHAR Reserved5[0x1C]; // Offset 0x64
+ UCHAR BiosTimerBaseAddress[2]; // Offset 0x80
+}SIO_CONFIG, *PSIO_CONFIG;
+
+
+//
+// Define constants used by SIO config
+//
+
+
+// PCI control register - bit values
+#define ENABLE_PCI_POSTED_WRITE_BUFFER 0x04
+#define ENABLE_ISA_MASTER_LINE_BUFFER 0x02
+#define EANBLE_DMA_LINE_BUFFER 0x01
+
+// PCI Arbiter contol register - bit values
+#define ENABLE_GAT 0x01
+
+
+// ISA CLock Divisor register - bit values
+#define ENABLE_COPROCESSOR_ERROR 0x20
+#define ENABLE_MOUSE_SUPPORT 0x10
+#define RSTDRV 0x08
+#define SYSCLK_DIVISOR 0x00
+
+//Utility Bus Chip Select A - bit values
+#define ENABLE_RTC 0x01
+#define ENABLE_KEYBOARD 0x02
+#define ENABLE_IDE_DECODE 0x10
+
+//Utility Bus Chip Select B - bit values
+#define ENABLE_RAM_DECODE 0x80
+#define ENABLE_PORT92 0x40
+#define DISABLE_PARALLEL_PORT 0x30
+#define DISABLE_SERIAL_PORTB 0x0c
+#define DISABLE_SERIAL_PORTA 0x03
+
+// Interrupt controller - bit values
+#define LEVEL_TRIGGERED 0x08
+#define SINGLE_MODE 0x02
+
+// NMI status/control - bit values
+#define DISABLE_IOCHK_NMI 0x08
+#define DISABLE_PCI_SERR_NMI 0x04
+
+// NMI enable - bit values
+#define DISABLE_NMI 0x80
+
+// DMA command - bit values
+#define DACK_ASSERT_HIGH 0x80
+#define DREQ_ASSERT_LOW 0x40
+#endif
+
+//
+// Define 8259 constants
+//
+
+#define SPURIOUS_VECTOR 7
+#define HIGHEST_8259_VECTOR 15
+//
+// Define 8254 timer constants
+//
+
+//
+// Convert the interval to rollover count for 8254 Timer1 device.
+// Since timer1 counts down a 16 bit value at a rate of 1.193M counts-per-
+// sec, the computation is:
+// RolloverCount = (Interval * 0.0000001) * (1.193 * 1000000)
+// = Interval * 0.1193
+// = Interval * 1193 / 10000
+//
+//
+
+
+
+#define COMMAND_8254_COUNTER0 0x00 // Select count 0
+#define COMMAND_8254_RW_16BIT 0x30 // Read/Write LSB firt then MSB
+#define COMMAND_8254_MODE2 0x4 // Use mode 2
+#define COMMAND_8254_BCD 0x0 // Binary count down
+#define COMMAND_8254_LATCH_READ 0x0 // Latch read command
diff --git a/private/ntos/nthals/halfire/ppc/pxstall.s b/private/ntos/nthals/halfire/ppc/pxstall.s
new file mode 100644
index 000000000..d10f24ccb
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxstall.s
@@ -0,0 +1,390 @@
+//#***********************************************************************
+//
+//
+//
+//
+// Copyright 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.
+//
+// Copyright 1993 International Buisness Machines Corporation.
+// All Rights Reserved.
+//
+// This file contains copyrighted material. Use of this file is
+// restricted by the provisions of a Motorola/IBM Joint Software
+// License Agreement.
+//
+// File Name:
+// PXSTALL.S
+//
+// Functions:
+// KeStallExecutionProcessor
+// HalpCalibrateStall
+//
+// History:
+// 21-Sep-1993 Steve Johns
+// Original Version
+// 24-Dec-1993 Peter Johnston
+// Adapted to 601 HAL in an attempt to avoid having different
+// versions if at all possible. Original was designed for both
+// 601 and 603 but had some 601 difficulties.
+// 17-Jan-1994 Steve Johns
+// Changed to treat 601 vs PowerPC time base differences more
+// transparently.
+//
+//#***********************************************************************
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxstall.s $
+ * $Revision: 1.6 $
+ * $Date: 1996/01/11 07:13:48 $
+ * $Locker: $
+ */
+
+
+#include "kxppc.h"
+
+#define ERRATA603 TRUE
+#define RTCU 4
+#define RTCL 5
+#define CMOS_INDEX 0x70
+#define CMOS_DATA 0x71
+#define RTC_SECOND 0x80
+
+
+ .extern HalpPerformanceFrequency
+ .extern HalpIoControlBase
+ .extern ..HalpDivide
+
+//
+// Register Definitions
+//
+ .set Microsecs, r.3
+ .set TimerLo , r.6 // MUST be same as defined in PXCLKSUP.S
+ .set TimerHi , r.7 // MUST be same as defined in PXCLKSUP.S
+ .set EndTimerLo, r.3
+ .set EndTimerHi, r.4
+ .set Temp , r.8
+ .set Temp2 , r.9
+ .set IO_Base , r.10
+
+//#***********************************************************************
+//
+// Synopsis:
+// VOID KeStallExecutionProcessor(
+// ULONG Microseconds)
+//
+// Purpose:
+// This function stalls the execution at least the specified number
+// of microseconds, but not substantially longer.
+//
+// Returns:
+// Nothing.
+//
+// Global Variables Referenced:
+// HalpPerformanceFrequency
+//#***********************************************************************
+
+ SPECIAL_ENTRY(KeStallExecutionProcessor)
+ mflr r.0 // Save Link Register
+ PROLOGUE_END(KeStallExecutionProcessor)
+
+ cmpli 0,0,Microsecs,0 // if (Microseconds == 0)
+ beqlr- // return;
+
+ bl ..HalpGetTimerRoutine // Get appropriate timer routine
+//
+// Read START time
+//
+ bctrl // ReadPerformanceCounter();
+
+//
+// Get PerformanceCounter frequency
+//
+ lwz Temp,[toc]HalpPerformanceFrequency(r.toc)
+ lwz Temp,0(Temp)
+//
+// Compute: (Microseconds * PerformanceFrequency) / 1,000,000
+//
+ mulhwu. EndTimerHi,Microsecs,Temp
+ mullw EndTimerLo,Microsecs,Temp
+
+
+
+ LWI (r.5, 1000000)
+ bl ..HalpDivide
+
+//
+// Account for software overhead
+//
+ .set Overhead, 30
+ cmpwi r.3, Overhead
+ ble SkipOverhead
+ addi r.3, r.3, -Overhead // Reduce delay
+SkipOverhead:
+
+//
+// Add delay to start time
+//
+ addc EndTimerLo, TimerLo, r.3
+ addze EndTimerHi, TimerHi
+
+
+
+//
+// while (ReadPerformanceCounter() < EndTimer);
+//
+StallLoop:
+ bctrl // ReadPerformanceCounter();
+ cmpl 0,0,TimerHi,EndTimerHi // Is TimerHi >= EndTimerHi ?
+ blt- StallLoop // No
+ bgt+ StallExit // Yes
+ cmpl 0,0,TimerLo,EndTimerLo // Is TimerLo >= EndTimerLo ?
+ blt StallLoop // Branch if not
+
+StallExit:
+ mtlr r.0 // Restore Link Register
+
+ SPECIAL_EXIT(KeStallExecutionProcessor)
+
+
+
+
+
+//
+// This routine is the ReadPerformanceCounter routine for the 601 processor.
+// The 601 RTC counts discontinuously (1 is added to RTCU when the value in
+// RTCL passes 999,999,999). This routine converts the RTC count to a
+// continuous 64-bit count by calculating:
+//
+// ((RTC.HighPart * 1,000,000,000) + RTC.LowPart) / 128
+//
+//
+ LEAF_ENTRY (ReadRTC)
+
+ mfspr TimerHi,RTCU // Read the RTC registers coherently
+ mfspr TimerLo,RTCL
+ mfspr Temp,RTCU
+ cmpl 0,0,TimerHi,Temp
+ bne- ..ReadRTC
+
+ lis Temp,(1000000000 >> 16) // RTC.HighPart * 1,000,000
+ ori Temp,Temp,(1000000000 & 0xFFFF)
+ mullw Temp2,Temp,TimerHi
+ mulhwu Temp,Temp,TimerHi
+ addc TimerLo,Temp2,TimerLo // + RTC.LowPart
+ addze TimerHi,Temp
+//
+// Each tick increments the RTC by 128, so let's divide that out.
+//
+ mr Temp,TimerHi // Divide 64-bit value by 128
+ rlwinm TimerLo,TimerLo,32-7,7,31
+ rlwinm TimerHi,TimerHi,32-7,7,31
+ rlwimi TimerLo,Temp,32-7,0,6
+
+ LEAF_EXIT (ReadRTC)
+
+
+
+
+
+//
+// This routine is the ReadPerformanceCounter routine for PowerPC
+// architectures (not the 601).
+//
+ LEAF_ENTRY (ReadTB)
+
+ mftbu TimerHi // Read the TB registers coherently
+ mftb TimerLo
+#if ERRATA603
+ mftb TimerLo
+ mftb TimerLo
+ mftb TimerLo
+#endif
+ mftbu Temp
+ cmpl 0,0,Temp,TimerHi
+ bne- ..ReadTB
+
+ LEAF_EXIT (ReadTB)
+
+
+//
+// Returns in the Count Register the entry point for the routine
+// that reads the appropriate Performance Counter (ReadRTC or ReadTB).
+//
+// Called from KeQueryPerformanceCounter and KeStallExecutionProcessor
+//
+ LEAF_ENTRY (HalpGetTimerRoutine)
+
+ mfpvr Temp // Read Processor Version Register
+ rlwinm Temp,Temp,16,16,31
+ cmpli 0,0,Temp,1 // Are we running on an MPC601 ?
+ lwz Temp,[toc]ReadTB(r.toc)
+ bne+ GetEntryPoint // Branch if not
+
+ lwz Temp,[toc]ReadRTC(r.toc)
+
+GetEntryPoint:
+ lwz Temp,0(Temp) // Get addr to ReadRTC or ReadTB
+ mtctr Temp
+
+ LEAF_EXIT (HalpGetTimerRoutine)
+
+
+
+
+
+//
+// Returns the number of performance counter ticks/second.
+//
+// The DECREMENTER is clocked at the same rate as the PowerPC Time Base (TB)
+// and the POWER RTC. The POWER RTC is supposed to be clocked at 7.8125 MHz,
+// but on early prototypes of the Sandalfoot platform, this is not true).
+// In either case, to keep the calibration routine simple and generic, we
+// will determine the DECREMENTER clock rate by counting ticks for exactly
+// 1 second (as measured against the CMOS RealTimeClock). We then use that
+// value in the KeStallExecutionProcessor() and KeQueryPerformanceCounter()
+//
+
+ LEAF_ENTRY(HalpCalibrateTB)
+
+ // Get base address of ISA I/O space so we can talk to the CMOS RTC
+ lwz IO_Base,[toc]HalpIoControlBase(r.toc)
+ lwz IO_Base,0(IO_Base)
+
+
+ li r.3,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,CMOS_INDEX(IO_Base) // Write CMOS index
+ eieio
+ lbz r.4,CMOS_DATA(IO_Base) // Read CMOS data
+
+
+WaitForTick1:
+ li r.3,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,CMOS_INDEX(IO_Base) // Write CMOS index
+ eieio
+ lbz r.3,CMOS_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4 // Loop until it changes
+ beq+ WaitForTick1
+
+
+ li r.4,-1 // Start the decrementer at max. count
+ mtdec r.4
+#if ERRATA603
+ isync
+#endif
+
+WaitForTick2:
+ li r.4,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.4,CMOS_INDEX(IO_Base) // Write CMOS index
+ eieio
+ lbz r.4,CMOS_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4
+ beq+ WaitForTick2
+
+ mfdec r.3 // Read the decrementer
+ neg r.3,r.3 // Compute delta ticks
+
+ mfpvr Temp // Read Processor Version Register
+ rlwinm Temp,Temp,16,16,31
+ cmpli 0,0,Temp,1 // if (CPU != 601)
+ bnelr // return(r.3);
+//
+// On the 601, the DECREMENTER decrements every ns, so the 7 LSBs are
+// not implemented.
+//
+ rlwinm r.3,r.3,32-7,7,31 // Divide count by 128
+
+
+ LEAF_EXIT(HalpCalibrateTB)
+
+
+
+ LEAF_ENTRY(HalpCalibrateTBPStack)
+
+#define NVRAM_INDEX_LO 0x74
+#define NVRAM_INDEX_HI 0x75
+#define NVRAM_DATA 0x77
+#define RTC_OFFSET 0x1ff8
+#define RTC_CONTROL 0x0
+// *BJ* Fix later.
+#undef RTC_SECOND
+#define RTC_SECOND 0x1
+#define RTC_MINUTE 0x2
+
+#define SYNCHRONIZE \
+ lwz Temp,[toc]HalpIoControlBase(r.toc);\
+ stw Temp,[toc]HalpIoControlBase(r.toc);\
+ nop;\
+ sync
+
+
+ // Get base address of ISA I/O space so we can talk to the CMOS RTC
+ lwz IO_Base,[toc]HalpIoControlBase(r.toc)
+ lwz IO_Base,0(IO_Base)
+
+
+ li r.3,RTC_OFFSET+ RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,NVRAM_INDEX_LO(IO_Base) // Write CMOS index lo
+ rlwinm r.3,r.3,32-8,24,31 // Shift > 8 and mask 0xff
+ stb r.3,NVRAM_INDEX_HI(IO_Base) // Write CMOS index hi
+ SYNCHRONIZE
+ lbz r.3,NVRAM_DATA(IO_Base) // Read CMOS data
+
+WaitForTick0.Ps:
+ li r.4,RTC_OFFSET+ RTC_SECOND // Read seconds from CMOS RTC
+ stb r.4,NVRAM_INDEX_LO(IO_Base) // Write CMOS index lo
+ rlwinm r.4,r.4,32-8,24,31 // Shift > 8 and mask 0xff
+ stb r.4,NVRAM_INDEX_HI(IO_Base) // Write CMOS index hi
+ SYNCHRONIZE
+ lbz r.4,NVRAM_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4 // Loop until it changes
+ beq+ WaitForTick0.Ps
+
+
+WaitForTick1.Ps:
+ li r.3,RTC_OFFSET+ RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,NVRAM_INDEX_LO(IO_Base) // Write CMOS index lo
+ rlwinm r.3,r.3,32-8,24,31 // Shift > 8 and mask 0xff
+ stb r.3,NVRAM_INDEX_HI(IO_Base) // Write CMOS index hi
+ SYNCHRONIZE
+ lbz r.3,NVRAM_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4 // Loop until it changes
+ beq+ WaitForTick1.Ps
+
+
+ li r.4,-1 // Start the decrementer at max. count
+ mtdec r.4
+#if ERRATA603
+ isync
+#endif
+
+WaitForTick2.Ps:
+ li r.4,RTC_OFFSET+ RTC_SECOND // Read seconds from CMOS RTC
+ stb r.4,NVRAM_INDEX_LO(IO_Base) // Write CMOS index lo
+ rlwinm r.4,r.4,32-8,24,31 // Shift > 8 and mask 0xff
+ stb r.4,NVRAM_INDEX_HI(IO_Base) // Write CMOS index hi
+ SYNCHRONIZE
+ lbz r.4,NVRAM_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4
+ beq+ WaitForTick2.Ps
+
+ mfdec r.3 // Read the decrementer
+ neg r.3,r.3 // Compute delta ticks
+
+ mfpvr Temp // Read Processor Version Register
+ rlwinm Temp,Temp,16,16,31
+ cmpli 0,0,Temp,1 // if (CPU != 601)
+ bnelr // return(r.3);
+//
+// On the 601, the DECREMENTER decrements every ns, so the 7 LSBs are
+// not implemented.
+//
+ rlwinm r.3,r.3,32-7,7,31 // Divide count by 128
+
+ LEAF_EXIT(HalpCalibrateTBPStack)
+
+
diff --git a/private/ntos/nthals/halfire/ppc/pxsysbus.c b/private/ntos/nthals/halfire/ppc/pxsysbus.c
new file mode 100644
index 000000000..651dae898
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxsysbus.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxsysbus.c $
+ * $Revision: 1.30 $
+ * $Date: 1996/07/13 01:16:01 $
+ * $Locker: $
+ */
+
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxsysbus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+ Jim Wooldridge - ported to PowerPC
+
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <arccodes.h>
+#include "fpdebug.h"
+#include "halp.h"
+#include "phsystem.h"
+#include "eisa.h"
+#include "pxmemctl.h"
+
+extern ULONG Vector2Irql[];
+extern ULONG Vector2Affinity[];
+
+//
+// Which Ints on Processor 1?
+//
+BOOLEAN HalpGetAffinityCalled = FALSE;
+
+
+#define TBS " "
+
+void
+HalpGetAffinity();
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+{
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+
+ TranslatedAddress->HighPart = BusAddress.HighPart;
+
+
+
+ //
+ // Determine the address based on whether the bus address
+ // is in I/O space, system space, or bus memory space.
+ //
+
+ switch (*AddressSpace) {
+ case MEMORY_ADDRESS_SPACE:
+ //
+ // The address is in memory space.
+ //
+ TranslatedAddress->LowPart = BusAddress.LowPart +
+ PCI_MEMORY_PHYSICAL_BASE;
+ if (VER_PRODUCTBUILD > 1233) {
+ //
+ // Due to a change in NT defined spaces, our previous method
+ // of using AddressSpace to communicate a driver's mapping
+ // needs no longer will work. So, starting with Build 1297
+ // we need to make sure the display driver is not mapped into
+ // the PCI_MEMORY_PHYSICAL_BASE but into it's "natural"
+ // location.
+ //
+ // This is a temp fix and must be revisited so that we
+ // can more specifically detect the framebuffer based
+ // driver requirements and not affect other devices that
+ // may have a legitimate need for this address offset into
+ // a bus location.
+ //
+ if ((BusAddress.LowPart&0xf0000000)==(0x70000000)) {
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ }
+ }
+ break;
+ //
+ // Everyone should be assumed IO space if not otherwise requested
+ //
+ default:
+ case IO_ADDRESS_SPACE:
+ //
+ // The address is in I/O space.
+ //
+ TranslatedAddress->LowPart = BusAddress.LowPart +
+ IO_CONTROL_PHYSICAL_BASE;
+ break;
+ case SYSTEM_ADDRESS_SPACE:
+ //
+ // The address is in system space.
+ //
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ break;
+ }
+
+ *AddressSpace = 0;
+
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+ //
+ // A carry occurred.
+ //
+ TranslatedAddress->HighPart += 1;
+
+ }
+
+ return(TRUE);
+}
+
+/*++
+
+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
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+{
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+ UNREFERENCED_PARAMETER( BusInterruptLevel );
+
+ if (HalpGetAffinityCalled == FALSE) {
+ HalpGetAffinity();
+ HalpGetAffinityCalled = TRUE;
+ }
+
+ *Affinity = Vector2Affinity[BusInterruptVector];
+
+ HDBG(DBG_INTERRUPTS|DBG_MPINTS,
+ HalpDebugPrint("HalpGetSystemInterruptVector: %x, %x, %d, %x\n",
+ BusInterruptLevel, BusInterruptVector, *Irql, *Affinity););
+
+
+ *Irql = (UCHAR) Vector2Irql[BusInterruptVector]; // see define in ntdef.h
+
+ //
+ // The vector is equal to the specified bus level plus the DEVICE_VECTORS.
+ //
+ BusInterruptLevel = BusInterruptVector;
+ HDBG(DBG_INTERRUPTS|DBG_MPINTS,
+ HalpDebugPrint( "%sint request: returning %x + %x = %x\n",
+ TBS, BusInterruptVector, DEVICE_VECTORS,
+ BusInterruptVector + DEVICE_VECTORS ););
+ return(BusInterruptVector + DEVICE_VECTORS);
+
+}
+
+//
+// HalpGetAffinity()
+//
+// This is a simple routine that gets a value from NVRAM to
+// overwrite the default value for where interrupts go.
+// This is mostly a hack for now.
+//
+void
+HalpGetAffinity()
+{
+ CHAR buf[256];
+ PKPRCB pPRCB;
+ ULONG count;
+ extern HalpInitProcAffinity(PCHAR,ULONG);
+
+ if ((count = HalpProcessorCount()) < 2) {
+ HalpInitProcAffinity((PCHAR)0,1);
+ return;
+ }
+
+ pPRCB = KeGetCurrentPrcb();
+ if (pPRCB->BuildType & PRCB_BUILD_UNIPROCESSOR) {
+ HalpInitProcAffinity((PCHAR)0,1);
+ return;
+ }
+
+ if (HalGetEnvironmentVariable("UNIPROCESSOR", sizeof(buf), buf)
+ == ESUCCESS) {
+ if (_stricmp(buf, "true") == 0) {
+ HalpInitProcAffinity((PCHAR)0,1);
+ return;
+ }
+ }
+
+ // it is mulitprocessor system.
+ //
+ // Get PROCNINTS Value from NVRAM
+ //
+ if (HalGetEnvironmentVariable("PROCNINTS", sizeof(buf), buf)
+ == ESUCCESS) {
+ HalpInitProcAffinity(buf,count);
+ return;
+ } else {
+ HalpInitProcAffinity((PCHAR)0,count);
+ return;
+ }
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxsysint.c b/private/ntos/nthals/halfire/ppc/pxsysint.c
new file mode 100644
index 000000000..39ff55351
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxsysint.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxsysint.c $
+ * $Revision: 1.12 $
+ * $Date: 1996/05/14 02:35:34 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991-1993 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:
+
+ pxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a Power PC.
+
+
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge
+
+ Removed internal interrupt support
+ Changed irql mapping
+ Removed internal bus support
+ Removed EISA, added PCI, PCMCIA, and ISA bus support
+
+ Steve Johns
+ Changed to support Timer 1 as profile interrupt
+ Added HalAcknowledgeIpi
+--*/
+
+#include "halp.h"
+#include "phsystem.h"
+#include "fpdebug.h"
+
+
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrupt.
+ //
+
+ if (Vector >= DEVICE_VECTORS &&
+ //
+ // For FirePOWER, allowable external device interrupts spans 32 bits
+ // not the 16 of sandalfoot ( or SIO ) architecture. The 16 bit limits
+ // will be enforced in HalpDisableSioInterrupts. We'll do our normal
+ // system interrupt stuff there for now but should move the system
+ // register activity to here and leave the SIO disable routine to deal
+ // ONLY with the SIO stuff.
+ //
+ Vector < (DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR + 16) ) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrupt and set the Level/Edge register.
+ //
+
+
+ if (Vector >= DEVICE_VECTORS &&
+ //
+ // For FirePOWER, allowable external device interrupts spans 32 bits
+ // not the 16 of sandalfoot ( or SIO ) architecture. The 16 bit limits
+ // will be enforced in HalpEnableSioInterrupts. We'll do our normal
+ // system interrupt stuff there for now but should move the system
+ // register activity to here and leave the SIO enable routine to deal
+ // ONLY with the SIO stuff.
+ //
+ Vector < (DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR + 16) ) {
+ HalpEnableSioInterrupt(Vector, InterruptMode);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+VOID
+HalRequestIpi(IN ULONG Mask)
+{
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+ rCPUMessageInterruptSet = Mask;
+ FireSyncRegister();
+ return;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine aknowledges an interprocessor interrupt on a set of
+ processors.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if the IPI is valid; otherwise FALSE is returned.
+
+--*/
+BOOLEAN
+HalAcknowledgeIpi (VOID)
+{
+ //
+ // Use this call to clear the interrupt from the Req register
+ //
+ rCPUMessageInterrupt = (ULONG)(1 << GetCpuId());
+ FireSyncRegister();
+ return (TRUE);
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxtime.c b/private/ntos/nthals/halfire/ppc/pxtime.c
new file mode 100644
index 000000000..450b6856f
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxtime.c
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxtime.c $
+ * $Revision: 1.14 $
+ * $Date: 1996/05/20 22:36:01 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991 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:
+
+ pxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a PowerPC system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial Power PC port
+
+ Change real time clock mapping to port 71.
+ Code assumes the DS1385S chip is compatible with existing
+ PC/AT type RTC's. The only known exception to PC/AT
+ compatibility on S-FOOT is the use of ports 810 and 812.
+ These ports provide password security for the RTC's NVRAM,
+ and are currently unused in this port since this address space
+ is available from kernel mode only in NT.
+
+ Steve Johns (sjohns@pets.sps.mot.com)
+ Changed to support years > 1999
+
+--*/
+
+#include "fpdebug.h"
+#include "halp.h"
+#include "pxrtcsup.h"
+#include "fpreg.h"
+#include "fpio.h"
+#include "fpds1385.h"
+#include "eisa.h"
+
+
+extern BOOLEAN RtcBinaryMode;
+extern BOOLEAN RtcFailure;
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+BOOLEAN
+HalQueryRealTimeClock (OUT PTIME_FIELDS TimeFields)
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+ BOOLEAN retVal = FALSE;
+
+ //
+ // Acquire the RTC spin lock to synchronize the collection of
+ // accesses to the RTC
+ KeAcquireSpinLock(&HalpRTCLock, &OldIrql);
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+ DataByte = HalpDS1385ReadReg(RTC_CONTROL_REGISTERD);
+
+ //
+ // Make sure the time is valid before setting values:
+ //
+ if ((DataByte & RTC_VRT ) == RTC_VRT) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpDS1385ReadReg(RTC_CONTROL_REGISTERA);
+ } while( (DataByte & RTC_UIP) == RTC_UIP);
+
+ //
+ // According to the chip spec, the only way to read the chip that
+ // is guarenteed to give a coherent time is to assert the SET bit;
+ // this essentially prevents the chip from updating the user visible
+ // copy of the time while we are reading it. Since the time will
+ // not update, there is the possiblity that we will loose a second.
+ //
+ DataByte = HalpDS1385ReadReg(RTC_CONTROL_REGISTERB);
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERB,
+ (UCHAR)((DataByte & ~RTC_UIE) | RTC_SET));
+
+ // Reset the failure flag (see below)
+ RtcFailure = FALSE;
+
+ // Read the values
+ TimeFields->Year = 1900 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ if (TimeFields->Year < 1980) TimeFields->Year += 100;
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday =
+ (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+
+ //
+ // Release the SET bit
+ //
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // We have a problem reading the RTC; see HalpDS1385ReadReg in
+ // fpds1385.c for a description. If we detect an
+ // error, that routine asserts RtcFailure. Use that value here.
+ //
+ retVal = !RtcFailure;
+ }
+
+ KeReleaseSpinLock(&HalpRTCLock, OldIrql);
+ return retVal;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+BOOLEAN
+HalSetRealTimeClock (IN PTIME_FIELDS TimeFields)
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+ BOOLEAN retVal = FALSE;
+
+ //
+ // Acquire the RTC spin lock to synchronize the collection of
+ // accesses to the RTC
+ KeAcquireSpinLock(&HalpRTCLock, &OldIrql);
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+ DataByte = HalpDS1385ReadReg(RTC_CONTROL_REGISTERD);
+
+ if (( DataByte & RTC_VRT ) == RTC_VRT) {
+ //
+ // Set the realtime clock control to set the time.
+ // RMW the control byte so we don't lose it's setup
+ //
+ DataByte = HalpDS1385ReadReg(RTC_CONTROL_REGISTERB);
+
+ //
+ // set control parameters: leave daylight savings disabled
+ // since the control program needs to know and has no way of
+ // passing that info in to here.
+ //
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERB,
+ (UCHAR)((DataByte & ~RTC_UIE) | RTC_SET));
+
+ //
+ // Write the realtime clock values.
+ //
+
+ if ( TimeFields->Year > 1999 ) {
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 2000));
+ } else {
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1900));
+ }
+
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK,
+ (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Release the realtime clock control to update the time.
+ //
+ HalpDS1385WriteReg(RTC_CONTROL_REGISTERB, DataByte);
+
+ retVal = TRUE;
+ }
+
+ KeReleaseSpinLock(&HalpRTCLock, OldIrql);
+ return retVal;
+}
+
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+ change return value from BCD to binary integer. I think the chip
+ can be configured to do this,... but as a quick fix I am doing it
+ here. (plj)
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+UCHAR
+HalpReadClockRegister (UCHAR Register)
+{
+ UCHAR BcdValue;
+
+ BcdValue = HalpDS1385ReadReg(Register);
+
+ //
+ // If the data mode is BCD, calculate the return value as BCD:
+ //
+ if ( FALSE == RtcBinaryMode ) {
+ BcdValue = (BcdValue >> 4) * 10 + (BcdValue & 0x0f);
+ }
+ return (BcdValue) ;
+}
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+{
+ UCHAR BcdValue;
+
+ if (TRUE == RtcBinaryMode) {
+ BcdValue = Value;
+ } else {
+ BcdValue = ((Value / 10) << 4) | (Value % 10);
+ }
+
+ //
+ // Now insert the value into the RTC register
+ //
+ HalpDS1385WriteReg(Register, BcdValue);
+
+ return;
+}
diff --git a/private/ntos/nthals/halfire/ppc/pxusage.c b/private/ntos/nthals/halfire/ppc/pxusage.c
new file mode 100644
index 000000000..75d3b0fd5
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxusage.c
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: pxusage.c $
+ * $Revision: 1.6 $
+ * $Date: 1996/01/11 07:14:14 $
+ * $Locker: $
+ */
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxusage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Array to remember hal's IDT usage
+//
+
+extern ADDRESS_USAGE *HalpAddressUsageList;
+extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+
+KAFFINITY HalpActiveProcessors;
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpEnableInterruptHandler)
+#pragma alloc_text(INIT,HalpRegisterVector)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+
+
+/*++
+
+Routine Description: BOOLEAN HalpEnableInterruptHandler ()
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+BOOLEAN
+HalpEnableInterruptHandler (
+ IN PKINTERRUPT Interrupt,
+ IN PKSERVICE_ROUTINE ServiceRoutine,
+ IN PVOID ServiceContext,
+ IN PKSPIN_LOCK SpinLock OPTIONAL,
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KIRQL SynchronizeIrql,
+ IN KINTERRUPT_MODE InterruptMode,
+ IN BOOLEAN ShareVector,
+ IN CCHAR ProcessorNumber,
+ IN BOOLEAN FloatingSave,
+ IN UCHAR ReportFlags,
+ IN KIRQL BusVector
+ )
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+
+ KeInitializeInterrupt( Interrupt,
+ ServiceRoutine,
+ ServiceContext,
+ SpinLock,
+ Vector,
+ Irql,
+ SynchronizeIrql,
+ InterruptMode,
+ ShareVector,
+ ProcessorNumber,
+ FloatingSave
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ if (!KeConnectInterrupt( Interrupt )) {
+ HalDisplayString("HalpEnableInterruptHandler: no connect \n");
+
+ return(FALSE);
+ }
+
+ HalpRegisterVector (ReportFlags, BusVector, Vector, Irql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+ return(TRUE);
+
+
+}
+
+
+
+/*++
+
+Routine Description: VOID HalpRegisterVector ()
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+
+/*++
+
+Routine Description: VOID HalpGetResourceSortValue ()
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ *sortvalue = RtlConvertUlongToLargeInteger(
+ pRCurLoc->u.Interrupt.Level );
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ *sortvalue = RtlConvertUlongToLargeInteger (0);
+ break;
+ }
+}
+
+/*++
+
+Routine Description: VOID HalpReportResourceUsage ()
+
+Arguments:
+
+Return Value:
+
+--*/
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList=NULL, pTPartList=NULL;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+
+ for(i=0; i < DEVICE_VECTORS; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+
+ for(pass=0; pass < 2; pass++) {
+ if (pass == 0) {
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ } else {
+
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TPartialDesc.u.Memory.Start ); // translated address
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+}
diff --git a/private/ntos/nthals/halfire/ppc/sysbios.c b/private/ntos/nthals/halfire/ppc/sysbios.c
new file mode 100644
index 000000000..9aa6dc90c
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/sysbios.c
@@ -0,0 +1,73 @@
+/*++
+
+
+Copyright (C) 1996 Motorola Inc.
+
+Module Name:
+
+ sysbios.c
+
+Abstract:
+
+ Emulate System BIOS functions.
+
+Author:
+
+ Scott Geranen
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "emulate.h"
+#include "sysbios.h"
+#include "pcibios.h"
+
+BOOLEAN
+HalpEmulateSystemBios(
+ IN OUT PRXM_CONTEXT P,
+ IN ULONG Number
+ )
+/*++
+
+Routine Description:
+
+ This function emulates a system BIOS. However, this is really
+ intended to support video bios functions, not all system BIOS
+ functions are implemented.
+
+Arguments:
+
+ P - Supplies a pointer to an emulator context structure.
+ Number - interrupt number used to enter
+
+Return Value:
+
+ TRUE = the function was emulated
+ FALSE = the function was not emulated
+
+--*/
+{
+ switch (Number) {
+ case 0x1A:
+ if (P->Gpr[EAX].Xh == PCIBIOS_PCI_FUNCTION_ID) {
+ return HalpEmulatePciBios(P);
+ }
+
+ //
+ // Fall into the default case.
+ //
+
+ default:
+ return FALSE; // not supported
+ }
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/sysbios.h b/private/ntos/nthals/halfire/ppc/sysbios.h
new file mode 100644
index 000000000..6119bc2d0
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/sysbios.h
@@ -0,0 +1,31 @@
+/*++ BUILD Version: 0000 // Increment this if a change has global effects
+
+Copyright (c) 1996 Motorola Inc.
+
+Module Name:
+
+ sysbios.h
+
+Abstract:
+
+ This module contains the private header file for the system BIOS
+ emulation.
+
+Author:
+
+ Scott Geranen (3-4-96)
+
+Revision History:
+
+--*/
+
+#ifndef _SYSBIOS_
+#define _SYSBIOS_
+
+BOOLEAN
+HalpEmulateSystemBios(
+ IN OUT PRXM_CONTEXT P,
+ IN ULONG Number
+ );
+
+#endif // _SYSBIOS_
diff --git a/private/ntos/nthals/halfire/ppc/txtpalet.h b/private/ntos/nthals/halfire/ppc/txtpalet.h
new file mode 100644
index 000000000..ffb5e97b1
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/txtpalet.h
@@ -0,0 +1,107 @@
+/******************************************************************************
+
+txtpalet.h
+
+ Author: Jess Botts
+
+ This file contains the text mode palette. Most of the entries are 0
+ because they are not used. The first 8 entries are used for all
+ background colors and normal intensity foregound colors. Background
+ colors are displayed at normal intensity only. The 8 entries that
+ begin at the 56th entry are used for high intensity foreground colors.
+
+ Each entry consists of 3 values, 1 for each color gun.
+
+******************************************************************************/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: txtpalet.h $
+ * $Revision: 1.4 $
+ * $Date: 1996/01/11 07:14:21 $
+ * $Locker: $
+ */
+
+UCHAR
+ TextPalette[] =
+ { /*
+ Line
+ R G B R G B R G B R G B Index
+ */
+
+// all background colors and normal intensity foregound colors
+
+ 0, 0, 0, 0, 0, 32, 0, 32, 0, 0, 32, 32, // 0
+ 32, 0, 0, 32, 0, 32, 32, 32, 0, 32, 32, 32,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+// high intensity foreground colors
+
+ 16, 16, 16, 0, 0, 63, 0, 63, 0, 0, 63, 63, // 56
+ 63, 0, 0, 63, 0, 63, 63, 63, 0, 63, 63, 63,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+/*****************************************************************************/
diff --git a/private/ntos/nthals/halfire/ppc/x86bios.c b/private/ntos/nthals/halfire/ppc/x86bios.c
new file mode 100644
index 000000000..3bb1a9686
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/x86bios.c
@@ -0,0 +1,1201 @@
+/*++
+
+Copyright (C) 1994,1995 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: x86bios.c $
+ * $Revision: 1.21 $
+ * $Date: 1996/07/02 04:58:06 $
+ * $Locker: $
+ */
+
+
+
+
+
+#include "halp.h"
+#include "xm86.h"
+#include "x86new.h"
+#include "pxpcisup.h"
+#include "pxmemctl.h"
+#include "fpdebug.h"
+#include "pci.h"
+//
+// Define global data.
+//
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+//PVOID HalpIoMemoryBase = NULL;
+PUCHAR HalpRomBase = NULL;
+
+UCHAR HalpVideoBus; // Used as arguments to the PCI BIOS
+UCHAR HalpVideoDevice; // init function. Set HalpInitX86Emulator,
+UCHAR HalpVideoFunction; // used by HalpInitializeX86DisplayAdapter.
+
+UCHAR HalpLastPciBus; // Set by scanning the configuration data and
+ // used by PCI BIOS eumulation code.
+
+ULONG ROM_Length;
+#define BUFFER_SIZE (128*1024)
+UCHAR ROM_Buffer[BUFFER_SIZE];
+
+static VOID DumpPCIConfig(PVOID ConfigBaseAddress)
+{
+ USHORT VendorID, DeviceID, RevisionID;
+ ULONG addr;
+ ULONG TempReg32;
+
+ VendorID = READ_REGISTER_USHORT(&((PCI_CONFIG)ConfigBaseAddress)->VendorID);
+ DeviceID = READ_REGISTER_USHORT(&((PCI_CONFIG)ConfigBaseAddress)->DeviceID);
+ RevisionID = READ_REGISTER_UCHAR(&((PCI_CONFIG)ConfigBaseAddress)->RevisionID);
+ PRNTDISP(DbgPrint("vendorID=0x%04x deviceID=0x%04x revisionID=0x%02x\n", VendorID, DeviceID, RevisionID));
+
+ TempReg32 = READ_REGISTER_ULONG((PULONG)&((PCI_CONFIG)ConfigBaseAddress)->Command);
+ PRNTDISP(DbgPrint("Status Command=0x%08x\n", TempReg32));
+
+ TempReg32 = READ_REGISTER_ULONG((PULONG)&((PCI_CONFIG)ConfigBaseAddress)->RevisionID);
+ PRNTDISP(DbgPrint("Revision ID=0x%08x\n", TempReg32));
+
+ addr = READ_REGISTER_ULONG(&((PCI_CONFIG)ConfigBaseAddress)->BaseAddress1); PRNTDISP(DbgPrint("BaseAddress1=0x%08x\n", addr));
+
+
+ addr = READ_REGISTER_ULONG(&((PCI_CONFIG)ConfigBaseAddress)->BaseAddress2); PRNTDISP(DbgPrint("BaseAddress2=0x%08x\n", addr));
+ addr = READ_REGISTER_ULONG(&((PCI_CONFIG)ConfigBaseAddress)->BaseAddress3); PRNTDISP(DbgPrint("BaseAddress3=0x%08x\n", addr));
+ addr = READ_REGISTER_ULONG(&((PCI_CONFIG)ConfigBaseAddress)->BaseAddress4); PRNTDISP(DbgPrint("BaseAddress4=0x%08x\n", addr));
+ addr = READ_REGISTER_ULONG(&((PCI_CONFIG)ConfigBaseAddress)->BaseAddress5); PRNTDISP(DbgPrint("BaseAddress5=0x%08x\n", addr));
+ addr = READ_REGISTER_ULONG(&((PCI_CONFIG)ConfigBaseAddress)->BaseAddress6); PRNTDISP(DbgPrint("BaseAddress6=0x%08x\n", addr));
+}
+
+
+
+BOOLEAN HalpInitX86Emulator(
+ VOID)
+
+{
+ BOOLEAN Found = FALSE;
+ ULONG ROM_size = 0;
+ PHYSICAL_ADDRESS PhysAddr;
+ USHORT Cmd, VendorID, Slot;
+ PVOID HalpVideoConfigBase;
+ PUCHAR ROM_Ptr;
+ ULONG i;
+ UCHAR Class;
+ UCHAR SubClass;
+ USHORT DeviceID = 0;
+ UCHAR RevisionID = 0;
+ ULONG mapSize = 0x800000;
+
+ PhysAddr.HighPart = 0x00000000;
+
+
+ //
+ // Scan PCI slots for video BIOS ROMs
+ //
+ for (Slot = 1; Slot < MAXIMUM_PCI_SLOTS; Slot++) {
+
+ HalpVideoConfigBase = (PVOID) ((ULONG) HalpPciConfigBase + HalpPciConfigSlot[Slot]);
+
+ // Read Vendor ID and check if slot is empty
+ VendorID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->VendorID);
+ if (VendorID == 0xFFFF)
+ continue; // Slot is empty; go to next slot
+
+ DumpPCIConfig(HalpVideoConfigBase);
+
+ Class = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[2]);
+ SubClass = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[1]);
+#define DISPLAY_CLASS 0x03
+ if ( !(Class == DISPLAY_CLASS && (SubClass == 0)) &&
+ !(Class == 0x00 && SubClass == 0x01))
+ continue;
+
+ DeviceID = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->DeviceID);
+ RevisionID = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->RevisionID);
+ //PRNTDISP(DbgPrint("vendorID=0x%04x deviceID=0x%04x revisionID=0x%02x\n", VendorID, DeviceID, RevisionID));
+ //DbgBreakPoint();
+
+ // Get size of ROM
+ WRITE_REGISTER_ULONG(&((PCI_CONFIG)HalpVideoConfigBase)->ROMbase, 0xFFFFFFFF);
+ ROM_size = READ_REGISTER_ULONG(&((PCI_CONFIG)HalpVideoConfigBase)->ROMbase);
+
+
+ if ((ROM_size != 0xFFFFFFFF) && (ROM_size != 0)) {
+ ROM_size = ~(ROM_size & 0xFFFFFFFE) + 1;
+ PRNTDISP(DbgPrint("ROM_size=0x%08x\n", ROM_size));
+ ROM_size += 0xC0000;
+ // if (ROM_size < 0xE0000) ROM_size = 0xE0000; // Map to end of option ROM space
+
+ //
+ // Set Expansion ROM Base Address & enable ROM
+ //
+ PhysAddr.LowPart = 0x000C0000 | 1;
+ WRITE_REGISTER_ULONG(&((PCI_CONFIG)HalpVideoConfigBase)->ROMbase, PhysAddr.LowPart);
+
+ //
+ // Enable Memory & I/O spaces in command register
+ //
+ Cmd = READ_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->Command);
+ WRITE_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->Command, Cmd | 3);
+ PRNTDISP(DbgPrint("HalpVideoConfigBase=0x%08x Slot=%d Cmd=0x%08x ROM_size=0x%08x\n", HalpVideoConfigBase, Slot, Cmd, ROM_size));
+
+ //
+ // Create a mapping to the PCI memory space
+ //
+ if (NULL == HalpIoMemoryBase) {
+ HalpIoMemoryBase = KePhase0MapIo((PVOID)IO_MEMORY_PHYSICAL_BASE, mapSize /*ROM_size*/);
+
+ if (HalpIoMemoryBase == NULL) {
+ PRNTDISP(DbgPrint("\nCan't create mapping to PCI memory space\n"));
+ return FALSE;
+ }
+ }
+ //
+ // Look for PCI option video ROM signature
+ //
+ HalpRomBase = ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
+ if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
+ //
+ // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
+ // Sometimes option ROM and video RAM can't co-exist.
+ //
+ ROM_Length = *(ROM_Ptr+2) << 9;
+ PRNTDISP(DbgPrint("ROM_Length=0x%08x\n", ROM_Length));
+ if (ROM_Length <= BUFFER_SIZE) {
+ for (i=0; i<ROM_Length; i++)
+ ROM_Buffer[i] = *ROM_Ptr++;
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+ } else {
+ PRNTDISP(DbgPrint("ROM_Length=0x%08x is bigger than 0x%08x\n", ROM_Length, BUFFER_SIZE));
+ goto cleanup;
+ }
+
+ // Bus 0 because we do not yet support display cards behind a
+ // bridge
+
+ HalpVideoBus = 0;
+
+ // Function 0 because display cards are as of now single
+ // function devices.
+
+ HalpVideoFunction = 0;
+
+ HalpVideoDevice = (UCHAR)Slot;
+
+ return TRUE; // Exit slot scan after finding 1st option ROM
+ }
+ } // end of if clause
+ } // end of for loop
+
+ cleanup:
+ // mogawa for BUG 3400
+ if (HalpIoMemoryBase) {
+ HalpIoMemoryBase = (PVOID)0;
+ KePhase0DeleteIoMap((PVOID)IO_MEMORY_PHYSICAL_BASE,
+ mapSize/*ROM_size*/);
+ }
+ return FALSE;
+}
+
+
+
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ XM86_CONTEXT Context;
+
+ //
+ // If the x86 BIOS Emulator has not been initialized, then return FALSE.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // If the Video Adapter initialization failed and an Int10 command is
+ // specified, then return FALSE.
+ //
+
+ if ((BiosCommand == 0x10) && (HalpEnableInt10Calls == FALSE)) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and emulate the specified command.
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand,
+ &Context,
+ HalpIoControlBase,
+ HalpIoMemoryBase) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and return TRUE.
+ //
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+ return TRUE;
+
+
+}
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ LoaderBlock for access to the number of PCI buses
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ ULONG MatchKey;
+ PCM_PARTIAL_RESOURCE_LIST Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Partial;
+ XM86_CONTEXT State;
+
+ //
+ // If EISA I/O Ports or EISA memory could not be mapped, then don't
+ // attempt to initialize the display adapter.
+ //
+
+ if (!HalpInitX86Emulator())
+ return FALSE;
+
+ if (HalpIoControlBase == NULL || HalpIoMemoryBase == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Get the number of PCI buses for the PCI BIOS functions
+ //
+
+ //
+ // Find the PCI info in the config data.
+ //
+
+//JJJ
+#if 1
+
+ HalpLastPciBus = 0;
+ MatchKey = 0;
+
+#else
+
+ PRNTDISP(DbgPrint("about to find last PCI bus\n"));
+
+
+ while ((ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ AdapterClass, MultiFunctionAdapter, &MatchKey)) != NULL) {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"PCI")) {
+
+ Descriptor = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+
+ PCIRegInfo = (PPCI_REGISTRY_INFO)&Descriptor->PartialDescriptors[1];
+
+ HalpLastPciBus = PCIRegInfo->NoBuses - 1;
+
+ break;
+ }
+
+ MatchKey++;
+ }
+
+#endif
+
+ //
+ // Initialize the x86 bios emulator.
+ //
+
+ x86BiosInitializeBios(HalpIoControlBase, HalpIoMemoryBase);
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Attempt to initialize the display adapter by executing its ROM bios
+ // code. The standard ROM bios code address for PC video adapters is
+ // 0xC000:0000 on the ISA bus.
+ //
+
+ State.Eax = (HalpVideoBus << 8) |
+ (HalpVideoDevice << 3) |
+ HalpVideoFunction;
+
+ State.Ecx = 0;
+ State.Edx = 0;
+ State.Ebx = 0;
+ State.Ebp = 0;
+ State.Esi = 0;
+ State.Edi = 0;
+
+ if (x86BiosInitializeAdapter(0xc0000, &State, HalpIoControlBase, HalpIoMemoryBase) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+ return FALSE;
+ }
+ HalpEnableInt10Calls = TRUE;
+
+ return TRUE;
+}
+
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ XM86_CONTEXT Context;
+
+ //
+ // Initialize the x86 bios context and make the INT 10 call to initialize
+ // the display adapter to 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+
+
+ return;
+}
+
+
+//
+// This code came from ..\..\x86new\x86bios.c
+//
+#define LOW_MEMORY_SIZE 0x800
+extern UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
+extern ULONG x86BiosScratchMemory;
+extern ULONG x86BiosIoMemory;
+extern ULONG x86BiosIoSpace;
+
+
+PVOID
+x86BiosTranslateAddress (
+ IN USHORT Segment,
+ IN USHORT Offset
+ )
+
+/*++
+
+Routine Description:
+
+ This translates a segment/offset address into a memory address.
+
+Arguments:
+
+ Segment - Supplies the segment register value.
+
+ Offset - Supplies the offset within segment.
+
+Return Value:
+
+ The memory address of the translated segment/offset pair is
+ returned as the function value.
+
+--*/
+
+{
+
+ ULONG Value;
+
+ //
+ // Compute the logical memory address and case on high hex digit of
+ // the resultant address.
+ //
+
+ Value = Offset + (Segment << 4);
+
+ Offset = (USHORT)(Value & 0xffff);
+ Value &= 0xf0000;
+ switch ((Value >> 16) & 0xf) {
+
+ //
+ // Interrupt vector/stack space.
+ //
+
+ case 0x0:
+ if (Offset > LOW_MEMORY_SIZE) {
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ } else {
+ return (PVOID)(&x86BiosLowMemory[0] + Offset);
+ }
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0x1:
+ case 0x2:
+ case 0x3:
+ case 0x4:
+ case 0x5:
+ case 0x6:
+ case 0x7:
+ case 0x8:
+ case 0x9:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+
+ //
+ // The memory range from 0xa0000 to 0xdffff maps to I/O memory.
+ //
+
+ case 0xa:
+ case 0xb:
+ return (PVOID)(x86BiosIoMemory + Offset + Value);
+
+ case 0xc:
+ case 0xd:
+ return (PVOID)(HalpRomBase + Offset);
+
+ //
+ // The memory range from 0x10000 to 0x9ffff reads as zero
+ // and writes are ignored.
+ //
+
+ case 0xe:
+ case 0xf:
+ x86BiosScratchMemory = 0;
+ return (PVOID)&x86BiosScratchMemory;
+ }
+
+ // NOT REACHED - NOT EXECUTED - Prevents Compiler Warning.
+ return (PVOID)NULL;
+}
+
+
+VOID HalpCopyROMs(VOID)
+{
+ ULONG i;
+ PUCHAR ROM_Shadow;
+
+ if (ROM_Buffer[0] == 0x55 && ROM_Buffer[1] == 0xAA) {
+ //DbgPrint("HalpCopyROMs: calling ExAllocatePool.\n");
+ HalpRomBase = ROM_Shadow = ExAllocatePool(NonPagedPool, ROM_Length);
+ for (i=0; i<ROM_Length; i++) {
+ *ROM_Shadow++ = ROM_Buffer[i];
+ }
+ }
+}
+
+
+/****Include File x86new\x86bios.c Here - except the routine x86BiosTranslateAddress. ****/
+
+/*++
+
+ Copyright (c) 1994 Microsoft Corporation
+
+ Module Name:
+
+ x86bios.c
+
+ Abstract:
+
+ This module implements supplies the HAL interface to the 386/486
+ real mode emulator for the purpose of emulating BIOS calls..
+
+ Author:
+
+ David N. Cutler (davec) 13-Nov-1994
+
+ Environment:
+
+ Kernel mode only.
+
+ Revision History:
+
+ --*/
+
+#include "nthal.h"
+#include "hal.h"
+#include "xm86.h"
+#include "x86new.h"
+
+//
+// Define the size of low memory.
+//
+
+#define LOW_MEMORY_SIZE 0x800
+//
+// Define storage for low emulated memory.
+//
+
+UCHAR x86BiosLowMemory[LOW_MEMORY_SIZE + 3];
+ULONG x86BiosScratchMemory;
+
+//
+// Define storage to capture the base address of I/O space and the
+// base address of I/O memory space.
+//
+
+ULONG x86BiosIoMemory;
+ULONG x86BiosIoSpace;
+
+//
+// Define BIOS initialized state.
+//
+
+BOOLEAN x86BiosInitialized = FALSE;
+
+
+//
+// contexst for PCI Config mechanism #1 [YS:042296]
+//
+
+//extern PVOID HalpPciConfigBase;
+//extern ULONG HalpPciConfigSlot[];
+
+#define BIT_ENABLE 1
+#define CONFIG_ADDR (0x00000CF8)
+#define CONFIG_DATA (0x00000CFC)
+
+typedef struct _PCI_CONFIG_ADDR {
+ union {
+ struct {
+ ULONG zeros:2;
+ ULONG RegisterNumber:6;
+ ULONG FunctionNumber:3;
+ ULONG DeviceNumber:5;
+ ULONG BusNumber:8;
+ ULONG Reserved:7;
+ ULONG EnableMapping:1;
+ } bits;
+ ULONG AsULONG;
+ } u;
+} PCI_CONFIG_ADDR, *PPCI_CONFIG_ADDR ;
+
+// I wonder if it's OK to use a static to keep value for CONFIG_ADDRESS register or not.
+// May be needed to put this in XM_CONTEXT structure. [YS]
+
+static PCI_CONFIG_ADDR regConfigAddr;
+
+// end of contexst for PCI Config mechanism #1 [YS:042296]
+
+
+
+ULONG
+x86BiosReadIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber
+ )
+
+/*++
+
+ Routine Description:
+
+ This function reads from emulated I/O space.
+
+ Arguments:
+
+ DataType - Supplies the datatype for the read operation.
+
+ PortNumber - Supplies the port number in I/O space to read from.
+
+ Return Value:
+
+ The value read from I/O space is returned as the function value.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are read from the specified port one at a time and
+ assembled into the specified datatype.
+
+ --*/
+
+{
+
+ ULONG Result;
+
+ ULONG slotNumber ;
+ ULONG offset ;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Compute port address and read port.
+ //
+
+ if (
+ ((PortNumber & 0xfffffffc) == CONFIG_DATA ) &&
+ (regConfigAddr.u.bits.EnableMapping == BIT_ENABLE )
+ ){
+ // This is read from PCI config register space so lets translate this
+ // to our memory mapped address for the corresponding register.
+
+ slotNumber = regConfigAddr.u.bits.DeviceNumber;
+
+ if (
+ (slotNumber < MAXIMUM_PCI_SLOTS) &&
+ !regConfigAddr.u.bits.BusNumber
+ ){
+
+ // Calc offset of register within individual slot config space
+ // taking into account that the PortNumber can refer to a byte
+ // within the 32 bit register starting at "CONFIG_DATA"
+
+ offset = (regConfigAddr.u.bits.RegisterNumber << 2) +
+ (PortNumber & 0x3);
+
+ u.Long = (PULONG)((ULONG)HalpPciConfigBase +
+ (ULONG)HalpPciConfigSlot[slotNumber] + offset);
+
+ PRNTDISP(
+ DbgPrint(
+ "RD: Port (0x%08x) Config Addr (0x%08x) register# (0x%08x) LONG: (0x%08x) type: (0x%08x)\n",
+ PortNumber,
+ regConfigAddr.u.AsULONG,
+ offset,
+ Result,
+ DataType
+ ));
+
+ } else {
+
+ // The config space read target is either out of our supported
+ // range of slots or on a bus that is not supported. Note we do
+ // not support display cards in any bus other that 0 (i.e a display
+ // card cannot reside behind a bridge).
+
+ return(0xffffffff);
+ }
+ } else if ((PortNumber & 0xfffffffc) == CONFIG_ADDR){
+
+ // This is a read to the register that would normally be the
+ // "CONFIG_ADDRESS" used in an Intel PC to hold the address in
+ // config space that will be accessed in a subsequent read/write to the
+ // the "CONFIG_DATA" register. So we simply return the value stored in
+ // our simulated version of thisregister.
+
+ return(regConfigAddr.u.AsULONG);
+
+ } else {
+
+ // Just a regular access so setup the standard address translation
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ }
+
+ // Lets do the actual read now...
+
+ if (DataType == BYTE_DATA) {
+ Result = READ_REGISTER_UCHAR(u.Byte);
+
+ } else if (DataType == LONG_DATA) {
+
+ if (((ULONG)u.Long & 0x3) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8) |
+ (READ_REGISTER_UCHAR(u.Byte + 2) << 16) |
+ (READ_REGISTER_UCHAR(u.Byte + 3) << 24);
+ } else {
+ Result = READ_REGISTER_ULONG(u.Long);
+ }
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ Result = (READ_REGISTER_UCHAR(u.Byte + 0)) |
+ (READ_REGISTER_UCHAR(u.Byte + 1) << 8);
+
+ } else {
+ Result = READ_REGISTER_USHORT(u.Word);
+ }
+ }
+
+
+ // PRNTDISP(DbgPrint("RD: Port (0x%08x) Result (0x%08x)\n", PortNumber, Result));
+
+ return Result;
+}
+
+
+
+VOID
+x86BiosWriteIoSpace (
+ IN XM_OPERATION_DATATYPE DataType,
+ IN USHORT PortNumber,
+ IN ULONG Value
+ )
+
+/*++
+
+ Routine Description:
+
+ This function write to emulated I/O space.
+
+ N.B. If an aligned operation is specified, then the individual
+ bytes are written to the specified port one at a time.
+
+ Arguments:
+
+ DataType - Supplies the datatype for the write operation.
+
+ PortNumber - Supplies the port number in I/O space to write to.
+
+ Value - Supplies the value to write.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+{
+ ULONG slotNumber;
+ ULONG offset;
+ PULONG aPciConfigRegs;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ // PRNTDISP(DbgPrint("WRT: Port Number (0x%08x) DataType (0x%08x) Value (0x%08x)\n", PortNumber, DataType, Value));
+
+ //
+ // Compute port address and read port.
+ //
+
+ if (
+ ((PortNumber & 0xfffffffc) == CONFIG_DATA ) &&
+ (regConfigAddr.u.bits.EnableMapping == BIT_ENABLE )
+ ){
+ // This is read from PCI config register space so lets translate this
+ // to our memory mapped address for the corresponding register.
+
+ slotNumber = regConfigAddr.u.bits.DeviceNumber;
+
+ if (
+ (slotNumber < MAXIMUM_PCI_SLOTS) &&
+ !regConfigAddr.u.bits.BusNumber
+ ){
+
+ // Calc offset of register within individual slot config space
+ // taking into account that the PortNumber can refer to a byte
+ // within the 32 bit register starting at "CONFIG_DATA"
+
+ offset = (regConfigAddr.u.bits.RegisterNumber << 2) +
+ (PortNumber & 0x3);
+
+ u.Long = (PULONG)((ULONG)HalpPciConfigBase +
+ (ULONG)HalpPciConfigSlot[slotNumber] + offset);
+
+
+ PRNTDISP(DbgPrint(
+ "WRT: Port Number (0x%08x) DataType (0x%08x) Value (0x%08x) Offset (0x%08x)\n",
+ PortNumber,
+ DataType,
+ Value,
+ offset
+ ));
+
+ } else {
+ return;
+ }
+ } else {
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ }
+
+ if (DataType == BYTE_DATA) {
+
+ if ( PortNumber == 0x3C3 ) { // start of [YS:042296]
+
+ // CAUTION // This code is a hack for S3 Trio64 "Z" version
+ //
+ // Do NOT touch to the 0x03C3
+ //
+ // We know that some of the version of S3 Trio64,
+ // such as S3 Trio64 "Z" version (86C764X) or some of the Trio64V+,
+ // have bug on the new-wake-up register at 3C3.
+ // This register is not only WRITE ONLY, but WRITE ONCE.
+ // A second write is bad news.
+ // We are supposed to write this register with a 0x01 to wake up the chip.
+ // But writting it a second time will cose all sorts of problems,
+ // like hanging the system.
+ // So of cource, in order to display the firmware screen, FW has to
+ // write it once to open up the chip and get it going.
+ // If the VGA BIOS code tries to do it a second time in HAL, hang the system.
+ //
+ // Of cource, this hack is only for some version of S3 Trio64 chip.
+ // But we don't know which version of the chip have this problem.
+ //
+ // We know this port is also used by other vender.
+ // But "just ignore access to 0x3c3" will be OK for now, because:
+ // Weitek P9100 assigns this port as VGA enable register on Motherboard mode.
+ // Cirrus assigns this port as sleep address register for non-PCI bus, and
+ // this port is never accessible for PCI bus.
+ // So, I just ignore all byte write access to 0x3C3 ...
+
+ // PRNTDISP(DbgPrint("WRT: 3C3 access ignored\n"));
+
+
+ return;
+ } // end of [YS:042296]
+
+ WRITE_REGISTER_UCHAR(u.Byte, (UCHAR)Value);
+
+ } else if (DataType == LONG_DATA) {
+
+ if ( PortNumber == CONFIG_ADDR ) {
+
+ // This is identified as the CONFIG_ADDRESS write phase of a
+ // standard PC style PCI configuration space access. This style
+ // of PCI configuration space access is referred to as
+ // "Configuratoin Mechanism #1" in the PCI spec. Rev. 2.1.
+ // What we do is store the CONFIG_ADDRESS as done below and
+ // when the CONFIG_DATA port is accessed we use the value stored
+ // below to figure out where is our PCI config space map we need to
+ // go to get, or put, the requested data.
+
+ regConfigAddr.u.AsULONG = Value;
+ } else {
+
+ if (((ULONG)u.Long & 0x3) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+ WRITE_REGISTER_UCHAR(u.Byte + 2, (UCHAR)(Value >> 16));
+ WRITE_REGISTER_UCHAR(u.Byte + 3, (UCHAR)(Value >> 24));
+
+ } else {
+ WRITE_REGISTER_ULONG(u.Long, Value);
+ }
+ }
+ } else {
+ if (((ULONG)u.Word & 0x1) != 0) {
+ WRITE_REGISTER_UCHAR(u.Byte + 0, (UCHAR)(Value));
+ WRITE_REGISTER_UCHAR(u.Byte + 1, (UCHAR)(Value >> 8));
+
+ } else {
+ WRITE_REGISTER_USHORT(u.Word, (USHORT)Value);
+ }
+ }
+
+ return;
+}
+
+VOID
+x86BiosInitializeBios (
+ IN PVOID BiosIoSpace,
+ IN PVOID BiosIoMemory
+ )
+
+/*++
+
+ Routine Description:
+
+ This function initializes x86 BIOS emulation.
+
+ Arguments:
+
+ BiosIoSpace - Supplies the base address of the I/O space to be used
+ for BIOS emulation.
+
+ BiosIoMemory - Supplies the base address of the I/O memory to be
+ used for BIOS emulation.
+
+ Return Value:
+
+ None.
+
+ --*/
+
+{
+
+ //
+ // Zero low memory.
+ //
+
+ memset(&x86BiosLowMemory, 0, LOW_MEMORY_SIZE);
+
+ //
+ // Save base address of I/O memory and I/O space.
+ //
+
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+
+ //
+ // Initialize the emulator and the BIOS.
+ //
+
+ XmInitializeEmulator(0,
+ LOW_MEMORY_SIZE,
+ x86BiosReadIoSpace,
+ x86BiosWriteIoSpace,
+ x86BiosTranslateAddress);
+
+ x86BiosInitialized = TRUE;
+ return;
+}
+
+XM_STATUS
+x86BiosExecuteInterrupt (
+ IN UCHAR Number,
+ IN OUT PXM86_CONTEXT Context,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+
+/*++
+
+ Routine Description:
+
+ This function executes an interrupt by calling the x86 emulator.
+
+ Arguments:
+
+ Number - Supplies the number of the interrupt that is to be emulated.
+
+ Context - Supplies a pointer to an x86 context structure.
+
+ Return Value:
+
+ The emulation completion status.
+
+ --*/
+
+{
+
+ XM_STATUS Status;
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ //
+ // Execute the specified interrupt.
+ //
+
+ Status = XmEmulateInterrupt(Number, Context);
+ if (Status != XM_SUCCESS) {
+ DbgPrint("HAL: Interrupt emulation failed, status %lx\n", Status);
+ }
+
+ return Status;
+}
+
+XM_STATUS
+x86BiosInitializeAdapter (
+ IN ULONG Adapter,
+ IN OUT PXM86_CONTEXT Context OPTIONAL,
+ IN PVOID BiosIoSpace OPTIONAL,
+ IN PVOID BiosIoMemory OPTIONAL
+ )
+
+/*++
+
+ Routine Description:
+
+ This function initializes the adapter whose BIOS starts at the
+ specified 20-bit address.
+
+ Arguments:
+
+ Adpater - Supplies the 20-bit address of the BIOS for the adapter
+ to be initialized.
+
+ Return Value:
+
+ The emulation completion status.
+
+ --*/
+
+{
+
+ PUCHAR Byte;
+ XM86_CONTEXT State;
+ USHORT Offset;
+ USHORT Segment;
+ XM_STATUS Status;
+
+ //
+ // If BIOS emulation has not been initialized, then return an error.
+ //
+
+ if (x86BiosInitialized == FALSE) {
+ return XM_EMULATOR_NOT_INITIALIZED;
+ }
+
+ //
+ // If an emulator context is not specified, then use a default
+ // context.
+ //
+
+ if (ARGUMENT_PRESENT(Context) == FALSE) {
+ State.Eax = 0;
+ State.Ecx = 0;
+ State.Edx = 0;
+ State.Ebx = 0;
+ State.Ebp = 0;
+ State.Esi = 0;
+ State.Edi = 0;
+ Context = &State;
+ }
+
+ //
+ // If a new base address is specified, then set the appropriate base.
+ //
+
+ if (BiosIoSpace != NULL) {
+ x86BiosIoSpace = (ULONG)BiosIoSpace;
+ }
+
+ if (BiosIoMemory != NULL) {
+ x86BiosIoMemory = (ULONG)BiosIoMemory;
+ }
+
+ //
+ // If the specified adpater is not BIOS code, then return an error.
+ //
+
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+ Byte = (PUCHAR)x86BiosTranslateAddress(Segment, Offset);
+ if ((*Byte++ != 0x55) || (*Byte != 0xaa)) {
+ return XM_ILLEGAL_CODE_SEGMENT;
+ }
+
+ //
+ // Call the BIOS code to initialize the specified adapter.
+ //
+
+ Adapter += 3;
+ Segment = (USHORT)((Adapter >> 4) & 0xf000);
+ Offset = (USHORT)(Adapter & 0xffff);
+ Status = XmEmulateFarCall(Segment, Offset, Context);
+ if (Status != XM_SUCCESS) {
+ DbgPrint("HAL: Adapter initialization falied, status %lx\n", Status);
+ }
+
+ return Status;
+}
+
diff --git a/private/ntos/nthals/halfire/ppc/x86bios.h b/private/ntos/nthals/halfire/ppc/x86bios.h
new file mode 100644
index 000000000..fd5de89d4
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/x86bios.h
@@ -0,0 +1,24 @@
+#ifndef _X86BIOS_H
+#define _X86BIOS_H
+
+/*
+ * Copyright (c) 1995 FirePower Systems, Inc.
+ * DO NOT DISTRIBUTE without permission
+ *
+ * $RCSfile: x86bios.h $
+ * $Revision: 1.6 $
+ * $Date: 1996/01/11 07:14:34 $
+ * $Locker: $
+ */
+
+#include "xm86.h"
+
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+extern ULONG HalpEnableInt10Calls;
+
+#endif // _X86BIOS_H
diff --git a/private/ntos/nthals/halfire/sources b/private/ntos/nthals/halfire/sources
new file mode 100644
index 000000000..816dc199c
--- /dev/null
+++ b/private/ntos/nthals/halfire/sources
@@ -0,0 +1,235 @@
+#
+# Copyright (c) 1995,1996 FirePower Systems, Inc.
+#
+# $RCSfile: sources $
+# $Revision: 1.54 $
+# $Date: 1996/07/02 05:16:46 $
+# $Locker: $
+#
+#
+# Copyright (c) 1993 Microsoft Corporation
+#
+# Module Name:
+#
+# sources.
+#
+# Abstract:
+#
+# This file specifies the target component being built and the list of
+# sources files needed to build that component. Also specifies optional
+# compiler switches and libraries that are unique for the component being
+# built.
+#
+#
+#
+# Author:
+#
+# David N. Cutler (davec) 8-Apr-1993
+#
+# Revision Histoy:
+#
+# Jim Wooldridge (jimw@austin.vnet.ibm.com) Power PC port
+#
+# NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+#
+#
+MAJORCOMP=ntos
+MINORCOMP=hal
+TARGETNAME=halfire
+TARGETTYPE=HAL
+HAL_MAJOR=3
+HAL_MINOR=00
+
+#
+# Make sure BASEDIR is set, and if it isn't set it to _NTDRIVE.
+# If _NTDRIVE is not set, then exit with error since the environment
+# does not match the expectations upon which this sources operates...
+#
+!IFNDEF BASEDIR
+! IFNDEF _NTDRIVE
+! ERROR neither BASEDIR nor _NTDRIVE is defined
+! ENDIF
+BASEDIR=$(_NTDRIVE)\NT
+!ENDIF
+
+#
+# COMMON DEFINES FOR ALL BUILD ENVIRONMENTS:
+#
+C_DEFINES= -DHAL_MAJOR=$(HAL_MAJOR) -DHAL_MINOR=$(HAL_MINOR) -DREORG
+
+#
+# Determine what style build environment this is: DDK style or ntos style....
+# Setup some library and include paths based on this evaluation.
+#
+!IFDEF DDKBUILDENV
+
+# If HALFIRE_EVAL is set, use the text in the HAL's blue screen
+# Otherwise, don't print anything out
+#
+EVAL=-DHALFIRE_EVAL=Beta
+
+!IF "$(DDKBUILDENV)" == "checked"
+C_DEFINES=$(C_DEFINES) -DHALDEBUG_ON
+!ENDIF
+
+INCLUDES=$(BASEDIR)\src\hal\inc;$(BASEDIR)\private\ntos\inc
+INCLUDES=$(BASEDIR)\src\hal\x86new;$(INCLUDES)
+LIBDIR=$(BASEDIR)
+C_DEFINES=$(C_DEFINES) -DPRINT_IT $(EVAL)
+TARGETPATH=$(BASEDIR)\lib
+TARGETLIBS=$(BASEDIR)\lib\*\$(DDKBUILDENV)\x86new.lib $(LIBDIR)\lib\*\$(DDKBUILDENV)\libc.lib
+DESTINATION_DIR=ppc\$(DDKBUILDENV)
+
+!ELSE
+
+#
+# Make sure this is an ntos environment since it did not pass the DDK env test...
+#
+! IF EXIST (..\..\..\ntos\nthals)
+
+INCLUDES=$(BASEDIR)\private\ntos\nthals\x86new;$(BASEDIR)\private\ntos\inc
+LIBDIR=$(BASEDIR)\public\sdk
+TARGETPATH=$(LIBDIR)\lib
+TARGETLIBS=$(BASEDIR)\private\ntos\nthals\x86new\obj\*\x86new.lib $(LIBDIR)\lib\*\libc.lib
+
+! IFDEF NTDEBUG
+C_DEFINES=$(C_DEFINES) -DHALDEBUG_ON
+! ENDIF
+
+! ELSE
+! ERROR BUILD ENVIRONMENT IS NOT RECOGNIZABLE!!
+! ENDIF
+
+!ENDIF # end of check for ddk or ntos build environment...
+
+
+# -DHALDEBUG_ON \
+# FirePower General Defines
+#
+# FIREPOWER_DAYTONA: General Changes for our platform
+# RES_640_480:
+# PROCESSOR604_22: sync inst. instead of eieio
+# HALDEBUG_ON: compile in HalpDebugPrintf support:
+# This routine performs debugprintfs
+# as well as debugprintfs.
+#
+# REMOVE THE FOLLOWING DEFINES FOR BUILDING AT MICROSOFT
+# HAL_SUPPORT_606: Provide HAL Support for 606 instead of kernel
+#
+C_DEFINES= $(C_DEFINES) \
+ -DFIREDATA \
+ -DFIREPOWER_DAYTONA
+
+#
+# FirePower Multi-Processor Specific Defines
+#
+# FIREPOWER_MP: Generic for the moment [10.30.94]
+# _MP_PPC: Kernel Define for MP Support
+#
+#
+C_DEFINES= $(C_DEFINES) \
+ -DFIREPOWER_MP \
+ -D_MP_PPC
+
+
+!IFNDEF BUILTBY
+C_DEFINES= $(C_DEFINES) -DBUILTBY=\"$(USERNAME)\"
+!ELSE
+C_DEFINES= $(C_DEFINES) -DBUILTBY=\"$(BUILTBY)\"
+!ENDIF
+
+#
+# announce to the user the set of variables used:
+#
+!IFDEF VERBOSE
+
+!MESSAGE
+!MESSAGE =================================================
+!MESSAGE BASEDIR: $(BASEDIR)
+!MESSAGE INCLUDES: $(INCLUDES)
+!MESSAGE TARGETPATH: $(TARGETPATH)
+!MESSAGE TARGETLIBS: $(TARGETLIBS)
+!MESSAGE C_DEFINES: $(C_DEFINES)
+!MESSAGE =================================================
+!MESSAGE
+
+!ENDIF
+
+SOURCES=
+
+HALPPC_SOURCES=hal.rc \
+ ..\drivesup.c \
+ ..\bushnd.c \
+ ppc\pxport.c \
+ ppc\pxinithl.c \
+ ppc\x86bios.c \
+ ppc\pxenviro.c \
+ ppc\pxbeep.c \
+ ppc\pxnatsup.c \
+ ppc\pxsiosup.c \
+ ppc\pxmemctl.c \
+ ppc\pxdisp.c \
+ ppc\pxstall.s \
+ ppc\pxcache.s \
+ ppc\pxclock.c \
+ ppc\pxcalstl.c \
+ ppc\pxclksup.s \
+ ppc\pxflshbf.s \
+ ppc\pxhwsup.c \
+ ppc\pxprof.c \
+ ppc\pxmapio.c \
+ ppc\pxsysint.c \
+ ppc\pxtime.c \
+ ppc\pxreturn.c \
+ ppc\pxintsup.s \
+ ppc\pxirql.c \
+ ppc\pxusage.c \
+ ppc\pxbusdat.c \
+ ppc\pxpcibus.c \
+ ppc\pxpciint.c \
+ ppc\pxisabus.c \
+ ppc\pxidle.c \
+ ppc\pxsysbus.c \
+ ppc\pxproc.c \
+ ppc\pxdat.c \
+ ppc\pxflshio.c \
+ ppc\pxmisc.s \
+ ppc\pxpcisup.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(PPC)
+!IFNDEF DDKBUILDENV
+NTTARGETFILES=ppc\phvrsion.c
+!ELSE
+NTTARGETFILES=\
+ $(TARGETPATH)\$(DESTINATION_DIR)\halfire.lib \
+ $(TARGETPATH)\$(DESTINATION_DIR)\halfire.dll
+!ENDIF
+!ENDIF
+
+#
+# Sources required for the FirePower Machines
+#
+FIREPOWER_SOURCES=$(HALPPC_SOURCES)\
+ ppc\fpi2c.c \
+ ppc\fpcpu.s\
+ ppc\fp82091.c\
+ ppc\fpds1385.c\
+ ppc\fpdcc.c \
+ ppc\fpbat.c \
+ ppc\fppcisup.c \
+ ppc\fpBt445.c \
+ ppc\fplibc.c \
+ ppc\fprgstry.c \
+ ppc\fpints.c \
+ ppc\phprods.c\
+ ppc\phcalls.c\
+ ppc\phsystem.s \
+ ppc\ctrlops.c \
+ ppc\sysbios.c \
+ ppc\pcibios.c
+
+PPC_SOURCES=$(FIREPOWER_SOURCES) \
+ ppc\phvrsion.c
+