diff options
Diffstat (limited to '')
46 files changed, 3966 insertions, 0 deletions
diff --git a/private/ntos/nthals/halwood/ppc/fwnvr.c b/private/ntos/nthals/halwood/ppc/fwnvr.c new file mode 100644 index 000000000..74d30689e --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/fwnvr.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\fwnvr.c> diff --git a/private/ntos/nthals/halwood/ppc/pxbeep.c b/private/ntos/nthals/halwood/ppc/pxbeep.c new file mode 100644 index 000000000..cb3db8ccc --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxbeep.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxbeep.c> diff --git a/private/ntos/nthals/halwood/ppc/pxbusdat.c b/private/ntos/nthals/halwood/ppc/pxbusdat.c new file mode 100644 index 000000000..cbc199e71 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxbusdat.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxbusdat.c> diff --git a/private/ntos/nthals/halwood/ppc/pxcache.s b/private/ntos/nthals/halwood/ppc/pxcache.s new file mode 100644 index 000000000..2c5630a60 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxcache.s @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxcache.s> diff --git a/private/ntos/nthals/halwood/ppc/pxcalstl.c b/private/ntos/nthals/halwood/ppc/pxcalstl.c new file mode 100644 index 000000000..3d972b02b --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxcalstl.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxcalstl.c> diff --git a/private/ntos/nthals/halwood/ppc/pxclksup.s b/private/ntos/nthals/halwood/ppc/pxclksup.s new file mode 100644 index 000000000..8452d5e05 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxclksup.s @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxclksup.s> diff --git a/private/ntos/nthals/halwood/ppc/pxclock.c b/private/ntos/nthals/halwood/ppc/pxclock.c new file mode 100644 index 000000000..16cb61886 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxclock.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxclock.c> diff --git a/private/ntos/nthals/halwood/ppc/pxdat.c b/private/ntos/nthals/halwood/ppc/pxdat.c new file mode 100644 index 000000000..978438ac0 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxdat.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxdat.c> diff --git a/private/ntos/nthals/halwood/ppc/pxdisp.c b/private/ntos/nthals/halwood/ppc/pxdisp.c new file mode 100644 index 000000000..103883cc6 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxdisp.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxdisp.c" + diff --git a/private/ntos/nthals/halwood/ppc/pxenviro.c b/private/ntos/nthals/halwood/ppc/pxenviro.c new file mode 100644 index 000000000..0f822c840 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxenviro.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxenviro.c> diff --git a/private/ntos/nthals/halwood/ppc/pxflshbf.s b/private/ntos/nthals/halwood/ppc/pxflshbf.s new file mode 100644 index 000000000..b2e4b591d --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxflshbf.s @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxflshbf.s> diff --git a/private/ntos/nthals/halwood/ppc/pxflshio.c b/private/ntos/nthals/halwood/ppc/pxflshio.c new file mode 100644 index 000000000..5817b14f5 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxflshio.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxflshio.c> diff --git a/private/ntos/nthals/halwood/ppc/pxhwsup.c b/private/ntos/nthals/halwood/ppc/pxhwsup.c new file mode 100644 index 000000000..9164059ae --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxhwsup.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxhwsup.c> diff --git a/private/ntos/nthals/halwood/ppc/pxidle.c b/private/ntos/nthals/halwood/ppc/pxidle.c new file mode 100644 index 000000000..16bfd2a08 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxidle.c @@ -0,0 +1,62 @@ +/*++ +TITLE("Processor Idle") + + +Copyright (c) 1994 Microsoft Corporation + +Module Name: + + pxidle.c + +abstract: + + This module implements system platform dependent power management + support. + +Author: + + Jim Wooldridge + +Environment: + + Kernel mode only. + +Revision History: + +--*/ + +#include "halp.h" + + +VOID +HalProcessorIdle( + VOID + ) + +/*++ + + Routine Description: + + This function is called when the current processor is idle with + interrupts disabled. There is no thread active and there are no + DPCs to process. Therefore, power can be switched to a standby + mode until the the next interrupt occurs on the current processor. + + N.B. This routine is entered with EE in MSR clear. This routine + must do any power management enabling necessary, set the EE + bit in MSR, then either return or wait for an interrupt. + + Arguments: + + None. + + Return Value: + + None. + + +--*/ + +{ + HalpProcessorIdle(); +} diff --git a/private/ntos/nthals/halwood/ppc/pxinfo.c b/private/ntos/nthals/halwood/ppc/pxinfo.c new file mode 100644 index 000000000..812bd48b4 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxinfo.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxinfo.c> diff --git a/private/ntos/nthals/halwood/ppc/pxinithl.c b/private/ntos/nthals/halwood/ppc/pxinithl.c new file mode 100644 index 000000000..f99a85307 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxinithl.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxinithl.c> diff --git a/private/ntos/nthals/halwood/ppc/pxintmod.c b/private/ntos/nthals/halwood/ppc/pxintmod.c new file mode 100644 index 000000000..a7bfe283c --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxintmod.c @@ -0,0 +1,78 @@ +/*++ + +Module Name: + + pxmemctl.c + +Abstract: + + This module implements interrupt mode translation for PowerPC machines. + + +Author: + + Jim Wooldridge (jimw@austin.vnet.ibm.com) + + +Revision History: + + + +--*/ + + + +#include "halp.h" + + +// +// Get the translated interrupt mode for the given vector +// + + +KINTERRUPT_MODE +HalpGetInterruptMode ( + IN ULONG Vector, + IN KIRQL Irql, + IN KINTERRUPT_MODE InterruptMode + ) + +{ + + // + // On Woodfield irq 15 is reserved for PCI interrupts and must be programmed level sensitive + // all other interrupts are edge triggered + // + + if (Vector == DEVICE_VECTORS + 15) { + + return LevelSensitive; + + } else { + + return Latched; + + } + + + +} + +// +// Correct the interrupt mode for the given vector. +// On Woodfield this function simply returns since all interrupt mode translations can be performed +// at HalpGetInterruptMode time with the interrupt vector. +// + + +VOID +HalpSetInterruptMode ( + IN ULONG Vector, + IN KIRQL Irql + ) + +{ + + return; + +} diff --git a/private/ntos/nthals/halwood/ppc/pxintrpt.c b/private/ntos/nthals/halwood/ppc/pxintrpt.c new file mode 100644 index 000000000..dddf4ce77 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxintrpt.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxintrpt.c" + diff --git a/private/ntos/nthals/halwood/ppc/pxintsup.s b/private/ntos/nthals/halwood/ppc/pxintsup.s new file mode 100644 index 000000000..f72297f65 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxintsup.s @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxintsup.s> diff --git a/private/ntos/nthals/halwood/ppc/pxirql.c b/private/ntos/nthals/halwood/ppc/pxirql.c new file mode 100644 index 000000000..7ad12df0b --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxirql.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxirql.c> diff --git a/private/ntos/nthals/halwood/ppc/pxisabus.c b/private/ntos/nthals/halwood/ppc/pxisabus.c new file mode 100644 index 000000000..a0a2942ed --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxisabus.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxisabus.c> diff --git a/private/ntos/nthals/halwood/ppc/pxmapio.c b/private/ntos/nthals/halwood/ppc/pxmapio.c new file mode 100644 index 000000000..38b6ef09e --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxmapio.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxmapio.c> diff --git a/private/ntos/nthals/halwood/ppc/pxmemctl.c b/private/ntos/nthals/halwood/ppc/pxmemctl.c new file mode 100644 index 000000000..8f3fdb04b --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxmemctl.c @@ -0,0 +1,338 @@ + +/*++ + +Copyright (c) 1990 Microsoft Corporation + +Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file +contains copyrighted material. Use of this file is restricted +by the provisions of a Motorola Software License Agreement. + +Copyright (c) 1994, 1995 International Buisness Machines Corporation. + +Module Name: + + pxmemctl.c + +Abstract: + + The module initializes any planar registers. + This module also implements machince check parity error handling. + +Author: + + Jim Wooldridge (jimw@austin.vnet.ibm.com) + + +Revision History: + + Chris Karamatas (ckaramatas@vnet.ibm.com) - added HalpHandleMemoryError + +--*/ + + + +#include "halp.h" +#include <pxmemctl.h> +#include "pxidaho.h" +#include "pci.h" +#include "pcip.h" + + + +BOOLEAN +HalpInitPlanar ( + VOID + ) + +{ + // + // Enable Dynamic Power Management on 603 and 603+. + // + + HalpSetDpm(); + + return TRUE; + +} + + + +BOOLEAN +HalpMapPlanarSpace ( + VOID + ) + +/*++ + +Routine Description: + + This routine maps the interrupt acknowledge and error address + spaces for a PowerPC system. + +Arguments: + + None. + +Return Value: + + If the initialization is successfully completed, than a value of TRUE + is returned. Otherwise, a value of FALSE is returned. + +--*/ + +{ + + + PHYSICAL_ADDRESS physicalAddress; + + + // + // Map interrupt control space. + // + + physicalAddress.HighPart = 0; + physicalAddress.LowPart = INTERRUPT_PHYSICAL_BASE; + HalpInterruptBase = MmMapIoSpace(physicalAddress, + PAGE_SIZE, + FALSE); + + 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. + +--*/ + +{ + + HalpPciConfigBase = (PVOID) IO_CONTROL_PHYSICAL_BASE; + + return TRUE; + +} + +BOOLEAN +HalpPhase0MapBusConfigSpace ( + 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. + +--*/ + +{ + + HalpPciConfigBase = (PVOID) IO_CONTROL_PHYSICAL_BASE; + + if (HalpIoControlBase == NULL) { + HalpIoControlBase = (PUCHAR)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE, 0x400000); + } + + if (HalpIoControlBase == NULL) + return FALSE; + else + return TRUE; + + +} + +VOID +HalpPhase0UnMapBusConfigSpace ( + 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. + +--*/ + +{ + +} + + +VOID +HalpDisplayRegister( + PUCHAR RegHex, + int Bytes + ) + +/*++ + +Routine Description: + + Displays (via HalDisplayString) a new-line terminated + string of hex digits representing the input value. The + input value is pointed to by the first argument is + from 1 to 4 bytes in length. + +Arguments: + + RegHex Pointer to the value to be displayed. + Bytes Length of input value in bytes (1-4). + +Return Value: + + None. + +--*/ + +{ +#define DISP_MAX 4 + UCHAR RegString[(DISP_MAX * 2) + 2]; + UCHAR Num, High, Low; + PUCHAR Byte = &RegString[(DISP_MAX * 2) + 1]; + + *Byte = '\0'; + *--Byte = '\n'; + + if ( (unsigned)Bytes > DISP_MAX ) { + Bytes = DISP_MAX; + } + + while (Bytes--) { + Num = *RegHex++; + High = (Num >> 4) + '0'; + Low = (Num & 0xf) + '0'; + if ( High > '9' ) { + High += ('A' - '0' - 0xA); + } + if ( Low > '9' ) { + Low += ('A' - '0' - 0xA); + } + *--Byte = Low; + *--Byte = High; + } + HalDisplayString(Byte); +} + +VOID +HalpHandleMemoryError( + VOID + ) + +{ + int byte; + IDAHO_CONFIG PCI_Config_Space; + UCHAR BusAddress[4]; + + // + // REM Make sure Options Reg.1 (0xBA) and Enable Detection Reg. (0xC0) are programed + // Reset Error Det Reg when done ? + + HalGetBusData(PCIConfiguration, 0, 0, &PCI_Config_Space, sizeof(IDAHO_CONFIG)); + + // Dump Error Detection Reg, Bus Address, Status Error, + + HalDisplayString ("TEA/MCP: System Error.\n"); + + HalDisplayString ("Error Detection Register 1: "); + HalpDisplayRegister (&PCI_Config_Space.ErrorDetection1,1); + + // + // The error may have been detected during xfers on: cpu (local), memory, or pci bus + // + // Idaho will NOT generate/check Local Bus Parity + + if (PCI_Config_Space.ErrorDetection1 & 0x03) { // idaho <-> 603 :Local bus Cycle + + HalDisplayString ("Unsupported Local Bus Cycle\n"); + + for (byte = 0; byte < 4; byte++) // Correct endianess if address is local + BusAddress[byte] = PCI_Config_Space.ErrorAddress[3-byte]; + HalDisplayString ("Local Bus Error Address: "); + HalpDisplayRegister(BusAddress,4); + + HalDisplayString ("CPU Bus Error Status - TT(0:4);TSIZ(0:2): "); + HalpDisplayRegister(&PCI_Config_Space.CpuBusErrorStatus,1); + +// if (ErrorDetection & 0x01 { +// HalDisplayString ("Unsupported Transfer Attributes\n"); +// } +// if (ErrorDetection & 0x02 { +// HalDisplay ("Extended Transfer Detected\n"); +// } + } + else if (PCI_Config_Space.ErrorDetection1 & 0x08) { // PCI Cycle + HalDisplayString ("PCI Cycle\n"); + + for (byte=0; byte<4; byte++) + BusAddress[byte] = PCI_Config_Space.ErrorAddress[byte]; + HalDisplayString ("PCI Bus Address: "); + HalpDisplayRegister(BusAddress,4); + + HalDisplayString ("PCI Bus Error Status: "); + HalpDisplayRegister(&PCI_Config_Space.PciBusErrorStatus,1); + +// if PCI_Config_Space.PciBusErrorStatus & 0x10 +// HalDisplayString("Memory Controller was Slave on PCI Bus\n"); +// else +// HalDisplayString("Memory Controller was Master on PCI Bus\n"); + + HalDisplayString ("PCI Device Status Register D(15:8): "); + HalpDisplayRegister(&PCI_Config_Space.DeviceStatus[1],1); + +// if PCI_Config_Space.DeviceStatus[1] & 0x81 +// HalDisplayString("Local Bus Agent Read Cycle\n"); + +// if ErrorDetection & 0x80 // Local Bus Agent Write Cycle +// HalDisplayString ("PCI System Error\n"); +// if ErrorDetection & 0x40 // Local Bus Agent Write\Read Address +// HalDisplayString ("PCI Parity Error\n ");// Parity Error +// Read PCI status Reg + +// if ErrorDetection & 0x20 +// HalDisplayString ("No Such Address in Physical Memory\n"); + + } +// if ErrorDetection & 0x10 +// HalDisplayString ("Refresh Timeout\n"); + +} diff --git a/private/ntos/nthals/halwood/ppc/pxmemctl.h b/private/ntos/nthals/halwood/ppc/pxmemctl.h new file mode 100644 index 000000000..1c0ca1966 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxmemctl.h @@ -0,0 +1,36 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + + +Module Name: + + pxmemctl.h + +Abstract: + + This header file defines the structures for the planar registers + for an Idaho memory controller. + + + + +Author: + + Jim Wooldridge + + +Revision History: + +--*/ + + +// +// define physical base addresses of planar +// + +#define INTERRUPT_PHYSICAL_BASE 0xbffffff0 // physical base of interrupt source +#define ERROR_ADDRESS_REGISTER 0xbfffeff0 + +#define IO_CONTROL_PHYSICAL_BASE 0x80000000 // physical base of IO control +#define SYSTEM_IO_CONTROL_SIZE 0x00008000 + + diff --git a/private/ntos/nthals/halwood/ppc/pxnatsup.c b/private/ntos/nthals/halwood/ppc/pxnatsup.c new file mode 100644 index 000000000..45b71d905 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxnatsup.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxnatsup.c> diff --git a/private/ntos/nthals/halwood/ppc/pxpcibrd.c b/private/ntos/nthals/halwood/ppc/pxpcibrd.c new file mode 100644 index 000000000..d10d244dd --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxpcibrd.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxpcibrd.c> diff --git a/private/ntos/nthals/halwood/ppc/pxpcibus.c b/private/ntos/nthals/halwood/ppc/pxpcibus.c new file mode 100644 index 000000000..2120ef5f4 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxpcibus.c @@ -0,0 +1,2404 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Copyright (c) 1996 International Business Machines Corporation + +Module Name: + + pxpcidat.c + +Abstract: + + Get/Set bus data routines for the PCI bus + +Author: + + Ken Reneris (kenr) 14-June-1994 + Jim Wooldridge Port to PowerPC + +Environment: + + Kernel mode + +Revision History: + + Chris Karamatas (ckaramatas@vnet.ibm.com) - Updated and merged support for various PPC boxes. + Jake Oshins (joshins@vnet.ibm.com) -- Further merging and generalization, support for more boxes. + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +#define PCI_DISPLAY_CONTROLLER 0x03 +#define PCI_PRE_REV_2 0x0 +#define IsVideoDevice(a) \ + (((a->BaseClass == PCI_DISPLAY_CONTROLLER) && \ + (a->SubClass == 0)) || \ + (((a->BaseClass == PCI_PRE_REV_2) && \ + (a->SubClass == 1)))) + +extern WCHAR rgzMultiFunctionAdapter[]; +extern WCHAR rgzConfigurationData[]; +extern WCHAR rgzIdentifier[]; +extern WCHAR rgzPCIIdentifier[]; + +ULONG HalpPciMaxBuses = 0; +extern ULONG HalpPciMaxSlots; +#if defined(UNION) +extern PVOID HalpPciConfigAddr[]; +extern PVOID HalpPciConfigData[]; +#endif +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, BusNo, f; + PBUS_HANDLER BusHandler; + PCI_SLOT_NUMBER SlotNumber; + PPCI_COMMON_CONFIG PciData; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + PKEY_VALUE_FULL_INFORMATION ValueInfo; + PCM_FULL_RESOURCE_DESCRIPTOR Desc; + PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc; + + // + // Search the hardware description looking for any reported + // PCI bus. The first ARC entry for a PCI bus will contain + // the PCI_REGISTRY_INFO. + + // + RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter); + InitializeObjectAttributes ( + &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + NULL, // handle + NULL); + + + status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes); + if (!NT_SUCCESS(status)) { + return ; + } + + unicodeString.Buffer = wstr; + unicodeString.MaximumLength = sizeof (wstr); + + RtlInitUnicodeString (&ConfigName, rgzConfigurationData); + RtlInitUnicodeString (&IdentName, rgzIdentifier); + + ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer; + + for (i=0; TRUE; i++) { + RtlIntegerToUnicodeString (i, 10, &unicodeString); + InitializeObjectAttributes ( + &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + hMFunc, + NULL); + + status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes); + if (!NT_SUCCESS(status)) { + // + // Out of Multifunction adapter entries... + // + + ZwClose (hMFunc); + return ; + } + + // + // Check the Indentifier to see if this is a PCI entry + // + + status = ZwQueryValueKey ( + hBus, + &IdentName, + KeyValueFullInformation, + ValueInfo, + sizeof (buffer), + &junk + ); + + if (!NT_SUCCESS (status)) { + ZwClose (hBus); + continue; + } + + p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset); + if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) { + ZwClose (hBus); + continue; + } + + // + // The first PCI entry has the PCI_REGISTRY_INFO structure + // attached to it. + // + + status = ZwQueryValueKey ( + hBus, + &ConfigName, + KeyValueFullInformation, + ValueInfo, + sizeof (buffer), + &junk + ); + + ZwClose (hBus); + if (!NT_SUCCESS(status)) { + continue ; + } + + Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR) + ValueInfo + ValueInfo->DataOffset); + PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR) + Desc->PartialResourceList.PartialDescriptors); + + if (PDesc->Type == CmResourceTypeDeviceSpecific) { + // got it.. + PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1); + break; + } + } + + // + // Initialize spinlock for synchronizing access to PCI space + // + + KeInitializeSpinLock (&HalpPCIConfigLock); + PciData = (PPCI_COMMON_CONFIG) iBuffer; + + // + // PCIRegInfo describes the system's PCI support as indicated by the BIOS. + // + + HwType = PCIRegInfo->HardwareMechanism & 0xf; + + // + // 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); + } + + + // + // For each PCI bus present, allocate a handler structure and + // fill in the dispatch functions + // + + do { + for (i=0; i < PCIRegInfo->NoBuses; i++) { + + // + // If handler not already built, do it now + // + + if (!HalpHandlerForBus (PCIBus, i)) { + HalpAllocateAndInitPciBusHandler (HwType, i, FALSE); + } + } + + // + // Bus handlers for all PCI buses have been allocated, go collect + // pci bridge information. + // + + } while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ; + + // + // Fixup SUPPORTED_RANGES + // + + HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses); + // + // Look for PCI controllers which have known work-arounds, and make + // sure they are applied. + // + + SlotNumber.u.bits.Reserved = 0; + for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) { + BusHandler = HalpHandlerForBus (PCIBus, BusNo); + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + SlotNumber.u.bits.FunctionNumber = f; + + // + // Read PCI configuration information + // + + HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Check for chips with known work-arounds to apply + // + + if (PciData->VendorID == 0x8086 && + PciData->DeviceID == 0x04A3 && + PciData->RevisionID < 0x11) { + + // + // 82430 PCMC controller + // + + HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2); + + buffer[0] &= ~0x08; // turn off bit 3 register 0x53 + + if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn + buffer[1] &= ~0x01; // bit 0 register 0x54 + } + + HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2); + } + + if (PciData->VendorID == 0x8086 && + PciData->DeviceID == 0x0484 && + PciData->RevisionID <= 3) { + + // + // 82378 ISA bridge & SIO + // + + HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1); + + buffer[0] &= ~0x1; // turn off bit 0 register 0x41 + + HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1); + } + + } // next function + } // next device + } // next bus + + // + // Build a tree that shows the relationship of all the PCI busses + // to be used when routing interrupts. + // + HalpMapPlugInPciBridges (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) HalpGetPCIIrq; + + + RtlInitializeBitMap (&BusData->DeviceConfigured, + BusData->ConfiguredBits, 256); + + switch (HwType) { + case 1: + // + // Initialize access port information for Type1 handlers + // + + RtlCopyMemory (&PCIConfigHandler, + &PCIConfigHandlerType1, + sizeof (PCIConfigHandler)); + + BusData->MaxDevice = HalpPciMaxSlots; + break; + + case 2: + // + // Initialize access port information for Type2 handlers + // + + RtlCopyMemory (&PCIConfigHandler, + &PCIConfigHandlerType2, + sizeof (PCIConfigHandler)); +#if defined(UNION) + BusData->Config.Type2.Address = HalpPciConfigAddr[BusNo >> 8]; + BusData->Config.Type2.Data = HalpPciConfigData[BusNo >> 8]; +#else + BusData->Config.Type2.Address = (PUCHAR)HalpIoControlBase + 0xCF8; + BusData->Config.Type2.Data = (PUCHAR)HalpIoControlBase + 0xCFC; +#endif + // + // Early PCI machines didn't decode the last bit of + // the device id. Shrink type 2 support max device. + // + BusData->MaxDevice = HalpPciMaxSlots; + + break; + + default: + // unsupport type + DBGMSG ("HAL: Unkown PCI type\n"); + } + + if (!TestAllocation) { +#ifdef SUBCLASSPCI + HalpSubclassPCISupport (Bus, HwType); +#endif + } + + return Bus; +} + +BOOLEAN +HalpIsValidPCIDevice ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ) +/*++ + +Routine Description: + + Reads the device configuration data for the given slot and + returns TRUE if the configuration data appears to be valid for + a PCI device; otherwise returns FALSE. + +Arguments: + + BusHandler - Bus to check + Slot - Slot to check + +--*/ + +{ + PPCI_COMMON_CONFIG PciData; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + ULONG i, j; + + + PciData = (PPCI_COMMON_CONFIG) iBuffer; + + // + // Read device common header + // + + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Valid device header? + // + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + + return FALSE; + } + + // + // Check fields for reasonable values + // + + if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) || + (PciData->u.type0.InterruptLine & 0x70)) { + return FALSE; + } + + for (i=0; i < PCI_TYPE0_ADDRESSES; i++) { + j = PciData->u.type0.BaseAddresses[i]; + + if (j & PCI_ADDRESS_IO_SPACE) { + if (j > 0xffff) { + // IO port > 64k? + return FALSE; + } + } else { + if (j > 0xf && j < 0x80000) { + // Mem address < 0x8000h? + return FALSE; + } + } + + if (Is64BitBaseAddress(j)) { + i += 1; + } + } + + // + // Guess it's a valid device.. + // + + return TRUE; +} + + +ULONG +HalpGetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the Pci bus data for a device. + +Arguments: + + BusNumber - Indicates which bus. + + VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word) + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + + If this PCI slot has never been set, then the configuration information + returned is zeroed. + + +--*/ +{ + PPCI_COMMON_CONFIG PciData; + ULONG iBuffer[PCI_COMMON_HDR_LENGTH/sizeof(ULONG)]; + PPCIPBUSDATA BusData; + ULONG Len; + ULONG i, bit; + + if (Length > sizeof (PCI_COMMON_CONFIG)) { + Length = sizeof (PCI_COMMON_CONFIG); + } + + Len = 0; + PciData = (PPCI_COMMON_CONFIG) iBuffer; + + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The user did not request any data from the common + // header. Verify the PCI device exists, then continue + // in the device specific area. + // + + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG)); + + if (PciData->VendorID == PCI_INVALID_VENDORID) { + return 0; + } + + } else { + + // + // Caller requested at least some data within the + // common header. Read the whole header, effect the + // fields we need to and then copy the user's requested + // bytes from the header + // + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + // + // Read this PCI devices slot data + // + + Len = PCI_COMMON_HDR_LENGTH; + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len); + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + PciData->VendorID = PCI_INVALID_VENDORID; + Len = 2; // only return invalid id + + } else { + + BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData); + } + + // + // Copy whatever data overlaps into the callers buffer + // + + if (Len < Offset) { + // no data at caller's buffer + return 0; + } + + Len -= Offset; + if (Len > Length) { + Len = Length; + } + + RtlMoveMemory(Buffer, iBuffer + Offset, Len); + + Offset += Len; + Buffer += Len; + Length -= Len; + } + + if (Length) { + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The remaining Buffer comes from the Device Specific + // area - put on the kitten gloves and read from it. + // + // Specific read/writes to the PCI device specific area + // are guarenteed: + // + // Not to read/write any byte outside the area specified + // by the caller. (this may cause WORD or BYTE references + // to the area in order to read the non-dword aligned + // ends of the request) + // + // To use a WORD access if the requested length is exactly + // a WORD long. + // + // To use a BYTE access if the requested length is exactly + // a BYTE long. + // +//PLJTMP - no really, use kitten gloves! Until the wd90c24a driver is +// fixed to NOT go read beyond common space on EVERYBODY's chips, +// if this chip is an NCR 810, lie like a rug! + + + if ( iBuffer[0] == 0x00011000 ) { + // + // NCR 810 + // + while ( Len < Length ) { + *Buffer++ = 0xff; + Len++; + } + return Len; + } +//PLJTMPend + + HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length); + Len += Length; + } + } + + return Len; +} + +ULONG +HalpSetPCIData ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length + ) +/*++ + +Routine Description: + + The function returns the Pci bus data for a device. + +Arguments: + + + VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word) + + Buffer - Supplies the space to store the data. + + Length - Supplies a count in bytes of the maximum amount to return. + +Return Value: + + Returns the amount of data stored into the buffer. + +--*/ +{ + PPCI_COMMON_CONFIG PciData, PciData2; + UCHAR iBuffer[PCI_COMMON_HDR_LENGTH]; + UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH]; + PPCIPBUSDATA BusData; + ULONG Len, cnt; + + + if (Length > sizeof (PCI_COMMON_CONFIG)) { + Length = sizeof (PCI_COMMON_CONFIG); + } + + + Len = 0; + PciData = (PPCI_COMMON_CONFIG) iBuffer; + PciData2 = (PPCI_COMMON_CONFIG) iBuffer2; + + + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The user did not request any data from the common + // header. Verify the PCI device exists, then continue in + // the device specific area. + // + + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG)); + + if (PciData->VendorID == PCI_INVALID_VENDORID) { + return 0; + } + + } else { + + // + // Caller requested to set at least some data within the + // common header. + // + + Len = PCI_COMMON_HDR_LENGTH; + HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len); + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) { + + // no device, or header type unkown + return 0; + } + + + // + // Set this device as configured + // + + BusData = (PPCIPBUSDATA) BusHandler->BusData; +#if DBG + cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber); + RtlSetBits (&BusData->DeviceConfigured, cnt, 1); +#endif + // + // Copy COMMON_HDR values to buffer2, then overlay callers changes. + // + + RtlMoveMemory (iBuffer2, iBuffer, Len); + BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2); + + Len -= Offset; + if (Len > Length) { + Len = Length; + } + + RtlMoveMemory (iBuffer2+Offset, Buffer, Len); + + // in case interrupt line or pin was editted + BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData); + +#if DBG + // + // Verify R/O fields haven't changed + // + if (PciData2->VendorID != PciData->VendorID || + PciData2->DeviceID != PciData->DeviceID || + PciData2->RevisionID != PciData->RevisionID || + PciData2->ProgIf != PciData->ProgIf || + PciData2->SubClass != PciData->SubClass || + PciData2->BaseClass != PciData->BaseClass || + PciData2->HeaderType != PciData->HeaderType || + PciData2->BaseClass != PciData->BaseClass || + PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant || + PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) { + DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n"); +// DbgBreakPoint (); + } +#endif + // + // Set new PCI configuration + // + + HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len); + + Offset += Len; + Buffer += Len; + Length -= Len; + } + + if (Length) { + if (Offset >= PCI_COMMON_HDR_LENGTH) { + // + // The remaining Buffer comes from the Device Specific + // area - put on the kitten gloves and write it + // + // Specific read/writes to the PCI device specific area + // are guarenteed: + // + // Not to read/write any byte outside the area specified + // by the caller. (this may cause WORD or BYTE references + // to the area in order to read the non-dword aligned + // ends of the request) + // + // To use a WORD access if the requested length is exactly + // a WORD long. + // + // To use a BYTE access if the requested length is exactly + // a BYTE long. + // + + HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length); + Len += Length; + } + } + + return Len; +} + +VOID +HalpReadPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ + if (!HalpValidPCISlot (BusHandler, Slot)) { + // + // Invalid SlotID return no data + // + + RtlFillMemory (Buffer, Length, (UCHAR) -1); + return ; + } + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length, + PCIConfigHandler.ConfigRead); +} + +VOID +HalpWritePCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ) +{ + if (!HalpValidPCISlot (BusHandler, Slot)) { + // + // Invalid SlotID do nothing + // + return ; + } + + HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length, + PCIConfigHandler.ConfigWrite); +} + +BOOLEAN +HalpValidPCISlot ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot + ) +{ + PCI_SLOT_NUMBER Slot2; + PPCIPBUSDATA BusData; + UCHAR HeaderType; + ULONG i; + + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + if (Slot.u.bits.Reserved != 0) { + return FALSE; + } + + if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) { //IBMCPK: added = + return FALSE; + } + + if (Slot.u.bits.FunctionNumber == 0) { + return TRUE; + } + + // + // Sandalfoot doesn't support Multifunction adapters + // + +// return FALSE; + + // + // Non zero function numbers are only supported if the + // device has the PCI_MULTIFUNCTION bit set in it's header + // + + i = Slot.u.bits.DeviceNumber; + + // + // Read DeviceNumber, Function zero, to determine if the + // PCI supports multifunction devices + // + + Slot2 = Slot; + Slot2.u.bits.FunctionNumber = 0; + + HalpReadPCIConfig ( + BusHandler, + Slot2, + &HeaderType, + FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType), + sizeof (UCHAR) + ); + + if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) { + // this device doesn't exists or doesn't support MULTIFUNCTION types + return FALSE; + } + + return TRUE; +} + + +VOID +HalpPCIConfig ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length, + IN FncConfigIO *ConfigIO + ) +{ + KIRQL OldIrql; + ULONG i; + UCHAR State[20]; + PPCIPBUSDATA BusData; + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State); + + while (Length) { + i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)]; + i = ConfigIO[i] (BusData, State, Buffer, Offset); + + Offset += i; + Buffer += i; + Length -= i; + } + + PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql); +} + +VOID HalpPCISynchronizeType1 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PPCI_TYPE1_CFG_BITS PciCfg1 + ) +{ + // + // Initialize PciCfg1 + // + + PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.AsULONG); + + +} + +VOID HalpPCIReleaseSynchronzationType1 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ) +{ + + +} + + +ULONG +HalpPCIReadUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfg1->u.AsULONG + i)); + return sizeof (UCHAR); +} + +ULONG +HalpPCIReadUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT)(PciCfg1->u.AsULONG + i)); + return sizeof (USHORT); +} + +ULONG +HalpPCIReadUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfg1->u.AsULONG)); + return sizeof (ULONG); +} + + +ULONG +HalpPCIWriteUcharType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_UCHAR (PciCfg1->u.AsULONG + i, *Buffer ); + return sizeof (UCHAR); +} + +ULONG +HalpPCIWriteUshortType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_USHORT (PciCfg1->u.AsULONG + i, *((PUSHORT) Buffer) ); + return sizeof (USHORT); +} + +ULONG +HalpPCIWriteUlongType1 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG (PciCfg1->u.AsULONG, *((PULONG) Buffer) ); + return sizeof (ULONG); +} + +VOID HalpPCISynchronizeType2 ( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PPCI_TYPE1_CFG_BITS PciCfg1 + ) +{ + + // + // Initialize PciCfg1 + // + + PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.AsULONG); + + KeRaiseIrql (PROFILE_LEVEL, Irql); + KiAcquireSpinLock (&HalpPCIConfigLock); + + + +} + + +VOID HalpPCIReleaseSynchronzationType2 ( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql + ) +{ + + KiReleaseSpinLock (&HalpPCIConfigLock); + KeLowerIrql (Irql); + +} + + +ULONG +HalpPCIReadUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + union { + ULONG All; + UCHAR Bytes[4]; + } Tmp; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data); + *Buffer = Tmp.Bytes[i]; + +// WRITE_PORT_ULONG ((PUCHAR) HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG ); +// *((PUCHAR) Buffer) = READ_PORT_UCHAR ((PUCHAR) HalpIoControlBase + 0xCFC + i); + + return sizeof (UCHAR); +} + +ULONG +HalpPCIReadUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + union { + ULONG All; + UCHAR Bytes[4]; + } Tmp; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data); + *Buffer++ = Tmp.Bytes[i++]; + if ( i == sizeof(ULONG) ) { + PciCfg1->u.bits.RegisterNumber++; + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data); + i = 0; + } + *Buffer = Tmp.Bytes[i]; + +// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG ); +// *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUCHAR)HalpIoControlBase + 0xCFC + i); + + return sizeof (USHORT); +} + +ULONG +HalpPCIReadUlongType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + *((PULONG) Buffer) = READ_PORT_ULONG(BusData->Config.Type2.Data); + +// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG); +// *((PULONG) Buffer) = READ_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCFC); + + return sizeof(ULONG); +} + + +ULONG +HalpPCIWriteUcharType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + union { + ULONG All; + UCHAR Bytes[4]; + } Tmp; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data); + Tmp.Bytes[i] = *Buffer; + WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All); + +// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG ); +// WRITE_PORT_UCHAR ((PUCHAR)HalpIoControlBase + 0xCFC + i,*Buffer); + + return sizeof (UCHAR); +} + +ULONG +HalpPCIWriteUshortType2 ( + IN PPCIPBUSDATA BusData, + IN PPCI_TYPE1_CFG_BITS PciCfg1, + IN PUCHAR Buffer, + IN ULONG Offset + ) +{ + ULONG i; + union { + ULONG All; + UCHAR Bytes[4]; + } Tmp; + + i = Offset % sizeof(ULONG); + PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG); + + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data); + Tmp.Bytes[i++] = *Buffer++; + if ( i == sizeof(ULONG) ) { + WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All); + PciCfg1->u.bits.RegisterNumber++; + WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data); + i = 0; + } + Tmp.Bytes[i] = *Buffer; + WRITE_PORT_ULONG(BusData->Config.Type2.Data, Tmp.All); + +// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG ); +// WRITE_PORT_USHORT ((PUCHAR)HalpIoControlBase + 0xCFC + (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(BusData->Config.Type2.Address, PciCfg1->u.AsULONG); + WRITE_PORT_ULONG(BusData->Config.Type2.Data, *((PULONG)Buffer)); + +// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, PciCfg1->u.AsULONG); +// WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCFC,*((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; + } + + 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 + // + + // Clear ROM reserved bits + + *BaseAddress[RomIndex] &= ~0x7FF; + + for (j=0; j < NoBaseAddress; j++) { + if (*BaseAddress[j]) { + i = *BaseAddress[j]; + + // scan for first set bit, that's the length & alignment + length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4); + while (!(i & length) && length) { + length <<= 1; + } + + // scan for last set bit, that's the maxaddress + 1 + for (m = length; i & m; m <<= 1) ; + m--; + + // check for hosed PCI configuration requirements + if (length & ~m) { +#if DBG + DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n", + BusNumber, + PciSlot.u.bits.DeviceNumber, + PciSlot.u.bits.FunctionNumber + ); + + DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i); +#endif + // the device is in error - punt. don't allow this + // resource any option - it either gets set to whatever + // bits it was able to return, or it doesn't get set. + + if (i & PCI_ADDRESS_IO_SPACE) { + m = i & ~0x3; + Descriptor->u.Port.MinimumAddress.LowPart = m; + } else { + m = i & ~0xf; + Descriptor->u.Memory.MinimumAddress.LowPart = m; + } + + m += length; // max address is min address + length + } + + // + // Add requested resource + // + + Descriptor->Option = 0; + if (i & PCI_ADDRESS_IO_SPACE) { + memtype = 0; + + if (!Is64BitBaseAddress(i) && + PciOrigData->Command & PCI_ENABLE_IO_SPACE) { + + // + // The IO range is/was already enabled at some location, add that + // as it's preferred setting. + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + Descriptor->Option = IO_RESOURCE_PREFERRED; + + Descriptor->u.Port.Length = length; + Descriptor->u.Port.Alignment = length; + Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3; + Descriptor->u.Port.MaximumAddress.LowPart = + Descriptor->u.Port.MinimumAddress.LowPart + length - 1; //IBMCPK:added -1 + + CompleteList->List[0].Count++; + Descriptor++; + + Descriptor->Option = IO_RESOURCE_ALTERNATIVE; + } + + // + // Add this IO range + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + + Descriptor->u.Port.Length = length; + Descriptor->u.Port.Alignment = length; + Descriptor->u.Port.MaximumAddress.LowPart = m; + + } else { + + memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK; + + Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; + if (j == RomIndex) { + // this is a ROM address + Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY; + } + + if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) { + Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE; + } + + if (!Is64BitBaseAddress(i) && + (j == RomIndex || + PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) { + + // + // The memory range is/was already enabled at some location, add that + // as it's preferred setting. + // + + Descriptor->Type = CmResourceTypeMemory; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Option = IO_RESOURCE_PREFERRED; + + Descriptor->u.Port.Length = length; + Descriptor->u.Port.Alignment = length; + Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF; + Descriptor->u.Port.MaximumAddress.LowPart = + Descriptor->u.Port.MinimumAddress.LowPart + length - 1; //IBMCPK: added -1 + + CompleteList->List[0].Count++; + Descriptor++; + + Descriptor->Flags = Descriptor[-1].Flags; + Descriptor->Option = IO_RESOURCE_ALTERNATIVE; + } + + // + // Add this memory range + // + + Descriptor->Type = CmResourceTypeMemory; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + + Descriptor->u.Memory.Length = length; + Descriptor->u.Memory.Alignment = length; + Descriptor->u.Memory.MaximumAddress.LowPart = m; + + if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) { + // limit to 20 bit address + Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF; + } + } + + CompleteList->List[0].Count++; + Descriptor++; + + + if (Is64BitBaseAddress(i)) { + // skip upper half of 64 bit address since this processor + // only supports 32 bits of address space + j++; + } + } + } + + CompleteList->ListSize = (ULONG) + ((PUCHAR) Descriptor - (PUCHAR) CompleteList); + + // + // Restore the device settings as we found them, enable memory + // and io decode after setting base addresses. This is done in + // case HalAdjustResourceList wants to read the current settings + // in the device. + // + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + &PciOrigData->Status, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status), + PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + PciOrigData, + 0, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + // + // Have the IO system allocate resource assignments + // + + status = IoAssignResources ( + RegistryPath, + DriverClassName, + DriverObject, + DeviceObject, + CompleteList, + pAllocatedResources + ); + + if (!NT_SUCCESS(status)) { + goto CleanUp; + } + + // + // Slurp the assigments back into the PciData structure and + // perform them + // + + CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors; + + // + // If PCI device has an interrupt resource then that was + // passed in as the first requested resource + // + + if (PciData->u.type0.InterruptPin) { + PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector; + BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData); + CmDescriptor++; + } + + // + // Pull out resources in the order they were passed to IoAssignResources + // + + for (j=0; j < NoBaseAddress; j++) { + i = *BaseAddress[j]; + if (i) { + if (i & PCI_ADDRESS_IO_SPACE) { + *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart; + } else { + *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart; + } + CmDescriptor++; + } + + if (Is64BitBaseAddress(i)) { + // skip upper 32 bits + j++; + } + } + + // + // Turn off decodes, then set new addresses + // + + HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); + + // + // Read configuration back and verify address settings took + // + + HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH); + + Match = TRUE; + if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine || + PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin || + PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) { + Match = FALSE; + } + + for (j=0; j < NoBaseAddress; j++) { + if (*BaseAddress[j]) { + if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) { + i = (ULONG) ~0x3; + } else { + i = (ULONG) ~0xF; + } + + if ((*BaseAddress[j] & i) != + *((PULONG) ((PUCHAR) BaseAddress[j] - + (PUCHAR) PciData + + (PUCHAR) PciData2)) & i) { + + Match = FALSE; + } + + if (Is64BitBaseAddress(*BaseAddress[j])) { + // skip upper 32 bits + j++; + } + } + } + + if (!Match) { +#if DBG + DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n", + BusNumber, + PciSlot.u.bits.DeviceNumber, + PciSlot.u.bits.FunctionNumber + ); +#endif + status = STATUS_DEVICE_PROTOCOL_ERROR; + goto CleanUp; + } + + // + // Settings took - turn on the appropiate decodes + // + + if (EnableRomBase && *BaseAddress[RomIndex]) { + // a rom address was allocated and should be enabled + *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED; + HalpWritePCIConfig ( + BusHandler, + PciSlot, + BaseAddress[RomIndex], + (ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData), + sizeof (ULONG) + ); + } + + // + // Enable IO, Memory, and BUS_MASTER decodes + // (use HalSetBusData since valid settings now set) + // + // But don't change video devices, they will be enabled or + // disabled by HalpInitializeDisplay() + // + // (For the moment, that means we are shutting off the + // S3 chip so that a plug-in Weitek card can get a chance + // to talk to GDI. + + if (!(IsVideoDevice(PciData))) { + + PciData->Command |= PCI_ENABLE_IO_SPACE | + PCI_ENABLE_MEMORY_SPACE | + PCI_ENABLE_BUS_MASTER; + } else { + + PciData->Command = PciOrigData->Command; + } + + HalSetBusDataByOffset ( + PCIConfiguration, + BusHandler->BusNumber, + PciSlot.u.AsULONG, + &PciData->Command, + FIELD_OFFSET (PCI_COMMON_CONFIG, Command), + sizeof (PciData->Command) + ); + +CleanUp: + if (!NT_SUCCESS(status)) { + + // + // Failure, if there are any allocated resources free them + // + + if (*pAllocatedResources) { + IoAssignResources ( + RegistryPath, + DriverClassName, + DriverObject, + DeviceObject, + NULL, + NULL + ); + + ExFreePool (*pAllocatedResources); + *pAllocatedResources = NULL; + } + + // + // Restore the device settings as we found them, enable memory + // and io decode after setting base addresses + // + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + &PciOrigData->Status, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status), + PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + + HalpWritePCIConfig ( + BusHandler, + PciSlot, + PciOrigData, + 0, + FIELD_OFFSET (PCI_COMMON_CONFIG, Status) + ); + } + + ExFreePool (WorkingPool); + return status; +} + +VOID +HalpPhase0DiscoverPciBuses( + IN PCONFIGURATION_COMPONENT_DATA Component + ) +/* + This function looks down the LoaderBlock looking for nodes that + correspond to PCI buses. When it has found them all, it sets + HalpPciMaxBuses. +*/ +{ + // Check to see if this component would look like a "multi(x)" + // entry in ARC. + if ((Component->ComponentEntry.Class == AdapterClass) && + (Component->ComponentEntry.Type == MultiFunctionAdapter)) { + + // + // First check to see if Identifier is valid, then + // check the string it points to. + // + if (Component->ComponentEntry.Identifier) { + + if ((Component->ComponentEntry.Identifier[0] == 'P') && + (Component->ComponentEntry.Identifier[1] == 'C') && + (Component->ComponentEntry.Identifier[2] == 'I')) { + + HalpPciMaxBuses++; // Increment the number of PCI buses + + } + } + } + + // + // Look at the Siblings of this component + // + if (Component->Sibling) { + HalpPhase0DiscoverPciBuses(Component->Sibling); + } + + // + // Look at the Children of this component + // + if (Component->Child) { + HalpPhase0DiscoverPciBuses(Component->Child); + } + + +} + + +#if DBG +VOID +HalpTestPci (ULONG flag2) +{ + PCI_SLOT_NUMBER SlotNumber; + PCI_COMMON_CONFIG PciData, OrigData; + ULONG i, f, j, k, bus; + BOOLEAN flag; + + + if (!flag2) { + return ; + } + + DbgBreakPoint (); + SlotNumber.u.bits.Reserved = 0; + + // + // Read every possible PCI Device/Function and display it's + // default info. + // + // (note this destories it's current settings) + // + + flag = TRUE; + for (bus = 0; flag; bus++) { + + for (i = 0; i < PCI_MAX_DEVICES; i++) { + SlotNumber.u.bits.DeviceNumber = i; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + SlotNumber.u.bits.FunctionNumber = f; + + // + // Note: This is reading the DeviceSpecific area of + // the device's configuration - normally this should + // only be done on device for which the caller understands. + // I'm doing it here only for debugging. + // + + j = HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + if (j == 0) { + // out of buses + flag = FALSE; + break; + } + + if (j < PCI_COMMON_HDR_LENGTH) { + continue; + } + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + 1 + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + memcpy (&OrigData, &PciData, sizeof PciData); + + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF; + } + + PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF; + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx", + bus, i, f, PciData.VendorID, PciData.DeviceID, + PciData.RevisionID); + + + if (PciData.u.type0.InterruptPin) { + DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin); + } + + if (PciData.u.type0.InterruptLine) { + DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine); + } + + if (PciData.u.type0.ROMBaseAddress) { + DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n", + PciData.Command, PciData.Status, PciData.ProgIf, + PciData.SubClass, PciData.BaseClass); + + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (PciData.u.type0.BaseAddresses[j]) { + DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]); + k = 1; + } + } + + if (PciData.u.type0.ROMBaseAddress == 0xC08001) { + + PciData.u.type0.ROMBaseAddress = 0xC00001; + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + HalGetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &PciData, + sizeof (PciData) + ); + + DbgPrint ("\n Bogus rom address, edit yields:%08lx", + PciData.u.type0.ROMBaseAddress); + } + + if (k) { + DbgPrint ("\n"); + } + + if (PciData.VendorID == 0x8086) { + // dump complete buffer + DbgPrint ("Command %x, Status %x, BIST %x\n", + PciData.Command, PciData.Status, + PciData.BIST + ); + + DbgPrint ("CacheLineSz %x, LatencyTimer %x", + PciData.CacheLineSize, PciData.LatencyTimer + ); + + for (j=0; j < 192; j++) { + if ((j & 0xf) == 0) { + DbgPrint ("\n%02x: ", j + 0x40); + } + DbgPrint ("%02x ", PciData.DeviceSpecific[j]); + } + DbgPrint ("\n"); + } + + + // + // now print original data + // + + if (OrigData.u.type0.ROMBaseAddress) { + DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress); + } + + DbgPrint ("\n"); + k = 0; + for (j=0; j < PCI_TYPE0_ADDRESSES; j++) { + if (OrigData.u.type0.BaseAddresses[j]) { + DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]); + k = 1; + } + } + + // + // Restore original settings + // + + HalSetBusData ( + PCIConfiguration, + bus, + SlotNumber.u.AsULONG, + &OrigData, + sizeof (PciData) + ); + + // + // Next + // + + if (k) { + DbgPrint ("\n\n"); + } + } + } + } + DbgBreakPoint (); +} +#endif diff --git a/private/ntos/nthals/halwood/ppc/pxpciint.c b/private/ntos/nthals/halwood/ppc/pxpciint.c new file mode 100644 index 000000000..089386edd --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxpciint.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxpciint.c> diff --git a/private/ntos/nthals/halwood/ppc/pxpcisup.c b/private/ntos/nthals/halwood/ppc/pxpcisup.c new file mode 100644 index 000000000..0da9534bb --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxpcisup.c @@ -0,0 +1,259 @@ +/*++ + +Copyright (c) 1996 Microsoft Corporation +Copyright (c) 1996 IBM Corporation + +Module Name: + + pxpcisup.c + +Abstract: + + This module contains machine specific PCI routines. + +Author: + + Jim Wooldridge (jimw@austin.vnet.ibm.com) + + +Revision History: + + + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" + +extern PVOID HalpPciConfigBase; +#define PCI_INTERRUPT_ROUTING_SCSI 13 +#define PCI_INTERRUPT_ROUTING_OTHER 15 + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE,HalpGetPCIIrq) +#endif + +ULONG HalpPciMaxSlots = PCI_MAX_DEVICES; + +ULONG +HalpTranslatePciSlotNumber ( + ULONG BusNumber, + ULONG SlotNumber + ) +/*++ + +Routine Description: + + This routine translate a PCI slot number to a PCI device number. + +Arguments: + + None. + +Return Value: + + Returns length of data written. + +--*/ + +{ + // + // Sandalfoot only has 1 PCI bus so bus number is unused + // + + PCI_TYPE1_CFG_BITS PciConfig; + PCI_SLOT_NUMBER PciSlotNumber; + + PciSlotNumber.u.AsULONG = SlotNumber; + + PciConfig.u.AsULONG = 0; + PciConfig.u.bits.DeviceNumber = PciSlotNumber.u.bits.DeviceNumber; + PciConfig.u.bits.FunctionNumber = PciSlotNumber.u.bits.FunctionNumber; + PciConfig.u.bits.BusNumber = BusNumber; + PciConfig.u.bits.Enable = TRUE; + + return (PciConfig.u.AsULONG); +} + +ULONG +HalpPhase0SetPciDataByOffset ( + ULONG BusNumber, + ULONG SlotNumber, + PUCHAR Buffer, + ULONG Offset, + ULONG Length + ) + +/*++ + +Routine Description: + + This routine writes to PCI configuration space prior to bus handler installation. + +Arguments: + + None. + +Return Value: + + Returns length of data written. + +--*/ + +{ + ULONG to; + PUCHAR from; + ULONG tmpLength; + ULONG i; + + if (SlotNumber < HalpPciMaxSlots) { + + to = HalpTranslatePciSlotNumber(BusNumber, SlotNumber); + to += Offset; + from = Buffer; + tmpLength = Length; + while (tmpLength > 0) { + WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, to ); + i = to % sizeof(ULONG); + WRITE_PORT_UCHAR ((PUCHAR)HalpIoControlBase + 0xCFC + i,*from); + to++; + from++; + tmpLength--; + } + return(Length); + } + else { + return (0); + } +} + +ULONG +HalpPhase0GetPciDataByOffset ( + ULONG BusNumber, + ULONG SlotNumber, + PUCHAR Buffer, + ULONG Offset, + ULONG Length + ) + +/*++ + +Routine Description: + + This routine reads PCI config space prior to bus handlder installation. + +Arguments: + + None. + +Return Value: + + Amount of data read. + +--*/ + +{ + PUCHAR to; + ULONG from; + ULONG tmpLength; + ULONG i; + + + if (SlotNumber < HalpPciMaxSlots) { + + + from = HalpTranslatePciSlotNumber(BusNumber, SlotNumber); + from += Offset; + to = Buffer; + tmpLength = Length; + while (tmpLength > 0) { + + WRITE_PORT_ULONG ((PUCHAR)HalpIoControlBase + 0xCF8, from); + i = from % sizeof(ULONG); + *((PUCHAR) to) = READ_PORT_UCHAR ((PUCHAR)HalpIoControlBase + 0xCFC + i); + to++; + from++; + tmpLength--; + } + return(Length); + } + else { + return (0); + } +} + +NTSTATUS +HalpGetPCIIrq ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER PciSlot, + OUT PSUPPORTED_RANGE *Interrupt + ) +{ + UCHAR buffer[PCI_COMMON_HDR_LENGTH]; + PPCI_COMMON_CONFIG PciData; + + PciData = (PPCI_COMMON_CONFIG)buffer; + HalGetBusData( + PCIConfiguration, + BusHandler->BusNumber, + PciSlot.u.AsULONG, + PciData, + PCI_COMMON_HDR_LENGTH + ); + + if (PciData->VendorID == PCI_INVALID_VENDORID || + PCI_CONFIG_TYPE (PciData) != 0) { + return STATUS_UNSUCCESSFUL; + } + + *Interrupt = ExAllocatePool(PagedPool, sizeof(SUPPORTED_RANGE)); + if (!*Interrupt) { + return STATUS_INSUFFICIENT_RESOURCES; + } + + RtlZeroMemory(*Interrupt, sizeof (SUPPORTED_RANGE)); + + if ( (PciData->VendorID == 0x1000) && // NCR + ( (PciData->DeviceID == 0x0001) || // 810 or 825 + (PciData->DeviceID == 0x0003) ) ) { + (*Interrupt)->Base = PCI_INTERRUPT_ROUTING_SCSI; + (*Interrupt)->Limit = PCI_INTERRUPT_ROUTING_SCSI; + } else { + (*Interrupt)->Base = PCI_INTERRUPT_ROUTING_OTHER; + (*Interrupt)->Limit = PCI_INTERRUPT_ROUTING_OTHER; + } + + return STATUS_SUCCESS; +} + +VOID +HalpMapPlugInPciBridges( + UCHAR NoBuses + ) + +/*++ + +Routine Description: + + Looks for any unexpected (plug-in) PCI-PCI bridges so + that interrupts can be mapped from these buses back + into the interrupt controller. + +Arguments: + + NoBuses -- This is the number of buses that HalpGetPciBridgeConfig found + +Return Value: + + none + +--*/ +{ + // Woodfield doesn't support plug-in PCI busses!!! + + return; +} + + diff --git a/private/ntos/nthals/halwood/ppc/pxport.c b/private/ntos/nthals/halwood/ppc/pxport.c new file mode 100644 index 000000000..19c0841dc --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxport.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxport.c> diff --git a/private/ntos/nthals/halwood/ppc/pxpower.s b/private/ntos/nthals/halwood/ppc/pxpower.s new file mode 100644 index 000000000..39dc14e06 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxpower.s @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxpower.s> diff --git a/private/ntos/nthals/halwood/ppc/pxproc.c b/private/ntos/nthals/halwood/ppc/pxproc.c new file mode 100644 index 000000000..5a8ee0570 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxproc.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxproc.c> diff --git a/private/ntos/nthals/halwood/ppc/pxprof.c b/private/ntos/nthals/halwood/ppc/pxprof.c new file mode 100644 index 000000000..5e9e3dc20 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxprof.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxprof.c> diff --git a/private/ntos/nthals/halwood/ppc/pxreset.s b/private/ntos/nthals/halwood/ppc/pxreset.s new file mode 100644 index 000000000..5aca035e2 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxreset.s @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxreset.s> diff --git a/private/ntos/nthals/halwood/ppc/pxreturn.c b/private/ntos/nthals/halwood/ppc/pxreturn.c new file mode 100644 index 000000000..f205f2c6b --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxreturn.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxreturn.c> diff --git a/private/ntos/nthals/halwood/ppc/pxs3.c b/private/ntos/nthals/halwood/ppc/pxs3.c new file mode 100644 index 000000000..0b7211142 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxs3.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxs3.c" + diff --git a/private/ntos/nthals/halwood/ppc/pxshadbf.s b/private/ntos/nthals/halwood/ppc/pxshadbf.s new file mode 100644 index 000000000..d637a3763 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxshadbf.s @@ -0,0 +1,2 @@ +#include <..\..\halppc\ppc\pxshadbf.s> + diff --git a/private/ntos/nthals/halwood/ppc/pxsiosup.c b/private/ntos/nthals/halwood/ppc/pxsiosup.c new file mode 100644 index 000000000..1768ca5ad --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxsiosup.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxsiosup.c> diff --git a/private/ntos/nthals/halwood/ppc/pxstall.s b/private/ntos/nthals/halwood/ppc/pxstall.s new file mode 100644 index 000000000..50d947500 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxstall.s @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxstall.s> diff --git a/private/ntos/nthals/halwood/ppc/pxsysbus.c b/private/ntos/nthals/halwood/ppc/pxsysbus.c new file mode 100644 index 000000000..038371625 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxsysbus.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxsysbus.c> diff --git a/private/ntos/nthals/halwood/ppc/pxsysint.c b/private/ntos/nthals/halwood/ppc/pxsysint.c new file mode 100644 index 000000000..ac1891797 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxsysint.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxsysint.c> diff --git a/private/ntos/nthals/halwood/ppc/pxtime.c b/private/ntos/nthals/halwood/ppc/pxtime.c new file mode 100644 index 000000000..5fe5a500a --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxtime.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxtime.c> diff --git a/private/ntos/nthals/halwood/ppc/pxusage.c b/private/ntos/nthals/halwood/ppc/pxusage.c new file mode 100644 index 000000000..3be115176 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxusage.c @@ -0,0 +1 @@ +#include <..\..\halppc\ppc\pxusage.c> diff --git a/private/ntos/nthals/halwood/ppc/pxwd.c b/private/ntos/nthals/halwood/ppc/pxwd.c new file mode 100644 index 000000000..bcfc1f5e9 --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/pxwd.c @@ -0,0 +1,2 @@ +#include "..\..\halppc\ppc\pxwd.c" + diff --git a/private/ntos/nthals/halwood/ppc/wdvga.c b/private/ntos/nthals/halwood/ppc/wdvga.c new file mode 100644 index 000000000..89d330fcf --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/wdvga.c @@ -0,0 +1,745 @@ +/****************************************************************************** + +Copyright (c) 1994 IBM Corporaion + +wdvga.c + + This module is a modification of the HAL display initialization and output + routines for IBM Woodfield WD90C24A Graphics system. This version of wdvga.c + is intended to be used by the OS loader to provide putc capabilities with + the WD card. + + This file was created by copying s3vga.c and modifying it to remove + everything except the code that initializes the VGA common registers. + +Author: + + Hiroshi Itoh 25-Feb-1994 + +Revision History: + + +******************************************************************************/ +#define USE_VGA_PALETTE 1 + +# include "halp.h" +# include "pvgaequ.h" +# include "wdvga.h" + +/*****************************************************************************/ + +// +++++++ IBM BJB added PCI bus definitions and tab size definition + +// PCI slot configuration space addresses + +# define UPPER_PCI_SLOT 0x80804000L +# define LOWER_PCI_SLOT 0x80802000L +# define PCI_BASE UPPER_PCI_SLOT + +// PCI configuration space record offsets + +# define VENDOR_ID 0x00 +# define DEVICE_ID 0x02 +# define COMMAND 0X04 +# define DEVICE_STATUS 0X06 +# define REVISION_ID 0x08 +# define PROG_INTERFACE 0x0a +# define BASE_MEM_ADDRESS 0x10 + +# define TAB_SIZE 4 + +/*****************************************************************************/ +// +// Define forward referenced procedure prototypes. +// + +VOID +InitializeWD ( + VOID + ); + +BOOLEAN WDIsPresent ( + VOID + ); + +VOID +SetWDVGAConfig ( + VOID + ); + +VOID +LockPR ( + USHORT, + PUCHAR + ); + +VOID +UnlockPR ( + USHORT, + PUCHAR + ); + +VOID +RestorePR ( + USHORT, + PUCHAR + ); + +// +// Define paradise registers setting variation +// + +#define pr72_alt (pr72 | 0x8000) // avoid pr30 index conflict +#define pr1b_ual (pr1b) // pr1b unlock variation +#define pr1b_ush (pr1b | 0x4000) // pr1b unlock variation +#define pr1b_upr (pr1b | 0x8000) // pr1b unlock variation + +// +// Define static data (in s3vga.c) +// + +extern +ULONG + Row, + Column, + ScrollLine, + DisplayText; + +/****************************************************************************** + + This routine initializes the WD display controller chip. + + This is the initialization routine for WD90C24A2. This routine initializes + the WD90C24A2 chip in the sequence of VGA BIOS. + +******************************************************************************/ + +VOID +InitializeWD( VOID ) + + { + + ULONG DataLong; + USHORT i, j; + UCHAR DataByte; + UCHAR Index; + PVOID Index_3x4, Data_3x5; + ULONG MemBase; + + + // these lines were moved to here from the original jxdisp.c + // routine that called this one + // + // In the HAL, we just put the video card into text mode. + + DisplayText = 25; + ScrollLine = 160; + + // Enable Video Subsystem according to the WD90C24 reference book + + WRITE_WD_UCHAR( SUBSYS_ENB, 0x16 ); + WRITE_WD_UCHAR( Setup_OP, 0x01 ); + WRITE_WD_UCHAR( SUBSYS_ENB, 0x0e ); + + WRITE_WD_UCHAR( VSub_EnB, VideoParam[0] ); + + SetWDVGAConfig(); + + // Note: Synchronous reset must be done before MISC_OUT write operation + + WRITE_WD_UCHAR( Seq_Index, RESET ); // Synchronous Reset ! + WRITE_WD_UCHAR( Seq_Data, 0x01 ); + + // For ATI card (0x63) we may want to change the frequence + + WRITE_WD_UCHAR( MiscOutW, VideoParam[1] ); + + // Note: Synchronous reset must be done before CLOCKING MODE register is + // modified + + WRITE_WD_UCHAR( Seq_Index, RESET ); // Synchronous Reset ! + WRITE_WD_UCHAR( Seq_Data, 0x01 ); + + // Sequencer Register + + for( Index = 1; Index < 5; Index++ ) + { + WRITE_WD_UCHAR( Seq_Index, Index ); + WRITE_WD_UCHAR( Seq_Data, VideoParam[SEQ_OFFSET + Index] ); + } + + // Set CRT Controller + // out 3D4, 0x11, 00 (bit 7 must be 0 to unprotect CRT R0-R7) + // UnLockCR0_7(); + + WRITE_WD_UCHAR( WD_3D4_Index, VERTICAL_RETRACE_END ); + + DataByte = READ_WD_UCHAR( WD_3D5_Data ); + DataByte = DataByte & 0x7f; + WRITE_WD_UCHAR( WD_3D5_Data, DataByte ); + + // CRTC controller CR0 - CR18 + + for( Index = 0; Index < 25; Index++ ) + { + WRITE_WD_UCHAR( WD_3D4_Index, Index ); + WRITE_WD_UCHAR( WD_3D5_Data, VideoParam[CRT_OFFSET + Index] ); + } + + // attribute write + // program palettes and mode register + + for( Index = 0; Index < 21; Index++ ) + { + WaitForVSync(); + DataByte = READ_WD_UCHAR( Stat1_In ); // Initialize Attr. F/F + WRITE_WD_UCHAR( Attr_Index, Index ); + +// KeStallExecutionProcessor( 5 ); + WRITE_WD_UCHAR( Attr_Data, VideoParam[ATTR_OFFSET + Index] ); + +// KeStallExecutionProcessor( 5 ); + WRITE_WD_UCHAR( Attr_Index, 0x20 ); // Set into normal operation + } + + WRITE_WD_UCHAR( Seq_Index, RESET ); // reset to normal operation ! + WRITE_WD_UCHAR( Seq_Data, 0x03 ); + + // graphics controller + + for( Index = 0; Index < 9; Index++ ) + { + WRITE_WD_UCHAR( GC_Index, Index ); + WRITE_WD_UCHAR( GC_Data, VideoParam[GRAPH_OFFSET + Index] ); + } + // turn off the text mode cursor + + WRITE_WD_UCHAR( WD_3D4_Index, CURSOR_START ); + WRITE_WD_UCHAR( WD_3D5_Data, 0x2D ); + + // Load character fonts into plane 2 (A0000-AFFFF) + + WRITE_WD_UCHAR( Seq_Index, 0x02 ); // Enable Write Plane reg + WRITE_WD_UCHAR( Seq_Data, 0x04 ); // select plane 2 + + WRITE_WD_UCHAR( Seq_Index, 0x04 ); // Memory Mode Control reg + WRITE_WD_UCHAR( Seq_Data, 0x06 ); // access to all planes, + + WRITE_WD_UCHAR( GC_Index, 0x05 ); // Graphic, Control Mode reg + WRITE_WD_UCHAR( GC_Data, 0x00 ); + + WRITE_WD_UCHAR( GC_Index, 0x06 ); + WRITE_WD_UCHAR( GC_Data, 0x04 ); + + WRITE_WD_UCHAR( GC_Index, 0x04 ); + WRITE_WD_UCHAR( GC_Data, 0x02 ); + + MemBase = 0xA0000; // Font Plane 2 + + for( i = 0; i < 256; i++ ) + { + for( j = 0; j < 16; j++ ) + { + WRITE_WD_VRAM( MemBase, VGAFont8x16[i * 16 + j] ); + MemBase++; + } + + // 32 bytes each character font + + for( j = 16; j < 32; j++ ) + { + WRITE_WD_VRAM( MemBase, 0 ); + MemBase++; + } + } + + // turn on screen + WRITE_WD_UCHAR( Seq_Index, 0x01 ); + DataByte = READ_WD_UCHAR( Seq_Data ); + DataByte &= 0xdf; + DataByte ^= 0x0; + WRITE_WD_UCHAR( Seq_Data, DataByte ); + + WaitForVSync(); + + // Enable all the planes through the DAC + WRITE_WD_UCHAR( DAC_Mask, 0xff ); + + for( i = 0; i < 768; i++ ) + { + WRITE_WD_UCHAR( DAC_Data, ColorPalette[i] ); + } + + // + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + // select plane 0, 1 + WRITE_WD_UCHAR( Seq_Index, 0x02); // Enable Write Plane reg + WRITE_WD_UCHAR( Seq_Data, VideoParam[SEQ_OFFSET + 0x02] ); + + // access to planes 0, 1. + WRITE_WD_UCHAR( Seq_Index, 0x04); // Memory Mode Control reg + WRITE_WD_UCHAR( Seq_Data, VideoParam[SEQ_OFFSET+0x04]); + + WRITE_WD_UCHAR( GC_Index, 0x05 ); // Graphic, Control Mode reg + WRITE_WD_UCHAR( GC_Data, VideoParam[GRAPH_OFFSET + 0x05] ); + + WRITE_WD_UCHAR( GC_Index, 0x04); + WRITE_WD_UCHAR( GC_Data, VideoParam[GRAPH_OFFSET + 0x04] ); + + WRITE_WD_UCHAR( GC_Index, 0x06); + WRITE_WD_UCHAR( GC_Data, VideoParam[GRAPH_OFFSET + 0x06] ); + + // + // Set screen into blue + // + + for( DataLong = 0xB8000; DataLong < 0xB8FA0; DataLong += 2 ) + { + WRITE_WD_VRAM( DataLong, 0x20 ); +#ifdef USE_VGA_PALETTE + WRITE_WD_VRAM( DataLong + 1, 0x07 ); +#else + WRITE_WD_VRAM( DataLong + 1, 0x1F ); +#endif + } + + // End of initialize S3 standard VGA +3 mode + + // + // Initialize the current display column, row, and ownership values. + // + + Column = 0; + Row = 0; + + return; + + } /* end of InitializeWD() */ + + +VOID +SetWDVGAConfig ( + VOID + ) + +/*++ + +Routine Description: + + Set WDVGA compatible configuration except DAC. + +Arguments: + + None. + +Return Value: + + None. + +--*/ + +{ + UCHAR SavePR5, SavePR10, SavePR11, SavePR20, SavePR72, Temp; + PUCHAR pPRtable; + + LockPR( pr1b, NULL ); + LockPR( pr30, NULL ); + + UnlockPR( pr20, NULL ); + UnlockPR( pr10, &SavePR10 ); + UnlockPR( pr11, &SavePR11 ); + +// non-ISO monitor setting clock + + WRITE_WD_UCHAR( Seq_Index, CLOCKING_MODE ); + Temp = READ_WD_UCHAR( Seq_Data ); + WRITE_WD_UCHAR( Seq_Data, (Temp | 0x01)); + + Temp = READ_WD_UCHAR( MiscOutR ); + WRITE_WD_UCHAR( MiscOutW, (Temp & 0xf3)); + +// other clocking chip selects + UnlockPR( pr72_alt, &SavePR72 ); + + WRITE_WD_UCHAR( Seq_Index, pr68 ); + Temp = READ_WD_UCHAR( Seq_Data ); + WRITE_WD_UCHAR( Seq_Data, ((Temp & 0xe7) | 0x08)); + + RestorePR( pr72_alt, &SavePR72 ); + + RestorePR( pr11, &SavePR11 ); + RestorePR( pr10, &SavePR10 ); + LockPR( pr20, NULL ); + +// start of WD90C24A2 both screen mode table + + pPRtable = wd90c24a_both; + while (*pPRtable != END_PVGA) { + switch (*pPRtable++) { + case W_CRTC : + WRITE_WD_UCHAR( WD_3D4_Index, *pPRtable++ ); + WRITE_WD_UCHAR( WD_3D5_Data, *pPRtable++ ); + break; + case W_SEQ : + WRITE_WD_UCHAR( Seq_Index, *pPRtable++ ); + WRITE_WD_UCHAR( Seq_Data, *pPRtable++ ); + break; + case W_GCR : + WRITE_WD_UCHAR( GC_Index, *pPRtable++ ); + WRITE_WD_UCHAR( GC_Data, *pPRtable++ ); + break; + default : + break; + } + } + + // unlock FLAT registers + + UnlockPR( pr1b_ual, NULL ); + + WRITE_WD_UCHAR( WD_3D4_Index, pr19 ); + WRITE_WD_UCHAR( WD_3D5_Data, ((pr19_s32 & 0xf3) | pr19_CENTER)); + + // lock FLAT registers + + LockPR( pr1b, NULL ); + +#ifndef USE_VGA_PALETTE + // PR1/PR4 setting + + UnlockPR( pr5, &SavePR5 ); + + WRITE_WD_UCHAR( GCR_Index, pr1 ); + Temp = READ_WD_UCHAR( GCR_Data ); + WRITE_WD_UCHAR( GCR_Data, (Temp | 0x30)); + WRITE_WD_UCHAR( GCR_Index, pr4 ); + Temp = READ_WD_UCHAR( GCR_Data ); + WRITE_WD_UCHAR( GCR_Data, (Temp | 0x01)); + + RestorePR( pr5, &SavePR5 ); + + // PR16 setting + + UnlockPR( pr10, &SavePR10 ); + + WRITE_WD_UCHAR( WD_3D4_Index, pr16 ); + WRITE_WD_UCHAR( WD_3D5_Data, 0); + + RestorePR( pr10, &SavePR10 ); + + // PR34a setting + + UnlockPR( pr20, &SavePR20 ); + + WRITE_WD_UCHAR( Seq_Index, pr34a ); + WRITE_WD_UCHAR( Seq_Data, 0x0f); + + RestorePR( pr20, &SavePR20 ); +#endif + + +} /* SetWDVGAConfig */ + + +// +// Internal functions +// + +VOID +LockPR ( + USHORT PRnum, + PUCHAR pPRval + ) +{ + USHORT pIndex, pData; + UCHAR Index, Data; + switch (PRnum) { + case pr5: + pIndex = GC_Index; + pData = GC_Data; + Index = pr5; + Data = pr5_lock; + break; + case pr10: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr10; + Data = pr10_lock; + break; + case pr11: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr11; + Data = pr11_lock; + break; + case pr1b: +// case pr1b_ual: +// case pr1b_ush: +// case pr1b_upr: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr1b; + Data = pr1b_lock; + break; + case pr20: + pIndex = Seq_Index; + pData = Seq_Data; + Index = pr20; + Data = pr20_lock; + break; + case pr30: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr30; + Data = pr30_lock; + break; + case pr72_alt: + pIndex = Seq_Index; + pData = Seq_Data; + Index = pr72; + Data = pr72_lock; + break; + default: + return; + } /* endswitch */ + + WRITE_WD_UCHAR( pIndex, Index ); + if (pPRval!=NULL) { + *pPRval = READ_WD_UCHAR( pData ); + } /* endif */ + WRITE_WD_UCHAR( pData, Data ); +} + +VOID +UnlockPR ( + USHORT PRnum, + PUCHAR pPRval + ) +{ + USHORT pIndex, pData; + UCHAR Index, Data; + switch (PRnum) { + case pr5: + pIndex = GC_Index; + pData = GC_Data; + Index = pr5; + Data = pr5_unlock; + break; + case pr10: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr10; + Data = pr10_unlock; + break; + case pr11: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr11; + Data = pr11_unlock; + break; +// case pr1b: + case pr1b_ual: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr1b; + Data = pr1b_unlock; + break; + case pr1b_ush: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr1b; + Data = pr1b_unlock_shadow; + break; + case pr1b_upr: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr1b; + Data = pr1b_unlock_pr; + break; + case pr20: + pIndex = Seq_Index; + pData = Seq_Data; + Index = pr20; + Data = pr20_unlock; + break; + case pr30: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr30; + Data = pr30_unlock; + break; + case pr72_alt: + pIndex = Seq_Index; + pData = Seq_Data; + Index = pr72; + Data = pr72_unlock; + break; + default: + return; + } /* endswitch */ + + WRITE_WD_UCHAR( pIndex, Index ); + if (pPRval!=NULL) { + *pPRval = READ_WD_UCHAR( pData ); + } /* endif */ + WRITE_WD_UCHAR( pData, Data ); + +} + +VOID +RestorePR ( + USHORT PRnum, + PUCHAR pPRval + ) +{ + USHORT pIndex, pData; + UCHAR Index, Data; + switch (PRnum) { + case pr5: + pIndex = GC_Index; + pData = GC_Data; + Index = pr5; + break; + case pr10: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr10; + break; + case pr11: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr11; + break; + case pr1b: +// case pr1b_ual: +// case pr1b_ush: +// case pr1b_upr: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr1b; + break; + case pr20: + pIndex = Seq_Index; + pData = Seq_Data; + Index = pr20; + break; + case pr30: + pIndex = WD_3D4_Index; + pData = WD_3D5_Data; + Index = pr30; + break; + case pr72_alt: + pIndex = Seq_Index; + pData = Seq_Data; + Index = pr72; + break; + default: + return; + } /* endswitch */ + + Data = *pPRval; + WRITE_WD_UCHAR( pIndex, Index ); + WRITE_WD_UCHAR( pData, Data ); + +} + + +BOOLEAN +WDIsPresent ( + VOID + ) + +/*++ + +Routine Description: + + This routine returns TRUE if an WDVGA is present. It assumes that it's + already been established that a VGA is present. It performs the Western + Digital recommended ID test. If all this works, then this is indeed an + chip from Western Digital. + + All the registers will be preserved either this function fails to find a + WD vga or a WD vga is found. + +Arguments: + + None. + +Return Value: + + TRUE if a WDVGA is present, FALSE if not. + +--*/ + +{ + UCHAR GraphSave0c; + UCHAR GraphSave0f; + UCHAR temp1,temp2; + BOOLEAN status = TRUE; + + // + // write 3ce.0c + // + + WRITE_WD_UCHAR( GC_Index, pr2 ); + GraphSave0c = temp1 = READ_WD_UCHAR( GC_Data ); + temp1 &= 0xbf; + WRITE_WD_UCHAR( GC_Data, temp1 ); + + // + // check 3ce.09 after lock + // + + LockPR( pr5, &GraphSave0f ); // lock it +// WRITE_WD_UCHAR( GC_Index, pr5 ); +// GraphSave0f = READ_WD_UCHAR( GC_Data ); +// WRITE_WD_UCHAR( GC_Data, pr5_lock ); // lock it + + WRITE_WD_UCHAR( GC_Index, pr0a ); + temp1 = READ_WD_UCHAR( GC_Data ); + WRITE_WD_UCHAR( GC_Data, (UCHAR)(temp1+1) ); + temp2 = READ_WD_UCHAR( GC_Data ); + WRITE_WD_UCHAR( GC_Data, temp1 ); + + if ((temp1+1) == temp2) { + status = FALSE; + goto NOT_WDVGA; // locked but writable + } + + // + // check 3ce.09 after unlock + // + + UnlockPR( pr5, NULL ); // lock it +// WRITE_WD_USHORT( GC_Index, (pr5_unlock*0x100+pr5) ); // unlock + + WRITE_WD_UCHAR( GC_Index, pr0a ); + temp1 = READ_WD_UCHAR( GC_Data ); + WRITE_WD_UCHAR( GC_Data, (UCHAR)(temp1+1) ); + temp2 = READ_WD_UCHAR( GC_Data ); + WRITE_WD_UCHAR( GC_Data, temp1 ); + + if ((temp1+1) != temp2) { + status = FALSE; + goto NOT_WDVGA; // unlocked but not-writable + } + +NOT_WDVGA: + + // + // write 3ce.0c (post-process) + // + + WRITE_WD_UCHAR( GC_Index, pr2 ); + WRITE_WD_UCHAR( GC_Data, GraphSave0c); + + RestorePR( pr5, &GraphSave0f ); +// WRITE_WD_UCHAR( GC_Index, pr5 ); +// WRITE_WD_UCHAR( GC_Data, GraphSave0f); + + return status; + +} + +/*****************************************************************************/ diff --git a/private/ntos/nthals/halwood/ppc/x86bios.c b/private/ntos/nthals/halwood/ppc/x86bios.c new file mode 100644 index 000000000..ba7969c5d --- /dev/null +++ b/private/ntos/nthals/halwood/ppc/x86bios.c @@ -0,0 +1 @@ +#include "..\..\halppc\ppc\x86bios.c" |