summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/haleagle
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/haleagle')
-rw-r--r--private/ntos/nthals/haleagle/hal.rc11
-rw-r--r--private/ntos/nthals/haleagle/makefile6
-rw-r--r--private/ntos/nthals/haleagle/ppc/ctrlops.c471
-rw-r--r--private/ntos/nthals/haleagle/ppc/fwnvr.c1745
-rw-r--r--private/ntos/nthals/haleagle/ppc/fwnvr.h37
-rw-r--r--private/ntos/nthals/haleagle/ppc/fwstatus.h17
-rw-r--r--private/ntos/nthals/haleagle/ppc/halp.h239
-rw-r--r--private/ntos/nthals/haleagle/ppc/mk48tdc.h68
-rw-r--r--private/ntos/nthals/haleagle/ppc/mk48time.c431
-rw-r--r--private/ntos/nthals/haleagle/ppc/pcibios.c1056
-rw-r--r--private/ntos/nthals/haleagle/ppc/pcibios.h58
-rw-r--r--private/ntos/nthals/haleagle/ppc/pcip.h186
-rw-r--r--private/ntos/nthals/haleagle/ppc/prepnvr.h134
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxbeep.c134
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxbusdat.c210
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxcache.s208
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxcalstl.c184
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxcirrus.h238
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxclksup.s145
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxclock.c243
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxdat.c110
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxdisp.c2211
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxds1385.c386
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxds1585.h106
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxenviro.c170
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxflshbf.s186
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxflshio.c128
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxhalp.h253
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxhwsup.c2199
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxidle.c65
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxinfo.c97
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxinithl.c396
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxintsup.s290
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxirql.c261
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxisabus.c130
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxl2.s551
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxmapio.c124
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxmemctl.c1643
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxmemctl.h45
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxmisc.s183
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxpcibrd.c544
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxpcibus.c2289
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxpciint.c221
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxpcisup.c235
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxpcisup.h54
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxport.c849
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxpower.s67
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxproc.c212
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxprof.c268
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxreset.s240
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxreturn.c133
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxs3.h760
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxsiosup.c1761
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxsiosup.h221
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxstall.s326
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxsysbus.c204
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxsysint.c214
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxsystyp.c96
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxsystyp.h44
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxtime.c137
-rw-r--r--private/ntos/nthals/haleagle/ppc/pxusage.c503
-rw-r--r--private/ntos/nthals/haleagle/ppc/sysbios.c73
-rw-r--r--private/ntos/nthals/haleagle/ppc/sysbios.h31
-rw-r--r--private/ntos/nthals/haleagle/ppc/txtpalet.h97
-rw-r--r--private/ntos/nthals/haleagle/ppc/x86bios.c1156
-rw-r--r--private/ntos/nthals/haleagle/sources97
66 files changed, 26187 insertions, 0 deletions
diff --git a/private/ntos/nthals/haleagle/hal.rc b/private/ntos/nthals/haleagle/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/haleagle/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/haleagle/makefile b/private/ntos/nthals/haleagle/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/haleagle/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/haleagle/ppc/ctrlops.c b/private/ntos/nthals/haleagle/ppc/ctrlops.c
new file mode 100644
index 000000000..f921d2ed6
--- /dev/null
+++ b/private/ntos/nthals/haleagle/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/haleagle/ppc/fwnvr.c b/private/ntos/nthals/haleagle/ppc/fwnvr.c
new file mode 100644
index 000000000..859d0aef9
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/fwnvr.c
@@ -0,0 +1,1745 @@
+/*
+***********************************************************************
+** NVRAM
+***********************************************************************
+*/
+#define _NOT_HALNVR_
+
+#ifdef _HALNVR_
+#include "halp.h"
+#else
+#include "fwp.h"
+#endif /* _HALNVR_ */
+
+#include "prepnvr.h"
+#include "fwstatus.h"
+#include "fwnvr.h"
+
+/*
+***********************************************************************
+** internal type definitions
+***********************************************************************
+*/
+typedef struct _nvrregs {
+ UCHAR reserved_0[0x74];
+ UCHAR addl; /* low half of address register */
+ UCHAR addh; /* high half of address register */
+ UCHAR polodata; /* NVRAM Data Port on Polo */
+ UCHAR sfdata; /* NVRAM Data Port on Sandalfoot */
+ UCHAR reserved_1[0x800-0x78];
+ UCHAR bb_data; /* NVRAM Data Port on BigBend (0x800) */
+ UCHAR reserved_2[0x400-1];
+ UCHAR bb_addl; /* NVRAM Lo Index Port on BigBend (0xC00) */
+ UCHAR bb_addh; /* NVRAM Hi Index Port on BigBend (0xC01) */
+
+ } NVRREGS, *PNVRREGS;
+
+typedef struct _nvr_object {
+ struct _nvr_object *self;
+ NVR_SYSTEM_TYPE systype;
+ HEADER* bhead;
+ HEADER* lhead;
+ UCHAR bend[NVSIZE*2];
+ UCHAR lend[NVSIZE*2];
+ } NVR_OBJECT, *PNVR_OBJECT;
+
+typedef NVRAM_MAP *PNVRAM_MAP;
+
+/*
+***********************************************************************
+** private macros, defines, and externs
+***********************************************************************
+*/
+extern PVOID HalpIoControlBase;
+#define NVRAM_VIRTUAL_BASE ((PUCHAR)HalpIoControlBase)
+
+#define _ppc_shortswap(_x) (((_x<<8)&0xff00)|((_x>>8)&0x00ff))
+
+#define _ppc_longswap(_x)\
+(((_x<<24)&0xff000000)|((_x<<8)&0x00ff0000)|\
+((_x>>8)&0x0000ff00)|((_x>>24)&0x000000ff))
+
+#define _toupr_(_c) (((_c >= 'a') && (_c <= 'z')) ? (_c - 'a' + 'A') : _c)
+
+#define MAXNVRFETCH NVSIZE*2
+
+/*
+***********************************************************************
+** prototypes of private methods
+** (prototypes of public methods are defined in fwnvr.h)
+***********************************************************************
+*/
+
+VOID nvr_clear_nvram(PNVR_OBJECT);
+UCHAR nvr_read(NVR_SYSTEM_TYPE, ULONG);
+VOID nvr_write(NVR_SYSTEM_TYPE, ULONG,UCHAR);
+PNVR_OBJECT nvr_create_object(NVR_SYSTEM_TYPE);
+PNVR_OBJECT nvr_alloc(ULONG);
+VOID nvr_free(PVOID);
+VOID nvr_default_nvram(PNVR_OBJECT);
+VOID nvr_read_nvram(PNVR_OBJECT);
+VOID nvr_write_Header(PNVR_OBJECT);
+VOID nvr_swap_Header(HEADER*, HEADER*);
+VOID nvr_headb2l(PNVR_OBJECT);
+VOID nvr_headl2b(PNVR_OBJECT);
+ULONG nvr_computecrc(ULONG, UCHAR);
+USHORT nvr_calc1crc(PNVR_OBJECT);
+USHORT nvr_calc2crc(PNVR_OBJECT);
+VOID nvr_read_GEArea(PNVR_OBJECT);
+VOID nvr_read_OSArea(PNVR_OBJECT);
+VOID nvr_read_CFArea(PNVR_OBJECT);
+VOID nvr_write_GEArea(PNVR_OBJECT);
+VOID nvr_write_OSArea(PNVR_OBJECT);
+VOID nvr_write_CFArea(PNVR_OBJECT);
+
+/*
+***********************************************************************
+** prototypes of private debug methods are defined below
+***********************************************************************
+*/
+//#undef KDB
+#ifdef KDB
+VOID nvr_display_object(PNVR_OBJECT);
+VOID nvr_display_lemap(PNVR_OBJECT);
+VOID nvr_display_bemap(PNVR_OBJECT);
+VOID nvr_test_setvar(VOID);
+#endif /* KDB */
+
+/*
+***********************************************************************
+** private data items - not visible to public clients
+***********************************************************************
+*/
+
+UCHAR _currentstring[MAXIMUM_ENVIRONMENT_VALUE];
+UCHAR _currentfetch[MAXNVRFETCH];
+
+#ifndef _HALNVR_
+NVR_OBJECT nvrobj;
+#endif /* _HALNVR_ */
+
+PNVR_OBJECT pnvrobj = 0;
+
+/*
+***********************************************************************
+** methods
+***********************************************************************
+*/
+
+/***********************************************************************/
+PNVR_OBJECT nvr_alloc(ULONG size)
+{
+ PNVR_OBJECT p;
+
+ p = (PNVR_OBJECT)0;
+
+#ifdef _HALNVR_
+ /* use HAL memory allocation here */
+ p = ExAllocatePool(NonPagedPool, size);
+ return(p);
+#else
+ /* use ARC FW memory allocation here */
+ p = &nvrobj;
+ return(p);
+#endif /* _HALNVR_ */
+}
+
+/***********************************************************************/
+VOID nvr_free(PVOID p)
+{
+ if (p == (PVOID)NULL)
+ return;
+
+#ifdef _HALNVR_
+ /* use HAL memory deallocation here */
+ ExFreePool(p);
+#endif /* _HALNVR_ */
+
+ return;
+}
+
+/***********************************************************************/
+UCHAR nvr_read(NVR_SYSTEM_TYPE st, ULONG addr)
+{
+ UCHAR uc;
+ UCHAR hi_index, lo_index;
+ PNVRREGS nvp = (PNVRREGS)NVRAM_VIRTUAL_BASE;
+ lo_index = (UCHAR)(addr & 0xff);
+ hi_index = (UCHAR)((addr >> 8) & 0x1f);
+ switch (st) {
+ case nvr_systype_bigbend:
+ WRITE_REGISTER_UCHAR(&nvp->bb_addl, lo_index);
+ WRITE_REGISTER_UCHAR(&nvp->bb_addh, hi_index);
+ break;
+ default:
+ WRITE_REGISTER_UCHAR(&nvp->addl, lo_index);
+ WRITE_REGISTER_UCHAR(&nvp->addh, hi_index);
+ break;
+ }
+#ifndef _HALNVR_
+ Eieio();
+#endif /* _HALNVR_ */
+
+ switch (st) {
+ case nvr_systype_powerstack:
+ case nvr_systype_sandalfoot:
+ uc = READ_REGISTER_UCHAR(&nvp->sfdata);
+ break;
+ case nvr_systype_bigbend:
+ uc = READ_REGISTER_UCHAR(&nvp->bb_data);
+ break;
+ case nvr_systype_polo:
+ case nvr_systype_woodfield:
+ uc = READ_REGISTER_UCHAR(&nvp->polodata);
+ break;
+ default:
+ uc = 0;
+ break;
+ }
+
+ return(uc);
+}
+
+/***********************************************************************/
+VOID nvr_write(NVR_SYSTEM_TYPE st, ULONG addr, UCHAR data)
+{
+ UCHAR hi_index, lo_index;
+ PNVRREGS nvp = (PNVRREGS)NVRAM_VIRTUAL_BASE;
+
+ lo_index = (UCHAR)(addr & 0xff);
+ hi_index = (UCHAR)((addr >> 8) & 0x1f);
+ switch (st) {
+ case nvr_systype_bigbend:
+ WRITE_REGISTER_UCHAR(&nvp->bb_addl, lo_index);
+ WRITE_REGISTER_UCHAR(&nvp->bb_addh, hi_index);
+ break;
+ default:
+ WRITE_REGISTER_UCHAR(&nvp->addl, lo_index);
+ WRITE_REGISTER_UCHAR(&nvp->addh, hi_index);
+ break;
+ }
+#ifndef _HALNVR_
+ Eieio();
+#endif /* _HALNVR_ */
+
+ switch (st) {
+ case nvr_systype_powerstack:
+ case nvr_systype_sandalfoot:
+ WRITE_REGISTER_UCHAR(&nvp->sfdata, data);
+ break;
+ case nvr_systype_bigbend:
+ WRITE_REGISTER_UCHAR(&nvp->bb_data, data);
+ break;
+ case nvr_systype_polo:
+ case nvr_systype_woodfield:
+ WRITE_REGISTER_UCHAR(&nvp->polodata, data);
+ break;
+ default:
+ break;
+ }
+
+#ifndef _HALNVR_
+ Eieio();
+#endif /* _HALNVR_ */
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_swap_Header(HEADER* dest, HEADER* src)
+{
+ ULONG i;
+ PUCHAR cp;
+
+ /* validate pointers */
+ if ((dest == NULL) || (src == NULL))
+ return;
+
+ dest->Size = _ppc_shortswap(src->Size);
+ dest->Version = src->Version;
+ dest->Revision = src->Revision;
+ dest->Crc1 = _ppc_shortswap(src->Crc1);
+ dest->Crc2 = _ppc_shortswap(src->Crc2);
+ dest->LastOS = src->LastOS;
+ dest->Endian = src->Endian;
+ dest->OSAreaUsage = src->OSAreaUsage;
+ dest->PMMode = src->PMMode;
+
+ /* convert NVRRESTART_BLOCK structure of Header */
+ dest->ResumeBlock.CheckSum = _ppc_longswap(src->ResumeBlock.CheckSum);
+ dest->ResumeBlock.BootStatus = _ppc_longswap(src->ResumeBlock.BootStatus);
+ dest->ResumeBlock.ResumeAddr =
+ (VOID *) _ppc_longswap((ULONG)src->ResumeBlock.ResumeAddr);
+ dest->ResumeBlock.SaveAreaAddr =
+ (VOID *) _ppc_longswap((ULONG)src->ResumeBlock.SaveAreaAddr);
+ dest->ResumeBlock.SaveAreaLength =
+ _ppc_longswap((ULONG)src->ResumeBlock.SaveAreaLength);
+ dest->ResumeBlock.HibResumeImageRBA =
+ _ppc_longswap((ULONG)src->ResumeBlock.HibResumeImageRBA);
+ dest->ResumeBlock.HibResumeImageRBACount =
+ _ppc_longswap((ULONG)src->ResumeBlock.HibResumeImageRBACount);
+ dest->ResumeBlock.Reserved =
+ _ppc_longswap((ULONG)src->ResumeBlock.Reserved);
+
+ /* convert SECURITY structure */
+ dest->Security.BootErrCnt =
+ _ppc_longswap(src->Security.BootErrCnt);
+ dest->Security.ConfigErrCnt =
+ _ppc_longswap(src->Security.ConfigErrCnt);
+ dest->Security.BootErrorDT[0] =
+ _ppc_longswap(src->Security.BootErrorDT[0]);
+ dest->Security.BootErrorDT[1] =
+ _ppc_longswap(src->Security.BootErrorDT[1]);
+ dest->Security.ConfigErrorDT[0] =
+ _ppc_longswap(src->Security.ConfigErrorDT[0]);
+ dest->Security.ConfigErrorDT[1] =
+ _ppc_longswap(src->Security.ConfigErrorDT[1]);
+ dest->Security.BootCorrectDT[0] =
+ _ppc_longswap(src->Security.BootCorrectDT[0]);
+ dest->Security.BootCorrectDT[1] =
+ _ppc_longswap(src->Security.BootCorrectDT[1]);
+ dest->Security.ConfigCorrectDT[0] =
+ _ppc_longswap(src->Security.ConfigCorrectDT[0]);
+ dest->Security.ConfigCorrectDT[1] =
+ _ppc_longswap(src->Security.ConfigCorrectDT[1]);
+ dest->Security.BootSetDT[0] =
+ _ppc_longswap(src->Security.BootSetDT[0]);
+ dest->Security.BootSetDT[1] =
+ _ppc_longswap(src->Security.BootSetDT[1]);
+ dest->Security.ConfigSetDT[0] =
+ _ppc_longswap(src->Security.ConfigSetDT[0]);
+ dest->Security.ConfigSetDT[1] =
+ _ppc_longswap(src->Security.ConfigSetDT[1]);
+ for (i = 0; i < 16; i++)
+ dest->Security.Serial[i] = src->Security.Serial[i];
+
+ /* convert ERROR_LOG 0 and ERROR_LOG 1 structure */
+ for (i = 0; i < 40; i++) {
+ dest->ErrorLog[0].ErrorLogEntry[i] = src->ErrorLog[0].ErrorLogEntry[i];
+ dest->ErrorLog[1].ErrorLogEntry[i] = src->ErrorLog[1].ErrorLogEntry[i];
+ }
+
+ /* convert remainder of Header */
+ dest->GEAddress = (VOID *) _ppc_longswap((ULONG)src->GEAddress);
+ dest->GELength = _ppc_longswap(src->GELength);
+ dest->GELastWriteDT[0] = _ppc_longswap(src->GELastWriteDT[0]);
+ dest->GELastWriteDT[1] = _ppc_longswap(src->GELastWriteDT[1]);
+
+ dest->ConfigAddress =
+ (VOID *)_ppc_longswap((ULONG)src->ConfigAddress);
+ dest->ConfigLength = _ppc_longswap(src->ConfigLength);
+ dest->ConfigLastWriteDT[0] =
+ _ppc_longswap(src->ConfigLastWriteDT[0]);
+ dest->ConfigLastWriteDT[1] =
+ _ppc_longswap(src->ConfigLastWriteDT[1]);
+ dest->ConfigCount = _ppc_longswap(src->ConfigCount);
+
+ dest->OSAreaAddress =
+ (VOID *)_ppc_longswap((ULONG)src->OSAreaAddress);
+ dest->OSAreaLength = _ppc_longswap(src->OSAreaLength);
+ dest->OSAreaLastWriteDT[0] =
+ _ppc_longswap(src->OSAreaLastWriteDT[0]);
+ dest->OSAreaLastWriteDT[1] =
+ _ppc_longswap(src->OSAreaLastWriteDT[1]);
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_headb2l(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR cp;
+ HEADER *dest;
+ HEADER *src;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ dest = (HEADER*)p->lend;
+ src = (HEADER*)p->bend;
+
+ nvr_swap_Header(dest, src);
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_headl2b(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR cp;
+ HEADER *dest;
+ HEADER *src;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ dest = (HEADER*)p->bend;
+ src = (HEADER*)p->lend;
+
+ nvr_swap_Header(dest, src);
+
+ return;
+}
+
+/*
+***********************************************************************
+** the following attempts to protect operation from faulty
+** intitialization of NVRAM by early versions of the machine FW
+***********************************************************************
+*/
+#define GEASIZE (NVSIZE-CONFSIZE-OSAREASIZE-sizeof(HEADER))
+VOID nvr_default_nvram(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR cp;
+ HEADER* bethp;
+
+#ifdef KDB
+DbgPrint("************** nvr_default_nvram: entry\n");
+#endif /* KDB */
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* clear the chip memory */
+ nvr_clear_nvram(p);
+
+ cp = (PUCHAR)p->bend;
+ bethp = (HEADER *) cp;
+ /* clear internal header */
+ for (i = 0; i < sizeof(HEADER); i++)
+ *cp++ = 0;
+
+ /* clear internal data areas */
+ for (i = 0; i < (NVSIZE*2); i++)
+ p->bend[i] = p->lend[i] = 0;
+
+ /* initialize size according to what we know about type */
+ if (p->systype == nvr_systype_polo)
+ bethp->Size = _ppc_shortswap((USHORT)8);
+ else if (p->systype == nvr_systype_woodfield)
+ bethp->Size = _ppc_shortswap((USHORT)8);
+ else
+ bethp->Size = _ppc_shortswap((USHORT)4);
+ bethp->Endian = 'B';
+
+ /* init the header to default values */
+ if (_ppc_shortswap((USHORT)bethp->Size) == 8) {
+ /* size of NVRAM is 8k */
+ if (_ppc_longswap((ULONG)bethp->GEAddress) == 0) {
+ bethp->GEAddress = (VOID *)_ppc_longswap((ULONG)sizeof(HEADER));
+ bethp->GELength = _ppc_longswap((ULONG)GEASIZE+NVSIZE);
+ }
+ if (_ppc_longswap((ULONG)bethp->OSAreaAddress) == 0) {
+ bethp->OSAreaAddress =
+ (VOID *)_ppc_longswap((ULONG)((NVSIZE*2)-(CONFSIZE+OSAREASIZE)));
+ bethp->OSAreaLength =
+ _ppc_longswap((ULONG)OSAREASIZE);
+ }
+ if (_ppc_longswap((ULONG)bethp->ConfigAddress) == 0) {
+ bethp->ConfigAddress = (VOID *)_ppc_longswap((ULONG)(NVSIZE*2));
+ bethp->ConfigLength = _ppc_longswap((ULONG)0);
+ }
+ }
+ else {
+ /* size is assumed to be 4k */
+ if (_ppc_longswap((ULONG)bethp->GEAddress) == 0) {
+ bethp->GEAddress = (VOID *)_ppc_longswap((ULONG)sizeof(HEADER));
+ bethp->GELength = _ppc_longswap((ULONG)GEASIZE);
+ }
+ if (_ppc_longswap((ULONG)bethp->OSAreaAddress) == 0) {
+ bethp->OSAreaAddress =
+ (VOID *)_ppc_longswap((ULONG)(NVSIZE-(CONFSIZE+OSAREASIZE)));
+ bethp->OSAreaLength =
+ _ppc_longswap((ULONG)OSAREASIZE);
+ }
+ if (_ppc_longswap((ULONG)bethp->ConfigAddress) == 0) {
+ bethp->ConfigAddress = (VOID *)_ppc_longswap((ULONG)NVSIZE);
+ bethp->ConfigLength = _ppc_longswap((ULONG)0);
+ }
+ }
+
+ /* transfer data to little endian (internal) side */
+ nvr_headb2l(p);
+
+ /* write the default header to chip memory */
+ nvr_write_Header(p);
+
+#ifdef KDB
+DbgPrint("************** nvr_default_nvram: exit\n");
+#endif /* KDB */
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_read_nvram(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR cp;
+ HEADER* hp;
+ USHORT us;
+ USHORT tmp;
+
+#ifdef KDB
+ DbgPrint("enter nvr_read_nvram\n");
+#endif /* KDB */
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* read data from the NVRAM chip */
+ hp = p->bhead;
+ cp = (PUCHAR)p->bend;
+ for (i = 0; i < sizeof(HEADER); i++)
+ *cp++ = nvr_read(p->systype,i);
+
+#ifdef KDB
+DbgPrint("IMMEDIATELY AFTER READ HEADER - NO DATA AREAS READ\n");
+nvr_display_bemap(p);
+#endif /* KDB */
+
+ if ((hp->Endian != 'B') && (hp->Endian != 'L')) {
+#ifdef KDB
+DbgPrint("BAD ENDIAN\n");
+#endif /* KDB */
+ nvr_default_nvram(p);
+ return;
+ }
+
+ /* convert big endian to little endian */
+ nvr_headb2l(p);
+
+ /* read in data areas */
+ nvr_read_GEArea(p);
+ nvr_read_OSArea(p);
+ nvr_read_CFArea(p);
+
+#ifdef KDB
+DbgPrint("After Areas\n");
+#endif /* KDB */
+
+ /* check valid checksum 1 */
+ us = _ppc_shortswap(hp->Crc1);
+ tmp = nvr_calc1crc(p);
+ if (tmp != us) {
+#ifdef KDB
+ DbgPrint("BADCRC1 nvr_read_nvram: orgcrc1: 0x%08x calccrc1: 0x%08x\n",
+ (int)us, (int)tmp);
+#endif /* KDB */
+ nvr_default_nvram(p);
+ return;
+ }
+
+#ifdef KDB
+DbgPrint("After CRC1\n");
+#endif /* KDB */
+
+#if 0 // Don't let a bad CRC #2 bother us
+ /* check valid checksum 2 */
+ us = _ppc_shortswap(hp->Crc2);
+ tmp = nvr_calc2crc(p);
+ if (tmp != us) {
+#ifdef KDB
+ DbgPrint("BADCRC2 nvr_read_nvram: orgcrc2: 0x%08x calccrc2: 0x%08x\n",
+ (int)us, (int)tmp);
+#endif /* KDB */
+ nvr_default_nvram(p);
+ return;
+ }
+
+#ifdef KDB
+DbgPrint("After CRC2\n");
+#endif /* KDB */
+#endif
+
+#ifdef KDB
+DbgPrint("exit nvr_read_nvram: SUCCESS\n");
+#endif /* KDB */
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_write_Header(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR cp;
+ USHORT us;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* convert little endian to big endian */
+ nvr_headl2b(p);
+
+ us = nvr_calc1crc(p);
+ p->bhead->Crc1 = _ppc_shortswap(us);
+ us = nvr_calc2crc(p);
+ p->bhead->Crc2 = _ppc_shortswap(us);
+
+ /* spit out data */
+ cp = (PUCHAR)p->bend;
+ for (i = 0; i < sizeof(HEADER); i++)
+ nvr_write(p->systype, i, *cp++);
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_read_GEArea(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR lp;
+ PUCHAR bp;
+ ULONG offset;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* suck up global environment data */
+ /* and place it in both little and big endian sides */
+ offset = (ULONG)p->lhead->GEAddress;
+ lp = (PUCHAR)((ULONG)p->lhead + offset);
+ bp = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->GELength; i++, bp++, lp++) {
+ *bp = *lp = nvr_read(p->systype, offset + i);
+ }
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_read_OSArea(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR lp;
+ PUCHAR bp;
+ ULONG offset;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* suck up OS specific data */
+ /* and place it in both little and big endian sides */
+ offset = (ULONG)p->lhead->OSAreaAddress;
+ lp = (PUCHAR)((ULONG)p->lhead + offset);
+ bp = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->OSAreaLength; i++, bp++, lp++) {
+ *bp = *lp = nvr_read(p->systype, offset + i);
+ }
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_read_CFArea(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR lp;
+ PUCHAR bp;
+ ULONG offset;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* suck up configuration data */
+ offset = (ULONG) p->lhead->ConfigAddress;
+ lp = (PUCHAR)((ULONG)p->lhead + offset);
+ bp = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->ConfigLength; i++) {
+ bp[i] = lp[i] = nvr_read(p->systype, (offset + i));
+ }
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_write_GEArea(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR dest;
+ PUCHAR src;
+ ULONG offset;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* copy from little endian to big endian staging area */
+ offset = (ULONG)p->lhead->GEAddress;
+ src = (PUCHAR)((ULONG)p->lhead + offset);
+ dest = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->GELength; i++, dest++, src++)
+ *dest = *src;
+
+ /* convert to big endian, compute crc, and write header */
+ nvr_write_Header(p);
+
+ /* spit out global environment data */
+ src = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->GELength; i++, src++) {
+ nvr_write(p->systype, (i + offset), *src);
+ }
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_write_OSArea(PNVR_OBJECT p)
+{
+ ULONG i;
+ ULONG offset;
+ PUCHAR src;
+ PUCHAR dest;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* copy from little endian to big endian staging area */
+ offset = (ULONG) p->lhead->OSAreaAddress;
+ src = (PUCHAR)((ULONG)p->lhead + offset);
+ dest = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->OSAreaLength; i++, dest++, src++)
+ *dest = *src;
+
+ /* spit out OS specific data */
+ /* header not needed - no crc for OS Area in Header */
+ src = (PUCHAR)((ULONG)p->bhead + offset);
+ for (i = 0; i < p->lhead->OSAreaLength; i++, src++) {
+ nvr_write(p->systype, (i + offset), *src);
+ }
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_write_CFArea(PNVR_OBJECT p)
+{
+ ULONG i;
+ PUCHAR dest;
+ PUCHAR src;
+ ULONG offset;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ /* copy from little endian to big endian staging area */
+ offset = (ULONG)p->lhead->ConfigAddress;
+ dest = (PUCHAR)((ULONG)p->bhead + offset - 1);
+ src = (PUCHAR)((ULONG)p->lhead + offset - 1);
+ for (i = 0; i < p->lhead->ConfigLength; i++, dest--, src--)
+ *dest = *src;
+
+ /* convert to big endian, compute crc, and write header */
+ nvr_write_Header(p);
+
+ /* spit out configuration data */
+ src = (PUCHAR)((ULONG)p->bhead + offset - 1);
+ for (i = 1; i <= p->lhead->ConfigLength; i++, src--) {
+ nvr_write(p->systype, (i + offset), *src);
+ }
+
+ return;
+}
+
+/***********************************************************************/
+PNVR_OBJECT nvr_create_object(NVR_SYSTEM_TYPE systemtype)
+{
+ ULONG i;
+ PUCHAR cp;
+ UCHAR pid;
+
+ pnvrobj = nvr_alloc(sizeof(NVR_OBJECT));
+
+ if (pnvrobj) {
+ /* success */
+ /* zero out input area */
+ for (i = 0, cp = (PUCHAR)pnvrobj; i < sizeof(NVR_OBJECT); i++, cp++)
+ *cp = 0;
+
+ /* initialize internal elements */
+ pnvrobj->self = pnvrobj;
+ pnvrobj->bhead = (HEADER *) pnvrobj->bend;
+ pnvrobj->lhead = (HEADER *) pnvrobj->lend;
+
+ switch (systemtype) {
+ case nvr_systype_powerstack:
+ case nvr_systype_sandalfoot:
+ pnvrobj->systype = nvr_systype_sandalfoot;
+ break;
+ case nvr_systype_bigbend:
+ pnvrobj->systype = nvr_systype_bigbend;
+ break;
+ case nvr_systype_polo:
+ pnvrobj->systype = nvr_systype_polo;
+ break;
+ case nvr_systype_woodfield:
+ pnvrobj->systype = nvr_systype_woodfield;
+ break;
+ default:
+ pnvrobj->systype = nvr_systype_unknown;
+ break;
+ }
+ }
+
+ return(pnvrobj);
+}
+
+/***********************************************************************/
+VOID nvr_delete_object()
+{
+ PNVR_OBJECT p = pnvrobj;
+
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ p->self = (PNVR_OBJECT)0;
+
+ (void)nvr_free(p);
+
+ pnvrobj = (PNVR_OBJECT)0;
+
+ return;
+}
+
+/***********************************************************************/
+STATUS_TYPE nvr_initialize_object(NVR_SYSTEM_TYPE systemtype)
+{
+ HEADER* hp;
+
+#ifdef KDB
+ DbgPrint("enter nvr_initialize_object\n");
+#endif /* KDB */
+
+ if (pnvrobj)
+ return(stat_exist);
+
+ /* create object or get static address */
+ if (!(pnvrobj = nvr_create_object(systemtype)))
+ return(stat_error);
+
+ /* read the header from NVRAM and convert to little endian */
+ nvr_read_nvram(pnvrobj);
+
+ return(stat_ok);
+}
+
+/***********************************************************************/
+VOID nvr_clear_nvram(PNVR_OBJECT p)
+{
+ ULONG i;
+ ULONG len;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ len = NVSIZE;
+ switch (p->systype) {
+ case nvr_systype_polo:
+ case nvr_systype_woodfield:
+ len *= 2;
+ break;
+ case nvr_systype_powerstack:
+ case nvr_systype_sandalfoot:
+ break;
+ case nvr_systype_delmar:
+ default:
+ break;
+ }
+
+ for (i = 0; i < len; i++) {
+ nvr_write(p->systype,i,0);
+ }
+
+ return;
+}
+
+/***********************************************************************/
+VOID nvr_destroy()
+{
+ NVR_SYSTEM_TYPE st;
+
+ /* validate pointer */
+ if ((pnvrobj == NULL) || (pnvrobj != pnvrobj->self))
+ return;
+
+ st = pnvrobj->systype;
+
+ nvr_delete_object();
+ nvr_initialize_object(st);
+ nvr_clear_nvram(pnvrobj);
+ nvr_delete_object();
+
+ nvr_initialize_object(st);
+
+#ifdef KDB
+ nvr_display_object(pnvrobj);
+ nvr_display_lemap(pnvrobj);
+ nvr_display_bemap(pnvrobj);
+#endif /* KDB */
+
+ return;
+}
+
+/*
+***********************************************************************
+** Computation of CRCs must be done consistent with the approach
+** taken by the Firmware (Dakota or Open FW). The algorithm for the
+** following CRC routines (i.e., nvr_computecrc, nvr_calc1crc,
+** nvr_calc2crc were obtained from the ESW group that develops
+** Dakota FW
+**
+** If Dakota changes, then these routines may have to change also.
+**
+** 07.21.94
+***********************************************************************
+*/
+
+#define rol(x,y) ( ( ((x)<<(y)) | ((x)>>(16 - (y))) ) & 0x0FFFF)
+#define ror(x,y) ( ( ((x)>>(y)) | ((x)<<(16 - (y))) ) & 0x0FFFF)
+
+ULONG nvr_computecrc(ULONG oldcrc, UCHAR data)
+{
+ ULONG pd, crc;
+
+ pd = ((oldcrc>>8) ^ data) << 8;
+
+ crc = 0xFF00 & (oldcrc << 8);
+ crc |= pd >> 8;
+ crc ^= rol(pd,4) & 0xF00F;
+ crc ^= ror(pd,3) & 0x1FE0;
+ crc ^= pd & 0xF000;
+ crc ^= ror(pd,7) & 0x01E0;
+ return crc;
+}
+
+USHORT nvr_calc1crc(PNVR_OBJECT p)
+{
+ ULONG ul;
+ ULONG i;
+ PUCHAR cp;
+ ULONG len1;
+ ULONG len2;
+ USHORT us;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return(0);
+
+ ul = 0x0ffff;
+
+ // do not include current Crc1/Crc2 in checksum
+ len1 = (sizeof(p->bhead->Size) +
+ sizeof(p->bhead->Version) +
+ sizeof(p->bhead->Revision));
+ len2 = (ULONG) p->lhead->OSAreaAddress;
+
+
+ // calculate the area before Crc1/Crc2 in the header
+ for (cp = (PUCHAR)p->bhead, i = 0; i < len1; i++)
+ ul = nvr_computecrc(ul, cp[i]);
+
+ // advance to calculate the area after Crc1, Crc2, and LastOS
+ // to include the region up to the OSArea
+ i += (sizeof(p->bhead->Crc1) + sizeof(p->bhead->Crc2)) + 1;
+ for (i = i; i < len2; i++)
+ ul = nvr_computecrc(ul, cp[i]);
+
+ us = (USHORT)(ul & 0x0ffff);
+
+ return(us);
+}
+
+USHORT nvr_calc2crc(PNVR_OBJECT p)
+{
+ ULONG ul;
+ PUCHAR cp;
+ PUCHAR end;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return 0;
+
+ ul = 0x0ffff;
+
+ cp = (PUCHAR)((ULONG)p->bhead + (ULONG)p->lhead->ConfigAddress);
+ end = (PUCHAR)((ULONG)p->bhead +
+ (ULONG)(((ULONG)p->lhead->Size << 10) - 1));
+ for (; cp < end; cp++)
+ ul = nvr_computecrc(ul, *cp);
+
+ return((USHORT)(ul & 0x0ffff));
+}
+
+/*
+***********************************************************************
+** Computation of CRCs must be done consistent with the approach
+** taken by the Firmware (Dakota or Open FW). The algorithm for the
+** above CRC routines (i.e., nvr_computecrc, nvr_calc1crc,
+** nvr_calc2crc were obtained from the ESW group that develops
+** Dakota FW
+**
+** 07.21.94
+***********************************************************************
+*/
+
+/*
+***********************************************************************
+** ----------- Methods Public to the higher layers of SW -------------
+** The methods below operate on the little endian section of the
+** data structure internal to this file. Little endian is the internal
+** (volatile RAM) representation of the NVRAM contents. All access to
+** NVRAM data (variables, etc) are performed on this internal
+** representation. When necessary, the internal representation is
+** downloaded back to NVRAM.
+***********************************************************************
+*/
+
+VOID nvr_print_object()
+{
+#ifdef KDB
+ nvr_display_object(pnvrobj);
+ nvr_display_lemap(pnvrobj);
+ nvr_display_bemap(pnvrobj);
+#endif /* KDB */
+ return;
+}
+
+STATUS_TYPE nvr_find_OS_variable(PUCHAR var, PULONG ni, PULONG vi)
+{
+ PUCHAR lvar;
+ PUCHAR cp;
+ ULONG i;
+ PNVRAM_MAP little_nvrmap;
+
+ if (*var == 0)
+ return(stat_error);
+
+ if (!pnvrobj)
+ return(stat_error);
+
+ little_nvrmap = (PNVRAM_MAP)pnvrobj->lend;
+
+ i = 0;
+ while (TRUE) {
+ lvar = var;
+ *ni = i;
+ cp = (PUCHAR)((ULONG)little_nvrmap +
+ (ULONG)(little_nvrmap->Header.OSAreaAddress));
+
+ /* does the variable we want start at this index? */
+ while (i < little_nvrmap->Header.OSAreaLength) {
+ /* break if mismatch */
+ if (_toupr_(cp[i]) != _toupr_(*lvar))
+ break;
+ lvar++;
+ i++;
+ }
+
+ /* if we're at the end of OSArea and var has a match */
+ if ((*lvar == 0) && (cp[i] == '=')) {
+ *vi = ++i;
+ return(stat_ok);
+ }
+
+ /* no match - set index to start of the next variable */
+ if (i >= little_nvrmap->Header.OSAreaLength)
+ return(stat_error);
+ while (cp[i++] != 0) {
+ if (i >= little_nvrmap->Header.OSAreaLength)
+ return(stat_error);
+ }
+ }
+}
+
+STATUS_TYPE nvr_find_GE_variable(PUCHAR var, PULONG ni, PULONG vi)
+{
+ PUCHAR lvar;
+ PUCHAR cp;
+ ULONG i;
+ HEADER* lhp;
+
+ if (*var == 0)
+ return(stat_error);
+
+ if (!pnvrobj)
+ return(stat_error);
+
+ lhp = (HEADER*)pnvrobj->lhead;
+
+ i = 0;
+ while (TRUE) {
+ lvar = var;
+ *ni = i;
+ cp = (PUCHAR)((ULONG)lhp + (ULONG)(lhp->GEAddress));
+
+ /* does the variable we want start at this index? */
+ while (i < lhp->GELength) {
+ /* break if mismatch */
+ if (_toupr_(cp[i]) != _toupr_(*lvar))
+ break;
+ lvar++;
+ i++;
+ }
+
+ /* if we're at the end of GEArea and var has a match */
+ if ((*lvar == 0) && (cp[i] == '=')) {
+ *vi = ++i;
+ return(stat_ok);
+ }
+
+ /* no match - set index to start of the next variable */
+ if (i >= lhp->GELength)
+ return(stat_error);
+ while (cp[i++] != 0) {
+ if (i >= lhp->GELength)
+ return(stat_error);
+ }
+ }
+}
+
+PUCHAR nvr_get_OS_variable(PUCHAR vname)
+{
+ ULONG ni;
+ ULONG vi;
+ ULONG i;
+ PNVRAM_MAP little_nvrmap;
+
+ if (!pnvrobj)
+ return((PUCHAR)NULL);
+
+ if (nvr_find_OS_variable(vname, &ni, &vi) != stat_ok)
+ return((PUCHAR)NULL);
+
+ little_nvrmap = (PNVRAM_MAP)pnvrobj->lend;
+
+ for (i = 0; i < MAXIMUM_ENVIRONMENT_VALUE - 1; i++) {
+ if (little_nvrmap->OSArea[vi] == 0)
+ break;
+ _currentstring[i] = little_nvrmap->OSArea[vi++];
+ }
+ _currentstring[i] = 0;
+
+ return(_currentstring);
+}
+
+PUCHAR nvr_get_GE_variable(PUCHAR vname)
+{
+ ULONG ni;
+ ULONG vi;
+ ULONG i;
+ PUCHAR cp;
+ HEADER* lhp;
+
+ if (!pnvrobj)
+ return((PUCHAR)NULL);
+
+ if (nvr_find_GE_variable(vname, &ni, &vi) != stat_ok)
+ return((PUCHAR)NULL);
+
+ lhp = (HEADER*)pnvrobj->lhead;
+ cp = (PUCHAR)((ULONG)lhp + (ULONG)lhp->GEAddress);
+
+ for (i = 0; i < MAXIMUM_ENVIRONMENT_VALUE - 1; i++) {
+ if (cp[vi] == 0) {
+ break;
+ }
+ _currentstring[i] = cp[vi++];
+ }
+ _currentstring[i] = 0;
+
+#ifdef KDB
+DbgPrint("get_GE vname: '%s' value: '%s'\n", vname, _currentstring);
+#endif /* KDB */
+
+ return(_currentstring);
+}
+
+STATUS_TYPE nvr_set_OS_variable(PUCHAR vname, PUCHAR value)
+{
+ ULONG nameindex;
+ ULONG valueindex;
+ ULONG eos;
+ PUCHAR str;
+ ULONG count;
+ CHAR c;
+ PUCHAR aptr;
+ HEADER* lhp;
+
+ if ((vname == 0) || (value == 0))
+ return(stat_error);
+
+ if (*vname == 0)
+ return(stat_error);
+
+ if (!pnvrobj)
+ return(stat_error);
+
+ lhp = (HEADER*)pnvrobj->lhead;
+
+#ifdef KDB
+DbgPrint("OS vname: '%s' value: '%s'\n", vname, value);
+#endif /* KDB */
+
+ /* initialize pointer to OS area */
+ aptr = (PUCHAR)((ULONG)lhp + (ULONG)lhp->OSAreaAddress);
+
+ // find the end of the used OS space by looking for
+ // the first non-null character from the top
+ eos = lhp->OSAreaLength - 1;
+ while (aptr[--eos] == 0) {
+ if (eos == 0)
+ break;
+ }
+
+ // position eos to the first new character, unless
+ // environment space is empty
+ if (eos != 0)
+ eos += 2;
+
+ // find out if the variable already has a value
+ count = lhp->OSAreaLength - eos;
+ if (nvr_find_OS_variable(vname, &nameindex, &valueindex) == stat_ok) {
+ // count free space
+ // start with the free area at the top and add
+ // the old nameindex value
+ for (str = &(aptr[valueindex]); *str != 0; str++)
+ count++;
+
+ // if free area is not large enough to handle new value return error
+ for (str = value; *str != 0; str++) {
+ if (count-- == 0)
+ return(stat_error);
+ }
+
+ // pack strings
+ // first move valueindex to the end of the value
+ while (aptr[valueindex++] != 0)
+ ;
+
+ // now move everything to where the variable starts
+ // covering up the old name/value pair
+ while (valueindex < eos) {
+ c = aptr[valueindex++];
+ aptr[nameindex++] = c;
+ }
+
+ // adjust new top of environment
+ eos = nameindex;
+
+ // zero to the end of OS area
+ while (nameindex < lhp->OSAreaLength)
+ aptr[nameindex++] = 0;
+ }
+ else {
+ // variable is new
+ // if free area is not large enough to handle new value return error
+ for (str = value; *str != 0; str++) {
+ if (count-- == 0)
+ return(stat_error);
+ }
+ }
+
+ /* if value is null, we have removed the variable */
+ if (*value) {
+ // insert new name, converting to upper case.
+ while (*vname != 0) {
+ aptr[eos++] = _toupr_(*vname);
+ vname++;
+ }
+ aptr[eos++] = '=';
+
+ // insert new value
+ while (*value != 0) {
+ aptr[eos++] = *value;
+ value++;
+ }
+ }
+
+ nvr_write_OSArea(pnvrobj);
+
+ return(stat_ok);
+}
+
+STATUS_TYPE nvr_set_GE_variable(PUCHAR vname, PUCHAR value)
+{
+ ULONG nameindex;
+ ULONG valueindex;
+ ULONG toe;
+ PUCHAR str;
+ ULONG count;
+ CHAR c;
+ PUCHAR aptr;
+ HEADER* lhp;
+
+ if (vname == 0)
+ return(stat_error);
+
+ if (*vname == 0)
+ return(stat_error);
+
+ if (!pnvrobj)
+ return(stat_error);
+
+ lhp = (HEADER*)pnvrobj->lhead;
+
+#ifdef KDB
+DbgPrint("set_GE vname: '%s' value: '%s'\n", vname, value);
+#endif /* KDB */
+
+ /* initialize pointer to OS area */
+ aptr = (PUCHAR)((ULONG)lhp + (ULONG)lhp->GEAddress);
+
+ /* find the top of the used environment space by looking for */
+ /* the first non-null character from the top */
+ toe = lhp->GELength - 1;
+
+ aptr = (PUCHAR)((ULONG)lhp + (ULONG)lhp->GEAddress);
+ while (aptr[--toe] == 0) {
+ if (toe == 0)
+ break;
+ }
+
+ /* adjust toe to the first new character, unless */
+ /* environment space is empty */
+ if (toe != 0)
+ toe += 2;
+
+ /* find out if the variable already has a value */
+ count = lhp->GELength - toe;
+ if (nvr_find_GE_variable(vname, &nameindex, &valueindex) == stat_ok) {
+ /* count free space */
+ /* start with the free area at the top and add */
+ /* the old nameindex value */
+ for (str = &(aptr[valueindex]); *str != 0; str++)
+ count++;
+
+ /* if free area is not large enough to handle new value return error */
+ if (value) {
+ for (str = value; *str != 0; str++) {
+ if (count-- == 0)
+ return(stat_error);
+ }
+ }
+
+ /* pack strings */
+ /* first move valueindex to the end of the value */
+ while (aptr[valueindex++] != 0)
+ ;
+
+ /* now move everything to where the variable starts */
+ /* covering up the old name/value pair */
+ while (valueindex < toe) {
+ c = aptr[valueindex++];
+ aptr[nameindex++] = c;
+ }
+
+ /* adjust new top of environment */
+ toe = nameindex;
+
+ /* zero to the end of GE area */
+ while (nameindex < lhp->GELength)
+ aptr[nameindex++] = 0;
+ }
+ else {
+ /* variable is new */
+ /* if free area is not large enough to handle new value return error */
+ if (value) {
+ for (str = value; *str != 0; str++) {
+ if (count-- == 0)
+ return(stat_error);
+ }
+ }
+ }
+
+ /* if value is null or is a pointer to a 0 */
+ /* the variable has been removed */
+ if ((value) && (*value)) {
+ /* insert new name, converting to upper case */
+ while (*vname != 0) {
+ aptr[toe] = _toupr_(*vname);
+ vname++;
+ toe++;
+ }
+ aptr[toe++] = '=';
+
+ /* insert new value */
+ while (*value != 0) {
+ aptr[toe] = *value;
+ value++;
+ toe++;
+ }
+ }
+
+ nvr_write_GEArea(pnvrobj);
+
+ return(stat_ok);
+}
+
+PUCHAR nvr_fetch_GE()
+{
+ ULONG i;
+ ULONG toe;
+ PNVRAM_MAP little_nvrmap;
+
+ if (!pnvrobj)
+ return NULL;
+
+ little_nvrmap = (NVRAM_MAP *)pnvrobj->lend;
+
+ // initialize hold buffer to zeros
+ for (i = 0; i < little_nvrmap->Header.GELength; i++)
+ _currentfetch[i] = 0;
+
+ // find the top of the used environment space by looking for
+ // the first non-null character from the top
+ toe = little_nvrmap->Header.GELength - 1;
+ while ((little_nvrmap->GEArea[--toe]) == 0) {
+ if (toe == 0)
+ break;
+ }
+
+ // toe contains last index of GE
+ if (toe == 0)
+ return(_currentfetch);
+
+ // copy from GE to hold buffer
+ for (i = 0; ((i <= toe) && (i < MAXNVRFETCH)); i++)
+ _currentfetch[i] = little_nvrmap->GEArea[i];
+
+ return(_currentfetch);
+}
+
+PUCHAR nvr_fetch_OS()
+{
+ ULONG i;
+ ULONG toe;
+ PNVRAM_MAP little_nvrmap;
+
+ if (!pnvrobj)
+ return NULL;
+
+ little_nvrmap = (NVRAM_MAP *)pnvrobj->lend;
+
+ // initialize the hold buffer to zeros
+ for (i = 0; i < little_nvrmap->Header.OSAreaLength; i++)
+ _currentfetch[i] = 0;
+
+ // find the top of the used environment space by looking for
+ // the first non-null character from the top
+ toe = little_nvrmap->Header.OSAreaLength - 1;
+ while ((little_nvrmap->OSArea[--toe]) == 0) {
+ if (toe == 0)
+ break;
+ }
+
+ // toe contains last index of OS
+ if (toe == 0)
+ return(_currentfetch);
+
+ // copy from OS to hold buffer
+ for (i = 0; ((i <= toe) && (i < MAXNVRFETCH)); i++)
+ _currentfetch[i] = little_nvrmap->OSArea[i];
+
+ return(_currentfetch);
+}
+
+PUCHAR nvr_fetch_CF()
+{
+ ULONG i;
+ PNVRAM_MAP little_nvrmap;
+
+ if (!pnvrobj)
+ return NULL;
+
+ little_nvrmap = (NVRAM_MAP *)pnvrobj->lend;
+
+ /* initialize the hold buffer to zeros */
+ for (i = 0; i < MAXNVRFETCH; i++)
+ _currentfetch[i] = 0;
+
+ /* copy from Config to hold buffer */
+ for (i = 0; i < little_nvrmap->Header.ConfigLength; i++)
+ _currentfetch[i] = little_nvrmap->ConfigArea[i];
+
+ return(_currentfetch);
+}
+
+/*
+***********************************************************************
+** ----------- Methods Public to the higher layers of SW -------------
+** The methods above operate on the little endian section of the
+** data structure internal to this file. Little endian is the internal
+** (volatile RAM) representation of the NVRAM contents. All access to
+** NVRAM data (variables, etc) are performed on this internal
+** representation. When necessary, the internal representation is
+** downloaded back to NVRAM.
+***********************************************************************
+*/
+
+#ifdef KDB
+/*
+***********************************************************************
+** The methods below are used in development and debug.
+***********************************************************************
+*/
+
+VOID nvr_display_object(PNVR_OBJECT p)
+{
+ PUCHAR cp;
+ int len;
+ UCHAR tmp;
+ PNVRAM_MAP mp;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ DbgPrint(" ---- ---- INTERNAL DISPLAY ---- ----\n\r");
+ DbgPrint(" Object Addr: 0x%08lx\n\r",(ULONG)p->self);
+ switch (p->systype) {
+ case nvr_systype_powerstack:
+ DbgPrint(" System Type: PowerStack\n\r");
+ break;
+ case nvr_systype_sandalfoot:
+ DbgPrint(" System Type: Sandalfoot\n\r");
+ break;
+ case nvr_systype_polo:
+ DbgPrint(" System Type: Polo\n\r");
+ break;
+ case nvr_systype_woodfield:
+ DbgPrint(" System Type: Woodfield\n\r");
+ break;
+ case nvr_systype_delmar:
+ DbgPrint(" System Type: Delmar\n\r");
+ break;
+ default:
+ DbgPrint(" System Type: Unknown\n\r");
+ break;
+ }
+ DbgPrint(" BE Header addr: 0x%08lx\n\r",(ULONG)p->bhead);
+ DbgPrint(" BE Map addr: 0x%08lx\n\r",(ULONG)p->bend);
+ DbgPrint(" LE Header addr: 0x%08lx\n\r",(ULONG)p->lhead);
+ DbgPrint(" LE Map addr: 0x%08lx\n\r",(ULONG)p->lend);
+ DbgPrint(" ---- ---- INTERNAL DISPLAY ---- ----\n\r");
+
+ return;
+}
+
+VOID nvr_display_lemap(PNVR_OBJECT p)
+{
+ PUCHAR cp;
+ PUCHAR max;
+ UCHAR tmp;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ DbgPrint(" -------- ---- ---- ---- ---- LITTLE DISPLAY\n\r");
+ DbgPrint(" NVR Size: 0x%04xK (%dK)", (int)p->lhead->Size,
+ (int)p->lhead->Size);
+ DbgPrint(" Version: 0x%02x Revision: 0x%02x\n\r",
+ (int)p->lhead->Version, (int)p->lhead->Revision);
+ DbgPrint(" Crc1: 0x%04x Crc2: 0x%04x\n\r",
+ (int)p->lhead->Crc1, (int)p->lhead->Crc2);
+ DbgPrint(" NVR Endian: '%c'\n\r",p->lhead->Endian);
+
+ tmp = p->lhead->Security.Serial[15];
+ p->lhead->Security.Serial[15] = 0;
+ DbgPrint(" NVR Serial: '%s'\n\r",p->lhead->Security.Serial);
+ p->lhead->Security.Serial[15] = tmp;
+
+ DbgPrint(" GEAddress: 0x%08lx GELength: 0x%08lx\n\r",
+ (ULONG)p->lhead->GEAddress, (ULONG)p->lhead->GELength);
+ cp = (PUCHAR)((ULONG)p->lhead + (ULONG)p->lhead->GEAddress);
+ max = (PUCHAR)((ULONG)p->lhead + (ULONG)p->lhead->GEAddress +
+ (ULONG)p->lhead->GELength);
+ while ((*cp) && (cp < max)) {
+ DbgPrint(" '%s'\n\r", cp);
+ cp += (strlen(cp) + 1);
+ }
+
+ DbgPrint(" OSAreaAddress: 0x%08lx OSAreaLength: 0x%08lx\n\r",
+ (ULONG)p->lhead->OSAreaAddress, (ULONG)p->lhead->OSAreaLength);
+ cp = (PUCHAR)((ULONG)p->lhead + (ULONG)p->lhead->OSAreaAddress);
+ max = (PUCHAR)((ULONG)p->lhead + (ULONG)p->lhead->OSAreaAddress +
+ (ULONG)p->lhead->OSAreaLength);
+ while ((*cp) && (cp < max)) {
+ DbgPrint(" '%s'\n\r", cp);
+ cp += (strlen(cp) + 1);
+ }
+
+ DbgPrint(" ConfigAddress: 0x%08lx ConfigLength: 0x%08lx Count: 0x%08lx\n\r",
+ (ULONG)p->lhead->ConfigAddress, (ULONG)p->lhead->ConfigLength,
+ (ULONG)p->lhead->ConfigCount);
+ DbgPrint(" -------- ---- ---- ---- ---- LITTLE DISPLAY\n\r");
+
+ return;
+}
+
+VOID nvr_display_bemap(PNVR_OBJECT p)
+{
+ PUCHAR cp;
+ PUCHAR max;
+ UCHAR tmp;
+ PNVRAM_MAP mp;
+ HEADER* hp;
+
+ /* validate pointer */
+ if ((p == NULL) || (p != p->self))
+ return;
+
+ mp = p->bend;
+ hp = p->bhead;
+
+ DbgPrint(" ---- ---- BIG DISPLAY ---- ----\n\r");
+ DbgPrint(" NVR Size: 0x%04xK (%dK)", (int)mp->Header.Size,
+ (int)mp->Header.Size);
+ DbgPrint(" Version: 0x%02x Revision: 0x%02x\n\r",
+ (int)mp->Header.Version, (int)mp->Header.Revision);
+ DbgPrint(" Crc1: 0x%04x Crc2: 0x%04x\n\r",
+ (int)mp->Header.Crc1, (int)mp->Header.Crc2);
+ DbgPrint(" NVR Endian: '%c'\n\r",mp->Header.Endian);
+
+ tmp = mp->Header.Security.Serial[15];
+ mp->Header.Security.Serial[15] = 0;
+ DbgPrint(" NVR Serial: '%s'\n\r",mp->Header.Security.Serial);
+ mp->Header.Security.Serial[15] = tmp;
+
+ DbgPrint(" GEAddress: 0x%08lx GELength: 0x%08lx\n\r",
+ (ULONG)hp->GEAddress, (ULONG)hp->GELength);
+ cp = (PUCHAR)((ULONG)hp + _ppc_longswap((ULONG)hp->GEAddress));
+ max = (PUCHAR)((ULONG)cp + _ppc_longswap((ULONG)hp->GELength));
+ while ((*cp) && (cp < max)) {
+ DbgPrint(" '%s'\n\r", cp);
+ cp += (strlen(cp) + 1);
+ }
+
+ DbgPrint(" OSAreaAddress: 0x%08lx OSAreaLength: 0x%08lx\n\r",
+ (ULONG)hp->OSAreaAddress, (ULONG)hp->OSAreaLength);
+ cp = (PUCHAR)((ULONG)hp + _ppc_longswap((ULONG)hp->OSAreaAddress));
+ max = (PUCHAR)((ULONG)cp + _ppc_longswap((ULONG)hp->OSAreaLength));
+ while ((*cp) && (cp < max)) {
+ DbgPrint(" '%s'\n\r", cp);
+ cp += (strlen(cp) + 1);
+ }
+
+ DbgPrint(" ConfigAddress: 0x%08lx ConfigLength: 0x%08lx Count: 0x%08lx\n\r",
+ (ULONG)hp->ConfigAddress, (ULONG)hp->ConfigLength,
+ (ULONG)hp->ConfigCount);
+ DbgPrint(" ---- ---- BIG DISPLAY ---- ----\n\r");
+
+ return;
+}
+
+VOID nvr_test_setvar(VOID)
+{
+ DbgPrint("\n\r");
+ DbgPrint("--------- VARIABLE SET TEST\n\r");
+ nvr_display_lemap(pnvrobj);
+ DbgPrint("---------\n\r");
+
+ (VOID)nvr_set_GE_variable("GESLUG0","this is it");
+ (VOID)nvr_set_GE_variable("GESLUG1","NO: this is it");
+ (VOID)nvr_set_GE_variable("GESLUG2","I beg your pardon! This is it");
+
+ (VOID)nvr_set_OS_variable("OSSLUG0","multi(0)scsi(0)");
+ (VOID)nvr_set_OS_variable("OSSLUG1","multi(0)scsi(1)");
+ (VOID)nvr_set_OS_variable("OSSLUG2",
+ "multi(0)scsi(0)disk(6)rdisk(0)partition(1)");
+ nvr_display_lemap(pnvrobj);
+
+ DbgPrint("--------- VARIABLE SET TEST\n\r");
+
+ return;
+}
+
+VOID nvr_test_object(NVR_SYSTEM_TYPE systemtype)
+{
+ PUCHAR cp;
+
+ nvr_initialize_object(systemtype);
+
+ nvr_display_object(pnvrobj);
+ nvr_display_lemap(pnvrobj);
+ nvr_display_bemap(pnvrobj);
+
+/***************************
+ cp = nvr_get_GE_variable("SYSTEMPARTITION");
+ if (cp) {
+ if (*cp == 0)
+ DbgPrint("nvr_test_object: SYSTEMPARTITION=-value zero-\n",cp);
+ else
+ DbgPrint("nvr_test_object: SYSTEMPARTITION='%s'\n",cp);
+ }
+ else
+ DbgPrint("nvr_test_object: SYSTEMPARTITION=-pointer NULL-\n");
+
+ cp = nvr_get_GE_variable("DOG000111");
+ if (cp) {
+ if (*cp == 0)
+ DbgPrint("nvr_test_object: DOG000111=-value zero-\n",cp);
+ else
+ DbgPrint("nvr_test_object: DOG000111='%s'\n",cp);
+ }
+ else
+ DbgPrint("nvr_test_object: DOG000111=-pointer NULL-\n");
+
+ DbgBreakPoint();
+ nvr_test_setvar();
+ DbgBreakPoint();
+***************************/
+
+/***************************
+ DbgPrint("--------- CLEARING NVRAM\n");
+ if (!(pnvrobj = nvr_create_object(systemtype)))
+ return;
+ nvr_clear_nvram(pnvrobj);
+ nvr_delete_object();
+ DbgPrint("--------- CLEARED NVRAM\n");
+ DbgBreakPoint();
+***************************/
+
+/***************************
+ DbgPrint("--------- REREAD NVRAM \n\r");
+ DbgPrint("---------\n");
+ DbgPrint("---------\n");
+ nvr_initialize_object(systemtype);
+ DbgPrint("nvr_calc1crc: 0x%08x\n",(int)nvr_calc1crc(pnvrobj));
+ DbgPrint("nvr_calc2crc: 0x%08x\n",(int)nvr_calc2crc(pnvrobj));
+ nvr_display_lemap(pnvrobj);
+ nvr_display_bemap(pnvrobj);
+ DbgPrint("--- SETTING VARS\n");
+ (VOID)nvr_set_GE_variable("GESLUG0","this is it");
+ (VOID)nvr_set_GE_variable("GESLUG1"," -------- this is it --------");
+ (VOID)nvr_set_OS_variable("OSSLUG0","multi(0)scsi(0)");
+ (VOID)nvr_set_OS_variable("OSSLUG1","multi(1)scsi(1)");
+ nvr_display_lemap(pnvrobj);
+ nvr_display_bemap(pnvrobj);
+ (VOID)nvr_set_GE_variable("GESLUG0","");
+ nvr_display_lemap(pnvrobj);
+
+ DbgPrint("---------\n");
+ DbgPrint("---------\n");
+ DbgPrint("--------- REREAD NVRAM \n\r");
+ DbgBreakPoint();
+
+***************************/
+
+ return;
+}
+#endif /* KDB */
diff --git a/private/ntos/nthals/haleagle/ppc/fwnvr.h b/private/ntos/nthals/haleagle/ppc/fwnvr.h
new file mode 100644
index 000000000..568d83f95
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/fwnvr.h
@@ -0,0 +1,37 @@
+#ifndef _FWNVR_H
+#define _FWNVR_H
+
+typedef enum _nvr_system_type {
+ nvr_systype_null = 0x00,
+ nvr_systype_unknown = 0x01,
+ nvr_systype_sandalfoot = 0x02,
+ nvr_systype_polo = 0x04,
+ nvr_systype_woodfield = 0x08,
+ nvr_systype_delmar = 0x10,
+ nvr_systype_bigbend = 0x20,
+ nvr_systype_powerstack = 0x40,
+ nvr_systype_last = 0x80
+ } NVR_SYSTEM_TYPE;
+
+STATUS_TYPE nvr_initialize_object(NVR_SYSTEM_TYPE);
+VOID nvr_delete_object(VOID);
+VOID nvr_destroy(VOID);
+STATUS_TYPE nvr_find_GE_variable(PUCHAR,PULONG,PULONG);
+STATUS_TYPE nvr_set_GE_variable(PUCHAR,PUCHAR);
+STATUS_TYPE nvr_find_OS_variable(PUCHAR,PULONG,PULONG);
+STATUS_TYPE nvr_set_OS_variable(PUCHAR,PUCHAR);
+
+PUCHAR nvr_get_GE_variable(PUCHAR);
+PUCHAR nvr_get_OS_variable(PUCHAR);
+PUCHAR nvr_fetch_GE(VOID);
+PUCHAR nvr_fetch_OS(VOID);
+PUCHAR nvr_fetch_CF(VOID);
+
+#ifdef KDB
+VOID nvr_print_object(VOID);
+VOID nvr_test_object(NVR_SYSTEM_TYPE);
+#endif /* KDB */
+
+#define MAXIMUM_ENVIRONMENT_VALUE 256
+
+#endif /* _FWNVR_H */
diff --git a/private/ntos/nthals/haleagle/ppc/fwstatus.h b/private/ntos/nthals/haleagle/ppc/fwstatus.h
new file mode 100644
index 000000000..fd09e6363
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/fwstatus.h
@@ -0,0 +1,17 @@
+#ifndef _FWSTATUS_H_
+#define _FWSTATUS_H_
+
+typedef enum _status_type {
+ stat_ok = 0,
+ stat_warning = 1,
+ stat_exist = 2,
+ stat_error = 3,
+ stat_badptr = 4,
+ stat_notexist = 5,
+ stat_noentry = 6,
+ stat_checksum = 7,
+ stat_badlength = 8,
+ stat_last = 0x40
+ } STATUS_TYPE;
+
+#endif /* _FWSTATUS_H_ */
diff --git a/private/ntos/nthals/haleagle/ppc/halp.h b/private/ntos/nthals/haleagle/ppc/halp.h
new file mode 100644
index 000000000..ad74517ac
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/halp.h
@@ -0,0 +1,239 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (C) 1991-1995 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 "hal.h"
+
+#include "ppcdef.h"
+#include "pxhalp.h"
+
+#ifndef _HALI_
+#include "..\inc\hali.h"
+#endif
+
+
+
+
+//
+// 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 SPRANGEPOOL NonPagedPool // for now, until crashdump is fixed
+#define HalpHandlerForBus HaliHandlerForBus
+#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
+
+
+//
+// Define function prototypes.
+//
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG,
+ ULONG
+ );
+
+BOOLEAN
+HalpInitPciIsaBridge (
+ VOID
+ );
+
+VOID
+HalpHandleIoError (
+ VOID
+ );
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ );
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ );
+
+BOOLEAN
+HalpHandleProfileInterrupt (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+
+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
+ );
+
+//
+// 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 HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+
+
+#define IRQ_VALID 0x01
+#define IRQ_PREFERRED 0x02
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/haleagle/ppc/mk48tdc.h b/private/ntos/nthals/haleagle/ppc/mk48tdc.h
new file mode 100644
index 000000000..c98179731
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/mk48tdc.h
@@ -0,0 +1,68 @@
+/*++
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ mk48tdc.h
+
+Abstract:
+
+ This module is the header file that describes hardware structure
+ for the realtime clock on the Comet (PowerPC 603/604) platform.
+
+ This module was taken from the jazzrtc.h file and renamed.
+
+Original Author:
+
+ David N. Cutler (davec) 3-May-1991
+
+Revision History:
+
+Who When What
+--- -------- -----------------------------------------------
+dgh 07/13/94 Redefined the TODC registers for the MK48T18 chip.
+dgh 07/22/94 Update file name in header comment.
+dgh 08/03/94 Redefined virtual address of RTC and NVRAM.
+dgh 08/08/94 Don't use virtual addresses for RTC and NVRAM, use
+ offsets instead. Actual virtual address will be in
+ the HalpNvramBaseAddr variable.
+kjr 10/18/94 Changes to support Revision B Comet motherboard.
+ Remove HalpNvramBaseAddr and use new NVRAM address
+ and data port.
+
+--*/
+
+#ifndef _MK48TDC
+#define _MK48TDC
+
+
+typedef struct _NVRAM_CONTROL {
+ UCHAR Reserved0[0x74];
+ UCHAR NvramIndexLo; // Offset 0x74
+ UCHAR NvramIndexHi; // Offset 0x75
+ UCHAR Reserved2[1];
+ UCHAR NvramData; // Offset 0x77
+} NVRAM_CONTROL, *PNVRAM_CONTROL;
+
+//
+// Define Realtime Clock register numbers
+// for the MK48T18 TODC Chip.
+//
+#define TODC_CONTROL 0 // TODC Control Register
+#define TODC_SECOND 1 // second of minute [0..59]
+#define TODC_MINUTE 2 // minute of hour [0..59]
+#define TODC_HOUR 3 // hour of day [0..23]
+#define TODC_DAY_OF_WEEK 4 // day of week [1..7]
+#define TODC_DAY_OF_MONTH 5 // day of month [1..31]
+#define TODC_MONTH 6 // month of year [1..12]
+#define TODC_YEAR 7 // year [00..99]
+
+
+//
+// Comet NVRAM/RTC Mapping
+//
+#define TODC_OFFSET 0x9ff8 // offset of RTC
+#define NVR_OFFSET 0x8000 // offset of NVRAM
+
+
+#endif // MK48TDC
diff --git a/private/ntos/nthals/haleagle/ppc/mk48time.c b/private/ntos/nthals/haleagle/ppc/mk48time.c
new file mode 100644
index 000000000..fe0ccf00d
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/mk48time.c
@@ -0,0 +1,431 @@
+/*++
+
+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:
+
+ mk48time.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a PowerPC system using the MK48T18 Clock Chip.
+
+Original Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+Who When What
+--- -------- -----------------------------------------------
+dgh 07/20/94 Created from pxtime.c and modified for MK48T18 chip.
+dgh 07/22/94 Fixed typo of HalpReadRawClockRegister.
+dgh 07/29/94 Don't run the day-of-week value through the BCD
+ conversion when reading the clock. Also mask it
+ to 3-bits.
+dgh 08/08/94 Compute RTC location from HalpNvramBaseAddr and the
+ RTC offset.
+dgh 08/09/94 HalQueryRealTimeClock: Forgot to restart the clock
+ after reading it.
+kjr 10/18/94 Changes for Revision B Comet Mother Board. Remove
+ HalpNvramBaseAddr and use new NVRAM address and data
+ port.
+
+--*/
+
+#include "halp.h"
+#include "mk48tdc.h"
+#include "eisa.h"
+
+#define WRITE 0x80 // Stop update while writing control bit
+#define READ 0x40 // Stop updating while reading control bit
+#define STOP 0x80 // Clock is stopped bit
+
+extern PVOID HalpIoControlBase;
+#define RTC_BASE (TODC_OFFSET)
+#define NVRAM ((PNVRAM_CONTROL) HalpIoControlBase)
+
+//***************************************************************************
+// Time of Day Clock registers for the MK48T18 chip can be viewed as an
+// array of bytes (UCHARs) where:
+//
+// Address of Real Time Clock Register bitmap of registers
+// -----------------------------------------------------------------------
+// TODC_OFFSET + 0: clock control/calibration reg. [W R S - - - - -]
+// TODC_OFFSET + 1: seconds register (00-59) [P - - - - - - -]
+// TODC_OFFSET + 2: minutes register (00-59) [0 - - - - - - -]
+// TODC_OFFSET + 3: hours register (00-23) [0 0 - - - - - -]
+// TODC_OFFSET + 4: day-of-week register (01-07) [0 F 0 0 0 - - -]
+// TODC_OFFSET + 5: day-of-month register (01-31) [0 0 - - - - - -]
+// TODC_OFFSET + 6: month register (01-12) [0 0 0 - - - - -]
+// TODC_OFFSET + 7: year register (00-99) [- - - - - - - -]
+// W=write, R=read, S=sign, P=stop
+// F=frequency test.
+//
+// NOTE: Values in the TODC registers are in BCD format
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+static UCHAR
+HalpReadRawClockRegister (
+ UCHAR Register
+ );
+
+static VOID
+HalpWriteRawClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+static UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+static VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClockMk (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+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.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL 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.
+ //
+ // NOTE: It isn't possible to test this clock chip to determine if
+ // the battery is still running or not. So we check the STOP
+ // bit and if set, then we return FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ DataByte = HalpReadRawClockRegister(TODC_SECOND);
+ if (!(DataByte & STOP)) {
+
+ //
+ // Clock is running.
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadRawClockRegister(TODC_CONTROL);
+ } while (DataByte & WRITE);
+
+ //
+ // First stop the clock from being updated while we read it.
+ //
+ DataByte = HalpReadRawClockRegister(TODC_CONTROL);
+ DataByte |= READ;
+ HalpWriteRawClockRegister(TODC_CONTROL, DataByte);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1900 + (CSHORT)HalpReadClockRegister(TODC_YEAR);
+ if (TimeFields->Year < 1980) TimeFields->Year += 100;
+
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(TODC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(TODC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(TODC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(TODC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(TODC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(TODC_SECOND);
+ TimeFields->Milliseconds = 0;
+
+ //
+ // Now restart the clock
+ //
+ DataByte = HalpReadRawClockRegister(TODC_CONTROL);
+ DataByte &= ~READ;
+ HalpWriteRawClockRegister(TODC_CONTROL, DataByte);
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClockMk (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+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.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL 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.
+ //
+ // NOTE: We can't determine if the battery is running or not on
+ // this clock chip. So, instead we check the STOP bit and
+ // if set, then we treat this as the same condition and
+ // return FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadRawClockRegister(TODC_SECOND);
+ if (!(DataByte & STOP)) {
+
+ //
+ // Clock is running.
+ // Set the realtime clock to stop updating while we set
+ // the time.
+ //
+
+
+ DataByte = HalpReadRawClockRegister(TODC_CONTROL);
+ DataByte |= WRITE;
+ HalpWriteRawClockRegister(TODC_CONTROL, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ if (TimeFields->Year > 1999)
+ HalpWriteClockRegister(TODC_YEAR, (UCHAR)(TimeFields->Year - 2000));
+ else
+ HalpWriteClockRegister(TODC_YEAR, (UCHAR)(TimeFields->Year - 1900));
+
+ HalpWriteClockRegister(TODC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(TODC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(TODC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(TODC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(TODC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(TODC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to resume updating the time.
+ //
+
+ DataByte = HalpReadRawClockRegister(TODC_CONTROL);
+ DataByte &= ~WRITE;
+ HalpWriteRawClockRegister(TODC_CONTROL, DataByte);
+
+
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+static UCHAR
+HalpReadRawClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+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.
+
+--*/
+
+{
+ //
+ // Read the specified Register from the Real Time Clock.
+ //
+ WRITE_REGISTER_UCHAR (&NVRAM->NvramIndexLo, (RTC_BASE + Register) & 0xFF);
+ WRITE_REGISTER_UCHAR (&NVRAM->NvramIndexHi, (RTC_BASE + Register) >> 8);
+ return(READ_REGISTER_UCHAR (&NVRAM->NvramData));
+}
+
+static UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+ change return value from BCD to binary integer. I think the chip
+
+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 BcdValue;
+
+
+ BcdValue = HalpReadRawClockRegister(Register);
+ //
+ // If this is NOT the day-of-week register, then
+ // convert from BCD. If it is day-of-week, then
+ // mask off to 3-bits.
+ //
+ if (Register != TODC_DAY_OF_WEEK)
+ {
+ BcdValue = ((BcdValue >> 4) & 0xf) * 10 + (BcdValue & 0xf);
+ }
+ else
+ BcdValue &= 0x07;
+
+ return BcdValue;
+}
+
+static VOID
+HalpWriteRawClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+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:
+
+ None
+
+--*/
+
+{
+ //
+ // Write the realtime clock register value.
+ //
+ WRITE_REGISTER_UCHAR (&NVRAM->NvramIndexLo, (RTC_BASE + Register) & 0xFF);
+ WRITE_REGISTER_UCHAR (&NVRAM->NvramIndexHi, (RTC_BASE + Register) >> 8);
+ WRITE_REGISTER_UCHAR (&NVRAM->NvramData, Value);
+}
+
+static VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+ The value is first converted to BCD format before being written to
+ the 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:
+
+ None
+
+--*/
+
+{
+ UCHAR BcdValue;
+
+ //
+ // First ensure that the value is in range 0 - 99
+ //
+ BcdValue = (((Value % 100) / 10) << 4) | (Value % 10);
+ HalpWriteRawClockRegister(Register, BcdValue);
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pcibios.c b/private/ntos/nthals/haleagle/ppc/pcibios.c
new file mode 100644
index 000000000..a922c00e3
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pcibios.c
@@ -0,0 +1,1056 @@
+/*++
+
+
+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;
+
+//
+// Mapped I/O space.
+//
+#define CONFIG_ADDR (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress)
+#define CONFIG_DATA (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData)
+
+
+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;
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ WRITE_PORT_ULONG (CONFIG_DATA, 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);
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ return READ_PORT_UCHAR ((PUCHAR)CONFIG_DATA + 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);
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ return READ_PORT_USHORT ((PUCHAR)CONFIG_DATA + 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);
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ return READ_PORT_ULONG (CONFIG_DATA);
+}
+
+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);
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ WRITE_PORT_UCHAR ((PUCHAR)CONFIG_DATA + 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);
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ WRITE_PORT_USHORT ((PUCHAR)CONFIG_DATA + 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);
+
+ WRITE_PORT_ULONG (CONFIG_ADDR, Addr.u.AsULONG );
+
+ WRITE_PORT_ULONG (CONFIG_DATA, 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/haleagle/ppc/pcibios.h b/private/ntos/nthals/haleagle/ppc/pcibios.h
new file mode 100644
index 000000000..2e47f6b23
--- /dev/null
+++ b/private/ntos/nthals/haleagle/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/haleagle/ppc/pcip.h b/private/ntos/nthals/haleagle/ppc/pcip.h
new file mode 100644
index 000000000..3aa4853ca
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pcip.h
@@ -0,0 +1,186 @@
+//
+// Hal specific PCI bus structures
+//
+
+typedef NTSTATUS
+(*PciIrqRange) (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+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;
+ PciIrqRange GetIrqRange;
+
+ BOOLEAN BridgeConfigRead;
+ UCHAR ParentBus;
+ UCHAR reserved[2];
+ UCHAR SwizzleIn[4];
+
+ 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))
+
+
+#if DBG
+#define IRQXOR 0x2B
+#else
+#define IRQXOR 0
+#endif
+
+
+//
+// Prototypes for functions in ixpcibus.c
+//
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+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
+ );
+
+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 PSUPPORTED_RANGE *Interrupt
+ );
+
+//
+// Prototypes for functions in ixpcibrd.c
+//
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ );
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ );
+
+//
+//
+//
+
+#ifdef SUBCLASSPCI
+
+VOID
+HalpSubclassPCISupport (
+ IN PBUS_HANDLER BusHandler,
+ IN ULONG HwType
+ );
+
+#endif
diff --git a/private/ntos/nthals/haleagle/ppc/prepnvr.h b/private/ntos/nthals/haleagle/ppc/prepnvr.h
new file mode 100644
index 000000000..93c8c09bc
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/prepnvr.h
@@ -0,0 +1,134 @@
+/* Structure map for NVRAM on PowerPC Reference Platform */
+
+/* Revision 1 changes (8/25/94):
+ - Power Management (RESTART_BLOCK struct)
+ - Normal added to PM_MODE
+ - OSIRQMask (HEADER struct) */
+
+/* All fields are either character/byte strings which are valid either
+endian or they are big-endian numbers.
+
+There are a number of Date and Time fields which are in RTC format,
+big-endian. These are stored in UT (GMT).
+
+For enum's: if given in hex then they are bit significant, i.e. only
+one bit is on for each enum.
+*/
+
+#ifndef _NVRAM_
+#define _NVRAM_
+
+#define NVSIZE 4096 /* size of NVRAM */
+#define OSAREASIZE 512 /* size of OSArea space */
+#define CONFSIZE 1024 /* guess at size of Configuration space */
+
+typedef struct _SECURITY {
+ unsigned long BootErrCnt; /* Count of boot password errors */
+ unsigned long ConfigErrCnt; /* Count of config password errors */
+ unsigned long BootErrorDT[2]; /* Date&Time from RTC of last error in pw */
+ unsigned long ConfigErrorDT[2]; /* Date&Time from RTC of last error in pw */
+ unsigned long BootCorrectDT[2]; /* Date&Time from RTC of last correct pw */
+ unsigned long ConfigCorrectDT[2]; /* Date&Time from RTC of last correct pw */
+ unsigned long BootSetDT[2]; /* Date&Time from RTC of last set of pw */
+ unsigned long ConfigSetDT[2]; /* Date&Time from RTC of last set of pw */
+ unsigned char Serial[16]; /* Box serial number */
+ } SECURITY;
+
+typedef enum _OS_ID {
+ Unknown = 0,
+ Firmware = 1,
+ AIX = 2,
+ NT = 3,
+ WPOS2 = 4,
+ WPAIX = 5,
+ Taligent = 6,
+ Solaris = 7,
+ Netware = 8,
+ USL = 9,
+ Low_End_Client = 10,
+ SCO = 11
+ } OS_ID;
+
+typedef struct _ERROR_LOG {
+ unsigned char ErrorLogEntry[40]; /* To be architected */
+ } ERROR_LOG;
+
+/*---Revision 1: Change the following struct:---*/
+typedef struct _RESUME_BLOCK {
+ /* Hibernation Resume Device will be an
+ environment variable */
+ unsigned long CheckSum; /* Checksum of RESUME_BLOCK */
+ volatile unsigned long BootStatus;
+
+ void * ResumeAddr; /* For Suspend Resume */
+ void * SaveAreaAddr; /* For Suspend Resume */
+ unsigned long SaveAreaLength; /* For Suspend Resume */
+
+ unsigned long HibResumeImageRBA; /* RBA (512B blocks) of compressed OS
+ memory image to be loaded by FW
+ on Resume from hibernation */
+ unsigned long HibResumeImageRBACount; /* Size of image in 512B blocks*/
+ unsigned long Reserved;
+ } RESUME_BLOCK;
+
+typedef enum _OSAREA_USAGE {
+ Empty = 0,
+ Used = 1
+ } OSAREA_USAGE;
+
+typedef enum _PM_MODE {
+ Suspend = 0x80, /* Part of state is in memory */
+ Hibernate = 0x40, /* Nothing in memory - state saved elsewhere */
+/* Revision 1: Normal added (actually was already here) */
+ Normal = 0x00 /* No power management in effect */
+ } PMMode;
+
+typedef struct _HEADER {
+ unsigned short Size; /* NVRAM size in K(1024) */
+ unsigned char Version; /* Structure map different */
+ unsigned char Revision; /* Structure map the same -
+ may be new values in old fields
+ in other words old code still works */
+ unsigned short Crc1; /* check sum from beginning of nvram to OSArea */
+ unsigned short Crc2; /* check sum of config */
+ unsigned char LastOS; /* OS_ID */
+ unsigned char Endian; /* B if big endian, L if little endian */
+ unsigned char OSAreaUsage; /* OSAREA_USAGE */
+ unsigned char PMMode; /* Shutdown mode */
+ RESUME_BLOCK ResumeBlock;
+ SECURITY Security;
+ ERROR_LOG ErrorLog[2];
+
+/* Global Environment information */
+ void * GEAddress;
+ unsigned long GELength;
+ /* Date&Time from RTC of last change to Global Environment */
+ unsigned long GELastWriteDT[2];
+
+/* Configuration information */
+ void * ConfigAddress;
+ unsigned long ConfigLength;
+ /* Date&Time from RTC of last change to Configuration */
+ unsigned long ConfigLastWriteDT[2];
+ unsigned long ConfigCount; /* Count of entries in Configuration */
+
+/* OS dependent temp area */
+ void * OSAreaAddress;
+ unsigned long OSAreaLength;
+ /* Date&Time from RTC of last change to OSAreaArea */
+ unsigned long OSAreaLastWriteDT[2];
+
+/* Revision 1: add this mask - function tbd */
+ /*unsigned short OSIRQMask; OS to FW IRQ Mask - "I've used this one" */
+ } HEADER;
+
+
+/* Here is the whole map of the NVRAM */
+typedef struct _NVRAM_MAP {
+ HEADER Header;
+ unsigned char GEArea[NVSIZE-CONFSIZE-OSAREASIZE-sizeof(HEADER)];
+ unsigned char OSArea[OSAREASIZE];
+ unsigned char ConfigArea[CONFSIZE];
+ } NVRAM_MAP;
+
+#endif /* ndef _NVRAM_ */
diff --git a/private/ntos/nthals/haleagle/ppc/pxbeep.c b/private/ntos/nthals/haleagle/ppc/pxbeep.c
new file mode 100644
index 000000000..2ac4b543c
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxbeep.c
@@ -0,0 +1,134 @@
+/*++
+
+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:
+
+--*/
+
+#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/haleagle/ppc/pxbusdat.c b/private/ntos/nthals/haleagle/ppc/pxbusdat.c
new file mode 100644
index 000000000..ef7f3462b
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxbusdat.c
@@ -0,0 +1,210 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxbusdat.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.
+
+Author:
+
+ Ken Reneris (kenr) July-28-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+
+--*/
+
+#include "halp.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,
+ ConfigurationSpaceUndefined,
+ 0, // Internal BusNumber 0
+ InterfaceTypeUndefined, // no parent bus
+ 0,
+ 0 // no bus specfic data
+ );
+
+ 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;
+
+
+ //
+ // Create bus handler - new style
+ //
+
+ HaliRegisterBusHandler (
+ InterfaceType,
+ BusDataType,
+ BusNumber,
+ ParentBusInterfaceType,
+ ParentBusNumber,
+ BusSpecificData,
+ NULL,
+ &Bus
+ );
+
+ 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/haleagle/ppc/pxcache.s b/private/ntos/nthals/haleagle/ppc/pxcache.s
new file mode 100644
index 000000000..a8c393646
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxcache.s
@@ -0,0 +1,208 @@
+//++
+//
+// 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:
+//
+// 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.
+// 07-Oct-94 saj Check for length=0 in Range functions
+//--
+
+#include "kxppc.h"
+#include "halppc.h"
+
+ .extern HalpIoControlBase
+
+// NOTE: 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.
+
+ .set HID0_ICFI, 0x0800 // I-Cache Flash Invalidate
+ .set HID0, 1008 // SPR # for HID0
+ .set BLOCK_SIZE, 32
+ .set BLOCK_LOG2, 5 // Should be == log2(BLOCK_SIZE)
+ .set BASE, 0x80000000 // base addr of valid cacheable region
+
+//++
+//
+// Routine Description:
+//
+// The D-Cache is flushed by loading 1 byte per cache line from a
+// valid address range, then flushing that address range.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcache)
+
+ mfsprg r.5, 1 // Get PCR->FirstLevelDcacheSize
+ lwz r.4, PcFirstLevelDcacheSize(r.5)
+
+ LWI (r.3, BASE) // Get a valid virtual address
+ srwi r.4, r.4, BLOCK_LOG2 // Convert to # cache lines
+//
+// Load r.4 cache lines starting from virtual address in r.3
+//
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.12)
+ sync // ensure ALL previous stores completed
+ subi r.6, r.3, BLOCK_SIZE // bias addr for pre-index
+FillLoop:
+ lbzu r.0, BLOCK_SIZE(r.6) // Read memory to force cache fill
+ bdnz FillLoop // into cache
+ ENABLE_INTERRUPTS(r.10)
+
+ mtctr r.4
+FlushRange:
+ dcbf r.0, r.3 // flush block
+ addi r.3, r.3, BLOCK_SIZE // bump address
+ bdnz FlushRange
+
+ LEAF_EXIT(HalSweepDcache)
+
+
+
+
+
+//++
+//
+// Routine Description:
+//
+// The I-Cache is flushed by toggling the Icache flash invalidate bit
+// in HID0. Invalidation is all that is necessary. Flushing to main
+// memory is not needed since the Icache can never be dirty.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcache)
+
+ LWI (r.3, BASE)
+
+FlashInvalidateIcache:
+ mfspr r.3, HID0
+ ori r.4, r.3, HID0_ICFI // Cache Flash Invalidate
+ isync
+ mtspr HID0, r.4 // Flash invalidate I-Cache
+ mtspr HID0, r.3 // re-enable (not needed on 604)
+
+ LEAF_EXIT(HalSweepIcache)
+
+//
+// Routine Description:
+//
+// The D-Cache is flushed by issuing a data cache block flush (DCBF)
+// instruction for each data block in the range.
+//
+// Arguments:
+//
+// r.3 - Starting address
+// r.4 - Length
+//
+// Return Value:
+//
+// None.
+//
+//
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+ andi. r.5, r.3, BLOCK_SIZE-1 // Get block offset of Start Addr
+ or. r.4, r.4, r.4 // Check for Length == 0
+ addi r.4, r.4, BLOCK_SIZE-1 // bump Length by BLOCK_SIZE-1
+ add r.4, r.4, r.5
+ srwi r.4, r.4, BLOCK_LOG2 // Compute # of cache blocks to flush
+ mtctr r.4
+ bne+ FlushRange // Branch if Length != 0
+
+ LEAF_EXIT(HalSweepDcacheRange)
+
+
+
+//
+// Routine Description:
+//
+// The I-Cache is flushed by issuing a Instruction Cache Block
+// Invalidate (ICBI) instruction for each data block in the range.
+// If the range is large, the entire Icache can be invalidated by
+// branching to FlashInvalidateIcache.
+//
+// Arguments:
+//
+// r.3 - Starting address
+// r.4 - Length
+//
+// Return Value:
+//
+// None.
+//
+//
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+ andi. r.5, r.3, BLOCK_SIZE-1 // Get block offset of Start Addr
+ or. r.4, r.4, r.4 // Check for Length == 0
+ addi r.4, r.4, BLOCK_SIZE-1 // bump Length by BLOCK_SIZE-1
+ add r.4, r.4, r.5
+ srwi r.4, r.4, BLOCK_LOG2 // Compute # of cache blocks to flush
+ beqlr- // return if Length == 0
+ mtctr r.4
+
+#if 0
+//
+// Possible speedup: If Length is fairly large (e.g. greater than 1/2
+// of the cache size), we will flash invalidate the entire cache, else
+// only sweep the desired range.
+//
+ li r.5, 16384/BLOCK_SIZE // # Icache lines on 604
+ cmpwi r.6, 3 // possible values are 3 or 4
+ bgt Threshold // Branch if 604
+ li r.5, 8192/BLOCK_SIZE // # Icache lines on 603
+Threshold:
+ srwi r.5, r.5, 1 // r.5 = IcacheLines/2
+ cmpl 0,0, r.4, r.5
+ bgt FlashInvalidateIcache
+#endif
+
+InvalidateIcache:
+ icbi 0, r.3 // invalidate block in I-cache
+ addi r.3, r.3, BLOCK_SIZE // bump address by BLOCK_SIZE
+ bdnz InvalidateIcache
+
+ LEAF_EXIT(HalSweepIcacheRange)
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxcalstl.c b/private/ntos/nthals/haleagle/ppc/pxcalstl.c
new file mode 100644
index 000000000..bc8044575
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxcalstl.c
@@ -0,0 +1,184 @@
+/*++
+
+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 "halp.h"
+#include "pxsystyp.h"
+
+//
+// KeQueryPerformanceCounter & KeStallExecutionProcessor are called
+// before Phase 0 initialization, so initialize it to a reasonable value.
+//
+ULONG HalpPerformanceFrequency = 80000000/16;
+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, HalpCalibrateStall)
+
+#endif
+
+
+
+ULONG
+HalpCalibrateTBPStack(
+ VOID
+ );
+
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{ int i;
+ ULARGE_INTEGER BigNumber;
+ ULONG Variance;
+ ULONG BusSpeed;
+ static ULONG BusSpeeds [] = {
+ 25000000,
+ 33333333,
+ 40000000,
+ 41875000,
+ 50000000,
+ 55833333,
+ 60000000,
+ 66000000,
+ 66666666,
+ 67000000,
+ 75000000,
+ 80000000,
+ 83333333,
+ 83750000,
+ 90000000,
+ 99000000,
+ 100000000,
+ 111666666,
+ 120000000,
+ 132000000,
+ 133333332,
+ 134000000,
+ 150000000,
+ 160000000,
+ 166666666,
+ 167500000
+ };
+
+
+
+ //
+ // Set initial scale factor
+ //
+
+ PCR->StallScaleFactor = 1;
+
+ //
+ // Compute the clock frequency of the Time Base & Decrementer
+ //
+ // It's possible for reads from the CMOS RTC to return odd results.
+ // For this reason, We can use a do-while loop, to ensure the calibration
+ // function is called at least once and is returning a reasonable value.
+ //
+
+ do {
+ switch( HalpSystemType ) {
+
+ case MOTOROLA_POWERSTACK:
+ HalpPerformanceFrequency = HalpCalibrateTBPStack();
+ break;
+
+ default:
+ case MOTOROLA_BIG_BEND:
+ HalpPerformanceFrequency = HalpCalibrateTB();
+ break;
+ }
+ } while( HalpPerformanceFrequency < 1000000 );
+
+ //
+ // CPU bus runs at 4 times the DECREMENTER frequency
+ //
+ BusSpeed = HalpPerformanceFrequency * 4;
+
+ //
+ // Choose the bus speed which is closest to calculated value.
+ // If the bus speed is not "close enough", then it may be
+ // a new speed which we don't know about. For this case
+ // we will leave the Performance Frequency alone.
+ //
+ for (i=0; i< (sizeof(BusSpeeds)/sizeof(ULONG)); i++) {
+ //
+ // We are going to allow for a 0.1% variation
+ // in calibrated frequency of the system bus clock.
+ // Calculate the variance as 1/2048 the frequency.
+ //
+ Variance = BusSpeeds[i] >> 11;
+ if ((BusSpeeds[i] - Variance < BusSpeed) &&
+ (BusSpeeds[i] + Variance > BusSpeed)) {
+ HalpPerformanceFrequency = BusSpeeds[i] / 4;
+ break;
+ }
+ }
+
+ //
+ // Initialize the system clock variables
+ //
+ HalpClockCount = (HalpPerformanceFrequency * (MAXIMUM_INCREMENT/10000)) / 1000;
+ HalpFullTickClockCount = HalpClockCount;
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxcirrus.h b/private/ntos/nthals/haleagle/ppc/pxcirrus.h
new file mode 100644
index 000000000..5ec9916ba
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxcirrus.h
@@ -0,0 +1,238 @@
+/*
+ * 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[] =
+{
+ 0x02,0x0f, // Enable Writing Pixel Extension
+ 0x06,0x12, // Unlock All Extensions
+ 0x07,0x00, // Extended Sequencer Mode (From Meeting)
+ 0x08,0x40, // EEPROM control register
+
+//
+// The Cirrus book says that all of the scratch pad registers
+// are "reserved for the Cirrus Logic BIOS" so it would be proper to
+// leave all of them alone.
+//
+
+// 0x09,0x68, // Scratch Pad 0 register
+// 0x0a,0x32, // Scratch Pad 1 register
+ 0x0b,0x4a, // VCLK 0 Numerator Register
+ 0x0c,0x5b, // VCLK 1 Numerator Register
+ 0x0d,0x42, // VCLK 2 Numerator Register
+ 0x0e,0x6e, // VCLK 3 Numerator Register
+ 0x0f,0x1d, // DRAM control
+ 0x10,0x00, // Graphics Cursor X Position
+ 0x11,0x00, // Graphics Cursor Y Position
+ 0x12,0x00, // Graphics Cursor Attributes
+ 0x13,0x00, // Graphics Pattern Address Offset Register
+// 0x14,0x00, // Scratch Pad Register 2
+// 0x15,0x02, // Scratch Pad Register 3
+ 0x16,0x71, // Performance Tuning
+ 0x17,0x31, // Configuration Readback and Extended Control
+ 0x18,0x00, // Signature Generator Control
+ 0x19,0x01, // Signature Register Result Low-Byte
+ 0x1a,0x00, // Signature Generator Result High-Byte
+ 0x1b,0x2b, // VCLK Denominator and Post-Scalar Value
+ 0x1c,0x2f,
+ 0x1d,0x1f,
+ 0x1e,0x2a,
+ 0x1f,0x1c, // MCLK Select Register
+ 0xff // End of list.
+};
+
+//
+// Extended CRTC Registers
+//
+
+static unsigned char ecrtc3[] =
+{
+ 0x19,0x00, // CR19: Inerlace End
+ 0x1a,0x00, // CR1a: Miscellaneous
+ 0x1b,0x00, // CR1b: Extended Display Controlls
+ 0x1d,0x00, // Overlay Extended Control
+ 0xff // End of list.
+};
+
+//
+// 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/haleagle/ppc/pxclksup.s b/private/ntos/nthals/haleagle/ppc/pxclksup.s
new file mode 100644
index 000000000..140c8fbee
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxclksup.s
@@ -0,0 +1,145 @@
+/***********************************************************************
+
+ 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.
+ 11-Sep-1995 Steve Johns
+ Removed 601 specific code
+ Removed 603 workaround, since we don't support < 603 v3.2
+***********************************************************************/
+
+#include <halppc.h>
+#define ERRATA603 FALSE
+
+
+ LEAF_ENTRY(HalpSetDecrementer)
+
+ mtdec r.3 // Set the DECREMENTER
+
+ LEAF_EXIT(HalpSetDecrementer)
+
+
+
+ LEAF_ENTRY(HalpUpdateDecrementer)
+
+//
+// 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
+
+
+/***********************************************************************
+ 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
+ .set TimerHi, r.7
+ .set Temp, r.8
+
+
+ LEAF_ENTRY(KeQueryPerformanceCounter)
+
+
+ cmpli 0,0,Freq,0 // Was PerformanceFrequency passed ?
+ beq ReadTB
+
+ 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)
+
+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
+
+ stw TimerLo,0(RetPtr)
+ stw TimerHi,4(RetPtr)
+
+ LEAF_EXIT(KeQueryPerformanceCounter)
+
+
+
+ .set TB, 284
+ .set TBU, 285
+
+ LEAF_ENTRY(HalpZeroPerformanceCounter)
+
+ li r.3, 0
+ mtspr TB,r.3
+ mtspr TBU,r.3
+
+ LEAF_EXIT(HalpZeroPerformanceCounter)
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxclock.c b/private/ntos/nthals/haleagle/ppc/pxclock.c
new file mode 100644
index 000000000..a621530d3
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxclock.c
@@ -0,0 +1,243 @@
+
+/*****************************************************************************
+
+ 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:
+// 09-Jun-95 Steve Johns
+// - Removed 1 level of buffering of time increment to match
+// buffering of DECREMENTER counts.
+******************************************************************************/
+
+#include "halp.h"
+
+extern ULONG HalpPerformanceFrequency;
+
+BOOLEAN
+KdPollBreakIn (
+ VOID
+ );
+
+ULONG HalpClockCount;
+ULONG HalpFullTickClockCount;
+ULONG HalpUpdateDecrementer();
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+BOOLEAN
+HalpHandleDecrementerInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ Clock interrupt handler for processor 0.
+
+Arguments:
+
+ Interrupt
+
+ ServiceContext
+
+ TrapFrame
+
+Return Value:
+
+ TRUE
+
+--*/
+{
+ KIRQL OldIrql;
+
+ //
+ // Raise irql via updating the PCR
+ //
+
+ OldIrql = PCR->CurrentIrql;
+
+ PCR->CurrentIrql = CLOCK2_LEVEL;
+
+ //
+ // Reset DECREMENTER, accounting for interrupt latency.
+ //
+
+ HalpUpdateDecrementer(HalpClockCount);
+
+ //
+ // Call the kernel to update system time
+ //
+
+ KeUpdateSystemTime(TrapFrame,HalpCurrentTimeIncrement);
+
+ //
+ // If tick rate has changed, then tell the kernel about it
+ //
+
+ HalpCurrentTimeIncrement = HalpNewTimeIncrement;
+
+ //
+ // Lower Irql to original value and enable interrupts
+ //
+
+ PCR->CurrentIrql = OldIrql;
+
+ HalpEnableInterrupts();
+
+ if ( KdDebuggerEnabled && KdPollBreakIn() ) {
+ DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
+ }
+
+ return (TRUE);
+}
+
+#if !defined(NT_UP)
+VOID
+HalpHandleDecrementerInterrupt1(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ Clock interrupt handler for processors other than 0.
+
+Arguments:
+
+ Interrupt
+
+ ServiceContext
+
+ TrapFrame
+
+Return Value:
+
+ TRUE
+
+--*/
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise irql via updating the PCR
+ //
+
+ OldIrql = PCR->CurrentIrql;
+
+ PCR->CurrentIrql = CLOCK2_LEVEL;
+
+ //
+ // Reset DECREMENTER, accounting for interrupt latency.
+ //
+
+ HalpUpdateDecrementer(HalpFullTickClockCount);
+
+ //
+ // Call the kernel to update run time for this thread and process.
+ //
+
+ KeUpdateRunTime(TrapFrame);
+
+ //
+ // Lower Irql to original value
+ //
+
+ PCR->CurrentIrql = OldIrql;
+
+ return;
+}
+#endif
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+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.
+
+--*/
+
+{
+
+ 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.
+ //
+
+ HalpClockCount = (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.
+ //
+
+ HalpNewTimeIncrement = DesiredIncrement/MINIMUM_INCREMENT * MINIMUM_INCREMENT;
+
+ KeLowerIrql(OldIrql);
+ return HalpNewTimeIncrement;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxdat.c b/private/ntos/nthals/haleagle/ppc/pxdat.c
new file mode 100644
index 000000000..cb05bec92
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxdat.c
@@ -0,0 +1,110 @@
+/*++
+
+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, 0x20, // SIO DMA
+ 0x400, 0x40, // SIO DMA
+ 0x480, 0x10, // SIO DMA
+ 0x4C0, 0x10, // SIO DMA
+ 0x4D6, 0x2, // SIO DMA
+
+ 0x020, 0x2, // PIC
+ 0x0A0, 0x2, // Cascaded PIC
+ 0x4D0, 0x2, // PIC edge/level
+
+ 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
+
+// 0x800, 0x1, // Big Bend NVRAM data port
+ 0x81C, 0x1, // Eagle external configuration register
+ 0x850, 0x1, // Eagle external configuration register
+// 0xC00, 0x2, // Big Bend NVRAM index ports
+ 0xCF8, 0x8, // PCI CONFIG_ADDRESS & CONFIG_DATA
+
+ 0,0
+ }
+};
+
+
+//
+// From usage.c
+//
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// Misc hal stuff in the registry
+//
+
+WCHAR rgzHalClassName[] = L"Hardware Abstraction Layer";
+
+
+//
+// From ixpcibus.c
+//
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+
+
+//
+// From ixpcibrd.c
+//
+
+WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources";
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg()
+#endif
+
+//
+// IDT vector usage info
+//
+
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
diff --git a/private/ntos/nthals/haleagle/ppc/pxdisp.c b/private/ntos/nthals/haleagle/ppc/pxdisp.c
new file mode 100644
index 000000000..d86393105
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxdisp.c
@@ -0,0 +1,2211 @@
+/*++
+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 Eagle-Based PowerPC system using an S3, Weitek P9000, Cirrus
+ CL-GD5434 video adapter, or most any video card with an option ROM.
+
+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
+
+--*/
+
+#include "halp.h"
+#include "pxs3.h"
+#include "string.h"
+#include "pxcirrus.h"
+#include "pxpcisup.h"
+
+//=============================================================================
+//
+// 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"
+
+#if defined(_PPC_)
+
+# define MEMORY_PHYSICAL_BASE VIDEO_MEMORY_BASE
+# define CONTROL_PHYSICAL_BASE VIDEO_CONTROL_BASE
+
+#endif
+
+//PHYSICAL ADDRESS of WEITEK P9000 video ram
+#define P9_VIDEO_MEMORY_BASE 0xC1200000
+
+//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
+
+
+#define ROWS 25
+#define COLS 80
+#define TAB_SIZE 4
+#define ONE_LINE (COLS*2)
+#define TWENTY_FOUR_LINES (ROWS-1)* ONE_LINE
+#define TWENTY_FIVE_LINES ROWS * ONE_LINE
+#define TEXT_ATTR 0x1F
+
+//
+// Define forward referenced procedure prototypes.
+//
+VOID HalpDisplayINT10Setup (VOID);
+
+VOID HalpOutputCharacterINT10 (
+ IN UCHAR Character );
+
+VOID HalpScrollINT10 (
+ IN UCHAR line
+ );
+
+VOID HalpDisplayCharacterVGA (
+ IN UCHAR Character );
+
+
+VOID
+HalpDisplayCharacterS3 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterS3 (
+ IN UCHAR AsciiChar
+ );
+
+VOID
+HalpDisplayPpcS3Setup (
+ VOID
+ );
+
+VOID
+HalpScrollS3(
+ IN UCHAR line
+ );
+
+VOID
+HalpDisplayPpcP9Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterP9 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterP91 (
+ IN UCHAR Character
+ );
+
+
+VOID
+WaitForVSync (
+ VOID
+ );
+
+VOID
+ScreenOn (
+ VOID
+ );
+
+VOID
+ScreenOff (
+ VOID
+ );
+
+VOID
+Scroll_Screen (
+ IN UCHAR line
+ );
+
+VOID
+HalpDisplayPpcP9Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterP9 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterP9(
+ IN PUCHAR Glyph
+ );
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterP91 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterP91(
+ IN PUCHAR Glyph
+ );
+
+
+
+
+VOID
+HalpDisplayCharacterCirrus (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterCirrus (
+ IN UCHAR AsciiChar
+ );
+
+VOID
+HalpDisplayPpcCirrusSetup (
+ VOID
+ );
+
+VOID HalpScrollCirrus (
+ IN UCHAR line
+ );
+
+
+BOOLEAN
+HalpInitializeX86DisplayAdapter(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+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();
+
+
+//
+//
+//
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+typedef
+VOID
+(*PHALP_DISPLAY_CHARACTER) (
+ UCHAR
+ );
+typedef
+VOID
+(*PHALP_SCROLL_SCREEN) (
+ UCHAR
+ );
+
+
+typedef
+VOID
+(*PHALP_OUTPUT_CHARACTER) (
+ UCHAR
+ );
+
+
+//
+// Define static data.
+//
+BOOLEAN HalpDisplayOwnedByHal;
+PHAL_RESET_DISPLAY_PARAMETERS HalpResetDisplayParameters = NULL;
+
+volatile PUCHAR HalpVideoMemoryBase = (PUCHAR)0;
+
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL;
+PHALP_OUTPUT_CHARACTER HalpOutputCharacter = NULL;
+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;
+
+
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+
+POEM_FONT_FILE_HEADER HalpFontHeader;
+
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey;
+ //LONG SlotNumber = 0;
+ //LONG ChipID = -1;
+
+
+
+
+
+ //
+ // 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);
+
+ while (ConfigurationEntry != NULL) {
+
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpOutputCharacter = HalpOutputCharacterS3;
+ HalpScrollScreen = HalpScrollS3;
+
+
+
+ if (ConfigurationEntry->ComponentEntry.Identifier[0] == 'C' &&
+ ConfigurationEntry->ComponentEntry.Identifier[1] == 'L' &&
+ ConfigurationEntry->ComponentEntry.Identifier[2] == '5' &&
+ ConfigurationEntry->ComponentEntry.Identifier[3] == '4') {
+ HalpDisplayControllerSetup = HalpDisplayPpcCirrusSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterCirrus;
+ HalpScrollScreen = HalpScrollCirrus;
+ break;
+ }
+ if (HalpInitializeX86DisplayAdapter(LoaderBlock)) {
+ HalpDisplayControllerSetup = HalpDisplayINT10Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterVGA;
+ HalpOutputCharacter = HalpOutputCharacterINT10;
+ HalpScrollScreen = HalpScrollINT10;
+ break;
+ }
+
+ if (ConfigurationEntry->ComponentEntry.Identifier[0] == 'S' &&
+ ConfigurationEntry->ComponentEntry.Identifier[1] == '3') {
+ HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
+ break;
+ }
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"P9000")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcP9Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterP9;
+ break;
+ }
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"P9100")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcP91Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterP91;
+ break;
+ }
+
+ break;
+
+ } // end While
+
+
+
+ //
+ // Initialize the display controller.
+ //
+
+ if (HalpDisplayControllerSetup != NULL) {
+ HalpDisplayControllerSetup();
+ }
+
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ 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:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Record the routine to reset display to text mode.
+ //
+ HalpResetDisplayParameters = ResetDisplayParameters;
+
+ //
+ // Set HAL ownership of the display to FALSE.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+
+VOID
+HalpDisplayPpcS3Setup (
+ VOID
+ )
+/*++
+
+Routine Description:
+ This routine initializes the S3 display controller chip.
+Arguments:
+ None.
+Return Value:
+ None.
+
+--*/
+{
+//
+// 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) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(S3_VIDEO_MEMORY_BASE,
+ 0x400000); // 4 MB
+ }
+
+ // Enable Video Subsystem
+ // According to chapter 5.4.2 regular VGA setup sequence
+
+ //=========================================================================
+ //
+ // 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);
+
+ //=========================================================================
+
+ // Subsystem Enable = 0x10;
+ 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
+ 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
+ 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 );
+#ifdef SAM_256
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x40 );
+#else
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+#endif
+
+ 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)
+ 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
+ //
+ 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;
+ HalpDisplayWidth = COLS;
+ HalpDisplayText = ROWS;
+ HalpScrollLine = ONE_LINE;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+ HalpDisplayOwnedByHal = TRUE;
+
+ return;
+} /* end of HalpDisplayPpcS3Setup() */
+
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ 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);
+
+ //
+ // 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 (HalpDisplayOwnedByHal == FALSE) {
+
+ //
+ // The display has been put in graphics mode, and we need to
+ // reset it to text mode before we can display any text on it.
+ //
+
+ if (HalpResetDisplayParameters) {
+ HalpDisplayOwnedByHal = HalpResetDisplayParameters(COLS, ROWS);
+ HalpScreenStart = 0; // used by Cirrus scroll
+ HalpColumn = 0;
+ HalpRow = 0;
+ }
+
+ if (!HalpDisplayOwnedByHal && HalpDisplayControllerSetup != NULL) {
+ HalpDisplayControllerSetup();
+ }
+
+ }
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+
+
+ //
+ // Lower IRQL to its previous level.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ return;
+}
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth;
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+
+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);
+ }
+ }
+
+ //=========================================================================
+ //
+ // 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 ); // scroll the screen up
+ else
+ ++HalpRow;
+ }
+ }
+
+ //=========================================================================
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpOutputCharacter(' ');
+ 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);
+ }
+ }
+ HalpOutputCharacter(Character);
+ } else /* skip the nonprintable character */
+ ;
+
+ return;
+
+} /* end of HalpDisplayCharacterVGA() */
+
+
+
+
+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 < COLS) {
+ 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 ++) {
+ //=======================================================================
+ //
+ // 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, ' ' );
+ }
+ }
+}
+
+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 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;
+}
+
+VOID
+HalpDisplayPpcP9Setup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the Weitek P9000 display contoller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PULONG buffer;
+ ULONG limit, index;
+ // For now I'll leave the P9000 in the same state that the firmware
+ // left it in. This should be 640x480.
+
+ HalpHorizontalResolution = 640;
+ HalpVerticalResolution = 480;
+
+ if (HalpVideoMemoryBase == NULL) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(P9_VIDEO_MEMORY_BASE,
+ 0x400000); // 4 MB
+ }
+
+ //
+ // 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)HalpVideoMemoryBase;
+ limit = (HalpHorizontalResolution *
+ HalpVerticalResolution) / sizeof(ULONG);
+
+ 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;
+
+} //end of HalpDisplayPpcP9Setup
+
+VOID
+HalpDisplayCharacterP9 (
+ 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') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ //RtlMoveMemory((PVOID)P9_VIDEO_MEMORY_BASE,
+ // (PVOID)(P9_VIDEO_MEMORY_BASE + HalpScrollLineP9),
+ // HalpScrollLengthP9);
+
+ // 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 == '\r') {
+ HalpColumn = 0;
+
+ } else {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterP9((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalpOutputCharacterP9(
+ 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) {
+ HalpDisplayCharacterP9('\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));
+ }
+ // Move the font bits around so the characters look right.
+ tmp = (FontValue >> 3) & 0x11111111; //bits 7 and 3 to the right 3
+ tmp |= (FontValue >> 1) & 0x22222222; //bits 6 and 2 to the right 1
+ tmp |= (FontValue << 1) & 0x44444444; //bits 5 and 1 to the left 1
+ tmp |= (FontValue << 3) & 0x88888888; //bits 4 and 0 to the left 3
+ FontValue = tmp;
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ if (FontValue >> 31 != 0)
+ *Destination = 0xFF; //Make this pixel white
+
+ Destination++;
+ //*Destination++ = (FontValue >> 31) ^ 1;
+ FontValue <<= 1;
+ }
+
+ Destination +=
+ (HalpHorizontalResolution - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+ return;
+}
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the Weitek P9100 display contoller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PULONG buffer;
+ ULONG limit, index;
+ // 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 (HalpVideoMemoryBase == NULL) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(P91_VIDEO_MEMORY_BASE,
+ 0x400000); // 4 MB
+ }
+
+ //
+ // 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)HalpVideoMemoryBase;
+ limit = (HalpHorizontalResolution *
+ HalpVerticalResolution) / sizeof(ULONG);
+
+ 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;
+
+} //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') {
+ 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 = 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 == '\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)(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
+
+ Destination++;
+ //*Destination++ = (FontValue >> 31) ^ 1;
+ FontValue <<= 1;
+ }
+
+ Destination +=
+ (HalpHorizontalResolution - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+ return;
+}
+
+
+//
+// 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(' ');
+ 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);
+ }
+}
+
+
+VOID
+HalpDisplayPpcCirrusSetup (
+ VOID
+ )
+{
+ int i;
+
+
+
+ if(HalpVideoMemoryBase == NULL) {
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(PCI_MEMORY_BASE,
+ 0x400000); // 4 MB
+ }
+
+//
+// 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);
+
+//
+// Reset Hidden color register
+//
+
+ inp(0x3c6);
+ inp(0x3c6);
+ inp(0x3c6);
+ inp(0x3c6);
+ outp(0x3c6,0x00);
+
+//
+// Load 8x16 font
+//
+
+ load8x16();
+
+//
+// Load color palette
+//
+
+ load_ramdac();
+
+ outportb(0x3c6,0xff);
+
+//
+// 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;
+}
+
+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
+ }
+}
+
+
+
+
+
+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 = ((ROWS-1) << 8) + COLS - 1; // DH,DL = lower right
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+}
+
+VOID HalpDisplayINT10Setup (VOID)
+{ ULONG Eax,Ebx,Ecx,Edx,Esi,Edi,Ebp;
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = COLS;
+ HalpDisplayText = ROWS;
+ HalpScrollLine = ONE_LINE;
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayOwnedByHal = TRUE;
+
+ //
+ // Reset the display to mode 3
+ //
+ Eax = 0x0003; // Function 0, Mode 3
+ Ebx = Ecx = Edx = Esi = Edi = Ebp = 0;
+ HalCallBios(0x10, &Eax,&Ebx,&Ecx,&Edx,&Esi,&Edi,&Ebp);
+
+ //
+ // 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);
+}
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxds1385.c b/private/ntos/nthals/haleagle/ppc/pxds1385.c
new file mode 100644
index 000000000..b1a48ae12
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxds1385.c
@@ -0,0 +1,386 @@
+/*++
+
+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 "halp.h"
+#include "pxds1585.h"
+#include "eisa.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+static UCHAR
+HalpReadRawClockRegister (
+ UCHAR Register
+ );
+
+static VOID
+HalpWriteRawClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+static UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+static VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClockDs (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+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.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL 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.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock 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;
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClockDs (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+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.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL 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.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteRawClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // 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);
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteRawClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+static UCHAR
+HalpReadRawClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+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.
+
+--*/
+
+{
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the SIO NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ //
+ // TEMPTEMP Disable NMI's for now because this is causing machines in the
+ // build lab to get NMI's during boot.
+ //
+
+
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR(&((PRTC_CONTROL)HalpIoControlBase)->RtcData);
+}
+
+static UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+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 BcdValue;
+
+
+ BcdValue = HalpReadRawClockRegister(Register);
+ return (BcdValue >> 4) * 10 + (BcdValue & 0x0f);
+}
+
+static VOID
+HalpWriteRawClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+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.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the SIO NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the SIO NMI is always enabled.
+ //
+
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PRTC_CONTROL)HalpIoControlBase)->RtcData, Value);
+ return;
+}
+
+static VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+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.
+
+--*/
+
+{
+ UCHAR BcdValue;
+
+ BcdValue = ((Value / 10) << 4) | (Value % 10);
+ HalpWriteRawClockRegister(Register, BcdValue);
+ return;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxds1585.h b/private/ntos/nthals/haleagle/ppc/pxds1585.h
new file mode 100644
index 000000000..cee3e7fd5
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxds1585.h
@@ -0,0 +1,106 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxds1585.h
+
+Abstract:
+
+ The module defines the structures, and defines for the DALLAS rtc chip.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+
+
+
+typedef struct _RTC_CONTROL {
+ UCHAR Reserved0[0x71];
+ UCHAR RtcData; // Offset 0x71
+} RTC_CONTROL, *PRTC_CONTROL;
+
+typedef struct _NVRAM_CONTROL {
+ UCHAR Reserved0[0x74];
+ UCHAR NvramIndexLo; // Offset 0x74
+ 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]
+
+//
+// Define Control Register A structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_A {
+ UCHAR RateSelect : 4;
+ UCHAR TimebaseDivisor : 3;
+ UCHAR UpdateInProgress : 1;
+} RTC_CONTROL_REGISTER_A, *PRTC_CONTROL_REGISTER_A;
+
+//
+// Define Control Register B structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_B {
+ UCHAR DayLightSavingsEnable : 1;
+ UCHAR HoursFormat : 1;
+ UCHAR DataMode : 1;
+ UCHAR SquareWaveEnable : 1;
+ UCHAR UpdateInterruptEnable : 1;
+ UCHAR AlarmInterruptEnable : 1;
+ UCHAR TimerInterruptEnable : 1;
+ UCHAR SetTime : 1;
+} RTC_CONTROL_REGISTER_B, *PRTC_CONTROL_REGISTER_B;
+
+//
+// Define Control Register C structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_C {
+ UCHAR Fill : 4;
+ UCHAR UpdateInterruptFlag : 1;
+ UCHAR AlarmInterruptFlag : 1;
+ UCHAR TimeInterruptFlag : 1;
+ UCHAR InterruptRequest : 1;
+} RTC_CONTROL_REGISTER_C, *PRTC_CONTROL_REGISTER_C;
+
+//
+// Define Control Register D structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_D {
+ UCHAR Fill : 7;
+ UCHAR ValidTime : 1;
+} RTC_CONTROL_REGISTER_D, *PRTC_CONTROL_REGISTER_D;
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxenviro.c b/private/ntos/nthals/haleagle/ppc/pxenviro.c
new file mode 100644
index 000000000..3248fbbf1
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxenviro.c
@@ -0,0 +1,170 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ pxenviro.c
+
+Abstract:
+
+ This module implements the interface to the HAL get and set
+ environment variable routines for a Power PC system.
+
+
+Author:
+
+ Jim Wooldridge Ported to PowerPC
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "arccodes.h"
+
+#include "prepnvr.h"
+#include "fwstatus.h"
+#include "fwnvr.h"
+
+// This is initialized in pxsystyp during phase 0 init.
+NVR_SYSTEM_TYPE nvr_system_type = nvr_systype_unknown;
+
+KSPIN_LOCK NVRAM_Spinlock;
+
+
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+
+{
+
+KIRQL Irql;
+PUCHAR tmpbuffer;
+
+
+ //
+ // Check input parameters
+ //
+ if (Variable == NULL ||
+ *Variable == 0 ||
+ Length < 1 ||
+ Buffer == NULL)
+ return(ENOENT);
+
+ //
+ // Grab control of NVRAM
+ //
+
+ KeAcquireSpinLock(&NVRAM_Spinlock, &Irql);
+
+ (VOID)nvr_initialize_object(nvr_system_type);
+
+ if ((tmpbuffer = nvr_get_GE_variable(Variable)) == NULL) {
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+ return(ENOENT);
+ }
+
+ //
+ // Copy the environment variable's value to Buffer
+ //
+
+ do {
+ *Buffer = *tmpbuffer++;
+ if (*Buffer++ == 0) {
+
+ nvr_delete_object();
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+ return(ESUCCESS);
+ }
+ } while (--Length);
+
+ //
+ // Truncate the returned string. The buffer was too short.
+ //
+ *--Buffer = 0;
+
+ nvr_delete_object();
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+ return(ENOMEM);
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+
+{
+ ARC_STATUS ReturnValue;
+ KIRQL Irql;
+
+
+
+ if (Value == NULL) return(ENOENT);
+
+ KeAcquireSpinLock(&NVRAM_Spinlock, &Irql); // Grab control of NVRAM
+
+ (VOID)nvr_initialize_object(nvr_system_type);
+
+ ReturnValue = nvr_set_GE_variable(Variable,Value);
+
+ nvr_delete_object(); // free object created by nvr_init_object
+
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+
+ return(ReturnValue);
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxflshbf.s b/private/ntos/nthals/haleagle/ppc/pxflshbf.s
new file mode 100644
index 000000000..dd7244b39
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxflshbf.s
@@ -0,0 +1,186 @@
+// 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
+//
+//--
+
+#include "kxppc.h"
+ .extern HalpIoControlBase
+ .set ISA, r.7
+
+
+// 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)
+
+//
+// It is required that the results of all stores to memory and I/O registers,
+// performed in "critical sections" just prior to calling KeFlushWriteBuffer,
+// be seen by other processors and mechanisms before returning from this
+// routine (KeFlushWriteBuffer). All write-posting queues, both processor and
+// external hardware, must be flushed so that their data are seen by other
+// processors and controllers on both the PCI and ISA busses.
+//
+
+//
+// The Eagle will initiate flushing it's write posting queue on either
+// an EIEIO or a SYNC. However, an EIEIO is a NOP on a 603, so we use
+// a LOAD from ISA I/O space to get the same effect.
+//
+
+
+ eieio //
+ lwz r.4,[toc]HalpIoControlBase(r.toc)
+ lwz r.4,0(r.4)
+ lbz r.4, 0x21(r.4)
+
+//
+// Lastly, theFlush write buffers on the processor! To do this, we must use the
+// "sync" instruction. The EIEIO instruction does NOT provide the required
+// synchronization with external hardware and controllers.
+//
+
+ sync
+
+
+ LEAF_EXIT(KeFlushWriteBuffer)
+
+
+
+ LEAF_ENTRY(HalpPatch_KeFlushWriteBuffer)
+
+ mflr r.8 // Save LR
+ bl Here
+Here: mflr r.9
+ mtlr r.8 // Restore LR
+
+ addi r.3, r.9, ..HalpFlushWriteBuffer603-Here
+ addi r.4, r.9, ..HalpFlushWriteBuffer604-Here
+
+ mfpvr r.0 // Distinguish 603/603e from 604/604e
+ andis. r.0, r.0, 0x0002
+ beq PatchTOC
+ mr r.4, r.3
+PatchTOC:
+ lwz r.7, [toc]KeFlushWriteBuffer(r.toc)
+ stw r.4, 0(r.7)
+ dcbf r.0, r.7 // Flush it from the L1 cache
+
+ LEAF_EXIT(HalpPatch_KeFlushWriteBuffer)
+
+
+ LEAF_ENTRY(HalpFlushWriteBuffer603)
+ lwz r.4,[toc]HalpIoControlBase(r.toc)
+ lwz r.4,0(r.4)
+ lbz r.4, 0x21(r.4)
+ sync
+ LEAF_EXIT(HalpFlushWriteBuffer603)
+
+
+
+ LEAF_ENTRY(HalpFlushWriteBuffer604)
+ eieio // Initiate flushing the Eagle write-post buffers
+ sync // Wait for the flushing to complete
+ LEAF_EXIT(HalpFlushWriteBuffer604)
+
+
+
+//
+//++
+//
+// 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)
+
+
+//
+//++
+//
+// VOID
+// HalpSetSDR1(
+// ULONG HashedPageTableBase,
+// ULONG HashedPageTableSize
+// )
+//
+// HashedPageTableSize is unused because we ASSUME that the HPT is 64K
+//
+
+ LEAF_ENTRY(HalpSetSDR1)
+
+ mtsdr1 r.3
+
+ LEAF_EXIT(HalpSetSDR1)
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxflshio.c b/private/ntos/nthals/haleagle/ppc/pxflshio.c
new file mode 100644
index 000000000..e13615ec9
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxflshio.c
@@ -0,0 +1,128 @@
+
+/*++
+
+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.
+
+--*/
+
+{
+
+
+ //
+ // check for 601, it has a combined I and D cache that bus snoops
+ //
+ //
+
+ if ((HalpGetProcessorVersion() >> 16) != 1) {
+
+ //
+ // 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 entire data cache.
+ //
+ // WARNING: HalSweepDcache is NOT MP-coherent, so calling it like
+ // this makes this HAL UP-only!
+ //
+
+ if (((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ }
+ return;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxhalp.h b/private/ntos/nthals/haleagle/ppc/pxhalp.h
new file mode 100644
index 000000000..66bbf8e46
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxhalp.h
@@ -0,0 +1,253 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (C) 1991-1995 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;
+
+//
+// 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;
+} 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,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+ULONG
+HalpPhase0SetPciDataByOffset(
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+PVOID
+KePhase0MapIo(
+ IN ULONG MemoryBase,
+ IN ULONG MemorySize
+ );
+
+PVOID
+KePhase0DeleteIoMap(
+ IN ULONG MemoryBase,
+ IN ULONG MemorySize
+ );
+
+ULONG
+HalpCalibrateTB(
+ VOID
+ );
+
+VOID
+HalpZeroPerformanceCounter(
+ VOID
+ );
+
+VOID
+HalpResetIrqlAfterInterrupt(
+ KIRQL TargetIrql
+ );
+
+#endif // _PXHALP_
diff --git a/private/ntos/nthals/haleagle/ppc/pxhwsup.c b/private/ntos/nthals/haleagle/ppc/pxhwsup.c
new file mode 100644
index 000000000..dd0d1ea39
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxhwsup.c
@@ -0,0 +1,2199 @@
+/*++
+
+Copyright (C) 1990-1995 Microsoft Corporation
+
+Copyright (C) 1994,1995 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 <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
+ );
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+{
+
+ 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);
+
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ 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 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);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+{
+ 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;
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ 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
+
+--*/
+
+{
+
+
+ UNREFERENCED_PARAMETER( AdapterObject );
+ UNREFERENCED_PARAMETER( Length );
+ UNREFERENCED_PARAMETER( LogicalAddress );
+ UNREFERENCED_PARAMETER( CacheEnabled );
+
+ MmFreeContiguousMemory (VirtualAddress);
+
+ return;
+
+}
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ 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 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);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ 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 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;
+
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ 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
+
+--+*/
+{
+ 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 );
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+ 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;
+ }
+ }
+}
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ 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.
+ //
+
+ 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);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+ 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;
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+ KIRQL OldIrql;
+ int i;
+
+ //
+ // raise irql to machine check level
+ //
+
+ KeRaiseIrql(MACHINE_CHECK_LEVEL,&OldIrql);
+
+ //
+ // Let the world know what happened.
+ //
+ HalDisplayString("\n *** Machine Check Exception ***\n");
+
+ //
+ // check memory controller machine check sources
+ //
+
+ HalpHandleMemoryError();
+
+ //
+ // check Bus NMI sources
+ //
+
+ HalpHandleIoError();
+
+ //
+ // Bug check - after stalling to allow
+ // any information printed on the screen
+ // by the Memory and IO Handlers to be read.
+ //
+ for (i=0; i<12; i++) {
+ HalDisplayString(".");
+ KeStallExecutionProcessor(1000000);
+ }
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+ KeLowerIrql(OldIrql);
+
+ return(TRUE);
+}
+
+
+BOOLEAN
+HalpAllocateMapBuffer(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates the required map buffers.
+
+
+Arguments:
+
+
+Return Value:
+
+ TRUE - success
+ FALSE - failure
+
+--*/
+
+{
+
+ 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;
+}
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+{
+ 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);
+
+ }
+
+}
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ KIRQL Irql;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ 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.
+ //
+
+ 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;
+
+ 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) {
+
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ MapBufferPhysicalAddress = MmGetPhysicalAddress(
+ MapBufferVirtualAddress
+ ).LowPart;
+
+ }
+
+ //
+ // Initailize the map registers where memory has been allocated.
+ //
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; i < NumberOfPages; i++) {
+
+ //
+ // Make sure the previous entry is physically contiguous with the next
+ // entry and that a 64K physical boundary 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 boundary.
+ //
+
+ 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/haleagle/ppc/pxidle.c b/private/ntos/nthals/haleagle/ppc/pxidle.c
new file mode 100644
index 000000000..038902d85
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxidle.c
@@ -0,0 +1,65 @@
+/*++
+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 "halp.h"
+
+
+
+
+VOID
+HalProcessorIdle(
+ VOID
+ )
+
+/*++
+
+ Routine Description:
+
+ 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.
+
+
+--*/
+
+{
+ extern VOID HalpProcessorIdle(VOID);
+ HalpProcessorIdle();
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxinfo.c b/private/ntos/nthals/haleagle/ppc/pxinfo.c
new file mode 100644
index 000000000..0ec6698b9
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxinfo.c
@@ -0,0 +1,97 @@
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+
+Module Name:
+
+ pxinfo.c
+
+Abstract:
+
+Environment:
+
+ Kernel mode only.
+
+--*/
+
+
+#include "halp.h"
+
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+{
+ NTSTATUS Status;
+ PVOID InternalBuffer;
+ ULONG Length;
+ union {
+ HAL_POWER_INFORMATION PowerInf;
+ HAL_PROCESSOR_SPEED_INFORMATION ProcessorInf;
+ } U;
+
+ PAGED_CODE();
+
+ Status = STATUS_SUCCESS;
+ *ReturnedLength = 0;
+ Length = 0;
+
+ switch (InformationClass) {
+ case HalInstalledBusInformation:
+ Status = HalpQueryInstalledBusInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength
+ );
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ //
+ // If non-zero Length copy data to callers buffer
+ //
+
+ if (Length) {
+ if (BufferSize < Length) {
+ Length = BufferSize;
+ }
+
+ *ReturnedLength = Length;
+ RtlCopyMemory (Buffer, InternalBuffer, Length);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+{
+ PAGED_CODE();
+ return STATUS_INVALID_LEVEL;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxinithl.c b/private/ntos/nthals/haleagle/ppc/pxinithl.c
new file mode 100644
index 000000000..28233a420
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxinithl.c
@@ -0,0 +1,396 @@
+/*++
+
+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 HalpInitializeInterrupts - 8259 initialized in phase 1
+ Removed Cache error handler - 601 has no cache error interrupt
+ Removed call to HalpCreateDmaSturctures - it supports internal DMA
+
+--*/
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "pxsystyp.h"
+extern ADDRESS_USAGE HalpDefaultIoSpace;
+extern ULONG HalpPciMaxSlots;
+extern ULONG HalpPciConfigSize;
+
+ULONG
+HalpSizeL2Cache(
+ VOID
+ );
+
+VOID
+HalpSynchronizeExecution(
+ VOID
+ );
+
+VOID
+HalpCopyROMs(
+ VOID
+ );
+
+
+VOID HalpPatch_KeFlushWriteBuffer(VOID);
+
+
+//
+// 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)
+
+#endif
+
+PVOID HalpIoControlBase = (PVOID) 0;
+ULONG L2_Cache_Size;
+
+VOID
+HalpInitBusHandlers (
+ VOID
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+VOID
+HalpEnableEagleSettings(
+ VOID
+ );
+
+VOID
+HalpCheckHardwareRevisionLevels(
+ VOID
+ );
+
+VOID
+HalpDumpHardwareState(
+ VOID
+ );
+
+VOID
+HalpEnableL2Cache(
+ VOID
+ );
+
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+ extern KSPIN_LOCK NVRAM_Spinlock;
+ PKPRCB Prcb;
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ Prcb = PCR->Prcb;
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ if (Prcb->Number == 0)
+ HalpSetSystemType( LoaderBlock );
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ //
+ // Get access to I/O space, check if I/O space has already been
+ // mapped by debbuger initialization.
+ //
+
+ if (HalpIoControlBase == NULL) {
+
+ HalpIoControlBase = (PVOID)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE, 0x20000);
+
+ if ( !HalpIoControlBase ) {
+ return FALSE;
+ }
+ }
+
+
+ //
+ // Initialize the display adapter. Must be done early
+ // so KeBugCheck() will be able to display
+ //
+ if (!HalpInitializeDisplay(LoaderBlock))
+ return FALSE;
+
+ // 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);
+ }
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+ //
+ // Initialize Spinlock for NVRAM
+ //
+
+ KeInitializeSpinLock( &NVRAM_Spinlock );
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNewTimeIncrement = MAXIMUM_INCREMENT;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Initialize all spin locks.
+ //
+
+#if defined(_MP_PPC_)
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+#endif
+
+ HalpRegisterAddressUsage (&HalpDefaultIoSpace);
+
+ //
+ // Calibrate execution stall
+ //
+ HalpCalibrateStall();
+
+ //
+ // Patch KeFlushWriteBuffer to the optimum code sequence
+ //
+ HalpPatch_KeFlushWriteBuffer();
+
+ //
+ // Size the L2 cache
+ //
+ L2_Cache_Size = HalpSizeL2Cache();
+ PCR->SecondLevelIcacheSize = L2_Cache_Size << 10;
+ PCR->SecondLevelDcacheSize = L2_Cache_Size << 10;
+
+ //
+ // Compute size of PCI Configuration Space mapping
+ //
+ HalpPciConfigSize = PAGE_SIZE * ((1 << (HalpPciMaxSlots-2)) + 1);
+
+ //
+ // Fill in handlers for APIs which this HAL supports
+ //
+
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+
+ }
+
+
+ //
+ // InitializeInterrupts
+ //
+
+ if (!HalpInitializeInterrupts())
+ return FALSE;
+
+ //
+ // return success
+ //
+ return TRUE;
+
+
+ } else {
+
+ if (Phase != 1)
+ return(FALSE);
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+
+
+ HalpRegisterInternalBusHandlers ();
+
+
+ if (!HalpAllocateMapBuffer()) {
+ return FALSE;
+ }
+
+ //
+ // Map I/O space and create ISA data structures.
+ //
+
+ if (!HalpMapIoSpace()) {
+ return FALSE;
+ }
+
+
+ if (!HalpCreateSioStructures()) {
+ return FALSE;
+ }
+
+ HalpCheckHardwareRevisionLevels();
+ HalpEnableL2Cache();
+ HalpEnableEagleSettings();
+ HalpDumpHardwareState();
+ HalpCopyROMs();
+
+ return TRUE;
+ }
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ 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. In order to access the PCR from this
+ routine, use the PCRsprg1 macro, not the PCR macro.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG IcacheSize, DcacheSize;
+ ULONG CacheBlockAlignment;
+
+ switch (HalpGetProcessorVersion() >> 16) {
+
+ case 1: // 601
+ IcacheSize = 32*1024;
+ DcacheSize = 32*1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+
+ case 3: // 603
+ IcacheSize = 8*1024;
+ DcacheSize = 8*1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+
+ case 6: // 603e
+ case 7: // 603ev
+ case 4: // 604
+ IcacheSize = 16*1024;
+ DcacheSize = 16*1024;
+ CacheBlockAlignment = 32 - 1;
+ break;
+
+ case 9: // 604+
+ 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;
+
+
+ return;
+}
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxintsup.s b/private/ntos/nthals/haleagle/ppc/pxintsup.s
new file mode 100644
index 000000000..1472ea053
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxintsup.s
@@ -0,0 +1,290 @@
+// 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 mask and unmask
+// interrupts on a PowerPC system.
+//
+// Author:
+//
+// Steve Johns
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 30-Dec-93 plj Added 603 support.
+// 7-Mar-95 Steve Johns Added HalpUpdate8259 for use in PXIRQL.C
+// 13-Mar-95 Steve Johns Assembly version of KeRaiseIrql
+//
+//--
+#include "halppc.h"
+
+
+
+
+
+
+ .extern HalpIoControlBase
+ .extern Halp8259MaskTable
+
+ .set NewIrql, r.3
+ .set OldIrql, r.4
+ .set Index, r.4
+ .set ISA_Base, r.5
+ .set MaskTable, r.6
+ .set MasterMask, r.8
+ .set SlaveMask, r.9
+ .set PCR, r.10
+ .set MSR, r.11
+ .set CLOCK2_LEVEL, 28
+
+#define KE_FLUSH_WRITE_BUFFERS() \
+ sync ;\
+ lbz r.0, 0x21(ISA_Base)
+
+
+//
+// VOID HalpUpdate8259(KIRQL NewIrql)
+//
+
+ LEAF_ENTRY(HalpUpdate8259)
+
+
+ //
+ // Get pointers to Halp8259MaskTable & ISA I/O space
+ //
+
+ lwz MaskTable,[toc]Halp8259MaskTable(r.toc)
+ add Index, NewIrql, NewIrql // Halp8259MaskTable is table of USHORTS
+
+ lwz ISA_Base,[toc]HalpIoControlBase(r.toc)
+ lwz ISA_Base,0(ISA_Base)
+
+ //
+ // MasterMask = Halp8259MaskTable[NewIrql];
+ //
+ lhzx MasterMask,Index,MaskTable
+
+ //
+ // SlaveMask = MasterMask >> 8;
+ //
+ srwi SlaveMask, MasterMask, 8
+
+ //
+ // WRITE_REGISTER_UCHAR(&(ISA_CONTROL->Interrupt1ControlPort1),
+ // (UCHAR) MasterMask);
+ //
+ stb MasterMask, 0x21(ISA_Base)
+
+ //
+ // WRITE_REGISTER_UCHAR(&(ISA_CONTROL->Interrupt2ControlPort1),
+ // (UCHAR) SlaveMask);
+ //
+ stb SlaveMask, 0xA1(ISA_Base)
+
+
+ //
+ // Make sure Eagle write buffers are flushed
+ //
+
+ KE_FLUSH_WRITE_BUFFERS()
+
+
+ LEAF_EXIT (HalpUpdate8259)
+
+
+/*************************************************************************/
+
+//
+// VOID KeRaiseIrql ( KIRQL NewIrql, OUT 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 receives the old
+// IRQL value.
+//
+// NOTE: This assembly routine has been measured to be 25% faster than
+// its "C" equivalent.
+
+ LEAF_ENTRY (KeRaiseIrql)
+
+ mfsprg PCR,1 // Get ptr to the PCR
+
+ cmpwi NewIrql, DISPATCH_LEVEL
+ mfmsr MSR
+
+ //
+ // *OldIrql = PCR->CurrentIrql;
+ //
+ lbz r0,PcCurrentIrql(PCR)
+ stb r0, 0(OldIrql)
+
+
+ //
+ // If this is a software-to-software transition,
+ // then don't change hardware interrupt state.
+ //
+ // if (NewIrql <= DISPATCH_LEVEL)
+ // goto RaiseSoftwareToSoftwareIrql;
+ //
+ ble RaiseSoftwareToSoftware
+
+ cmpli cr1, 0, NewIrql, CLOCK2_LEVEL
+
+
+ //
+ // MSR[EE] = 0;
+ //
+ rlwinm r.0,MSR,0,~MASK_SPR(MSR_EE,1)
+ mtmsr r.0
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+
+ //
+ // if (NewIrql >= CLOCK2_LEVEL) {
+ // goto RaiseSoftwareToSoftware;
+ // }
+ //
+
+ bge 1,RaiseSoftwareToSoftware
+
+
+
+
+
+ //
+ // Get pointers to Halp8259MaskTable & ISA I/O space
+ //
+
+ lwz MaskTable,[toc]Halp8259MaskTable(r.toc)
+ add Index, NewIrql, NewIrql // Halp8259MaskTable is table of USHORTS
+
+ lwz ISA_Base,[toc]HalpIoControlBase(r.toc)
+ lwz ISA_Base,0(ISA_Base)
+
+ //
+ // MasterMask = Halp8259MaskTable[NewIrql];
+ //
+ lhzx MasterMask,Index,MaskTable
+
+ //
+ // SlaveMask = MasterMask >> 8;
+ //
+ srwi SlaveMask, MasterMask, 8
+
+ //
+ // WRITE_REGISTER_UCHAR(&(ISA_CONTROL->Interrupt1ControlPort1),
+ // (UCHAR) MasterMask);
+ //
+ stb MasterMask, 0x21(ISA_Base)
+
+
+ //
+ // WRITE_REGISTER_UCHAR(&(ISA_CONTROL->Interrupt2ControlPort1),
+ // (UCHAR) SlaveMask);
+ //
+ stb SlaveMask, 0xA1(ISA_Base)
+
+
+ //
+ // Make sure Eagle write buffers are flushed.
+ //
+
+ KE_FLUSH_WRITE_BUFFERS()
+
+ //
+ // PCR->CurrentIrql = NewIrql;
+ //
+ stb NewIrql, PcCurrentIrql(PCR)
+
+
+ //
+ // MSR[EE] = 1;
+ //
+ ori MSR,MSR,MASK_SPR(MSR_EE,1)
+ mtmsr MSR
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+ blr
+
+
+
+RaiseSoftwareToSoftware:
+ //
+ // PCR->CurrentIrql = NewIrql;
+ //
+ stb NewIrql, PcCurrentIrql(PCR)
+
+ LEAF_EXIT (KeRaiseIrql)
+
+
+
+//
+// VOID HalpResetIrqlAfterInterrupt(KIRQL NewIrql)
+//
+// Routine Description:
+//
+// This function disables external interrupts, lowers the current
+// IRQL to the specified value and returns with interrupts disabled.
+//
+// This routine is called instead of KeLowerIrql to return IRQL to
+// its level prior to being raised due to an external interrupt.
+//
+// We know current IRQL is > DISPATCH_LEVEL
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// Return Value:
+//
+// None.
+//
+
+// {
+// HalpDisableInterrupts();
+// PCR->CurrentIrql = NewIrql;
+// if (NewIrql < CLOCK2_LEVEL)
+// HalpUpdate8259(NewIrql);
+// }
+
+
+ LEAF_ENTRY (HalpResetIrqlAfterInterrupt)
+
+ mfmsr MSR
+ cmpwi NewIrql, CLOCK2_LEVEL
+ mfsprg PCR,1 // Get ptr to the PCR
+
+ //
+ // MSR[EE] = 0;
+ //
+ rlwinm MSR,MSR,0,~MASK_SPR(MSR_EE,1)
+ mtmsr MSR
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+
+ stb NewIrql,PcCurrentIrql(PCR)
+ blt+ ..HalpUpdate8259
+
+ LEAF_EXIT (HalpResetIrqlAfterInterrupt)
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxirql.c b/private/ntos/nthals/haleagle/ppc/pxirql.c
new file mode 100644
index 000000000..2fecf0219
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxirql.c
@@ -0,0 +1,261 @@
+// 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).
+//
+//--
+
+#include "halp.h"
+
+//
+// Initialize the 8259 IRQL mask table
+//
+
+USHORT Halp8259MaskTable[] = { 0x0000, // irql0 Low level
+ 0x0000, // irql1 APC
+ 0x0000, // irql2 Dispatch
+ 0x0000, // irql3
+ 0x0000, // irql4
+ 0x0000, // irql5
+ 0x0000, // irql6
+ 0x0000, // irql7
+ 0x0000, // irql8
+ 0x0000, // irql9
+ 0x0000, // irql10
+ 0x0080, // irql11 parallel
+ 0x00C0, // irql12 floppy
+ 0x00E0, // irql13 parallel
+ 0x00F0, // irql14 com 1
+ 0x00F8, // irql15 com 2
+ 0x80F8, // irql16 pci slot
+ 0xC0F8, // irql17 isa slot
+ 0xE0F8, // irql18 scsi
+ 0xF0F8, // irql19 mouse
+ 0xF8F8, // irql20 isa slot
+ 0xFCF8, // irql21 audio
+ 0xFEF8, // irql22 isa slot
+ 0xFFF8, // irql23 rtc
+ 0xFFF8, // irql24 cascade
+ 0xFFFA, // irql25 kb
+ 0xFFFB, // irql26 timer 1
+ 0xFFFB, // irql27 PROFILE_LEVEL
+ 0xFFFF, // irql28 CLOCK LEVEL
+ 0xFFFF, // irql29 IPI_LEVEL
+ 0xFFFF, // irql30 POWER_LEVEL
+ 0xFFFF // irql31 HIGH_LEVEL
+ };
+
+
+
+VOID
+KiDispatchSoftwareInterrupt(
+ VOID
+ );
+
+VOID
+HalpUpdate8259(
+ KIRQL NewIrql
+ );
+
+
+//
+// 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;
+
+
+ OldIrql = PCR->CurrentIrql;
+
+ //
+ // If this is a software-to-software transition don't change hardware
+ // interrupt state
+ //
+
+ if (OldIrql > DISPATCH_LEVEL) {
+
+ HalpDisableInterrupts();
+ PCR->CurrentIrql = NewIrql;
+
+ //
+ // If old IRQL is < CLOCK2_LEVEL then interrupt are enabled
+ // in the MSR but the 8259 mask must be updated. If not, then
+ // interrupts need to be enabled, however the 8259 does not need to
+ // be updated.
+ //
+
+ if (NewIrql < CLOCK2_LEVEL) {
+ HalpUpdate8259(NewIrql);
+ HalpEnableInterrupts();
+ }
+ } else {
+ PCR->CurrentIrql = NewIrql;
+ }
+
+ //
+ // check for DPC's
+
+ if ((NewIrql < DISPATCH_LEVEL) && PCR->SoftwareInterrupt)
+ KiDispatchSoftwareInterrupt();
+
+}
+
+#if 0 // This code has been re-written in assembly. See PXINTSUP.C
+//
+// VOID
+// HalpResetIrqlAfterInterrupt(
+// KIRQL TargetIrql
+// )
+//
+// Routine Description:
+//
+// This function disables external interrupts, lowers the current
+// IRQL to the specified value and returns with interrupts disabled.
+//
+// This routine is called instead of KeLowerIrql to return IRQL to
+// its level prior to being raised due to an external interrupt.
+//
+// We know current IRQL is > DISPATCH_LEVEL
+//
+// Arguments:
+//
+// TargetIrql - Supplies the new IRQL value.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+VOID
+HalpResetIrqlAfterInterrupt(
+ KIRQL TargetIrql
+ )
+
+{
+
+ PUCHAR PIC_Address;
+ USHORT PIC_Mask;
+
+
+ HalpDisableInterrupts();
+ PCR->CurrentIrql = TargetIrql;
+
+ //
+ // If TargetIrql < CLOCK2_LEVEL, then the 8259 mask must be updated.
+ //
+
+ if (TargetIrql < CLOCK2_LEVEL) {
+ HalpUpdate8259(TargetIrql);
+ }
+}
+
+/*************************************************************************/
+
+//
+// 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 receives the old
+// IRQL value.
+//
+
+VOID
+KeRaiseIrql(
+ IN KIRQL NewIrql,
+ OUT PKIRQL OldIrql
+ )
+
+{
+ //
+ // If this is a software-to-software transition, don't change hardware
+ // interrupt state
+ //
+
+ if (NewIrql > DISPATCH_LEVEL) {
+
+ HalpDisableInterrupts();
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+
+ //
+ // If new IRQL is >= CLOCK2_LEVEL, disable interrupts in the MSR but
+ // don't touch the 8259's. Otherwise, leave interrupts enabled and
+ // update the 8259's.
+ //
+
+ if (NewIrql < CLOCK2_LEVEL) {
+ HalpUpdate8259(NewIrql);
+ HalpEnableInterrupts();
+ }
+
+ } else {
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+ }
+}
+#endif
diff --git a/private/ntos/nthals/haleagle/ppc/pxisabus.c b/private/ntos/nthals/haleagle/ppc/pxisabus.c
new file mode 100644
index 000000000..0c0c03faf
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxisabus.c
@@ -0,0 +1,130 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxisabus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "halp.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
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetIsaInterruptVector)
+#pragma alloc_text(PAGE,HalpAdjustIsaResourceList)
+#endif
+
+
+ULONG
+HalpGetIsaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+{
+
+ //
+ // irq2 shows up on irq9
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ BusInterruptVector = 9;
+ }
+
+ if (BusInterruptLevel > 15) {
+ return 0;
+ }
+
+ //
+ // Get parent's translation from here..
+ //
+ return BusHandler->ParentHandler->GetInterruptVector (
+ BusHandler->ParentHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+
+ SUPPORTED_RANGE InterruptRange;
+
+ RtlZeroMemory (&InterruptRange, sizeof InterruptRange);
+ InterruptRange.Base = 0;
+ InterruptRange.Limit = 15;
+
+ return HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ &InterruptRange,
+ pResourceList
+ );
+}
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxl2.s b/private/ntos/nthals/haleagle/ppc/pxl2.s
new file mode 100644
index 000000000..045e29257
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxl2.s
@@ -0,0 +1,551 @@
+//
+//
+// 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:
+//
+// PXL2.S
+//
+// Abstract:
+//
+// This module implements the routines to size & enable the L2 cache
+// on an Eagle based system.
+//
+// Author:
+//
+// Steve Johns (sjohns@pets.sps.mot.com)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 11-Aug-94 saj Added Eagle L2 cache support for Big Bend.
+// 23-Nov-94 saj Added input parameter specifying write-back or write-thru
+// 01-Dec-94 saj Removed all hardware workarounds
+// Enable L2 Parity error checking (Eagle register 0xC4)
+// 08-Mar-95 saj Added input parameter EagleAC
+// 21-Aug-95 v-matth Steve's sizing functionality is walking on the
+// page file database if we have 128Mb of RAM. I'm
+// going to change it to save off main memory before
+// we do our writes to main memory, then restore those
+// values before we exit.
+// 01-Sep-95 saj Check if L2 is already enabled. If so, just exit.
+// Otherwise, size L2 and exit with L2 disabled. Don't read
+// DBATs, since can't be read reliably on 603e.
+//
+
+#include "kxppc.h"
+#include "halppc.h"
+
+ .extern HalpIoControlBase
+
+ .set HID0, 1008
+//
+// Eagle register A8 fields:
+//
+ .set CF_WRITE_THRU, 0x0001 // Write-through
+ .set CF_WRITE_BACK, 0x0002 // Write-back
+ .set CF_L2_MP, 0x0003 // Bits 1..0 (LE bit order)
+
+//
+// Eagle register AC fields:
+//
+ .set L2_EN, 0x40000000
+ .set L2_UPDATE_EN, 0x80000000
+ .set CF_FLUSH_L2, 0x10000000
+ .set CF_INV_MODE, 0x00001000
+//
+// L2 cache sizes:
+//
+ .set CF_L2_SIZE, 0x0030 // Bits 5..4 (LE bit order)
+ .set L2_1M, 0x0020
+ .set L2_512K, 0x0010
+ .set L2_256K, 0x0000
+ .set L2_LINE_SIZE, 32
+//
+// Local parameters
+//
+ .set CacheSize, r.3 // Return value
+ .set Pattern, r.3
+ .set Offset, r.5
+ .set EagleA8, r.6
+ .set EagleAC, r.7
+ .set L2off, r.8 // Eagle register A8 for L2 disabled
+ .set Restore, r.9
+ .set ISA, r.10 // Pointer to ISA I/O space
+ .set Virtual, r.11
+
+ .set Pattern0, 0x77777777 // Patterns for L2 cache sizing
+ .set Pattern1, 0x11111111
+ .set Pattern2, 0x22222222
+ .set Pattern3, 0X33333333
+ .set Pattern4, 0x44444444
+
+ .set VIRTUAL, 0xFFC00000 // Virtual address for L2 sizing
+ .set PHYSICAL, 0x00C00000 // Physical mem. used for L2 sizing
+ .set BAT_REG, 1 // BAT register to use for L2 sizing
+
+//***********************************************************************
+//
+// Synopsis:
+// ULONG HalpSizeL2(VOID)
+//
+// Purpose:
+// Sizes and enables the Eagle L2 cache.
+//
+// Returns:
+// Size of L2 cache or zero if not installed.
+// Valid sizes are 256, 512, and 1024.
+//
+// Global Variables Referenced:
+// HalpIoControlBase
+//
+// NOTE: Interrupts are assumed to be disabled upon entry.
+//***********************************************************************
+
+
+ LEAF_ENTRY(HalpSizeL2)
+
+//
+// Lock the I-cache so instruction fetching doesn't impact the L2 cache
+// while we are sizing it. With the I-cache locked, instruction fetches will
+// not bursted in, so the L2 will not respond to those cycles.
+//
+ mfspr r.0, HID0
+ ori r.0, r.0, 0x2000 // Lock the Icache
+ mtspr HID0, r.0
+
+
+
+//
+// Get ptr to Eagle I/O (ISA bus)
+//
+ lwz ISA,[toc]HalpIoControlBase(r.toc) // Get base of ISA I/O
+ lwz ISA,0(ISA)
+
+ LWI (EagleA8, 0x800000A8) // Processor Interface Configuration 1
+ addi EagleAC, EagleA8, 4 // Processor Interface Configuration 2
+
+//
+// Return if L2 cache is already enabled.
+//
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ lwz r.0, 0xCFC(ISA)
+ andis. r.4, r.0, (L2_EN >> 16) // Test L2_EN
+ beq Init_BAT
+
+ stw EagleA8, 0xCF8(ISA)
+ sync
+ lwz r.4, 0xCFC(ISA)
+ andi. r.4, r.4, CF_L2_MP // Test CF_L2_MP
+ beq Init_BAT
+
+ andi. r.0, r.0, CF_L2_SIZE // Isolate L2 size field
+ cmpi 0,0,r.0, 0x30 // Reserved ?
+ li CacheSize, 0
+ beq L2_Exit
+
+ li CacheSize, 256
+ cmpi 0,0,r.0, L2_256K
+ beq L2_Exit
+
+ li CacheSize, 512
+ cmpi 0,0,r.0, L2_512K
+ beq L2_Exit
+
+ li CacheSize, 1024
+ b L2_Exit
+
+
+//
+// Initialize a BAT register to map the memory at PHYSICAL to VIRTUAL.
+// The sizing algorithm depends on the block of memory being marked WRITE-THRU.
+//
+Init_BAT:
+ LWI (Virtual, VIRTUAL)
+ LWI (r.0, PHYSICAL + 0x5A) // WIMG = 1011; PP = 10
+ mtdbatl BAT_REG, r.0
+ ori r.0, Virtual, 0x003F // BL = 2MB; Vs = Vp = 1
+ mtdbatu BAT_REG, r.0
+
+ isync
+
+
+
+//
+// Save the 4 test locations.
+//
+ lis Offset, 4 // Offset = 256K
+
+ lwz Pattern,[toc].LRDATA(rtoc) // Pattern <- address of .LRDATA
+ lwz r.0, 0 (Virtual)
+ stw r.0, 0 (Pattern) // Save Memory[ 0K];
+ dcbf r.0, Virtual
+
+ lwzux r.0, Virtual, Offset
+ dcbf r.0, Virtual
+ stw r0, 4(Pattern) // Save Memory[256K];
+
+ lwzux r.0, Virtual, Offset
+ mr r.9, Virtual // r.9 = Virtual + 512K
+ dcbf r.0, Virtual
+ stw r0, 8(Pattern) // Save Memory[512K];
+
+ lwzux r.0, Virtual, Offset
+ dcbf r.0, Virtual
+ stw r0,12(Pattern) // Save Memory[768K];
+ LWI (Virtual, VIRTUAL)
+
+
+//
+// Set the L2 cache to Write-Through
+//
+ stw EagleA8, 0xCF8(ISA)
+ sync
+ lwz L2off, 0xCFC(ISA)
+ rlwinm L2off, L2off,0,~CF_L2_MP
+ ori r.0, L2off, CF_WRITE_THRU
+ stw r.0, 0xCFC(ISA)
+ sync
+
+//
+// Enable the L2 cache for 1 MB
+//
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ lwz r.0, 0xCFC(ISA)
+ rlwinm r.0, r.0, 0, ~CF_L2_SIZE
+ ori r.0, r.0, L2_1M
+ oris r.0, r.0, ((L2_EN+L2_UPDATE_EN) >> 16)
+ stw r.0, 0xCFC(ISA)
+ sync
+ sync
+
+//
+// Load the 4 test locations into the L2 cache.
+//
+ lwzx r.0, r.9, Offset // 768 KB
+ lwz r.0, 0(r.9) // 512 KB
+ lwzx r.0, Virtual, Offset // 256 KB
+ lwz r.0, 0 (Virtual) // 0 KB
+
+
+//
+// Store different patterns to the 4 test locations. This should cause
+// values to be stored in the L2 cache and memory.
+//
+ LWI (Pattern, Pattern4) // L2_Cache[768K] = Pattern4;
+ stwx Pattern, r.9, Offset
+
+ LWI (Pattern, Pattern3) // L2_Cache[512K] = Pattern3;
+ stw Pattern, 0 (r.9)
+
+ LWI (Pattern, Pattern2) // L2_Cache[256K] = Pattern2;
+ stwx Pattern, Virtual, Offset
+
+ LWI (Pattern, Pattern1) // L2_Cache[ 0K] = Pattern1;
+ stw Pattern, 0 (Virtual)
+
+//
+// Disable the L2 cache. The tags are NOT invalidated. No L2 snoop
+// operations or data updates are performed.
+//
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ lwz r.0, 0xCFC(ISA)
+ rlwinm r.0, r.0, 0, ~(L2_EN+L2_UPDATE_EN)
+ stw r.0, 0xCFC(ISA)
+ sync
+
+//
+// Store PATTERN0 to our 4 test locations. Only L1 and main memory will be
+// written since the L2 cache has been disabled. This allows us to distinguish
+// patterns in the L2 from main memory.
+//
+
+ LWI (Pattern, Pattern0) // L2_Cache[768K] = Pattern0;
+ stwx Pattern, r.9, Offset
+ stw Pattern, 0 (r.9) // L2_Cache[512K] = Pattern0;
+ stwx Pattern, Virtual,Offset // L2_Cache[256K] = Pattern0;
+ stw Pattern, 0 (Virtual) // L2_Cache[ 0K] = Pattern0;
+
+//
+// Load 8 locations (for an 8-way L1 cache) 4096 bytes apart in order to flush
+// the test locations from the L1. We can't use DCBF since that would flush
+// the L2 also.
+//
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ lwzu Pattern, 4096(Virtual)
+ LWI (Virtual, VIRTUAL)
+
+//
+// Re-enable the L2 cache
+//
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ lwz r.0, 0xCFC(ISA)
+ oris r.0, r.0, ((L2_EN + L2_UPDATE_EN) >> 16)
+ stw r.0, 0xCFC(ISA)
+ sync
+
+ lwz Pattern, 0(Virtual) // Read test location @ 0 KB
+ lwzx r.0, Virtual, Offset // Read test location @ 256 KB
+ rlwimi Pattern, r.0, 0, 8, 15
+ lwz r.0, 0 (r.9) // Read test location @ 512 KB
+ rlwimi Pattern, r.0, 0, 16, 23
+ lwzx r.0, r.9, Offset // Read test location @ 768 KB
+ rlwimi Pattern, r.0, 0, 24, 31
+
+//
+// Test the pattern from L2 to determine it's size
+//
+
+ LWI (r.0, 0x11777777)
+ cmpl 0,0, Pattern, r.0
+ beq Set_256K
+
+ LWI (r.0, 0x11227777)
+ cmpl 0,0, Pattern, r.0
+ beq Set_512K
+
+ LWI (r.0, 0x11223344)
+ cmpl 0,0, Pattern, r.0
+ beq Set_1M
+
+// LWI (r.0, 0x77777777)
+// cmpl 0,0, Pattern, r.0
+// bne InvalidPattern
+
+ li CacheSize, 0
+ b DisableCache
+
+
+//
+// Unexpected pattern. Return it for display.
+//
+InvalidPattern:
+// mr CacheSize, Pattern // Not needed if CacheSize == Pattern
+ b DisableCache
+
+
+
+Set_256K:
+ li CacheSize, 256
+ li r.4, L2_256K
+ b SetCacheSize
+
+Set_512K:
+ li CacheSize, 512
+ li r.4, L2_512K
+ b SetCacheSize
+
+Set_1M:
+ li CacheSize, 1024
+ li r.4, L2_1M
+
+//
+// r.3 = cache size in KB
+// r.4 = cache size field to be inserted into Eagle register AC.
+//
+SetCacheSize:
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ lwz r.9, 0xCFC(ISA)
+ rlwimi r.9, r.4, 0, CF_L2_SIZE // Insert CF_L2_SIZE field
+ stw r.9, 0xCFC(ISA)
+ sync
+
+//
+// Eagle 2.1 BUG:
+// Write-back works OK
+// Write-thru walks thru addresses but does not invalidate them.
+// Don't need to flush for write-thru anyway!!!!
+//
+// NOTE: If changing from WRITE-BACK to WRITE-THROUGH, you must flush
+// beforehand because castouts are not supported in write-through.
+// If the L2 has dirty data, then switching to write-through, the
+// dirty data won't get flushed (cast out) to main memory.
+//
+ rlwinm r.4, r.9, 0, 1,31 // Clear L2_UPDATE_EN (lock L2)
+ stw r.4, 0xCFC(ISA)
+ oris r.0, r.4, (CF_FLUSH_L2 >> 16) // Toggle CF_FLUSH_L2
+ sync
+ stw r.0, 0xCFC(ISA)
+ sync
+ stw r.4, 0xCFC(ISA)
+//
+// Flush the L2 by walking through memory (2x L2 size)
+//
+ rlwinm r.0, CacheSize, 10-5+1, 0, 31 // L2Size * (1024 / LINE_SIZE) * 2
+ mtctr r.0
+ subi r.4, Virtual, L2_LINE_SIZE
+FlushLoop:
+ lwzu r.0, L2_LINE_SIZE (r.4)
+ bdnz FlushLoop
+
+//
+// Disable the L2 cache
+//
+DisableCache:
+ sync
+ lwz r.9, 0xCFC(ISA)
+ rlwinm r.9, r.9, 0, ~(L2_EN+L2_UPDATE_EN)
+ stw r.9, 0xCFC(ISA)
+ sync
+
+
+ stw EagleA8, 0xCF8(ISA)
+ sync
+ stw L2off, 0xCFC(ISA) // Disable the L2 cache
+ sync
+
+//
+// Restore the original contents of the test locations
+//
+ lwz Restore,[toc].LRDATA(rtoc)
+ lwz r0, 0(Restore) // Restore test location 0
+ stw r0, 0(Virtual)
+
+ lwz r0, 4(Restore) // Restore test location 1
+ stwux r0, Virtual, Offset
+
+ lwz r0, 8(Restore) // Restore test location 2
+ stwux r0, Virtual, Offset
+
+ lwz r0,12(Restore) // Restore test location 3
+ stwx r0, Virtual, Offset
+
+ li r.0, 0 // Invalidate the BAT we used
+ mtdbatu BAT_REG, r.0
+ mtdbatl BAT_REG, r.0
+L2_Exit:
+ mfspr r.0, HID0
+ rlwinm r.0, r.0, 0, ~0x2000 // Unlock the Icache
+ mtspr HID0, r.0
+
+ LEAF_EXIT(HalpSizeL2)
+
+
+
+
+//***********************************************************************
+//
+// Synopsis:
+// VOID HalpFlushAndDisableL2(VOID)
+//
+// Purpose:
+// If the L2 is enabled and in WRITE-BACK mode, the L2 is flushed.
+// In either mode, the L2 is invalidated, and upon exit, the L2 is
+// left disabled.
+//
+// Returns:
+// nothing
+//
+// Global Variables Referenced:
+// HalpIoControlBase
+//
+// NOTE: Interrupts are assumed to be disabled upon entry.
+//***********************************************************************
+ LEAF_ENTRY(HalpFlushAndDisableL2)
+
+ mfsprg r.12, 1 // Get PCR->SecondLevelDcacheSize
+ lwz r.0, PcSecondLevelDcacheSize (r.12)
+ srwi. r.0, r.0, 5 // # lines in L2
+ beqlr-
+ mtctr r.0
+
+
+ lwz ISA,[toc]HalpIoControlBase(r.toc) // Get base of ISA I/O
+ lwz ISA,0(ISA)
+
+ LWI (EagleA8, 0x800000A8) // Processor Interface Configuration 1
+ addi EagleAC, EagleA8, 4 // Processor Interface Configuration 2
+
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ lwz r.5, 0xCFC(ISA)
+ andis. r.0, r.5, (L2_EN >> 16) // Disable the L2 (L2_EN = 0)
+ beqlr
+
+ mfspr r.9, HID0 // Lock the Icache
+ ori r.0, r.9, 0x2000
+ mtspr HID0, r.0
+ isync
+
+ stw EagleA8, 0xCF8(ISA) // Check CF_L2_MP
+ sync
+ lwz r.4, 0xCFC(ISA)
+ andi. r.0, r.4, CF_L2_MP
+ beq FlushExit // Return if L2 is disabled
+
+
+ cmpwi r.0, CF_WRITE_THRU // Is L2 in write-through mode ?
+ beq InvalidateL2 // Yes, then flush is not necessary
+
+//
+// Flush the L2 contents to main memory
+//
+ stw EagleAC, 0xCF8(ISA) // Clear L2_UPDATE_EN (lock L2)
+ rlwinm r.0, r.5, 0, 1,31
+ oris r.0, r.0, (CF_FLUSH_L2 >> 16) // Toggle CF_FLUSH_L2
+ stw r.0, 0xCFC(ISA)
+ sync
+ stw r.5, 0xCFC(ISA)
+
+
+InvalidateL2:
+ stw EagleAC, 0xCF8(ISA) // Clear L2_UPDATE_EN (lock L2)
+ sync
+ rlwinm r.5, r.5, 0, 2,0 // Clear L2_EN (disable the L2 cache)
+ ori r.0, r.5, CF_INV_MODE // Set L2 to invalidate mode
+ stw r.0, 0xCFC(ISA)
+ sync
+
+//
+// Invalidate the L2 by walking thru memory
+//
+ LWI (r.12, 0x80000000-L2_LINE_SIZE)
+Invalidate:
+ lwzu r.0, L2_LINE_SIZE (r.12)// Read from L2 cache
+ bdnz Invalidate
+
+
+ stw EagleA8, 0xCF8(ISA)
+ sync
+ rlwinm r.4, r.4, 0, ~CF_L2_MP // Clear CF_L2_MP
+ stw r.4, 0xCFC(ISA)
+
+FlushExit:
+ stw EagleAC, 0xCF8(ISA)
+ sync
+ rlwinm r.5, r.5, 0, 2,31 // Clear L2_EN & L2_UPDATE_EN
+ stw r.5, 0xCFC(ISA) // Clear CF_INV_MODE
+
+
+ mtspr HID0, r.9 // Unlock the Icache
+
+ LEAF_EXIT(HalpFlushAndDisableL2)
+
+
+.LRDATA:
+// loc 0 - Holds memory at 0K
+ .ualong 0x0
+// loc 4 - Holds memory at 256K
+ .ualong 0x0
+// loc 8 - Holds memory at 512K
+ .ualong 0x0
+// loc 12 - Holds memory at 1024K
+ .ualong 0x0
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxmapio.c b/private/ntos/nthals/haleagle/ppc/pxmapio.c
new file mode 100644
index 000000000..edf50cc91
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxmapio.c
@@ -0,0 +1,124 @@
+/*++
+
+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
+
+--*/
+
+#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/haleagle/ppc/pxmemctl.c b/private/ntos/nthals/haleagle/ppc/pxmemctl.c
new file mode 100644
index 000000000..9a844710b
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxmemctl.c
@@ -0,0 +1,1643 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+ Steve Johns (sjohns@pets.sps.mot.com)
+
+Revision History:
+
+--*/
+
+
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "pxpcisup.h"
+#include "pci.h"
+#include "pcip.h"
+#include "arccodes.h"
+#include "pxsystyp.h"
+#include <string.h>
+
+
+ULONG PciInterruptRoutingOther = 15;
+
+VOID HalDisplayString(PUCHAR String);
+ULONG HalpGetHID0(VOID);
+VOID HalpSetHID0(ULONG Value);
+BOOLEAN HalpStrCmp();
+VOID HalpEnableL2Cache(VOID);
+ULONG HalpSizeL2Cache(VOID);
+extern ULONG HalpSizeL2(VOID);
+extern ULONG L2_Cache_Size;
+extern VOID HalpFlushAndDisableL2(VOID);
+extern HalpPciConfigSize;
+BOOLEAN HalpInitPlanar(VOID);
+BOOLEAN HalpMapPlanarSpace(VOID);
+VOID HalpEnableEagleSettings(VOID);
+VOID HalpEnable_HID0_Settings(ULONG);
+VOID HalpCheckHardwareRevisionLevels(VOID);
+VOID HalpDumpHardwareState(VOID);
+
+#define EAGLECHIPID 0x0001
+
+#define BUF_LEN 120
+#define NEGATECHAR '~'
+
+#define EagleIndexRegister ((PULONG) (((PUCHAR) HalpIoControlBase) + 0xcf8))
+#define EagleDataRegister ((((PUCHAR) HalpIoControlBase) + 0xcfc))
+
+#define HalpReadEagleUlong(Port) \
+ (*EagleIndexRegister = (Port), __builtin_eieio(), *((PULONG) EagleDataRegister))
+
+#define HalpWriteEagleUlong(Port, Value) \
+ (*EagleIndexRegister = (Port), *((PULONG) EagleDataRegister) = (Value), __builtin_sync())
+
+#define HalpReadEagleUshort(Port) \
+ (*EagleIndexRegister = (Port&~3), __builtin_eieio(), *((PUSHORT)(EagleDataRegister+(Port&0x2))))
+
+#define HalpWriteEagleUshort(Port, Value) \
+ (*EagleIndexRegister = (Port&~3), *((PUSHORT)(EagleDataRegister+(Port&0x2))) = (Value), __builtin_sync())
+
+#define HalpWriteEagleUchar(Port, Value) \
+ (*EagleIndexRegister = (Port&~3), *((PUCHAR)(EagleDataRegister+(Port&0x3))) = (Value), __builtin_sync())
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpStrCmp)
+#pragma alloc_text(INIT,HalpEnableL2Cache)
+#pragma alloc_text(INIT,HalpInitPlanar)
+#pragma alloc_text(INIT,HalpMapPlanarSpace)
+#pragma alloc_text(INIT,HalpEnableEagleSettings)
+#pragma alloc_text(INIT,HalpEnable_HID0_Settings)
+#pragma alloc_text(INIT,HalpCheckHardwareRevisionLevels)
+#pragma alloc_text(INIT,HalpSizeL2Cache)
+#endif
+
+
+UCHAR HalpReadEagleUchar(ULONG Port)
+{ UCHAR c;
+ *EagleIndexRegister = Port & ~3;
+ __builtin_eieio();
+ c = *((PUCHAR)(EagleDataRegister+(Port&0x3)));
+ return (c);
+}
+
+
+// Eagle rev 2.1 reads Config register 0xC0 bit 4 into bit 3 instead.
+// Writes to bit 4 are OK.
+UCHAR HalpReadEagleC0(ULONG Port)
+{ UCHAR c;
+
+ c = HalpReadEagleUchar(0x800000C0);
+ c |= ((c & 0x08) << 1);
+ return (c);
+}
+
+
+
+typedef UCHAR (*PHALP_READ_EAGLE) (ULONG Port);
+PHALP_READ_EAGLE HalpReadEagleRegC0;
+
+
+#define HalpDisplayHex32(Num, Buf) HalpDisplayHex( 32, Num, Buf)
+#define HalpDisplayHex16(Num, Buf) HalpDisplayHex( 16, Num, Buf)
+#define HalpDisplayHex8(Num, Buf) HalpDisplayHex( 8, Num, Buf)
+
+VOID HalpDisplayHex(
+ ULONG NoBits,
+ ULONG Number,
+ IN PUCHAR Buffer
+)
+{ int Bits;
+
+ for (Bits=NoBits-4; Bits >= 0; Bits -=4) {
+ *Buffer++ = (UCHAR) ((((Number >> Bits) & 0xF) > 9) ?
+ ((Number >> Bits) & 0xF) - 10 + 'A' :
+ ((Number >> Bits) & 0xF) + '0');
+ }
+ *Buffer++ = '.';
+ *Buffer++ = '\n';
+ *Buffer++ = '\0';
+
+}
+
+
+UCHAR HalpUpperCase(UCHAR c)
+{
+ if (c >= 'a' && c <= 'z')
+ c -= 'a'-'A';
+ return c;
+}
+
+
+//
+// Routine Description:
+//
+// This routine is a helper routine for parameter parsing. It compares
+// String1 to String2.
+//
+// Return Value
+//
+// TRUE if strings match; otherwise FALSE
+// MatchLen - the number of characters correctly matched.
+//
+
+// #define HalpStrCmp(String1, String2) ( strcmp(String1, String2) == 0)
+BOOLEAN HalpStrCmp( char *String0, char *String1 )
+{
+char *tmp0, *tmp1;
+
+ tmp0 = String0;
+ tmp1 = String1;
+ while( (*tmp0 = toupper( *tmp0 )) && (*tmp1 = toupper( *tmp1 )) )
+ {
+ tmp0++; tmp1++;
+ }
+ return( strcmp(String0, String1) == 0 );
+}
+
+typedef struct tagEAGLEA8 {
+ union {
+ struct {
+ ULONG CF_L2_MP : 2;
+ ULONG SPECULATIVE_PCI : 1;
+ ULONG CF_APARK : 1;
+ ULONG CF_LOOP_SNOOP : 1;
+ ULONG LITTLE_ENDIAN : 1;
+ ULONG STORE_GATHERING : 1;
+ ULONG NO_PORTS_REG : 1;
+ ULONG Reserved1 : 1;
+ ULONG CF_DPARK : 1;
+ ULONG TEA_EN : 1;
+ ULONG MCP_EN : 1;
+ ULONG FLASH_WR_EN : 1;
+ ULONG CF_LBA_EN : 1;
+ ULONG Reserved2 : 1;
+ ULONG CF_MP_ID : 1;
+ ULONG ADDRESS_MAP : 1;
+ ULONG PROC_TYPE : 2;
+ ULONG DISCONTIGOUS_IO : 1;
+ ULONG ROM_CS : 1;
+ ULONG CF_CACHE_1G : 1;
+ ULONG CF_BREAD_WS : 2;
+ ULONG CF_CBA_MASK : 8;
+ } EagleA8;
+
+ ULONG AsUlong;
+ } u;
+} EAGLEA8;
+
+typedef struct tagEAGLEAC {
+ union {
+ struct {
+ ULONG CF_WDATA : 1;
+ ULONG CF_DOE : 1;
+ ULONG CF_APHASE : 2;
+ ULONG CF_L2_SIZE : 2;
+ ULONG CF_TOE_WIDTH : 1;
+ ULONG CF_FAST_CASTOUT : 1;
+ ULONG CF_BURST_RATE : 1;
+ ULONG CF_L2_HIT_DELAY : 2;
+ ULONG reserved1 : 1;
+ ULONG CF_INV_MODE : 1;
+ ULONG CF_HOLD : 1;
+ ULONG CF_ADDR_ONLY : 1;
+ ULONG reserved2 : 1;
+ ULONG CF_HIT_HIGH : 1;
+ ULONG CF_MOD_HIGH : 1;
+ ULONG CF_SNOOP_WS : 2;
+ ULONG CF_WMODE : 2;
+ ULONG CF_DATA_RAM_TYP : 2;
+ ULONG CF_FAST_L2_MODE : 1;
+ ULONG CF_BYTE_DECODE : 1;
+ ULONG reserved3 : 2;
+ ULONG CF_FLUSH_L2 : 1;
+ ULONG reserved4 : 1;
+ ULONG L2_ENABLE : 1;
+ ULONG L2_UPDATE_EN : 1;
+ } EagleAC;
+
+ ULONG AsUlong;
+ } u;
+} EAGLEAC;
+
+
+
+typedef struct tagEAGLEC0 {
+ union {
+ struct {
+ UCHAR LOCAL_BUS : 1;
+ UCHAR PCI_MASTER_ABORT : 1;
+ UCHAR MEM_READ_PARITY : 1;
+ UCHAR Reserved : 1;
+ UCHAR MASTER_PERR : 1;
+ UCHAR MEM_SELECT_ERROR : 1;
+ UCHAR SLAVE_PERR : 1;
+ UCHAR PCI_TARGET_ABORT : 1;
+ } EagleC0;
+
+ UCHAR AsUchar;
+ } u;
+} EAGLEC0;
+
+
+typedef enum {
+ MPC601 = 1,
+ MPC603 = 3,
+ MPC603e = 6,
+ MPC604 = 4,
+ MPC604e = 9
+} CPU_TYPE;
+
+
+// Parity Enable for memory interface
+#define PCKEN 0x10000
+// Machine Check Enable
+#define MCP_EN 0x800
+// Memory Read Parity Enable
+#define MRPE 0x04
+
+typedef enum {
+ WriteThrough,
+ WriteBack
+} L2MODE;
+
+// Oem Output Display function filter noise if OEM or quite
+
+VOID OemDisplayString(PUCHAR String)
+{
+UCHAR CharBuffer[BUF_LEN];
+
+ if(HalGetEnvironmentVariable("HALREPORT",sizeof(CharBuffer),&CharBuffer[0]) == ESUCCESS) {
+ if(HalpStrCmp("YES", CharBuffer)) {
+ HalDisplayString(String);
+ }
+ } else {
+ if(HalGetEnvironmentVariable("MOT-OEM-ID",sizeof(CharBuffer),&CharBuffer[0]) != ESUCCESS) {
+ HalDisplayString(String);
+ }
+ }
+}
+
+char *
+MyStrtok (
+ char * string,
+ const char * control
+ )
+{
+ unsigned char *str;
+ const unsigned char *ctrl = control;
+
+ unsigned char map[32];
+ int count;
+
+ static char *nextoken;
+
+ /* Clear control map */
+ for (count = 0; count < 32; count++)
+ map[count] = 0;
+
+ /* Set bits in delimiter table */
+ do {
+ map[*ctrl >> 3] |= (1 << (*ctrl & 7));
+ } while (*ctrl++);
+
+ /* Initialize str. If string is NULL, set str to the saved
+ * pointer (i.e., continue breaking tokens out of the string
+ * from the last strtok call) */
+ if (string)
+ str = string;
+ else
+ str = nextoken;
+
+ /* Find beginning of token (skip over leading delimiters). Note that
+ * there is no token iff this loop sets str to point to the terminal
+ * null (*str == '\0') */
+ while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )
+ str++;
+
+ string = str;
+
+ /* Find the end of the token. If it is not the end of the string,
+ * put a null there. */
+ for ( ; *str ; str++ )
+ if ( map[*str >> 3] & (1 << (*str & 7)) ) {
+ *str++ = '\0';
+ break;
+ }
+
+ /* Update nextoken (or the corresponding field in the per-thread data
+ * structure */
+ nextoken = str;
+
+ /* Determine if a token has been found. */
+ if ( string == str )
+ return NULL;
+ else
+ return string;
+}
+
+
+VOID HalpEnableL2Cache()
+{ EAGLEAC EagleRegAC;
+ EAGLEA8 EagleRegA8;
+ USHORT CpuRevision;
+ CPU_TYPE CpuType;
+ BOOLEAN SynchronousSRAMs, Negate;
+ UCHAR EagleRevision;
+ L2MODE Mode;
+ int i;
+ UCHAR CharBuffer[BUF_LEN], *Value, c1, c2;
+ UCHAR L2_Parameter[BUF_LEN];
+
+ long BridgeChipId;
+
+ BridgeChipId = HalpReadEagleUshort(0x80000002);
+
+ //
+ // For non-EAGLE chips, firmware has already enabled the L2 cache.
+ // No further action is necessary, return.
+ //
+ if (BridgeChipId != EAGLECHIPID)
+ return;
+
+ EagleRevision = HalpReadEagleUchar(0x80000008);
+
+ //
+ // Set some fields in Eagle Register 0xA8
+ //
+ EagleRegA8.u.AsUlong = HalpReadEagleUlong(0x800000A8);
+ EagleRegA8.u.EagleA8.TEA_EN = 1; // Enable TEA
+
+ CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF);
+ CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16);
+
+ EagleRegA8.u.EagleA8.CF_BREAD_WS = 0; // works for 601 & 604
+ switch (CpuType) {
+ case MPC601:
+ EagleRegA8.u.EagleA8.PROC_TYPE = 0;
+ break;
+
+ case MPC603:
+ case MPC603e:
+ EagleRegA8.u.EagleA8.PROC_TYPE = 2;
+ EagleRegA8.u.EagleA8.CF_BREAD_WS = 1; // assumes DRTRY mode !!!
+ break;
+
+ case MPC604:
+ case MPC604e:
+ EagleRegA8.u.EagleA8.PROC_TYPE = 3;
+ break;
+ }
+
+ //
+ // Set the default L2 cache timing.
+ // The timing will be platform dependent.
+ // If the L2 is already on (via firmware), just return.
+ //
+
+ EagleRegAC.u.AsUlong = HalpReadEagleUlong(0x800000AC);
+ if (EagleRegAC.u.EagleAC.L2_ENABLE)
+ return;
+
+ EagleRegAC.u.EagleAC.CF_WMODE = 3;
+ EagleRegAC.u.EagleAC.CF_MOD_HIGH = 1;
+ EagleRegAC.u.EagleAC.CF_ADDR_ONLY = 1;
+ EagleRegAC.u.EagleAC.CF_APHASE = 1;
+ EagleRegAC.u.EagleAC.CF_DOE = 1;
+ EagleRegAC.u.EagleAC.CF_WDATA = 1;
+ EagleRegAC.u.EagleAC.L2_UPDATE_EN = 1;
+ EagleRegAC.u.EagleAC.L2_ENABLE = 1;
+
+
+ switch (HalpSystemType) {
+ case MOTOROLA_BIG_BEND:
+ case MOTOROLA_POWERSTACK:
+ default:
+ SynchronousSRAMs = TRUE;
+ break;
+ }
+
+ if (SynchronousSRAMs) {
+ EagleRegAC.u.EagleAC.CF_DATA_RAM_TYP = 0;
+ EagleRegAC.u.EagleAC.CF_HOLD = 0;
+ EagleRegAC.u.EagleAC.CF_BURST_RATE = 0;
+ } else {
+ EagleRegAC.u.EagleAC.CF_HOLD = 1;
+ EagleRegAC.u.EagleAC.CF_BURST_RATE = 1;
+ if (EagleRevision == 0x21)
+ EagleRegAC.u.EagleAC.CF_DOE = 0;
+ }
+
+ //
+ // Set up the default L2 cache mode.
+ // Default to WRITE-THROUGH prior to Eagle 2.4, else WRITE-BACK
+ //
+ Mode = WriteThrough;
+ if (EagleRevision >= 0x24) {
+ Mode = WriteBack;
+ EagleRegA8.u.EagleA8.CF_LOOP_SNOOP = 1;
+ EagleRegA8.u.EagleA8.CF_CBA_MASK = 0x3f;
+ }
+
+ if (HalpSystemType == MOTOROLA_BIG_BEND) {
+ EagleRegAC.u.EagleAC.CF_SNOOP_WS = 3;
+ EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY = 1;
+ EagleRegAC.u.EagleAC.CF_TOE_WIDTH = 1;
+
+ } else {
+ EagleRegAC.u.EagleAC.CF_SNOOP_WS = 2;
+ EagleRegAC.u.EagleAC.CF_FAST_CASTOUT = 1;
+ EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY = 2;
+ }
+
+ //
+ // There are IBM 604 parts (Revision 3.3 and earlier) that cannot burst
+ // at the fastest rate in WRITE-BACK mode.
+ //
+ if ((Mode == WriteBack) && (CpuType == MPC604) && (CpuRevision < 0x0304))
+ EagleRegAC.u.EagleAC.CF_BURST_RATE = 1; // -2-2-2
+
+
+ //
+ // Parse the environment variable "L2"
+ //
+
+ if (HalGetEnvironmentVariable("L2", BUF_LEN, &CharBuffer[0]) == ESUCCESS) {
+
+ // Copy L2 environment variable
+ i = 0;
+ while (L2_Parameter[i] = CharBuffer[i]) {
+ i++;
+ }
+
+ for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, " :;,") )
+ {
+ if (*Value == NEGATECHAR) {
+ Value++;
+ Negate = TRUE;
+ } else
+ Negate = FALSE;
+
+ // Check for L2 = "OFF"
+ if (HalpStrCmp( "OFF", Value ))
+ {
+ OemDisplayString("HAL: L2 cache is disabled via environment variable L2\n");
+ HalpFlushAndDisableL2();
+ PCR->SecondLevelDcacheSize = PCR->SecondLevelIcacheSize = 0;
+ return;
+ }
+ // Check for WriteBack
+ else if ( HalpStrCmp( "WB", Value ) )
+ {
+ if (Negate) {
+ Value--;
+ goto ParseError;
+ }
+ Mode = WriteBack;
+ EagleRegA8.u.EagleA8.CF_LOOP_SNOOP = 1;
+ EagleRegA8.u.EagleA8.CF_CBA_MASK = 0x3f;
+ }
+ // Check for WriteThrough
+ else if ( HalpStrCmp( "WT", Value ) )
+ {
+ if (Negate) {
+ Value--;
+ goto ParseError;
+ }
+ Mode = WriteThrough;
+ EagleRegA8.u.EagleA8.CF_LOOP_SNOOP = 0;
+ EagleRegA8.u.EagleA8.CF_CBA_MASK = 0x00;
+ }
+ else if (SynchronousSRAMs && HalpStrCmp("FAST_CASTOUT", Value)) {
+ if (Negate) {
+ EagleRegAC.u.EagleAC.CF_FAST_CASTOUT = 0;
+ } else
+ EagleRegAC.u.EagleAC.CF_FAST_CASTOUT = 1;
+ }
+ else if ( HalpStrCmp( "FAST_MODE", Value ) ) {
+ if (Negate) {
+ EagleRegAC.u.EagleAC.CF_FAST_L2_MODE = 0;
+ } else
+ EagleRegAC.u.EagleAC.CF_FAST_L2_MODE = 1;
+ }
+ // Check for cache timings
+ else if ( ( HalpStrCmp( "3-1-1-1", Value ) ) ||
+ ( HalpStrCmp( "4-1-1-1", Value ) ) ||
+ ( HalpStrCmp( "5-1-1-1", Value ) ) )
+ {
+ if (Negate) {
+ Value--;
+ goto ParseError;
+ }
+
+ EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY = *Value - '2';
+// HIT_DELAY is where it samples HIT if =1, then 3-1-1-1 is fastest.
+// CF_DOE_DELAY adds 1 more delay to # cycles, but doesn't change where
+// HIT is sampled. If 66MHz or greater, then DOE_DELAY should be set.
+// same thing with WRITE_DELAY.
+
+ EagleRegAC.u.EagleAC.CF_SNOOP_WS = *Value - '2';
+ if( SynchronousSRAMs ) // Asynchronous SRAMs can't do -1-1-1
+ EagleRegAC.u.EagleAC.CF_BURST_RATE = 0;
+ }
+ else if ( ( HalpStrCmp( "3-2-2-2", Value ) ) ||
+ ( HalpStrCmp( "4-2-2-2", Value ) ) ||
+ ( HalpStrCmp( "5-2-2-2", Value ) ) )
+ {
+ if (Negate) {
+ Value--;
+ goto ParseError;
+ }
+
+ EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY = *Value - '2';
+ EagleRegAC.u.EagleAC.CF_SNOOP_WS = *Value - '2';
+ EagleRegAC.u.EagleAC.CF_BURST_RATE = 1;
+ } else {
+
+ParseError: HalDisplayString("HAL: Error in L2 environment variable: ");
+ HalDisplayString(L2_Parameter);
+ HalDisplayString("\n illegal parameter begins here ");
+ for (i = 0; i < Value - CharBuffer; i++)
+ HalDisplayString("\304");
+ HalDisplayString("^\n");
+ break;
+ }
+
+ } // End for
+ } // End If
+
+
+ //
+ // Enable L2 cache
+ //
+ OemDisplayString("HAL: L2 cache is ");
+
+ if (L2_Cache_Size == 0) {
+ OemDisplayString("not installed.\n");
+ return;
+ }
+
+ if (Mode == WriteThrough)
+ EagleRegA8.u.EagleA8.CF_L2_MP = 1;
+ else
+ EagleRegA8.u.EagleA8.CF_L2_MP = 2;
+
+ HalpWriteEagleUlong(0x800000A8, EagleRegA8.u.AsUlong);
+ HalpWriteEagleUlong(0x800000AC, EagleRegAC.u.AsUlong);
+
+ switch (L2_Cache_Size) {
+
+ case 256:
+ OemDisplayString("256 KB");
+ break;
+
+ case 512:
+ OemDisplayString("512 KB");
+ break;
+
+ case 1024:
+ OemDisplayString("1 MB");
+ break;
+
+ default:
+ OemDisplayString("an invalid configuration. Pattern = ");
+ HalpDisplayHex32(L2_Cache_Size, CharBuffer);
+ OemDisplayString(CharBuffer);
+ PCR->SecondLevelDcacheSize = PCR->SecondLevelDcacheSize = 0;
+ return;
+ }
+
+ //
+ // Display cache mode and timing
+ //
+ if (Mode == WriteBack)
+ OemDisplayString(" (write-back ");
+ else
+ OemDisplayString(" (write-through ");
+
+ CharBuffer[0] = (UCHAR) EagleRegAC.u.EagleAC.CF_L2_HIT_DELAY + '2';
+ CharBuffer[1] = '\0';
+ OemDisplayString(CharBuffer);
+ if (EagleRegAC.u.EagleAC.CF_BURST_RATE)
+ OemDisplayString("-2-2-2)\n");
+ else
+ OemDisplayString("-1-1-1)\n");
+
+ return;
+}
+
+
+
+ULONG HalpSizeL2Cache()
+{ EAGLEAC EagleRegAC;
+ EAGLEA8 EagleRegA8;
+ CPU_TYPE CpuType;
+
+ long BridgeChipId;
+
+ BridgeChipId = HalpReadEagleUshort(0x80000002);
+
+ //
+ // For non-EAGLE chips, firmware has set up the L2 cache size in
+ // the config block and NT Kernel has copied this info into PCR
+ // structure. So, no work needs to be done, retrieve the size from PCR
+ //
+ if (BridgeChipId != EAGLECHIPID)
+ return( (PCR->SecondLevelIcacheSize >> 10) );
+
+ //
+ // Set some fields in Eagle Register 0xA8
+ //
+ EagleRegA8.u.AsUlong = HalpReadEagleUlong(0x800000A8);
+
+ CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16);
+ switch (CpuType) {
+
+ case MPC603:
+ case MPC603e:
+ EagleRegA8.u.EagleA8.PROC_TYPE = 2;
+ EagleRegA8.u.EagleA8.CF_BREAD_WS = 1;
+ break;
+
+ case MPC604:
+ case MPC604e:
+ EagleRegA8.u.EagleA8.PROC_TYPE = 3;
+ EagleRegA8.u.EagleA8.CF_BREAD_WS = 0;
+ break;
+
+ default:
+ return 0; // This HAL doesn't work with this processor
+ }
+
+ HalpWriteEagleUlong(0x800000A8, EagleRegA8.u.AsUlong);
+
+ EagleRegAC.u.AsUlong = HalpReadEagleUlong(0x800000AC);
+ EagleRegAC.u.EagleAC.CF_MOD_HIGH = 1;
+ HalpWriteEagleUlong(0x800000AC, EagleRegAC.u.AsUlong);
+
+ return ( HalpSizeL2());
+}
+
+
+
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ )
+
+{ ULONG j;
+ USHORT CpuRevision;
+ CPU_TYPE CpuType;
+ UCHAR EagleRevision, c;
+ UCHAR CharBuffer[20], i;
+
+ long BridgeChipId;
+
+ switch (HalpSystemType) {
+
+ case MOTOROLA_BIG_BEND:
+ HalDisplayString("\nHAL: Motorola Big Bend System");
+ break;
+
+ case MOTOROLA_POWERSTACK:
+// HalDisplayString("\nHAL: Motorola PowerStack System");
+ break;
+
+ case SYSTEM_UNKNOWN:
+ default:
+ HalDisplayString("\nHAL: WARNING : UNKNOWN SYSTEM TYPE\n");
+ break;
+
+ }
+
+ OemDisplayString("\nHAL: Version 2.37 5/24/96.");
+
+ CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16);
+ CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF);
+
+ OemDisplayString("\nHAL: Processor is a 60");
+ i = 0;
+ switch (CpuType) {
+ case MPC601:
+ case MPC603:
+ case MPC604:
+ CharBuffer[i++] = (UCHAR)(CpuType) + '0';
+ break;
+
+ case MPC603e:
+ CharBuffer[i++] = '3';
+ CharBuffer[i++] = 'e';
+ break;
+
+ case MPC604e:
+ CharBuffer[i++] = '4';
+ CharBuffer[i++] = 'e';
+ break;
+
+ default:
+ CharBuffer[i++] = '?';
+ break;
+ }
+ CharBuffer[i] = '\0';
+ OemDisplayString(CharBuffer);
+
+ OemDisplayString(" revision ");
+ i = 0;
+ c = (UCHAR)((CpuRevision >> 8) & 0xf);
+ CharBuffer[i++] = c + '0';
+ CharBuffer[i++] = '.';
+ if (c = (UCHAR)((CpuRevision >> 4) & 0xf))
+ CharBuffer[i++] = c + '0';
+ c = (UCHAR)(CpuRevision & 0xf);
+ if (CpuType == MPC604 && c == 0) { // 604 v3.01
+ CharBuffer[i++] = '0';
+ CharBuffer[i++] = '1';
+ } else {
+ CharBuffer[i++] = c + '0';
+ }
+ CharBuffer[i] = '\0';
+ OemDisplayString(CharBuffer);
+
+
+ BridgeChipId = HalpReadEagleUshort(0x80000002);
+
+ if (BridgeChipId == EAGLECHIPID)
+ OemDisplayString("\nHAL: Eagle Revision");
+ else
+ OemDisplayString("\nHAL: Bridge Chip Revision");
+
+ i = 0;
+ EagleRevision = HalpReadEagleUchar(0x80000008);
+ CharBuffer[i++] = ' ';
+ CharBuffer[i++] = (UCHAR) (EagleRevision >> 4) + '0';
+ CharBuffer[i++] = '.';
+ CharBuffer[i++] = (UCHAR) (EagleRevision & 0x0F) + '0';
+ CharBuffer[i++] = '\n';
+ CharBuffer[i] = '\0';
+ OemDisplayString(CharBuffer);
+
+ return TRUE;
+}
+
+
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the interrupt acknowledge and error address
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, then a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map interrupt control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = INTERRUPT_PHYSICAL_BASE;
+ HalpInterruptBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ if (HalpInterruptBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+
+
+}
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, then a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Map the PCI config space.
+ //
+
+ physicalAddress.LowPart = PCI_CONFIG_PHYSICAL_BASE;
+ HalpPciConfigBase = MmMapIoSpace(physicalAddress, HalpPciConfigSize, FALSE);
+ if (HalpPciConfigBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ )
+
+{
+
+ UCHAR StatusByte;
+ ULONG ErrorAddress;
+ UCHAR TextAddress[11];
+ USHORT EagleRegister, Byte;
+
+ EagleRegister = HalpReadEagleUshort(0x80000006);
+ if (EagleRegister & 0x8100)
+ HalDisplayString("\nEAGLE Status Register: PARITY Error Detected.");
+ if (EagleRegister & 0x4000)
+ HalDisplayString("\nEAGLE Status Register: SERR asserted.");
+
+// MOTKJR 08/22/95 - Don't check for the following bit.
+// It is always set when NT scans the slots on the PCI bus.
+// if (EagleRegister & 0x2000)
+// HalDisplayString("\nEAGLE Status Register: Transaction terminated with master-abort.");
+
+ if (EagleRegister & 0x1000)
+ HalDisplayString("\nEAGLE Status Register: Transaction terminated by target-abort while master.");
+ if (EagleRegister & 0x0800)
+ HalDisplayString("\nEAGLE Status Register: Transaction terminated by target-abort while slave.");
+
+ //
+ // Check Memory Error Detection Register 2
+ //
+ StatusByte = HalpReadEagleUchar(0x800000C5);
+
+ if (StatusByte & 0x10) {
+ HalDisplayString ("\nEAGLE Error Detection Register 2: L2 Parity Error Detected");
+ }
+
+ if (StatusByte & 0x80) {
+ // HalDisplayString ("\nEAGLE Error Detection Register 2: Invalid Error Address");
+#if DBG
+ //
+ // We have had a catastrophic hardware malfunction.
+ // Dump the state of the Eagle and HID 0 registers.
+ //
+ HalDisplayString("\n");
+ HalpDumpHardwareState();
+#endif
+ return;
+ }
+
+ //
+ // Read the error address register first
+ //
+ ErrorAddress = HalpReadEagleUlong(0x800000C8);
+ //
+ // Convert error address to HEX characters
+ //
+ HalpDisplayHex32(ErrorAddress, TextAddress);
+ TextAddress[ 8] = '.';
+ TextAddress[ 9] = '\0';
+ TextAddress[10] = '\0';
+
+
+ //
+ // Check Memory Error Detection Register 1
+ //
+
+ StatusByte = HalpReadEagleUchar(0x800000C1);
+
+ if (StatusByte & 0x08) {
+ HalDisplayString("\nEAGLE: PCI initiated Cycle.");
+ } else {
+ HalDisplayString("\nEAGLE: CPU initiated Cycle.");
+ }
+
+ if (StatusByte & 0xC0) {
+ HalDisplayString ("\nEAGLE: PCI ");
+ if (StatusByte & 0x80)
+ HalDisplayString ("SERR");
+ else
+ HalDisplayString ("target PERR");
+ HalDisplayString (" signaled at address ");
+ HalDisplayString (TextAddress);
+ }
+
+ if (StatusByte & 0x24) {
+ HalDisplayString ("\nEAGLE: Memory ");
+ if (StatusByte & 0x20)
+ HalDisplayString ("Select");
+ else
+ HalDisplayString ("Read Parity");
+ HalDisplayString (" error at address ");
+ HalDisplayString (TextAddress);
+ }
+
+#if DBG
+ //
+ // We have had a catastrophic hardware malfunction.
+ // Dump the state of the Eagle and HID 0 registers.
+ //
+ HalDisplayString("\n");
+ HalpDumpHardwareState();
+#endif
+}
+
+
+VOID HalpEnableEagleSettings(VOID)
+{
+ ULONG EagleRegister, UseFirmwareSettings;
+ volatile ULONG FakeVectorFetch;
+ USHORT CpuRevision;
+ EAGLEC0 ErrorEnable1;
+ CPU_TYPE CpuType;
+ UCHAR EagleRevision;
+ UCHAR CharBuffer[BUF_LEN], *Value;
+ BOOLEAN Negate;
+
+ long BridgeChipId;
+
+#define SetEagleUcharC0( Clear, Val ) \
+ SetEagleReg(Clear, 0x800000C0, Val, HalpReadEagleRegC0, HalpWriteEagleUchar);
+
+#define SetEagleUchar( Clear, Offset, Val ) \
+ SetEagleReg(Clear, Offset, Val, HalpReadEagleUchar, HalpWriteEagleUchar);
+
+#define SetEagleUshort( Clear, Offset, Val ) \
+ SetEagleReg(Clear, Offset, Val, HalpReadEagleUshort, HalpWriteEagleUshort);
+
+#define SetEagleUlong( Clear, Offset, Val ) \
+ SetEagleReg(Clear, Offset, Val, HalpReadEagleUlong, HalpWriteEagleUlong);
+
+#define SetEagleReg( Clear, Offset, Val, GetReg, SetReg) \
+{ \
+ if (Clear) { \
+ SetReg(Offset, GetReg(Offset) & ~Val); \
+ } else { \
+ SetReg(Offset, GetReg(Offset) | Val); \
+ } \
+}
+
+ CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16);
+ CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF);
+ EagleRevision = HalpReadEagleUchar(0x80000008);
+ UseFirmwareSettings = FALSE;
+
+ //
+ // Adjust default settings for any known chip bugs or anomalies here.
+ // Eagle revision 2.1 has funny bits in Register C0.
+ //
+
+ //
+ // If the bridge chip is not Eagle then set the revision number to 0x24
+ // Currently the sister chip grackle is the only one supported by this
+ // code and it is equivalent to Eagle revision 0x24
+ //
+ BridgeChipId = HalpReadEagleUshort(0x80000002);
+ if (BridgeChipId != EAGLECHIPID)
+ EagleRevision = 0x24;
+
+
+ if (EagleRevision == 0x21)
+ HalpReadEagleRegC0 = HalpReadEagleC0;
+ else
+ HalpReadEagleRegC0 = HalpReadEagleUchar;
+
+
+ //
+ // Set Address and Data Park bits in Eagle.
+ // These particular bits are not "parity" related.
+ //
+ HalpWriteEagleUlong(0x800000A8, HalpReadEagleUlong(0x800000A8) | 0x208);
+
+ //
+ // Setup and initialize the default EAGLE Parity Checking.
+ // This default is platform dependent.
+ //
+
+ switch (HalpSystemType) {
+ case MOTOROLA_POWERSTACK:
+ //
+ // PowerStack Systems will initialize EAGLE Parity Checking
+ // settings at the Boot ROM or ARC Firmware level. Use these
+ // EAGLE settings if they are present, otherwise use defaults.
+ //
+ UseFirmwareSettings = ((HalpReadEagleUlong(0x800000F0) & PCKEN) &&
+ (HalpReadEagleRegC0(0x800000C0) & MRPE));
+ if (UseFirmwareSettings)
+ break;
+
+ HalpWriteEagleUchar(0x800000C4, 0x10); // Enable L2 Parity Checking.
+ // fall-through to default
+
+ default:
+
+ //
+ // Enable parity checking in Eagle chip
+ //
+ ErrorEnable1.u.AsUchar = 0;
+ ErrorEnable1.u.EagleC0.PCI_TARGET_ABORT = 1;
+ ErrorEnable1.u.EagleC0.MEM_SELECT_ERROR = 1;
+ ErrorEnable1.u.EagleC0.MEM_READ_PARITY = 1;
+ HalpWriteEagleUchar(0x800000C0, ErrorEnable1.u.AsUchar);
+
+ if (EagleRevision >= 0x22) {
+ //
+ // NT must be loaded with the PCKEN bit enabled. Check PCKEN to make
+ // sure it is enabled. If it is not enabled, then don't enable parity
+ // checking since parity errors will be found all over memory.
+ //
+ EagleRegister = HalpReadEagleUlong(0x800000F0);
+ if (EagleRegister & PCKEN) {
+
+ //
+ // Enable parity checking in Eagle chip
+ //
+ ErrorEnable1.u.EagleC0.LOCAL_BUS = 1;
+ HalpWriteEagleUchar(0x800000C0, ErrorEnable1.u.AsUchar);
+
+ //
+ // Enable SERR checking in the Command register.
+ //
+ EagleRegister = HalpReadEagleUshort(0x80000004);
+ HalpWriteEagleUshort(0x80000004, (USHORT)(EagleRegister | 0x100)); // SERR only.
+
+ //
+ // Conditionally enable Machine Check in the Eagle.
+ // Systems with IBM 604 revision 3.2 & 3.3 parts have problems
+ // with parity. Motorola parts are OK. It would be great if we
+ // could tell them apart (one from the other), but we can't. So,
+ // don't enable internal Cache parity on this (or earlier) parts.
+ //
+ if ((CpuType != MPC604) || (CpuRevision >= 0x0304)) {
+ EagleRegister = HalpReadEagleUlong(0x800000A8);
+ HalpWriteEagleUlong(0x800000A8, EagleRegister | MCP_EN);
+ }
+ }
+ }
+ }
+
+
+ //
+ // The environment variable "EAGLESETTINGS" is defined as:
+ // Matching a string serves to enable that feature while a tilde (~)
+ // immediately before the parameter string indicates that it is to be disabled.
+ //
+
+ if ( HalGetEnvironmentVariable("EAGLESETTINGS", BUF_LEN, &CharBuffer[0]) == ESUCCESS ) {
+
+ for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, ":;,") ) {
+
+ Negate = FALSE;
+
+ if (*Value == NEGATECHAR) {
+ Value++;
+ Negate = TRUE;
+ }
+
+ if (HalpStrCmp("MCP_EN", Value) || HalpStrCmp("MCP", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, MCP_EN );
+
+ } else if (HalpStrCmp("TEA_EN", Value) || HalpStrCmp("TEA", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, 0x400 );
+
+ } else if (HalpStrCmp("DPARK", Value) || HalpStrCmp("CF_DPARK", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, 0x200 );
+
+ } else if (HalpStrCmp("GATHERING", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, 0x040 );
+
+ } else if (HalpStrCmp("CF_LOOP_SNOOP", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, 0x010 );
+
+ } else if (HalpStrCmp("APARK", Value) || HalpStrCmp("CF_APARK", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, 0x008 );
+
+ } else if (HalpStrCmp("SPECULATIVE", Value)) {
+ SetEagleUlong( Negate, 0x800000A8, 0x004 );
+
+ } else if (HalpStrCmp("L2_PARITY", Value) || HalpStrCmp("L2", Value)) {
+ SetEagleUchar( Negate, 0x800000C4, 0x10 );
+
+ } else if (HalpStrCmp("PCKEN", Value)) {
+ SetEagleUlong( Negate, 0x800000F0, PCKEN );
+
+ } else if (HalpStrCmp("SERR", Value)) {
+ SetEagleUshort( Negate, 0x80000004, 0x100 );
+
+ } else if (HalpStrCmp("RX_SERR_EN", Value) || HalpStrCmp("RX_SERR", Value)) {
+ SetEagleUchar( Negate, 0x800000BA, 0x20 );
+
+ } else if (HalpStrCmp("TARGET_ABORT", Value)) {
+ SetEagleUcharC0( Negate, 0x80 );
+
+ } else if (HalpStrCmp("SLAVE_PERR", Value)) {
+ SetEagleUcharC0( Negate, 0x40 );
+ SetEagleUshort( Negate, 0x80000004, 0x040 );
+
+ } else if (HalpStrCmp("SELECT_ERROR", Value) || HalpStrCmp("SELECT", Value)) {
+ SetEagleUcharC0( Negate, 0x20 );
+
+ } else if (HalpStrCmp("MASTER_PERR", Value)) {
+ SetEagleUcharC0( Negate, 0x10 );
+ SetEagleUshort( Negate, 0x80000004, 0x040 );
+
+ } else if (HalpStrCmp("DRAM", Value) || HalpStrCmp("READ", Value) || HalpStrCmp("MEMORY", Value)) {
+ SetEagleUcharC0( Negate, MRPE );
+
+ } else if (HalpStrCmp("MASTER_ABORT", Value)) {
+ SetEagleUcharC0( Negate, 0x02 );
+
+ } else if (HalpStrCmp("LOCAL_ERROR", Value) || HalpStrCmp("LOCAL", Value)) {
+ SetEagleUcharC0( Negate, 0x01 );
+
+ //
+ // Enabling (or disabling) EAGLE parity by listing
+ // all of the individual bits was too complicated.
+ // For simplicity, we will define one pseudo-bit
+ // called "PARITY". This will set (or clear) all
+ // of the individual parity bits for EAGLE platforms.
+ //
+ } else if (HalpStrCmp("PARITY", Value)) {
+ // Conditionally turn on L2 checking.
+ if (HalpSystemType == MOTOROLA_POWERSTACK) {
+ SetEagleReg( Negate, 0x800000C4, 0x10, HalpReadEagleUchar, HalpWriteEagleUchar );
+ }
+
+ // Set or Clear the PCKEN bit.
+ SetEagleReg( Negate, 0x800000F0, PCKEN, HalpReadEagleUlong, HalpWriteEagleUlong );
+
+ // Set or Clear parity checking in Eagle chip
+ SetEagleUcharC0( Negate, 0xA5 );
+
+ // Set or Clear the SERR bit in the Command register.
+ SetEagleReg( Negate, 0x80000004, 0x100, HalpReadEagleUshort, HalpWriteEagleUshort );
+
+ // Set or Clear the MCP_EN last.
+ SetEagleReg( Negate, 0x800000A8, MCP_EN, HalpReadEagleUlong, HalpWriteEagleUlong );
+
+ } else if (HalpStrCmp("CF_ADDR_ONLY_DISABLE", Value)) {
+ SetEagleUlong( Negate, 0x800000AC, 0x4000);
+ } else if (HalpStrCmp("CF_BURST_RATE", Value)) {
+ SetEagleUlong( Negate, 0x800000AC, 0x0100);
+ } else if (HalpStrCmp("CF_FAST_CASTOUT", Value)) {
+ SetEagleUlong( Negate, 0x800000AC, 0x0080);
+ } else if (HalpStrCmp("CF_TOE_WIDTH", Value)) {
+ SetEagleUlong( Negate, 0x800000AC, 0x0040);
+ } else if (HalpStrCmp("CF_DOE", Value)) {
+ SetEagleUlong( Negate, 0x800000AC, 0x0002);
+ } else if (HalpStrCmp("CF_WDATA", Value)) {
+ SetEagleUlong( Negate, 0x800000AC, 0x0001);
+
+ } else {
+ HalDisplayString( "HAL: Error in EAGLESETTINGS environment variable: ");
+ HalDisplayString(CharBuffer);
+ HalDisplayString("^\n");
+ }
+ } // End for
+ } // End If
+
+ //
+ // Initialize the PowerPC HID0 register here,
+ // before we clear the detection bits in the EAGLE.
+ // Otherwise we can miss the MCP pin signal transition.
+ //
+ HalpEnable_HID0_Settings(UseFirmwareSettings);
+
+ //
+ // Clear any detection bits that may have been set while enabling L2 cache.
+ // The Eagle does not clear the MCP_ signal until it sees a fetch from
+ // the Machine Check vector. So, we must simulate a vector fetch.
+ //
+ FakeVectorFetch = *((volatile PULONG)(0x80000200)); // Clear the EAGLE MCP_ signal if it is set.
+ HalpWriteEagleUchar(0x800000C1, 0xFF); // Clear Error Detection Register 1.
+ HalpWriteEagleUchar(0x800000C5, 0xFF); // Clear Error Detection Register 2.
+ EagleRegister = HalpReadEagleUshort(0x80000006); // Get any Un-documented Status bits.
+ HalpWriteEagleUshort(0x80000006, 0xF900 | (USHORT)(EagleRegister)); // Clear Status Register Bits.
+ FakeVectorFetch = *((volatile PULONG)(0x80000200)); // Clear the EAGLE MCP_ signal if it is set.
+
+ //
+ // Print this message last to confirm everything is working.
+ //
+
+}
+
+VOID HalpEnable_HID0_Settings(ULONG UseDefaultsHidSettings)
+{
+ ULONG EagleRegister;
+ USHORT CpuRevision;
+ CPU_TYPE CpuType;
+ UCHAR EagleRevision;
+ UCHAR CharBuffer[BUF_LEN], *Value;
+ ULONG HidEnable, HidDisable, CurrentHID0;
+ BOOLEAN Negate;
+
+ long BridgeChipId;
+
+#define HID0_MCP (0x80000000)
+#define HID0_CACHE (0x40000000)
+#define HID0_ADDRESS (0x20000000)
+#define HID0_DATA (0x10000000)
+#define HID0_PAR (0x01000000)
+#define HID0_DPM (0x00100000)
+#define HID0_ILOCK (0x00002000)
+#define HID0_DLOCK (0x00001000)
+#define HID0_FBIOB (0x00000010)
+#define HID0_BHT (0x00000004)
+
+#define SetCPUMask( Disable, Val ) \
+{ \
+ if (Disable) \
+ HidDisable |= Val; \
+ else \
+ HidEnable |= Val; \
+}
+
+ CpuType = (CPU_TYPE)(HalpGetProcessorVersion() >> 16);
+ CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF);
+
+ EagleRevision = HalpReadEagleUchar(0x80000008);
+
+ //
+ // If the bridge chip is not Eagle then set the revision number to 0x24
+ // Currently the sister chip grackle is the only one supported by this
+ // code and it is equivalent to Eagle revision 0x24
+ //
+ BridgeChipId = HalpReadEagleUshort(0x80000002);
+ if (BridgeChipId != EAGLECHIPID)
+ EagleRevision = 0x24;
+
+
+ HidEnable = 0;
+ HidDisable = 0;
+ CurrentHID0 = HalpGetHID0();
+
+ switch (CpuType) {
+ case MPC603e:
+ if (CpuRevision <= 0x102) {
+ //
+ // Disable Dynamic Power Management on 603e revisions 1.1 & 1.2
+ // 603e revisions 1.1 and 1.2 have errata w.r.t DPM.
+ //
+ CurrentHID0 &= ~HID0_DPM;
+ break;
+ }
+ // else fall through to 603
+
+ case MPC603:
+ //
+ // Enable Dynamic Power Management
+ //
+ CurrentHID0 |= HID0_DPM;
+ }
+
+ //
+ // Set the default CPU Parity Checking.
+ // This default is platform dependent.
+ //
+
+ switch (HalpSystemType) {
+ case MOTOROLA_POWERSTACK:
+ //
+ // PowerStack Systems will initialize HID0 Parity Checking
+ // settings at the Boot ROM or ARC Firmware level. Use these
+ // HID0 settings if they are present, otherwise use defaults.
+ //
+ if (UseDefaultsHidSettings) {
+ // Just enable the Machine Check Pin.
+ // Hopefully, everything else has been setup.
+ CurrentHID0 |= (HID0_MCP);
+ break;
+ }
+ // fall-through to default
+
+ default:
+ CurrentHID0 &= ~(HID0_MCP | HID0_DATA | HID0_CACHE | HID0_ADDRESS);
+
+ //
+ // Systems with IBM 604 revision 3.3 & 3.2 parts have problems with
+ // L1 parity checking. Motorola parts are OK, but we can't tell
+ // Motorola parts from IBM. So, don't enable L1 cache parity checking
+ // on 604 v3.3 or v3.2 parts.
+ switch (CpuType) {
+ case MPC604:
+ if (CpuRevision == 0x303 || CpuRevision == 0x302)
+ break;
+ // else fall through and enable Cache Parity
+ case MPC604e:
+ CurrentHID0 |= (HID0_CACHE);
+ // fall through
+ default:
+ break;
+ }
+
+ //
+ // Set up the default Parity Checking. No checking prior to Eagle 2.2.
+ // NT must be loaded with the PCKEN bit enabled. Check PCKEN to make
+ // sure it is enabled. If it is not enabled, then don't enable parity
+ // checking since parity errors will be found all over memory.
+ //
+
+ EagleRegister = HalpReadEagleUlong(0x800000F0);
+ if ((EagleRevision >= 0x22) && (EagleRegister & PCKEN)) {
+ //
+ // Systems with IBM 604 revision 3.3 parts have problems with
+ // parity generation. Motorola parts are OK. It would be great
+ // if we could tell them apart (one from the other), but we can't.
+ // So don't enable data parity checking on this (or earlier) parts.
+ //
+ if ((CpuType != MPC604) || (CpuRevision >= 0x0304))
+ CurrentHID0 |= (HID0_MCP | HID0_DATA);
+ }
+ break;
+ }
+
+ //
+ // The environment variable "HID0SETTINGS" is defined either as:
+ // "CACHE", "ADDRESS", "DATA", "MCP", "DPM" with either blank or semi-colon
+ // characters used as separators. Matching a string serves to enable
+ // that feature while a tilde (~) immediately before the parameter
+ // string indicates that it is to be disabled.
+ //
+
+ if (HalGetEnvironmentVariable("HID0SETTINGS", BUF_LEN, &CharBuffer[0]) == ESUCCESS) {
+ for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, ":;,") ) {
+
+ Negate = FALSE;
+
+ if (*Value == NEGATECHAR) {
+ Value++;
+ Negate = TRUE;
+ }
+
+ if (HalpStrCmp("MCP", Value)) {
+ SetCPUMask(Negate, HID0_MCP);
+ } else if (HalpStrCmp("ADDRESS", Value)) {
+ SetCPUMask(Negate, HID0_ADDRESS);
+ } else if (HalpStrCmp("DATA", Value)) {
+ SetCPUMask(Negate, HID0_DATA);
+ } else if (HalpStrCmp("PAR", Value)) {
+ SetCPUMask(Negate, HID0_PAR);
+ } else if (HalpStrCmp("ILOCK", Value)) {
+ SetCPUMask(Negate, HID0_ILOCK);
+ } else if (HalpStrCmp("DLOCK", Value)) {
+ SetCPUMask(Negate, HID0_DLOCK);
+ } else {
+ switch (CpuType) {
+ case MPC604:
+ case MPC604e:
+ if (HalpStrCmp("BHT", Value)) {
+ SetCPUMask(Negate, HID0_BHT);
+ continue;
+ }
+ if (HalpStrCmp("CACHE", Value)) {
+ SetCPUMask(Negate, HID0_CACHE);
+ continue;
+ }
+ break;
+
+ case MPC603:
+ case MPC603e:
+ if (HalpStrCmp("DPM", Value)) {
+ SetCPUMask(Negate, HID0_DPM);
+ continue;
+ }
+ if (HalpStrCmp("FBIOB", Value)) {
+ SetCPUMask(Negate, HID0_FBIOB);
+ continue;
+ }
+ break;
+
+
+ } // End switch
+
+ HalDisplayString("HAL: Error in HID0SETTINGS environment variable: ");
+ HalDisplayString(CharBuffer);
+ HalDisplayString("\n");
+ } // End else
+
+ } // End for
+ } // End if
+
+ //
+ // Check for inconsistencies in HID0SETTINGS
+ //
+ if (HidEnable & HidDisable) {
+ HalDisplayString("HAL: Inconsistent settings in HID0SETTINGS environment variable.\n");
+ HalDisplayString(" Disable setting will override enable setting.\n");
+ //
+ // Enforce DISABLE override ENABLE
+ //
+ HidEnable &= ~HidDisable;
+ }
+
+ //
+ // Disable and Enable the bits in the HID0 register.
+ //
+ CurrentHID0 &= ~HidDisable; // Disable bits first.
+ HalpSetHID0(CurrentHID0);
+
+ CurrentHID0 |= HidEnable; // Enable Bits last.
+ HalpSetHID0(CurrentHID0);
+
+ //
+ // Print this message last to confirm everything is working.
+ //
+
+}
+
+
+VOID HalpCheckHardwareRevisionLevels(VOID)
+{
+ ULONG EagleRegister, i;
+ USHORT CpuRevision;
+ CPU_TYPE CpuType;
+ UCHAR EagleRevision;
+ ARC_STATUS Status;
+ UCHAR Buffer[10];
+
+ long BridgeChipId;
+
+ i = HalpGetProcessorVersion();
+ CpuType = (CPU_TYPE)(i >> 16);
+ CpuRevision = (USHORT)(i & 0xFFFF);
+
+ EagleRevision = HalpReadEagleUchar(0x80000008);
+ //
+ // Minimum hardware requirements:
+ // Eagle: v2.1 or greater
+ // 603 or 604: v3.2 or greater
+ // 603e or 604e: any CPU revision
+ //
+
+ //
+ // If the bridge chip is not Eagle then set the revision number to 0x24
+ // Currently the sister chip grackle is the only one supported by this
+ // code and it is equivalent to Eagle revision 0x24
+ //
+ BridgeChipId = HalpReadEagleUshort(0x80000002);
+ if (BridgeChipId != EAGLECHIPID)
+ EagleRevision = 0x24;
+
+
+ if (EagleRevision >= 0x21) {
+ switch (CpuType) {
+ case MPC603:
+ case MPC604:
+ if (CpuRevision >= 0x0302)
+ return;
+ else
+ break;
+
+ default:
+ return;
+ }
+ }
+
+ // If the environment variable BOOTOLDHARDWARE exists (value is
+ // a don't care), then try to boot anyway.
+ Status = HalGetEnvironmentVariable("BOOTOLDHARDWARE", 5, Buffer);
+ if (Status == ESUCCESS || Status == ENOMEM)
+ return;
+
+ HalDisplayString("\nHAL: Unsupported CPU and/or EAGLE revision level. Set the\n");
+ HalDisplayString(" environment variable BOOTOLDHARDWARE to any value to boot anyway.");
+
+ //
+ // Bug check - after stalling to allow
+ // any information printed on the screen
+ // to be read and seen by the user.
+ //
+ HalDisplayString("\n");
+ for (i=0; i<12; i++) {
+ HalDisplayString(".");
+ KeStallExecutionProcessor(1000000);
+ }
+
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ return;
+}
+
+
+
+VOID HalpDumpHardwareState(VOID)
+{ ULONG EagleRegister, HID0;
+ UCHAR CharBuffer[12];
+
+#if DBG
+
+ if ( HalGetEnvironmentVariable("DBG_HAL", BUF_LEN, &CharBuffer[0]) == ESUCCESS ) {
+
+ EagleRegister = HalpReadEagleUshort(0x80000004);
+ HalDisplayString("HAL: Eagle register 04 = 0x");
+ HalpDisplayHex16(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUshort(0x80000006);
+ HalDisplayString("HAL: Eagle register 06 = 0x");
+ HalpDisplayHex16(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUlong(0x800000A8);
+ HalDisplayString("HAL: Eagle register A8 = 0x");
+ HalpDisplayHex32(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUlong(0x800000AC);
+ HalDisplayString("HAL: Eagle register AC = 0x");
+ HalpDisplayHex32(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUchar(0x800000C0);
+ HalDisplayString("HAL: Eagle register C0 = 0x");
+ HalpDisplayHex8(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUchar(0x800000C1);
+ HalDisplayString("HAL: Eagle register C1 = 0x");
+ HalpDisplayHex8(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUchar(0x800000C3);
+ HalDisplayString("HAL: Eagle register C3 = 0x");
+ HalpDisplayHex8(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUchar(0x800000C4);
+ HalDisplayString("HAL: Eagle register C4 = 0x");
+ HalpDisplayHex8(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUchar(0x800000C5);
+ HalDisplayString("HAL: Eagle register C5 = 0x");
+ HalpDisplayHex8(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUchar(0x800000C7);
+ HalDisplayString("HAL: Eagle register C7 = 0x");
+ HalpDisplayHex8(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ EagleRegister = HalpReadEagleUlong(0x800000C8);
+ HalDisplayString("HAL: Eagle register C8 = 0x");
+ HalpDisplayHex32(EagleRegister, CharBuffer );
+ HalDisplayString(CharBuffer);
+
+ HID0 = HalpGetHID0();
+ HalDisplayString("HAL: PowerPC Register HID0 = 0x");
+ HalpDisplayHex32(HID0, CharBuffer );
+ HalDisplayString(CharBuffer);
+ }
+
+#endif
+
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxmemctl.h b/private/ntos/nthals/haleagle/ppc/pxmemctl.h
new file mode 100644
index 000000000..25f180ea6
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxmemctl.h
@@ -0,0 +1,45 @@
+/*++ 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:
+
+--*/
+
+
+//
+// define physical base addresses of planar
+//
+
+#define INTERRUPT_PHYSICAL_BASE 0xbffffff0 // physical base of interrupt source
+#define ERROR_ADDRESS_REGISTER 0xbfffeff0
+
+#define IO_CONTROL_PHYSICAL_BASE 0x80000000 // physical base of IO control
+#define SYSTEM_IO_CONTROL_SIZE 0x00008000
+
+
+typedef struct _PLANAR_CONTROL {
+ UCHAR Reserved[0xcf8];
+
+ ULONG ConfigAddress; // 0xcf8
+ ULONG ConfigData; // 0xcfc
+
+} PLANAR_CONTROL, *PPLANAR_CONTROL;
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxmisc.s b/private/ntos/nthals/haleagle/ppc/pxmisc.s
new file mode 100644
index 000000000..8e3b58ac7
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxmisc.s
@@ -0,0 +1,183 @@
+//++
+//
+// 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)
+
+
+
+
+// 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.
+//
+// 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 Quotient,DividendLo,Divisor // Quotient = 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 dividend
+ mr r.8, DividendLo // Save unshifted DividendLo
+ slw DividendLo,DividendLo,N // shift lower part of dividend
+ 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)
+
+
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxpcibrd.c b/private/ntos/nthals/haleagle/ppc/pxpcibrd.c
new file mode 100644
index 000000000..91ef86864
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxpcibrd.c
@@ -0,0 +1,544 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxpcibrd.c
+
+Abstract:
+
+ Get PCI-PCI bridge information
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "stdio.h"
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzReservedResources[];
+
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+#else
+#define DBGMSG(a)
+#endif
+
+
+
+#define IsPciBridge(a) \
+ (a->VendorID != PCI_INVALID_VENDORID && \
+ PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
+ a->SubClass == 4 && a->BaseClass == 6)
+
+
+typedef struct {
+ ULONG BusNo;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG IO, Memory, PFMemory;
+ UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
+} CONFIGBRIDGE, *PCONFIGBRIDGE;
+
+//
+// Internal prototypes
+//
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG Base,
+ IN ULONG Limit
+ );
+
+
+ULONG
+HalpGetBridgedPCIInterrupt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetBridgedPCIISAInt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetBridgedPCIIrqTable (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ );
+
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetPciBridgeConfig)
+#pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk)
+#pragma alloc_text(INIT,HalpFixupPciSupportedRanges)
+#endif
+
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ )
+/*++
+
+Routine Description:
+
+ Scan the devices on all known pci buses trying to locate any
+ PCI to PCI bridges. Record the hierarchy for the buses, and
+ which buses have what addressing limits.
+
+Arguments:
+
+ HwType - Configuration type.
+ MaxPciBus - # of PCI buses reported by the bios
+
+--*/
+{
+ PBUS_HANDLER ChildBus;
+ PPCIPBUSDATA ChildBusData;
+ ULONG d, f, i, j, BusNo;
+ UCHAR Rescan;
+ BOOLEAN FoundDisabledBridge;
+ CONFIGBRIDGE CB;
+
+ Rescan = 0;
+ FoundDisabledBridge = FALSE;
+
+ //
+ // Find each bus on a bridge and initialize it's base and limit information
+ //
+
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ // next device
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge, next function
+ continue;
+ }
+
+ if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is not enabled - skip it for now
+ FoundDisabledBridge = TRUE;
+ continue;
+ }
+
+ if ((ULONG) CB.PciData->u.type1.PrimaryBus !=
+ CB.BusHandler->BusNumber) {
+
+ DBGMSG ("HAL GetPciData: bad primarybus!!!\n");
+ // what to do?
+ }
+
+ //
+ // Found a PCI-PCI bridge. Determine it's parent child relationships
+ //
+
+ ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus);
+ if (!ChildBus) {
+ DBGMSG ("HAL GetPciData: found configured PCI bridge\n");
+
+ // up the number of buses
+ if (CB.PciData->u.type1.SecondaryBus > Rescan) {
+ Rescan = CB.PciData->u.type1.SecondaryBus;
+ }
+ continue;
+ }
+
+ ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
+ if (ChildBusData->BridgeConfigRead) {
+ // this child buses relationships already processed
+ continue;
+ }
+
+ //
+ // Remember the limits which are programmed into this bridge
+ //
+
+ ChildBusData->BridgeConfigRead = TRUE;
+ HalpSetBusHandlerParent (ChildBus, CB.BusHandler);
+ ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber;
+ ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
+
+ ChildBus->BusAddresses->IO.Base =
+ PciBridgeIO2Base(
+ CB.PciData->u.type1.IOBase,
+ CB.PciData->u.type1.IOBaseUpper16
+ );
+
+ ChildBus->BusAddresses->IO.Limit =
+ PciBridgeIO2Limit(
+ CB.PciData->u.type1.IOLimit,
+ CB.PciData->u.type1.IOLimitUpper16
+ );
+
+ //
+ // Special VGA address remapping occuring on this bridge?
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ HalpSetPciBridgedVgaCronk (
+ ChildBus->BusNumber,
+ (ULONG) ChildBus->BusAddresses->IO.Base,
+ (ULONG) ChildBus->BusAddresses->IO.Limit
+ );
+ }
+
+ //
+ // If supported I/O ranges on this bus are limited to
+ // 256 bytes on every 1K aligned boundary within the
+ // range, then redo supported IO BusAddresses to match
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ // assume Base is 1K aligned
+ i = (ULONG) ChildBus->BusAddresses->IO.Base;
+ j = (ULONG) ChildBus->BusAddresses->IO.Limit;
+
+ // convert head entry
+ ChildBus->BusAddresses->IO.Limit = i + 256;
+ i += 1024;
+
+ // add remaining ranges
+ while (i < j) {
+ HalpAddRange (
+ &ChildBus->BusAddresses->IO,
+ 1, // address space
+ 0, // system base
+ i, // bus address
+ i + 256 // bus limit
+ );
+
+ // next range
+ i += 1024;
+ }
+ }
+
+ ChildBus->BusAddresses->Memory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase);
+
+ ChildBus->BusAddresses->Memory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit);
+
+ // On x86 it's ok to clip Prefetch to 32 bits
+
+ if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) {
+ ChildBus->BusAddresses->PrefetchMemory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase);
+
+
+ ChildBus->BusAddresses->PrefetchMemory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit);
+
+ if (CB.PciData->u.type1.PrefetchLimitUpper32) {
+ ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff;
+ }
+ }
+
+ // should call HalpAssignPCISlotResources to assign
+ // baseaddresses, etc...
+ }
+ }
+ }
+
+ if (Rescan) {
+ *MaxPciBus = Rescan;
+ return TRUE;
+ }
+
+ if (!FoundDisabledBridge) {
+ return FALSE;
+ }
+
+ DBGMSG ("HAL GetPciData: found disabled pci bridge\n");
+
+ return FALSE;
+}
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ )
+/*++
+
+Routine Description:
+
+ PCI-PCI bridged buses only see addresses which their parent
+ buses supports. So adjust any PCI SUPPORT_RANGES to be
+ a complete subset of all of it's parent buses.
+
+ PCI-PCI briges use postive address decode to forward addresses.
+ So, remove any addresses from any PCI bus which are bridged to
+ a child PCI bus.
+
+--*/
+{
+ ULONG i;
+ PBUS_HANDLER Bus, ParentBus;
+ PSUPPORTED_RANGES HRanges;
+
+ //
+ // Pass 1 - shrink all PCI supported ranges to be a subset of
+ // all of it's parent buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ HRanges = Bus->BusAddresses;
+ Bus->BusAddresses = HalpMergeRanges (
+ ParentBus->BusAddresses,
+ HRanges
+ );
+
+ HalpFreeRangeList (HRanges);
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Pass 2 - remove all child PCI bus ranges from parent PCI buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ if (ParentBus->InterfaceType == PCIBus) {
+ HalpRemoveRanges (
+ ParentBus->BusAddresses,
+ Bus->BusAddresses
+ );
+ }
+
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Cleanup
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+ HalpConsolidateRanges (Bus->BusAddresses);
+ }
+}
+
+
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG BaseAddress,
+ IN ULONG LimitAddress
+ )
+/*++
+
+Routine Description: .
+
+ The 'vga compatible addresses' bit is set in the bridge control register.
+ This causes the bridge to pass any I/O address in the range of: 10bit
+ decode 3b0-3bb & 3c0-3df, as TEN bit addresses.
+
+ As far as I can tell this "feature" is an attempt to solve some problem
+ which the folks solving it did not fully understand, so instead of doing
+ it right we have this fine mess.
+
+ The solution is to take the least of all evils which is to remove any
+ I/O port ranges which are getting remapped from any IoAssignResource
+ request. (ie, IoAssignResources will never contemplate giving any
+ I/O port out in the suspected ranges).
+
+ note: memory allocation error here is fatal so don't bother with the
+ return codes.
+
+Arguments:
+
+ Base - Base of IO address range in question
+ Limit - Limit of IO address range in question
+
+--*/
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ ULONG Length;
+ PCM_RESOURCE_LIST ResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG AddressMSBs;
+ WCHAR ValueName[80];
+ NTSTATUS status;
+
+ //
+ // Open reserved resource settings
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzReservedResources);
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ //
+ // Build resource list of reserved ranges
+ //
+
+ Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 *
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) +
+ sizeof (CM_RESOURCE_LIST);
+
+ ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, Length);
+ memset (ResourceList, 0, Length);
+
+ ResourceList->Count = 1;
+ ResourceList->List[0].InterfaceType = PCIBus;
+ ResourceList->List[0].BusNumber = BusNumber;
+ Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+
+ while (BaseAddress < LimitAddress) {
+ AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr
+
+ //
+ // Add xx3b0 through xx3bb
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0;
+ Descriptor->u.Port.Length = 0xb;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Add xx3c0 through xx3df
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0;
+ Descriptor->u.Port.Length = 0x1f;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Next range
+ //
+
+ BaseAddress += 1024;
+ }
+
+ //
+ // Add the reserved ranges to avoid during IoAssignResource
+ //
+
+ swprintf (ValueName, L"HAL_PCI_%d", BusNumber);
+ RtlInitUnicodeString (&unicodeString, ValueName);
+
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_RESOURCE_LIST,
+ ResourceList,
+ (ULONG) Descriptor - (ULONG) ResourceList
+ );
+
+
+ ExFreePool (ResourceList);
+ ZwClose (handle);
+}
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxpcibus.c b/private/ntos/nthals/haleagle/ppc/pxpcibus.c
new file mode 100644
index 000000000..a7f1f4b4f
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxpcibus.c
@@ -0,0 +1,2289 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxpcibus.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 "pxmemctl.h"
+#include "pxpcisup.h"
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+
+extern ULONG HalpPciMaxSlots;
+
+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;
+
+
+
+//
+// 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
+ }
+};
+
+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) DbgPrint(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)
+#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
+#endif
+
+
+
+VOID
+HalpInitializePciBus (
+ VOID
+ )
+{
+ PPCI_REGISTRY_INFO PCIRegInfo;
+ UNICODE_STRING unicodeString, ConfigName, IdentName;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE hMFunc, hBus;
+ NTSTATUS status;
+ 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)) {
+ 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);
+ return ;
+ }
+
+ //
+ // 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;
+ }
+ }
+
+ //
+ // 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;
+
+#if 0
+ //
+ // 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) {
+
+ //
+ // 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);
+ }
+#endif
+
+
+ //
+ // For each PCI bus present, allocate a handler structure and
+ // fill in the dispatch functions
+ //
+
+ do {
+ for (i=0; i < PCIRegInfo->NoBuses; i++) {
+
+ //
+ // If handler not already built, do it now
+ //
+
+ if (!HalpHandlerForBus (PCIBus, i)) {
+ HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
+ }
+ }
+
+ //
+ // Bus handlers for all PCI buses have been allocated, go collect
+ // pci bridge information.
+ //
+
+ } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
+
+ //
+ // Fixup SUPPORTED_RANGES
+ //
+
+ HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
+
+#if DBG
+ HalpTestPci (0);
+#endif
+}
+
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+
+ Bus = HalpAllocateBusHandler (
+ PCIBus, // Interface type
+ PCIConfiguration, // Has this configuration space
+ BusNo, // bus #
+ Internal, // child of this bus
+ 0, // and number
+ sizeof (PCIPBUSDATA) // sizeof bus specific buffer
+ );
+
+ //
+ // Fill in PCI handlers
+ //
+
+ Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
+ Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
+ Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
+ Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
+ Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
+ Bus->BusAddresses->Dma.Limit = 0;
+
+ BusData = (PPCIPBUSDATA) Bus->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;
+
+ //
+ // Set defaults
+ //
+
+ Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq;
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ // direct Method.
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+
+ BusData->MaxDevice = HalpPciMaxSlots;
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ // indirect Method.
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+
+ //
+ // Allow access all 32 devices per bus.
+ //
+ BusData->MaxDevice = PCI_MAX_DEVICES;
+ break;
+
+ default:
+ // unsupport type
+ DBGMSG ("HAL: Unkown PCI type\n");
+ }
+
+ if (!TestAllocation) {
+#ifdef SUBCLASSPCI
+ HalpSubclassPCISupport (Bus, HwType);
+#endif
+ }
+
+ return Bus;
+}
+
+BOOLEAN
+HalpIsValidPCIDevice (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+/*++
+
+Routine Description:
+
+ Reads the device configuration data for the given slot and
+ returns TRUE if the configuration data appears to be valid for
+ a PCI device; otherwise returns FALSE.
+
+Arguments:
+
+ BusHandler - Bus to check
+ Slot - Slot to check
+
+--*/
+
+{
+ 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;
+}
+
+
+
+
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+ 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.
+
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ 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
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // 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 (BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Has this PCI device been configured?
+ //
+
+#if 0
+ //
+ // 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;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len, cnt;
+
+
+ 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
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if 0
+ 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 (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 (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) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+ //DbgBreakPoint ();
+ }
+#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
+ )
+{
+#define ATIBUG 1
+#if ATIBUG
+ USHORT VendorId;
+ LONG Len;
+#endif
+
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+#if ATIBUG
+//
+// Temporary Hack (MOTKJR) - We have discovered a problem between the ATI
+// Video Driver and the NCR 810/825 SCSI parts. The NCR chip has hardware
+// registers in Configuration Space above 0x40 which have a side effect that
+// a read from these registers is destructive to its contents. If a SCSI
+// operation is active when these registers are read, the NCR device will
+// abort the operation and further I/O is impossible. Therefore, we will
+// not allow anyone to read from Offset 0x40 to 0xFF for any PCI slot that
+// has an NCR vendor ID number. Care must be taken to check for requests
+// which overlap both the PCI Common Header and the Device Dependent area.
+//
+#define NCR_VENDOR_ID 0x1000
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) &VendorId, 0x0, sizeof(VendorId),
+ PCIConfigHandler.ConfigRead);
+
+ if ((VendorId == NCR_VENDOR_ID) && (Offset + Length > PCI_COMMON_HDR_LENGTH)) {
+ Len = PCI_COMMON_HDR_LENGTH - Offset;
+ if (Len < 0)
+ Len = 0;
+ RtlFillMemory ((PVOID)((PUCHAR)Buffer+Len), Length-Len, (UCHAR) -1);
+ if (Offset >= PCI_COMMON_HDR_LENGTH)
+ return;
+ Length = Len;
+ }
+#endif
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ UCHAR HeaderType;
+ ULONG i;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // 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;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PCIConfigHandler.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;
+ }
+
+ PCIConfigHandler.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 = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.bits.DeviceNumber)
+ + 0x100 * Slot.u.bits.FunctionNumber;
+
+}
+
+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;
+ if ((PciCfg1->u.bits.BusNumber = BusHandler->BusNumber) == 0) {
+
+ // This hack is to maintain device number compatibility
+ // on bus 0 with the Type1 functions. We do this so that
+ // the installed base maintains the same "slot" numbering.
+ // The notable issue is with network interfaces where the
+ // slot number is stored in the registry at install time.
+ // It was judged too subtle and too painful to have everyone
+ // reinstall networking if they added a bridged device to
+ // their system.
+
+ int MappedDev;
+ ULONG Offset;
+ #define PRESHIFT 8 // Make invalid slot numbers to map to dev 9.
+ // Dev 9 is inaccessible from the eagle.
+
+ // Get the offset from the Type1 (direct mapping) offset table.
+ // If the device number isn't "valid", use an offset that won't
+ // actually end up selecting any device.
+
+ Offset = (Slot.u.bits.DeviceNumber < HalpPciMaxSlots) ?
+ HalpPciConfigSlot[Slot.u.bits.DeviceNumber] : (1 << PRESHIFT);
+
+ // Determine the device number accessed by the "offset".
+ // If bit 11 is set, MappedDev = 11; bit 12, MappedDev = 12;...
+
+ Offset >>= PRESHIFT;
+ MappedDev = PRESHIFT - 1;
+
+ do {
+ MappedDev++;
+ Offset >>= 1;
+
+ } while (Offset);
+
+ // The eagle docs say to set the device number field to 10
+ // for PCI device 31.
+
+ PciCfg1->u.bits.DeviceNumber = (MappedDev == 31) ? 10 : MappedDev;
+
+ } else {
+ PciCfg1->u.bits.DeviceNumber = 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 (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ *((PUCHAR) Buffer) = READ_PORT_UCHAR ((PUCHAR)&((PPLANAR_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 (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUCHAR)&((PPLANAR_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 (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG (&((PPLANAR_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 (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ WRITE_PORT_UCHAR ((PUCHAR)&((PPLANAR_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 (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG );
+ WRITE_PORT_USHORT ((PUCHAR)&((PPLANAR_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 (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData,*((PULONG)Buffer));
+ return sizeof(ULONG);
+}
+
+
+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
+ )
+/*++
+
+Routine Description:
+
+ 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 status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
+ PCI_SLOT_NUMBER PciSlot;
+ PPCIPBUSDATA BusData;
+ 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, Option;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
+ BOOLEAN Match, EnableRomBase;
+
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+ BusNumber = BusHandler->BusNumber;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // 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;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // 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);
+ 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:
+ 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 (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++;
+ }
+
+ //
+ // Add a memory/port resoruce for each PCI resource
+ //
+
+ *BaseAddress[RomIndex] &= ~0x7ff;
+
+ //
+ // Rom Base Address resource is not enabled, as the ROM code cannot
+ // be executed on a risk box, and the algorithm below interprets
+ // the card's Rom Base Address requirements incorrectly
+ //
+
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+ i = *BaseAddress[j];
+
+ // 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
+ DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
+ BusNumber,
+ PciSlot.u.bits.DeviceNumber,
+ PciSlot.u.bits.FunctionNumber
+ );
+
+ DbgPrint ("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;
+
+ } 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;
+ }
+
+ 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)) {
+ 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 (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
+ DbgPrint ("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 compatability
+ 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 ;
+ }
+
+ DbgBreakPoint ();
+ 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)
+ );
+
+#if 0
+ 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)
+ );
+#endif
+
+ DbgPrint ("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) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.Command, PciData.Status, PciData.ProgIf,
+ PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+#if 0
+ 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)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+#endif
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+#if 0
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+#endif
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+#endif
diff --git a/private/ntos/nthals/haleagle/ppc/pxpciint.c b/private/ntos/nthals/haleagle/ppc/pxpciint.c
new file mode 100644
index 000000000..36c139b3f
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxpciint.c
@@ -0,0 +1,221 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxpciint.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 "pci.h"
+#include "pcip.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#pragma alloc_text(PAGE,HalpGetISAFixedPCIIrq)
+#endif
+
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ if (BusInterruptLevel < 1) {
+ // bogus bus level
+ return 0;
+ }
+
+
+ //
+ // 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
+ );
+}
+
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ On the current PC implementations, the bios has already filled in
+ InterruptLine as it's ISA value and there's no portable way to
+ change it.
+
+
+--*/
+{
+}
+
+
+
+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
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ On the current PC implementations, this information is
+ fixed by the BIOS. Just make sure the value isn't being
+ editted since PCI doesn't tell us how to dynically
+ connect the interrupt.
+
+--*/
+{
+}
+
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+ Rewrite the callers requested resource list to fit within
+ the supported ranges of this bus
+--*/
+{
+ NTSTATUS Status;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER PciSlot;
+ PSUPPORTED_RANGE Interrupt;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+
+ Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ //
+ // Adjust resources
+ //
+
+ Status = HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ Interrupt,
+ pResourceList
+ );
+
+ ExFreePool (Interrupt);
+ return Status;
+}
+
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData (
+ 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;
+ }
+
+ *Interrupt = ExAllocatePool (PagedPool, sizeof (SUPPORTED_RANGE));
+ if (!*Interrupt) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory (*Interrupt, sizeof (SUPPORTED_RANGE));
+ (*Interrupt)->Base = 1; // base = 1, limit = 0
+
+ if (!PciData->u.type0.InterruptPin) {
+ return STATUS_SUCCESS;
+ }
+
+ if (PciData->u.type0.InterruptLine == 0) {
+#if DBG
+ DbgPrint ("HalpGetValidPCIFixedIrq: BIOS did not assign an interrupt vector for the device\n");
+#endif
+ //
+ // We need to let the caller continue, since the caller may
+ // not care that the interrupt vector is connected or not
+ //
+
+ return STATUS_SUCCESS;
+ }
+
+ (*Interrupt)->Base = PciData->u.type0.InterruptLine;
+ (*Interrupt)->Limit = PciData->u.type0.InterruptLine;
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxpcisup.c b/private/ntos/nthals/haleagle/ppc/pxpcisup.c
new file mode 100644
index 000000000..272a16022
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxpcisup.c
@@ -0,0 +1,235 @@
+
+
+/*++
+
+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:
+
+ pxpcisup.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:
+
+ T. White -- Added dword I/O to allow GXT150P to work correctly
+
+Special Note:
+
+ Please make sure that the dword I/O mechanisms are carried
+ forward for any box which is to support the GXT150P graphics
+ adapter. The GXT150P graphics adapter runs in any PowerPC
+ machine with a standard PCI bus connector.
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxpcisup.h"
+
+extern PVOID HalpPciConfigBase;
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpPhase0SetPciDataByOffset)
+#pragma alloc_text(INIT,HalpPhase0GetPciDataByOffset)
+#endif
+
+ULONG HalpPciConfigSlot[] = { 0x0800,
+ 0x1000,
+ 0x2000,
+ 0x4000,
+ 0x8000,
+ 0x10000,
+ 0x20000,
+ 0x40000,
+ 0x80000
+ };
+
+ULONG HalpPciMaxSlots = sizeof(HalpPciConfigSlot)/sizeof(ULONG);
+ULONG HalpPciConfigSize;
+
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG BusNumber,
+ ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+ //
+ // Sandalfoot only has 1 PCI bus so bus number is unused
+ //
+
+ UNREFERENCED_PARAMETER(BusNumber);
+
+ return ((ULONG) ((PUCHAR) HalpPciConfigBase + HalpPciConfigSlot[SlotNumber]));
+
+}
+
+
+ULONG
+HalpPhase0SetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes to PCI configuration space prior to bus handler installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ PUCHAR to;
+ PUCHAR from;
+ ULONG tmpLength;
+ PULONG ulong_to, ulong_from;
+
+ if (SlotNumber < HalpPciMaxSlots) {
+
+ to = (PUCHAR)HalpPciConfigBase + HalpPciConfigSlot[SlotNumber];
+ to += Offset;
+ from = Buffer;
+
+ // The GXT150P graphics adapter requires the use of dword I/O
+ // to some of its PCI configuration registers. Therefore, this
+ // code uses dword I/O when possible.
+
+ // If the bus address is not dword aligned or the length
+ // is not a multiple of 4 (dword size) bytes, then use byte I/O
+ if(((ULONG)to & 0x3)||(Length & 0x3)){
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ *to++ = *from++;
+ tmpLength--;
+ }
+ // If the bus address is dword aligned and the length is
+ // a multiple of 4 (dword size) bytes, then use dword I/O
+ }else{
+ ulong_to = (PULONG) to;
+ ulong_from = (PULONG) from;
+ tmpLength = Length >> 2;
+ while (tmpLength > 0) {
+ *ulong_to++ = *ulong_from++;
+ tmpLength--;
+ }
+ }
+
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+ULONG
+HalpPhase0GetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads PCI config space prior to bus handlder installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Amount of data read.
+
+--*/
+
+{
+ PUCHAR to;
+ PUCHAR from;
+ ULONG tmpLength;
+ PULONG ulong_to, ulong_from;
+
+ if (SlotNumber < HalpPciMaxSlots) {
+
+ from = (PUCHAR)HalpPciConfigBase + HalpPciConfigSlot[SlotNumber];
+ from += Offset;
+ to = Buffer;
+
+ // The GXT150P graphics adapter requires the use of dword I/O
+ // to some of its PCI configuration registers. Therefore, this
+ // code uses dword I/O when possible.
+
+ // If the bus address is not dword aligned or the length
+ // is not a multiple of 4 (dword size) bytes, then use byte I/O
+ if(((ULONG)from & 0x3)||(Length & 0x3)){
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ *to++ = *from++;
+ tmpLength--;
+ }
+ // If the bus address is dword aligned and the length is
+ // a multiple of 4 (dword size) bytes, then use dword I/O
+ }else{
+ ulong_to = (PULONG) to;
+ ulong_from = (PULONG) from;
+ tmpLength = Length >> 2;
+ while (tmpLength > 0) {
+ *ulong_to++ = *ulong_from++;
+ tmpLength--;
+ }
+ }
+
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxpcisup.h b/private/ntos/nthals/haleagle/ppc/pxpcisup.h
new file mode 100644
index 000000000..a598de5e5
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxpcisup.h
@@ -0,0 +1,54 @@
+/*++
+
+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:
+
+
+
+--*/
+
+extern ULONG HalpPciConfigSlot[];
+extern ULONG HalpPciMaxSlots;
+
+#define PCI_CONFIG_PHYSICAL_BASE 0x80800000 // physical base of PCI config space
+
+#define PCI_MEMORY_BASE 0xC0000000
+
+
+
+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/haleagle/ppc/pxport.c b/private/ntos/nthals/haleagle/ppc/pxport.c
new file mode 100644
index 000000000..6c91f4b59
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxport.c
@@ -0,0 +1,849 @@
+/*++
+
+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;
+ULONG KdCurrentComPort = COM1_PORT;
+ULONG HalpSavedBaudRate;
+ULONG HalpSavedComPort;
+
+extern PVOID HalpIoControlBase;
+
+//
+// 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.
+//
+
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ 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;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ 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) {
+
+ HalpIoControlBase = (PVOID)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE,
+ 0x20000);
+
+ 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;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ 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 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.
+ //
+
+
+ Status = HalpGetByte(Input, FALSE);
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ PSP_MODEM_STATUS LsrByte;
+
+ 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;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+DEBUG_PARAMETERS ComParams;
+
+ if (HalpSavedComPort != KdCurrentComPort ||
+ HalpSavedBaudRate != KdCurrentBaudRate) {
+ if (HalpSavedComPort == COM2_PORT)
+ ComParams.CommunicationPort = 2;
+ else
+ ComParams.CommunicationPort = 1;
+ ComParams.BaudRate = HalpSavedBaudRate;
+ KdPortInitialize(&ComParams, NULL, TRUE);
+ }
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ HalpSavedBaudRate = KdCurrentBaudRate;
+ HalpSavedComPort = KdCurrentComPort;
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ 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);
+}
+
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ 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/haleagle/ppc/pxpower.s b/private/ntos/nthals/haleagle/ppc/pxpower.s
new file mode 100644
index 000000000..e02d56689
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxpower.s
@@ -0,0 +1,67 @@
+//++
+//
+// Copyright (c) 1993-1995 IBM Corporation
+//
+// Copyright (c) 1994, 1995 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:
+//
+// pxpower.s
+//
+// Abstract:
+//
+// This module implements the routines to flush cache on the PowerPC.
+//
+// Author:
+//
+// Steve Johns - Motorola
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 12-Sep-94 saj Wrote it
+// 25-Oct-94 saj Enable interrupts if 604
+// Set DOZE bit in HID0 before POW in MSR
+// 25-Sep-95 kjr Added 603ev support.
+//--
+
+#include "kxppc.h"
+
+
+ .set HID0, 1008 // SPR # for HID0
+
+
+
+ LEAF_ENTRY(HalpProcessorIdle)
+
+ mfmsr r.4 // Read MSR
+ ori r.4, r.4, 0x8000 // Enable External/Decrementer interrupts
+
+ mfpvr r.0 // Read PVR
+ rlwinm r.0, r.0, 16, 15, 31
+ cmpwi r.0, 3 // Is it a 603?
+ beq EnableDoze
+ cmpwi r.0, 6 // Is it a 603e?
+ beq EnableDoze
+ cmpwi r.0, 7 // Is it a 603ev?
+ beq EnableDoze
+
+ b EnableInterrupts // If not, just enable interrupts
+
+EnableDoze:
+ mfspr r.3, HID0 // Set Doze mode in HID0 (bit 8)
+ oris r.3, r.3, 0x0080
+ mtspr HID0, r.3
+ sync
+
+ oris r.4, r.4, 0x0004 // Set POW in MSR (bit 13)
+
+EnableInterrupts:
+ mtmsr r.4
+ isync
+
+ LEAF_EXIT(HalpProcessorIdle)
diff --git a/private/ntos/nthals/haleagle/ppc/pxproc.c b/private/ntos/nthals/haleagle/ppc/pxproc.c
new file mode 100644
index 000000000..5ec201f37
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxproc.c
@@ -0,0 +1,212 @@
+/*++
+
+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 "halp.h"
+
+UCHAR HalName[] = "PowerPC HAL";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+extern VOID HalpInitializePciBus (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#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
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return FALSE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+}
+
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+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.
+
+--*/
+
+{
+
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG Number;
+ PKPRCB Prcb;
+
+ //
+ // 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.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ Number = 0;
+ while (NextRestartBlock != NULL) {
+ if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) &&
+ (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) {
+ RtlZeroMemory(&NextRestartBlock->u.Ppc, sizeof(PPC_RESTART_STATE));
+
+ //
+ // Set processor start address.
+ //
+
+ NextRestartBlock->u.Ppc.Iar = ProcessorState->ContextFrame.Iar;
+
+ //
+ // 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.
+ //
+
+ NextRestartBlock->u.Ppc.IntR3 = ProcessorState->ContextFrame.Gpr3;
+ NextRestartBlock->u.Ppc.IntR4 = ProcessorState->ContextFrame.Gpr4;
+ NextRestartBlock->u.Ppc.IntR5 = ProcessorState->ContextFrame.Gpr5;
+ NextRestartBlock->u.Ppc.IntR6 = ProcessorState->ContextFrame.Gpr6;
+ NextRestartBlock->u.Ppc.IntR7 = ProcessorState->ContextFrame.Gpr7;
+ NextRestartBlock->u.Ppc.IntR8 = ProcessorState->ContextFrame.Gpr8;
+ NextRestartBlock->u.Ppc.IntR9 = ProcessorState->ContextFrame.Gpr9;
+ NextRestartBlock->u.Ppc.IntR10 = ProcessorState->ContextFrame.Gpr10;
+
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ return TRUE;
+ }
+
+ Number++;
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ interfacetype = Internal;
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ interfacetype = Isa;
+
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+
+#ifdef POWER_MANAGEMENT
+ HalInitSystemPhase2();
+#endif
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxprof.c b/private/ntos/nthals/haleagle/ppc/pxprof.c
new file mode 100644
index 000000000..fdd31e5f1
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxprof.c
@@ -0,0 +1,268 @@
+
+/*****************************************************************************
+
+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
+
+******************************************************************************/
+
+#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:
+
+ ProfileSource
+
+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:
+
+ ProfileSource
+
+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/haleagle/ppc/pxreset.s b/private/ntos/nthals/haleagle/ppc/pxreset.s
new file mode 100644
index 000000000..ad4bfb697
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxreset.s
@@ -0,0 +1,240 @@
+//++
+//
+// 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:
+//
+// pxreset.s
+//
+// Abstract:
+//
+// This module implements the routine HalpPowerPcReset, which can be
+// used to return the PowerPC to Big Endian with cache flushed and
+// branches to the rom based machine reset handler.
+//
+// Author:
+//
+// Steve Johns Sept-1994
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// 3/21/95 saj Fixed HID0 getting trashed.
+//--
+
+#include "kxppc.h"
+ .new_section .text,"crx5"
+
+ .extern HalpIoControlBase
+ .extern HalpSystemType
+
+ .set ISA, r.1
+
+ .set HID0, 1008
+ .set DISABLES, MASK_SPR(MSR_EE,1) | MASK_SPR(MSR_DR,1) | MASK_SPR(MSR_IR,1)
+ .set HID0_DCE, 0x4000 // 603 Data Cache Enable
+ .set HID0_ICE, 0x8000 // 603 Instruction Cache Enable
+ .set HID0_ICFI, 0x0800 // I-Cache Flash Invalidate
+ .set HID0_DCFI, 0x0400 // D-Cache Flash Invalidate
+
+
+ LEAF_ENTRY(HalpPowerPcReset)
+
+
+ lwz r.3,[toc]HalpSystemType(r.toc) // Get system type for later use.
+ lwz r.3, 0(r.3)
+
+ LWI (r.4, 0xfff00100) // Address of ROM reset vector
+ mfspr r.5, HID0
+
+ LWI (r.7, 0x80000000) // I/O space for physical mode
+
+ lwz ISA,[toc]HalpIoControlBase(r.toc)
+ lwz ISA,0(ISA) // Get base address of ISA I/O space
+
+
+ LWI (r.12, 0x800000A8) // Index to Eagle register 0xA8
+ stw r.12, 0xCF8(ISA)
+ sync
+ lwz r.6, 0xCFC(ISA)
+ rlwinm r.6, r.6, 0, 0, 29 // Disable L2 cache
+ rlwinm r.6, r.6, 0, 21, 19 // Disable Machine Checks from Eagle
+ stw r.6, 0xCFC(ISA) // Disable the L2 cache
+ rlwinm r.6, r.6, 0, 27, 25 // Clear LE_MODE of Eagle register A8
+
+ mfmsr r.8
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_EE,1)
+ isync
+ mtmsr r.8 // disable interrupts
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+ bl here // get current address
+here:
+ mflr r.9 // (r.9) = &here
+ addi r.9, r.9, BigEndian-here
+ rlwinm r.9, r.9, 0, 0x7fffffff // convert address to physical
+
+
+// When we get here
+// r.4 contains the address of the ROM resident Machine Reset
+// handler.
+// r.5 contains HID0 present value.
+// r.6 contains Eagle register A8 value for switching to Big Endian
+// r.7 contains the port address (real) used to switch memory
+// endianness.
+// r.8 contains MSR present value.
+// r.9 contains the physical address of "BigEndian"
+
+
+
+// Disable D-Cache and Data address translation, flush I-Cache
+// and disable interrupts.
+
+ mr r.10, r.5
+ ori r.5,r.5,HID0_DCE+HID0_ICE+HID0_ICFI+HID0_DCFI // Invalidate caches
+ rlwinm r.10, r.10, 0, ~HID0_DCE// turn off D-cache
+ rlwinm r.10, r.10, 0, ~HID0_ICE// turn off I-cache
+ sync
+ mtspr HID0, r.5 // Flash invalidate both caches
+ mtspr HID0, r.10 // Disable both caches
+
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_DR,1)
+ isync
+ mtmsr r.8 // disable data address translation,
+ // disable interrupts.
+ cror 0,0,0 // N.B. 603e/ev Errata 15
+
+// We will use a MTMSR instruction to switch to big-endian, untranslated,
+// interrupts disabled at the same time. We use an RFI to effect the
+// branch to the reset vector (0xFFF00100).
+
+ li r.8, MASK_SPR(MSR_IP,1)
+ ori r.8, r.8, MASK_SPR(MSR_ME,1)
+ mtsrr1 r.8 // state = Machine Check Enabled
+ mtsrr0 r.9 // RFI to BigEndian
+
+
+ //
+ // Try to issue a hard reset. If this fails, the fall
+ // thru and continue to manually return to firmware.
+ //
+
+ cmpwi r.3, 0 // Skip port 92 reset for BigBend. *BJ*
+ beq NoPort92
+
+ li r.9, 0xFF // All ones
+ stb r.9, 0x92(r.7) // Reset the System
+ eieio
+ lwz r.9, 0x21(r.7) // Flush the Eagle write buffers
+ sync
+ sync
+ sync
+ sync
+
+ //
+ // Continue returning to firmware...
+ //
+
+
+NoPort92:
+
+
+ stw r.12, 0xCF8(r.7)
+ sync
+ stw r.6, 0xCFC(r.7) // switch PCI bus to big-endian (Eagle)
+ li r.6, 0
+ sync
+ rfi
+
+
+ .align 5
+
+//
+// When the assembler mode is Big-Endian, instructions are stored in the .OBJ
+// in a different order. To be safe, we will place instructions in groups of
+// fours, where the execution order within a group is not important.
+BigEndian:
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+
+//
+// Return the processor as close as possible to the reset state
+//
+ mtibatl 0, r.6 // Invalidate BAT registers
+ mtibatu 0, r.6
+ mtibatl 1, r.6
+ mtibatu 1, r.6
+ mtibatl 2, r.6
+ mtibatu 2, r.6
+ mtibatl 3, r.6
+ mtibatu 3, r.6
+
+ mtsr 0, r.6 // Zero the Segment Registers
+ mtsr 1, r.6
+ mtsr 2, r.6
+ mtsr 3, r.6
+ mtsr 4, r.6
+ mtsr 5, r.6
+ mtsr 6, r.6
+ mtsr 7, r.6
+ mtsr 8, r.6
+ mtsr 9, r.6
+ mtsr 10, r.6
+ mtsr 11, r.6
+ mtsr 12, r.6
+ mtsr 13, r.6
+ mtsr 14, r.6
+ mtsr 15, r.6
+
+ mtsprg 0,r.6 // Should get cleared in the firmware
+ mtsprg 1,r.6 // (used for branch table)
+ mtsprg 2,r.6
+ mtsprg 3,r.6
+
+ li r.9,-1 // DECREMENTER = 0xFFFFFFFF
+ mtdec r.9
+ li r.9, 128 // # TLBs on a 604 (603 has 32)
+ mtsrr0 r.4 // rfi target = 0xfff00100
+
+ li r.7, 0
+ mtctr r.9
+ nop
+ nop
+
+Invalidate_TLB:
+ tlbie r.7 // Invalidate Instruction & Data TLBs
+ nop
+ nop
+ nop
+
+ addi r.7, r.7, 4096 // next TLB
+ nop
+ nop
+ nop
+
+ bdnz Invalidate_TLB
+ nop
+ nop
+ nop
+
+ rfi // go to machine reset handler
+ rfi
+ rfi
+ rfi
+
+ LEAF_EXIT(HalpPowerPcReset)
diff --git a/private/ntos/nthals/haleagle/ppc/pxreturn.c b/private/ntos/nthals/haleagle/ppc/pxreturn.c
new file mode 100644
index 000000000..2638d8e6a
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxreturn.c
@@ -0,0 +1,133 @@
+/*++
+
+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 "pxsystyp.h"
+
+
+//
+// Define keyboard registers structure.
+//
+
+typedef struct _KBD_REGISTERS {
+ union {
+ UCHAR Output;
+ UCHAR Input;
+ } Data;
+
+ union {
+ UCHAR Status;
+ UCHAR Command;
+ } Control;
+} KBD_REGISTERS;
+
+#define KBD_IBF_MASK 2 // input buffer full mask
+
+#define KBD_DATA_PORT 0x60
+#define KBD_COMMAND_PORT 0x64
+#define KbdGetStatus() (READ_REGISTER_UCHAR(&HalpIoControlBase + KBD_COMMAND_PORT))
+#define KbdStoreCommand(Byte) WRITE_REGISTER_UCHAR(&HalpIoControlBase + KBD_COMMAND_PORT, Byte)
+#define KbdStoreData(Byte) WRITE_REGISTER_UCHAR(&HalpIoControlBase + KBD_DATA_PORT, Byte)
+#define KbdGetData() (READ_REGISTER_UCHAR(&HalpIoControlBase + KBD_DATA_PORT))
+
+VOID
+HalpPowerPcReset(
+ VOID
+ );
+
+VOID HalpFlushAndDisableL2(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.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+ HalpDisableInterrupts();
+ if (HalpSystemType == MOTOROLA_BIG_BEND)
+ HalpFlushAndDisableL2();
+ HalpPowerPcReset(); // does not return
+
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxs3.h b/private/ntos/nthals/haleagle/ppc/pxs3.h
new file mode 100644
index 000000000..96f669688
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxs3.h
@@ -0,0 +1,760 @@
+/*++
+
+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
+
+--*/
+
+#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.
+//
+
+extern PVOID HalpIoControlBase;
+
+//
+// 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/haleagle/ppc/pxsiosup.c b/private/ntos/nthals/haleagle/ppc/pxsiosup.c
new file mode 100644
index 000000000..1cd1c9789
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxsiosup.c
@@ -0,0 +1,1761 @@
+/*++
+
+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 "halp.h"
+#include "pxsystyp.h"
+#include "eisa.h"
+#include "pxsiosup.h"
+#include "pxpcisup.h"
+#include "pxmemctl.h"
+#include "bugcodes.h"
+
+
+#define SioId 0x04848086 // UMC 8886
+
+PVOID HalpPciIsaBridgeConfigBase;
+extern USHORT Halp8259MaskTable[];
+extern PADAPTER_OBJECT MasterAdapterObject;
+VOID HalpUpdate8259(KIRQL Irql);
+
+
+
+//
+// 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;
+
+//
+// Map the interrupt controllers priority scheme to NT IRQL values.
+// The SIO prioritizes IRQs as follows:
+// IRQ0, IRQ1, IRQ8 ... IRQ15, IRQ3, IRQ4 ... IRQ7.
+//
+// NOTE: The following table must be coordinated with the entries
+// in Halp8259MaskTable in PXIRQL.C
+//
+KIRQL VectorToIrql[16] = {
+// IRQL Vector
+// ---- ------
+ 26, // 0
+ 25, // 1
+ 24, // 2
+ 15, // 3
+ 14, // 4
+ 13, // 5
+ 12, // 6
+ 11, // 7
+ 23, // 8
+ 22, // 9
+ 21, // 10
+ 20, // 11
+ 19, // 12
+ 18, // 13
+ 17, // 14
+ 16 }; // 15
+
+KIRQL HalpTranslateVectorToIrql(
+ IN ULONG Vector
+ )
+{ // It is assumed that the caller has checked that Vector is valid (0..15)
+ return VectorToIrql[Vector];
+}
+
+//
+// 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 registers
+// and level\edge control registers.
+//
+
+USHORT HalpSioInterruptLevel = 0x0000; // Default to edge-sensitive
+
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called from phase 0 initialization, it initializes the
+ 8259 interrupt controller ( currently it masks all 8259 interrupts).
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+
+--*/
+
+{ UCHAR DataByte;
+ ULONG Vector;
+
+
+ //
+ // Initialize the SIO interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second initialization control word sets the interrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // 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;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+
+ //
+ // Mask all 8259 interrupts (except the Slave input)
+ //
+
+ for (Vector=0; Vector<= HIGHEST_8259_VECTOR; Vector++) {
+ HalpDisableSioInterrupt(Vector + DEVICE_VECTORS);
+ }
+ HalpEnableSioInterrupt(SLAVE_IRQL_LEVEL + DEVICE_VECTORS, Latched);
+
+ //
+ // Reserve the external interrupt vector for exclusive use by the HAL.
+ //
+
+ PCR->ReservedVectors |= (1 << EXTERNAL_INTERRUPT_VECTOR);
+
+ return TRUE;
+
+}
+
+
+BOOLEAN
+HalpCreateSioStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for SIO operations
+ and connects the intermediate interrupt dispatcher.
+
+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.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+
+
+ //
+ // 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;
+
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ DataByte
+ );
+
+ //
+ // Connect the external interrupt handler
+ //
+
+ PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] = (PKINTERRUPT_ROUTINE) 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);
+
+ //
+ // Raise the IRQL while the SIO interrupt controller is initialized.
+ //
+
+ KeRaiseIrql(CLOCK2_LEVEL, &oldIrql);
+
+ //
+ // Initialize any planar registers
+ //
+
+ HalpInitPlanar();
+
+
+ //
+ // Enable the clock interrupt
+ //
+ HalpUpdateDecrementer(1000); // Get those decrementer ticks going
+
+
+ //
+ // Set ISA bus interrupt affinity.
+ //
+
+ HalpIsaBusAffinity = PCR->SetMember;
+
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+
+ //
+ // 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
+HalpMapIoControlSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+
+ 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;
+
+}
+
+BOOLEAN
+HalpHandleExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the SIO device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the SIO
+ controller.
+
+ N.B. This routine is entered and left with external interrupts disabled.
+
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the SIO interrupt acknowledge
+ register.
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ PSECONDARY_DISPATCH SioHandler;
+ PKINTERRUPT SioInterrupt;
+ USHORT interruptVector;
+ BOOLEAN returnValue;
+ UCHAR OldIrql;
+ USHORT Isr;
+ UCHAR Irql;
+
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(HalpInterruptBase);
+
+ //
+ // check for nmi interrupt before we raise irql since we would raise to a
+ // bogus level
+ //
+
+ if (interruptVector == 0xFF) {
+
+ HalpHandleMachineCheck(NULL, NULL);
+ }
+
+ //
+ // check for spurious interrupt
+ //
+
+ if (interruptVector == SPURIOUS_VECTOR) {
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0,
+ 0x0B);
+ Isr = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0);
+ if (!(Isr & 0x80)) {
+
+ //
+ // Spurious interrupt
+ //
+
+#if DBG
+ //DbgPrint("A spurious interrupt occurred. \n");
+ HalpSpuriousInterruptCount++;
+#endif
+ return(0);
+
+ }
+ }
+
+ if (interruptVector > HIGHEST_8259_VECTOR) {
+#if DBG
+ DbgPrint("A bogus interrupt (0x%02x) occurred. \n", interruptVector);
+ HalpBogusInterruptCount++;
+#endif
+ return (0);
+ }
+
+ //
+ // Translate vector to IRQL and raise IRQL
+ //
+
+ Irql = HalpTranslateVectorToIrql(interruptVector);
+ KeRaiseIrql( Irql, &OldIrql);
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ SioHandler = (PSECONDARY_DISPATCH)
+ PCR->InterruptRoutine[DEVICE_VECTORS + interruptVector];
+ SioInterrupt = CONTAINING_RECORD(SioHandler,
+ KINTERRUPT,
+ DispatchCode[0]);
+
+ returnValue = SioHandler(SioInterrupt,
+ SioInterrupt->ServiceContext,
+ TrapFrame
+ );
+
+ //
+ // Dismiss the interrupt in the SIO interrupt controllers.
+ //
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ //
+ // Lower IRQL but disable external interrupts.
+ // Return to caller with interrupts disabled.
+ //
+
+
+ HalpResetIrqlAfterInterrupt(OldIrql);
+
+ return(returnValue);
+
+}
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the SIO interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{ USHORT MaskBit, i;
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+ Vector -= DEVICE_VECTORS;
+
+ if (Vector <= HIGHEST_8259_VECTOR) {
+ //
+ // Generate 8259 mask
+ //
+ MaskBit = (USHORT) (1 << Vector);
+
+ //
+ // Set the mask bit in Halp8259MaskTable
+ //
+ for (i = 0; i <= 31; i++) {
+ Halp8259MaskTable[i] |= MaskBit;
+ }
+
+ // Write new mask values to 8259s
+ HalpUpdate8259(PCR->CurrentIrql);
+ }
+}
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{
+
+ 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);
+
+}
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ 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.
+
+--*/
+
+{ USHORT MaskBit, Irql, i;
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+ Vector -= DEVICE_VECTORS;
+
+ if (Vector <= HIGHEST_8259_VECTOR) {
+ //
+ // Generate 8259 mask
+ //
+ MaskBit = (USHORT) ~(1 << Vector);
+
+
+ //
+ // Force interrupts to be latched (edge-triggered) if Big Bend
+ //
+ if(HalpSystemType == MOTOROLA_BIG_BEND)
+ InterruptMode = Latched;
+
+ //
+ // Set the level/edge control register.
+ //
+ if (InterruptMode == LevelSensitive) {
+ HalpSioInterruptLevel |= ~MaskBit;
+ } else {
+ HalpSioInterruptLevel &= MaskBit;
+ }
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2EdgeLevel,
+ (UCHAR) (HalpSioInterruptLevel >> 8)
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1EdgeLevel,
+ (UCHAR) HalpSioInterruptLevel
+ );
+ }
+
+
+ //
+ // Clear mask bit in Halp8259MaskTable
+ //
+ Irql = VectorToIrql[Vector];
+ for (i = 0; i < Irql; i++) {
+ Halp8259MaskTable[i] &= MaskBit;
+ }
+
+ // Write new mask values to 8259s
+ HalpUpdate8259(PCR->CurrentIrql);
+ }
+}
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ 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 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;
+
+ 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 2
+ //
+
+ 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);
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ 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 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/haleagle/ppc/pxsiosup.h b/private/ntos/nthals/haleagle/ppc/pxsiosup.h
new file mode 100644
index 000000000..6b94bdc51
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxsiosup.h
@@ -0,0 +1,221 @@
+
+/*++
+
+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:
+
+
+--*/
+
+#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/haleagle/ppc/pxstall.s b/private/ntos/nthals/haleagle/ppc/pxstall.s
new file mode 100644
index 000000000..fd3555c0d
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxstall.s
@@ -0,0 +1,326 @@
+//#***********************************************************************
+//
+// 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.
+// 11-Sep-1995 Steve Johns
+// Removed 601 specific ocde
+// Removed 603 workaround, since we don't support < 603 v3.2
+//
+//#***********************************************************************
+
+
+
+#include "halppc.h"
+
+#define ERRATA603 FALSE
+#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
+ .set TimerHi , r.7
+ .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;
+
+//
+// Read START time
+//
+ bl ..HalpReadTB // 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:
+ bl ..HalpReadTB // Read Time Base
+ 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 PowerPC
+// architectures (not the 601).
+//
+ LEAF_ENTRY (HalpReadTB)
+
+ 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- ..HalpReadTB
+
+ LEAF_EXIT (HalpReadTB)
+
+
+
+//
+// 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
+
+ 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
+#define RTC_SECONDS 0x1
+#define WRITE 0x80
+#define READ 0x40
+
+#define SYNCHRONIZE \
+ sync; \
+ sync; \
+ sync
+
+#define READ_RTC_REG(reg, reg_num_lo, reg_num_hi) \
+ stb reg_num_lo,NVRAM_INDEX_LO(r10); \
+ stb reg_num_hi,NVRAM_INDEX_HI(r10); \
+ SYNCHRONIZE; \
+ lbz reg,NVRAM_DATA(r10)
+
+#define WRITE_RTC_REG(reg, reg_num_lo, reg_num_hi) \
+ stb reg_num_lo,NVRAM_INDEX_LO(r10); \
+ stb reg_num_hi,NVRAM_INDEX_HI(r10); \
+ SYNCHRONIZE; \
+ stb reg,NVRAM_DATA(r10); \
+ SYNCHRONIZE
+
+// Here are the steps to getting the Seconds register out of the CMOS RTC
+// A. Stop the RTC
+// 1. Read control reg
+// 2. Set READ bit
+// 3. write control reg
+//
+// B. Read Seconds
+//
+// C. Restart the RTC
+// 1. Read control reg
+// 2. Clear READ bit
+// 3. write control reg
+
+#define GET_SECONDS(reg) \
+ READ_RTC_REG(r9, r7, r8); \
+ ori r9,r9,READ; \
+ WRITE_RTC_REG(r9, r7, r8); \
+ \
+ READ_RTC_REG(reg, r5, r6); \
+ \
+ READ_RTC_REG(r9, r7, r8); \
+ andi. r9,r9,~READ; \
+ WRITE_RTC_REG(r9, r7, r8)
+
+ // Get base address of ISA I/O space
+ // so we can talk to the CMOS RTC
+ lwz r10,[toc]HalpIoControlBase(r.toc)
+ lwz r10,0(r10)
+
+ // Set up some offsets into the Real
+ // Time Clock...
+ li r5,RTC_OFFSET+RTC_SECONDS // r5 <- Seconds register offset
+ rlwinm r6,r5,32-8,24,31 // r6 <- Shift > 8 and mask 0xff
+ li r7,RTC_OFFSET+RTC_CONTROL // r7 <- Control register Offset
+ rlwinm r8,r7,32-8,24,31 // r8 <- Shift > 8 and mask 0xff
+
+WaitForRTC.Ps:
+ READ_RTC_REG(r3, r7, r8) // Read Control register
+ andi. r3,r3,WRITE // Is it being written to?
+ bne WaitForRTC.Ps // If so, loop again
+ GET_SECONDS(r3) // Get RTC seconds register
+
+WaitForTick0.Ps:
+ READ_RTC_REG(r4, r7, r8) // Read Control register
+ andi. r4,r4,WRITE // Is it being written to?
+ bne WaitForTick0.Ps // If so, loop again
+ GET_SECONDS(r4) // Get RTC seconds register
+ cmpw r4,r3 // Loop until it changes
+ beq WaitForTick0.Ps
+
+
+WaitForTick1.Ps:
+ READ_RTC_REG(r3, r7, r8) // Read Control register
+ andi. r3,r3,WRITE // Is it being written to?
+ bne WaitForTick1.Ps // If so, loop again
+ GET_SECONDS(r3) // Get RTC seconds register
+ cmpw r3,r4 // Loop until it changes
+ beq WaitForTick1.Ps
+
+ li r4,-1 // Start the decrementer at max. count
+ mtdec r4
+#if ERRATA603
+ isync
+#endif
+
+WaitForTick2.Ps:
+ READ_RTC_REG(r4, r7, r8) // Read Control register
+ andi. r4,r4,WRITE // Is it being written to?
+ bne WaitForTick2.Ps // If so, loop again
+ GET_SECONDS(r4) // Get RTC seconds register
+ cmpw r4,r3 // Loop until it changes
+ beq WaitForTick2.Ps
+
+ mfdec r.3 // Read the decrementer
+ neg r.3,r.3 // Compute delta ticks
+
+ LEAF_EXIT(HalpCalibrateTBPStack)
+
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxsysbus.c b/private/ntos/nthals/haleagle/ppc/pxsysbus.c
new file mode 100644
index 000000000..cb3e6c720
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxsysbus.c
@@ -0,0 +1,204 @@
+/*++
+
+
+Copyright (C) 1989-1995 Microsoft Corporation
+
+Module Name:
+
+ pxsysbus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+ Jim Wooldridge - IBM
+ - ported to PowerPC
+ 9/26/95 Steve Johns - Motorola
+ - use BusInterruptLevel instead of BusInterruptVector
+
+
+--*/
+
+#include "halp.h"
+
+#include "eisa.h"
+#include "pxmemctl.h"
+#include "pxsiosup.h"
+#include "pxsystyp.h"
+
+KIRQL HalpTranslateVectorToIrql(IN ULONG Vector);
+
+
+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
+
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+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
+
+--*/
+
+{
+ PSUPPORTED_RANGE pRange;
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
+ *AddressSpace = pRange->SystemAddressSpace;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+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.
+
+--*/
+{
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+ UNREFERENCED_PARAMETER( BusInterruptVector );
+
+
+ if (BusInterruptLevel > HIGHEST_8259_VECTOR) {
+ //
+ // Invalid BusInterruptLevel, so return Affinity of 0x0000;
+ //
+ *Affinity = 0;
+ return(DEVICE_VECTORS);
+
+ } else {
+
+ *Affinity = 1;
+
+ //
+ // Translate BusInterruptLevel to IRQL
+ //
+ *Irql = HalpTranslateVectorToIrql(BusInterruptLevel);
+
+ //
+ // The vector is equal to the specified bus level + DEVICE_VECTORS.
+ //
+ return(BusInterruptLevel + DEVICE_VECTORS);
+
+ }
+}
+
diff --git a/private/ntos/nthals/haleagle/ppc/pxsysint.c b/private/ntos/nthals/haleagle/ppc/pxsysint.c
new file mode 100644
index 000000000..b02a11ca7
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxsysint.c
@@ -0,0 +1,214 @@
+/*++
+
+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"
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+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.
+
+--*/
+
+{
+
+ 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 && Vector < DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR ) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+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
+
+--*/
+
+{
+
+ 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 && Vector < DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR ) {
+ HalpEnableSioInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+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.
+
+--*/
+
+{
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+
+
+ return;
+}
+
+BOOLEAN
+HalAcknowledgeIpi (VOID)
+
+/*++
+
+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.
+
+--*/
+
+{
+ return (TRUE);
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxsystyp.c b/private/ntos/nthals/haleagle/ppc/pxsystyp.c
new file mode 100644
index 000000000..a35666f81
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxsystyp.c
@@ -0,0 +1,96 @@
+//++
+//
+// Copyright (c) 1994, 1995 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:
+//
+// pxsystyp.c
+//
+// Abstract:
+//
+// Add a global variable to indicate which system implementation we are
+// running on. Called early in phase 0 init.
+//
+// Author:
+//
+// Bill Jones 12/94
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+
+#include "halp.h"
+#include "fwstatus.h"
+#include "arc.h"
+#include "pxsystyp.h"
+#include "fwnvr.h"
+
+SYSTEM_TYPE HalpSystemType = SYSTEM_UNKNOWN;
+extern NVR_SYSTEM_TYPE nvr_system_type;
+
+extern ULONG HalpPciConfigSlot[];
+ULONG HalpPciPowerStack[] = { 0x0800,
+ 0x1000,
+ 0x2000,
+ 0x4000,
+ 0x10000,
+ 0x20000,
+ 0x40000,
+ 0x80000,
+ 0x8000
+ };
+
+BOOLEAN
+HalpSetSystemType( PLOADER_PARAMETER_BLOCK LoaderBlock );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpSetSystemType)
+#endif
+
+BOOLEAN
+HalpSetSystemType( PLOADER_PARAMETER_BLOCK LoaderBlock )
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey;
+
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ SystemClass,
+ ArcSystem,
+ &MatchKey);
+
+ if (ConfigurationEntry != NULL) {
+
+
+#if DBG
+ //DbgPrint("HAL: System configuration = %s\n",ConfigurationEntry->ComponentEntry.Identifier);
+#endif
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"MOTOROLA-Big Bend")) {
+ HalpSystemType = MOTOROLA_BIG_BEND;
+ nvr_system_type = nvr_systype_bigbend;
+
+ } else {
+ //
+ // Assume it is a PowerStack or OEM'ed PowerStack
+ //
+ //
+ HalpSystemType = MOTOROLA_POWERSTACK;
+ nvr_system_type = nvr_systype_powerstack;
+ //
+ // Change PCI addresses for Blackhawk
+ // to support other PCI video boards.
+ //
+ memcpy(HalpPciConfigSlot, HalpPciPowerStack, sizeof(HalpPciPowerStack));
+
+ }
+ }
+ return TRUE;
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxsystyp.h b/private/ntos/nthals/haleagle/ppc/pxsystyp.h
new file mode 100644
index 000000000..f58fdcbf5
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxsystyp.h
@@ -0,0 +1,44 @@
+//++
+//
+// Copyright (c) 1993 IBM Corporation
+//
+// Copyright (c) 1994, 1995 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:
+//
+// pxsystyp.h
+//
+// Abstract:
+//
+// Add a global variable to indicate which system implementation we are
+// running on. Called early in phase 0 init.
+//
+// Author:
+//
+// Bill Jones 12/94
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+
+
+BOOLEAN
+HalpSetSystemType( PLOADER_PARAMETER_BLOCK LoaderBlock );
+
+
+
+typedef enum {
+ MOTOROLA_BIG_BEND = 0,
+ MOTOROLA_POWERSTACK,
+ SYSTEM_UNKNOWN = 255
+} SYSTEM_TYPE;
+
+
+extern SYSTEM_TYPE HalpSystemType;
diff --git a/private/ntos/nthals/haleagle/ppc/pxtime.c b/private/ntos/nthals/haleagle/ppc/pxtime.c
new file mode 100644
index 000000000..7d18eb667
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxtime.c
@@ -0,0 +1,137 @@
+/*++
+
+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
+
+
+--*/
+
+#include "halp.h"
+#include "pxsystyp.h"
+
+BOOLEAN
+HalQueryRealTimeClockMk (
+ OUT PTIME_FIELDS TimeFields
+ );
+BOOLEAN
+HalSetRealTimeClockMk (
+ OUT PTIME_FIELDS TimeFields
+ );
+BOOLEAN
+HalQueryRealTimeClockDs (
+ OUT PTIME_FIELDS TimeFields
+ );
+BOOLEAN
+HalSetRealTimeClockDs (
+ OUT PTIME_FIELDS TimeFields
+ );
+
+
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+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.
+
+--*/
+
+{
+ switch (HalpSystemType) {
+
+ break;
+
+ case MOTOROLA_POWERSTACK:
+ return HalQueryRealTimeClockMk(TimeFields);
+ break;
+
+ case SYSTEM_UNKNOWN:
+ case MOTOROLA_BIG_BEND:
+ default:
+ return HalQueryRealTimeClockDs(TimeFields);
+ break;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+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.
+
+--*/
+
+{
+ switch (HalpSystemType) {
+
+ break;
+
+ case MOTOROLA_POWERSTACK:
+ return HalSetRealTimeClockMk(TimeFields);
+ break;
+
+ case SYSTEM_UNKNOWN:
+ case MOTOROLA_BIG_BEND:
+ default:
+ return HalSetRealTimeClockDs(TimeFields);
+ break;
+ }
+}
diff --git a/private/ntos/nthals/haleagle/ppc/pxusage.c b/private/ntos/nthals/haleagle/ppc/pxusage.c
new file mode 100644
index 000000000..4a9fbf1f3
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/pxusage.c
@@ -0,0 +1,503 @@
+/*++
+
+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
+
+
+
+
+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
+ )
+/*++
+
+Routine Description:
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // 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 )) {
+
+ return(FALSE);
+ }
+
+ HalpRegisterVector (ReportFlags, BusVector, Vector, Irql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+ return(TRUE);
+
+
+}
+
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+#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;
+}
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ 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
+
+
+--*/
+{
+ 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;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ 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;
+ }
+
+
+ ASSERT(pRPartList != NULL);
+ ASSERT(pTPartList != NULL);
+
+ if(pRPartList) pRPartList->Count++;
+ if(pTPartList) 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/haleagle/ppc/sysbios.c b/private/ntos/nthals/haleagle/ppc/sysbios.c
new file mode 100644
index 000000000..9aa6dc90c
--- /dev/null
+++ b/private/ntos/nthals/haleagle/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/haleagle/ppc/sysbios.h b/private/ntos/nthals/haleagle/ppc/sysbios.h
new file mode 100644
index 000000000..6119bc2d0
--- /dev/null
+++ b/private/ntos/nthals/haleagle/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/haleagle/ppc/txtpalet.h b/private/ntos/nthals/haleagle/ppc/txtpalet.h
new file mode 100644
index 000000000..307464362
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/txtpalet.h
@@ -0,0 +1,97 @@
+/******************************************************************************
+
+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.
+
+******************************************************************************/
+
+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/haleagle/ppc/x86bios.c b/private/ntos/nthals/haleagle/ppc/x86bios.c
new file mode 100644
index 000000000..1002fae70
--- /dev/null
+++ b/private/ntos/nthals/haleagle/ppc/x86bios.c
@@ -0,0 +1,1156 @@
+/*++
+
+Copyright (c) 1994 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.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ 9/26/95 Steve Johns - Motorola
+ - Don't scan last PCI slot if PowerStack
+ - Don't execute PCI ROM if BaseClass indicates not video
+
+ 3/29/96 Scott Geranen - Motorola
+ - call PCI BIOS with bus/dev/func arguments
+--*/
+
+
+#define USE_BIOS_EMULATOR
+
+
+
+#include "halp.h"
+#include "xm86.h"
+#include "x86new.h"
+#include "pxpcisup.h"
+#include "pxsystyp.h"
+#include "pci.h"
+
+extern ULONG HalpPciMaxSlots;
+extern ULONG HalpPciConfigSize;
+//
+// 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.
+
+//
+// The MPC105 and the IBM27-82660 map the device number to the AD
+// line differently. This value is used to compensate for the
+// difference. Any HAL #including this file should set this value
+// appropriately. Note that this value is subtracted from the
+// computed AD line.
+//
+#ifndef PCI_DEVICE_NUMBER_OFFSET
+#define PCI_DEVICE_NUMBER_OFFSET 0 // default value for eagle
+#endif
+
+ULONG ROM_Length;
+#define BUFFER_SIZE (64*1024)
+UCHAR ROM_Buffer[BUFFER_SIZE];
+
+
+BOOLEAN HalpInitX86Emulator(
+ VOID)
+
+{
+ULONG ROM_size = 0;
+PHYSICAL_ADDRESS PhysAddr;
+USHORT Cmd, VendorID;
+ULONG Slot, EndSlot;
+PVOID HalpVideoConfigBase;
+PUCHAR ROM_Ptr, ROM_Shadow;
+ULONG i;
+UCHAR BaseClass;
+
+
+ PhysAddr.HighPart = 0x00000000;
+
+ EndSlot = HalpPciMaxSlots;
+ if (HalpSystemType == MOTOROLA_POWERSTACK)
+ EndSlot--;
+
+ //
+ // Scan PCI slots for video BIOS ROMs, except 2 PCI "slots" on motherboard
+ //
+ for (Slot = 2; Slot < EndSlot; Slot++) {
+
+ //
+ // Create a mapping to PCI configuration space
+ //
+ if( HalpPciConfigBase == NULL) {
+
+ HalpPciConfigBase = KePhase0MapIo(PCI_CONFIG_PHYSICAL_BASE, HalpPciConfigSize);
+
+
+ if (HalpPciConfigBase == NULL) {
+ DbgPrint("\nCan't create mapping to PCI Configuration Space\n");
+ return FALSE;
+ }
+ }
+ 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
+
+ //
+ // If Base Class does not indicate video, go to next slot
+ //
+ BaseClass = READ_REGISTER_UCHAR(&((PCI_CONFIG)HalpVideoConfigBase)->ClassCode[2]);
+ if (BaseClass != 0 && BaseClass != 3)
+ continue;
+
+
+ //
+ // 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 = 0xD0000; // 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);
+
+ //
+ // Delete the mapping to PCI config space
+ //
+ HalpPciConfigBase = HalpVideoConfigBase = NULL;
+ KePhase0DeleteIoMap( PCI_CONFIG_PHYSICAL_BASE, HalpPciConfigSize);
+
+ //
+ // Create a mapping to the PCI memory space
+ //
+ HalpIoMemoryBase = KePhase0MapIo(PCI_MEMORY_BASE, ROM_size);
+
+ if (HalpIoMemoryBase == NULL) {
+ 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;
+ if (ROM_Length <= BUFFER_SIZE) {
+ for (i=0; i<ROM_Length; i++)
+ ROM_Buffer[i] = *ROM_Ptr++;
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+ }
+
+ //
+ // Setup the PCI location for calling the BIOS init code.
+ // "Slot" needs to be translated into the device number
+ // suitable for CF8/CFC config accesses. In this case,
+ // if bit 11 set, dev = 11, etc.
+ //
+ HalpVideoBus = 0;
+ HalpVideoFunction = 0;
+
+ i = HalpPciConfigSlot[Slot] >> 1;
+ HalpVideoDevice = 0;
+
+ while (i) {
+ HalpVideoDevice++;
+ i >>= 1;
+ }
+
+ HalpVideoDevice -= PCI_DEVICE_NUMBER_OFFSET;
+
+ return TRUE; // Exit slot scan after finding 1st option ROM
+ }
+
+ //
+ // Delete mapping to PCI memory space
+ //
+ HalpIoMemoryBase = NULL;
+ KePhase0DeleteIoMap(PCI_MEMORY_BASE, HalpPciConfigSize);
+
+ //
+ // Restore PCI command register
+ //
+ HalpPciConfigBase = KePhase0MapIo(PCI_CONFIG_PHYSICAL_BASE, HalpPciConfigSize);
+
+ if (HalpPciConfigBase == NULL) {
+ DbgPrint("\nCan't create mapping to PCI Configuration Space\n");
+ return FALSE;
+ }
+ HalpVideoConfigBase = (PVOID) ((ULONG) HalpPciConfigBase + HalpPciConfigSlot[Slot]);
+ WRITE_REGISTER_USHORT(&((PCI_CONFIG)HalpVideoConfigBase)->Command, Cmd);
+
+
+ } // end of if clause
+ } // end of for loop
+
+
+ //
+ // Delete mapping to PCI config space
+ //
+ if (HalpPciConfigBase) {
+ HalpPciConfigBase = NULL;
+ KePhase0DeleteIoMap(PCI_CONFIG_PHYSICAL_BASE, HalpPciConfigSize);
+ }
+
+
+ //
+ // Create a mapping to ISA memory space, unless one already exists
+ //
+ if (HalpIoMemoryBase == NULL) {
+ HalpIoMemoryBase = KePhase0MapIo(PCI_MEMORY_BASE, ROM_size);
+ }
+
+
+ if (HalpIoMemoryBase == NULL) {
+ return FALSE;
+ } else {
+ //
+ // Look for ISA option video ROM signature
+ //
+ ROM_Ptr = (PUCHAR) HalpIoMemoryBase + 0xC0000;
+ HalpRomBase = ROM_Ptr;
+ if (*ROM_Ptr == 0x55 && *(ROM_Ptr+1) == 0xAA) {
+ //
+ // Copy ROM to RAM. PCI Spec says you can't execute from ROM.
+ // ROM and video RAM sometimes can't co-exist.
+ //
+ ROM_Length = *(ROM_Ptr+2) << 9;
+ if (ROM_Length <= BUFFER_SIZE) {
+ for (i=0; i<ROM_Length; i++)
+ ROM_Buffer[i] = *ROM_Ptr++;
+ HalpRomBase = (PUCHAR) ROM_Buffer;
+ }
+ return TRUE;
+ }
+
+ //
+ // No video option ROM was found. Delete mapping to PCI memory space.
+ //
+ KePhase0DeleteIoMap(PCI_MEMORY_BASE, 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.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+
+ 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;
+
+#else
+
+ return FALSE;
+
+#endif
+
+}
+
+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.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+ 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.
+ //
+ HalpLastPciBus = 0;
+ MatchKey = 0;
+ 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++;
+ }
+
+
+ //
+ // 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;
+
+#endif
+
+ return TRUE;
+}
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(USE_BIOS_EMULATOR)
+
+ 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);
+
+#endif
+
+ 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) {
+ 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;
+
+//
+// Hardware Configuration Mechanism #1 emulation.
+//
+// The eagle does not distinguish between CF8 and CFC on reads.
+// At least one BIOS we know of writes/reads CF8 to see if HW
+// mechanism 1 is implemented.
+//
+ULONG x86CF8Shadow;
+
+//
+// Hardware Configuration Mechanism #2 emulation.
+//
+static struct {
+ UCHAR CSE;
+ UCHAR Forward;
+} x86ConfigMechanism2 = { 0, 0};
+
+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;
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Convert mechanism #2 config accesses to mechanism #1.
+ //
+ if (((PortNumber & 0xF000) == 0xC000) &&
+ ((x86ConfigMechanism2.CSE & 0xF0) != 0)) {
+
+ WRITE_REGISTER_ULONG(x86BiosIoSpace + 0xCF8,
+ (1 << 31) | // Enable
+ (x86ConfigMechanism2.Forward << 16) | // Bus
+ ((((PortNumber & 0x0F00) >> 8) + 11) << 11) | // Dev
+ (((x86ConfigMechanism2.CSE & 0x0E) >> 1) << 8) | // Function
+ (PortNumber & 0x00FC) // Register
+ );
+
+ PortNumber = 0xCFC + (PortNumber & 3); // convert to config data port
+ // and let code below do the rest
+ }
+
+ //
+ // Compute port address and read port.
+ //
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ if (DataType == BYTE_DATA) {
+ //
+ // Emulate config mechanism #2
+ //
+ if (PortNumber == 0xCF8) {
+ Result = x86ConfigMechanism2.CSE;
+ } else if (PortNumber == 0xCFA) {
+ Result = x86ConfigMechanism2.Forward;
+ } else {
+ 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 {
+ //
+ // Watch out for reads from CF8, the eagle will generate a config
+ // cycle rather than returning the contents of the CONFIG_ADDR reg.
+ //
+ if (PortNumber == 0xCF8) {
+
+ Result = x86CF8Shadow;
+
+ } 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);
+ }
+ }
+
+ 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.
+
+--*/
+
+{
+
+ union {
+ PUCHAR Byte;
+ PUSHORT Word;
+ PULONG Long;
+ } u;
+
+ //
+ // Convert mechanism #2 config accesses to mechanism #1.
+ //
+ if (((PortNumber & 0xF000) == 0xC000) &&
+ ((x86ConfigMechanism2.CSE & 0xF0) != 0)) {
+
+ WRITE_REGISTER_ULONG(x86BiosIoSpace + 0xCF8,
+ (1 << 31) | // Enable
+ (x86ConfigMechanism2.Forward << 16) | // Bus
+ ((((PortNumber & 0x0F00) >> 8) + 11) << 11) | // Dev
+ (((x86ConfigMechanism2.CSE & 0x0E) >> 1) << 8) | // Function
+ (PortNumber & 0x00FC) // Register
+ );
+
+ PortNumber = 0xCFC + (PortNumber & 3); // convert to config data port
+ // and let code below do the rest
+ }
+
+ //
+ // Compute port address and read port.
+ //
+
+ u.Long = (PULONG)(x86BiosIoSpace + PortNumber);
+ if (DataType == BYTE_DATA) {
+ //
+ // Emulate config mechanism #2
+ //
+ if (PortNumber == 0xCF8) {
+ x86ConfigMechanism2.CSE = (UCHAR)Value;
+ } else if (PortNumber == 0xCFA) {
+ x86ConfigMechanism2.Forward = (UCHAR)Value;
+ } else {
+ WRITE_REGISTER_UCHAR(u.Byte, (UCHAR)Value);
+ }
+
+ } else if (DataType == LONG_DATA) {
+ 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);
+
+ //
+ // Shadow writes to CF8.
+ //
+ if (PortNumber == 0xCF8) {
+ x86CF8Shadow = 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/haleagle/sources b/private/ntos/nthals/haleagle/sources
new file mode 100644
index 000000000..858f3bce6
--- /dev/null
+++ b/private/ntos/nthals/haleagle/sources
@@ -0,0 +1,97 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ Motorola Eagle based systems.
+
+
+
+Author:
+
+ Bill Jones - 12/15/94
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=haleagle
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=..\x86new\obj\*\x86new.lib \
+ $(BASEDIR)\public\sdk\lib\*\libc.lib
+
+!IF $(PPC)
+
+TARGETTYPE=HAL
+
+!ELSE
+
+TARGETTYPE=DRIVER
+
+!ENDIF
+
+C_DEFINES=-D_HALNVR_
+
+INCLUDES=..\x86new;..\..\inc;
+
+SOURCES=
+
+PPC_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ ppc\fwnvr.c \
+ ppc\mk48time.c \
+ ppc\pxbeep.c \
+ ppc\pxbusdat.c \
+ ppc\pxcache.s \
+ ppc\pxcalstl.c \
+ ppc\pxclksup.s \
+ ppc\pxclock.c \
+ ppc\pxdat.c \
+ ppc\pxdisp.c \
+ ppc\pxds1385.c \
+ ppc\pxenviro.c \
+ ppc\pxflshbf.s \
+ ppc\pxflshio.c \
+ ppc\pxhwsup.c \
+ ppc\pxidle.c \
+ ppc\pxinfo.c \
+ ppc\pxinithl.c \
+ ppc\pxintsup.s \
+ ppc\pxirql.c \
+ ppc\pxisabus.c \
+ ppc\pxl2.s \
+ ppc\pxmapio.c \
+ ppc\pxmemctl.c \
+ ppc\pxmisc.s \
+ ppc\pxpcibrd.c \
+ ppc\pxpcibus.c \
+ ppc\pxpciint.c \
+ ppc\pxpcisup.c \
+ ppc\pxport.c \
+ ppc\pxpower.s \
+ ppc\pxproc.c \
+ ppc\pxprof.c \
+ ppc\pxreset.s \
+ ppc\pxreturn.c \
+ ppc\pxsiosup.c \
+ ppc\pxstall.s \
+ ppc\pxsysbus.c \
+ ppc\pxsysint.c \
+ ppc\pxsystyp.c \
+ ppc\pxtime.c \
+ ppc\pxusage.c \
+ ppc\x86bios.c \
+ ppc\ctrlops.c \
+ ppc\sysbios.c \
+ ppc\pcibios.c
+
+DLLDEF=obj\*\hal.def
+