summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halwood/ppc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/ntos/nthals/halwood/ppc/fwnvr.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxbeep.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxbusdat.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxcache.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxcalstl.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxclksup.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxclock.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxdat.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxdisp.c2
-rw-r--r--private/ntos/nthals/halwood/ppc/pxenviro.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxflshbf.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxflshio.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxhwsup.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxidle.c62
-rw-r--r--private/ntos/nthals/halwood/ppc/pxinfo.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxinithl.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxintmod.c78
-rw-r--r--private/ntos/nthals/halwood/ppc/pxintrpt.c2
-rw-r--r--private/ntos/nthals/halwood/ppc/pxintsup.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxirql.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxisabus.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxmapio.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxmemctl.c338
-rw-r--r--private/ntos/nthals/halwood/ppc/pxmemctl.h36
-rw-r--r--private/ntos/nthals/halwood/ppc/pxnatsup.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxpcibrd.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxpcibus.c2404
-rw-r--r--private/ntos/nthals/halwood/ppc/pxpciint.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxpcisup.c259
-rw-r--r--private/ntos/nthals/halwood/ppc/pxport.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxpower.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxproc.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxprof.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxreset.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxreturn.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxs3.c2
-rw-r--r--private/ntos/nthals/halwood/ppc/pxshadbf.s2
-rw-r--r--private/ntos/nthals/halwood/ppc/pxsiosup.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxstall.s1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxsysbus.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxsysint.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxtime.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxusage.c1
-rw-r--r--private/ntos/nthals/halwood/ppc/pxwd.c2
-rw-r--r--private/ntos/nthals/halwood/ppc/wdvga.c745
-rw-r--r--private/ntos/nthals/halwood/ppc/x86bios.c1
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"