summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halvict
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halvict
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/nthals/halvict')
-rw-r--r--private/ntos/nthals/halvict/hal.rc11
-rw-r--r--private/ntos/nthals/halvict/makefile6
-rw-r--r--private/ntos/nthals/halvict/ppc/fwnvr.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxbbl.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxbeep.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxbl.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxbusdat.c281
-rw-r--r--private/ntos/nthals/halvict/ppc/pxcache.s1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxcalstl.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxclksup.s1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxclock.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxdat.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxdisp.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxenviro.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxfirsup.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxflshbf.s1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxflshio.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxhwsup.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxidle.c85
-rw-r--r--private/ntos/nthals/halvict/ppc/pxinfo.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxinithl.c506
-rw-r--r--private/ntos/nthals/halvict/ppc/pxintrpt.c1505
-rw-r--r--private/ntos/nthals/halvict/ppc/pxintrpt.h103
-rw-r--r--private/ntos/nthals/halvict/ppc/pxirql.c337
-rw-r--r--private/ntos/nthals/halvict/ppc/pxisabus.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxmapio.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxmemctl.c706
-rw-r--r--private/ntos/nthals/halvict/ppc/pxmemctl.h143
-rw-r--r--private/ntos/nthals/halvict/ppc/pxmisc.s2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxnatsup.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxp91.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxpcibrd.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxpcibus.c2318
-rw-r--r--private/ntos/nthals/halvict/ppc/pxpciint.c290
-rw-r--r--private/ntos/nthals/halvict/ppc/pxpcisup.c708
-rw-r--r--private/ntos/nthals/halvict/ppc/pxport.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxpower.s1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxproc.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxprof.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxreset.s557
-rw-r--r--private/ntos/nthals/halvict/ppc/pxreturn.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxs3.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxshadbf.s2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxstall.s1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxsysbus.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxtime.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxusage.c1
-rw-r--r--private/ntos/nthals/halvict/ppc/pxvm.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/pxwd.c2
-rw-r--r--private/ntos/nthals/halvict/ppc/x86bios.c1
-rw-r--r--private/ntos/nthals/halvict/sources107
51 files changed, 7712 insertions, 0 deletions
diff --git a/private/ntos/nthals/halvict/hal.rc b/private/ntos/nthals/halvict/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halvict/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/halvict/makefile b/private/ntos/nthals/halvict/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halvict/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/halvict/ppc/fwnvr.c b/private/ntos/nthals/halvict/ppc/fwnvr.c
new file mode 100644
index 000000000..74d30689e
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/fwnvr.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\fwnvr.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxbbl.c b/private/ntos/nthals/halvict/ppc/pxbbl.c
new file mode 100644
index 000000000..5466a07f1
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxbbl.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxbbl.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxbeep.c b/private/ntos/nthals/halvict/ppc/pxbeep.c
new file mode 100644
index 000000000..cb3db8ccc
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxbeep.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxbeep.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxbl.c b/private/ntos/nthals/halvict/ppc/pxbl.c
new file mode 100644
index 000000000..c80af0ce0
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxbl.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxbl.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxbusdat.c b/private/ntos/nthals/halvict/ppc/pxbusdat.c
new file mode 100644
index 000000000..88573c58d
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxbusdat.c
@@ -0,0 +1,281 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Ken Reneris (kenr) July-28-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+ Chris P. Karamatas (ckaramatas@vnet.ibm.com) 2.96 - Merged for common HAL
+
+--*/
+
+#include "halp.h"
+#include "ibmppc.h"
+
+VOID HalpInitOtherBuses (VOID);
+
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+//
+// Prototype for system bus handlers
+//
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetIsaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+ Bus = HalpAllocateBusHandler (Internal, -1, 0, -1, 0, 0);
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus 0
+
+ Bus = HalpAllocateBusHandler (Isa, -1, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->GetInterruptVector = HalpGetIsaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+
+ HalpInitOtherBuses ();
+}
+
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ )
+/*++
+
+Routine Description:
+
+ Stub function to map old style code into new HalRegisterBusHandler code.
+
+ Note we can add our specific bus handler functions after this bus
+ handler structure has been added since this is being done during
+ hal initialization.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+ extern UCHAR HalpEpciMin;
+ extern UCHAR HalpEpciMax;
+
+ //
+ // 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->PrefetchMemory.Base = 1;
+
+ switch (InterfaceType) {
+ case Internal:
+ //
+ // This is a logical mapping of the 60X bus.
+ //
+ Bus->BusAddresses->Memory.Limit = 0xFEFFFFFF;
+ Bus->BusAddresses->Memory.SystemAddressSpace = 0;
+ Bus->BusAddresses->Memory.SystemBase = 0;
+ Bus->BusAddresses->IO.SystemBase = 0x80000000;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0;
+
+ break;
+
+ case PCIBus:
+
+ if (HalpSystemType == IBM_DORAL) {
+
+ //
+ // DORAL Cpu to PCI Addressing model. (See Doral spec,
+ // PCI Bridge Function).
+ //
+ // CPU Address PCI I/O PCI MEM EPCI I/O EPCI MEM
+ // Addr Addr Addr Addr
+ //
+ // 0x80000000 0
+ // 0x9fffffff 1fffffff
+ // 0xa0000000 20000000
+ // 0xafffffff 2fffffff
+ // 0xb0000000
+ // 0xbfffffff
+ // 0xc0000000 0
+ // 0xdfffffff 1fffffff
+ // 0xe0000000 20000000
+ // 0xfeffffff 3effffff *
+ //
+ // * This is 4GB - 16MB (-1), which is unclear from the spec but
+ // required.
+ //
+
+ if ( (BusNumber < HalpEpciMin) || (BusNumber > HalpEpciMax) ) {
+ //
+ // PCI bus.
+ //
+ Bus->BusAddresses->IO.SystemBase = 0x80000000;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0x00000000;
+ Bus->BusAddresses->IO.Limit = 0x1fffffff;
+
+ Bus->BusAddresses->Memory.SystemBase = 0xc0000000;
+ Bus->BusAddresses->Memory.SystemAddressSpace = 0x00000000;
+ Bus->BusAddresses->Memory.Limit = 0x1fffffff;
+ } else {
+ //
+ // EPCI bus.
+ //
+ Bus->BusAddresses->IO.SystemBase = 0x80000000;
+ Bus->BusAddresses->IO.Base = 0x20000000;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0x00000000;
+ Bus->BusAddresses->IO.Limit = 0x2fffffff;
+
+ Bus->BusAddresses->Memory.SystemBase = 0xc0000000;
+ Bus->BusAddresses->Memory.Base = 0x20000000;
+ Bus->BusAddresses->Memory.SystemAddressSpace = 0x00000000;
+ Bus->BusAddresses->Memory.Limit = 0x3effffff;
+ }
+
+ } else { // All other (NON-Doral) IBM PPC's Fall through here
+
+ 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;
+
+ }
+ break;
+
+ default:
+ // EISA, ISA, PCMCIA...
+ 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;
+
+ }
+ }
+
+ return Bus;
+}
+
diff --git a/private/ntos/nthals/halvict/ppc/pxcache.s b/private/ntos/nthals/halvict/ppc/pxcache.s
new file mode 100644
index 000000000..2c5630a60
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxcache.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxcache.s>
diff --git a/private/ntos/nthals/halvict/ppc/pxcalstl.c b/private/ntos/nthals/halvict/ppc/pxcalstl.c
new file mode 100644
index 000000000..3d972b02b
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxcalstl.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxcalstl.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxclksup.s b/private/ntos/nthals/halvict/ppc/pxclksup.s
new file mode 100644
index 000000000..8452d5e05
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxclksup.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxclksup.s>
diff --git a/private/ntos/nthals/halvict/ppc/pxclock.c b/private/ntos/nthals/halvict/ppc/pxclock.c
new file mode 100644
index 000000000..16cb61886
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxclock.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxclock.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxdat.c b/private/ntos/nthals/halvict/ppc/pxdat.c
new file mode 100644
index 000000000..978438ac0
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxdat.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxdat.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxdisp.c b/private/ntos/nthals/halvict/ppc/pxdisp.c
new file mode 100644
index 000000000..103883cc6
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxdisp.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxdisp.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxenviro.c b/private/ntos/nthals/halvict/ppc/pxenviro.c
new file mode 100644
index 000000000..0f822c840
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxenviro.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxenviro.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxfirsup.c b/private/ntos/nthals/halvict/ppc/pxfirsup.c
new file mode 100644
index 000000000..5fd3db1f2
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxfirsup.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxfirsup.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxflshbf.s b/private/ntos/nthals/halvict/ppc/pxflshbf.s
new file mode 100644
index 000000000..b2e4b591d
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxflshbf.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxflshbf.s>
diff --git a/private/ntos/nthals/halvict/ppc/pxflshio.c b/private/ntos/nthals/halvict/ppc/pxflshio.c
new file mode 100644
index 000000000..5817b14f5
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxflshio.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxflshio.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxhwsup.c b/private/ntos/nthals/halvict/ppc/pxhwsup.c
new file mode 100644
index 000000000..9164059ae
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxhwsup.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxhwsup.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxidle.c b/private/ntos/nthals/halvict/ppc/pxidle.c
new file mode 100644
index 000000000..55114b480
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxidle.c
@@ -0,0 +1,85 @@
+/*++
+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"
+#include "pxmp.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.
+
+
+--*/
+
+{
+ //
+ // If this processor is newly IDLE, drop the MPIC TaskPriority register
+ // for this processor to 0 to make it a desirable target for interrupts.
+ //
+
+ if ( HALPCR->HardPriority ) {
+ HALPCR->MpicProcessorBase->TaskPriority = 0;
+ HALPCR->HardPriority = 0;
+ }
+
+#ifdef POWER_MANAGEMENT
+
+ if(HalpProcessorIdleEx != NULL) {
+ HalpProcessorIdleEx();
+ } else {
+ HalpProcessorIdle();
+ }
+
+#else
+
+ HalpEnableInterrupts();
+
+#endif // POWER_MANAGEMENT
+}
diff --git a/private/ntos/nthals/halvict/ppc/pxinfo.c b/private/ntos/nthals/halvict/ppc/pxinfo.c
new file mode 100644
index 000000000..812bd48b4
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxinfo.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxinfo.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxinithl.c b/private/ntos/nthals/halvict/ppc/pxinithl.c
new file mode 100644
index 000000000..ed0de708b
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxinithl.c
@@ -0,0 +1,506 @@
+/*++
+
+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.
+
+Copyright (c) 1993-1996 International Business Machines Corporation
+
+Module Name:
+
+ pxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.ibm.com) Initial Power PC port
+
+ Removed call to HalpMapFixedTbEntries, the PPC port
+ maps all memory via calls to MmMapIoSpace().
+ Removed call to HalpInializeInterrupts - 8259 initialized in phase 1
+ Removed Cache error handler - 601 has no cache error interrupt
+ Removed call to HalpCreateDmaSturctures - it supports internal DMA
+ internal DMA contoller.
+
+ Jake Oshins
+ Support Victory machines
+
+ Chris Karamatas (ckaramatas@vnet.ibm.com) 2.96
+ Unification
+
+--*/
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "pxmp.h"
+#include "ibmppc.h"
+
+#if _MSC_VER < 1000
+
+#define UNIQUE_PCR ((KPCR *)__builtin_get_sprg1())
+
+#else
+
+#define UNIQUE_PCR ((KPCR *)__sregister_get(273))
+
+#endif
+
+extern ADDRESS_USAGE HalpDefaultIoSpace;
+
+extern VOID HalpCopyOEMFontFile();
+
+VOID
+HalpSynchronizeExecution(
+ VOID
+ );
+
+VOID
+HalpConnectFixedInterrupts(
+ VOID
+ );
+
+VOID
+HalpMapMpicProcessorRegisters(
+ VOID
+ );
+
+ULONG
+HalpGetPhysicalProcessorNumber(
+ VOID
+ );
+
+IBM_SYSTEM_TYPE
+HalpSetSystemType(
+ PLOADER_PARAMETER_BLOCK
+ );
+
+//
+// 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, HalpSetSystemType)
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+
+#endif
+
+PVOID HalpIoControlBase = (PVOID) 0;
+PVOID HalpIoMemoryBase = (PVOID) 0;
+
+ULONG HalpInitPhase;
+ULONG HalpPhysicalIpiMask[MAXIMUM_PROCESSORS];
+
+IBM_SYSTEM_TYPE HalpSystemType;
+
+VOID
+HalpInitBusHandlers (
+ VOID
+ );
+
+VOID
+HalpInitializePciAccess (
+ VOID
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+
+IBM_SYSTEM_TYPE
+HalpSetSystemType(
+ PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ Sets the global variable HalpSystemType according to the type
+ of system we are running on. Also sets pointers to various
+ tables accordingly.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value assigned to HalpSystemType. N.B. A value
+ of IBM_UNKNOWN indicates failure.
+
+--*/
+
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey;
+ UCHAR *ptr;
+
+#define SYSTEM_IS(x) \
+ (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,(x)))
+
+#define SYSTEM_ID_STARTS(x) \
+ (!strncmp(ConfigurationEntry->ComponentEntry.Identifier, \
+ (x), \
+ strlen(x)))
+
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ SystemClass,
+ ArcSystem,
+ &MatchKey);
+
+ HalpSystemType = IBM_UNKNOWN;
+
+ if (ConfigurationEntry != NULL) {
+
+#if DBG
+
+ DbgPrint("HAL: System configuration = %s\n",
+ ConfigurationEntry->ComponentEntry.Identifier);
+
+#endif
+
+ if ( SYSTEM_IS(SID_IBM_TIGER) ) {
+ HalpSystemType = IBM_TIGER;
+ } else if ( SYSTEM_IS(SID_IBM_VICTORY) ) {
+ HalpSystemType = IBM_VICTORY;
+ } else if ( SYSTEM_IS(SID_IBM_DORAL) ||
+ SYSTEM_IS(SID_IBM_TERLINGUA) ||
+ SYSTEM_ID_STARTS(SID_IBM_DORAL_START) ||
+ SYSTEM_ID_STARTS(SID_IBM_TERLINGUA_START) ) {
+ HalpSystemType = IBM_DORAL;
+ } else {
+ DbgPrint("HAL: UNKNOWN SYSTEM: %s\n", ConfigurationEntry->ComponentEntry.Identifier);
+ }
+ } else {
+ DbgPrint("HAL: No SYSTEM Entry in Loader Block\n");
+ }
+ return HalpSystemType;
+
+#undef SYSTEM_IS
+}
+
+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.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+ ULONG ProcessorNumber;
+
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ HalpInitPhase = Phase;
+
+ Prcb = PCR->Prcb;
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ //
+ // 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;
+ }
+ }
+
+ // 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);
+ }
+
+ //
+ // Every processor needs to determine its PHYSICAL processor
+ // number (Prcb->Number is a logical s/w concept) and record
+ // it in the PER Cpu data (HAL reserved space in the PCR).
+ //
+ // Get the physical number from the processor's PIR register
+ // (Processor Id Register).
+ //
+
+ ProcessorNumber = HalpGetPhysicalProcessorNumber();
+ HALPCR->PhysicalProcessor = ProcessorNumber;
+ HalpPhysicalIpiMask[Prcb->Number] = 1 << ProcessorNumber;
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+ if ( !HalpSetSystemType(LoaderBlock) ) {
+ KeBugCheck(BAD_SYSTEM_CONFIG_INFO);
+ }
+
+ //
+ // Get access to PCI Configuration Address and Data
+ // registers.
+ //
+
+ HalpInitializePciAccess();
+
+ //
+ // Do very early planar initialization, for example,
+ // get access to the memory controller error status
+ // registers.
+ //
+
+ HalpInitPlanar();
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNewTimeIncrement = MAXIMUM_INCREMENT;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Initialize all spin locks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+#ifdef POWER_MANAGEMENT
+ //
+ // Fill in handlers for APIs which this hal supports
+ //
+
+ HalSuspendHibernateSystem = HaliSuspendHibernateSystem;
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+ HalQueryBusSlots = HaliQueryBusSlots;
+ HalSlotControl = HaliSlotControl;
+ HalCompleteSlotControl = HaliCompleteSlotControl;
+#endif // POWER_MANAGEMENT
+
+ HalpRegisterAddressUsage (&HalpDefaultIoSpace);
+
+ //
+ // initialize HalpPciMaxBuses (not really used YET)
+ //
+
+ HalpPhase0DiscoverPciBuses(LoaderBlock->ConfigurationRoot);
+
+ //
+ // Initialize the display adapter.
+ //
+
+ if (!HalpInitializeDisplay(LoaderBlock)) {
+ return FALSE;
+ }
+
+ //
+ // Initialize per Machine (as opposed to per Processor)
+ // Interrupt Hardware.
+ //
+
+ if (!HalpInitializeInterrupts()) {
+ return FALSE;
+ }
+ } else {
+
+ //
+ // Processor is not 0.
+ //
+
+ HalpMapMpicProcessorRegisters();
+ HalpConnectFixedInterrupts();
+ }
+
+ //
+ // Calibrate execution stall
+ //
+
+ HalpCalibrateStall();
+
+ //
+ // 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;
+ }
+
+ //
+ // retain the OEM Font File for later use
+ //
+
+ HalpCopyOEMFontFile();
+ HalpCopyBiosShadow();
+
+ 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.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Define a static structure that KeRaise/LowerIrql can use
+ // until access to the MPIC is initialized.
+ //
+ static MPIC_PER_PROCESSOR_REGS DummyMpicRegs;
+
+ //
+ // If this is the first processor to do so, initialize the cache
+ // sweeping routines depending on type of processor.
+ //
+
+ if ( Number == 0 ) {
+ if ( HalpCacheSweepSetup() ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+ }
+
+ //
+ // Set HAL per processor data MpicProcessorBase pointing
+ // to the above structure. This pointer will be overwritten
+ // once access to the MPIC itself is available.
+ // Note: We don't have real access to the PCR yet.
+ //
+
+ ((PPER_PROCESSOR_DATA)&UNIQUE_PCR->HalReserved)->MpicProcessorBase = &DummyMpicRegs;
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halvict/ppc/pxintrpt.c b/private/ntos/nthals/halvict/ppc/pxintrpt.c
new file mode 100644
index 000000000..4cd20cab5
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxintrpt.c
@@ -0,0 +1,1505 @@
+/*++
+
+Copyright (c) 1996 International Business Machines Corporation
+Copyright (c) 1996 Microsoft Corporation
+
+Module Name:
+
+ pxintrpt.c
+
+Abstract:
+
+ This module implements machine specific interrupt functions
+ for IBM's PowerPC Machines.
+
+ Code in this module was largely gathered from other modules
+ in earlier versions of the HAL.
+
+Author:
+
+ Peter Johnston (plj@vnet.ibm.com) Oct 1995.
+
+Environment:
+
+ Kernel mode.
+
+Revision History:
+
+ Jake Oshins
+ Made it support Victory machines
+ Chris Karamatas
+ Merged Victory/Doral/Tiger.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "pxfirsup.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxmp.h"
+#include "pxmpic2.h"
+#include "ibmppc.h"
+#include "pxintrpt.h"
+
+#if _MSC_VER >= 1000
+
+//
+// VC++ doesn't have the same intrinsics as MCL.
+//
+// Although the MSR is not strictly a SPR, the compiler recognizes
+// all ones (~0) as being the MSR and emits the appropriate code.
+//
+
+#define __builtin_set_msr(x) __sregister_set(_PPC_MSR_,x)
+
+#endif
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PVOID ServiceContext,
+ PVOID TrapFrame
+ );
+
+
+extern ADDRESS_USAGE HalpMpicSpace;
+
+//
+// The following function is called when a machine check occurs.
+//
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Provide prototype for Decrementer Interrupts on processors other
+// than 0.
+//
+
+BOOLEAN
+HalpHandleDecrementerInterrupt1 (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpHandleIpi(
+ IN PVOID Unused0,
+ IN PVOID Unused1,
+ IN PVOID TrapFrame
+ );
+
+VOID
+HalpMapMpicProcessorRegisters(
+ VOID
+ );
+
+VOID
+HalpMapMpicSpace(
+ VOID
+ );
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpConnectFixedInterrupts(
+ VOID
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpConnectFixedInterrupts)
+#pragma alloc_text(PAGE,HalpGetPCIIrq)
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#pragma alloc_text(INIT,HalpMapMpicProcessorRegisters)
+#pragma alloc_text(INIT,HalpMapMpicSpace)
+#endif
+
+
+//
+// ERRATA: MPIC2 Ipi SelectProcessor registers need their addresses
+// munged.
+//
+
+ULONG Mpic2IpiBugFix;
+
+//
+// ERRATA end.
+//
+
+//
+// Define globals for the pointers to MPIC Global and Interrupt Source
+// address spaces.
+//
+
+PMPIC_GLOBAL_REGS HalpMpicGlobal;
+PMPIC_INTERRUPT_SOURCE_REGS HalpMpicInterruptSource;
+ULONG HalpMpicBasePhysicalAddress;
+ULONG HalpMpicSupportedInts;
+ULONG HalpMpicMaxVector;
+
+
+PVOID
+HalpAssignReservedVirtualSpace(
+ ULONG BasePage,
+ ULONG LengthInPages
+ );
+
+
+#if defined(SOFT_HDD_LAMP)
+
+//
+// On PowerPC machines the HDD lamp is software driven. We
+// turn it on any time we take an interrupt from a Mass Storage
+// Controller (assuming it isn't already on) and turn it off the 2nd
+// clock tick after we turn it on if we have not received
+// any more MSC interrupts since the first clock tick.
+//
+
+HDD_LAMP_STATUS HalpHddLamp;
+
+ULONG HalpMassStorageControllerVectors;
+
+#endif
+
+extern UCHAR IrqlToTaskPriority[]; // in pxirql.c
+
+//
+// Save area for ISA interrupt mask resiters and level\edge control
+// registers. (Declared in pxfirsup.c).
+//
+
+extern UCHAR HalpSioInterrupt1Mask;
+extern UCHAR HalpSioInterrupt2Mask;
+extern UCHAR HalpSioInterrupt1Level;
+extern UCHAR HalpSioInterrupt2Level;
+
+
+VOID
+HalpMapMpicProcessorRegisters(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+
+ Map MPIC per-processor registers for this processor. Note
+ that although the logical processor Prcb->Number, may not be
+ the physical processor bt the same number. We must map the
+ registers appropriate to this physical processor.
+ Also, the VA of this space will only ever be used by THIS
+ processor so we will use HAL reserved space rather than an
+ address assigned by MmMapIoSpace, the only reason for this
+ is to save the system a page per processor (not a big deal).
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG PerProcessorRegs;
+ ULONG i;
+ PerProcessorRegs = HalpMpicBasePhysicalAddress + MPIC_PROCESSOR_0_OFFSET +
+ (HALPCR->PhysicalProcessor * MPIC_PROCESSOR_REGS_SIZE);
+
+ HALPCR->MpicProcessorBase = HalpAssignReservedVirtualSpace(
+ PerProcessorRegs >> PAGE_SHIFT,
+ 1);
+
+ if ( !HALPCR->MpicProcessorBase ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Set priority for this processor to mask ALL interrupts.
+ //
+
+ HALPCR->MpicProcessorBase->TaskPriority = MPIC_MAX_PRIORITY;
+ HALPCR->HardPriority = MPIC_MAX_PRIORITY;
+ HALPCR->PendingInterrupts = 0;
+ MPIC_SYNC();
+
+ //
+ // Reading the Acknowledge register now would give us the spurious
+ // vector,... but,... clear the In-Service Register just in case
+ // there's something still in it. This is done by writing to the
+ // EOI register.
+ //
+ // There could potentially be one in service interrupt for each
+ // level the MPIC supports, so do it that many times.
+ //
+
+ for ( i = 0 ; i < MPIC_SUPPORTED_IPI ; i++ ) {
+ HALPCR->MpicProcessorBase->EndOfInterrupt = 0;
+ MPIC_SYNC();
+ }
+}
+
+
+VOID
+HalpMapMpicSpace(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Locate and map the MPIC 2 (or 2A) controller. Initialize
+ all interrupts disabled.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG MpicBasePhysicalAddress = 0;
+ ULONG DeviceVendor;
+ ULONG i;
+ ULONG SlotNumber;
+ MPIC_ISVP InterruptSource;
+ MPIC_IPIVP IpiSource;
+
+ //
+ // Find the MPIC controller.
+ // This should probably be passed in in the h/w config, but
+ // neither the configuration nor the PCI bus have been initialized
+ // yet. So, search for it using Phase 0 routines.
+ //
+
+ for ( SlotNumber = 0; SlotNumber < 32 ; SlotNumber++ ) {
+ HalpPhase0GetPciDataByOffset(
+ 0,
+ SlotNumber,
+ &DeviceVendor,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, VendorID),
+ sizeof(DeviceVendor)
+ );
+ if ( (DeviceVendor == MPIC2_PCI_VENDOR_DEVICE) ||
+ (DeviceVendor == MPIC2A_PCI_VENDOR_DEVICE) ||
+ (DeviceVendor == HYDRA_PCI_VENDOR_DEVICE ) ) {
+ HalpPhase0GetPciDataByOffset(
+ 0,
+ SlotNumber,
+ &MpicBasePhysicalAddress,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses[0]),
+ sizeof(MpicBasePhysicalAddress)
+ );
+ break;
+ }
+ }
+
+
+ //
+ // Assert that (a) we found it, and (b) if MPIC2, its I/O space
+ // really is I/O space, or, if MPIC2A, its I/O space is PCI
+ // memory space.
+ //
+
+ if ( !MpicBasePhysicalAddress) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ // Default to standard MPIC
+ HalpMpicSupportedInts = MPIC_SUPPORTED_INTS;
+
+ switch ( DeviceVendor ) {
+
+ case MPIC2_PCI_VENDOR_DEVICE:
+ if ( !(MpicBasePhysicalAddress & 0x1) ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+ MpicBasePhysicalAddress |= 0x80000000;
+
+ //
+ // ERRATA: MPIC2 bug, the IPI SelectProcessor registers need to be
+ // munged.
+ //
+
+ Mpic2IpiBugFix = 0x2;
+
+ //
+ // ERRATA end.
+ //
+ break;
+
+ case HYDRA_PCI_VENDOR_DEVICE:
+ //
+ // For Tiger: MPIC is within Hydra, so we add 0x40000 to Hydra Base to
+ // reach MPIC space - IBMCPK
+ //
+ MpicBasePhysicalAddress += 0x40000;
+
+ HalpMpicSupportedInts = HYDRA_MPIC_SUPPORTED_INTS;
+
+ // Fall thru.
+
+ case MPIC2A_PCI_VENDOR_DEVICE:
+ if ( MpicBasePhysicalAddress & 0x1 ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+ MpicBasePhysicalAddress |= 0xc0000000;
+ break;
+
+ default:
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // Remove lower 2 bits, (I/O space indicator and "reserved").
+ //
+
+ MpicBasePhysicalAddress &= ~0x3;
+
+ HalpMpicBasePhysicalAddress = MpicBasePhysicalAddress;
+
+ //
+ // Map MPIC Global Registers and Interrupt Source Configuration
+ // registers.
+
+ HalpMpicGlobal = HalpAssignReservedVirtualSpace(
+ (MpicBasePhysicalAddress + MPIC_GLOBAL_OFFSET) >> PAGE_SHIFT,
+ 1);
+ if ( !HalpMpicGlobal ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ HalpMpicInterruptSource = HalpAssignReservedVirtualSpace(
+ (MpicBasePhysicalAddress + MPIC_INTERRUPT_SOURCE_OFFSET) >> PAGE_SHIFT,
+ 1);
+
+ if ( !HalpMpicInterruptSource ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ HalpMpicGlobal->Configuration.Mode = MPIC_MIXED_MODE;
+
+ if ( DeviceVendor == HYDRA_PCI_VENDOR_DEVICE ) {
+ //
+ // Set Hydra Feature Register bit MpicIsMaster (bit 8).
+ //
+
+ PVOID HydraBase = HalpAssignReservedVirtualSpace(
+ (MpicBasePhysicalAddress - 0x40000) >> PAGE_SHIFT,
+ 1);
+ PULONG HydraFeatureRegister = (PULONG)((ULONG)HydraBase + 0x38);
+ if ( !HydraBase ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ *HydraFeatureRegister |= 0x100;
+
+ HalpReleaseReservedVirtualSpace(HydraBase, 1);
+ }
+
+ //
+ // Disable all interrupt sources.
+ //
+
+ *(PULONG)&InterruptSource = 0;
+
+ InterruptSource.Priority = 0;
+ InterruptSource.Sense = 1;
+ InterruptSource.Polarity = 0;
+
+ for ( i = 0 ; i < HalpMpicSupportedInts ; i++ ) {
+ InterruptSource.Vector = i + MPIC_BASE_VECTOR;
+ MPIC_WAIT_SOURCE(i);
+ HalpMpicInterruptSource->Int[i].VectorPriority = InterruptSource;
+ MPIC_WAIT_SOURCE(i);
+ HalpMpicInterruptSource->Int[i].SelectProcessor = 0;
+ }
+
+ MPIC_SYNC();
+
+ //
+ // Set source 0 (the 8259) to Active High, Level Triggered.
+ //
+
+ MPIC_WAIT_SOURCE(0);
+ HalpMpicInterruptSource->Int[0].VectorPriority.Polarity = 1;
+ MPIC_SYNC();
+
+
+ //
+ // Set IPI Vector/Priority. 0 is the only one we really
+ // use. However, we set 3 to the MAX and NMI so we can
+ // use it to wake the dead when debugging (maybe).
+ //
+ // Set IPI 0 to overload vector 30 which is one of the reserved
+ // vectors on DORAL.
+ // Set IPI 1 & 2 to do nothing.
+ // Set IPI 3 to overload vector 29 which is reserved on DORAL. ALSO,
+ // set IPI 3 NMI. (Priority is irrelevant).
+ //
+
+ *(PULONG)&IpiSource = 0;
+
+ IpiSource.Vector = MPIC_IPI0_VECTOR;
+ IpiSource.Priority = 14;
+ MPIC_WAIT_IPI_SOURCE(0);
+ HalpMpicGlobal->Ipi[0].VectorPriority = IpiSource;
+
+ IpiSource.Vector = MPIC_IPI1_VECTOR;
+ IpiSource.Priority = 0;
+ MPIC_WAIT_IPI_SOURCE(1);
+ HalpMpicGlobal->Ipi[1].VectorPriority = IpiSource;
+
+ IpiSource.Vector = MPIC_IPI2_VECTOR;
+ MPIC_WAIT_IPI_SOURCE(2);
+ HalpMpicGlobal->Ipi[2].VectorPriority = IpiSource;
+
+ IpiSource.Vector = MPIC_IPI3_VECTOR;
+ IpiSource.NMI = 1;
+ MPIC_WAIT_IPI_SOURCE(3);
+ HalpMpicGlobal->Ipi[3].VectorPriority = IpiSource;
+ MPIC_SYNC();
+
+ //
+ // Initialize per processor registers for this processor.
+ //
+
+ HalpMapMpicProcessorRegisters();
+
+ //
+ // Register this I/O space as in-use.
+ //
+
+ MpicBasePhysicalAddress &= 0x7FFFFFFF; // Get bus-relative address
+
+ // Length can only be a USHORT, so we do this four times
+ HalpMpicSpace.Element[0].Start = MpicBasePhysicalAddress;
+ HalpMpicSpace.Element[0].Length = 0xFFFF;
+ HalpMpicSpace.Element[1].Start = MpicBasePhysicalAddress + 0x10000;
+ HalpMpicSpace.Element[1].Length = 0xFFFF;
+ HalpMpicSpace.Element[2].Start = MpicBasePhysicalAddress + 0x20000;
+ HalpMpicSpace.Element[2].Length = 0xFFFF;
+ HalpMpicSpace.Element[3].Start = MpicBasePhysicalAddress + 0x30000;
+ HalpMpicSpace.Element[3].Length = 0xFFFF;
+
+ switch ( DeviceVendor ) {
+ case MPIC2_PCI_VENDOR_DEVICE:
+
+ HalpMpicSpace.Type = CmResourceTypePort;
+ break;
+
+ case HYDRA_PCI_VENDOR_DEVICE:
+ case MPIC2A_PCI_VENDOR_DEVICE:
+
+ HalpMpicSpace.Type = CmResourceTypeMemory;
+ break;
+ }
+
+ HalpRegisterAddressUsage(&HalpMpicSpace);
+}
+
+
+VOID
+HalpConnectFixedInterrupts(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Set required interrupt vectors in the PCR, called once on each
+ processor in the system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Connect the machine check handler
+ //
+
+ PCR->InterruptRoutine[MACHINE_CHECK_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleMachineCheck;
+
+ //
+ // Connect the external interrupt handler
+ //
+
+ PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleExternalInterrupt;
+
+
+ //
+ // Connect directly to the decrementer handler. Processor 0 uses
+ // HalpHandleDecrementerInterrupt, other processors use
+ // HalpHandleDecrementerInterrupt1.
+ //
+
+ PCR->InterruptRoutine[DECREMENT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleDecrementerInterrupt1;
+
+ //
+ // Connect the Inter-Processor Interrupt (IPI) handler.
+ //
+
+ PCR->InterruptRoutine[MPIC_IPI0_VECTOR + DEVICE_VECTORS] =
+ (PKINTERRUPT_ROUTINE)HalpHandleIpi;
+
+ //
+ // Connect the Profile interrupt (Timer 1 IRQ0) handler.
+ //
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] =
+ (PKINTERRUPT_ROUTINE)HalpHandleProfileInterrupt;
+
+ //
+ // Enable the clock interrupt
+ //
+
+ HalpUpdateDecrementer(1000); // Get those decrementer ticks going
+
+
+}
+
+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 in 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 Vector;
+ BOOLEAN returnValue;
+ UCHAR OldIrql;
+ USHORT Isr;
+ ULONG TaskPriority;
+
+ //
+ // Read the MPIC interrupt vector.
+ //
+
+ Vector = (USHORT)(HALPCR->MpicProcessorBase->Acknowledge & 0xff);
+
+ //
+ // Check for cancelled (spurious) interrupts.
+ //
+
+ if ( Vector == 0xff ) {
+ return 0;
+ }
+
+ //
+ // Check for 8259 interrupt.
+ //
+
+ if ( Vector == MPIC_8259_VECTOR ) {
+
+ //
+ // Read the 8259 interrupt vector.
+ //
+
+ Vector = READ_REGISTER_UCHAR(HalpInterruptBase);
+
+ //
+ // Acknowledge this interrupt immediately in the MPIC2
+ // controller so higher priority 8259 interrupts can be
+ // delivered.
+ //
+
+ HALPCR->MpicProcessorBase->EndOfInterrupt = 0;
+
+ //
+ // Check for NMI interrupt before we raise irql since we would
+ // raise to a bogus level.
+ //
+
+ if (Vector == 0xFF) {
+
+ HalpHandleMachineCheck(NULL, NULL);
+ }
+
+ //
+ // check for spurious interrupt
+ //
+
+ if (Vector == SPURIOUS_VECTOR) {
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0,
+ 0x0B);
+ Isr = READ_REGISTER_UCHAR(
+ &((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0);
+
+ if (!(Isr & 0x80)) {
+
+ //
+ // Spurious interrupt
+ //
+
+ return 0;
+ }
+ }
+
+#if defined(SOFT_HDD_LAMP)
+
+ } else if ( HalpMassStorageControllerVectors & ( 1 << Vector) ) {
+ //
+ // On any Mass Storage Controller interrupt, light the HDD lamp.
+ // The system timer routines will turn it off again in a little
+ // while.
+ //
+
+ if ( !HalpHddLamp.Count ) {
+ *(PUCHAR)((PUCHAR)HalpIoControlBase + HDD_LAMP_PORT) = 1;
+ }
+ HalpHddLamp.Count = 10;
+
+#endif
+
+ }
+
+ //
+ // Raise IRQL - We rely on the MPIC and 8259 controllers to
+ // hold off any lower or equal priority interrupts. Therefore
+ // all we need do is update the PCRs notion of IRQL and re
+ // enable interrupts.
+ //
+
+ OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = HalpVectorToIrql[Vector];
+ HalpEnableInterrupts();
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ SioHandler = (PSECONDARY_DISPATCH)
+ PCR->InterruptRoutine[DEVICE_VECTORS + Vector];
+ SioInterrupt = CONTAINING_RECORD(SioHandler,
+ KINTERRUPT,
+ DispatchCode[0]);
+
+ returnValue = SioHandler(SioInterrupt,
+ SioInterrupt->ServiceContext,
+ TrapFrame
+ );
+
+ //
+ // Clear the interrupt in the appropriate controller. To
+ // avoid the possibility of being drowned with interrupts
+ // at this level, disable interrupts first (we need to
+ // return to our caller with interrupts disabled anyway).
+ //
+
+ HalpDisableInterrupts();
+
+ if ( Vector < MPIC_8259_VECTOR ) {
+ //
+ // Dismiss the interrupt in the SIO interrupt controllers.
+ //
+ // If this is a cascaded interrupt then the interrupt must
+ // be dismissed in both controllers.
+ //
+
+ if (Vector & 0x08) {
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+
+ } else {
+
+ HALPCR->MpicProcessorBase->EndOfInterrupt = 0;
+ }
+
+ //
+ // Lower IRQL without enabling external interrupts. It is
+ // possible that Irql was raised above this level and lowered
+ // back to this level in the mean time. If so, the TaskPriority
+ // will have been adjusted and we need to adjust it downwards.
+ //
+
+ PCR->CurrentIrql = OldIrql;
+
+ TaskPriority = IrqlToTaskPriority[OldIrql];
+
+ if ( TaskPriority < HALPCR->HardPriority ) {
+ HALPCR->MpicProcessorBase->TaskPriority = TaskPriority;
+ HALPCR->HardPriority = TaskPriority;
+ }
+
+ return returnValue;
+}
+
+
+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.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2EdgeLevel,
+ HalpSioInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1EdgeLevel,
+ HalpSioInterrupt1Level
+ );
+ }
+
+}
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the SIO interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the EISA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ }
+
+}
+
+VOID
+HalpEnableMpicInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the MPIC interrupt at the source.
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt that is enabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ MPIC_ISVP VectorPriority;
+
+ //
+ // Calculate the MPIC source.
+ //
+
+ ULONG Source = Vector - (DEVICE_VECTORS + MPIC_BASE_VECTOR);
+
+ MPIC_WAIT_SOURCE(Source);
+
+ VectorPriority = HalpMpicInterruptSource->Int[Source].VectorPriority;
+
+ if (Source == 0) { // special 8259 case
+ VectorPriority.Priority = 2;
+ } else if (Source < MPIC_SUPPORTED_INTS) {
+ VectorPriority.Priority = (Source / 2) + 3;
+ } else {
+ // Extra hydra poles get the same (highest) priority
+ VectorPriority.Priority = 10;
+ }
+ HalpMpicInterruptSource->Int[Source].VectorPriority = VectorPriority;
+
+
+ MPIC_WAIT_SOURCE(Source);
+
+ HalpMpicInterruptSource->Int[Source].SelectProcessor =
+ 1 << HALPCR->PhysicalProcessor;
+}
+
+VOID
+HalpDisableMpicInterrupt(
+ 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.
+
+--*/
+
+{
+ MPIC_ISVP VectorPriority;
+ //
+ // Calculate the MPIC source.
+ //
+
+ ULONG Source = Vector - (DEVICE_VECTORS + MPIC_BASE_VECTOR);
+
+ MPIC_WAIT_SOURCE(Source);
+
+ VectorPriority = HalpMpicInterruptSource->Int[Source].VectorPriority;
+ VectorPriority.Priority = 0;
+ HalpMpicInterruptSource->Int[Source].VectorPriority = VectorPriority;
+
+ if (HalpSystemType == IBM_DORAL) {
+
+ MPIC_WAIT_SOURCE(Source);
+
+ HalpMpicInterruptSource->Int[Source].SelectProcessor = 0;
+
+ }
+}
+
+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:
+
+
+--*/
+
+{
+ ULONG Vector;
+
+ //
+ // Mask all 8259 interrupts (except the cascade interrupt)
+ //
+
+ for (Vector=0;Vector<16;Vector++) {
+ if (Vector == 2)
+ continue;
+ HalpDisableSioInterrupt(Vector + DEVICE_VECTORS);
+ }
+
+ //
+ // Map MPIC space and mask interrupts.
+ //
+
+ HalpMapMpicSpace();
+
+ //
+ // Set appropriate Interrupt Vector to Irql mapping for this
+ // machine.
+ //
+
+ HalpMpicMaxVector = MPIC_BASE_VECTOR + DEVICE_VECTORS +
+ HalpMpicSupportedInts - 1;
+
+ //
+ // Reserve the external interrupt vector for exclusive use by the HAL.
+ //
+
+ PCR->ReservedVectors |= (1 << EXTERNAL_INTERRUPT_VECTOR);
+
+ return TRUE;
+
+}
+
+
+KINTERRUPT_MODE
+HalpGetInterruptMode (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+/*++
+
+Routine Description:
+
+ Force interrupt mode for (machine specific) interrupt vectors.
+ If the vector is not one of those hardwired, return the caller's
+ requested mode.
+
+ On Doral, all ISA style interrupts (8259) except 13 (Power
+ Management) are edge sensitive. 13 is level sensitive.
+
+Arguments:
+
+ Vector - Vector for which translation is being requested.
+ Irql - Not used.
+ InterruptMode - Requested mode.
+
+Return Value:
+
+ Interrupt mode for this vector.
+
+--*/
+
+
+{
+ if ((HalpSystemType == IBM_TIGER) &&
+ (Vector == DEVICE_VECTORS + 15)) {
+ return LevelSensitive;
+ } else if ( Vector == (DEVICE_VECTORS + 13) ) {
+ return LevelSensitive;
+ } else {
+ return Latched;
+ }
+}
+
+VOID
+HalpSetInterruptMode (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+/*++
+
+Routine Description:
+
+ Correct the interrupt mode for a given vector. This is a no-op
+ as the correct interrupt mode was assigned in HalpGetInterruptMode.
+
+Arguments:
+
+ Vector - Vector to correct. (Not used).
+ Irql - Not used.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+
+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 );
+
+ *Affinity = 1;
+
+ //
+ // Set the IRQL level. Map the interrupt controllers priority scheme to
+ // NT irql values. The SIO prioritizes irq's as follows:
+ //
+ // irq0, irq1, irq8, irq9 ... irq15, irq3, irq4 ... irq7.
+ //
+ // The MPIC is a straight mapping.
+ //
+
+ *Irql = HalpVectorToIrql[BusInterruptLevel];
+
+
+ //
+ // The vector is equal to the specified bus level plus the DEVICE_VECTORS.
+ //
+
+ return(BusInterruptLevel + DEVICE_VECTORS);
+
+}
+
+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 (Vector >= DEVICE_VECTORS ) {
+ if ( Vector < DEVICE_VECTORS + MPIC_BASE_VECTOR ) {
+
+ HalpDisableSioInterrupt(Vector);
+
+ } else if ( Vector <= HalpMpicMaxVector ) {
+
+ HalpDisableMpicInterrupt(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;
+ KINTERRUPT_MODE TranslatedInterruptMode;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ if ( Vector >= DEVICE_VECTORS ) {
+ if ( Vector < DEVICE_VECTORS + MPIC_BASE_VECTOR ) {
+
+ //
+ // It's an 8259 vector.
+ //
+ // Get translated interrupt mode
+ //
+
+
+ TranslatedInterruptMode = HalpGetInterruptMode(Vector,
+ Irql,
+ InterruptMode);
+
+
+ HalpEnableSioInterrupt(Vector, TranslatedInterruptMode);
+
+ } else if ( Vector <= HalpMpicMaxVector ) {
+
+ HalpEnableMpicInterrupt(Vector);
+ }
+ }
+
+ //
+ // 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.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ extern ULONG Mpic2IpiBugFix;
+ extern ULONG HalpPhysicalIpiMask[];
+ ULONG BugFix = Mpic2IpiBugFix;
+ ULONG PhysicalMask = 0;
+ PULONG PhysicalIpiMask = HalpPhysicalIpiMask;
+ ULONG OldMsr = __builtin_get_msr();
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+
+ __builtin_set_msr(OldMsr & 0xffff7fff); // Disable Interrupts
+
+ //
+ // Mask is a mask of logical CPUs. Convert it to a mask of
+ // Physical CPUs so the IPI requests will be distributed
+ // properly.
+ //
+
+ do {
+ if ( Mask & 1 ) {
+ PhysicalMask |= *PhysicalIpiMask;
+ }
+ PhysicalIpiMask++;
+ Mask >>= 1;
+ } while ( Mask );
+
+ //
+ // Send the IPI interrupt(s).
+ //
+
+ HALPCR->MpicProcessorBase->Ipi[0 ^ BugFix].SelectProcessor = PhysicalMask;
+
+ __builtin_set_msr(OldMsr); // Restore previous interrupt
+ // setting.
+ 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);
+}
+
+BOOLEAN
+HalpHandleIpi(
+ IN PVOID Unused0,
+ IN PVOID Unused1,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an Inter-Processor Interrupt
+ being received by this processor. It passes the request onto the
+ kernel.
+
+Arguments:
+
+ Unused0 - Not used.
+ Unused1 - Not used.
+ TrapFrame - Volatile context at time interrupt occured.
+
+Return Value:
+
+ Returns TRUE (this routine always succeeds).
+
+--*/
+
+{
+ KeIpiInterrupt(TrapFrame);
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halvict/ppc/pxintrpt.h b/private/ntos/nthals/halvict/ppc/pxintrpt.h
new file mode 100644
index 000000000..e75201f14
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxintrpt.h
@@ -0,0 +1,103 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ vectirql.h
+
+Abstract:
+
+ This module implements machine specific interrupt functions
+ for IBM's PowerPC Machines.
+
+ Code in this module was largely gathered from other modules
+ in earlier versions of the HAL.
+
+Author:
+
+ Chris Karamatas - Collected VectorToIrql Tables into one file.
+
+Environment:
+
+ Kernel mode.
+
+Revision History:
+
+
+--*/
+
+
+//
+// The following table maps Interrupt Vectors to the appropriate
+// IRQL. The MPIC is initialized to assign vectors 16 thru 31
+// to its sources 0 thru 15. The 8259 gives us vectors 0 thru 15.
+//
+// It is possible that we are actually dealing with a Hydra, which
+// is an MPIC with sources 0 through 19, so we have extra entries
+// in the table.
+//
+// The MPIC is also programmed with priority in ascending order by
+// vector (and source).
+//
+// This table should reflect the real mapping of vector to device
+// priority. This implementation assumes that all MPIC sources
+// are at a higher priority than 8259 sources.
+//
+
+UCHAR HalpVectorToIrql[40] = {
+
+ // 8259 Master, Priority 1 - 2
+
+ 18, // 0 Timer 1 Counter 0
+ 17, // 1 Keyboard
+ 16, // 2 Cascade (not translated)
+
+ 7, // 3 Com 2
+ 6, // 4 Com 1
+ 5, // 5 Audio
+ 4, // 6 Floppy
+ 3, // 7 Parallel Port
+
+ // 8259 Slave, Priority 3-10
+
+ 15, // 8 RTC
+ 14, // 9 Audio (MIDI), ISA Slots pin B04
+ 13, // 10 ISA Slots pin D03
+ 12, // 11 ISA Slots pin D04
+ 11, // 12 Mouse, ISA Slots pin D05
+ 10, // 13 Power Management Interrupt
+ 9, // 14 ISA Slots pin D07
+ 8, // 15 ISA Slots pin D06
+
+ // MPIC Sources - The following values are chosen arbitarily. Support
+ // should be added to reprogram the MPIC and this table
+ // once the device configuration is known.
+
+ 0, // 0 8259 interrupt, will get from above
+ 19, // 1
+ 20, // 2
+ 20, // 3
+ 21, // 4
+ 21, // 5
+ 22, // 6
+ 22, // 7
+ 23, // 8
+ 23, // 9
+ 24, // 10
+ 24, // 11
+ 25, // 12
+ 25, // 13
+ 26, // 14
+ 26, // 15
+ 26, // 16 Possible Hydra interrupt source
+ 26, // 17 Hydra
+ 26, // 18 Hydra
+ 26, // 19 Hydra
+ IPI_LEVEL, // 36 Reserved, PLUS IPI[0]
+ IPI_LEVEL, // 37 Reserved, PLUS IPI[1]
+ IPI_LEVEL, // 38 Reserved, PLUS IPI[2]
+ IPI_LEVEL, // 39 Reserved, PLUS IPI[3]
+};
+
diff --git a/private/ntos/nthals/halvict/ppc/pxirql.c b/private/ntos/nthals/halvict/ppc/pxirql.c
new file mode 100644
index 000000000..de9a694e0
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxirql.c
@@ -0,0 +1,337 @@
+// TITLE("Manipulate Interrupt Request Level")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+// Copyright (c) 1995 International Business Machines Corporation
+//
+// 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)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// Peter L Johnston (plj@vnet.ibm.com) August 1995.
+// Rewrote for Lazy IRQL based on MPIC2.
+//
+// Jake Oshins (joshins@vnet.ibm.com)
+// Support Victory machines
+//
+//--
+
+#include "halp.h"
+#include "pxmp.h"
+
+#define ISA_CONTROL ((PEISA_CONTROL) HalpIoControlBase)
+extern UCHAR HalpSioInterrupt1Mask;
+extern UCHAR HalpSioInterrupt2Mask;
+extern BOOLEAN HalpProfilingActive;
+
+#if 0
+//
+// The following is not used with Lazy IRQL/MPIC2 but the informationed
+// contained herein is useful.
+//
+// VICTORY 8259 Interrupt assignments.
+//
+// IRQ Mask Device
+//
+// 0 0001 Timer 1 Counter 0
+// 1 0002 Keyboard
+// 2 0004 2nd 8259 Cascade
+// 3 0008 Serial Port 2, EISA IRQ3
+// 4 0010 Serial Port 1, EISA IRQ4
+// 5 0020 EISA IRQ5
+// 6 0040 Floppy Disk
+// 7 0080 Parallel Port, ISA Slots pin B21
+// 8 0100 Real Time Clock
+// 9 0200 EISA IRQ9
+// 10 0400 EISA IRQ10
+// 11 0800 EISA IRQ11
+// 12 1000 Mouse
+// 13 2000 Power Management Interrupt (also SCSI)
+// 14 4000 EISA IRQ14 (Mini-SP)
+// 15 8000 EISA IRQ15
+//
+// DORAL 8259 Interrupt assignments.
+//
+// IRQ Mask Device
+//
+// 0 0001 Timer 1 Counter 0
+// 1 0002 Keyboard
+// 2 0004 2nd 8259 Cascade
+// 3 0008 Serial Port 2, ISA Slots pin B25
+// 4 0010 Serial Port 1, ISA Slots pin B24
+// 5 0020 Audio, ISA Slots pin B23
+// 6 0040 Floppy Disk
+// 7 0080 Parallel Port, ISA Slots pin B21
+// 8 0100 Real Time Clock
+// 9 0200 Audio (MIDI), ISA Slots pin B04
+// 10 0400 ISA Slots pin D03
+// 11 0800 ISA Slots pin D04
+// 12 1000 Mouse, ISA Slots pin D05
+// 13 2000 Power Management Interrupt
+// 14 4000 ISA Slots pin D07
+// 15 8000 ISA Slots pin D06
+//
+//
+// Victory MPIC2 IRQ assignments:
+// Level Source
+// 0 EISA 8259 Cascade
+// 1 On-board SCSI
+// 2 PCI Slot 1 A&C
+// 3 PCI Slot 1 B&D
+// 4 PCI Slot 2 A&C
+// 5 PCI Slot 2 B&D
+// 6 PCI Slot 3 A&C // this slot doesn't exist on some machines
+// 7 PCI Slot 3 B&D
+// 8 PCI Slot 4 A&C // beginning of secondary PCI bus
+// 9 PCI Slot 4 B&D
+// 10 PCI Slot 5 A&C
+// 11 PCI Slot 5 B&D
+// 12 PCI Slot 6 A&C
+// 13 PCI Slot 6 B&D
+// 14 PCI Slot 7 A&C
+// 15 PCI Slot 7 B&D
+
+//
+// Initialize the 8259 irql mask table.
+//
+
+USHORT Halp8259MaskTable[] = { 0x0000, // irql0 Low level
+ 0x0000, // irql1 APC
+ 0x0000, // irql2 Dispatch
+ 0x0080, // irql3 parallel
+ 0x00c0, // irql4 floppy
+ 0x00e0, // irql5 audio
+ 0x00f0, // irql6 com 1
+ 0x00f8, // irql7 com 2
+ 0x80f8, // irql8 isa pin D06
+ 0xc0f8, // irql9 isa pin D07
+ 0xe0f8, // irql10 pow
+ 0xf0f8, // irql11 mouse, isa pin D05
+ 0xf8f8, // irql12 isa pin D04
+ 0xfcf8, // irql13 isa pin D03
+ 0xfef8, // irql14 audio (MIDI), isa B04
+ 0xfff8, // irql15 rtc
+ 0xfff8, // irql16 cascade
+ 0xfffa, // irql17 kb
+ 0xfffb, // irql18 timer 1/ profile
+ 0xffff, // irql19 clock level
+ 0xffff, // irql20
+ 0xffff, // irql21
+ 0xffff, // irql22
+ 0xffff, // irql23
+ 0xffff, // irql24
+ 0xffff, // irql25
+ 0xffff, // irql26
+ 0xffff, // irql27
+ 0xffff, // irql28
+ 0xffff, // irql29 IPI Level
+ 0xffff, // irql30
+ 0xffff // irql31 High level
+ };
+#endif
+
+//
+// Map IRQL to MPIC2 TaskPriority. We are somewhat lazy here in that
+// all 8259 interrupts are considered to be at the same level. This
+// is so we can avoid setting the 8259 mask registers for the majority
+// of Raise/Lower Irqls.
+//
+
+UCHAR IrqlToTaskPriority[32] = {
+
+ // User, APC and DISPATCH level all get TaskPriority of 1.
+ // (TaskPriority of 0 is for the IDLE loop).
+
+ 1, // 0
+ 1, // 1
+ 1, // 2
+
+ // 8259 - mask source 0 (at priority 2) in the MPIC
+
+ 2, // 3 - 18
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+ 2, //
+
+ // MPIC source 1 (priority 3)
+
+ // Spread this across the Victory
+ // PCI slots, with emphasis on the
+ // secondary PCI bus.
+ 3, // 19
+ 4, // 20
+ 5, // 21
+ 6, // 22
+ 7, // 23
+ 8, // 24
+ 9, // 25
+ 10, // 26
+
+ // The following, except HIGH_LEVEL aren't used by Victory.
+ // Doral needs them.
+
+ 11, // 27
+ 12, // 28 DECREMENTER_LEVEL
+ 14, // 29 IPI_LEVEL
+
+ // MPIC source 15, Power Fail.
+
+ 15, // 30 POWER_LEVEL
+ 15 // 31 HIGH_LEVEL
+};
+
+
+
+
+VOID
+KiDispatchSoftwareInterrupt(
+ VOID
+ );
+
+
+VOID
+KeLowerIrql(
+ 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.
+//
+//--
+
+{
+ KIRQL OldIrql;
+ PUCHAR PIC_Address;
+ UCHAR PIC_Mask;
+
+
+ OldIrql = PCR->CurrentIrql;
+
+ //
+ // If this is a software to software transition don't change hardware
+ // interrupt state
+ //
+
+ if (OldIrql > DISPATCH_LEVEL) {
+
+ ULONG TaskPriority = IrqlToTaskPriority[NewIrql];
+
+ HalpDisableInterrupts();
+ HALPCR->MpicProcessorBase->TaskPriority = TaskPriority;
+ PCR->CurrentIrql = NewIrql;
+ HALPCR->HardPriority = TaskPriority;
+
+ if ( NewIrql <= IPI_LEVEL ) {
+
+ HalpEnableInterrupts();
+ }
+ } else {
+ PCR->CurrentIrql = NewIrql;
+ }
+
+ //
+ // check for DPC's
+ //
+
+ if ((NewIrql < DISPATCH_LEVEL) && PCR->SoftwareInterrupt) {
+ KiDispatchSoftwareInterrupt();
+ }
+}
+
+/*************************************************************************/
+
+//
+// VOID KeRaiseIrql (
+// KIRQL NewIrql,
+// PKIRQL OldIrql
+// )
+//
+// Routine Description:
+//
+// This function raises the current IRQL to the specified value and returns
+// the old IRQL value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// OldIrql - Supplies a pointer to a variable that recieves the old
+// IRQL value.
+//
+
+VOID
+KeRaiseIrql(
+ IN KIRQL NewIrql,
+ OUT PKIRQL OldIrql
+ )
+
+{
+ //
+ // If this is a software to software transition don't change hardware
+ // interrupt state
+ //
+
+ if (NewIrql > DISPATCH_LEVEL) {
+
+ ULONG TaskPriority = IrqlToTaskPriority[NewIrql];
+
+ HalpDisableInterrupts();
+
+ HALPCR->MpicProcessorBase->TaskPriority = TaskPriority;
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+ HALPCR->HardPriority = TaskPriority;
+
+ if ( NewIrql <= IPI_LEVEL ) {
+
+ HalpEnableInterrupts();
+ }
+ } else {
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+ }
+}
diff --git a/private/ntos/nthals/halvict/ppc/pxisabus.c b/private/ntos/nthals/halvict/ppc/pxisabus.c
new file mode 100644
index 000000000..a38788df8
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxisabus.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxisabus.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxmapio.c b/private/ntos/nthals/halvict/ppc/pxmapio.c
new file mode 100644
index 000000000..38b6ef09e
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxmapio.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxmapio.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxmemctl.c b/private/ntos/nthals/halvict/ppc/pxmemctl.c
new file mode 100644
index 000000000..b3ada428d
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxmemctl.c
@@ -0,0 +1,706 @@
+
+/*++
+
+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.
+
+Copyright (c) 1996 International Business Machines Corporation
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+ Jake Oshins (joshins@vnet.ibm.com)
+ Support newer Victory machines, (Lightning-2, Thunderbolt)
+ Peter L Johnston (plj@vnet.ibm.com) Handle UNION (aka Doral/Terlingua)
+
+--*/
+
+
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "pxdakota.h"
+#include "pci.h"
+#include "pcip.h"
+// #include "pxmp.h"
+#include "ibmppc.h"
+
+#define BYTE_SWAP(x) ((((x) & 0x000000ff) << 24) | \
+ (((x) & 0x0000ff00) << 8 ) | \
+ (((x) & 0x00ff0000) >> 8 ) | \
+ (((x) & 0xff000000) >> 24))
+
+//
+// Device ID/Vendor ID for IBM PCI Host Bridge (in UNION).
+//
+
+#define IBMUNIONPCIBRIDGE 0x003a1014
+
+//
+// Prototype routines to be discarded at end of phase 1.
+//
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ );
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace (
+ VOID
+ );
+
+VOID
+HalpPhase0UnMapBusConfigSpace (
+ VOID
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitPlanar)
+#pragma alloc_text(INIT,HalpMapPlanarSpace)
+#pragma alloc_text(INIT,HalpMapBusConfigSpace)
+#pragma alloc_text(INIT,HalpPhase0MapBusConfigSpace)
+#pragma alloc_text(INIT,HalpPhase0UnMapBusConfigSpace)
+#endif
+
+
+//
+// Virtual address of UNION System Control Registers (page).
+//
+
+PVOID HalpUnionControlRegs;
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ )
+
+{
+
+ ULONG pcidata;
+ static Pass = 0;
+
+ if ( Pass++ == 0 ) {
+ //
+ // This would be an error,...
+ //
+ return TRUE;
+ }
+
+ switch (HalpSystemType) {
+ case IBM_VICTORY:
+
+ // Write NMI status and control register NMISC
+ WRITE_PORT_UCHAR((PUCHAR)HalpIoControlBase + 0x61, 0x04);
+
+ // Write Mode select register PCI-Eisa bridge
+ WRITE_PORT_UCHAR((PUCHAR)HalpIoControlBase + 0x22, 0x40);
+ WRITE_PORT_UCHAR((PUCHAR)HalpIoControlBase + 0x23, 0x40);
+
+
+ // Set it so that the memory controller (montana/nevada
+ // will not cause a machine check when he is the initiator
+ // of a transaction when a pci parity error takes place
+ // won't cause a machine check. A server should probably
+ // do things like parity checking
+ // on the PCI bus, but there are lots of broken adapters
+ // out there that don't generate PCI bus parity.
+
+ // Read Montana Enable detection register (and surrounding bytes)
+
+ HalpPhase0GetPciDataByOffset(0, // primary PCI bus
+ 0, // location of Montana/Nevada
+ &pcidata,
+ 0xc0,
+ 4);
+
+ pcidata &= ~(1 << 5);
+
+ // Now write back Montana Enable detection register
+
+ HalpPhase0SetPciDataByOffset(0, // primary PCI bus
+ 0, // location of Montana/Nevada
+ &pcidata,
+ 0xc0,
+ 4);
+ break;
+ case IBM_DORAL:
+ HalpUnionControlRegs = HalpAssignReservedVirtualSpace(
+ UNION_SYSTEM_CONTROL_REG_BASE >> PAGE_SHIFT,
+ 1);
+ //
+ // If the above failed, there's nothing we can do about it now
+ // anyway.
+ //
+ break;
+ case IBM_TIGER:
+ //
+ // CPK? What goes here?
+ //
+ break;
+ }
+ return TRUE;
+}
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the interrupt acknowledge register for the 8259.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map 8259 interrupt control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ switch (HalpSystemType) {
+ case IBM_DORAL:
+ physicalAddress.LowPart = UNION_INTERRUPT_PHYSICAL_BASE;
+ break;
+ case IBM_VICTORY:
+ case IBM_TIGER:
+ physicalAddress.LowPart = INTERRUPT_PHYSICAL_BASE;
+ break;
+ }
+ HalpInterruptBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+ return TRUE;
+}
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Access to the PCI Configuration and Data registers has already been
+ obtained. This routine does nothing.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+
+{
+ return TRUE;
+}
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Access to the PCI Configuration and Data registers has already been
+ obtained. This routine does nothing.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+
+{
+ return TRUE;
+}
+
+VOID
+HalpPhase0UnMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Return the space mapped above. Except we didn't actually map
+ anything above, so do nothing.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ return;
+}
+
+VOID
+HalpDisplayRegister(
+ PUCHAR RegHex,
+ ULONG Bytes
+ )
+
+/*++
+
+Routine Description:
+
+ Displays (via HalDisplayString) a new-line terminated
+ string of hex digits representing the input value. The
+ input value is pointed to by the first argument is
+ from 1 to 4 bytes in length.
+
+Arguments:
+
+ RegHex Pointer to the value to be displayed.
+ Bytes Length of input value in bytes (1-4).
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+#define DISP_MAX 4
+
+ UCHAR RegString[(DISP_MAX * 2) + 2];
+ UCHAR Num, High, Low;
+ PUCHAR Byte = &RegString[(DISP_MAX * 2) + 1];
+
+ *Byte = '\0';
+ *--Byte = '\n';
+
+ if ( (unsigned)Bytes > DISP_MAX ) {
+ Bytes = DISP_MAX;
+ }
+
+ while (Bytes--) {
+ Num = *RegHex++;
+ High = (Num >> 4) + '0';
+ Low = (Num & 0xf) + '0';
+ if ( High > '9' ) {
+ High += ('A' - '0' - 0xA);
+ }
+ if ( Low > '9' ) {
+ Low += ('A' - '0' - 0xA);
+ }
+ *--Byte = Low;
+ *--Byte = High;
+ }
+ HalDisplayString(Byte);
+}
+
+VOID
+HalpHandleVictoryMemoryError(
+ VOID
+ )
+{
+ UCHAR StatusByte;
+ ULONG ErrorAddress;
+
+ //
+ // Read the error address register first
+ //
+
+
+ ErrorAddress = READ_PORT_ULONG(HalpErrorAddressRegister);
+
+ //
+ // Check TEA conditions
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->MemoryParityErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString("TEA: Memory Parity Error at Address ");
+ HalpDisplayRegister((PUCHAR)&ErrorAddress, sizeof(ErrorAddress));
+ }
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->L2CacheErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString ("TEA: L2 Cache Parity Error\n");
+ }
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->TransferErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString ("TEA: Transfer Error at Address ");
+ HalpDisplayRegister((PUCHAR)&ErrorAddress, sizeof(ErrorAddress));
+ }
+}
+
+VOID
+HalpHandleTigerMemoryError(
+ VOID
+ )
+{
+ // CPK: Your turn. (plj).
+}
+
+VOID
+HalpHandleDoralMemoryError(
+ VOID
+ )
+
+{
+ static ULONG RecursionLevel = 0;
+ ULONG Status;
+ ULONG Address;
+ ULONG PciCsr0;
+ ULONG PciCsr1;
+ ULONG PciPlssr0;
+ ULONG PciPlssr1;
+ ULONG MemErrorStatus;
+ ULONG MemErrorAddress;
+ ULONG OldPciConfigAddress;
+ ULONG HostBridgePciAddress = 0x80000000;
+ ULONG PciConfigData;
+ ULONG PciBridgeFound = 0;
+ UCHAR Syndrome = 0;
+ PCHAR PciBusString;
+ extern KSPIN_LOCK HalpPCIConfigLock;
+ extern PVOID HalpPciConfigAddr[];
+ extern PVOID HalpPciConfigData[];
+ extern UCHAR HalpEpciMin;
+
+ switch ( ++RecursionLevel ) {
+ case 1:
+ //
+ // Read the System Error Status Register and try to display
+ // something reasonable based on what's in there.
+ //
+
+ Status = *(PULONG)((ULONG)HalpUnionControlRegs + UNION_SESR);
+ Status = BYTE_SWAP(Status);
+
+ //
+ // Before calling HalDisplayString which will interact with
+ // the PCI bus, try to gather all the pertinent info.
+ //
+ PciCsr0 = *((PULONG)HalpPciConfigAddr[0] + UNION_PCI_CSR_OFFSET);
+ PciCsr1 = *((PULONG)HalpPciConfigAddr[1] + UNION_PCI_CSR_OFFSET);
+ PciPlssr0 = *((PULONG)HalpPciConfigAddr[0] + UNION_PCI_PLSSR_OFFSET);
+ PciPlssr1 = *((PULONG)HalpPciConfigAddr[1] + UNION_PCI_PLSSR_OFFSET);
+
+ if ( Status & ~(UNION_SEAR_NOT_SET) ) {
+ //
+ // Status Error Address Register contains valid data,
+ // display it also.
+ //
+ Address = *(PULONG)((ULONG)HalpUnionControlRegs + UNION_SEAR);
+ Address = BYTE_SWAP(Address);
+
+ } else if ( Status &
+ (UNION_SESR_PCI32_BUS_MASTER | UNION_SESR_PCI64_BUS_MASTER) ) {
+
+ ULONG i = 0;
+ PciBusString = "on the 32 bit PCI bus.\n";
+ if ( Status & UNION_SESR_PCI64_BUS_MASTER ) {
+ i = 1;
+ PciBusString = "on the 64 bit PCI bus.\n";
+ }
+
+ //
+ // The error was a PCI error. It is possible we are still
+ // holding the PCI config access lock, so, unconditionally
+ // blow it away.
+ //
+ // However, we need to access the PCI config space for the
+ // bridge, so we need the lock but cannot acquire it in the
+ // usual way, (a) because it may already be locked, and (b)
+ // KeAcquireSpinLock will change IRQL.
+ //
+ // WARNING: Arcane knowledge about what a KSPIN_LOCK really
+ // is!
+ //
+
+ HalpPCIConfigLock = 0xdeaddead;
+ __builtin_isync();
+
+ //
+ // Get current value of this bridge's PCI CONFIG ADDRESS
+ // register.
+ //
+
+ OldPciConfigAddress = *(PULONG)(HalpPciConfigAddr[i]);
+ __builtin_sync();
+
+ //
+ // Set address for access to the host PCI bridge's config
+ // space.
+ //
+
+ if ( i != 0 ) {
+ //
+ // EPCI Bridge.
+ //
+
+ HostBridgePciAddress |= HalpEpciMin << 16;
+ }
+
+ *(PULONG)(HalpPciConfigAddr[i]) = HostBridgePciAddress;
+ __builtin_sync();
+
+ PciConfigData = *(PULONG)(HalpPciConfigData[i]);
+
+ if ( PciConfigData == IBMUNIONPCIBRIDGE ) {
+ PciBridgeFound = 1;
+ *(PULONG)(HalpPciConfigAddr[i]) = HostBridgePciAddress + 4;
+ __builtin_sync();
+
+ PciConfigData = *(PULONG)(HalpPciConfigData[i]);
+ }
+
+ //
+ // Release spin lock.
+ //
+
+ HalpPCIConfigLock = 0;
+ }
+
+ if ( Status & UNION_SESR_CPU_MEMORY_ACCESS ) {
+ //
+ // Memory Error. Read the Memory Error Status and
+ // Memory Error Address registers as well.
+ //
+ MemErrorStatus = *(PULONG)
+ ((ULONG)HalpUnionControlRegs + UNION_MESR);
+ MemErrorStatus = BYTE_SWAP(MemErrorStatus);
+ MemErrorAddress = *(PULONG)
+ ((ULONG)HalpUnionControlRegs + UNION_MEAR);
+ MemErrorAddress = BYTE_SWAP(MemErrorAddress);
+ Syndrome = (UCHAR)(MemErrorStatus & 0xff);
+ }
+
+ HalDisplayString("Machine Check : System Error Status = 0x");
+ HalpDisplayRegister((PUCHAR)&Status, sizeof(Status));
+
+ if ( Status & ~(UNION_SEAR_NOT_SET) ) {
+ HalDisplayString(" System Error Address = 0x");
+ HalpDisplayRegister((PUCHAR)&Address, sizeof(Address));
+ }
+
+ //
+ // The following strangness is just in case it is possible
+ // for more than one bit to be set.
+ //
+
+ if ( Status & UNION_SESR_CHECKSTOP ) {
+ HalDisplayString("UNION initiated checkstop.\n");
+ }
+
+ if ( Status & UNION_SESR_FLASH_WRITE ) {
+ HalDisplayString("FLASH Write Error. A write to flash\n");
+ HalDisplayString("memory was attempted but is not enabled.\n");
+ }
+
+ if ( Status & UNION_SESR_IGMC_ACCESS ) {
+ HalDisplayString("Access performed to IGMC when not enabled.\n");
+ }
+
+ if ( Status & UNION_SESR_DISABLED_ADDRESS ) {
+ HalDisplayString("Access performed to system I/O\n");
+ HalDisplayString("address space that is not enabled.\n");
+ }
+
+ if ( Status & UNION_SESR_T1_ACCESS ) {
+ HalDisplayString(
+ "T = 1 Access Error, a T = 1 PIO cycle was detected.\n");
+ }
+
+ if ( Status & UNION_SESR_ADDRESS_BUS_PARITY ) {
+ HalDisplayString("Address bus parity error.\n");
+ }
+
+ if ( Status & UNION_SESR_DATA_BUS_PARITY ) {
+ HalDisplayString("Data bus parity error.\n");
+ }
+
+ if ( Status & UNION_SESR_NO_L2_HIT_ACCESS ) {
+ HalDisplayString(
+ "L2_HIT_signal not active after AACK_; Addressing error.\n");
+ }
+
+ if ( Status & UNION_SESR_CPU_TO_PCI_ACCESS ) {
+ HalDisplayString(
+ "An error occurred on PCI bus while processing a load/store request.\n");
+ }
+
+ if ( Status &
+ (UNION_SESR_PCI32_BUS_MASTER | UNION_SESR_PCI64_BUS_MASTER) ) {
+ HalDisplayString(
+ "An error occurred during a PCI master initiated operation\n");
+ HalDisplayString(PciBusString);
+ HalDisplayString("Last PCI Configuration Address = 0x");
+ HalpDisplayRegister((PUCHAR)&OldPciConfigAddress,
+ sizeof(OldPciConfigAddress));
+ if ( PciBridgeFound ) {
+ HalDisplayString("PCI Bridge Status/Command = 0x");
+ HalpDisplayRegister((PUCHAR)&PciConfigData,
+ sizeof(PciConfigData));
+ }
+ }
+ if ( PciCsr0 ) {
+ HalDisplayString("Channel Status [32 bit bus] = 0x");
+ HalpDisplayRegister((PUCHAR)&PciCsr0, sizeof(PciCsr0));
+ }
+ if ( PciPlssr0 ) {
+ HalDisplayString("Processor Load/Store Status [32 bit bus] = 0x");
+ HalpDisplayRegister((PUCHAR)&PciPlssr0, sizeof(PciPlssr0));
+ }
+ if ( PciCsr1 ) {
+ HalDisplayString("Channel Status [64 bit bus] = 0x");
+ HalpDisplayRegister((PUCHAR)&PciCsr1, sizeof(PciCsr1));
+ }
+ if ( PciPlssr1 ) {
+ HalDisplayString("Processor Load/Store Status [32 bit bus] = 0x");
+ HalpDisplayRegister((PUCHAR)&PciPlssr1, sizeof(PciPlssr1));
+ }
+
+ if ( Status & UNION_SESR_XFERDATA ) {
+ HalDisplayString(
+ "An error occured during an operation in the memory\n");
+ HalDisplayString("controller's XferData unit.\n");
+ }
+
+ if ( Status & UNION_SESR_DATA_BUS_TIMEOUT ) {
+ //
+ // N.B. This error cannot be detected except via JTAG logic
+ // as UNION will checkstop rather than machine check in this
+ // case. This error indicates that the 60x bus did not
+ // respond in 8ms.
+ //
+ HalDisplayString("Data bus timeout.\n");
+ }
+
+ if ( Status & UNION_SESR_CPU_MEMORY_ACCESS ) {
+ HalDisplayString(
+ "An error occurred during a memory access by the CPU.\n");
+ HalDisplayString("Memory Error Status Register = 0x");
+ HalpDisplayRegister((PUCHAR)&MemErrorStatus,
+ sizeof(MemErrorStatus));
+ HalDisplayString("Memory Error Address Register = 0x");
+ HalpDisplayRegister((PUCHAR)&MemErrorAddress,
+ sizeof(MemErrorAddress));
+
+ if ( MemErrorStatus & UNION_MESR_DOUBLE_BIT ) {
+ HalDisplayString(
+ "bit 0 - A double bit memory error was detected.\n");
+ HalDisplayString(
+ " Syndrome bits = 0x");
+ HalpDisplayRegister(&Syndrome, sizeof(UCHAR));
+ }
+
+ if ( MemErrorStatus & UNION_MESR_SINGLE_BIT ) {
+ HalDisplayString(
+ "bit 1 - A single bit memory error was detected/corrected.\n");
+ if ( !(MemErrorStatus & UNION_MESR_SINGLE_BIT) ) {
+ HalDisplayString(
+ " Syndrome bits = 0x");
+ HalpDisplayRegister(&Syndrome, sizeof(UCHAR));
+ } else {
+ HalDisplayString(
+ " Error Address and Syndrome are for the Double bit error only.\n");
+ }
+ }
+
+ if ( MemErrorStatus & UNION_MESR_OVERLAPPED_MEM_EXT ) {
+ HalDisplayString(
+ "bit 3 - An access to an address that is mapped in two different memory\n");
+ HalDisplayString(
+ " extents was detected. This is a System Software error.\n");
+ }
+ }
+ break;
+ case 2:
+ HalDisplayString(
+ "Machine Check while trying to report Machine Check\n");
+ default:
+ //
+ // If we get here we took a second machine check while processing
+ // the first. Just hang.
+ //
+ for (;;);
+ }
+}
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ )
+
+{
+ switch (HalpSystemType) {
+ case IBM_VICTORY:
+ HalpHandleVictoryMemoryError();
+ return;
+ case IBM_DORAL:
+ HalpHandleDoralMemoryError();
+ return;
+ case IBM_TIGER:
+ HalpHandleTigerMemoryError();
+ return;
+ }
+ return;
+}
diff --git a/private/ntos/nthals/halvict/ppc/pxmemctl.h b/private/ntos/nthals/halvict/ppc/pxmemctl.h
new file mode 100644
index 000000000..569bae171
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxmemctl.h
@@ -0,0 +1,143 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1996 International Business Machines Corporation
+
+
+Module Name:
+
+ pxmemctl.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ for an Idaho memory controller.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+ Peter L Johnston (plj@vnet.ibm.com) August 1995.
+ Doral.
+
+--*/
+
+
+//
+// define physical base addresses of planar registers (non UNION)
+//
+
+#define INTERRUPT_PHYSICAL_BASE 0xbffffff0 // physical base of interrupt source
+#define ERROR_ADDRESS_REGISTER 0xbfffeff0
+
+//
+// define physical base addresses of UNION planar registers
+//
+
+//
+// 8259 Interrupt Source (DORAL)
+//
+
+#define UNION_INTERRUPT_PHYSICAL_BASE 0xbfff7700
+
+//
+// IO Space (ISA)
+//
+
+#define IO_CONTROL_PHYSICAL_BASE 0x80000000
+
+//
+// UNION System Control Registers
+//
+
+#define UNION_SYSTEM_CONTROL_REG_BASE 0xff001000
+
+//
+// System Error Control Register (offset from UNION_SYSTEM_CONTROL_REG_BASE)
+//
+
+#define UNION_SECR 0x50
+
+//
+// System Error Status Register (offset)
+//
+
+#define UNION_SESR 0x60
+
+//
+// System Error Address Register (offset)
+//
+
+#define UNION_SEAR 0x70
+
+//
+// Memory Error Status Register (offset)
+//
+
+#define UNION_MESR 0x120
+
+//
+// Memory Error Address Register (offset)
+//
+
+#define UNION_MEAR 0x130
+
+//
+// System Error Status Register bit definitions.
+//
+
+// Reserved 0xe0000000
+#define UNION_SESR_CHECKSTOP 0x20000000
+#define UNION_SESR_FLASH_WRITE 0x10000000
+#define UNION_SESR_IGMC_ACCESS 0x08000000
+#define UNION_SESR_DISABLED_ADDRESS 0x04000000
+// Reserved 0x03f00000
+#define UNION_SESR_T1_ACCESS 0x00080000
+#define UNION_SESR_ADDRESS_BUS_PARITY 0x00040000
+#define UNION_SESR_DATA_BUS_PARITY 0x00020000
+#define UNION_SESR_NO_L2_HIT_ACCESS 0x00010000
+#define UNION_SESR_CPU_TO_PCI_ACCESS 0x00008000
+#define UNION_SESR_PCI32_BUS_MASTER 0x00004000
+#define UNION_SESR_PCI64_BUS_MASTER 0x00002000
+#define UNION_SESR_XFERDATA 0x00001000
+#define UNION_SESR_DATA_BUS_TIMEOUT 0x00000800
+#define UNION_SESR_CPU_MEMORY_ACCESS 0x00000400
+// Reserved 0x000003ff
+
+//
+// Bits 17, 18 and 19 above represent PCI initiated errors and
+// the System Error Address Register is not updated. In these
+// cases the PCI bridges or xferdata logic must be interogated
+// to determine the cause of the error. Bit 16 also requires
+// bridge interrogation.
+//
+
+#define UNION_SEAR_NOT_SET (UNION_SESR_PCI32_BUS_MASTER | \
+ UNION_SESR_PCI64_BUS_MASTER | \
+ UNION_SESR_XFERDATA)
+
+//
+// Memory Error Status Register bit definitions
+//
+
+#define UNION_MESR_DOUBLE_BIT 0x80000000
+#define UNION_MESR_SINGLE_BIT 0x40000000
+#define UNION_MESR_ADDRESS 0x20000000
+#define UNION_MESR_OVERLAPPED_MEM_EXT 0x10000000
+//reserved 0x0fffff00
+#define UNION_MESR_SYNDROME 0x000000ff
+
+//
+// UNION Channel Status Register is at offset 0x1800 from the PCI Config
+// Address register. Processor Load/Store Status Register is at offset
+// 0x1810.
+//
+
+#define UNION_PCI_CSR_OFFSET 0x1800
+#define UNION_PCI_PLSSR_OFFSET 0x1810
+
diff --git a/private/ntos/nthals/halvict/ppc/pxmisc.s b/private/ntos/nthals/halvict/ppc/pxmisc.s
new file mode 100644
index 000000000..2afe3e6da
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxmisc.s
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxmisc.s"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxnatsup.c b/private/ntos/nthals/halvict/ppc/pxnatsup.c
new file mode 100644
index 000000000..45b71d905
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxnatsup.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxnatsup.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxp91.c b/private/ntos/nthals/halvict/ppc/pxp91.c
new file mode 100644
index 000000000..0427a3f5f
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxp91.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxp91.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxpcibrd.c b/private/ntos/nthals/halvict/ppc/pxpcibrd.c
new file mode 100644
index 000000000..d10d244dd
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxpcibrd.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxpcibrd.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxpcibus.c b/private/ntos/nthals/halvict/ppc/pxpcibus.c
new file mode 100644
index 000000000..ae07be2d7
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxpcibus.c
@@ -0,0 +1,2318 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Copyright (c) 1996 International Business Machines Corporation
+
+Module Name:
+
+ pxpcidat.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+ Jim Wooldridge Port to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Chris Karamatas (ckaramatas@vnet.ibm.com) - Updated and merged support for various PPC boxes.
+ Jake Oshins (joshins@vnet.ibm.com) -- Further merging and generalization, support for more boxes.
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "ibmppc.h"
+
+#define PCI_DISPLAY_CONTROLLER 0x03
+#define PCI_PRE_REV_2 0x0
+#define IsVideoDevice(a) \
+ (((a->BaseClass == PCI_DISPLAY_CONTROLLER) && \
+ (a->SubClass == 0)) || \
+ (((a->BaseClass == PCI_PRE_REV_2) && \
+ (a->SubClass == 1))))
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+
+ULONG HalpPciMaxBuses = 0;
+extern ULONG HalpPciMaxSlots;
+extern PVOID HalpPciConfigAddr[];
+extern PVOID HalpPciConfigData[];
+extern UCHAR HalpEpciMin;
+extern UCHAR HalpEpciMax;
+
+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
+ );
+
+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, BusNo, f;
+ PBUS_HANDLER BusHandler;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ 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);
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // PCIRegInfo describes the system's PCI support as indicated by the BIOS.
+ //
+
+ HwType = PCIRegInfo->HardwareMechanism & 0xf;
+
+ //
+ // 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);
+
+ //
+ // Look for PCI controllers which have known work-arounds, and make
+ // sure they are applied.
+ //
+
+ SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) {
+ BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Check for chips with known work-arounds to apply
+ //
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x04A3 &&
+ PciData->RevisionID < 0x11) {
+
+ //
+ // 82430 PCMC controller
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+
+ buffer[0] &= ~0x08; // turn off bit 3 register 0x53
+
+ if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn
+ buffer[1] &= ~0x01; // bit 0 register 0x54
+ }
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
+ }
+
+ if (PciData->VendorID == 0x8086 &&
+ PciData->DeviceID == 0x0484 &&
+ PciData->RevisionID <= 3) {
+
+ //
+ // 82378 ISA bridge & SIO
+ //
+
+ HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+
+ buffer[0] &= ~0x1; // turn off bit 0 register 0x41
+
+ HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
+ }
+
+ } // next function
+ } // next device
+ } // next bus
+
+#if DBG
+ HalpTestPci (0);
+#endif
+}
+
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ )
+{
+ PBUS_HANDLER Bus;
+ PPCIPBUSDATA BusData;
+ ULONG UnionBridge;
+
+ 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
+
+ BusData->GetIrqRange = (PciIrqRange) HalpGetPCIIrq;
+
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+
+ BusData->MaxDevice = HalpPciMaxSlots;
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+
+ //
+ // If BusNo is in the range of busses supported on UNION's
+ // EPCI bus, initialize the BusData for the appropriate
+ // bridge.
+ //
+ // N.B. Initialization is such that non-UNION machines
+ // correct values are obtained.
+ //
+ if ( (BusNo < HalpEpciMin) || (BusNo > HalpEpciMax) ) {
+ UnionBridge = 0;
+ } else {
+ UnionBridge = 1;
+ }
+ BusData->Config.Type2.Address =
+ HalpPciConfigAddr[UnionBridge];
+ BusData->Config.Type2.Data =
+ HalpPciConfigData[UnionBridge];
+
+ //
+ // Early PCI machines didn't decode the last bit of
+ // the device id. Shrink type 2 support max device.
+ //
+ BusData->MaxDevice = HalpPciMaxSlots;
+
+ 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);
+ }
+
+ //
+ // 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 DBG
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line (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
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+ 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) { //IBMCPK: added =
+ return FALSE;
+ }
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Sandalfoot doesn't support Multifunction adapters
+ //
+
+// return FALSE;
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+
+ 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.AsULONG);
+
+
+}
+
+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 = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.AsULONG);
+
+ 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;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ *Buffer = Tmp.Bytes[i];
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ *Buffer++ = Tmp.Bytes[i++];
+ if ( i == sizeof(ULONG) ) {
+ PciCfg1->u.bits.RegisterNumber++;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ i = 0;
+ }
+ *Buffer = Tmp.Bytes[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(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG(BusData->Config.Type2.Data);
+
+ return sizeof(ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ Tmp.Bytes[i] = *Buffer;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All);
+
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ Tmp.Bytes[i++] = *Buffer++;
+ if ( i == sizeof(ULONG) ) {
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All);
+ PciCfg1->u.bits.RegisterNumber++;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ i = 0;
+ }
+ Tmp.Bytes[i] = *Buffer;
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All);
+
+ 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(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG(BusData->Config.Type2.Data, *((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 resources
+ 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;
+ }
+
+ 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 resource for each PCI resource
+ //
+
+ // Clear ROM reserved bits
+
+ *BaseAddress[RomIndex] &= ~0x7FF;
+
+ 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 (!Is64BitBaseAddress(i) &&
+ 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; //IBMCPK:added -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; //IBMCPK: added -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;
+ }
+
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper half of 64 bit address since this processor
+ // only supports 32 bits of address space
+ j++;
+ }
+ }
+ }
+
+ 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
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ i = *BaseAddress[j];
+ if (i) {
+ if (i & PCI_ADDRESS_IO_SPACE) {
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+ } else {
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+ }
+ CmDescriptor++;
+ }
+
+ if (Is64BitBaseAddress(i)) {
+ // skip upper 32 bits
+ j++;
+ }
+ }
+
+ //
+ // Turn off decodes, then set new addresses
+ //
+
+ 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 (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, and BUS_MASTER decodes
+ // (use HalSetBusData since valid settings now set)
+ //
+ // But don't change video devices, they will be enabled or
+ // disabled by HalpInitializeDisplay()
+ //
+ // (For the moment, that means we are shutting off the
+ // S3 chip so that a plug-in Weitek card can get a chance
+ // to talk to GDI.
+
+ if (!(IsVideoDevice(PciData))) {
+
+ PciData->Command |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+ } else {
+
+ PciData->Command = PciOrigData->Command;
+ }
+
+ 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;
+}
+
+VOID
+HalpPhase0DiscoverPciBuses(
+ IN PCONFIGURATION_COMPONENT_DATA Component
+ )
+/*
+ This function looks down the LoaderBlock looking for nodes that
+ correspond to PCI buses. When it has found them all, it sets
+ HalpPciMaxBuses.
+*/
+{
+ // Check to see if this component would look like a "multi(x)"
+ // entry in ARC.
+ if ((Component->ComponentEntry.Class == AdapterClass) &&
+ (Component->ComponentEntry.Type == MultiFunctionAdapter)) {
+
+ //
+ // First check to see if Identifier is valid, then
+ // check the string it points to.
+ //
+ if (Component->ComponentEntry.Identifier) {
+
+ if ((Component->ComponentEntry.Identifier[0] == 'P') &&
+ (Component->ComponentEntry.Identifier[1] == 'C') &&
+ (Component->ComponentEntry.Identifier[2] == 'I')) {
+
+ HalpPciMaxBuses++; // Increment the number of PCI buses
+
+ }
+ }
+ }
+
+ //
+ // Look at the Siblings of this component
+ //
+ if (Component->Sibling) {
+ HalpPhase0DiscoverPciBuses(Component->Sibling);
+ }
+
+ //
+ // Look at the Children of this component
+ //
+ if (Component->Child) {
+ HalpPhase0DiscoverPciBuses(Component->Child);
+ }
+
+
+}
+
+#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)
+ );
+
+ 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)
+ );
+
+ 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 (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);
+ }
+
+ 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");
+ }
+
+
+ //
+ // 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)
+ );
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+#endif
diff --git a/private/ntos/nthals/halvict/ppc/pxpciint.c b/private/ntos/nthals/halvict/ppc/pxpciint.c
new file mode 100644
index 000000000..6e7fd7ab8
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxpciint.c
@@ -0,0 +1,290 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpciint.c
+
+Abstract:
+
+ All PCI bus interrupt mapping is in this module, so that a real
+ system which doesn't have all the limitations which PC PCI
+ systems have can replaced this code easly.
+ (bus memory & i/o address mappings can also be fix here)
+
+Author:
+
+ Ken Reneris
+ Jim Wooldridge - Ported to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "ibmppc.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#endif
+
+#define PCI_DISPLAY_CONTROLLER 0x03
+#define PCI_PRE_REV_2 0x0
+#define IsVideoDevice(a) \
+ (((a->BaseClass == PCI_DISPLAY_CONTROLLER) && \
+ (a->SubClass == 0)) || \
+ (((a->BaseClass == PCI_PRE_REV_2) && \
+ (a->SubClass == 1))))
+
+#define P91_DEVICE_ID 0x9100100E
+extern PHYSICAL_ADDRESS HalpP9CoprocPhysicalAddress; // in pxp91.c
+
+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
+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 Sandalfoot and Polo machines PCI interrupts are statically routed
+// via slot number. This routine just returns and the static routing
+// is done in HalpGetIsaFixedPCIIrq
+//
+
+--*/
+{
+
+
+}
+
+
+
+VOID
+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.
+
+
+--*/
+{
+}
+
+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;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG cnt;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+
+ Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ DbgPrint("Bad IRQ range\n");
+ return Status;
+ }
+
+ //
+ // Adjust resources
+ //
+
+ Status = HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ Interrupt,
+ pResourceList
+ );
+
+ ExFreePool (Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ DbgPrint("Bad HaliAdjustResourceListRange\n");
+ return Status;
+ }
+
+ //
+ // This next part is a major HACK. The Weitek video
+ // adapter (which is one of IBM's favorites) needs
+ // to have its frame buffer enabled by the HAL so
+ // that the HAL can write to the screen. The device
+ // driver for this card needs to touch the frame buffer
+ // during its initialization phase, which overlaps with
+ // the period of time that the HAL is writing to the
+ // screen. So, to avoid breaking one or the other,
+ // we need to force the device driver to use the
+ // same I/O space for the frame buffer that the HAL
+ // was using. Unfortunately, this is the only place
+ // to do it. -- Jake Oshins 1/2/96
+
+ HalpGetPCIData(BusHandler,
+ RootHandler,
+ PciSlot,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // We want to do this only for video devices that are
+ // already decoding a range of memory.
+ //
+ if ((IsVideoDevice(PciData)) &&
+ (PciData->u.type0.BaseAddresses[0] & 0xfffffffe))
+ {
+ for (cnt = (*pResourceList)->List->Count; cnt; cnt--) {
+ switch ((*pResourceList)->List->Descriptors->Type) {
+ case CmResourceTypeInterrupt:
+ case CmResourceTypePort:
+ case CmResourceTypeDma:
+ break;
+
+ case CmResourceTypeMemory:
+
+ //
+ // Set the bottom of the range to the value in the Base Address Register
+ //
+ (*pResourceList)->List->Descriptors->u.Memory.MinimumAddress.LowPart =
+ PciData->u.type0.BaseAddresses[0];
+
+ //
+ // Set the top of the range to the BAR plus the requested length
+ //
+ (*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart =
+ PciData->u.type0.BaseAddresses[0] +
+ (*pResourceList)->List->Descriptors->u.Memory.Length;
+ }
+ }
+
+ }
+
+ // JAKETEMP pull this out when reworking Baby Blue code!!!!
+
+ // Yet another MAJOR HACK!
+ //
+ // If this is a Doral/Terlingua, then space on the primary PCI bus is
+ // limited. The Baby Blue card, if it is plugged in, will require the
+ // entire upper half. Although this is ridiculous, we want to support
+ // it. And since all boot devices initialize before video, we have to
+ // make sure that nothing has claimed the upper half of the bus'
+ // address space. -- Jake Oshins 3/7/96
+
+ if ((HalpSystemType == IBM_DORAL) && (BusHandler->BusNumber == 0)) {
+ for (cnt = (*pResourceList)->List->Count; cnt; cnt--) {
+ switch ((*pResourceList)->List->Descriptors->Type) {
+ case CmResourceTypeInterrupt:
+ case CmResourceTypePort:
+ case CmResourceTypeDma:
+ break;
+
+ case CmResourceTypeMemory:
+
+ //
+ // If the requested range maximum is above the first 256MB of
+ // memory space, then the requested maximum is 256MB and the
+ // minimum is 0. (i.e. Let IoAssignResources place it anywhere
+ // in the first 256MB.
+ //
+
+ if ((*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart > 0x0fffffff) {
+ (*pResourceList)->List->Descriptors->u.Memory.MinimumAddress.LowPart = 0x0;
+ (*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart = 0x0fffffff;
+
+ }
+
+ }
+
+ }
+ }
+ return Status;
+
+}
+
+
diff --git a/private/ntos/nthals/halvict/ppc/pxpcisup.c b/private/ntos/nthals/halvict/ppc/pxpcisup.c
new file mode 100644
index 000000000..14cb7ba41
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxpcisup.c
@@ -0,0 +1,708 @@
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+ Jake Oshins
+ Support Victory machines
+ Peter Johnston
+ Merge Victory/Doral versions.
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "pxmpic2.h"
+#include "ibmppc.h"
+
+#define IsPciBridge(a) \
+ (a->VendorID != PCI_INVALID_VENDORID && \
+ PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
+ a->SubClass == 4 && a->BaseClass == 6)
+
+//
+// UNION has two top level PCI busses.
+//
+
+#define UNION_PCI_BASE_0 0xbfff8000
+#define UNION_PCI_BASE_1 0xbfef8000
+
+PVOID HalpPciConfigAddr[2];
+PVOID HalpPciConfigData[2];
+UCHAR HalpEpciMin = 0xff;
+UCHAR HalpEpciMax = 0xff;
+
+ULONG HalpPciMaxSlots = PCI_MAX_DEVICES;
+
+typedef struct _PCI_BUS_NODE {
+ struct _PCI_BUS_NODE *Sibling;
+ struct _PCI_BUS_NODE *Child;
+ ULONG BusNumber; // logical bus number
+ ULONG BaseBus; // number of the root bus
+ ULONG BaseSlot; // slot in the base bus that these PPBs are plugged into
+} PCI_BUS_NODE, *PPCI_BUS_NODE;
+
+PPCI_BUS_NODE HalpPciBusTree = NULL;
+
+UCHAR
+HalpSearchPciBridgeMap(
+ IN PPCI_BUS_NODE Node,
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER PciSlot,
+ IN UCHAR InterruptPin
+ );
+
+VOID
+HalpInitializePciAccess (
+ VOID
+ );
+
+ULONG
+HalpPhase0SetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+ULONG
+HalpPhase0GetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIrq)
+#pragma alloc_text(INIT,HalpInitializePciAccess)
+#pragma alloc_text(INIT,HalpPhase0GetPciDataByOffset)
+#pragma alloc_text(INIT,HalpPhase0SetPciDataByOffset)
+#pragma alloc_text(PAGE,HalpSearchPciBridgeMap)
+#endif
+
+
+
+
+VOID
+HalpInitializePciAccess (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Fill the HalpPciConfigAddr and HalpPciConfigData arrays with
+ virtual addresses used to access the various top level PCI
+ busses on this machine.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if ( HalpSystemType != IBM_DORAL ) {
+ HalpPciConfigAddr[0] = (PVOID)((ULONG)HalpIoControlBase + 0xcf8);
+ HalpPciConfigData[0] = (PVOID)((ULONG)HalpIoControlBase + 0xcfc);
+
+ return;
+ }
+
+ //
+ // UNION based systems (eg Doral)
+ //
+
+ HalpPciConfigAddr[0] = HalpAssignReservedVirtualSpace(
+ UNION_PCI_BASE_0 >> PAGE_SHIFT,
+ 2);
+ HalpPciConfigData[0] = (PVOID)((ULONG)HalpPciConfigAddr[0] + 0x10);
+
+ HalpPciConfigAddr[1] = HalpAssignReservedVirtualSpace(
+ UNION_PCI_BASE_1 >> PAGE_SHIFT,
+ 2);
+ HalpPciConfigData[1] = (PVOID)((ULONG)HalpPciConfigAddr[1] + 0x10);
+
+ if ( !HalpPciConfigAddr[0] ||
+ !HalpPciConfigAddr[1] ) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+#define EPCI_KLUDGE
+#if defined(EPCI_KLUDGE)
+#define IBMHOSTPCIBRIDGE 0x003a1014
+ //
+ // The EPCI bus on doral is initialized with a bus number of 0x80
+ // for reasons unclear. Reset it so it is the next logical bus
+ // following the max PCI bus.
+ //
+ // The following code is really grungy, we should use PCI
+ // access routines to do it,.... the gist of it is
+ //
+ // (1) Check that we have an IBM Host/PCI bridge.
+ // (2) Check that it thinks it's bus 80 and subordinate
+ // bus 80 also (ie no subordinate busses).
+ // (3) Change to bus 0 subordinate bus 0.
+ //
+
+ {
+ ULONG BusInfo;
+ PULONG PciAddr = (PULONG)(HalpPciConfigAddr[0]);
+ PULONG PciData = (PULONG)(HalpPciConfigData[0]);
+ PULONG EpciAddr = (PULONG)(HalpPciConfigAddr[1]);
+ PULONG EpciData = (PULONG)(HalpPciConfigData[1]);
+ ULONG BusNo;
+ ULONG Found = 0;
+
+ //
+ // First, locate the host bridge on the PCI bus. Hopefully
+ // it's on bus 0.
+ //
+
+ *PciAddr = 0x80000000;
+ __builtin_eieio();
+ BusInfo = *PciData;
+
+ if ( BusInfo == IBMHOSTPCIBRIDGE ) {
+ //
+ // Have bridge, see what the bus range is.
+ //
+ *PciAddr = 0x80000040;
+ __builtin_eieio();
+ BusInfo = *PciData;
+ HalpEpciMin = (UCHAR)(((BusInfo >> 8) & 0xff) + 1);
+ //
+ // Now, find bridge on EPCI bus. Scan for it.
+ //
+ for ( BusNo = 0 ; BusNo < 0x100 ; BusNo++ ) {
+ *EpciAddr = 0x80000000 | (BusNo << 16);
+ __builtin_eieio();
+ BusInfo = *EpciData;
+ if ( BusInfo == IBMHOSTPCIBRIDGE ) {
+ *EpciAddr = 0x80000000 | (BusNo << 16) | 0x40;
+ __builtin_eieio();
+ BusInfo = *EpciData;
+
+ // Subordinate bus number - Primary bus number
+ HalpEpciMax = (UCHAR)(((BusInfo >> 8) & 0xff) - (BusInfo & 0xff));
+ HalpEpciMax += HalpEpciMin;
+
+ BusInfo &= 0xffff0000;
+ BusInfo |= (HalpEpciMax << 8) | HalpEpciMin;
+ *EpciData = BusInfo;
+ Found = 1;
+ break;
+ }
+ }
+ if ( !Found ) {
+ //
+ // No bridge on EPCI bus?
+ //
+ HalpEpciMin = HalpEpciMax = 0xff;
+ }
+ }
+ }
+
+#endif
+
+#define AMD_KLUDGE
+#if defined(AMD_KLUDGE)
+#define AMDPCIETHERNET 0x20001022
+ //
+ // Open firmware is configuring the AMD chip in a way we cannot
+ // deal with. It is possible to issue a hard reset on Doral/Terlingua
+ // so that's what we do here.
+ //
+
+ {
+ PULONG PciAddr = (PULONG)(HalpPciConfigAddr[0]);
+ PULONG PciData = (PULONG)(HalpPciConfigData[0]);
+ PVOID CRRBase;
+ ULONG CfgSpace[16];
+ ULONG Slot;
+ ULONG i;
+
+ for ( Slot = 0 ; Slot < 32 ; Slot++ ) {
+ HalpPhase0GetPciDataByOffset(0,
+ Slot,
+ CfgSpace,
+ 0,
+ 64);
+ if ( CfgSpace[0] == AMDPCIETHERNET ) {
+ //
+ // Change the command (and status) of this puppy
+ // so that when we write it back it's disabled.
+ //
+ CfgSpace[1] = 0;
+
+ //
+ // Ok, now we need to write to UNION's Component
+ // Reset Register for this bridge. Bits of interest
+ // are 0 thru 5 correcponding to devices 1 thru 6
+ // (spec says 0 thru 5 but they seem to want you
+ // to skip the memory controller before you start
+ // counting).
+ //
+ // Also, this register isn't byte reversed so we hit
+ // bits 24 thru 31 instead,... note that setting to
+ // 1 means leave it alone, setting to 0 resets.
+ //
+ // This register is at xxxf7ef0 which isn't mapped.
+ // This is the PCI bridge (not EPCI) so xxx in this
+ // case is bff.
+ //
+ CRRBase = HalpAssignReservedVirtualSpace(0xbfff7, 1);
+
+ if ( !CRRBase ) {
+ //
+ // Bad things happened, give up.
+ //
+ break;
+ }
+
+ *(PULONG)((ULONG)CRRBase + 0xef0) = 0xfc ^ (0x80 >> (Slot - 1));
+ //
+ // Wait a while then unset the reset bit.
+ //
+ for ( i = 0 ; i < 1000000 ; i++ ) {
+ __builtin_eieio();
+ }
+ *(PULONG)((ULONG)CRRBase + 0xef0) = 0xfc;
+ //
+ // Wait a while longer then write back the config space.
+ //
+ for ( i = 0 ; i < 1000000 ; i++ ) {
+ __builtin_eieio();
+ }
+ HalpReleaseReservedVirtualSpace(CRRBase, 1);
+ HalpPhase0SetPciDataByOffset(0,
+ Slot,
+ CfgSpace,
+ 0,
+ 64);
+ //
+ // Assume there's only one.
+ //
+ break;
+ }
+ }
+ }
+
+#endif
+
+
+}
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG BusNumber,
+ ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine translate a PCI slot number to a PCI device number.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ //
+ // Sandalfoot only has 1 PCI bus so bus number is unused
+ //
+
+ PCI_TYPE1_CFG_BITS PciConfig;
+ PCI_SLOT_NUMBER PciSlotNumber;
+
+ PciSlotNumber.u.AsULONG = SlotNumber;
+
+ PciConfig.u.AsULONG = 0;
+ PciConfig.u.bits.DeviceNumber = PciSlotNumber.u.bits.DeviceNumber;
+ PciConfig.u.bits.FunctionNumber = PciSlotNumber.u.bits.FunctionNumber;
+ PciConfig.u.bits.BusNumber = BusNumber;
+ PciConfig.u.bits.Enable = TRUE;
+
+ return (PciConfig.u.AsULONG);
+}
+
+ULONG
+HalpPhase0SetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes to PCI configuration space prior to bus handler
+ installation.
+
+Arguments:
+
+ BusNumber PCI Bus Number. This is the 8 bit BUS Number which is
+ bits 23-16 of the Configuration Address. In support of
+ multiple top level busses, the upper 24 bits of this
+ argument will supply the index into the table of
+ configuration address registers.
+ SlotNumber PCI Slot Number, 8 bits composed of the 5 bit device
+ number (bits 15-11 of the configuration address) and
+ the 3 bit function number (10-8).
+ Buffer Address of source data.
+ Offset Number of bytes to skip from base of PCI config area.
+ Length Number of bytes to write
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ PCI_TYPE1_CFG_BITS ConfigAddress;
+ ULONG ReturnLength;
+ PVOID ConfigAddressRegister;
+ PVOID ConfigDataRegister;
+ PUCHAR Bfr = (PUCHAR)Buffer;
+
+ if ( BusNumber < HalpEpciMin ) {
+ ConfigAddressRegister = HalpPciConfigAddr[0];
+ ConfigDataRegister = HalpPciConfigData[0];
+ } else {
+ ConfigAddressRegister = HalpPciConfigAddr[1];
+ ConfigDataRegister = HalpPciConfigData[1];
+ }
+
+ ASSERT(!(Offset & ~0xff));
+ ASSERT(Length);
+ ASSERT((Offset + Length) <= 256);
+
+ if ( Length + Offset > 256 ) {
+ if ( Offset > 256 ) {
+ return 0;
+ }
+ Length = 256 - Offset;
+ }
+
+ ReturnLength = Length;
+
+ ConfigAddress.u.AsULONG = HalpTranslatePciSlotNumber(BusNumber,
+ SlotNumber);
+ ConfigAddress.u.bits.RegisterNumber = (Offset & 0xfc) >> 2;
+
+ if ( Offset & 0x3 ) {
+ //
+ // Access begins at a non-register boundary in the config
+ // space. We need to read the register containing the data
+ // and rewrite only the changed data. (I wonder if this
+ // ever really happens?)
+ //
+ ULONG SubOffset = Offset & 0x3;
+ ULONG SubLength = 4 - SubOffset;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ if ( SubLength > Length ) {
+ SubLength = Length;
+ }
+
+ //
+ // Adjust Length (remaining) and (new) Offset bu amount covered
+ // in this first word.
+ //
+ Length -= SubLength;
+ Offset += SubLength;
+
+ //
+ // Get the first word (register), replace only those bytes that
+ // need to be changed, then write the whole thing back out again.
+ //
+ WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddress.u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(ConfigDataRegister);
+
+ while ( SubLength-- ) {
+ Tmp.Bytes[SubOffset++] = *Bfr++;
+ }
+
+ WRITE_PORT_ULONG(ConfigDataRegister, Tmp.All);
+
+ //
+ // Aim ConfigAddressRegister at the next word (register).
+ //
+ ConfigAddress.u.bits.RegisterNumber++;
+ }
+
+ //
+ // Do the majority of the transfer 4 bytes at a time.
+ //
+ while ( Length > sizeof(ULONG) ) {
+ ULONG Tmp = *(UNALIGNED PULONG)Bfr;
+ WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddress.u.AsULONG);
+ WRITE_PORT_ULONG(ConfigDataRegister, Tmp);
+ ConfigAddress.u.bits.RegisterNumber++;
+ Bfr += sizeof(ULONG);
+ Length -= sizeof(ULONG);
+
+ }
+
+ //
+ // Do bytes in last register.
+ //
+ if ( Length ) {
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+ ULONG i = 0;
+ WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddress.u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(ConfigDataRegister);
+
+ while ( Length-- ) {
+ Tmp.Bytes[i++] = *(PUCHAR)Bfr++;
+ }
+ WRITE_PORT_ULONG(ConfigDataRegister, Tmp.All);
+ }
+
+ return ReturnLength;
+}
+
+ULONG
+HalpPhase0GetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads PCI config space prior to bus handlder installation.
+
+Arguments:
+
+ BusNumber PCI Bus Number. This is the 8 bit BUS Number which is
+ bits 23-16 of the Configuration Address. In support of
+ multiple top level busses, the upper 24 bits of this
+ argument will supply the index into the table of
+ configuration address registers.
+ SlotNumber PCI Slot Number, 8 bits composed of the 5 bit device
+ number (bits 15-11 of the configuration address) and
+ the 3 bit function number (10-8).
+ Buffer Address of source data.
+ Offset Number of bytes to skip from base of PCI config area.
+ Length Number of bytes to write
+
+Return Value:
+
+ Amount of data read.
+
+--*/
+
+{
+ PCI_TYPE1_CFG_BITS ConfigAddress;
+ PCI_TYPE1_CFG_BITS ConfigAddressTemp;
+ ULONG ReturnLength;
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+ PVOID ConfigAddressRegister;
+ PVOID ConfigDataRegister;
+
+ if ( BusNumber < HalpEpciMin ) {
+ ConfigAddressRegister = HalpPciConfigAddr[0];
+ ConfigDataRegister = HalpPciConfigData[0];
+ } else {
+ ConfigAddressRegister = HalpPciConfigAddr[1];
+ ConfigDataRegister = HalpPciConfigData[1];
+ }
+
+ ASSERT(!(Offset & ~0xff));
+ ASSERT(Length);
+ ASSERT((Offset + Length) <= 256);
+
+ if ( Length + Offset > 256 ) {
+ if ( Offset > 256 ) {
+ return 0;
+ }
+ Length = 256 - Offset;
+ }
+
+ ReturnLength = Length;
+
+ ConfigAddress.u.AsULONG = HalpTranslatePciSlotNumber(BusNumber,
+ SlotNumber);
+ ConfigAddress.u.bits.RegisterNumber = (Offset & 0xfc) >> 2;
+
+ //
+ // If we are being asked to read data when function != 0, check
+ // first to see if this device decares itself as a multi-function
+ // device. If it doesn't, don't do this read.
+ //
+ if (ConfigAddress.u.bits.FunctionNumber != 0) {
+
+ ConfigAddressTemp.u.bits.RegisterNumber = 3; // contains header type
+ ConfigAddressTemp.u.bits.FunctionNumber = 0; // look at base package
+ ConfigAddressTemp.u.bits.DeviceNumber = ConfigAddress.u.bits.DeviceNumber;
+ ConfigAddressTemp.u.bits.BusNumber = ConfigAddress.u.bits.BusNumber;
+ ConfigAddressTemp.u.bits.Enable = TRUE;
+
+ WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddressTemp.u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(ConfigDataRegister);
+
+ if (!(Tmp.Bytes[2] & 0x80)) { // if the Header type field's multi-function bit is not set
+
+ for (i = 0; i < Length; i++) {
+ *((PUCHAR)Buffer)++ = 0xff; // Make this read as if the device isn't populated
+ }
+
+ return Length;
+ }
+ }
+
+ i = Offset & 0x3;
+
+ while ( Length ) {
+ WRITE_PORT_ULONG(ConfigAddressRegister, ConfigAddress.u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(ConfigDataRegister);
+ while ( (i < 4) && Length) {
+ *((PUCHAR)Buffer)++ = Tmp.Bytes[i];
+ i++;
+ Length--;
+ }
+ i = 0;
+ ConfigAddress.u.bits.RegisterNumber++;
+ }
+ return ReturnLength;
+}
+
+NTSTATUS
+HalpGetPCIIrq (
+ 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;
+ UCHAR InterruptPin;
+ UCHAR BaseLimit = 0;
+ UCHAR Class;
+
+ 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));
+
+ InterruptPin = PciData->u.type0.InterruptPin;
+ Class = PciData->BaseClass;
+
+ if (InterruptPin == 0) { // Device doesn't implement an interrupt
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ BaseLimit = PciData->u.type0.InterruptLine + MPIC_BASE_VECTOR;
+
+ (*Interrupt)->Base = BaseLimit;
+ (*Interrupt)->Limit = BaseLimit;
+
+#if DBG
+ DbgPrint("Interrupt line, by the hardware: 0x%x\n",
+ PciData->u.type0.InterruptLine + MPIC_BASE_VECTOR);
+#endif
+
+ if ( BaseLimit != NOT_MPIC) {
+
+#if defined(SOFT_HDD_LAMP)
+
+ if ( Class == 1 ) {
+ //
+ // This device is a Mass Storage Controller, set flag to
+ // turn on the HDD Lamp when interrupts come in on this
+ // vector.
+ //
+ // (Shouldn't there be a constant defined somewhere for
+ // the Class? (plj)).
+ //
+
+ extern ULONG HalpMassStorageControllerVectors;
+
+ HalpMassStorageControllerVectors |= 1 << BaseLimit;
+ }
+
+#endif
+
+ return STATUS_SUCCESS;
+ }
+
+ ASSERT(!(BaseLimit == NOT_MPIC)); // We should never hit this because
+ // there should never be a device
+ // with an interrupt pin != 0 that
+ // has no valid mapping to the MPIC
+ return STATUS_UNSUCCESSFUL;
+}
+
diff --git a/private/ntos/nthals/halvict/ppc/pxport.c b/private/ntos/nthals/halvict/ppc/pxport.c
new file mode 100644
index 000000000..19c0841dc
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxport.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxport.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxpower.s b/private/ntos/nthals/halvict/ppc/pxpower.s
new file mode 100644
index 000000000..39dc14e06
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxpower.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxpower.s>
diff --git a/private/ntos/nthals/halvict/ppc/pxproc.c b/private/ntos/nthals/halvict/ppc/pxproc.c
new file mode 100644
index 000000000..5a8ee0570
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxproc.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxproc.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxprof.c b/private/ntos/nthals/halvict/ppc/pxprof.c
new file mode 100644
index 000000000..5e9e3dc20
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxprof.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxprof.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxreset.s b/private/ntos/nthals/halvict/ppc/pxreset.s
new file mode 100644
index 000000000..0b6c055f7
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxreset.s
@@ -0,0 +1,557 @@
+//++
+//
+// Copyright (c) 1993, 94, 95, 96 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:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) September 1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// plj Feb 1995 Zap TLB before resetting, add 603+
+// and 604+ support.
+//
+// jlw Added eagle memory controller support
+// plj Aug 1995 MP version (UNION dependent).
+//
+//
+//--
+
+#include "kxppc.h"
+
+#define HPT_LOCK 0x4fc
+
+
+ .set C_LINE_SZ, 64
+ .set C_LINE_CNT, 64
+ .set C_SETS, 8
+
+ .set C_SIZE, C_LINE_SZ * C_LINE_CNT * C_SETS
+
+ .set HID0, 1008
+ .set DISABLES, MASK_SPR(MSR_DR,1) | MASK_SPR(MSR_IR,1)
+
+
+ .set H0_603_DCE, 0x4000 // 603 Data Cache Enable
+ .set H0_603_ICE, 0x8000 // 603 Instruction Cache Enable
+ .set H0_603_ICFI, 0x0800 // 603 I-Cache Flash Invalidate
+
+ .set H0_604_DCE, 0x4000 // 604 Data Cache Enable
+ .set H0_604_ICE, 0x8000 // 604 Instruction Cache Enable
+ .set H0_604_DCIA, 0x0400 // 604 I-Cache Invalidate All
+ .set H0_604_ICIA, 0x0800 // 604 I-Cache Invalidate All
+
+ .set TLB_CLASSES_601, 128 // 601 tlb has 128 congruence classes
+ .set TLB_CLASSES_603, 32 // 603 tlb has 32 congruence classes
+ .set TLB_CLASSES_604, 64 // 604 tlb has 64 congruence classes
+
+
+ LEAF_ENTRY(HalpPowerPcReset)
+ li r.6, -1
+ mtdec r.6
+ isync
+
+ bl ..HalpResetHelper
+here:
+ mflr r.9 // r.9 = &here
+
+ LWI(r.4, 0xfff00100) // address of rom reset handler
+ LWI(r.7, 0x80000092) // address of MEM CTLR endian sw
+ li r.6, 0
+
+ bne not_601 // jif processor is not a 601
+
+ //
+ // processor is a 601
+ //
+
+ rlwinm r.5, r.5, 0, ~(0x0008) // turn off little endian
+
+ //
+ // disable instruction and data relocation and switch
+ // interrupt prefix to fetch from ROM
+ //
+
+ andi. r.8, r.8, ~DISABLES & 0xffff
+ ori r.8, r.8, MASK_SPR(MSR_IP,1)
+ mtsrr1 r.8 // this will also be target state
+ nop // for rfi
+
+//
+// Ensure all code from 'cachem' to 'end_little' is in cache by loading a
+// byte in each address line in that range.
+
+ addi r.9, r.9, cachem-here // (r.9) = physical &cachem
+
+ // r.9 now contains the physical address of cachem. (assuming
+ // this code was loaded as part of kernel which is loaded at
+ // physical 0 = virtual 0x80000000). We effect the switch to
+ // physical addressing thru an rfi with the target state set
+ // to resume at cachem with relocation and interrupts disabled.
+
+ mtsrr0 r.9 // address of cachem for rfi
+ addi r.10, r.9, end_little-cachem // (r.10) = &end_little
+ addi r.11, r.9, HalpPowerPcReset.end-cachem // (r.11) = &reset_end
+
+ addi r.12, r.9, -C_LINE_SZ // bias addr for 1st iteration by
+ // amount added by lbzu prior to load
+
+ rfi // switch
+cachem:
+ lbzu r.13, C_LINE_SZ(r.12) // get byte at (r.13)+C_LINE_SZ
+ cmplw r.12, r.10 // bumping r.12 by C_LINE_SZ
+ addi r.13, r.13, 1 // ensure load completed.
+ blt cachem // get all in range here-end_little.
+
+ isync
+ mtsrr0 r.4 // set rom reset target for next rfi
+ lis r.9, 0x87f0 // Segment register base 0x87f00000
+ li r.10, 0xf // Set all 16 segment registers
+
+ li r.11, 0
+ mtibatl 0, r.6 // zero bat 0-3 upper and lower
+ 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
+setsr: rlwimi r.11, r.10, 28, 0, 3 // Shift segment reg. # to bits 0-3
+ or r.12, r.9, r.10 // Segment register value 0x87f000sr
+ mtsrin r.12, r.11
+
+ addic. r.10, r.10, -1 // Next segment register
+ bne setsr
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ sync // quiet the machine down
+ sync
+ sync
+
+ sync
+ stb r.6, 0(r.7) // switch memory
+ eieio // flush io
+ sync
+
+ sync
+ sync
+ sync
+ mtspr HID0, r.5 // switch ends on the cpu
+
+ sync
+ sync
+ sync
+ 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
+ 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
+ mtsr 0, r.9 // Set the last segment register
+
+ rfi // head off into the reset handler
+ rfi
+ addi r.0, r.1, 0x138 // we never get here
+ oris r.0, r.0, 0x4c // rfi (big-endian)
+end_little:
+
+ b $
+
+//
+// For the 603 (and hopefully other) processor(s) things are a little
+// easier because little-endianness is controlled by the MSR. We still
+// have to change memory seperately so we still want code from the memory
+// switch thru the cpu switch in cache.
+//
+// When we get here
+// r.4 contains the address of the ROM resident Machine Reset
+// handler.
+// r.6 contains 0.
+// r.7 contains the port address (real) used to switch memory
+// endianness.
+// r.8 contains MSR present value.
+// r.9 contains the address of "here".
+// r.31 contains the processor type
+
+
+not_601:
+
+//
+// MSR bits ILE and POW must be disabled via mtmsr as rfi only moves
+// the least significant 16 bits into the MSR.
+//
+
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_POW,1) // -= Power Management
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_ILE,1) // -= Interrupt Little Endian
+ sync
+ mtmsr r.8
+ isync
+
+//
+// Use an rfi to switch to big-endian, untranslated, interrupt prefix on
+// with a target address in the nice harmless pallindromic code below.
+// use another rfi to branch to the rom resident reset handler.
+//
+
+ li r.8, MASK_SPR(MSR_ME,1) | MASK_SPR(MSR_IP,1)
+ addi r.9, r.9, uncached_6034-here
+ mtsrr1 r.8 // state = Machine Check Enabled
+ bl here2
+here2: mflr r.28
+ rlwinm r.28, r.28, 0, 0x7fffffff // convert address to physical
+ lwz r.29, endofroutine - here2(r.28)
+ mtsrr0 r.9 // rfi to uncached_6034
+ b jumpswap
+
+memoryswap:
+ ori r.8, r.28, 0
+ addi r.8, r.8, uncached_6034-here2
+ addi r.9, 0, 0
+ li r.15, swapend - uncached_6034
+ addis r.14, 0, 0
+ addi r.14, 0, 4
+swaploop:
+ lwz r.11, 0(r.8)
+ lwz r.12, 4(r.8)
+ stwbrx r.11, r.14, r.8
+ stwbrx r.12, 0, r.8
+ addi r.8, r.8, 8
+ subi r.15, r.15, 8
+ cmpi 0, 0, r.15, 0
+ bgt swaploop
+
+jumpswap:
+
+//
+// The following bizzareness is to ensure that the memory switch thru
+// the disabling of cache is in cache. There is less than 32 bytes so
+// they must be part of either the cache line we are currently in, or
+// the one at the target of the branch. Therefore, branching over them,
+// doing a little and branching back to them should be enough to enure
+// they're cache resident.
+//
+
+ b fill_icache
+goto_bigendian:
+ sync
+ stb r.6, 0(r.7) // switch memory
+ sync
+ lwz r.30, endofroutine - here2(r.28)
+ cmp 0, 0, r.29, r.30
+ beq memoryswap
+ rfi
+fill_icache:
+ isync
+ sync // complete everything!
+ b goto_bigendian
+
+ .align 5
+
+uncached_6034:
+ .big_endian // out of cache fetches must be
+ // assembled in same mode as processor
+ 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
+
+ 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
+
+ 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
+ mtsrr0 r.4 // rfi target = 0xfff00100
+ mtspr HID0, r.10 // DISABLE CACHING
+
+ mtibatl 0, r.6 // invalidate/clear all bats
+ 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
+
+ mtdbatl 0, r.6
+ mtdbatu 0, r.6
+ mtdbatl 1, r.6
+ mtdbatu 1, r.6
+
+ mtdbatl 2, r.6
+ mtdbatu 2, r.6
+ mtdbatl 3, r.6
+ mtdbatu 3, r.6
+
+ mtsr 0, r.6
+ 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
+
+ rfi // go to machine reset handler
+ // never get here
+ rfi // previous rfi on a dword boundary
+ // allow for word swap
+ .little_endian
+endofroutine:
+ sync
+ .globl swapend
+ .long swapend
+swapend:
+
+ LEAF_EXIT(HalpPowerPcReset)
+
+ LEAF_ENTRY(HalpResetUnion)
+
+ bl ..HalpResetHelper
+
+//
+// Union has a Software Power on Reset control register. Any write to
+// this register will send a hard reset to all processors and I/O devices
+// and the memory controller (Union) itself.
+//
+
+ li r.0, -1 // something to write
+ isync
+ lis r.8, 0xff00 // get address of S/R POR reg
+ stw r.0, 0xe8(r.8) // should never get here.
+ sync
+ sync
+ sync
+ sync
+ isync
+
+ LEAF_EXIT(HalpResetUnion)
+
+//++
+//
+// HalpResetHelper
+//
+// This routine locks the HPT, invalidates the TLB, disables the caches
+// and returns to the caller in REAL mode.
+//
+// On entry, interrupts are expected to be disabled.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// cr.0 EQ if processor is a 601
+// r.5 contains HID0 present value.
+// r.8 contains MSR present value.
+// r.31 contains PVR >> 16.
+//
+//--
+
+ LEAF_ENTRY(HalpResetHelper)
+
+ mfspr r.5, HID0
+ mfpvr r.31 // determine processor type
+ mfmsr r.8
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_EE,1) // disable interrupts
+ mtmsr r.8
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_DR,1) // -= Data Relocation
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_IR,1) // -= Inst Relocation
+ mtsrr1 r.8 // rfi target state
+ mflr r.9 // (r.9) = return address
+ rlwinm r.9, r.9, 0, 0x7fffffff // convert address to physical
+
+ //
+ // Get the processor into real mode. The following assumes
+ // physical = (virtual & 0x7fffffff) for this code. If this
+ // assumption cannot be guaranteed (this code has been paged?)
+ // then we should copy it to low memory,.... we are at high
+ // IRQL so we can't page fault but has it always been locked?
+ // (This question arises as more or the kernel and hal are made
+ // pageable and moved out of BAT protection).
+ //
+ bl almost_real
+almost_real:
+ mflr r.3 // r.3 = &almost_real
+ addi r.3, r.3, real-almost_real
+ rlwinm r.3, r.3, 0, 0x7fffffff // convert address to physical
+ mtsrr0 r.3 // set target address
+ rfi
+real:
+
+ //
+ // The processor is now executing in REAL mode.
+ //
+ mtlr r.9 // set real return address
+
+ //
+ // Attempt to get the HPT lock. If attempt fails 1024 * 1024
+ // times, just take it anyway (the other processor(s) is
+ // probably dead) or this processor already has it.
+ //
+
+ li r.3, HPT_LOCK // get address of HPT LOCK
+ lis r.9, 0x10 // retry count (1024 * 1024)
+ mtctr r.9
+ li r.9, 1 // lock value
+
+lockhpt:
+ lwarx r.10, 0, r.3 // get current lock value
+ cmpwi r.10, 0
+ bne lockretry
+ stwcx. r.9, 0, r.3
+ beq lockedhpt
+lockretry:
+ bdnz lockhpt
+
+ //
+ // Failed to obtain lock. Forcibly lock it.
+ //
+
+ stw r.9, 0(r.3)
+
+lockedhpt:
+
+ //
+ // invalidate all tlb entries
+ //
+
+ li r.3, TLB_CLASSES_601 // use largest known number of
+ // congruence classes
+ mtctr r.3 // number of classes = iteration count
+zaptlb: tlbie r.3 // invalidate tlb congruence class
+ addi r.3, r.3, 4096 // increment to next class address
+ bdnz zaptlb // loop through all classes
+ sync
+
+ srwi r.31, r.31, 16 // isolate processor type
+ cmpwi r.31, 1 // is 601?
+
+ beqlr // return if 601 (no cache control)
+
+ cmpwi cr.0, r.31, 3 // is 603?
+ cmpwi cr.4, r.31, 7 // is 603ev?
+ cmpwi cr.1, r.31, 6 // is 603e?
+ cmpwi cr.2, r.31, 4 // is 604?
+ cmpwi cr.3, r.31, 9 // is 604e?
+ beq cr.0, is_603
+ beq cr.4, is_603
+ bne cr.1, not_603
+
+//
+// 603 I-Cache is invalidated by setting ICFI in HID0. Unlike
+// the 604, this bit is not self clearing.
+//
+
+is_603: rlwinm r.5, r.5, 0, ~H0_603_DCE// turn off D-cache
+ rlwinm r.10, r.5, 0, ~H0_603_ICE// turn off I-cache
+ ori r.10, r.10, H0_603_ICFI // I-Cache Flash Invalidate
+ ori r.5, r.5, H0_603_ICE // I-cache enable
+ isync
+ mtspr HID0, r.10 // invalidate/disable
+ mtspr HID0, r.5 // enable
+ blr // return
+
+not_603:
+ beq cr.2, is_604
+// bne not_604
+
+// Note: the above branch is commented out because we don't
+// currently have any other options,... 620 will probably
+// be different.
+
+
+is_604: tlbsync // wait all processor tlb invalidate
+ sync
+
+//
+// 604 caches must be enabled in order to be invalidated. It
+// is acceptable to enable and invalidate with the same move
+// to hid0. The data cache will be left disabled, the instruction
+// cache enabled.
+//
+
+ ori r.5, r.5, H0_604_DCE | H0_604_ICE
+ ori r.10, r.5, H0_604_DCIA | H0_604_ICIA
+
+ rlwinm r.5, r.5, 0, ~H0_604_DCE
+ rlwinm r.5, r.5, 0, ~H0_604_DCIA
+ rlwinm r.5, r.5, 0, ~H0_604_ICIA
+
+ mtspr HID0, r.10 // enable + invalidate
+ mtspr HID0, r.5 // disable data cache
+
+ rlwinm r.10, r.5, 0, ~H0_604_ICE // disable i-cache later
+
+ LEAF_EXIT(HalpResetHelper)
diff --git a/private/ntos/nthals/halvict/ppc/pxreturn.c b/private/ntos/nthals/halvict/ppc/pxreturn.c
new file mode 100644
index 000000000..8181c91f7
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxreturn.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxreturn.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxs3.c b/private/ntos/nthals/halvict/ppc/pxs3.c
new file mode 100644
index 000000000..0b7211142
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxs3.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxs3.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxshadbf.s b/private/ntos/nthals/halvict/ppc/pxshadbf.s
new file mode 100644
index 000000000..d637a3763
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxshadbf.s
@@ -0,0 +1,2 @@
+#include <..\..\halppc\ppc\pxshadbf.s>
+
diff --git a/private/ntos/nthals/halvict/ppc/pxstall.s b/private/ntos/nthals/halvict/ppc/pxstall.s
new file mode 100644
index 000000000..50d947500
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxstall.s
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxstall.s>
diff --git a/private/ntos/nthals/halvict/ppc/pxsysbus.c b/private/ntos/nthals/halvict/ppc/pxsysbus.c
new file mode 100644
index 000000000..bbc98ee76
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxsysbus.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxsysbus.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxtime.c b/private/ntos/nthals/halvict/ppc/pxtime.c
new file mode 100644
index 000000000..5fe5a500a
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxtime.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxtime.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxusage.c b/private/ntos/nthals/halvict/ppc/pxusage.c
new file mode 100644
index 000000000..3be115176
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxusage.c
@@ -0,0 +1 @@
+#include <..\..\halppc\ppc\pxusage.c>
diff --git a/private/ntos/nthals/halvict/ppc/pxvm.c b/private/ntos/nthals/halvict/ppc/pxvm.c
new file mode 100644
index 000000000..d515cb51f
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxvm.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxvm.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/pxwd.c b/private/ntos/nthals/halvict/ppc/pxwd.c
new file mode 100644
index 000000000..bcfc1f5e9
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/pxwd.c
@@ -0,0 +1,2 @@
+#include "..\..\halppc\ppc\pxwd.c"
+
diff --git a/private/ntos/nthals/halvict/ppc/x86bios.c b/private/ntos/nthals/halvict/ppc/x86bios.c
new file mode 100644
index 000000000..ba7969c5d
--- /dev/null
+++ b/private/ntos/nthals/halvict/ppc/x86bios.c
@@ -0,0 +1 @@
+#include "..\..\halppc\ppc\x86bios.c"
diff --git a/private/ntos/nthals/halvict/sources b/private/ntos/nthals/halvict/sources
new file mode 100644
index 000000000..5985d56c0
--- /dev/null
+++ b/private/ntos/nthals/halvict/sources
@@ -0,0 +1,107 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+Revision Histoy:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Power PC port
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halvict
+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_MP_PPC_ -DDAKOTA -DVICTORY -DSOFT_HDD_LAMP -D_HALNVR_
+
+INCLUDES=..\halppc\ppc;..\x86new;$(BASEDIR)\private\ntos\inc
+
+SOURCES=
+
+PPC_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ ppc\pxbeep.c \
+ ppc\pxnatsup.c \
+ ppc\pxfirsup.c \
+ ppc\pxmemctl.c \
+ ppc\pxpcisup.c \
+ ppc\pxdisp.c \
+ ppc\pxp91.c \
+ ppc\pxwd.c \
+ ppc\pxs3.c \
+ ppc\pxbbl.c \
+ ppc\pxbl.c \
+ ppc\pxshadbf.s \
+ ppc\pxstall.s \
+ ppc\pxcache.s \
+ ppc\pxclock.c \
+ ppc\pxcalstl.c \
+ ppc\pxclksup.s \
+ ppc\pxflshbf.s \
+ ppc\pxhwsup.c \
+ ppc\pxprof.c \
+ ppc\pxenviro.c \
+ ppc\pxmapio.c \
+ ppc\pxtime.c \
+ ppc\pxreset.s \
+ ppc\pxreturn.c \
+ ppc\pxinithl.c \
+ ppc\pxport.c \
+ ppc\pxirql.c \
+ ppc\pxusage.c \
+ ppc\pxbusdat.c \
+ ppc\pxpcibus.c \
+ ppc\pxpciint.c \
+ ppc\pxisabus.c \
+ ppc\pxidle.c \
+ ppc\pxsysbus.c \
+ ppc\pxproc.c \
+ ppc\pxdat.c \
+ ppc\fwnvr.c \
+ ppc\pxflshio.c \
+ ppc\pxinfo.c \
+ ppc\pxpcibrd.c \
+ ppc\pxvm.c \
+ ppc\pxpower.s \
+ ppc\pxintrpt.c \
+ ppc\pxmisc.s \
+ ppc\x86bios.c
+
+DLLDEF=obj\*\hal.def
+