From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/nthals/halps/ppc/ctrlops.c | 1 + private/ntos/nthals/halps/ppc/fwnvr.c | 1 + private/ntos/nthals/halps/ppc/mk48time.c | 1 + private/ntos/nthals/halps/ppc/pcibios.c | 1 + private/ntos/nthals/halps/ppc/pxbeep.c | 1 + private/ntos/nthals/halps/ppc/pxbusdat.c | 1 + private/ntos/nthals/halps/ppc/pxcache.s | 1 + private/ntos/nthals/halps/ppc/pxcalstl.c | 1 + private/ntos/nthals/halps/ppc/pxclksup.s | 1 + private/ntos/nthals/halps/ppc/pxclock.c | 1 + private/ntos/nthals/halps/ppc/pxdakota.h | 57 + private/ntos/nthals/halps/ppc/pxdat.c | 1 + private/ntos/nthals/halps/ppc/pxdisp.c | 1 + private/ntos/nthals/halps/ppc/pxds1385.c | 1 + private/ntos/nthals/halps/ppc/pxenviro.c | 1 + private/ntos/nthals/halps/ppc/pxflshbf.s | 117 ++ private/ntos/nthals/halps/ppc/pxflshio.c | 1 + private/ntos/nthals/halps/ppc/pxhwsup.c | 1 + private/ntos/nthals/halps/ppc/pxidle.c | 1 + private/ntos/nthals/halps/ppc/pxinfo.c | 1 + private/ntos/nthals/halps/ppc/pxinithl.c | 384 +++++ private/ntos/nthals/halps/ppc/pxintsup.s | 1 + private/ntos/nthals/halps/ppc/pxirql.c | 1 + private/ntos/nthals/halps/ppc/pxisabus.c | 1 + private/ntos/nthals/halps/ppc/pxl2.s | 183 +++ private/ntos/nthals/halps/ppc/pxmapio.c | 1 + private/ntos/nthals/halps/ppc/pxmemctl.c | 1132 +++++++++++++++ private/ntos/nthals/halps/ppc/pxmisc.s | 1 + private/ntos/nthals/halps/ppc/pxpcibrd.c | 1 + private/ntos/nthals/halps/ppc/pxpcibus.c | 2289 ++++++++++++++++++++++++++++++ private/ntos/nthals/halps/ppc/pxpciint.c | 1 + private/ntos/nthals/halps/ppc/pxpcisup.c | 1 + private/ntos/nthals/halps/ppc/pxport.c | 1 + private/ntos/nthals/halps/ppc/pxpower.s | 1 + private/ntos/nthals/halps/ppc/pxproc.c | 1 + private/ntos/nthals/halps/ppc/pxprof.c | 1 + private/ntos/nthals/halps/ppc/pxreset.s | 433 ++++++ private/ntos/nthals/halps/ppc/pxreturn.c | 1 + private/ntos/nthals/halps/ppc/pxsiosup.c | 1 + private/ntos/nthals/halps/ppc/pxstall.s | 1 + private/ntos/nthals/halps/ppc/pxsysbus.c | 1 + private/ntos/nthals/halps/ppc/pxsysint.c | 1 + private/ntos/nthals/halps/ppc/pxsystyp.c | 1 + private/ntos/nthals/halps/ppc/pxtime.c | 1 + private/ntos/nthals/halps/ppc/pxusage.c | 1 + private/ntos/nthals/halps/ppc/sysbios.c | 1 + private/ntos/nthals/halps/ppc/x86bios.c | 1 + 47 files changed, 4635 insertions(+) create mode 100644 private/ntos/nthals/halps/ppc/ctrlops.c create mode 100644 private/ntos/nthals/halps/ppc/fwnvr.c create mode 100644 private/ntos/nthals/halps/ppc/mk48time.c create mode 100644 private/ntos/nthals/halps/ppc/pcibios.c create mode 100644 private/ntos/nthals/halps/ppc/pxbeep.c create mode 100644 private/ntos/nthals/halps/ppc/pxbusdat.c create mode 100644 private/ntos/nthals/halps/ppc/pxcache.s create mode 100644 private/ntos/nthals/halps/ppc/pxcalstl.c create mode 100644 private/ntos/nthals/halps/ppc/pxclksup.s create mode 100644 private/ntos/nthals/halps/ppc/pxclock.c create mode 100644 private/ntos/nthals/halps/ppc/pxdakota.h create mode 100644 private/ntos/nthals/halps/ppc/pxdat.c create mode 100644 private/ntos/nthals/halps/ppc/pxdisp.c create mode 100644 private/ntos/nthals/halps/ppc/pxds1385.c create mode 100644 private/ntos/nthals/halps/ppc/pxenviro.c create mode 100644 private/ntos/nthals/halps/ppc/pxflshbf.s create mode 100644 private/ntos/nthals/halps/ppc/pxflshio.c create mode 100644 private/ntos/nthals/halps/ppc/pxhwsup.c create mode 100644 private/ntos/nthals/halps/ppc/pxidle.c create mode 100644 private/ntos/nthals/halps/ppc/pxinfo.c create mode 100644 private/ntos/nthals/halps/ppc/pxinithl.c create mode 100644 private/ntos/nthals/halps/ppc/pxintsup.s create mode 100644 private/ntos/nthals/halps/ppc/pxirql.c create mode 100644 private/ntos/nthals/halps/ppc/pxisabus.c create mode 100644 private/ntos/nthals/halps/ppc/pxl2.s create mode 100644 private/ntos/nthals/halps/ppc/pxmapio.c create mode 100644 private/ntos/nthals/halps/ppc/pxmemctl.c create mode 100644 private/ntos/nthals/halps/ppc/pxmisc.s create mode 100644 private/ntos/nthals/halps/ppc/pxpcibrd.c create mode 100644 private/ntos/nthals/halps/ppc/pxpcibus.c create mode 100644 private/ntos/nthals/halps/ppc/pxpciint.c create mode 100644 private/ntos/nthals/halps/ppc/pxpcisup.c create mode 100644 private/ntos/nthals/halps/ppc/pxport.c create mode 100644 private/ntos/nthals/halps/ppc/pxpower.s create mode 100644 private/ntos/nthals/halps/ppc/pxproc.c create mode 100644 private/ntos/nthals/halps/ppc/pxprof.c create mode 100644 private/ntos/nthals/halps/ppc/pxreset.s create mode 100644 private/ntos/nthals/halps/ppc/pxreturn.c create mode 100644 private/ntos/nthals/halps/ppc/pxsiosup.c create mode 100644 private/ntos/nthals/halps/ppc/pxstall.s create mode 100644 private/ntos/nthals/halps/ppc/pxsysbus.c create mode 100644 private/ntos/nthals/halps/ppc/pxsysint.c create mode 100644 private/ntos/nthals/halps/ppc/pxsystyp.c create mode 100644 private/ntos/nthals/halps/ppc/pxtime.c create mode 100644 private/ntos/nthals/halps/ppc/pxusage.c create mode 100644 private/ntos/nthals/halps/ppc/sysbios.c create mode 100644 private/ntos/nthals/halps/ppc/x86bios.c (limited to 'private/ntos/nthals/halps/ppc') diff --git a/private/ntos/nthals/halps/ppc/ctrlops.c b/private/ntos/nthals/halps/ppc/ctrlops.c new file mode 100644 index 000000000..d6419aa5f --- /dev/null +++ b/private/ntos/nthals/halps/ppc/ctrlops.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\ctrlops.c> diff --git a/private/ntos/nthals/halps/ppc/fwnvr.c b/private/ntos/nthals/halps/ppc/fwnvr.c new file mode 100644 index 000000000..34ac6b7a6 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/fwnvr.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\fwnvr.c> diff --git a/private/ntos/nthals/halps/ppc/mk48time.c b/private/ntos/nthals/halps/ppc/mk48time.c new file mode 100644 index 000000000..c8af7cb9e --- /dev/null +++ b/private/ntos/nthals/halps/ppc/mk48time.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\mk48time.c> diff --git a/private/ntos/nthals/halps/ppc/pcibios.c b/private/ntos/nthals/halps/ppc/pcibios.c new file mode 100644 index 000000000..63cbc3092 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pcibios.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pcibios.c> diff --git a/private/ntos/nthals/halps/ppc/pxbeep.c b/private/ntos/nthals/halps/ppc/pxbeep.c new file mode 100644 index 000000000..11eef682e --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxbeep.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxbeep.c> diff --git a/private/ntos/nthals/halps/ppc/pxbusdat.c b/private/ntos/nthals/halps/ppc/pxbusdat.c new file mode 100644 index 000000000..4eb375ea6 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxbusdat.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxbusdat.c> diff --git a/private/ntos/nthals/halps/ppc/pxcache.s b/private/ntos/nthals/halps/ppc/pxcache.s new file mode 100644 index 000000000..464a93823 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxcache.s @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxcache.s> diff --git a/private/ntos/nthals/halps/ppc/pxcalstl.c b/private/ntos/nthals/halps/ppc/pxcalstl.c new file mode 100644 index 000000000..7b5e7048c --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxcalstl.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxcalstl.c> diff --git a/private/ntos/nthals/halps/ppc/pxclksup.s b/private/ntos/nthals/halps/ppc/pxclksup.s new file mode 100644 index 000000000..3bb344c2b --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxclksup.s @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxclksup.s> diff --git a/private/ntos/nthals/halps/ppc/pxclock.c b/private/ntos/nthals/halps/ppc/pxclock.c new file mode 100644 index 000000000..140008534 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxclock.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxclock.c> diff --git a/private/ntos/nthals/halps/ppc/pxdakota.h b/private/ntos/nthals/halps/ppc/pxdakota.h new file mode 100644 index 000000000..597c7d413 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxdakota.h @@ -0,0 +1,57 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + + +Module Name: + + pxdakota.h + +Abstract: + + This header file defines the structures for the planar registers + on Dakota memory controllers. + +--*/ + + +// +// define stuctures for memory control and planar register +// + + + +typedef struct _DAKOTA_CONTROL { + UCHAR Reserved0[0x803]; // Offset 0x000 + UCHAR SimmId; // Offset 0x803 + UCHAR SimmPresent; // Offset 0x804 + UCHAR Reserved1[3]; + UCHAR HardfileLight; // Offset 0x808 + UCHAR Reserved2[3]; + UCHAR EquiptmentPresent; // Offset 0x80C + UCHAR Reserved3[3]; + UCHAR PasswordProtect1; // Offset 0x810 + UCHAR Reserved4; + UCHAR PasswordProtect2; // Offset 0x812 + UCHAR Reserved5; + UCHAR L2Flush; // Offset 0x814 + UCHAR Reserved6[3]; + UCHAR Keylock; // Offset 0x818 + UCHAR Reserved7[3]; + UCHAR SystemControl; // Offset 0x81c + UCHAR Reserved8[3]; + UCHAR MemoryController; // Offset 0x820 + UCHAR MemoryControllerTiming; // Offset 0x821 + UCHAR Reserved9[0x16]; + UCHAR Eoi9; // Offset 0x838 + UCHAR Reserved10[3]; + UCHAR Eoi11; // Offset 0x83C + UCHAR Reserved11[3]; + UCHAR MemoryParityErrorStatus; // Offset 0x840 + UCHAR MemoryParityErrorClear; // Offset 0x841 + UCHAR L2CacheErrorStatus; // Offset 0x842 + UCHAR L2CacheErrorClear; // Offset 0x843 + UCHAR TransferErrorStatus; // Offset 0x844 + UCHAR TransferErrorClear; // Offset 0x845 + UCHAR Reserved12[0xa]; + UCHAR IoMap; // Offset 0x850 + UCHAR Reserved13[3]; +} DAKOTA_CONTROL, *PDAKOTA_CONTROL; diff --git a/private/ntos/nthals/halps/ppc/pxdat.c b/private/ntos/nthals/halps/ppc/pxdat.c new file mode 100644 index 000000000..9036550ff --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxdat.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxdat.c> diff --git a/private/ntos/nthals/halps/ppc/pxdisp.c b/private/ntos/nthals/halps/ppc/pxdisp.c new file mode 100644 index 000000000..e476e5e83 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxdisp.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxdisp.c> diff --git a/private/ntos/nthals/halps/ppc/pxds1385.c b/private/ntos/nthals/halps/ppc/pxds1385.c new file mode 100644 index 000000000..6164c0faa --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxds1385.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxds1385.c> diff --git a/private/ntos/nthals/halps/ppc/pxenviro.c b/private/ntos/nthals/halps/ppc/pxenviro.c new file mode 100644 index 000000000..bb67da576 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxenviro.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxenviro.c> diff --git a/private/ntos/nthals/halps/ppc/pxflshbf.s b/private/ntos/nthals/halps/ppc/pxflshbf.s new file mode 100644 index 000000000..358b5de88 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxflshbf.s @@ -0,0 +1,117 @@ +// TITLE("Miscellaneous Kernel Functions") +//++ +// +// Copyright (C) 1991-1995 Microsoft Corporation +// +// Copyright (C) 1994,1995 MOTOROLA, INC. All Rights Reserved. This file +// contains copyrighted material. Use of this file is restricted +// by the provisions of a Motorola Software License Agreement. +// +// Module Name: +// +// pxflshbf.s +// +// Abstract: +// +// This module implements the system dependent kernel function to flush +// the write buffer or otherwise synchronize writes on a Power PC +// system. +// +// +// +// Author: +// +// David N. Cutler (davec) 24-Apr-1991 +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +// Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port +// +// Used PowerPC eieio instruction to flush writes +// +//-- + +#include "kxppc.h" + + +// SBTTL("Flush Write Buffer") +// +//++ +// +// NTSTATUS +// KeFlushWriteBuffer ( +// VOID +// ) +// +// Routine Description: +// +// This function flushes the write buffer on the current processor. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(KeFlushWriteBuffer) + + eieio // synchronize I/O + + LEAF_EXIT(KeFlushWriteBuffer) + + + +// +//++ +// +// NTSTATUS +// HalpSynchronizeExecution() +// VOID +// ) +// +// Routine Description: +// +// This function flushes the write buffer on the current processor. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(HalpSynchronizeExecution) + + sync // synchronize + + LEAF_EXIT(HalpSynchronizeExecution) + + +// +//++ +// +// VOID +// HalpSetSDR1( +// ULONG HashedPageTableBase, +// ULONG HashedPageTableSize +// ) +// +// HashedPageTableSize is unused because we ASSUME that the HPT is 64K +// + + LEAF_ENTRY(HalpSetSDR1) + + mtsdr1 r.3 + + LEAF_EXIT(HalpSetSDR1) diff --git a/private/ntos/nthals/halps/ppc/pxflshio.c b/private/ntos/nthals/halps/ppc/pxflshio.c new file mode 100644 index 000000000..50fe4eb28 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxflshio.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxflshio.c> diff --git a/private/ntos/nthals/halps/ppc/pxhwsup.c b/private/ntos/nthals/halps/ppc/pxhwsup.c new file mode 100644 index 000000000..af734beb1 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxhwsup.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxhwsup.c> diff --git a/private/ntos/nthals/halps/ppc/pxidle.c b/private/ntos/nthals/halps/ppc/pxidle.c new file mode 100644 index 000000000..edd5c4520 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxidle.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxidle.c> diff --git a/private/ntos/nthals/halps/ppc/pxinfo.c b/private/ntos/nthals/halps/ppc/pxinfo.c new file mode 100644 index 000000000..5c76d0b6c --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxinfo.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxinfo.c> diff --git a/private/ntos/nthals/halps/ppc/pxinithl.c b/private/ntos/nthals/halps/ppc/pxinithl.c new file mode 100644 index 000000000..48149828a --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxinithl.c @@ -0,0 +1,384 @@ +/*++ + +Copyright (c) 1991-1993 Microsoft Corporation + +Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file +contains copyrighted material. Use of this file is restricted +by the provisions of a Motorola Software License Agreement. + +Module Name: + + pxinithl.c + +Abstract: + + + This module implements the initialization of the system dependent + functions that define the Hardware Architecture Layer (HAL) for a + Power PC system. + + +Author: + + David N. Cutler (davec) 25-Apr-1991 + +Environment: + + Kernel mode only. + +Revision History: + + Jim Wooldridge (jimw@austin.ibm.com) Initial Power PC port + + Removed call to HalpMapFixedTbEntries, the PPC port + maps all memory via calls to MmMapIoSpace(). + Removed call to HalpInitializeInterrupts - 8259 initialized in phase 1 + Removed Cache error handler - 601 has no cache error interrupt + Removed call to HalpCreateDmaSturctures - it supports internal DMA + +--*/ + +#include "halp.h" +#include "pxmemctl.h" +#include "pxsystyp.h" + +extern ADDRESS_USAGE HalpDefaultIoSpace; +extern ULONG HalpPciMaxSlots; +extern ULONG HalpPciConfigSize; + +ULONG +HalpSizeL2Cache( + VOID + ); + +VOID +HalpSynchronizeExecution( + VOID + ); + +VOID +HalpCopyROMs( + VOID + ); + + +// +// Put all code for HAL initialization in the INIT section. It will be +// deallocated by memory management when phase 1 initialization is +// completed. +// + +#if defined(ALLOC_PRAGMA) + +#pragma alloc_text(INIT, HalInitSystem) +#pragma alloc_text(INIT, HalInitializeProcessor) + +#endif + +PVOID HalpIoControlBase = (PVOID) 0; + +VOID +HalpInitBusHandlers ( + VOID + ); + +VOID +HalpRegisterInternalBusHandlers ( + VOID + ); + +VOID +HalpEnableBridgeSettings( + VOID + ); + +VOID +HalpCheckHardwareRevisionLevels( + VOID + ); + +VOID +HalpDumpHardwareState( + VOID + ); + +VOID +HalpEnableL2Cache( + VOID + ); + + +// +// Define global spin locks used to synchronize various HAL operations. +// + +KSPIN_LOCK HalpBeepLock; +KSPIN_LOCK HalpDisplayAdapterLock; +KSPIN_LOCK HalpSystemInterruptLock; + +BOOLEAN +HalInitSystem ( + IN ULONG Phase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock + ) + +/*++ + +Routine Description: + + This function initializes the Hardware Architecture Layer (HAL) for a + Power PC system. + +Arguments: + + Phase - Supplies the initialization phase (zero or one). + + LoaderBlock - Supplies a pointer to a loader parameter block. + +Return Value: + + A value of TRUE is returned is the initialization was successfully + complete. Otherwise a value of FALSE is returend. + +--*/ + +{ + + extern KSPIN_LOCK NVRAM_Spinlock; + PKPRCB Prcb; + + + // + // Initialize the HAL components based on the phase of initialization + // and the processor number. + // + + Prcb = PCR->Prcb; + if ((Phase == 0) || (Prcb->Number != 0)) { + + if (Prcb->Number == 0) + HalpSetSystemType( LoaderBlock ); + + // + // Phase 0 initialization. + // + // N.B. Phase 0 initialization is executed on all processors. + // + // + // Get access to I/O space, check if I/O space has already been + // mapped by debbuger initialization. + // + + if (HalpIoControlBase == NULL) { + + HalpIoControlBase = (PVOID)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE, 0x20000); + + if ( !HalpIoControlBase ) { + return FALSE; + } + } + + // + // Initialize the display adapter. Must be done early + // so KeBugCheck() will be able to display + // + if (!HalpInitializeDisplay(LoaderBlock)) + return FALSE; + + // Verify that the processor block major version number conform + // to the system that is being loaded. + // + + if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) { + KeBugCheck(MISMATCHED_HAL); + } + + // + // If processor 0 is being initialized, then initialize various + // variables, spin locks, and the display adapter. + // + + if (Prcb->Number == 0) { + + // + // Initialize Spinlock for NVRAM + // + + KeInitializeSpinLock( &NVRAM_Spinlock ); + + // + // Set the interval clock increment value. + // + + HalpCurrentTimeIncrement = MAXIMUM_INCREMENT; + HalpNewTimeIncrement = MAXIMUM_INCREMENT; + KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT); + + // + // Initialize all spin locks. + // + +#if defined(_MP_PPC_) + + KeInitializeSpinLock(&HalpBeepLock); + KeInitializeSpinLock(&HalpDisplayAdapterLock); + KeInitializeSpinLock(&HalpSystemInterruptLock); + +#endif + + HalpRegisterAddressUsage (&HalpDefaultIoSpace); + + // + // Calibrate execution stall + // + HalpCalibrateStall(); + + // + // Compute size of PCI Configuration Space mapping + // + HalpPciConfigSize = PAGE_SIZE * ((1 << (HalpPciMaxSlots-2)) + 1); + + // + // Fill in handlers for APIs which this HAL supports + // + + HalQuerySystemInformation = HaliQuerySystemInformation; + HalSetSystemInformation = HaliSetSystemInformation; + HalRegisterBusHandler = HaliRegisterBusHandler; + HalHandlerForBus = HaliHandlerForBus; + HalHandlerForConfigSpace = HaliHandlerForConfigSpace; + + } + + // + // InitializeInterrupts + // + + if (!HalpInitializeInterrupts()) + + return FALSE; + + // + // return success + // + + return TRUE; + + + } else { + + if (Phase != 1) + return(FALSE); + + + // + // Phase 1 initialization. + // + // N.B. Phase 1 initialization is only executed on processor 0. + // + + + HalpRegisterInternalBusHandlers (); + + + if (!HalpAllocateMapBuffer()) { + return FALSE; + } + + + // + // Map I/O space and create ISA data structures. + // + + if (!HalpMapIoSpace()) { + return FALSE; + } + + if (!HalpCreateSioStructures()) { + return FALSE; + } + + HalpCheckHardwareRevisionLevels(); + HalpEnableL2Cache(); + HalpEnableBridgeSettings(); + HalpDumpHardwareState(); + HalpCopyROMs(); + + return TRUE; + + } +} + +VOID +HalInitializeProcessor ( + IN ULONG Number + ) + +/*++ + +Routine Description: + + This function is called early in the initialization of the kernel + to perform platform dependent initialization for each processor + before the HAL Is fully functional. + + N.B. When this routine is called, the PCR is present but is not + fully initialized. In order to access the PCR from this + routine, use the PCRsprg1 macro, not the PCR macro. + +Arguments: + + Number - Supplies the number of the processor to initialize. + +Return Value: + + None. + +--*/ + +{ + ULONG IcacheSize, DcacheSize; + ULONG CacheBlockAlignment; + + switch (HalpGetProcessorVersion() >> 16) { + + case 1: // 601 + IcacheSize = 32*1024; + DcacheSize = 32*1024; + CacheBlockAlignment = 32 - 1; + break; + + case 3: // 603 + IcacheSize = 8*1024; + DcacheSize = 8*1024; + CacheBlockAlignment = 32 - 1; + break; + + case 6: // 603e + case 7: // 603ev + case 4: // 604 + IcacheSize = 16*1024; + DcacheSize = 16*1024; + CacheBlockAlignment = 32 - 1; + break; + + case 9: // 604+ + IcacheSize = 32*1024; + DcacheSize = 32*1024; + CacheBlockAlignment = 32 - 1; + break; + + default: + KeBugCheck(HAL_INITIALIZATION_FAILED); + return; + } + + + PCRsprg1->FirstLevelIcacheSize = IcacheSize; + PCRsprg1->FirstLevelDcacheSize = DcacheSize; + PCRsprg1->DcacheAlignment = CacheBlockAlignment; + PCRsprg1->IcacheAlignment = CacheBlockAlignment; + + return; +} + diff --git a/private/ntos/nthals/halps/ppc/pxintsup.s b/private/ntos/nthals/halps/ppc/pxintsup.s new file mode 100644 index 000000000..98c676fb5 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxintsup.s @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxintsup.s> diff --git a/private/ntos/nthals/halps/ppc/pxirql.c b/private/ntos/nthals/halps/ppc/pxirql.c new file mode 100644 index 000000000..3889d1b8c --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxirql.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxirql.c> diff --git a/private/ntos/nthals/halps/ppc/pxisabus.c b/private/ntos/nthals/halps/ppc/pxisabus.c new file mode 100644 index 000000000..524dfa8ef --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxisabus.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxisabus.c> diff --git a/private/ntos/nthals/halps/ppc/pxl2.s b/private/ntos/nthals/halps/ppc/pxl2.s new file mode 100644 index 000000000..a45f5dd6f --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxl2.s @@ -0,0 +1,183 @@ +// +// +// Copyright (c) 1993 IBM Corporation +// +// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file +// contains copyrighted material. Use of this file is restricted +// by the provisions of a Motorola Software License Agreement. +// +// Module Name: +// +// PXL2.S +// +// Abstract: +// +// This module implements the routines to size the L2 cache +// on PowerStack based system. +// +// Author: +// +// Karl Rusnock (karl_rusnock@phx.mcd.mot.com) +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// 08-Dec-95 kjr Created this file for MCG PowerStack 2 Systems. +// + +#include "kxppc.h" +#include "halppc.h" + + .extern HalpIoControlBase + .set HID0, 1008 +// +// L2 cache sizes: +// + .set L2_SIZE, 0x3 // Bits 1..0 (LE bit order) + .set L2_1M, 0x2 + .set L2_512K, 0x0 + .set L2_256K, 0x1 + .set L2_LINE_SIZE, 32 + + .set CacheSize, r.3 // Return value + .set L2CONFIG, r.9 + .set ISA, r.10 // Pointer to ISA I/O space + +//*********************************************************************** +// +// Synopsis: +// ULONG HalpSizeL2(VOID) +// +// Purpose: +// Sizes the L2 cache. +// +// Returns: +// Size of L2 cache or zero if not installed. +// Valid sizes are 256, 512, and 1024. +// +// Global Variables Referenced: +// HalpIoControlBase +// +// NOTE: Interrupts are assumed to be disabled upon entry. +//*********************************************************************** + + + LEAF_ENTRY(HalpSizeL2) + +// +// Get ptr to Bridge I/O (ISA bus) +// + lwz ISA,[toc]HalpIoControlBase(r.toc) // Get base of ISA I/O + lwz ISA,0(ISA) + + lbz r.0, 0x823(ISA) // Cache Configuration Register. + + andi. r.0, r.0, L2_SIZE // Isolate L2 size field + cmpi 0,0, r.0, L2_SIZE // L2 Cache Not Present? + li CacheSize, 0 + beq L2_Exit + + li CacheSize, 256 + cmpi 0,0,r.0, L2_256K + beq L2_Exit + + li CacheSize, 512 + cmpi 0,0,r.0, L2_512K + beq L2_Exit + + li CacheSize, 1024 + +L2_Exit: + +// +// r.3 = cache size in KB +// + LEAF_EXIT(HalpSizeL2) + + +//*********************************************************************** +// +// Synopsis: +// VOID HalpFlushAndDisableL2(VOID) +// +// Purpose: +// Assumes that the L2 is enabled and in WRITE-THROUGH mode. +// The L2 is invalidated and disabled. +// +// Returns: +// nothing +// +// Global Variables Referenced: +// HalpIoControlBase +// +// NOTE: Interrupts are assumed to be disabled upon entry. +//*********************************************************************** + + + LEAF_ENTRY(HalpFlushAndDisableL2) + + mfspr r.9, HID0 // Lock the Icache + ori r.0, r.9, 0x2000 + mtspr HID0, r.0 + isync + + li r.3, 0xC0 // Bits controlling L2 + lwz ISA, [toc]HalpIoControlBase(r.toc) // Get base of ISA I/O + lwz ISA, 0(ISA) + + lbz r.5, 0x81C(ISA) // Read System Control Register. + andc r.5, r.5, r.3 // Set bits to disable L2. + stb r.5, 0x814(ISA) // Invalidate L2 first. + stb r.5, 0x81C(ISA) // Disable L2 second. + stb r.5, 0x814(ISA) // Invalidate L2 again, to be safe. + lbz r.5, 0x81C(ISA) // Synchronize with I/O. + sync + + mtspr HID0, r.9 // Unlock the Icache + + LEAF_EXIT(HalpFlushAndDisableL2) + + +//*********************************************************************** +// +// Synopsis: +// VOID HalpFlushAndEnableL2(VOID) +// +// Purpose: +// Assumes that the L2 is Disabled. +// The L2 is invalidated and enabled. +// +// Returns: +// nothing +// +// Global Variables Referenced: +// HalpIoControlBase +// +// NOTE: Interrupts are assumed to be disabled upon entry. +//*********************************************************************** + + + LEAF_ENTRY(HalpFlushAndEnableL2) + + mfspr r.9, HID0 // Lock the Icache + ori r.0, r.9, 0x2000 + mtspr HID0, r.0 + isync + + li r.3, 0xC0 // Bits controlling L2 + lwz ISA, [toc]HalpIoControlBase(r.toc) // Get base of ISA I/O + lwz ISA, 0(ISA) + + lbz r.5, 0x81C(ISA) // Read System Control Register. + or r.5, r.5, r.3 // Set bits to disable L2. + stb r.5, 0x814(ISA) // Invalidate L2 first. + stb r.5, 0x81C(ISA) // Enable L2 second. + lbz r.5, 0x81C(ISA) // Synchronize with I/O. + sync + + mtspr HID0, r.9 // Unlock the Icache + + LEAF_EXIT(HalpFlushAndEnableL2) + diff --git a/private/ntos/nthals/halps/ppc/pxmapio.c b/private/ntos/nthals/halps/ppc/pxmapio.c new file mode 100644 index 000000000..110871d90 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxmapio.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxmapio.c> diff --git a/private/ntos/nthals/halps/ppc/pxmemctl.c b/private/ntos/nthals/halps/ppc/pxmemctl.c new file mode 100644 index 000000000..73cdad933 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxmemctl.c @@ -0,0 +1,1132 @@ + +/*++ + +Copyright (C) 1990-1995 Microsoft Corporation + +Copyright (C) 1994,1995 MOTOROLA, INC. All Rights Reserved. This file +contains copyrighted material. Use of this file is restricted +by the provisions of a Motorola Software License Agreement. + +Module Name: + + pxmemctl.c + +Abstract: + + The module initializes any planar registers. + This module also implements machince check parity error handling. + +--*/ + + + +#include "halp.h" +#include "pxmemctl.h" +#include "pxdakota.h" +#include "arccodes.h" + + +VOID HalDisplayString(PUCHAR String); +ULONG HalpGetHID0(VOID); +VOID HalpSetHID0(ULONG Value); +BOOLEAN HalpStrCmp( char *, char *); +VOID HalpEnableL2Cache(VOID); +ULONG HalpSizeL2Cache(VOID); +extern ULONG HalpSizeL2(VOID); +BOOLEAN HalpInitPlanar(VOID); +BOOLEAN HalpMapPlanarSpace(VOID); +VOID HalpFlushAndEnableL2(VOID); +VOID HalpFlushAndDisableL2(VOID); +VOID HalpEnableBridgeSettings(VOID); +VOID HalpEnable_HID0_Settings(VOID); +VOID HalpCheckHardwareRevisionLevels(VOID); +VOID HalpDumpHardwareState(VOID); + +#define PCI_CONFIG_PHYSICAL_BASE 0x80800000 // physical base of PCI config space +#define PCI_CONFIG_SIZE 0x00800000 + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpStrCmp) +#pragma alloc_text(INIT,HalpInitPlanar) +#pragma alloc_text(INIT,HalpMapPlanarSpace) +#pragma alloc_text(INIT,HalpEnableL2Cache) +#pragma alloc_text(INIT,HalpSizeL2Cache) +#pragma alloc_text(INIT,HalpEnableBridgeSettings) +#pragma alloc_text(INIT,HalpEnable_HID0_Settings) +#pragma alloc_text(INIT,HalpCheckHardwareRevisionLevels) +#endif + +#define NEGATECHAR '~' + +#define BridgeIndexRegister ((PULONG) (((PUCHAR) HalpIoControlBase) + 0xcf8)) +#define BridgeDataRegister (((ULONG) HalpIoControlBase) + 0xcfc) + +#define HalpReadBridgeUlong(Port) \ + (*BridgeIndexRegister = (Port), __builtin_eieio(), *((PULONG) BridgeDataRegister)) + +#define HalpWriteBridgeUlong(Port, Value) \ + (*BridgeIndexRegister = (Port), *((PULONG) BridgeDataRegister) = (Value), __builtin_sync()) + +#define HalpReadBridgeUshort(Port) \ + (*BridgeIndexRegister = (Port), __builtin_eieio(), *((PUSHORT)(BridgeDataRegister+(Port&0x2)))) + +#define HalpWriteBridgeUshort(Port, Value) \ + (*BridgeIndexRegister = (Port), *((PUSHORT)(BridgeDataRegister+(Port&0x2))) = (Value), __builtin_sync()) + +#define HalpReadBridgeUchar(Port) \ + (*BridgeIndexRegister = (Port), __builtin_eieio(), *((PUCHAR)(BridgeDataRegister+(Port&0x3)))) + +#define HalpWriteBridgeUchar(Port, Value) \ + (*BridgeIndexRegister = (Port), *((PUCHAR)(BridgeDataRegister+(Port&0x3))) = (Value), __builtin_sync()) + + +#define HalpDisplayHex32(Num, Buf) HalpDisplayHex( 32, Num, Buf) +#define HalpDisplayHex16(Num, Buf) HalpDisplayHex( 16, Num, Buf) +#define HalpDisplayHex8(Num, Buf) HalpDisplayHex( 8, Num, Buf) + +VOID HalpDisplayHex( + ULONG NoBits, + ULONG Number, + IN PUCHAR Buffer +) +{ int Bits; + + for (Bits=NoBits-4; Bits >= 0; Bits -=4) { + *Buffer++ = (UCHAR) ((((Number >> Bits) & 0xF) > 9) ? + ((Number >> Bits) & 0xF) - 10 + 'A' : + ((Number >> Bits) & 0xF) + '0'); + } + *Buffer++ = '.'; + *Buffer++ = '\n'; + *Buffer++ = '\0'; + +} + + +UCHAR HalpUpperCase(UCHAR c) +{ + if (c >= 'a' && c <= 'z') + c -= 'a'-'A'; + return c; +} + + +// +// Routine Description: +// +// This routine is a helper routine for parameter parsing. +// It compares UpperCase of String1 to UpperCase of String2. +// +// Return Value +// +// TRUE if strings match; otherwise FALSE +// + +BOOLEAN HalpStrCmp( char *String0, char *String1 ) +{ +char *tmp0, *tmp1; + + tmp0 = String0; + tmp1 = String1; + while( (*tmp0 = toupper( *tmp0 )) && (*tmp1 = toupper( *tmp1 )) ) + { + tmp0++; tmp1++; + } + return( strcmp(String0, String1) == 0 ); +} + + +// Oem Output Display function filter noise if OEM or quite + +VOID OemDisplayString ( + PUCHAR String + ) + +{ +#define BUF_LEN 120 +UCHAR CharBuffer[BUF_LEN]; + + if(HalGetEnvironmentVariable("HALREPORT",sizeof(CharBuffer),&CharBuffer[0]) == ESUCCESS) { + if(HalpStrCmp("YES", CharBuffer)) { + HalDisplayString(String); + } + } else { + if(HalGetEnvironmentVariable("MOT-OEM-ID",sizeof(CharBuffer),&CharBuffer[0]) != ESUCCESS) { + HalDisplayString(String); + } + } +} + +BOOLEAN +HalpInitPlanar ( + VOID + ) + +{ + USHORT CpuRevision, CpuType; + UCHAR BridgeRevision, c; + UCHAR CharBuffer[20], i; + + OemDisplayString("\nHAL: Motorola PowerStack 2 Systems."); + OemDisplayString("\nHAL: Version 2.37 5/24/96."); + + CpuType = (USHORT)(HalpGetProcessorVersion() >> 16); + CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF); + + OemDisplayString("\nHAL: Processor is a 6"); + i = 0; + switch (CpuType) { + case 1: + case 3: + case 4: + CharBuffer[i++] = '0'; + CharBuffer[i++] = (UCHAR)(CpuType) + '0'; + break; + + case 6: + CharBuffer[i++] = '0'; + CharBuffer[i++] = '3'; + CharBuffer[i++] = 'e'; + break; + + case 7: + CharBuffer[i++] = '0'; + CharBuffer[i++] = '3'; + CharBuffer[i++] = 'e'; + CharBuffer[i++] = 'v'; + break; + + case 9: + CharBuffer[i++] = '0'; + CharBuffer[i++] = '4'; + CharBuffer[i++] = 'e'; + CharBuffer[i++] = 'v'; + break; + + case 20: + CharBuffer[i++] = '2'; + CharBuffer[i++] = '0'; + break; + + default: + CharBuffer[i++] = '?'; + CharBuffer[i++] = '?'; + break; + } + CharBuffer[i] = '\0'; + OemDisplayString(CharBuffer); + + OemDisplayString(" revision "); + i = 0; + c = (UCHAR)((CpuRevision >> 8) & 0xf); + CharBuffer[i++] = c + '0'; + CharBuffer[i++] = '.'; + if (c = (UCHAR)((CpuRevision >> 4) & 0xf)) + CharBuffer[i++] = c + '0'; + c = (UCHAR)(CpuRevision & 0xf); + CharBuffer[i++] = c + '0'; + CharBuffer[i++] = '.'; + CharBuffer[i] = '\0'; + OemDisplayString(CharBuffer); + + OemDisplayString("\nHAL: Bridge 27-82660 revision "); + BridgeRevision = HalpReadBridgeUchar(0x80000008); + i = 0; + CharBuffer[i++] = (UCHAR) (BridgeRevision >> 4) + '0'; + CharBuffer[i++] = '.'; + CharBuffer[i++] = (UCHAR) (BridgeRevision & 0x0F) + '0'; + CharBuffer[i++] = '.'; + CharBuffer[i++] = '\n'; + CharBuffer[i] = '\0'; + OemDisplayString(CharBuffer); + + return TRUE; +} + +char * +MyStrtok ( + char * string, + const char * control + ) +{ + unsigned char *str; + const unsigned char *ctrl = control; + + unsigned char map[32]; + int count; + + static char *nextoken; + + /* Clear control map */ + for (count = 0; count < 32; count++) + map[count] = 0; + + /* Set bits in delimiter table */ + do { + map[*ctrl >> 3] |= (1 << (*ctrl & 7)); + } while (*ctrl++); + + /* Initialize str. If string is NULL, set str to the saved + * pointer (i.e., continue breaking tokens out of the string + * from the last strtok call) */ + if (string) + str = string; + else + str = nextoken; + + /* Find beginning of token (skip over leading delimiters). Note that + * there is no token iff this loop sets str to point to the terminal + * null (*str == '\0') */ + while ( (map[*str >> 3] & (1 << (*str & 7))) && *str ) + str++; + + string = str; + + /* Find the end of the token. If it is not the end of the string, + * put a null there. */ + for ( ; *str ; str++ ) + if ( map[*str >> 3] & (1 << (*str & 7)) ) { + *str++ = '\0'; + break; + } + + /* Update nextoken (or the corresponding field in the per-thread data + * structure */ + nextoken = str; + + /* Determine if a token has been found. */ + if ( string == str ) + return NULL; + else + return string; +} + + +VOID +HalpEnableBridgeSettings( + VOID + ) +{ + UCHAR CharBuffer[BUF_LEN], *Value; + BOOLEAN Negate; + ULONG StatusRegister; + volatile ULONG ErrorAddress; + +#define SetBridgeUchar( Clear, Offset, Val ) \ + SetBridgeReg(Clear, Offset, Val, HalpReadBridgeUchar, HalpWriteBridgeUchar); + +#define SetBridgeUshort( Clear, Offset, Val ) \ + SetBridgeReg(Clear, Offset, Val, HalpReadBridgeUshort, HalpWriteBridgeUshort); + +#define SetBridgeUlong( Clear, Offset, Val ) \ + SetBridgeReg(Clear, Offset, Val, HalpReadBridgeUlong, HalpWriteBridgeUlong); + +#define SetBridgeReg( Clear, Offset, Val, GetReg, SetReg) \ +{ \ + if (Clear) { \ + SetReg(Offset, GetReg(Offset) & ~Val); \ + } else { \ + SetReg(Offset, GetReg(Offset) | Val); \ + } \ +} + + // + // MOTKJR - Errata 19 from the Errata Summary Revision 1.3 says: + // The error handling logic incorrectly detects EIEIO as a CPU transfer type error. + // Always mask CPU transfer type errors (Error Enable 1 bit 0). + // + StatusRegister = HalpReadBridgeUchar(0x800000C0); // Clear CPU Transfer type error enable bit. + HalpWriteBridgeUchar(0x800000C0, ~0x01 & (UCHAR)(StatusRegister)); + + // + // The environment variable "BRIDGESETTINGS" is defined as: + // Matching a string serves to enable that feature while a tilde (~) + // immediately before the parameter string indicates that it is to be disabled. + // + + if ((HalGetEnvironmentVariable("BRIDGESETTINGS", BUF_LEN, &CharBuffer[0]) == ESUCCESS) || + (HalGetEnvironmentVariable("EAGLESETTINGS", BUF_LEN, &CharBuffer[0]) == ESUCCESS)) { + + for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, " :;,") ) { + + Negate = FALSE; + + if (*Value == NEGATECHAR) { + Value++; + Negate = TRUE; + } + + if (HalpStrCmp("PCI_PARITY", Value)) { + SetBridgeUshort( Negate, 0x80000004, 0x0040 ); + } + else if (HalpStrCmp("SERR", Value)) { + SetBridgeUshort( Negate, 0x80000004, 0x0140 ); + } + else if (HalpStrCmp("MCP_EN", Value) || HalpStrCmp("MCP", Value)) { + SetBridgeUchar( Negate, 0x800000BA, 0x01 ); + } + else if (HalpStrCmp("TEA_EN", Value) || HalpStrCmp("TEA", Value)) { + SetBridgeUchar( Negate, 0x800000BA, 0x02 ); + } + else if (HalpStrCmp("PCI_ISA_IO_MAPPING", Value)) { + SetBridgeUchar( Negate, 0x800000BA, 0x04 ); + } + else if (HalpStrCmp("POWER_MANAGEMENT", Value)) { + SetBridgeUchar( Negate, 0x800000BB, 0x02 ); + } + else if (HalpStrCmp("CPU_TRANSFER_TYPE", Value)) { + SetBridgeUchar( Negate, 0x800000C0, 0x01 ); + } + else if (HalpStrCmp("PARITY", Value) || HalpStrCmp("MEMORY", Value)) { + SetBridgeUchar( Negate, 0x800000C0, 0x04 ); + } + else if (HalpStrCmp("SINGLE_BIT_ECC", Value)) { + SetBridgeUchar( Negate, 0x800000C0, 0x04 ); + } + else if (HalpStrCmp("MULTI_BIT_ECC", Value)) { + SetBridgeUchar( Negate, 0x800000C0, 0x08 ); + } + else if (HalpStrCmp("SELECT", Value)) { + SetBridgeUchar( Negate, 0x800000C0, 0x20 ); + } + else if (HalpStrCmp("SERR_WHEN_PERR", Value)) { + SetBridgeUchar( Negate, 0x800000C0, 0x40 ); + } + else if (HalpStrCmp("TARGET_ABORT", Value)) { + SetBridgeUchar( Negate, 0x800000C0, 0x80 ); + } + else if (HalpStrCmp("CPU_DATA_BUS_PARITY", Value)) { + SetBridgeUchar( Negate, 0x800000C4, 0x04 ); + } + else if (HalpStrCmp("L2_PARITY", Value) || HalpStrCmp("L2", Value)) { + SetBridgeUchar( Negate, 0x800000C4, 0x08 ); + } + else if (HalpStrCmp("MASTER_ABORT", Value)) { + SetBridgeUchar( Negate, 0x800000C4, 0x10 ); + } + else if (HalpStrCmp("ECC", Value) || HalpStrCmp("MEMORY_ERROR_CHECKING", Value)) { + SetBridgeUchar( Negate, 0x800000D4, 0x01 ); + SetBridgeUchar( Negate, 0x800000C0, 0x08 ); + } + else if (HalpStrCmp("MEMORY_DRAM", Value)) { + SetBridgeUchar( Negate, 0x800000D4, 0x04 ); + } + else if (HalpStrCmp("L2_SRAM", Value)) { + SetBridgeUchar( Negate, 0x800000D4, 0x08 ); + } + else if (HalpStrCmp("MCP_MODE", Value)) { + SetBridgeUchar( Negate, 0x800000D4, 0x10 ); + } + else if (HalpStrCmp("EXTERNAL_REGISTER", Value)) { + SetBridgeUchar( Negate, 0x800000D4, 0x20 ); + } + else if (HalpStrCmp("BROADCAST_SNOOP", Value)) { + SetBridgeUchar( Negate, 0x800000D4, 0x80 ); + } else { + HalDisplayString("HAL: Error in BRIDGESETTINGS environment variable: "); + HalDisplayString(CharBuffer); + HalDisplayString("\n"); + } + } // End for + } // End If + + // + // Clear the error address register and L2 Cache Error register. + // + + ErrorAddress = READ_PORT_ULONG(HalpErrorAddressRegister); + StatusRegister = READ_PORT_UCHAR(&((PDAKOTA_CONTROL) + HalpIoControlBase)->L2CacheErrorClear); + + HalpWriteBridgeUchar(0x800000C1, 0xFF); // Clear Error Detection Register 1. + HalpWriteBridgeUchar(0x800000C5, 0xFF); // Clear Error Detection Register 2. + StatusRegister = HalpReadBridgeUshort(0x80000006); // Get any Un-documented Status bits. + HalpWriteBridgeUshort(0x80000006, 0xF900 | (USHORT)(StatusRegister)); // Clear Device Status Register. + + // + // Initialize the PowerPC HID0 register here, + // before we clear the detection bits in the Kauai/Lanai. + // Otherwise we can miss the MCP pin signal transition. + // + HalpEnable_HID0_Settings(); // Setup HID0 register. +} + + +ULONG +HalpSizeL2Cache( + VOID + ) +{ + return (HalpSizeL2()); +} + + +VOID +HalpEnableL2Cache( + VOID + ) +{ + BOOLEAN Negate; + int i; + UCHAR CharBuffer[BUF_LEN], *Value; + UCHAR L2_Parameter[BUF_LEN]; + UCHAR ControlByte; + + // + // Parse the environment variable "L2" + // + + if (HalGetEnvironmentVariable("L2", BUF_LEN, &CharBuffer[0]) == ESUCCESS) { + + // Copy L2 environment variable + i = 0; + while (L2_Parameter[i] = CharBuffer[i]) { + i++; + } + + for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, " :;,") ) + { + if (*Value == NEGATECHAR) { + Value++; + Negate = TRUE; + } else + Negate = FALSE; + + // Check for L2 = "OFF" + if (HalpStrCmp( "OFF", Value )) + { + OemDisplayString("HAL: L2 cache is disabled via environment variable L2\n"); + HalpFlushAndDisableL2(); + PCR->SecondLevelDcacheSize = PCR->SecondLevelIcacheSize = 0; + return; + } + // Check for WriteThrough + else if ( HalpStrCmp( "WT", Value ) || HalpStrCmp( "ON", Value )) + { + if (Negate) { + Value--; + goto ParseError; + } + + // + // Enable L2 cache on Kauai / Lanai. + // + HalpFlushAndEnableL2(); + + } else { + +ParseError: HalDisplayString("HAL: Error in L2 environment variable: "); + HalDisplayString(L2_Parameter); + HalDisplayString("\n illegal parameter begins here "); + for (i = 0; i < Value - CharBuffer; i++) + HalDisplayString("\304"); + HalDisplayString("^\n"); + break; + } + + } // End for + } // End If + + return; +} + +VOID +HalpEnable_HID0_Settings( + VOID + ) +{ + USHORT CpuRevision, CpuType; + UCHAR CharBuffer[BUF_LEN], *Value; + ULONG HidEnable, HidDisable, CurrentHID0; + BOOLEAN Negate; + +#define HID_MCP (0x80000000) +#define HID_CACHE (0x40000000) +#define HID_ADDRESS (0x20000000) +#define HID_DATA (0x10000000) +#define HID_PAR (0x01000000) +#define HID_DPM (0x00100000) +#define HID_FBIOB (0x00000010) +#define HID_BHT (0x00000004) +#define HID_NOOPTI (0x00000001) + +#define SetCPUMask( Disable, Val ) \ +{ \ + if (Disable) \ + HidDisable |= Val; \ + else \ + HidEnable |= Val; \ +} + + CpuType = (USHORT)(HalpGetProcessorVersion() >> 16); + CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF); + + HidEnable = 0; + HidDisable = 0; + CurrentHID0 = HalpGetHID0(); + + switch (CpuType) { + case 7: // 603ev + // + // Work-around for early parts. + // + CurrentHID0 |= HID_NOOPTI; + + case 3: // 603 + case 6: // 603e + // + // Enable Dynamic Power Management + // + CurrentHID0 |= HID_DPM; + break; + + case 4: // 604 + case 9: // 604e + // + // Enable L1 Cache Parity Checking + // + CurrentHID0 |= HID_CACHE; + break; + } + + // + // Set the default CPU Parity Checking. + // This default can be platform dependent. + // + + CurrentHID0 |= HID_MCP; + + // + // The environment variable "HID0SETTINGS" is defined either as: + // "CACHE", "ADDRESS", "DATA", "MCP", "DPM" with either blank or semi-colon + // characters used as separators. Matching a string serves to enable + // that feature while a tilde (~) immediately before the parameter + // string indicates that it is to be disabled. + // + + if (HalGetEnvironmentVariable("HID0SETTINGS", BUF_LEN, &CharBuffer[0]) == ESUCCESS) { + for( Value = MyStrtok(CharBuffer, " :;,"); Value; Value = MyStrtok(NULL, " :;,") ) { + + Negate = FALSE; + + if (*Value == NEGATECHAR) { + Value++; + Negate = TRUE; + } + + if (HalpStrCmp("MCP", Value)) { + SetCPUMask(Negate, HID_MCP); + } else if (HalpStrCmp("ADDRESS", Value)) { + SetCPUMask(Negate, HID_ADDRESS); + } else if (HalpStrCmp("DATA", Value)) { + SetCPUMask(Negate, HID_DATA); + } else if (HalpStrCmp("PAR", Value)) { + SetCPUMask(Negate, HID_PAR); + } else if (HalpStrCmp("BHT", Value)) { + SetCPUMask(Negate, HID_BHT); + } else if (HalpStrCmp("CACHE", Value)) { + SetCPUMask(Negate, HID_CACHE); + } else if (HalpStrCmp("DPM", Value)) { + SetCPUMask(Negate, HID_DPM); + } else if (HalpStrCmp("FBIOB", Value)) { + SetCPUMask(Negate, HID_FBIOB); + } else if (HalpStrCmp("NOOPTI", Value)) { + SetCPUMask(Negate, HID_NOOPTI); + } else { + + HalDisplayString("HAL: Error in HID0SETTINGS environment variable: "); + HalDisplayString(CharBuffer); + HalDisplayString("\n"); + } + } // End While + } // End If + + // + // Check for inconsistencies in HID0SETTINGS + // + if (HidEnable & HidDisable) { + HalDisplayString("HAL: Inconsistent settings in HID0SETTINGS environment variable.\n"); + HalDisplayString(" Disable setting will override enable setting.\n"); + // + // Enforce DISABLE override ENABLE + // + HidEnable &= ~HidDisable; + } + + // + // Disable and Enable the bits in the HID0 register. + // + CurrentHID0 &= ~HidDisable; // Disable bits first. + HalpSetHID0(CurrentHID0); + + CurrentHID0 |= HidEnable; // Enable Bits last. + HalpSetHID0(CurrentHID0); +} + + +BOOLEAN +HalpMapPlanarSpace ( + VOID + ) + +/*++ + +Routine Description: + + This routine maps the interrupt acknowledge and error address + spaces for a PowerPC system. + +Arguments: + + None. + +Return Value: + + If the initialization is successfully completed, than a value of TRUE + is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + + PHYSICAL_ADDRESS physicalAddress; + + + // + // Map interrupt control space. + // + + physicalAddress.HighPart = 0; + physicalAddress.LowPart = INTERRUPT_PHYSICAL_BASE; + HalpInterruptBase = MmMapIoSpace(physicalAddress, + PAGE_SIZE, + FALSE); + + // + // Map the error address register + // + + physicalAddress.HighPart = 0; + physicalAddress.LowPart = ERROR_ADDRESS_REGISTER; + HalpErrorAddressRegister = MmMapIoSpace(physicalAddress, + PAGE_SIZE, + FALSE); + + if (HalpInterruptBase == NULL || HalpErrorAddressRegister == NULL) + return FALSE; + else + return TRUE; + + + +} + +BOOLEAN +HalpMapBusConfigSpace ( + VOID + ) + +/*++ + +Routine Description: + + This routine maps the HAL PCI config + spaces for a PowerPC system. + +Arguments: + + None. + +Return Value: + + If the initialization is successfully completed, than a value of TRUE + is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + + PHYSICAL_ADDRESS physicalAddress; + + + // + // Map the PCI config space. + // + + physicalAddress.LowPart = PCI_CONFIG_PHYSICAL_BASE; + HalpPciConfigBase = MmMapIoSpace(physicalAddress, + PCI_CONFIG_SIZE, + FALSE); + + if (HalpPciConfigBase == NULL) + return FALSE; + else + return TRUE; + +} + +BOOLEAN +HalpPhase0MapBusConfigSpace ( + VOID + ) + +/*++ + +Routine Description: + + This routine maps the HAL PCI config + spaces for a PowerPC system during phase 0 initialization. + +Arguments: + + None. + +Return Value: + + If the initialization is successfully completed, than a value of TRUE + is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + // + // Map the PCI config space. + // + + HalpPciConfigBase = (PUCHAR)KePhase0MapIo(PCI_CONFIG_PHYSICAL_BASE, 0x400000); + + if (HalpPciConfigBase == NULL) + return FALSE; + else + return TRUE; + +} + +VOID +HalpPhase0UnMapBusConfigSpace ( + VOID + ) + +/*++ + +Routine Description: + + This routine maps the HAL PCI config + spaces for a PowerPC system during phase 0 initialization. + +Arguments: + + None. + +Return Value: + + If the initialization is successfully completed, than a value of TRUE + is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + // + // Unmap the PCI config space and set HalpPciConfigBase to NULL. + // + + KePhase0DeleteIoMap(PCI_CONFIG_PHYSICAL_BASE, 0x400000); + HalpPciConfigBase = NULL; + +} + + +VOID +HalpHandleMemoryError( + VOID + ) + +{ + + UCHAR StatusByte; + ULONG ErrorAddress; + UCHAR TextAddress[20]; + USHORT DeviceStatus; + + // + // Read the error address register first + // + + ErrorAddress = READ_PORT_ULONG(HalpErrorAddressRegister); + + // + // Convert error address to HEX characters + // + + HalpDisplayHex32(ErrorAddress, TextAddress ); + + DeviceStatus = HalpReadBridgeUshort(0x80000006); + if (DeviceStatus & 0x8100) + HalDisplayString("\n27-82660: Status Register: PARITY Error Detected.\n"); + if (DeviceStatus & 0x4000) + HalDisplayString("\n27-82660: Status Register: SERR asserted.\n"); + +// MOTKJR 08/22/95 - Don't check for the following bit. +// It is always set when NT scans the slots on the PCI bus. +// if (DeviceStatus & 0x2000) +// HalDisplayString("\n27-82660: Status Register: Transaction terminated with master-abort.\n"); + + if (DeviceStatus & 0x1000) + HalDisplayString("\n27-82660: Status Register: Transaction terminated by target-abort while master.\n"); + if (DeviceStatus & 0x0800) + HalDisplayString("\n27-82660: Status Register: Transaction terminated by target-abort while slave.\n"); + + // + // Check TEA conditions + // + + StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL) + HalpIoControlBase)->MemoryParityErrorStatus); + + if (!(StatusByte & 0x01)) { + HalDisplayString ("27-82660: Memory Parity Error at Address "); + HalDisplayString (TextAddress); + } + + StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL) + HalpIoControlBase)->L2CacheErrorStatus); + + if (!(StatusByte & 0x01)) { + HalDisplayString ("27-82660: L2 Cache Parity Error\n"); + } + + StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL) + HalpIoControlBase)->TransferErrorStatus); + + if (!(StatusByte & 0x01)) { + HalDisplayString ("27-82660: Transfer Error at Address "); + HalDisplayString (TextAddress); + } + + // + // Check the Error Status 1 Register + // + + StatusByte = HalpReadBridgeUchar(0x800000C1); + + if (StatusByte & 0x03) + HalDisplayString("27-82660: CPU Transfer Error.\n"); + + if (StatusByte & 0x04) + HalDisplayString("27-82660: Memory Parity Error.\n"); + + if (StatusByte & 0x08) + HalDisplayString("27-82660: Memory Multi-bit ECC Error.\n"); + + if (StatusByte & 0x20) + HalDisplayString("27-82660: Memory Select Error.\n"); + + if (StatusByte & 0x40) + HalDisplayString("27-82660: PCI Data Bus Parity Error or PCI_SERR asserted.\n"); + + // + // Check the Error Status 2 Register + // + + StatusByte = HalpReadBridgeUchar(0x800000C5); + + if (StatusByte & 0x04) + HalDisplayString("27-82660: CPU Data Bus Parity Error.\n"); + + if (StatusByte & 0x08) + HalDisplayString("27-82660: L2 Parity Error.\n"); + + // + // Check the PCI Bus Error Status Register + // + + StatusByte = HalpReadBridgeUchar(0x800000C7); + + if (StatusByte & 0x10) + HalDisplayString("27-82660: PCI cycle with 82660 Bridge as target.\n"); + +#if DBG + // + // We have had a catastrophic hardware malfunction. + // Dump the state of the Bridge and HID 0 registers. + // + HalDisplayString("\n"); + HalpDumpHardwareState(); +#endif +} + + +VOID +HalpCheckHardwareRevisionLevels( + VOID + ) +{ + USHORT CpuRevision, CpuType; + UCHAR BridgeRevision; + UCHAR CharBuffer[20], i; + ARC_STATUS Status; + + CpuType = (USHORT)(HalpGetProcessorVersion() >> 16); + CpuRevision = (USHORT)(HalpGetProcessorVersion() & 0xFFFF); + BridgeRevision = HalpReadBridgeUchar(0x80000008); + + // + // Minimum hardware requirements: + // 660 Bridge: v1.1 or greater + // 603 or 604: v3.2 or greater + // 603e: v1.4 or greater + // 603ev: any CPU revision + // 601, 604e, 620: any CPU revision + // + if (BridgeRevision >= 0x01) { + switch (CpuType) { + case 3: // 603 + case 4: // 604 + if (CpuRevision >= 0x0302) + return; + break; + + case 6: // 603e + if (CpuRevision >= 0x0104) + return; + break; + + case 1: // 601 + case 7: // 603ev + case 9: // 604e + case 20: // 620 + default: + return; + } + } + + // + // If the environment variable BOOTOLDHARDWARE exists + // (value is a don't care), then try to boot anyway. + // + Status = HalGetEnvironmentVariable("BOOTOLDHARDWARE", 5, CharBuffer); + if (Status == ESUCCESS || Status == ENOMEM) + return; + + HalDisplayString("HAL: Unsupported CPU and/or Bridge revision level."); + + // + // Bug check - after stalling to allow + // any information printed on the screen + // to be read and seen by the user. + // + for (i=0; i<15; i++) { + HalDisplayString("."); + KeStallExecutionProcessor(1000000); + } + + KeBugCheck(HAL_INITIALIZATION_FAILED); + return; +} + + +VOID HalpDumpHardwareState(VOID) +{ ULONG BridgeRegister, HID0; + UCHAR CharBuffer[12]; + +#if DBG + + if ( HalGetEnvironmentVariable("DBG_HAL", BUF_LEN, &CharBuffer[0]) == ESUCCESS ) { + + BridgeRegister = HalpReadBridgeUshort(0x80000004); + HalDisplayString("HAL: Bridge register 04 = 0x"); + HalpDisplayHex16(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUshort(0x80000006); + HalDisplayString("HAL: Bridge register 06 = 0x"); + HalpDisplayHex16(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUchar(0x800000A0); + HalDisplayString("HAL: Bridge register A0 = 0x"); + HalpDisplayHex8(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUchar(0x800000A1); + HalDisplayString("HAL: Bridge register A1 = 0x"); + HalpDisplayHex8(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUchar(0x800000A2); + HalDisplayString("HAL: Bridge register A2 = 0x"); + HalpDisplayHex8(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUchar(0x800000B1); + HalDisplayString("HAL: Bridge register B1 = 0x"); + HalpDisplayHex8(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUchar(0x800000BA); + HalDisplayString("HAL: Bridge register BA = 0x"); + HalpDisplayHex8(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUchar(0x800000BB); + HalDisplayString("HAL: Bridge register BB = 0x"); + HalpDisplayHex8(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUchar(0x800000C0); + HalDisplayString("HAL: Bridge register C0 = 0x"); + HalpDisplayHex8(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUchar(0x800000C1); + HalDisplayString("HAL: Bridge register C1 = 0x"); + HalpDisplayHex8(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUchar(0x800000C3); + HalDisplayString("HAL: Bridge register C3 = 0x"); + HalpDisplayHex8(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUchar(0x800000C4); + HalDisplayString("HAL: Bridge register C4 = 0x"); + HalpDisplayHex8(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUchar(0x800000C5); + HalDisplayString("HAL: Bridge register C5 = 0x"); + HalpDisplayHex8(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUchar(0x800000C7); + HalDisplayString("HAL: Bridge register C7 = 0x"); + HalpDisplayHex8(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUlong(0x800000C8); + HalDisplayString("HAL: Bridge register C8 = 0x"); + HalpDisplayHex32(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + BridgeRegister = HalpReadBridgeUchar(0x800000D4); + HalDisplayString("HAL: Bridge register D4 = 0x"); + HalpDisplayHex8(BridgeRegister, CharBuffer ); + HalDisplayString(CharBuffer); + + HID0 = HalpGetHID0(); + HalDisplayString("HAL: PowerPC Register HID0 = 0x"); + HalpDisplayHex32(HID0, CharBuffer ); + HalDisplayString(CharBuffer); + + HalDisplayString("HAL: PCR Virtual Address - sprg1 = 0x"); + HalpDisplayHex32((ULONG)PCRsprg1, CharBuffer ); + HalDisplayString(CharBuffer); + } + +#endif + +} diff --git a/private/ntos/nthals/halps/ppc/pxmisc.s b/private/ntos/nthals/halps/ppc/pxmisc.s new file mode 100644 index 000000000..e7014c025 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxmisc.s @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxmisc.s> diff --git a/private/ntos/nthals/halps/ppc/pxpcibrd.c b/private/ntos/nthals/halps/ppc/pxpcibrd.c new file mode 100644 index 000000000..d9b36ce5d --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxpcibrd.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxpcibrd.c> diff --git a/private/ntos/nthals/halps/ppc/pxpcibus.c b/private/ntos/nthals/halps/ppc/pxpcibus.c new file mode 100644 index 000000000..ef86e6e28 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxpcibus.c @@ -0,0 +1,2289 @@ +/*++ + + +Copyright (C) 1989-1995 Microsoft Corporation + +Module Name: + + pxpcibus.c + +Abstract: + + Get/Set bus data routines for the PCI bus + +Author: + + Ken Reneris (kenr) 14-June-1994 + Jim Wooldridge Port to PowerPC + +Environment: + + Kernel mode + +Revision History: + + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +#include "pxmemctl.h" +#include "pxpcisup.h" + +extern WCHAR rgzMultiFunctionAdapter[]; +extern WCHAR rgzConfigurationData[]; +extern WCHAR rgzIdentifier[]; +extern WCHAR rgzPCIIdentifier[]; + +extern ULONG HalpPciMaxSlots; + +typedef ULONG (*FncConfigIO) ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +typedef VOID (*FncSync) ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PVOID State + ); + +typedef VOID (*FncReleaseSync) ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ); + +typedef struct _PCI_CONFIG_HANDLER { + FncSync Synchronize; + FncReleaseSync ReleaseSynchronzation; + FncConfigIO ConfigRead[3]; + FncConfigIO ConfigWrite[3]; +} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER; + + + +// +// Prototypes +// + +ULONG +HalpGetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +ULONG +HalpSetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +NTSTATUS +HalpAssignPCISlotResources ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN ULONG SlotNumber, + IN OUT PCM_RESOURCE_LIST *AllocatedResources + ); + +VOID +HalpInitializePciBus ( + VOID + ); + +BOOLEAN +HalpIsValidPCIDevice ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ); + +BOOLEAN +HalpValidPCISlot ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ); + +//------------------------------------------------- + +VOID HalpPCISynchronizeType1 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PVOID State + ); + +VOID HalpPCIReleaseSynchronzationType1 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ); + +ULONG HalpPCIReadUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +VOID HalpPCISynchronizeType2 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PVOID State + ); + +VOID HalpPCIReleaseSynchronzationType2 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ); + +ULONG HalpPCIReadUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIReadUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + +ULONG HalpPCIWriteUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset + ); + + +// +// Globals +// + +KSPIN_LOCK HalpPCIConfigLock; + +PCI_CONFIG_HANDLER PCIConfigHandler; + +PCI_CONFIG_HANDLER PCIConfigHandlerType1 = { + HalpPCISynchronizeType1, + HalpPCIReleaseSynchronzationType1, + { + HalpPCIReadUlongType1, // 0 + HalpPCIReadUcharType1, // 1 + HalpPCIReadUshortType1 // 2 + }, + { + HalpPCIWriteUlongType1, // 0 + HalpPCIWriteUcharType1, // 1 + HalpPCIWriteUshortType1 // 2 + } +}; + +PCI_CONFIG_HANDLER PCIConfigHandlerType2 = { + HalpPCISynchronizeType2, + HalpPCIReleaseSynchronzationType2, + { + HalpPCIReadUlongType2, // 0 + HalpPCIReadUcharType2, // 1 + HalpPCIReadUshortType2 // 2 + }, + { + HalpPCIWriteUlongType2, // 0 + HalpPCIWriteUcharType2, // 1 + HalpPCIWriteUshortType2 // 2 + } +}; + +UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} }; + +VOID +HalpPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length, + IN FncConfigIO *ConfigIO + ); + +#if DBG +#define DBGMSG(a) DbgPrint(a) +VOID +HalpTestPci ( + ULONG + ); +#else +#define DBGMSG(a) +#endif + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpInitializePciBus) +#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler) +#pragma alloc_text(INIT,HalpIsValidPCIDevice) +#pragma alloc_text(PAGE,HalpAssignPCISlotResources) +#endif + + + +VOID +HalpInitializePciBus ( + VOID + ) +{ + PPCI_REGISTRY_INFO PCIRegInfo; + UNICODE_STRING unicodeString, ConfigName, IdentName; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE hMFunc, hBus; + NTSTATUS status; + UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99]; + PWSTR p; + WCHAR wstr[8]; + ULONG i, d, junk, HwType; + PBUS_HANDLER BusHandler; + PCI_SLOT_NUMBER SlotNumber; + PKEY_VALUE_FULL_INFORMATION ValueInfo; + PCM_FULL_RESOURCE_DESCRIPTOR Desc; + PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc; + + + // + // Search the hardware description looking for any reported + // PCI bus. The first ARC entry for a PCI bus will contain + // the PCI_REGISTRY_INFO. + + RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter); + InitializeObjectAttributes ( + &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + NULL, // handle + NULL); + + + status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes); + if (!NT_SUCCESS(status)) { + return ; + } + + unicodeString.Buffer = wstr; + unicodeString.MaximumLength = sizeof (wstr); + + RtlInitUnicodeString (&ConfigName, rgzConfigurationData); + RtlInitUnicodeString (&IdentName, rgzIdentifier); + + ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer; + + for (i=0; TRUE; i++) { + RtlIntegerToUnicodeString (i, 10, &unicodeString); + InitializeObjectAttributes ( + &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + hMFunc, + NULL); + + status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes); + if (!NT_SUCCESS(status)) { + // + // Out of Multifunction adapter entries... + // + + ZwClose (hMFunc); + return ; + } + + // + // Check the Indentifier to see if this is a PCI entry + // + + status = ZwQueryValueKey ( + hBus, + &IdentName, + KeyValueFullInformation, + ValueInfo, + sizeof (buffer), + &junk + ); + + if (!NT_SUCCESS (status)) { + ZwClose (hBus); + continue; + } + + p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset); + if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) { + ZwClose (hBus); + continue; + } + + // + // The first PCI entry has the PCI_REGISTRY_INFO structure + // attached to it. + // + + status = ZwQueryValueKey ( + hBus, + &ConfigName, + KeyValueFullInformation, + ValueInfo, + sizeof (buffer), + &junk + ); + + ZwClose (hBus); + if (!NT_SUCCESS(status)) { + continue ; + } + + Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR) + ValueInfo + ValueInfo->DataOffset); + PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR) + Desc->PartialResourceList.PartialDescriptors); + + if (PDesc->Type == CmResourceTypeDeviceSpecific) { + // got it.. + PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1); + break; + } + } + + // + // Initialize spinlock for synchronizing access to PCI space + // + + KeInitializeSpinLock (&HalpPCIConfigLock); + + // + // PCIRegInfo describes the system's PCI support as indicated by the BIOS. + // + + HwType = PCIRegInfo->HardwareMechanism & 0xf; + +#if 0 + // + // Some AMI bioses claim machines are Type2 configuration when they + // are really type1. If this is a Type2 with at least one bus, + // try to verify it's not really a type1 bus + // + + if (PCIRegInfo->NoBuses && HwType == 2) { + + // + // Check each slot for a valid device. Which every style configuration + // space shows a valid device first will be used + // + + SlotNumber.u.bits.Reserved = 0; + SlotNumber.u.bits.FunctionNumber = 0; + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + SlotNumber.u.bits.DeviceNumber = d; + + // + // First try what the BIOS claims - type 2. Allocate type2 + // test handle for PCI bus 0. + // + + HwType = 2; + BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE); + + if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) { + break; + } + + // + // Valid device not found on Type2 access for this slot. + // Reallocate the bus handler are Type1 and take a look. + // + + HwType = 1; + BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE); + + if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) { + break; + } + + HwType = 2; + } + + // + // Reset handler for PCI bus 0 to whatever style config space + // was finally decided. + // + + HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE); + } +#endif + + + // + // For each PCI bus present, allocate a handler structure and + // fill in the dispatch functions + // + + do { + for (i=0; i < PCIRegInfo->NoBuses; i++) { + + // + // If handler not already built, do it now + // + + if (!HalpHandlerForBus (PCIBus, i)) { + HalpAllocateAndInitPciBusHandler (HwType, i, FALSE); + } + } + + // + // Bus handlers for all PCI buses have been allocated, go collect + // pci bridge information. + // + + } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ; + + // + // Fixup SUPPORTED_RANGES + // + + HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses); + +#if DBG + HalpTestPci (0); +#endif +} + + +PBUS_HANDLER +HalpAllocateAndInitPciBusHandler ( + IN ULONG HwType, + IN ULONG BusNo, + IN BOOLEAN TestAllocation + ) +{ + PBUS_HANDLER Bus; + PPCIPBUSDATA BusData; + + Bus = HalpAllocateBusHandler ( + PCIBus, // Interface type + PCIConfiguration, // Has this configuration space + BusNo, // bus # + Internal, // child of this bus + 0, // and number + sizeof (PCIPBUSDATA) // sizeof bus specific buffer + ); + + // + // Fill in PCI handlers + // + + Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData; + Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData; + Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus; + Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList; + Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources; + Bus->BusAddresses->Dma.Limit = 0; + + BusData = (PPCIPBUSDATA) Bus->BusData; + + // + // Fill in common PCI data + // + + BusData->CommonData.Tag = PCI_DATA_TAG; + BusData->CommonData.Version = PCI_DATA_VERSION; + BusData->CommonData.ReadConfig = (PciReadWriteConfig) HalpReadPCIConfig; + BusData->CommonData.WriteConfig = (PciReadWriteConfig) HalpWritePCIConfig; + BusData->CommonData.Pin2Line = (PciPin2Line) HalpPCIPin2ISALine; + BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin; + + // + // Set defaults + // + + Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF; + Bus->BusAddresses->IO.Limit = 0x3F7FFFFF; + BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq; + + RtlInitializeBitMap (&BusData->DeviceConfigured, + BusData->ConfiguredBits, 256); + + switch (HwType) { + case 1: + // + // Initialize access port information for Type1 handlers + // direct Method. + // + + RtlCopyMemory (&PCIConfigHandler, + &PCIConfigHandlerType1, + sizeof (PCIConfigHandler)); + + BusData->MaxDevice = HalpPciMaxSlots; + break; + + case 2: + // + // Initialize access port information for Type2 handlers + // indirect Method. + // + + RtlCopyMemory (&PCIConfigHandler, + &PCIConfigHandlerType2, + sizeof (PCIConfigHandler)); + + // + // Allow access all 32 devices per bus. + // + BusData->MaxDevice = PCI_MAX_DEVICES; + break; + + default: + // unsupport type + DBGMSG ("HAL: Unkown PCI type\n"); + } + + if (!TestAllocation) { +#ifdef SUBCLASSPCI + HalpSubclassPCISupport (Bus, HwType); +#endif + } + + return Bus; +} + +BOOLEAN +HalpIsValidPCIDevice ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ) +/*++ + +Routine Description: + + Reads the device configuration data for the given slot and + returns TRUE if the configuration data appears to be valid for + a PCI device; otherwise returns FALSE. + +Arguments: + + BusHandler - Bus to check + Slot - Slot to check + +--*/ + +{ + PPCI_COMMON_CONFIG PciData; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + ULONG i, j; + + + PciData = (PPCI_COMMON_CONFIG) iBuffer; + + // + // Read device common header + // + + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Valid device header? + // + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + + return FALSE; + } + + // + // Check fields for reasonable values + // + + if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) || + (PciData->u.type0.InterruptLine & 0x70)) { + return FALSE; + } + + for (i=0; i < PCI_TYPE0_ADDRESSES; i++) { + j = PciData->u.type0.BaseAddresses[i]; + + if (j & PCI_ADDRESS_IO_SPACE) { + if (j > 0xffff) { + // IO port > 64k? + return FALSE; + } + } else { + if (j > 0xf && j < 0x80000) { + // Mem address < 0x8000h? + return FALSE; + } + } + + if (Is64BitBaseAddress(j)) { + i += 1; + } + } + + // + // Guess it's a valid device.. + // + + return TRUE; +} + + + + + +ULONG +HalpGetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the Pci bus data for a device. + +Arguments: + + BusNumber - Indicates which bus. + + VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word) + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + + If this PCI slot has never been set, then the configuration information + returned is zeroed. + + +--*/ +{ + PPCI_COMMON_CONFIG PciData; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + PPCIPBUSDATA BusData; + ULONG Len; + ULONG i, bit; + + if (Length > sizeof (PCI_COMMON_CONFIG)) { + Length = sizeof (PCI_COMMON_CONFIG); + } + + Len = 0; + PciData = (PPCI_COMMON_CONFIG) iBuffer; + + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The user did not request any data from the common + // header. Verify the PCI device exists, then continue + // in the device specific area. + // + + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG)); + + if (PciData->VendorID == PCI_INVALID_VENDORID) { + return 0; + } + + } else { + + // + // Caller requested at least some data within the + // common header. Read the whole header, effect the + // fields we need to and then copy the user's requested + // bytes from the header + // + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + // + // Read this PCI devices slot data + // + + Len = PCI_COMMON_HDR_LENGTH; + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len); + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + PciData->VendorID = PCI_INVALID_VENDORID; + Len = 2; // only return invalid id + + } else { + + BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData); + } + + // + // Has this PCI device been configured? + // + +#if 0 + // + // On DBG build, if this PCI device has not yet been configured, + // then don't report any current configuration the device may have. + // + + bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber); + if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) { + + for (i=0; i < PCI_TYPE0_ADDRESSES; i++) { + PciData->u.type0.BaseAddresses[i] = 0; + } + + PciData->u.type0.ROMBaseAddress = 0; + PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE); + } +#endif + + + // + // Copy whatever data overlaps into the callers buffer + // + + if (Len < Offset) { + // no data at caller's buffer + return 0; + } + + Len -= Offset; + if (Len > Length) { + Len = Length; + } + + RtlMoveMemory(Buffer, iBuffer + Offset, Len); + + Offset += Len; + Buffer += Len; + Length -= Len; + } + + if (Length) { + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The remaining Buffer comes from the Device Specific + // area - put on the kitten gloves and read from it. + // + // Specific read/writes to the PCI device specific area + // are guarenteed: + // + // Not to read/write any byte outside the area specified + // by the caller. (this may cause WORD or BYTE references + // to the area in order to read the non-dword aligned + // ends of the request) + // + // To use a WORD access if the requested length is exactly + // a WORD long. + // + // To use a BYTE access if the requested length is exactly + // a BYTE long. + // + + HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length); + Len += Length; + } + } + + return Len; +} + +ULONG +HalpSetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the Pci bus data for a device. + +Arguments: + + + VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word) + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + +--*/ +{ + PPCI_COMMON_CONFIG PciData, PciData2; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH]; + PPCIPBUSDATA BusData; + ULONG Len, cnt; + + + if (Length > sizeof (PCI_COMMON_CONFIG)) { + Length = sizeof (PCI_COMMON_CONFIG); + } + + + Len = 0; + PciData = (PPCI_COMMON_CONFIG) iBuffer; + PciData2 = (PPCI_COMMON_CONFIG) iBuffer2; + + + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The user did not request any data from the common + // header. Verify the PCI device exists, then continue in + // the device specific area. + // + + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG)); + + if (PciData->VendorID == PCI_INVALID_VENDORID) { + return 0; + } + + } else { + + // + // Caller requested to set at least some data within the + // common header. + // + + Len = PCI_COMMON_HDR_LENGTH; + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len); + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + + // no device, or header type unkown + return 0; + } + + + // + // Set this device as configured + // + + BusData = (PPCIPBUSDATA) BusHandler->BusData; +#if 0 + cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber); + RtlSetBits (&BusData->DeviceConfigured, cnt, 1); +#endif + // + // Copy COMMON_HDR values to buffer2, then overlay callers changes. + // + + RtlMoveMemory (iBuffer2, iBuffer, Len); + BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2); + + Len -= Offset; + if (Len > Length) { + Len = Length; + } + + RtlMoveMemory (iBuffer2+Offset, Buffer, Len); + + // in case interrupt line or pin was editted + BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData); + +#if DBG + // + // Verify R/O fields haven't changed + // + if (PciData2->VendorID != PciData->VendorID || + PciData2->DeviceID != PciData->DeviceID || + PciData2->RevisionID != PciData->RevisionID || + PciData2->ProgIf != PciData->ProgIf || + PciData2->SubClass != PciData->SubClass || + PciData2->BaseClass != PciData->BaseClass || + PciData2->HeaderType != PciData->HeaderType || + PciData2->BaseClass != PciData->BaseClass || + PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant || + PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) { + DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n"); + //DbgBreakPoint (); + } +#endif + // + // Set new PCI configuration + // + + HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len); + + Offset += Len; + Buffer += Len; + Length -= Len; + } + + if (Length) { + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The remaining Buffer comes from the Device Specific + // area - put on the kitten gloves and write it + // + // Specific read/writes to the PCI device specific area + // are guarenteed: + // + // Not to read/write any byte outside the area specified + // by the caller. (this may cause WORD or BYTE references + // to the area in order to read the non-dword aligned + // ends of the request) + // + // To use a WORD access if the requested length is exactly + // a WORD long. + // + // To use a BYTE access if the requested length is exactly + // a BYTE long. + // + + HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length); + Len += Length; + } + } + + return Len; +} + +VOID +HalpReadPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ +#define ATIBUG 1 +#if ATIBUG + USHORT VendorId; + LONG Len; +#endif + + if (!HalpValidPCISlot (BusHandler, Slot)) { + // + // Invalid SlotID return no data + // + + RtlFillMemory (Buffer, Length, (UCHAR) -1); + return ; + } + +#if ATIBUG +// +// Temporary Hack (MOTKJR) - We have discovered a problem between the ATI +// Video Driver and the NCR 810/825 SCSI parts. The NCR chip has hardware +// registers in Configuration Space above 0x40 which have a side effect that +// a read from these registers is destructive to its contents. If a SCSI +// operation is active when these registers are read, the NCR device will +// abort the operation and further I/O is impossible. Therefore, we will +// not allow anyone to read from Offset 0x40 to 0xFF for any PCI slot that +// has an NCR vendor ID number. Care must be taken to check for requests +// which overlap both the PCI Common Header and the Device Dependent area. +// +#define NCR_VENDOR_ID 0x1000 + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) &VendorId, 0x0, sizeof(VendorId), + PCIConfigHandler.ConfigRead); + + if ((VendorId == NCR_VENDOR_ID) && (Offset + Length > PCI_COMMON_HDR_LENGTH)) { + Len = PCI_COMMON_HDR_LENGTH - Offset; + if (Len < 0) + Len = 0; + RtlFillMemory ((PVOID)((PUCHAR)Buffer+Len), Length-Len, (UCHAR) -1); + if (Offset >= PCI_COMMON_HDR_LENGTH) + return; + Length = Len; + } +#endif + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length, + PCIConfigHandler.ConfigRead); +} + +VOID +HalpWritePCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ + if (!HalpValidPCISlot (BusHandler, Slot)) { + // + // Invalid SlotID do nothing + // + return ; + } + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length, + PCIConfigHandler.ConfigWrite); +} + +BOOLEAN +HalpValidPCISlot ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ) +{ + PCI_SLOT_NUMBER Slot2; + PPCIPBUSDATA BusData; + UCHAR HeaderType; + ULONG i; + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + if (Slot.u.bits.Reserved != 0) { + return FALSE; + } + + if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) { + return FALSE; + } + + if (Slot.u.bits.FunctionNumber == 0) { + return TRUE; + } + + // + // Non zero function numbers are only supported if the + // device has the PCI_MULTIFUNCTION bit set in it's header + // + + i = Slot.u.bits.DeviceNumber; + + // + // Read DeviceNumber, Function zero, to determine if the + // PCI supports multifunction devices + // + + Slot2 = Slot; + Slot2.u.bits.FunctionNumber = 0; + + HalpReadPCIConfig ( + BusHandler, + Slot2, + &HeaderType, + FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType), + sizeof (UCHAR) + ); + + if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) { + // this device doesn't exists or doesn't support MULTIFUNCTION types + return FALSE; + } + + return TRUE; +} + + +VOID +HalpPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length, + IN FncConfigIO *ConfigIO + ) +{ + KIRQL OldIrql; + ULONG i; + UCHAR State[20]; + PPCIPBUSDATA BusData; + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State); + + while (Length) { + i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)]; + i = ConfigIO[i] (BusData, State, Buffer, Offset); + + Offset += i; + Buffer += i; + Length -= i; + } + + PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql); +} + +VOID HalpPCISynchronizeType1 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PPCI_TYPE1_CFG_BITS PciCfg1 + ) +{ + // + // Initialize PciCfg1 + // + + PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.bits.DeviceNumber) + + 0x100 * Slot.u.bits.FunctionNumber; + +} + +VOID HalpPCIReleaseSynchronzationType1 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ) +{ + + +} + + +ULONG +HalpPCIReadUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfg1->u.AsULONG + i)); + return sizeof (UCHAR); +} + +ULONG +HalpPCIReadUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT)(PciCfg1->u.AsULONG + i)); + return sizeof (USHORT); +} + +ULONG +HalpPCIReadUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfg1->u.AsULONG)); + return sizeof (ULONG); +} + + +ULONG +HalpPCIWriteUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_UCHAR (PciCfg1->u.AsULONG + i, *Buffer ); + return sizeof (UCHAR); +} + +ULONG +HalpPCIWriteUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_USHORT (PciCfg1->u.AsULONG + i, *((PUSHORT) Buffer) ); + return sizeof (USHORT); +} + +ULONG +HalpPCIWriteUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG (PciCfg1->u.AsULONG, *((PULONG) Buffer) ); + return sizeof (ULONG); +} + +VOID HalpPCISynchronizeType2 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PPCI_TYPE1_CFG_BITS PciCfg1 + ) +{ + + // + // Initialize PciCfg1 + // + + PciCfg1->u.AsULONG = 0; + if ((PciCfg1->u.bits.BusNumber = BusHandler->BusNumber) == 0) { + + // This hack is to maintain device number compatibility + // on bus 0 with the Type1 functions. We do this so that + // the installed base maintains the same "slot" numbering. + // The notable issue is with network interfaces where the + // slot number is stored in the registry at install time. + // It was judged too subtle and too painful to have everyone + // reinstall networking if they added a bridged device to + // their system. + + int MappedDev; + ULONG Offset; + #define PRESHIFT 9 // Make invalid slot numbers to map to dev 0. + // Dev 0 is inaccessible from the 27-82660 Bridge. + + // Get the offset from the Type1 (direct mapping) offset table. + // If the device number isn't "valid", use an offset that won't + // actually end up selecting any device. + + Offset = (Slot.u.bits.DeviceNumber < HalpPciMaxSlots) ? + HalpPciConfigSlot[Slot.u.bits.DeviceNumber] : (1 << (PRESHIFT+1)); + + // Determine the device number accessed by the "offset". + // If bit 11 is set, MappedDev = 11; bit 12, MappedDev = 12;... + + Offset >>= PRESHIFT; + MappedDev = PRESHIFT - 1; + + do { + MappedDev++; + Offset >>= 1; + + } while (Offset); + + // The 27-82660 docs say to set the device number field to + // 10 less than the PCI Address bit number. + + PciCfg1->u.bits.DeviceNumber = MappedDev - 10; + + } else { + PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber; + } + PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber; + PciCfg1->u.bits.Enable = TRUE; + + KeRaiseIrql (PROFILE_LEVEL, Irql); + KiAcquireSpinLock (&HalpPCIConfigLock); + +} + + +VOID HalpPCIReleaseSynchronzationType2 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ) +{ + + KiReleaseSpinLock (&HalpPCIConfigLock); + KeLowerIrql (Irql); + +} + + +ULONG +HalpPCIReadUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG ); + *((PUCHAR) Buffer) = READ_PORT_UCHAR ((PUCHAR)&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData + i); + return sizeof (UCHAR); +} + +ULONG +HalpPCIReadUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG ); + *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUCHAR)&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData + i); + return sizeof (USHORT); +} + +ULONG +HalpPCIReadUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG); + *((PULONG) Buffer) = READ_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData); + return sizeof(ULONG); +} + + +ULONG +HalpPCIWriteUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG ); + WRITE_PORT_UCHAR ((PUCHAR)&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData + i,*Buffer); + return sizeof (UCHAR); +} + +ULONG +HalpPCIWriteUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG ); + WRITE_PORT_USHORT ((PUCHAR)&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData + (USHORT) i,*((PUSHORT)Buffer)); + return sizeof (USHORT); +} + +ULONG +HalpPCIWriteUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigAddress, PciCfg1->u.AsULONG); + WRITE_PORT_ULONG (&((PPLANAR_CONTROL)HalpIoControlBase)->ConfigData,*((PULONG)Buffer)); + return sizeof(ULONG); +} + + +NTSTATUS +HalpAssignPCISlotResources ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN ULONG Slot, + IN OUT PCM_RESOURCE_LIST *pAllocatedResources + ) +/*++ + +Routine Description: + + Reads the targeted device to determine it's required resources. + Calls IoAssignResources to allocate them. + Sets the targeted device with it's assigned resoruces + and returns the assignments to the caller. + +Arguments: + +Return Value: + + STATUS_SUCCESS or error + +--*/ +{ + NTSTATUS status; + PUCHAR WorkingPool; + PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2; + PCI_SLOT_NUMBER PciSlot; + PPCIPBUSDATA BusData; + PIO_RESOURCE_REQUIREMENTS_LIST CompleteList; + PIO_RESOURCE_DESCRIPTOR Descriptor; + PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor; + ULONG BusNumber; + ULONG i, j, m, length, memtype; + ULONG NoBaseAddress, RomIndex, Option; + PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1]; + PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1]; + BOOLEAN Match, EnableRomBase; + + + *pAllocatedResources = NULL; + PciSlot = *((PPCI_SLOT_NUMBER) &Slot); + BusNumber = BusHandler->BusNumber; + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + // + // Allocate some pool for working space + // + + i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) + + sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 + + PCI_COMMON_HDR_LENGTH * 3; + + WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i); + if (!WorkingPool) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Zero initialize pool, and get pointers into memory + // + + RtlZeroMemory (WorkingPool, i); + CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool; + PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3); + PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2); + PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1); + + // + // Read the PCI device's configuration + // + + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + if (PciData->VendorID == PCI_INVALID_VENDORID) { + ExFreePool (WorkingPool); + return STATUS_NO_SUCH_DEVICE; + } + + // + // Make a copy of the device's current settings + // + + RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH); + + // + // Initialize base addresses base on configuration data type + // + + switch (PCI_CONFIG_TYPE(PciData)) { + case 0 : + NoBaseAddress = PCI_TYPE0_ADDRESSES+1; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + BaseAddress[j] = &PciData->u.type0.BaseAddresses[j]; + OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j]; + } + BaseAddress[j] = &PciData->u.type0.ROMBaseAddress; + OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress; + RomIndex = j; + break; + case 1: + NoBaseAddress = PCI_TYPE1_ADDRESSES+1; + for (j=0; j < PCI_TYPE1_ADDRESSES; j++) { + BaseAddress[j] = &PciData->u.type1.BaseAddresses[j]; + OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j]; + } + BaseAddress[j] = &PciData->u.type1.ROMBaseAddress; + OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress; + RomIndex = j; + break; + + default: + ExFreePool (WorkingPool); + return STATUS_NO_SUCH_DEVICE; + } + + // + // If the BIOS doesn't have the device's ROM enabled, then we won't + // enable it either. Remove it from the list. + // + + EnableRomBase = TRUE; + if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) { + ASSERT (RomIndex+1 == NoBaseAddress); + EnableRomBase = FALSE; + NoBaseAddress -= 1; + } + + // + // Set resources to all bits on to see what type of resources + // are required. + // + + for (j=0; j < NoBaseAddress; j++) { + *BaseAddress[j] = 0xFFFFFFFF; + } + +//*BJ* PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE); + *BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED; + HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine + BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData); + + // + // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device + // + + CompleteList->InterfaceType = PCIBus; + CompleteList->BusNumber = BusNumber; + CompleteList->SlotNumber = Slot; + CompleteList->AlternativeLists = 1; + + CompleteList->List[0].Version = 1; + CompleteList->List[0].Revision = 1; + + Descriptor = CompleteList->List[0].Descriptors; + + // + // If PCI device has an interrupt resource, add it + // + + if (PciData->u.type0.InterruptPin) { + CompleteList->List[0].Count++; + + Descriptor->Option = 0; + Descriptor->Type = CmResourceTypeInterrupt; + Descriptor->ShareDisposition = CmResourceShareShared; + Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; + + // Fill in any vector here - we'll pick it back up in + // HalAdjustResourceList and adjust it to it's allowed settings + Descriptor->u.Interrupt.MinimumVector = 0; + Descriptor->u.Interrupt.MaximumVector = 0xff; + Descriptor++; + } + + // + // Add a memory/port resoruce for each PCI resource + // + + *BaseAddress[RomIndex] &= ~0x7ff; + + // + // Rom Base Address resource is not enabled, as the ROM code cannot + // be executed on a risk box, and the algorithm below interprets + // the card's Rom Base Address requirements incorrectly + // + + + for (j=0; j < NoBaseAddress; j++) { + if (*BaseAddress[j]) { + i = *BaseAddress[j]; + + // scan for first set bit, that's the length & alignment + length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4); + while (!(i & length) && length) { + length <<= 1; + } + + // scan for last set bit, that's the maxaddress + 1 + for (m = length; i & m; m <<= 1) ; + m--; + + // check for hosed PCI configuration requirements + if (length & ~m) { +#if DBG + DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n", + BusNumber, + PciSlot.u.bits.DeviceNumber, + PciSlot.u.bits.FunctionNumber + ); + + DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i); +#endif + // the device is in error - punt. don't allow this + // resource any option - it either gets set to whatever + // bits it was able to return, or it doesn't get set. + + if (i & PCI_ADDRESS_IO_SPACE) { + m = i & ~0x3; + Descriptor->u.Port.MinimumAddress.LowPart = m; + } else { + m = i & ~0xf; + Descriptor->u.Memory.MinimumAddress.LowPart = m; + } + + m += length; // max address is min address + length + } + + // + // Add requested resource + // + + Descriptor->Option = 0; + if (i & PCI_ADDRESS_IO_SPACE) { + memtype = 0; + + if (PciOrigData->Command & PCI_ENABLE_IO_SPACE) { + + // + // The IO range is/was already enabled at some location, add that + // as it's preferred setting. + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + Descriptor->Option = IO_RESOURCE_PREFERRED; + + Descriptor->u.Port.Length = length; + Descriptor->u.Port.Alignment = length; + Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3; + Descriptor->u.Port.MaximumAddress.LowPart = + Descriptor->u.Port.MinimumAddress.LowPart + length - 1; + + CompleteList->List[0].Count++; + Descriptor++; + + Descriptor->Option = IO_RESOURCE_ALTERNATIVE; + } + + // + // Add this IO range + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + + Descriptor->u.Port.Length = length; + Descriptor->u.Port.Alignment = length; + Descriptor->u.Port.MaximumAddress.LowPart = m; + + } else { + + memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK; + + Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; + if (j == RomIndex) { + // this is a ROM address + Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY; + } + + if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) { + Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; + } + + if (!Is64BitBaseAddress(i) && + (j == RomIndex || + PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) { + + // + // The memory range is/was already enabled at some location, add that + // as it's preferred setting. + // + + Descriptor->Type = CmResourceTypeMemory; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Option = IO_RESOURCE_PREFERRED; + + Descriptor->u.Port.Length = length; + Descriptor->u.Port.Alignment = length; + Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF; + Descriptor->u.Port.MaximumAddress.LowPart = + Descriptor->u.Port.MinimumAddress.LowPart + length - 1; + + CompleteList->List[0].Count++; + Descriptor++; + + Descriptor->Flags = Descriptor[-1].Flags; + Descriptor->Option = IO_RESOURCE_ALTERNATIVE; + } + + // + // Add this memory range + // + + Descriptor->Type = CmResourceTypeMemory; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + + Descriptor->u.Memory.Length = length; + Descriptor->u.Memory.Alignment = length; + Descriptor->u.Memory.MaximumAddress.LowPart = m; + + if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) { + // limit to 20 bit address + Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF; + } + + if (Is64BitBaseAddress(i)) { + // skip upper half of 64 bit address since this processor + // only supports 32 bits of address space + j++; + } + } + + CompleteList->List[0].Count++; + Descriptor++; + + } + } + + CompleteList->ListSize = (ULONG) + ((PUCHAR) Descriptor - (PUCHAR) CompleteList); + + // + // Restore the device settings as we found them, enable memory + // and io decode after setting base addresses. This is done in + // case HalAdjustResourceList wants to read the current settings + // in the device. + // + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + &PciOrigData->Status, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status), + PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + PciOrigData, + 0, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + // + // Have the IO system allocate resource assignments + // + + status = IoAssignResources ( + RegistryPath, + DriverClassName, + DriverObject, + DeviceObject, + CompleteList, + pAllocatedResources + ); + + if (!NT_SUCCESS(status)) { + goto CleanUp; + } + + // + // Slurp the assigments back into the PciData structure and + // perform them + // + + CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors; + + // + // If PCI device has an interrupt resource then that was + // passed in as the first requested resource + // + + if (PciData->u.type0.InterruptPin) { + PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector; + BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData); + CmDescriptor++; + } + + // + // Pull out resources in the order they were passed to IoAssignResources + // + + m = 0; + for (j=0; j < NoBaseAddress; j++) { + i = *BaseAddress[j]; + if (i) { + if (i & PCI_ADDRESS_IO_SPACE) { + m |= PCI_ENABLE_IO_SPACE; + *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart; + } else { + m |= PCI_ENABLE_MEMORY_SPACE; + *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart; + + if (Is64BitBaseAddress(i)) { + // skip upper 32 bits + j++; + } + } + CmDescriptor++; + } + } + + // + // Set addresses, but do not turn on decodes + // + + HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Read configuration back and verify address settings took + // + + HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH); + + Match = TRUE; + if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine || + PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin || + PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) { + Match = FALSE; + } + + for (j=0; j < NoBaseAddress; j++) { + if (*BaseAddress[j]) { + if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) { + i = (ULONG) ~0x3; + } else { + i = (ULONG) ~0xF; + } + + if ((*BaseAddress[j] & i) != + *((PULONG) ((PUCHAR) BaseAddress[j] - + (PUCHAR) PciData + + (PUCHAR) PciData2)) & i) { + + Match = FALSE; + } + + if (!(*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) && + (Is64BitBaseAddress(*BaseAddress[j]))) { + // skip upper 32 bits + j++; + } + } + } + + if (!Match) { +#if DBG + DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n", + BusNumber, + PciSlot.u.bits.DeviceNumber, + PciSlot.u.bits.FunctionNumber + ); +#endif + status = STATUS_DEVICE_PROTOCOL_ERROR; + goto CleanUp; + } + + // + // Settings took - turn on the appropiate decodes + // + + if (EnableRomBase && *BaseAddress[RomIndex]) { + // a rom address was allocated and should be enabled + *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED; + HalpWritePCIConfig ( + BusHandler, + PciSlot, + BaseAddress[RomIndex], + (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData), + sizeof (ULONG) + ); + } + + // enable IO & Memory decodes (use HalSetBusData since valid settings now set) + + // Set Bus master bit on for win95 compatability + m |= PCI_ENABLE_BUS_MASTER; + + PciData->Command |= (USHORT) m; + HalSetBusDataByOffset ( + PCIConfiguration, + BusHandler->BusNumber, + PciSlot.u.AsULONG, + &PciData->Command, + FIELD_OFFSET (PCI_COMMON_CONFIG, Command), + sizeof (PciData->Command) + ); + +CleanUp: + if (!NT_SUCCESS(status)) { + + // + // Failure, if there are any allocated resources free them + // + + if (*pAllocatedResources) { + IoAssignResources ( + RegistryPath, + DriverClassName, + DriverObject, + DeviceObject, + NULL, + NULL + ); + + ExFreePool (*pAllocatedResources); + *pAllocatedResources = NULL; + } + + // + // Restore the device settings as we found them, enable memory + // and io decode after setting base addresses + // + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + &PciOrigData->Status, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status), + PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + PciOrigData, + 0, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + } + + ExFreePool (WorkingPool); + return status; +} + +#if DBG +VOID +HalpTestPci (ULONG flag2) +{ + PCI_SLOT_NUMBER SlotNumber; + PCI_COMMON_CONFIG PciData, OrigData; + ULONG i, f, j, k, bus; + BOOLEAN flag; + + + if (!flag2) { + return ; + } + + DbgBreakPoint (); + SlotNumber.u.bits.Reserved = 0; + + // + // Read every possible PCI Device/Function and display it's + // default info. + // + // (note this destories it's current settings) + // + + flag = TRUE; + for (bus = 0; flag; bus++) { + + for (i = 0; i < PCI_MAX_DEVICES; i++) { + SlotNumber.u.bits.DeviceNumber = i; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + SlotNumber.u.bits.FunctionNumber = f; + + // + // Note: This is reading the DeviceSpecific area of + // the device's configuration - normally this should + // only be done on device for which the caller understands. + // I'm doing it here only for debugging. + // + + j = HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + if (j == 0) { + // out of buses + flag = FALSE; + break; + } + + if (j < PCI_COMMON_HDR_LENGTH) { + continue; + } + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + 1 + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + +#if 0 + memcpy (&OrigData, &PciData, sizeof PciData); + + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF; + } + + PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF; + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); +#endif + + DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx", + bus, i, f, PciData.VendorID, PciData.DeviceID, + PciData.RevisionID); + + + if (PciData.u.type0.InterruptPin) { + DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin); + } + + if (PciData.u.type0.InterruptLine) { + DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine); + } + + if (PciData.u.type0.ROMBaseAddress) { + DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n", + PciData.Command, PciData.Status, PciData.ProgIf, + PciData.SubClass, PciData.BaseClass); + + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (PciData.u.type0.BaseAddresses[j]) { + DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]); + k = 1; + } + } + +#if 0 + if (PciData.u.type0.ROMBaseAddress == 0xC08001) { + + PciData.u.type0.ROMBaseAddress = 0xC00001; + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + DbgPrint ("\n Bogus rom address, edit yields:%08lx", + PciData.u.type0.ROMBaseAddress); + } +#endif + + if (k) { + DbgPrint ("\n"); + } + + if (PciData.VendorID == 0x8086) { + // dump complete buffer + DbgPrint ("Command %x, Status %x, BIST %x\n", + PciData.Command, PciData.Status, + PciData.BIST + ); + + DbgPrint ("CacheLineSz %x, LatencyTimer %x", + PciData.CacheLineSize, PciData.LatencyTimer + ); + + for (j=0; j < 192; j++) { + if ((j & 0xf) == 0) { + DbgPrint ("\n%02x: ", j + 0x40); + } + DbgPrint ("%02x ", PciData.DeviceSpecific[j]); + } + DbgPrint ("\n"); + } + + +#if 0 + // + // now print original data + // + + if (OrigData.u.type0.ROMBaseAddress) { + DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n"); + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (OrigData.u.type0.BaseAddresses[j]) { + DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]); + k = 1; + } + } + + // + // Restore original settings + // + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &OrigData, + sizeof (PciData) + ); +#endif + + // + // Next + // + + if (k) { + DbgPrint ("\n\n"); + } + } + } + } + DbgBreakPoint (); +} +#endif diff --git a/private/ntos/nthals/halps/ppc/pxpciint.c b/private/ntos/nthals/halps/ppc/pxpciint.c new file mode 100644 index 000000000..0160a0c96 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxpciint.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxpciint.c> diff --git a/private/ntos/nthals/halps/ppc/pxpcisup.c b/private/ntos/nthals/halps/ppc/pxpcisup.c new file mode 100644 index 000000000..abf5bc95f --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxpcisup.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxpcisup.c> diff --git a/private/ntos/nthals/halps/ppc/pxport.c b/private/ntos/nthals/halps/ppc/pxport.c new file mode 100644 index 000000000..d6ca10d1f --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxport.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxport.c> diff --git a/private/ntos/nthals/halps/ppc/pxpower.s b/private/ntos/nthals/halps/ppc/pxpower.s new file mode 100644 index 000000000..cb0822573 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxpower.s @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxpower.s> diff --git a/private/ntos/nthals/halps/ppc/pxproc.c b/private/ntos/nthals/halps/ppc/pxproc.c new file mode 100644 index 000000000..91b9dc338 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxproc.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxproc.c> diff --git a/private/ntos/nthals/halps/ppc/pxprof.c b/private/ntos/nthals/halps/ppc/pxprof.c new file mode 100644 index 000000000..e04f3f9bd --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxprof.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxprof.c> diff --git a/private/ntos/nthals/halps/ppc/pxreset.s b/private/ntos/nthals/halps/ppc/pxreset.s new file mode 100644 index 000000000..d328bf4a3 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxreset.s @@ -0,0 +1,433 @@ +//++ +// +// Copyright (C) 1993-1995 IBM Corporation +// +// Copyright (C) 1994-1995 MOTOROLA, INC. All Rights Reserved. This file +// contains copyrighted material. Use of this file is restricted +// by the provisions of a Motorola Software License Agreement. +// +// Module Name: +// +// 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. +// +// +// Environment: +// +// Kernel mode only. +// +// +//-- + +#include "kxppc.h" + + .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) + LWI(r.4, 0xfff00100) // address of rom reset handler + mfspr r.5, HID0 + mfpvr r.31 // determine processor type + li r.6, 0 + li r.7, 0x92 + oris r.7, r.7, 0x8000 + mfmsr r.8 + rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_EE,1) // disable interrupts + mtmsr r.8 + cror 0,0,0 // N.B. 603e/ev Errata 15 + + // + // 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 + + srwi r.31, r.31, 16 // isolate processor type + cmpwi r.31, 1 // is 601? + + bl here // get current address +here: + mflr r.9 // (r.9) = &here + rlwinm r.9, r.9, 0, 0x7fffffff // convert address to physical + + bne not_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. + + 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 + mtsr 0, r.9 // Set the last segment register + 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 + + rfi // head off into the reset handler +end_little: + addi r.0, r.1, 0x138 // we never get here + addi r.0, r.1, 0x138 + + 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.5 contains HID0 present value. +// 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 physical address of "here" +// r.31 contains the processor type + + +not_601: + cmpwi r.31, 3 // is 603? + beq is_603 + cmpwi r.31, 6 // is 603+? + beq is_603 + cmpwi r.31, 7 // is 603ev? + beq is_603 + + cmpwi cr.2, r.31, 4 // is 604? + cmpwi cr.3, r.31, 9 // is 604+? + b 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 + b common_6034 + +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 + +// +// 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 + +// b common_6034 // join common code + + +// +// The following is common to both 603 and 604 +// + +common_6034: + +// +// 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_DR,1) // -= Data Relocation + 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 + sync + +// +// Try to issue a hard reset. If this fails, the fall +// thru and continue to manually return to firmware. +// + + addi r.5, r.0, 0xFF // All ones + stb r.5, 0(r.7) // Reset the System + sync + sync + sync + sync + +// +// Continue returning to firmware... +// + +// +// 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, swapend - uncached_6034 + addis r.15, r.15, 0 + addi r.9, 0, 0 + addi r.15, 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: + stb r.6, 0(r.7) // switch memory + sync + sync + sync + sync + 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 + .globl uncached_6034 + .long uncached_6034 + +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 + 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 + .little_endian +endofroutine: + sync + .globl swapend + .long swapend +swapend: + + LEAF_EXIT(HalpPowerPcReset) diff --git a/private/ntos/nthals/halps/ppc/pxreturn.c b/private/ntos/nthals/halps/ppc/pxreturn.c new file mode 100644 index 000000000..812168de2 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxreturn.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxreturn.c> diff --git a/private/ntos/nthals/halps/ppc/pxsiosup.c b/private/ntos/nthals/halps/ppc/pxsiosup.c new file mode 100644 index 000000000..ab763410f --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxsiosup.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxsiosup.c> diff --git a/private/ntos/nthals/halps/ppc/pxstall.s b/private/ntos/nthals/halps/ppc/pxstall.s new file mode 100644 index 000000000..b22d5550b --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxstall.s @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxstall.s> diff --git a/private/ntos/nthals/halps/ppc/pxsysbus.c b/private/ntos/nthals/halps/ppc/pxsysbus.c new file mode 100644 index 000000000..c3d901bd9 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxsysbus.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxsysbus.c> diff --git a/private/ntos/nthals/halps/ppc/pxsysint.c b/private/ntos/nthals/halps/ppc/pxsysint.c new file mode 100644 index 000000000..4c2e8240d --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxsysint.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxsysint.c> diff --git a/private/ntos/nthals/halps/ppc/pxsystyp.c b/private/ntos/nthals/halps/ppc/pxsystyp.c new file mode 100644 index 000000000..d80b78b0e --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxsystyp.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxsystyp.c> diff --git a/private/ntos/nthals/halps/ppc/pxtime.c b/private/ntos/nthals/halps/ppc/pxtime.c new file mode 100644 index 000000000..fed4558b9 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxtime.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxtime.c> diff --git a/private/ntos/nthals/halps/ppc/pxusage.c b/private/ntos/nthals/halps/ppc/pxusage.c new file mode 100644 index 000000000..1c856c8e5 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/pxusage.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\pxusage.c> diff --git a/private/ntos/nthals/halps/ppc/sysbios.c b/private/ntos/nthals/halps/ppc/sysbios.c new file mode 100644 index 000000000..9838c5a93 --- /dev/null +++ b/private/ntos/nthals/halps/ppc/sysbios.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\sysbios.c> diff --git a/private/ntos/nthals/halps/ppc/x86bios.c b/private/ntos/nthals/halps/ppc/x86bios.c new file mode 100644 index 000000000..62067325c --- /dev/null +++ b/private/ntos/nthals/halps/ppc/x86bios.c @@ -0,0 +1 @@ +#include <..\..\haleagle\ppc\x86bios.c> -- cgit v1.2.3