summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halppc
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halppc
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/nthals/halppc')
-rw-r--r--private/ntos/nthals/halppc/hal.rc11
-rw-r--r--private/ntos/nthals/halppc/makefile6
-rw-r--r--private/ntos/nthals/halppc/makefile.inc3
-rw-r--r--private/ntos/nthals/halppc/ppc/bbldef.h446
-rw-r--r--private/ntos/nthals/halppc/ppc/bblfont.h1499
-rw-r--r--private/ntos/nthals/halppc/ppc/bblrastz.h113
-rw-r--r--private/ntos/nthals/halppc/ppc/bblrmdac.h802
-rw-r--r--private/ntos/nthals/halppc/ppc/bldef.h144
-rw-r--r--private/ntos/nthals/halppc/ppc/blfw.h121
-rw-r--r--private/ntos/nthals/halppc/ppc/blrastz.h348
-rw-r--r--private/ntos/nthals/halppc/ppc/blrmdac.h152
-rw-r--r--private/ntos/nthals/halppc/ppc/fwdebug.h99
-rw-r--r--private/ntos/nthals/halppc/ppc/fwnvr.c2033
-rw-r--r--private/ntos/nthals/halppc/ppc/fwnvr.h313
-rw-r--r--private/ntos/nthals/halppc/ppc/fwstatus.h17
-rw-r--r--private/ntos/nthals/halppc/ppc/halp.h503
-rw-r--r--private/ntos/nthals/halppc/ppc/ibmppc.h60
-rw-r--r--private/ntos/nthals/halppc/ppc/pcip.h186
-rw-r--r--private/ntos/nthals/halppc/ppc/prepnvr.h134
-rw-r--r--private/ntos/nthals/halppc/ppc/pxbbl.c1546
-rw-r--r--private/ntos/nthals/halppc/ppc/pxbeep.c134
-rw-r--r--private/ntos/nthals/halppc/ppc/pxbl.c1700
-rw-r--r--private/ntos/nthals/halppc/ppc/pxbusdat.c200
-rw-r--r--private/ntos/nthals/halppc/ppc/pxcache.s1188
-rw-r--r--private/ntos/nthals/halppc/ppc/pxcalstl.c132
-rw-r--r--private/ntos/nthals/halppc/ppc/pxclksup.s153
-rw-r--r--private/ntos/nthals/halppc/ppc/pxclock.c283
-rw-r--r--private/ntos/nthals/halppc/ppc/pxdakota.h67
-rw-r--r--private/ntos/nthals/halppc/ppc/pxdat.c123
-rw-r--r--private/ntos/nthals/halppc/ppc/pxdisp.c1733
-rw-r--r--private/ntos/nthals/halppc/ppc/pxdisp.h360
-rw-r--r--private/ntos/nthals/halppc/ppc/pxds1585.h106
-rw-r--r--private/ntos/nthals/halppc/ppc/pxenviro.c170
-rw-r--r--private/ntos/nthals/halppc/ppc/pxfirsup.c1606
-rw-r--r--private/ntos/nthals/halppc/ppc/pxfirsup.h219
-rw-r--r--private/ntos/nthals/halppc/ppc/pxflshbf.s121
-rw-r--r--private/ntos/nthals/halppc/ppc/pxflshio.c197
-rw-r--r--private/ntos/nthals/halppc/ppc/pxhalp.h345
-rw-r--r--private/ntos/nthals/halppc/ppc/pxhwsup.c2188
-rw-r--r--private/ntos/nthals/halppc/ppc/pxidaho.h139
-rw-r--r--private/ntos/nthals/halppc/ppc/pxidle.c62
-rw-r--r--private/ntos/nthals/halppc/ppc/pxinfo.c213
-rw-r--r--private/ntos/nthals/halppc/ppc/pxinithl.c325
-rw-r--r--private/ntos/nthals/halppc/ppc/pxintmod.c79
-rw-r--r--private/ntos/nthals/halppc/ppc/pxintrpt.c105
-rw-r--r--private/ntos/nthals/halppc/ppc/pxintsup.s35
-rw-r--r--private/ntos/nthals/halppc/ppc/pxirql.c284
-rw-r--r--private/ntos/nthals/halppc/ppc/pxisabus.c133
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmapio.c124
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmemctl.c311
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmemctl.h38
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmisc.s159
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmp.h59
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmpic2.h309
-rw-r--r--private/ntos/nthals/halppc/ppc/pxmpint.c323
-rw-r--r--private/ntos/nthals/halppc/ppc/pxnatsup.c80
-rw-r--r--private/ntos/nthals/halppc/ppc/pxnatsup.h57
-rw-r--r--private/ntos/nthals/halppc/ppc/pxp91.c1334
-rw-r--r--private/ntos/nthals/halppc/ppc/pxp91.h1380
-rw-r--r--private/ntos/nthals/halppc/ppc/pxpcibrd.c1028
-rw-r--r--private/ntos/nthals/halppc/ppc/pxpcibus.c2386
-rw-r--r--private/ntos/nthals/halppc/ppc/pxpciint.c254
-rw-r--r--private/ntos/nthals/halppc/ppc/pxpcisup.c326
-rw-r--r--private/ntos/nthals/halppc/ppc/pxport.c848
-rw-r--r--private/ntos/nthals/halppc/ppc/pxpower.s123
-rw-r--r--private/ntos/nthals/halppc/ppc/pxproc.c212
-rw-r--r--private/ntos/nthals/halppc/ppc/pxprof.c268
-rw-r--r--private/ntos/nthals/halppc/ppc/pxreset.s455
-rw-r--r--private/ntos/nthals/halppc/ppc/pxreturn.c187
-rw-r--r--private/ntos/nthals/halppc/ppc/pxrtcsup.h28
-rw-r--r--private/ntos/nthals/halppc/ppc/pxs3.c677
-rw-r--r--private/ntos/nthals/halppc/ppc/pxs3.h445
-rw-r--r--private/ntos/nthals/halppc/ppc/pxshadbf.s37
-rw-r--r--private/ntos/nthals/halppc/ppc/pxsiosup.c2218
-rw-r--r--private/ntos/nthals/halppc/ppc/pxsiosup.h219
-rw-r--r--private/ntos/nthals/halppc/ppc/pxstall.s324
-rw-r--r--private/ntos/nthals/halppc/ppc/pxsysbus.c111
-rw-r--r--private/ntos/nthals/halppc/ppc/pxsysint.c227
-rw-r--r--private/ntos/nthals/halppc/ppc/pxtime.c386
-rw-r--r--private/ntos/nthals/halppc/ppc/pxusage.c499
-rw-r--r--private/ntos/nthals/halppc/ppc/pxvgaequ.h141
-rw-r--r--private/ntos/nthals/halppc/ppc/pxvm.c297
-rw-r--r--private/ntos/nthals/halppc/ppc/pxwd.c938
-rw-r--r--private/ntos/nthals/halppc/ppc/pxwd.h706
-rw-r--r--private/ntos/nthals/halppc/ppc/txtpalet.h97
-rw-r--r--private/ntos/nthals/halppc/ppc/x86bios.c359
-rw-r--r--private/ntos/nthals/halppc/sources106
87 files changed, 39012 insertions, 0 deletions
diff --git a/private/ntos/nthals/halppc/hal.rc b/private/ntos/nthals/halppc/hal.rc
new file mode 100644
index 000000000..3cba4ad89
--- /dev/null
+++ b/private/ntos/nthals/halppc/hal.rc
@@ -0,0 +1,11 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Hardware Abstraction Layer DLL"
+#define VER_INTERNALNAME_STR "hal.dll"
+
+#include "common.ver"
+
diff --git a/private/ntos/nthals/halppc/makefile b/private/ntos/nthals/halppc/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/nthals/halppc/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/nthals/halppc/makefile.inc b/private/ntos/nthals/halppc/makefile.inc
new file mode 100644
index 000000000..db43490ff
--- /dev/null
+++ b/private/ntos/nthals/halppc/makefile.inc
@@ -0,0 +1,3 @@
+$(TARGETPATH)\ppc\hal.lib: $(TARGETPATH)\ppc\halppc.lib
+ copy $** $@
+
diff --git a/private/ntos/nthals/halppc/ppc/bbldef.h b/private/ntos/nthals/halppc/ppc/bbldef.h
new file mode 100644
index 000000000..97a9ee69f
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/bbldef.h
@@ -0,0 +1,446 @@
+
+#ifndef _H_BBLDEF
+#define _H_BBLDEF
+
+#include "halp.h"
+
+//#include <ntos.h>
+
+//
+// Used for debugging
+//
+
+#if defined(BBL_DBG) && DBG
+#define BBL_DBG_PRINT DbgPrint
+#else
+#define BBL_DBG_PRINT
+#endif // !DBG
+
+//
+// Define the physical memory attribites
+//
+
+//#define BBL_BASE_ADDR 0xD0000000
+//#define BBL_VIDEO_MEMORY_BASE 0xD4000000
+#define BBL_VIDEO_MEMORY_OFFSET 0x04000000
+#define BBL_VIDEO_MEMORY_LENGTH 0x200000 // 2 MB
+//#define BBL_REG_ADDR_BASE 0xDA000000
+#define BBL_REG_ADDR_OFFSET 0x0A000000
+#define BBL_REG_ADDR_LENGTH 0x1000 // 4 K
+#define BBL_SCANLINE_LENGTH 0x800 // 2 K
+
+
+//
+// Define the register base
+//
+
+#define BBL_REG_BASE (HalpBBLRegisterBase)
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_REG (regbase, register, data) *
+* caddr_t regbase; *
+* caddr_t register; *
+* unsigned long data; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* register - Register offset of adapter register to write *
+* data - Data to write to the register *
+* *
+* Description: Writes the "data" value in the adapter register *
+* *
+* Notes: This macro may only be used by the device driver because *
+* it does not require the adapter pointer. This macro may *
+* only be called from kernel level code. *
+* *
+******************************************************************************/
+
+#define BBL_SET_REG(regbase, register, data) \
+ (*((volatile unsigned long *) \
+ ((unsigned long)(regbase) | (register)))) = \
+ ((volatile unsigned long)(data))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_GET_REG (regbase, register) *
+* caddr_t regbase; *
+* caddr_t register; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* register - Register offset of adapter register to write *
+* *
+* Description: Reads the value in the adapter register *
+* *
+* Notes: This macro may only be used by the device driver because *
+* it does not require the adapter pointer. This macro may *
+* only be called from kernel level code. *
+* *
+* Returns: This macro is a RHS macro which expands to the value of *
+* the register *
+* *
+******************************************************************************/
+
+#define BBL_GET_REG(regbase, register) \
+ (volatile unsigned long) \
+ (*((volatile unsigned long *) \
+ ((unsigned long)(regbase) | (register))))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_DD_EIEIO *
+* *
+* Parameters: None *
+* *
+* Description: This macro expands to the PowerPC assembly instruction eieio *
+* *
+* Notes: This macro compiles to an in-line assembly instruction so *
+* there is no function call overhead. The eieio instruction *
+* takes between 3 and 6 cycles on the 601 processor which *
+* amounts to 45 - 90 ns on the 66MHX 601 processor. *
+* *
+* Returns: Expands into the "eieio" in-line assembly instruction. *
+* *
+******************************************************************************/
+
+#define BBL_EIEIO __builtin_eieio()
+
+
+//
+// Configure the GXT150 Graphics Adapter. This function sets the
+// necessary PCI config space registers to enable the GXT150P
+// Graphics Adapter in the system for further I/O requests to it
+//
+
+// Standard PCI configuration register offsets
+#define PCI_DEV_VEND_ID_REG 0x00
+#define PCI_CMD_STAT_REG 0x04
+#define PCI_CMD_REG 0x04
+#define PCI_STAT_REG 0x06
+#define PCI_BASE_ADDR_REG 0x10
+
+// GXT150P device specific configuration register offsets
+#define BBL_DEV_CHAR_REG 0x40
+#define BBL_BUID1_REG 0x48
+#define BBL_XIVR_REG 0x60
+#define BBL_INTL_REG 0x64
+#define BBL_BELE_REG 0x70
+
+// GXT150P configuration register values
+#define BBL_DEV_VEND_ID 0x001B1014
+#define BBL_DEV_CHAR_VAL 0x34900040
+#define BBL_BUID1_VAL 0x00A50000
+#define BBL_XIVR_VAL 0x00000004
+#define BBL_INTL_VAL 0x0000000F
+#define BBL_BELE_VAL 0x00000008 // Little Endian Mode
+
+#define BBL_VEN_ID 0x1014
+#define BBL_DEV_ID 0x001b
+
+#define BBL_MEM_ENABLE 0x0002
+
+
+//
+// Define the monitor ID (cable and DIP switch) masks
+//
+
+#define BBL_MON_ID_DIP_SWITCHES_SHIFT 16
+#define BBL_MON_ID_DIP_SWITCHES_MASK \
+ (0xF << BBL_MON_ID_DIP_SWITCHES_SHIFT)
+
+#define BBL_MON_ID_CABLE_ID_0 0x0
+#define BBL_MON_ID_CABLE_ID_H 0x1
+#define BBL_MON_ID_CABLE_ID_V 0x2
+#define BBL_MON_ID_CABLE_ID_1 0x3
+
+#define BBL_MON_ID_CABLE_BIT_0_SHIFT 6
+#define BBL_MON_ID_CABLE_BIT_0_MASK \
+ (0x3 << BBL_MON_ID_CABLE_BIT_0_SHIFT)
+#define BBL_MON_ID_CABLE_BIT_1_SHIFT 4
+#define BBL_MON_ID_CABLE_BIT_1_MASK \
+ (0x3 << BBL_MON_ID_CABLE_BIT_1_SHIFT)
+#define BBL_MON_ID_CABLE_BIT_2_SHIFT 2
+#define BBL_MON_ID_CABLE_BIT_2_MASK \
+ (0x3 << BBL_MON_ID_CABLE_BIT_2_SHIFT)
+#define BBL_MON_ID_CABLE_BIT_3_SHIFT 0
+#define BBL_MON_ID_CABLE_BIT_3_MASK \
+ (0x3 << BBL_MON_ID_CABLE_BIT_3_SHIFT)
+
+
+//
+// For CRT control register:
+//
+// 7 6 5 4 3 2 1 0
+// --------------------------------------------
+// | 0 | 0 | 0 | VSP | HSP | CSE | CSG | BPE |
+// --------------------------------------------
+//
+// where VPS = vert. sync polarity
+// HPS = horz. sync polarity (reversed if either CSE or CSG
+// are on for DD2 parts)
+//
+// CSE = composite sync enable on HSYNC (when enabled, bit 4 -> don't care)
+//
+// CSG = composite sync on green (when enabled, bits 4,3,2 -> don't care)
+// BPE = blanking pedistal enable
+//
+
+
+//
+// Define the monitor types
+//
+
+typedef struct _bbl_mon_data_t {
+ ULONG monitor_id;
+#define BBL_MON_PEDISTAL_ENABLE (1L << 0)
+#define BBL_MON_COMPOSITE_SYNC_ON_GREEN (1L << 1)
+#define BBL_MON_COMPOSITE_SYNC_ON_HSYNC (1L << 2)
+#define BBL_MON_HORZ_SYNC_POLARITY_POSITIVE (1L << 3)
+#define BBL_MON_VERT_SYNC_POLARITY_POSITIVE (1L << 4)
+ ULONG crt_cntl;
+ ULONG x_res;
+ ULONG y_res;
+ ULONG frame_rate;
+ ULONG pixel_freq;
+ ULONG hrz_total;
+ ULONG hrz_disp_end;
+ ULONG hrz_sync_start;
+ ULONG hrz_sync_end1;
+ ULONG hrz_sync_end2;
+ ULONG vrt_total;
+ ULONG vrt_disp_end;
+ ULONG vrt_sync_start;
+ ULONG vrt_sync_end;
+#define BBL_MON_COLOR (1L << 0)
+#define BBL_MON_MONO (0L << 0)
+ ULONG flags;
+} bbl_mon_data_t, *pbbl_mon_data_t;
+
+
+//
+// Set up the monitor data information
+//
+
+static bbl_mon_data_t bbl_mon_data[] = {
+
+ #define BBL_MT_1 0x000200cc /* 0010 1010 */
+ /* 1024x768 70Hz 78Mhz PSYNC */
+ { BBL_MT_1,
+ BBL_MON_VERT_SYNC_POLARITY_POSITIVE |
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE,
+ 1024,768,7000,7800,
+ 1367,1023,1047,1327,0,
+ 813,767,767,775,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_2 0x000a00cc /* 1010 1010 */
+ /* 1280x1024 60Hz 112Mhz NSYNC */
+ { BBL_MT_2,
+ 0x0,
+ 1280,1024,6000,11200,
+ 1759,1279,1299,1455,1103,
+ 1055,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_3 0x000b00cc /* 1011 1010 */
+ /* 1024x768 75.8Hz 86Mhz PSYNC */
+ { BBL_MT_3,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_VERT_SYNC_POLARITY_POSITIVE,
+ 1024,768,7580,8600,
+ 1407,1023,1031,1351,711,
+ 805,767,767,775,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_4 0x000d00cc /* 1101 1010 */
+ /* 1280x1024 77Hz 148Mhz NSYNC */
+ { BBL_MT_4,
+ 0x0,
+ 1280,1024,7700,14800,
+ 1819,1279,1319,1503,1115,
+ 1055,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_5 0x000f00cc /* 1111 1010 */
+ /* 1024x768 60Hz 64Mhz NSYNC */
+ { BBL_MT_5,
+ 0x0,
+ 1024,768,6000,6400,
+ 1311,1023,1055,1151,991,
+ 812,767,770,773,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_6 0x000f003f /* 1111 0111 */
+ /* 1280x1024 67Hz 128Mhz NSYNC */
+ { BBL_MT_6,
+ 0x0,
+ 1280,1024,6700,12800,
+ 1807,1279,1351,1607,0,
+ 1055,1023,1023,1031,
+ BBL_MON_MONO },
+
+ #define BBL_MT_7 0x000f004c /* 1111 H010 */
+ /* 1024x768 70Hz 78Mhz PSYNC */
+ { BBL_MT_7,
+ BBL_MON_VERT_SYNC_POLARITY_POSITIVE |
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE,
+ 1024,768,7000,7800,
+ 1367,1023,1047,1327,0,
+ 813,767,767,775,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_8 0x00010030 /* 0001 0100 */
+ /* 1024x768 75.8Hz 86Mhz SOG */
+ { BBL_MT_8,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1024,768,7580,8600,
+ 1407,1023,1031,1351,711,
+ 805,767,767,775,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_8_PATCH 0x000b0030 /* 1011 0100 */
+ /* 1024x768 75.8Hz 86Mhz PSYNC */
+ { BBL_MT_8_PATCH,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_VERT_SYNC_POLARITY_POSITIVE,
+ 1024,768,7580,8600,
+ 1407,1023,1031,1351,711,
+ 805,767,767,775,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_8_PATCH_1 0x00040030 /* 0100 0100 */
+ /* 1024x768 75.8Hz 86Mhz SOG */
+ { BBL_MT_8_PATCH_1,
+ BBL_MON_PEDISTAL_ENABLE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE,
+ 1024,768,7580,8600,
+ 1407,1023,1031,1231,831,
+ 805,767,770,778,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_9 0x00020030 /* 0010 0100 */
+ /* 1024x768 70Hz 75Mhz SOG */
+ { BBL_MT_9,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1024,768,7000,7500,
+ 1323,1023,1115,1191,1039,
+ 807,767,767,769,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_10 0x00030030 /* 0011 0100 */
+ /* 1024x768 60Hz 64Mhz SOG */
+ { BBL_MT_10,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1024,768,6000,6400,
+ 1311,1023,1087,1183,991,
+ 812,767,770,773,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_11 0x00060030 /* 0110 0100 */
+ /* 1280x1024 74Hz 135Mhz SOG */
+ { BBL_MT_11,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1280,1024,7400,13500,
+ 1711,1279,1311,1455,1167,
+ 1065,1023,1023,1026,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_12 0x00070030 /* 0111 0100 */
+ /* 1280x1024 60Hz 108Mhz SOG */
+ { BBL_MT_12,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1280,1024,6000,10800,
+ 1707,1279,1323,1507,1139,
+ 1052,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_13 0x000d0030 /* 1101 0100 */
+ /* 1280x1024 77Hz 148Mhz SOG */
+ { BBL_MT_13,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1280,1024,7700,14800,
+ 1819,1279,1319,1503,1115,
+ 1055,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_14 0x000e0030 /* 1110 0100 */
+ /* 1280x1024 67Hz 120Mhz SOG */
+ { BBL_MT_14,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1280,1024,6700,12000,
+ 1695,1279,1311,1471,1151,
+ 1055,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_15 0x000f0030 /* 1111 0100 */
+ /* 1280x1024 60Hz 112Mhz SOG */
+ { BBL_MT_15,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_GREEN |
+ BBL_MON_PEDISTAL_ENABLE,
+ 1280,1024,6000,11200,
+ 1759,1279,1299,1455,1103,
+ 1055,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_16 0x000f00bf /* 1111 V111 */
+ /* 1280x1024 72Hz 128Mhz */
+ { BBL_MT_16,
+ 0x0,
+ 1280,1024,7200,12800,
+ 1687,1279,1311,1451,1167,
+ 1059,1023,1026,1029,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_17 0x000400ff /* 0100 1111 */
+ /* 1152x900 66Hz 93Mhz CSYNC */
+ { BBL_MT_17,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_HSYNC,
+ 1152,900,6600,9300,
+ 1503,1151,1179,1307,1051,
+ 936,899,901,905,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_18 0x000500ff /* 0101 1111 */
+ /* 1152x900 76Hz 106Mhz CSYNC */
+ { BBL_MT_18,
+ BBL_MON_HORZ_SYNC_POLARITY_POSITIVE |
+ BBL_MON_COMPOSITE_SYNC_ON_HSYNC,
+ 1152,900,7600,10600,
+ 1471,1151,1163,1259,1067,
+ 942,899,901,909,
+ BBL_MON_COLOR },
+
+ #define BBL_MT_DEFAULT 0x000f00ff /* 1111 1111 */
+ /* THIS IS THE DEFAULT MONITOR ID */
+ /* THIS IS THE NO-MONITOR ATTACHED ID */
+ /* These settings are the same as BBL_MT_5 */
+ /* 1024x768 60Hz 64Mhz NSYNC */
+ { BBL_MT_DEFAULT,
+ 0x0,
+ 1024,768,6000,6400,
+ 1311,1023,1055,1151,991,
+ 812,767,770,773,
+ BBL_MON_COLOR },
+};
+
+#endif // _H_BBLDEF
+
diff --git a/private/ntos/nthals/halppc/ppc/bblfont.h b/private/ntos/nthals/halppc/ppc/bblfont.h
new file mode 100644
index 000000000..450aa9642
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/bblfont.h
@@ -0,0 +1,1499 @@
+/*++
+
+Module Name:
+
+ bblfont.h
+
+Abstract:
+
+ This header file defines a font suitable for use with the HAL
+ text on the GXT150P graphics adapter. The font data is standard
+ OEM VGA font data (10x20 glyphs)
+
+--*/
+
+/*
+UCHAR BBLFont[12288] = {
+*/
+UCHAR BBLFont[11832] = {
+0x00, 0x02, 0x3e, 0x2c, 0x00, 0x00, 0x28, 0x63,
+0x29, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69,
+0x67, 0x68, 0x74, 0x20, 0x42, 0x69, 0x74, 0x73,
+0x74, 0x72, 0x65, 0x61, 0x6d, 0x20, 0x49, 0x6e,
+0x63, 0x2e, 0x20, 0x31, 0x39, 0x38, 0x34, 0x2e,
+0x20, 0x41, 0x6c, 0x6c, 0x20, 0x72, 0x69, 0x67,
+0x68, 0x74, 0x73, 0x20, 0x72, 0x65, 0x73, 0x65,
+0x72, 0x76, 0x65, 0x64, 0x2e, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x60, 0x00,
+0x60, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x90, 0x01, 0xff, 0x0a, 0x00,
+0x14, 0x00, 0x30, 0x0a, 0x00, 0x0a, 0x00, 0x01,
+0xfe, 0x1f, 0x00, 0xfd, 0x01, 0x00, 0x00, 0x00,
+0x00, 0x36, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x72, 0x04, 0x00, 0x00, 0x00, 0x0a, 0x00,
+0x72, 0x04, 0x0a, 0x00, 0x9a, 0x04, 0x0a, 0x00,
+0xc2, 0x04, 0x0a, 0x00, 0xea, 0x04, 0x0a, 0x00,
+0x12, 0x05, 0x0a, 0x00, 0x3a, 0x05, 0x0a, 0x00,
+0x62, 0x05, 0x0a, 0x00, 0x8a, 0x05, 0x0a, 0x00,
+0xb2, 0x05, 0x0a, 0x00, 0xda, 0x05, 0x0a, 0x00,
+0x02, 0x06, 0x0a, 0x00, 0x2a, 0x06, 0x0a, 0x00,
+0x52, 0x06, 0x0a, 0x00, 0x7a, 0x06, 0x0a, 0x00,
+0xa2, 0x06, 0x0a, 0x00, 0xca, 0x06, 0x0a, 0x00,
+0xf2, 0x06, 0x0a, 0x00, 0x1a, 0x07, 0x0a, 0x00,
+0x42, 0x07, 0x0a, 0x00, 0x6a, 0x07, 0x0a, 0x00,
+0x92, 0x07, 0x0a, 0x00, 0xba, 0x07, 0x0a, 0x00,
+0xe2, 0x07, 0x0a, 0x00, 0x0a, 0x08, 0x0a, 0x00,
+0x32, 0x08, 0x0a, 0x00, 0x5a, 0x08, 0x0a, 0x00,
+0x82, 0x08, 0x0a, 0x00, 0xaa, 0x08, 0x0a, 0x00,
+0xd2, 0x08, 0x0a, 0x00, 0xfa, 0x08, 0x0a, 0x00,
+0x22, 0x09, 0x0a, 0x00, 0x4a, 0x09, 0x0a, 0x00,
+0x72, 0x09, 0x0a, 0x00, 0x9a, 0x09, 0x0a, 0x00,
+0xc2, 0x09, 0x0a, 0x00, 0xea, 0x09, 0x0a, 0x00,
+0x12, 0x0a, 0x0a, 0x00, 0x3a, 0x0a, 0x0a, 0x00,
+0x62, 0x0a, 0x0a, 0x00, 0x8a, 0x0a, 0x0a, 0x00,
+0xb2, 0x0a, 0x0a, 0x00, 0xda, 0x0a, 0x0a, 0x00,
+0x02, 0x0b, 0x0a, 0x00, 0x2a, 0x0b, 0x0a, 0x00,
+0x52, 0x0b, 0x0a, 0x00, 0x7a, 0x0b, 0x0a, 0x00,
+0xa2, 0x0b, 0x0a, 0x00, 0xca, 0x0b, 0x0a, 0x00,
+0xf2, 0x0b, 0x0a, 0x00, 0x1a, 0x0c, 0x0a, 0x00,
+0x42, 0x0c, 0x0a, 0x00, 0x6a, 0x0c, 0x0a, 0x00,
+0x92, 0x0c, 0x0a, 0x00, 0xba, 0x0c, 0x0a, 0x00,
+0xe2, 0x0c, 0x0a, 0x00, 0x0a, 0x0d, 0x0a, 0x00,
+0x32, 0x0d, 0x0a, 0x00, 0x5a, 0x0d, 0x0a, 0x00,
+0x82, 0x0d, 0x0a, 0x00, 0xaa, 0x0d, 0x0a, 0x00,
+0xd2, 0x0d, 0x0a, 0x00, 0xfa, 0x0d, 0x0a, 0x00,
+0x22, 0x0e, 0x0a, 0x00, 0x4a, 0x0e, 0x0a, 0x00,
+0x72, 0x0e, 0x0a, 0x00, 0x9a, 0x0e, 0x0a, 0x00,
+0xc2, 0x0e, 0x0a, 0x00, 0xea, 0x0e, 0x0a, 0x00,
+0x12, 0x0f, 0x0a, 0x00, 0x3a, 0x0f, 0x0a, 0x00,
+0x62, 0x0f, 0x0a, 0x00, 0x8a, 0x0f, 0x0a, 0x00,
+0xb2, 0x0f, 0x0a, 0x00, 0xda, 0x0f, 0x0a, 0x00,
+0x02, 0x10, 0x0a, 0x00, 0x2a, 0x10, 0x0a, 0x00,
+0x52, 0x10, 0x0a, 0x00, 0x7a, 0x10, 0x0a, 0x00,
+0xa2, 0x10, 0x0a, 0x00, 0xca, 0x10, 0x0a, 0x00,
+0xf2, 0x10, 0x0a, 0x00, 0x1a, 0x11, 0x0a, 0x00,
+0x42, 0x11, 0x0a, 0x00, 0x6a, 0x11, 0x0a, 0x00,
+0x92, 0x11, 0x0a, 0x00, 0xba, 0x11, 0x0a, 0x00,
+0xe2, 0x11, 0x0a, 0x00, 0x0a, 0x12, 0x0a, 0x00,
+0x32, 0x12, 0x0a, 0x00, 0x5a, 0x12, 0x0a, 0x00,
+0x82, 0x12, 0x0a, 0x00, 0xaa, 0x12, 0x0a, 0x00,
+0xd2, 0x12, 0x0a, 0x00, 0xfa, 0x12, 0x0a, 0x00,
+0x22, 0x13, 0x0a, 0x00, 0x4a, 0x13, 0x0a, 0x00,
+0x72, 0x13, 0x0a, 0x00, 0x9a, 0x13, 0x0a, 0x00,
+0xc2, 0x13, 0x0a, 0x00, 0xea, 0x13, 0x0a, 0x00,
+0x12, 0x14, 0x0a, 0x00, 0x3a, 0x14, 0x0a, 0x00,
+0x62, 0x14, 0x0a, 0x00, 0x8a, 0x14, 0x0a, 0x00,
+0xb2, 0x14, 0x0a, 0x00, 0xda, 0x14, 0x0a, 0x00,
+0x02, 0x15, 0x0a, 0x00, 0x2a, 0x15, 0x0a, 0x00,
+0x52, 0x15, 0x0a, 0x00, 0x7a, 0x15, 0x0a, 0x00,
+0xa2, 0x15, 0x0a, 0x00, 0xca, 0x15, 0x0a, 0x00,
+0xf2, 0x15, 0x0a, 0x00, 0x1a, 0x16, 0x0a, 0x00,
+0x42, 0x16, 0x0a, 0x00, 0x6a, 0x16, 0x0a, 0x00,
+0x92, 0x16, 0x0a, 0x00, 0xba, 0x16, 0x0a, 0x00,
+0xe2, 0x16, 0x0a, 0x00, 0x0a, 0x17, 0x0a, 0x00,
+0x32, 0x17, 0x0a, 0x00, 0x5a, 0x17, 0x0a, 0x00,
+0x82, 0x17, 0x0a, 0x00, 0xaa, 0x17, 0x0a, 0x00,
+0xd2, 0x17, 0x0a, 0x00, 0xfa, 0x17, 0x0a, 0x00,
+0x22, 0x18, 0x0a, 0x00, 0x4a, 0x18, 0x0a, 0x00,
+0x72, 0x18, 0x0a, 0x00, 0x9a, 0x18, 0x0a, 0x00,
+0xc2, 0x18, 0x0a, 0x00, 0xea, 0x18, 0x0a, 0x00,
+0x12, 0x19, 0x0a, 0x00, 0x3a, 0x19, 0x0a, 0x00,
+0x62, 0x19, 0x0a, 0x00, 0x8a, 0x19, 0x0a, 0x00,
+0xb2, 0x19, 0x0a, 0x00, 0xda, 0x19, 0x0a, 0x00,
+0x02, 0x1a, 0x0a, 0x00, 0x2a, 0x1a, 0x0a, 0x00,
+0x52, 0x1a, 0x0a, 0x00, 0x7a, 0x1a, 0x0a, 0x00,
+0xa2, 0x1a, 0x0a, 0x00, 0xca, 0x1a, 0x0a, 0x00,
+0xf2, 0x1a, 0x0a, 0x00, 0x1a, 0x1b, 0x0a, 0x00,
+0x42, 0x1b, 0x0a, 0x00, 0x6a, 0x1b, 0x0a, 0x00,
+0x92, 0x1b, 0x0a, 0x00, 0xba, 0x1b, 0x0a, 0x00,
+0xe2, 0x1b, 0x0a, 0x00, 0x0a, 0x1c, 0x0a, 0x00,
+0x32, 0x1c, 0x0a, 0x00, 0x5a, 0x1c, 0x0a, 0x00,
+0x82, 0x1c, 0x0a, 0x00, 0xaa, 0x1c, 0x0a, 0x00,
+0xd2, 0x1c, 0x0a, 0x00, 0xfa, 0x1c, 0x0a, 0x00,
+0x22, 0x1d, 0x0a, 0x00, 0x4a, 0x1d, 0x0a, 0x00,
+0x72, 0x1d, 0x0a, 0x00, 0x9a, 0x1d, 0x0a, 0x00,
+0xc2, 0x1d, 0x0a, 0x00, 0xea, 0x1d, 0x0a, 0x00,
+0x12, 0x1e, 0x0a, 0x00, 0x3a, 0x1e, 0x0a, 0x00,
+0x62, 0x1e, 0x0a, 0x00, 0x8a, 0x1e, 0x0a, 0x00,
+0xb2, 0x1e, 0x0a, 0x00, 0xda, 0x1e, 0x0a, 0x00,
+0x02, 0x1f, 0x0a, 0x00, 0x2a, 0x1f, 0x0a, 0x00,
+0x52, 0x1f, 0x0a, 0x00, 0x7a, 0x1f, 0x0a, 0x00,
+0xa2, 0x1f, 0x0a, 0x00, 0xca, 0x1f, 0x0a, 0x00,
+0xf2, 0x1f, 0x0a, 0x00, 0x1a, 0x20, 0x0a, 0x00,
+0x42, 0x20, 0x0a, 0x00, 0x6a, 0x20, 0x0a, 0x00,
+0x92, 0x20, 0x0a, 0x00, 0xba, 0x20, 0x0a, 0x00,
+0xe2, 0x20, 0x0a, 0x00, 0x0a, 0x21, 0x0a, 0x00,
+0x32, 0x21, 0x0a, 0x00, 0x5a, 0x21, 0x0a, 0x00,
+0x82, 0x21, 0x0a, 0x00, 0xaa, 0x21, 0x0a, 0x00,
+0xd2, 0x21, 0x0a, 0x00, 0xfa, 0x21, 0x0a, 0x00,
+0x22, 0x22, 0x0a, 0x00, 0x4a, 0x22, 0x0a, 0x00,
+0x72, 0x22, 0x0a, 0x00, 0x9a, 0x22, 0x0a, 0x00,
+0xc2, 0x22, 0x0a, 0x00, 0xea, 0x22, 0x0a, 0x00,
+0x12, 0x23, 0x0a, 0x00, 0x3a, 0x23, 0x0a, 0x00,
+0x62, 0x23, 0x0a, 0x00, 0x8a, 0x23, 0x0a, 0x00,
+0xb2, 0x23, 0x0a, 0x00, 0xda, 0x23, 0x0a, 0x00,
+0x02, 0x24, 0x0a, 0x00, 0x2a, 0x24, 0x0a, 0x00,
+0x52, 0x24, 0x0a, 0x00, 0x7a, 0x24, 0x0a, 0x00,
+0xa2, 0x24, 0x0a, 0x00, 0xca, 0x24, 0x0a, 0x00,
+0xf2, 0x24, 0x0a, 0x00, 0x1a, 0x25, 0x0a, 0x00,
+0x42, 0x25, 0x0a, 0x00, 0x6a, 0x25, 0x0a, 0x00,
+0x92, 0x25, 0x0a, 0x00, 0xba, 0x25, 0x0a, 0x00,
+0xe2, 0x25, 0x0a, 0x00, 0x0a, 0x26, 0x0a, 0x00,
+0x32, 0x26, 0x0a, 0x00, 0x5a, 0x26, 0x0a, 0x00,
+0x82, 0x26, 0x0a, 0x00, 0xaa, 0x26, 0x0a, 0x00,
+0xd2, 0x26, 0x0a, 0x00, 0xfa, 0x26, 0x0a, 0x00,
+0x22, 0x27, 0x0a, 0x00, 0x4a, 0x27, 0x0a, 0x00,
+0x72, 0x27, 0x0a, 0x00, 0x9a, 0x27, 0x0a, 0x00,
+0xc2, 0x27, 0x0a, 0x00, 0xea, 0x27, 0x0a, 0x00,
+0x12, 0x28, 0x0a, 0x00, 0x3a, 0x28, 0x0a, 0x00,
+0x62, 0x28, 0x0a, 0x00, 0x8a, 0x28, 0x0a, 0x00,
+0xb2, 0x28, 0x0a, 0x00, 0xda, 0x28, 0x0a, 0x00,
+0x02, 0x29, 0x0a, 0x00, 0x2a, 0x29, 0x0a, 0x00,
+0x52, 0x29, 0x0a, 0x00, 0x7a, 0x29, 0x0a, 0x00,
+0xa2, 0x29, 0x0a, 0x00, 0xca, 0x29, 0x0a, 0x00,
+0xf2, 0x29, 0x0a, 0x00, 0x1a, 0x2a, 0x0a, 0x00,
+0x42, 0x2a, 0x0a, 0x00, 0x6a, 0x2a, 0x0a, 0x00,
+0x92, 0x2a, 0x0a, 0x00, 0xba, 0x2a, 0x0a, 0x00,
+0xe2, 0x2a, 0x0a, 0x00, 0x0a, 0x2b, 0x0a, 0x00,
+0x32, 0x2b, 0x0a, 0x00, 0x5a, 0x2b, 0x0a, 0x00,
+0x82, 0x2b, 0x0a, 0x00, 0xaa, 0x2b, 0x0a, 0x00,
+0xd2, 0x2b, 0x0a, 0x00, 0xfa, 0x2b, 0x08, 0x00,
+0x22, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x7f,
+0xe1, 0xc0, 0xd2, 0xd2, 0xc0, 0xde, 0xcc, 0xe1,
+0x7f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x7f,
+0xff, 0xff, 0xed, 0xed, 0xff, 0xe1, 0xf3, 0xff,
+0x7f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0xf3, 0xff, 0xff, 0xff, 0x7f, 0x3f,
+0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0,
+0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0c, 0x1e, 0x3f, 0x7f, 0xff, 0x7f, 0x3f,
+0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x0c, 0x1e, 0x1e, 0x6d, 0xff, 0xff, 0x6d, 0x0c,
+0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x0c, 0x1e, 0x3f, 0x7f, 0xff, 0xff, 0x6d, 0x0c,
+0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x1e, 0x1e, 0x0c, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xc0, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0x40,
+0x40, 0x40, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1e, 0x21, 0x40, 0x80, 0x80, 0x80, 0x80, 0x40,
+0x21, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
+0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1,
+0x80, 0x80, 0x8c, 0x9e, 0x9e, 0x8c, 0x80, 0x80,
+0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0x40, 0x40, 0x40,
+0x40, 0x40, 0x40, 0x40, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x01,
+0x03, 0x07, 0x3e, 0x7e, 0xe7, 0xc3, 0xc3, 0xe7,
+0x7e, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc0, 0xc0, 0xc0, 0x40, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+0x61, 0xc0, 0xc0, 0xc0, 0xc0, 0x61, 0x3f, 0x0c,
+0x0c, 0x3f, 0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xc0,
+0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0f,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7c, 0xfc,
+0xfc, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xc0, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x79,
+0xfb, 0xf3, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x7f,
+0x33, 0x61, 0x61, 0x33, 0x7f, 0xde, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc0, 0x80, 0x00, 0x80, 0x80, 0x00,
+0x80, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x70, 0x78,
+0x7c, 0x7e, 0x7f, 0x7f, 0x7f, 0x7e, 0x7c, 0x78,
+0x70, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07,
+0x0f, 0x1f, 0x3f, 0x7f, 0x3f, 0x1f, 0x0f, 0x07,
+0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x3f, 0x7f,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7f,
+0x3f, 0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x73, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x7b,
+0x7b, 0x7b, 0x7b, 0x3b, 0x1b, 0x1b, 0x1b, 0x1b,
+0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x33,
+0x30, 0x1c, 0x1e, 0x36, 0x33, 0x33, 0x1b, 0x1e,
+0x0e, 0x03, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x3f, 0x7f,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7f,
+0x3f, 0x1e, 0x0c, 0x7f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x3f, 0x7f,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x7f,
+0x3f, 0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+0x0e, 0x07, 0x7f, 0x7f, 0x07, 0x0e, 0x0c, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+0x1c, 0x38, 0x7f, 0x7f, 0x38, 0x1c, 0x0c, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x60, 0x60, 0x60, 0x60, 0x7f, 0x7f, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x12, 0x33, 0x7f, 0x7f, 0x33, 0x12, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x1e, 0x3f, 0x7f, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x7f, 0x3f, 0x1e, 0x0c, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e,
+0x1e, 0x1e, 0x1e, 0x1e, 0x0c, 0x0c, 0x0c, 0x00,
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x33, 0x7f, 0x7f, 0x33, 0x33, 0x7f, 0x7f, 0x33,
+0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x1e, 0x3f,
+0x73, 0x70, 0x38, 0x1c, 0x06, 0x03, 0x03, 0x73,
+0x3f, 0x1e, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xdb, 0xdb,
+0x76, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x33, 0x36,
+0x66, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0xc0, 0xc0, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b,
+0x31, 0x1b, 0x0e, 0x18, 0x33, 0x61, 0x61, 0x63,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0xc0, 0x80, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c,
+0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18,
+0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+0x30, 0x10, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c,
+0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+0x06, 0x04, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0x33, 0x1e, 0x7f, 0x1e, 0x33, 0x61,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+0x0c, 0x0c, 0x7f, 0x7f, 0x0c, 0x0c, 0x0c, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x0c, 0x0c, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18,
+0x30, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x61, 0x6d, 0x6d, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x3c,
+0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x01, 0x03, 0x07, 0x0e, 0x1c, 0x38, 0x70,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x01, 0x03, 0x0e, 0x0f, 0x03, 0x01, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x33,
+0x33, 0x33, 0x33, 0x63, 0x7f, 0x7f, 0x03, 0x03,
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x60, 0x60, 0x7e, 0x7f, 0x03, 0x01, 0x01, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x60, 0x60, 0x6e, 0x7f, 0x73, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f,
+0x01, 0x03, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x33, 0x1e, 0x3f, 0x73, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x73, 0x3f, 0x1d, 0x01, 0x01, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00,
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00,
+0x0c, 0x0c, 0x04, 0x08, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c,
+0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x3e, 0x3e, 0x00, 0x00, 0x3e, 0x3e, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+0x18, 0x0c, 0x06, 0x03, 0x01, 0x03, 0x06, 0x0c,
+0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x03, 0x07, 0x0e, 0x0c, 0x0c, 0x00,
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x61, 0x61, 0x67, 0x6f, 0x69, 0x69, 0x6f, 0x67,
+0x60, 0x3f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e,
+0x33, 0x61, 0x61, 0x61, 0x61, 0x7f, 0x7f, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f,
+0x61, 0x61, 0x61, 0x7f, 0x7f, 0x61, 0x61, 0x61,
+0x7f, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f,
+0x63, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x63,
+0x7f, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x60, 0x60, 0x60, 0x7e, 0x7e, 0x60, 0x60, 0x60,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x60, 0x60, 0x60, 0x7e, 0x7e, 0x60, 0x60, 0x60,
+0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x60, 0x60, 0x60, 0x67, 0x67, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x61, 0x7f, 0x7f, 0x61, 0x61, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x67,
+0x6e, 0x7c, 0x78, 0x70, 0x78, 0x7c, 0x6e, 0x67,
+0x63, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60,
+0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x73, 0x73, 0x7f, 0x7f, 0x6d, 0x6d, 0x61, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x71,
+0x71, 0x79, 0x79, 0x6d, 0x6d, 0x67, 0x67, 0x63,
+0x63, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f,
+0x63, 0x61, 0x61, 0x63, 0x7f, 0x7e, 0x60, 0x60,
+0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x61, 0x61, 0x61, 0x61, 0x67, 0x77,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f,
+0x63, 0x61, 0x61, 0x63, 0x7f, 0x7e, 0x63, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x70, 0x38, 0x1c, 0x06, 0x03, 0x03, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x33,
+0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d,
+0x7f, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x33, 0x33, 0x1e, 0x0c, 0x0c, 0x1e, 0x33, 0x33,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x61, 0x33, 0x1e, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x01, 0x03, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0x60,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x1e, 0x1e, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60,
+0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06,
+0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e,
+0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
+0x06, 0x06, 0x06, 0x1e, 0x1e, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x0c, 0x1e, 0x33, 0x40, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x00, 0x00, 0x1c, 0x0c, 0x06, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x3e, 0x3f, 0x01, 0x3f, 0x7f, 0x61, 0x61,
+0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60,
+0x60, 0x6e, 0x7f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x7f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1e, 0x3f, 0x73, 0x60, 0x60, 0x60, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x1d, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x7f, 0x7f, 0x70,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x1f,
+0x18, 0x18, 0x7f, 0x7f, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x01, 0x03, 0x3f, 0x3e, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60,
+0x60, 0x6e, 0x7f, 0x73, 0x61, 0x61, 0x61, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x00,
+0x00, 0x3c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00,
+0x00, 0x1e, 0x1e, 0x06, 0x06, 0x06, 0x06, 0x06,
+0x06, 0x06, 0x06, 0x0e, 0x3c, 0x38, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60,
+0x60, 0x63, 0x66, 0x6c, 0x78, 0x70, 0x7c, 0x66,
+0x63, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x6d, 0x7f, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d,
+0x6d, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x6e, 0x7f, 0x73, 0x61, 0x61, 0x61, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x6e, 0x7f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x7f, 0x6e, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1d, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x6f, 0x7f, 0x78, 0x70, 0x60, 0x60, 0x60,
+0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1e, 0x3f, 0x61, 0x70, 0x3f, 0x03, 0x61,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
+0x18, 0x3f, 0x3f, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x1f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x33,
+0x1e, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0x61, 0x61, 0x6d, 0x6d, 0x7f, 0x7f,
+0x73, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0x73, 0x3f, 0x1e, 0x0c, 0x1e, 0x3f,
+0x73, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x01, 0x01, 0x3f, 0x3e, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7f, 0x7f, 0x03, 0x06, 0x0c, 0x18, 0x30,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x0c, 0x07, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c,
+0x06, 0x06, 0x06, 0x06, 0x06, 0x03, 0x06, 0x06,
+0x06, 0x06, 0x06, 0x0c, 0x38, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6d, 0x47,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+0x1c, 0x3e, 0x77, 0x77, 0xe3, 0xe3, 0xe3, 0xff,
+0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x73,
+0x3f, 0x1e, 0x0c, 0x26, 0x1c, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x18,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x7f, 0x7f, 0x70,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x21,
+0x00, 0x3e, 0x3f, 0x01, 0x3f, 0x7f, 0x61, 0x61,
+0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x00, 0x3e, 0x3f, 0x01, 0x3f, 0x7f, 0x61, 0x61,
+0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x06,
+0x00, 0x3e, 0x3f, 0x01, 0x3f, 0x7f, 0x61, 0x61,
+0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1e, 0x33, 0x33, 0x1e,
+0x00, 0x3e, 0x3f, 0x01, 0x3f, 0x7f, 0x61, 0x61,
+0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1e, 0x3f, 0x73, 0x60, 0x60, 0x60, 0x73,
+0x3f, 0x1e, 0x0c, 0x26, 0x1c, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x21,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x7f, 0x7f, 0x70,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x7f, 0x7f, 0x70,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x06,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x7f, 0x7f, 0x70,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x00, 0x3c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x21,
+0x00, 0x3c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x06,
+0x00, 0x3c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x33, 0x33, 0x00, 0x0c, 0x1e,
+0x33, 0x61, 0x61, 0x61, 0x61, 0x7f, 0x7f, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x1e, 0x33, 0x33, 0x1e, 0x0c, 0x1e,
+0x33, 0x61, 0x61, 0x61, 0x61, 0x7f, 0x7f, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x07, 0x0c, 0x18, 0x00, 0x7f, 0x7f,
+0x60, 0x60, 0x60, 0x7e, 0x7e, 0x60, 0x60, 0x60,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x77, 0x7f, 0x0c, 0x7c, 0xff, 0xcc, 0xcc,
+0xff, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0,
+0xc0, 0xc0, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x3f,
+0x6c, 0xcc, 0xcc, 0xcf, 0xcf, 0xfc, 0xfc, 0xcc,
+0xcf, 0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0xc0,
+0xc0, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x21,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x06,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1e, 0x21,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x06,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x01, 0x01, 0x3f, 0x3e, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x33, 0x33, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x33, 0x33, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+0x0c, 0x1e, 0x3f, 0x73, 0x60, 0x60, 0x60, 0x73,
+0x3f, 0x1e, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1f,
+0x31, 0x31, 0x30, 0x7c, 0x30, 0x30, 0x30, 0x31,
+0x7f, 0x6e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x61,
+0x61, 0x61, 0x33, 0x1e, 0x7f, 0x7f, 0x0c, 0x7f,
+0x7f, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x80, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f,
+0x63, 0x61, 0x61, 0x63, 0x7f, 0x7e, 0x61, 0x63,
+0x6f, 0x63, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+0x80, 0x00, 0x07, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x7f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc,
+0xcc, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x80, 0xc0,
+0xc0, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x18,
+0x00, 0x3e, 0x3f, 0x01, 0x3f, 0x7f, 0x61, 0x61,
+0x7f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x18,
+0x00, 0x3c, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x18,
+0x00, 0x1e, 0x3f, 0x73, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0c, 0x18,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x3f, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3f, 0x46,
+0x00, 0x6e, 0x7f, 0x73, 0x61, 0x61, 0x61, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x18, 0x3f, 0x46, 0x00, 0x61, 0x71,
+0x71, 0x79, 0x79, 0x6d, 0x6d, 0x67, 0x67, 0x63,
+0x63, 0x61, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x03,
+0x3f, 0x63, 0x63, 0x3f, 0x00, 0x7f, 0x7f, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x3b,
+0x31, 0x31, 0x3b, 0x1f, 0x00, 0x3f, 0x3f, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x00, 0x0c, 0x0c, 0x1c,
+0x38, 0x70, 0x61, 0x73, 0x3f, 0x1e, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7f, 0x7f, 0x60, 0x60, 0x60, 0x60,
+0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7f, 0x7f, 0x03, 0x03, 0x03, 0x03,
+0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x18, 0x18,
+0x19, 0x1b, 0x07, 0x0e, 0x1c, 0x3b, 0x74, 0xe0,
+0xc0, 0x83, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x40, 0xc0, 0xc0, 0x80, 0x00, 0x00,
+0x00, 0x80, 0xc0, 0xc0, 0x80, 0x00, 0xc0, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x18, 0x18,
+0x19, 0x1b, 0x07, 0x0e, 0x1c, 0x39, 0x73, 0xe5,
+0xcd, 0x8f, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x40, 0xc0, 0xc0, 0x80, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x00, 0x0c, 0x0c, 0x0c,
+0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x19, 0x33, 0x66, 0x33, 0x19, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x66, 0x33, 0x19, 0x33, 0x66, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x84, 0x42, 0x21, 0x10, 0x08, 0x84,
+0x42, 0x21, 0x10, 0x08, 0x84, 0x42, 0x21, 0x10,
+0x08, 0x84, 0x42, 0x21, 0x10, 0x08, 0x00, 0x00,
+0x00, 0x80, 0x40, 0x00, 0x00, 0x00, 0x80, 0x40,
+0x00, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00,
+0x80, 0x40, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x40, 0x80,
+0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80,
+0x40, 0x80, 0x40, 0x80, 0x40, 0x80, 0x40, 0x80,
+0x40, 0x80, 0x7b, 0xf7, 0xef, 0xde, 0xbd, 0x7b,
+0xf7, 0xef, 0xde, 0xbd, 0x7b, 0xf7, 0xef, 0xde,
+0xbd, 0x7b, 0xf7, 0xef, 0xde, 0xbd, 0xc0, 0x80,
+0x40, 0xc0, 0xc0, 0xc0, 0x80, 0x40, 0xc0, 0xc0,
+0xc0, 0x80, 0x40, 0xc0, 0xc0, 0xc0, 0x80, 0x40,
+0xc0, 0xc0, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0xfc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0xfc, 0xfc, 0x0c, 0x0c, 0xfc, 0xfc, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0xf3, 0xf3, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xfc, 0xfc, 0x0c, 0x0c, 0xfc, 0xfc, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0xf3, 0xf3, 0x03, 0x03, 0xf3, 0xf3, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0xff, 0x03, 0x03, 0xf3, 0xf3, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0xf3, 0xf3, 0x03, 0x03, 0xff, 0xff, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0xfc, 0xfc, 0x0c, 0x0c, 0xfc, 0xfc, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xfc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0xff, 0xff, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x70, 0x70, 0x7f, 0x7f, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x7f, 0x7f, 0x70, 0x70, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0xf3, 0xf3, 0x00, 0x00, 0xff, 0xff, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0xff, 0x00, 0x00, 0xf3, 0xf3, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x70, 0x70, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0xf3, 0xf3, 0x00, 0x00, 0xf3, 0xf3, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0f, 0x0f, 0x0c, 0x0c, 0x0f, 0x0f, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x7f, 0x7f, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0xf3, 0xf3, 0x73, 0x73, 0x73, 0x73,
+0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
+0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0xc0, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x19, 0x3f, 0x77, 0x63, 0x63, 0x63, 0x77,
+0x3f, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7f,
+0x63, 0x63, 0x62, 0x66, 0x67, 0x63, 0x61, 0x61,
+0x6f, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x61, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
+0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
+0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x3f,
+0x18, 0x0c, 0x06, 0x03, 0x03, 0x06, 0x0c, 0x18,
+0x3f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0xc0, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0xc0, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x1f, 0x3f, 0x76, 0x63, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x00,
+0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x73,
+0x7f, 0x6d, 0x40, 0x40, 0xc0, 0xc0, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x70, 0xf1, 0x19, 0x0b, 0x0e, 0x0e, 0x0c, 0x0c,
+0x0c, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f,
+0x0c, 0x3f, 0x7f, 0x61, 0x61, 0x7f, 0x3f, 0x0c,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f,
+0x73, 0x61, 0x61, 0x7f, 0x7f, 0x61, 0x61, 0x73,
+0x3f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e,
+0x33, 0x61, 0x61, 0x61, 0x61, 0x61, 0x21, 0x33,
+0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x3f, 0x70, 0x30, 0x18,
+0x0e, 0x3f, 0x73, 0x63, 0x63, 0x63, 0x63, 0x63,
+0x63, 0x76, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33,
+0x7b, 0xcc, 0xcc, 0xcc, 0xcc, 0x7f, 0x77, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0,
+0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x03, 0x1f, 0x37, 0x67, 0x6d, 0x6d, 0x79, 0x7b,
+0x3e, 0x30, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x3f,
+0x70, 0x60, 0x60, 0x7f, 0x7f, 0x60, 0x60, 0x70,
+0x3f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x3f, 0x33,
+0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
+0x61, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
+0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f,
+0x00, 0x00, 0x00, 0x7f, 0x7f, 0x00, 0x00, 0x00,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+0x0c, 0x0c, 0x7f, 0x7f, 0x0c, 0x0c, 0x0c, 0x00,
+0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+0x1c, 0x07, 0x01, 0x07, 0x1c, 0x70, 0x00, 0x7f,
+0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+0x0e, 0x38, 0x60, 0x38, 0x0e, 0x03, 0x00, 0x7f,
+0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x80, 0x00, 0x80, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0f, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00,
+0x00, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc,
+0xcc, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+0x0c, 0x0c, 0x00, 0x7f, 0x7f, 0x00, 0x0c, 0x0c,
+0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xf8, 0xcc,
+0xcf, 0xc7, 0x00, 0x00, 0x78, 0xf8, 0xcc, 0xcf,
+0xc7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00, 0x00,
+0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x33, 0x33,
+0x33, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03,
+0x03, 0x03, 0x63, 0x63, 0x73, 0x73, 0x1b, 0x0f,
+0x0f, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x33,
+0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x13,
+0x03, 0x02, 0x0c, 0x1f, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x3f, 0x3f,
+0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
+0x3f, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x35,
+0x31, 0x34, 0x6f, 0x65, 0x6d, 0x00, 0x00, 0x00,
+0xe8, 0x01, 0x34, 0x00, 0x56, 0x53, 0x5f, 0x56,
+0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x49,
+0x4e, 0x46, 0x4f, 0x00, 0xbd, 0x04, 0xef, 0xfe,
+0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x03, 0x00,
+0x67, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x03, 0x00,
+0x67, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x7a, 0x01, 0x00, 0x00, 0x53, 0x74, 0x72, 0x69,
+0x6e, 0x67, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e,
+0x66, 0x6f, 0x00, 0x00, 0x66, 0x01, 0x00, 0x00,
+0x30, 0x34, 0x30, 0x39, 0x30, 0x34, 0x45, 0x34,
+0x00, 0x00, 0x00, 0x00, 0x27, 0x00, 0x17, 0x00,
+0x43, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x4e,
+0x61, 0x6d, 0x65, 0x00, 0x4d, 0x69, 0x63, 0x72,
+0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f,
+0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f,
+0x6e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x2b, 0x00,
+0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63,
+0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x00,
+0x38, 0x35, 0x31, 0x34, 0x2f, 0x61, 0x20, 0x28,
+0x31, 0x30, 0x32, 0x34, 0x78, 0x37, 0x36, 0x38,
+0x29, 0x20, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75,
+0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x65, 0x72,
+0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x66, 0x6f,
+0x6e, 0x74, 0x00, 0x00, 0x16, 0x00, 0x06, 0x00,
+0x46, 0x69, 0x6c, 0x65, 0x56, 0x65, 0x72, 0x73,
+0x69, 0x6f, 0x6e, 0x00, 0x33, 0x2e, 0x31, 0x30,
+0x00, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x09, 0x00,
+0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
+0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00,
+0x4f, 0x45, 0x4d, 0x46, 0x4f, 0x4e, 0x54, 0x53,
+0x00, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x27, 0x00,
+0x4c, 0x65, 0x67, 0x61, 0x6c, 0x43, 0x6f, 0x70,
+0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x00, 0x00,
+0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
+0x74, 0x20, 0xa9, 0x20, 0x4d, 0x69, 0x63, 0x72,
+0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f,
+0x72, 0x70, 0x2e, 0x20, 0x31, 0x39, 0x39, 0x31,
+0x2d, 0x31, 0x39, 0x39, 0x32, 0x00, 0x00, 0x00,
+0x24, 0x00, 0x0c, 0x00, 0x4f, 0x72, 0x69, 0x67,
+0x69, 0x6e, 0x61, 0x6c, 0x46, 0x69, 0x6c, 0x65,
+0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00, 0x00,
+0x38, 0x35, 0x31, 0x34, 0x4f, 0x45, 0x4d, 0x2e,
+0x46, 0x4f, 0x4e, 0x00, 0x39, 0x00, 0x29, 0x00,
+0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x4e,
+0x61, 0x6d, 0x65, 0x00, 0x4d, 0x69, 0x63, 0x72,
+0x6f, 0x73, 0x6f, 0x66, 0x74, 0xae, 0x20, 0x57,
+0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x28, 0x54,
+0x4d, 0x29, 0x20, 0x4f, 0x70, 0x65, 0x72, 0x61,
+0x74, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x79, 0x73,
+0x74, 0x65, 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x1a, 0x00, 0x06, 0x00, 0x50, 0x72, 0x6f, 0x64,
+0x75, 0x63, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69,
+0x6f, 0x6e, 0x00, 0x00, 0x33, 0x2e, 0x31, 0x30,
+0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+0x56, 0x61, 0x72, 0x46, 0x69, 0x6c, 0x65, 0x49,
+0x6e, 0x66, 0x6f, 0x00, 0x14, 0x00, 0x04, 0x00,
+0x54, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74,
+0x69, 0x6f, 0x6e, 0x00, 0x09, 0x04, 0xe4, 0x04,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
diff --git a/private/ntos/nthals/halppc/ppc/bblrastz.h b/private/ntos/nthals/halppc/ppc/bblrastz.h
new file mode 100644
index 000000000..839b9ff56
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/bblrastz.h
@@ -0,0 +1,113 @@
+
+#ifndef _H_BBLRASTZ
+#define _H_BBLRASTZ
+
+/******************************************************************************
+* *
+* Define the BBL rasterizer register address range: *
+* *
+******************************************************************************/
+
+#define BBL_REGISTER_ADDR_RANGE_START 0x0A000000
+
+
+/******************************************************************************
+* *
+* Define the BBL rasterizer register offsets: *
+* *
+******************************************************************************/
+
+#define BBL_CMD_DATA_REG 0x0000
+#define BBL_STATUS_REG 0x0000
+#define BBL_CNTL_REG 0x0040
+#define BBL_FG_REG 0x0044
+#define BBL_BG_REG 0x0048
+#define BBL_PLANE_MASK_REG 0x0050
+#define BBL_LINE_STYLE_DASH_1234_REG 0x0054
+#define BBL_LINE_STYLE_DASH_5678_REG 0x0058
+#define BBL_SCISSOR_ENABLE_REG 0x007C
+#define BBL_WIN_ORIGIN_OFFSETS_REG 0x0080
+#define BBL_WID_CLIP_TEST_REG 0x0084
+#define BBL_PIXEL_MASK_REG 0x00A0
+#define BBL_INTR_ENABLE_STATUS_REG 0x00B8
+#define BBL_CONFIG_REG 0x00BC
+#define BBL_RAMDAC_C0_C1_0_0_REG 0x00C0
+#define BBL_RAMDAC_C0_C1_0_1_REG 0x00C4
+#define BBL_RAMDAC_C0_C1_1_0_REG 0x00C8
+#define BBL_RAMDAC_C0_C1_1_1_REG 0x00CC
+#define BBL_RESET_CURRENT_CMD_REG 0x00D4
+
+
+/******************************************************************************
+* *
+* Define bitfields for the BBL rasterizer status register: *
+* *
+******************************************************************************/
+
+#define BBL_VERTICAL_RETRACE (1 << 0)
+#define BBL_ADAPTER_BUSY (1 << 2)
+#define BBL_CACHE_LINE_BUFFER_EMPTY (1 << 4)
+#define BBL_FREE_SPACE_SHIFT 16
+
+
+/******************************************************************************
+* *
+* Define the commands: *
+* *
+******************************************************************************/
+
+#define BBL_CMD_SHIFT 24
+#define BBL_POLYFILL_RECT_ID 0x86
+#define BBL_POLYFILL_RECT_CMD \
+ (int) (BBL_POLYFILL_RECT_ID << BBL_CMD_SHIFT)
+
+
+/******************************************************************************
+* *
+* Macro: BBL_FILL_RECT (regbase, dst_x, dst_y, width, height) *
+* caddr_t regbase; *
+* short dst_x, dst_y; *
+* unsigned short width, height; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* dst_x, dst_y - Screen coords of where to start the rect *
+* width, height - Dimensions of the rect *
+* *
+* Description: Performs a fill rectangle command to the adapter *
+* *
+******************************************************************************/
+
+#define BBL_FILL_RECT(regbase, dst_x, dst_y, width, height) \
+ BBL_SET_REG((regbase), BBL_CMD_DATA_REG, \
+ BBL_POLYFILL_RECT_CMD | 0x1); \
+ BBL_SET_REG((regbase), BBL_CMD_DATA_REG, \
+ (((unsigned short)(dst_x) << 16) | \
+ (unsigned short)(dst_y))); \
+ BBL_SET_REG((regbase), BBL_CMD_DATA_REG, \
+ (((unsigned short)(height) << 16) | \
+ (unsigned short)(width)))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_BUSY_POLL (regbase) *
+* caddr_t regbase; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* *
+* Description: Performs a busy poll on the adapter and returns when the *
+* adapter is no longer busy. In the case of a shallow bus *
+* interface FIFO on the adapter, this macro will also make *
+* sure that the FIFO is empty and that the adapter is not *
+* busy. This is a synchronous call. *
+* *
+******************************************************************************/
+
+#define BBL_BUSY_POLL(regbase) \
+ while(BBL_GET_REG((regbase), BBL_STATUS_REG) & \
+ BBL_ADAPTER_BUSY) \
+ ;
+
+
+#endif /* ! _H_BBLRASTZ */
+
diff --git a/private/ntos/nthals/halppc/ppc/bblrmdac.h b/private/ntos/nthals/halppc/ppc/bblrmdac.h
new file mode 100644
index 000000000..b5f1176ff
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/bblrmdac.h
@@ -0,0 +1,802 @@
+
+#ifndef _H_BBLRMDAC
+#define _H_BBLRMDAC
+
+/******************************************************************************
+* *
+* Define the ramdac register addresses: *
+* *
+******************************************************************************/
+
+#define BBL_RAMDAC_CONFIG_LOW_REG 0x0001
+#define BBL_RAMDAC_CONFIG_HIGH_REG 0x0002
+#define BBL_RAMDAC_RGB_FORMAT_REG 0x0003
+#define BBL_RAMDAC_MONITOR_ID_REG 0x0005
+#define BBL_RAMDAC_VRAM_MASK_REG 0x0006
+#define BBL_RAMDAC_WID_OL_MASK_REG 0x0007
+#define BBL_RAMDAC_PLL_REF_REG 0x0010
+#define BBL_RAMDAC_PLL_VCO_DIVIDER_REG 0x0011
+#define BBL_RAMDAC_CRT_CNTL_REG 0x0012
+#define BBL_RAMDAC_HORIZONTAL_TOTAL_LOW_REG 0x0013
+#define BBL_RAMDAC_HORIZONTAL_TOTAL_HIGH_REG 0x0014
+#define BBL_RAMDAC_HORIZONTAL_DISPLAY_END_LOW_REG 0x0015
+#define BBL_RAMDAC_HORIZONTAL_DISPLAY_END_HIGH_REG 0x0016
+#define BBL_RAMDAC_HSYNC_START_LOW_REG 0x0017
+#define BBL_RAMDAC_HSYNC_START_HIGH_REG 0x0018
+#define BBL_RAMDAC_HSYNC_END1_LOW_REG 0x0019
+#define BBL_RAMDAC_HSYNC_END1_HIGH_REG 0x001A
+#define BBL_RAMDAC_HSYNC_END2_LOW_REG 0x001B
+#define BBL_RAMDAC_HSYNC_END2_HIGH_REG 0x001C
+#define BBL_RAMDAC_VERTICAL_COUNT_LOW_REG 0x001D
+#define BBL_RAMDAC_VERTICAL_COUNT_HIGH_REG 0x001E
+#define BBL_RAMDAC_VERTICAL_DISPLAY_LOW_REG 0x001F
+#define BBL_RAMDAC_VERTICAL_DISPLAY_HIGH_REG 0x0020
+#define BBL_RAMDAC_VERTICAL_SYNC_START_LOW_REG 0x0021
+#define BBL_RAMDAC_VERTICAL_SYNC_START_HIGH_REG 0x0022
+#define BBL_RAMDAC_VERTICAL_SYNC_END_LOW_REG 0x0023
+#define BBL_RAMDAC_VERTICAL_SYNC_END_HIGH_REG 0x0024
+#define BBL_RAMDAC_ICON_CURSOR_CNTL_REG 0x0030
+#define BBL_RAMDAC_ICON_CURSOR_HOTSPOT_X_REG 0x0032
+#define BBL_RAMDAC_ICON_CURSOR_HOTSPOT_Y_REG 0x0033
+#define BBL_RAMDAC_CURSOR_X_POS_LOW_REG 0x0034
+#define BBL_RAMDAC_CURSOR_X_POS_HIGH_REG 0x0035
+#define BBL_RAMDAC_CURSOR_Y_POS_LOW_REG 0x0036
+#define BBL_RAMDAC_CURSOR_Y_POS_HIGH_REG 0x0037
+#define BBL_RAMDAC_CURSOR_BLINK_RATE_REG 0x0043
+#define BBL_RAMDAC_CURSOR_BLINK_DUTY_CYCLE_REG 0x0044
+#define BBL_RAMDAC_ICON_CURSOR_RAM_START_ADDR 0x0100
+#define BBL_RAMDAC_ICON_CURSOR_RAM_END_ADDR 0x04FF
+#define BBL_RAMDAC_WAT_START_ADDR 0x0500
+#define BBL_RAMDAC_WAT_END_ADDR 0x051F
+#define BBL_RAMDAC_FB_LUT_START_ADDR 0x0600
+#define BBL_RAMDAC_FB_LUT_END_ADDR 0x09FF
+#define BBL_RAMDAC_FB_LUT_0_START_ADDR 0x0600
+#define BBL_RAMDAC_FB_LUT_0_END_ADDR 0x06FF
+#define BBL_RAMDAC_CURSOR_LUT_0_START_ADDR 0x0A10
+#define BBL_RAMDAC_CURSOR_LUT_0_END_ADDR 0x0A12
+
+
+/******************************************************************************
+* *
+* Define the frame buffer look up tables and length: *
+* *
+******************************************************************************/
+
+#define BBL_RAMDAC_FB_LUT_0 0
+#define BBL_RAMDAC_FB_LUT_LENGTH 256
+
+
+/******************************************************************************
+* *
+* Define the cursor colormaps lengths: *
+* *
+******************************************************************************/
+
+#define BBL_RAMDAC_CURSOR_LUT_0 0
+#define BBL_RAMDAC_CURSOR_LUT_LENGTH 4
+
+
+/******************************************************************************
+* *
+* Define the cursor pixmap dimensions: *
+* *
+******************************************************************************/
+
+#define BBL_RAMDAC_CURSOR_RAM_LENGTH 1024
+#define BBL_RAMDAC_ICON_CURSOR_WIDTH 64
+#define BBL_RAMDAC_ICON_CURSOR_HEIGHT 64
+#define BBL_RAMDAC_ICON_CURSOR_DEPTH 2
+
+
+/******************************************************************************
+* *
+* Define the icon cursor control register bitfields: *
+* *
+******************************************************************************/
+
+#define BBL_DISABLE_ICON_CURSOR_DISPLAY (0 << 0)
+#define BBL_ENABLE_ICON_CURSOR_DISPLAY (1 << 0)
+#define BBL_DISABLE_ICON_CURSOR_BLINK (0 << 1)
+#define BBL_ENABLE_ICON_CURSOR_BLINK (1 << 1)
+
+
+/******************************************************************************
+* *
+* Define the monitor ID register bitfields: *
+* *
+******************************************************************************/
+
+#define BBL_RAMDAC_MONITOR_ID_CABLE_ID_MASK 0x0F
+#define BBL_RAMDAC_MONITOR_ID_DIP_SWITCH_MASK 0xF0
+
+
+/******************************************************************************
+* *
+* Define the pixel mask bitfields: *
+* *
+******************************************************************************/
+
+#define BBL_DEFAULT_VRAM_PIXEL_MASK_VALUE 0xFF
+#define BBL_DEFAULT_WID_OL_PIXEL_MASK_VALUE 0x0F
+
+
+/******************************************************************************
+* *
+* Define the WAT table entry information and length: *
+* *
+******************************************************************************/
+
+#define BBL_RAMDAC_WAT_LENGTH 16
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_RAMDAC_ADDRESS_REGS (regbase, address) *
+* caddr_t regbase; *
+* unsigned short address; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* address - RAMDAC address *
+* *
+* Description: Sets the address pointer in the RAMDAC to point *
+* to the "address" parameter. This is used to read and write *
+* RAMDAC registers, look up tables, and any other *
+* memory area on the RAMDAC chip. *
+* *
+******************************************************************************/
+
+#define BBL_SET_RAMDAC_ADDRESS_REGS(regbase, address) \
+ BBL_EIEIO; \
+ BBL_SET_REG ((regbase), BBL_RAMDAC_C0_C1_0_0_REG, \
+ (((volatile unsigned long)(address) & 0x000000FF) << 24)); \
+ BBL_SET_REG ((regbase), BBL_RAMDAC_C0_C1_1_0_REG, \
+ (((volatile unsigned long)(address) & 0x0000FF00) << 16)); \
+ BBL_EIEIO
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_RAMDAC_DATA_NON_LUT (regbase, data) *
+* caddr_t regbase; *
+* unsigned char data; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* data - Data to be written to the RAMDAC *
+* *
+* Description: Writes data to a RAMDAC register. *
+* *
+******************************************************************************/
+
+#define BBL_SET_RAMDAC_DATA_NON_LUT(regbase, data) \
+ BBL_SET_REG ((regbase), BBL_RAMDAC_C0_C1_0_1_REG, \
+ (((volatile unsigned long)(data) & 0xFF) << 24))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_GET_RAMDAC_DATA_NON_LUT (regbase) *
+* caddr_t regbase; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* *
+* Description: Reads register data from the RAMDAC. *
+* *
+* Returns: This is RHS macro which expands to the data read from *
+* the RAMDAC *
+* *
+******************************************************************************/
+
+#define BBL_GET_RAMDAC_DATA_NON_LUT(regbase) \
+ (unsigned char) \
+ (BBL_GET_REG ((regbase), BBL_RAMDAC_C0_C1_0_1_REG))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_RAMDAC_DATA_LUT (regbase, data) *
+* caddr_t regbase; *
+* unsigned char data; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* data - Data to be written to the RAMDAC *
+* *
+* Description: Writes data to a RAMDAC lookup table. *
+* *
+******************************************************************************/
+
+#define BBL_SET_RAMDAC_DATA_LUT(regbase, data) \
+ BBL_SET_REG ((regbase), BBL_RAMDAC_C0_C1_1_1_REG, \
+ (((volatile unsigned long)(data) & 0x000000FF) << 24))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_GET_RAMDAC_DATA_LUT (regbase) *
+* caddr_t regbase; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* *
+* Description: Reads lookup table data from the RAMDAC. *
+* *
+* Returns: This is a RHS macro which expands to the data read from the *
+* RAMDAC *
+* *
+******************************************************************************/
+
+#define BBL_GET_RAMDAC_DATA_LUT(regbase) \
+ (unsigned char) \
+ (BBL_GET_REG ((regbase), BBL_RAMDAC_C0_C1_1_1_REG))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_16BIT_RAMDAC_REG (regbase, data) *
+* caddr_t regbase; *
+* unsigned short data; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* data - 16 bit value to write to a 16bit RAMDAC register *
+* *
+* Description: Writes two consecutive 8bit (high/low) RAMDAC registers with *
+* the 16bit data value passed in. *
+* *
+******************************************************************************/
+
+#define BBL_SET_16BIT_RAMDAC_REG(regbase, data) \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), ((data) & 0x00FF)); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), (((data) & 0xFF00) >> 8))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_PLL_REF_REG (regbase, frequency) *
+* caddr_t regbase; *
+* unsigned short frequency; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* frequency - RAMDAC oscillator is running at *
+* *
+* Description: Writes the frequency value to the RAMDAC PLL reference *
+* register. First the frequency value has to be modified to *
+* match what the hardware expects. This is a simple division *
+* by 2, therefore the frequency value passed in should be a *
+* multiple of 2. *
+* *
+******************************************************************************/
+
+#define BBL_SET_PLL_REF_REG(regbase, frequency) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_PLL_REF_REG); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), \
+ ((frequency >> 1) & 0x1F))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_PLL_VCO_DIVIDER_REG (regbase, frequency) *
+* caddr_t regbase; *
+* unsigned short frequency; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* frequency - Drives the pixel clock and VRAM speed *
+* (THIS VALUE IS MULTIPLIED BY 100 !!!) *
+* *
+* Description: Writes the frequency value to the RAMDAC PLL VCO Divider *
+* register. First the frequency value has to be modified to *
+* match what the hardware expects. The register is an 8 bit *
+* register where the upper 2 bits determine the frequency *
+* range and the lower 6 bits indicate a frequency in that *
+* range. The following table illustrates this: *
+* *
+* 7 6 5 4 3 2 1 0 *
+* +---+---+---+---+---+---+---+---+ *
+* | DF | VIDEO COUNT VALUE | *
+* +---+---+---+---+---+---+---+---+ *
+* | 0 | 0 | (4 x VF) - 65 | *
+* +---+---+---+---+---+---+---+---+ *
+* | 0 | 1 | (2 x VF) - 65 | *
+* +---+---+---+---+---+---+---+---+ *
+* | 1 | 0 | VF - 65 | *
+* +---+---+---+---+---+---+---+---+ *
+* | 1 | 1 | (VF / 2) - 65 | *
+* +---+---+---+---+---+---+---+---+ *
+* *
+* Where: *
+* *
+* 7-6 DF = Desired Frequency Range *
+* = 0 0 16.25 MHZ - 32.0 MHZ in 0.25 MHZ steps *
+* = 0 1 32.5 MHZ - 64.0 MHZ in 0.5 MHZ steps *
+* = 1 0 65.0 MHZ - 128.0 MHZ in 1.0 MHZ steps *
+* = 1 1 130.0 MHZ - 200.0 MHZ in 2.0 MHZ steps *
+* *
+* Notes: The frequency parameter passed in must be multiplied by 100 *
+* before calling this macro! This eliminates the use of any *
+* floating point. *
+* *
+******************************************************************************/
+
+#define BBL_SET_PLL_VCO_DIVIDER_REG(regbase, frequency) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_PLL_VCO_DIVIDER_REG); \
+ if((frequency) > 12800){ \
+ BBL_SET_RAMDAC_DATA_NON_LUT((regbase), \
+ (0xC0 | (((frequency) - 13000) / 200))); \
+ }else if((frequency) > 6400){ \
+ BBL_SET_RAMDAC_DATA_NON_LUT((regbase), \
+ (0x80 | (((frequency) - 6500) / 100))); \
+ }else if((frequency) > 3200){ \
+ BBL_SET_RAMDAC_DATA_NON_LUT((regbase), \
+ (0x40 | (((frequency) - 3250) / 50))); \
+ }else{ /* frequency <= 3200 */ \
+ BBL_SET_RAMDAC_DATA_NON_LUT((regbase), \
+ (0x00 | (((frequency) - 1625) / 25))); \
+ }
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_CRT_CNTL_REG (regbase, control_bits) *
+* caddr_t regbase; *
+* unsigned char control_bits; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* control_bits - Data to write to the 8bit RAMDAC CRT control *
+* register *
+* *
+* Description: Writes the control_bits value into the RAMDAC *
+* CRT control register. *
+* *
+******************************************************************************/
+
+#define BBL_SET_CRT_CNTL_REG(regbase, control_bits) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_CRT_CNTL_REG); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), (control_bits))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_HORIZONTAL_TOTAL_REG (regbase, num_pixels) *
+* caddr_t regbase; *
+* unsigned short num_pixels; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* num_pixels - The number of pixels for the HORIZONTAL TOTAL *
+* register. This value must be a multiple of 4 and *
+* range from 0-2044. *
+* *
+* Description: Writes the num_pixels value into the RAMDAC high/low *
+* HORIZONTAL TOTAL registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_HORIZONTAL_TOTAL_REG(regbase, num_pixels) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_HORIZONTAL_TOTAL_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((num_pixels) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_HORIZONTAL_DISPLAY_END_REG (regbase, num_pixels) *
+* caddr_t regbase; *
+* unsigned short num_pixels; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* num_pixels - The number of pixels for the HORIZONTAL DISPLAY *
+* END register. This value must be a multiple of 4 *
+* and range from 0 - 2044. *
+* *
+* Description: Writes the num_pixels value into the RAMDAC high/low *
+* HORIZONTAL DISPLAY END registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_HORIZONTAL_DISPLAY_END_REG(regbase, num_pixels) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_HORIZONTAL_DISPLAY_END_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((num_pixels) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_HORIZONTAL_SYNC_START_REG (regbase, *
+* pixel_position) *
+* caddr_t regbase; *
+* unsigned short pixel_position; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* pixel_position - Pixel position for the start of horizontal *
+* retrace. This value has to be a multiple of *
+* of 4 and range from 0 - 2044 *
+* *
+* Description: Writes the pixel_position value into the RAMDAC *
+* high/low HORIZONTAL SYNC START registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_HORIZONTAL_SYNC_START_REG(regbase, pixel_position) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_HSYNC_START_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((pixel_position) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_HORIZONTAL_SYNC_END1_REG (regbase, pixel_position) *
+* caddr_t regbase; *
+* unsigned short pixel_position; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* pixel_position - Pixel position for the end of horizontal *
+* retrace. This value has to be a multiple of *
+* of 4 and range from 0 - 2044 *
+* *
+* Description: Writes the pixel_position value into the RAMDAC *
+* high/low HORIZONTAL SYNC END1 registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_HORIZONTAL_SYNC_END1_REG(regbase, pixel_position) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_HSYNC_END1_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((pixel_position) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_HORIZONTAL_SYNC_END2_REG (regbase, pixel_position) *
+* caddr_t regbase; *
+* unsigned short pixel_position; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* pixel_position - Pixel position for the end of horizontal *
+* retrace. This value has to be a multiple of *
+* of 4 and range from 0 - 2044 *
+* *
+* Description: Writes the pixel_position value into the RAMDAC *
+* high/low HORIZONTAL SYNC END2 registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_HORIZONTAL_SYNC_END2_REG(regbase, pixel_position) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_HSYNC_END2_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((pixel_position) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_VERTICAL_TOTAL_REG (regbase, num_scan_lines) *
+* caddr_t regbase; *
+* unsigned short num_scan_lines; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* num_scan_lines - Number of scan lines per frame. This value *
+* has to range from 0 - 2047. *
+* *
+* Description: Writes the num_scan_lines value into the RAMDAC *
+* high/low VERTICAL TOTAL registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_VERTICAL_TOTAL_REG(regbase, num_scan_lines) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_VERTICAL_COUNT_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((num_scan_lines) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_VERTICAL_DISPLAY_END_REG (regbase, scan_line) *
+* caddr_t regbase; *
+* unsigned short scan_line; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* scan_line - Last visible scan line. This value has to range *
+* from 0 - 2047. *
+* *
+* Description: Writes the scan_line value into the RAMDAC *
+* high/low VERTICAL DISPLAY END registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_VERTICAL_DISPLAY_END_REG(regbase, scan_line) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_VERTICAL_DISPLAY_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((scan_line) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_VERTICAL_SYNC_START_REG (regbase, scan_line) *
+* caddr_t regbase; *
+* unsigned short scan_line; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* scan_line - Indicates which scan line the vertical sync pulse *
+* begins. This value has to range from 0 - 2047. *
+* *
+* Description: Writes the scan_line value into the RAMDAC *
+* high/low VERTICAL SYNC START registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_VERTICAL_SYNC_START_REG(regbase, scan_line) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_VERTICAL_SYNC_START_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((scan_line) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_VERTICAL_SYNC_END_REG (regbase, scan_line) *
+* caddr_t regbase; *
+* unsigned short scan_line; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* scan_line - Indicates which scan line the vertical sync pulse *
+* ends. This value has to range from 0 - 2047. *
+* *
+* Description: Writes the scan_line value into the RAMDAC *
+* high/low VERTICAL SYNC END registers *
+* *
+******************************************************************************/
+
+#define BBL_SET_VERTICAL_SYNC_END_REG(regbase, scan_line) \
+ BBL_SET_RAMDAC_ADDRESS_REGS((regbase), \
+ BBL_RAMDAC_VERTICAL_SYNC_END_LOW_REG); \
+ BBL_SET_16BIT_RAMDAC_REG ((regbase), \
+ ((scan_line) & 0x07FF))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_ICON_CURSOR_CNTL (regbase, control_bits) *
+* caddr_t regbase; *
+* unsigned char control_bits; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* control_bits - Control bits to write to the icon cursor *
+* control register *
+* *
+* Description: Writes the control_bits to the RAMDAC icon cursor control *
+* register *
+* *
+* Notes: None. *
+* *
+******************************************************************************/
+
+#define BBL_SET_ICON_CURSOR_CNTL(regbase, control_bits) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_ICON_CURSOR_CNTL_REG); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), (control_bits))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_ICON_CURSOR_PIXMAP (regbase, width, height, data) *
+* caddr_t regbase; *
+* unsigned short width, height; *
+* unsigned char *data; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* data - Pointer to the cursor pixmap in memory *
+* *
+* Description: This macro will load the icon cursor pixmap. *
+* *
+* Notes: The format of the data is as follows: *
+* *
+* +--+--+--+--+--+--+--+--+ *
+* | p0 | p1 | p2 | p3 | *
+* +--+--+--+--+--+--+--+--+ *
+* *
+* The data area must be byte aligned for the pixel data *
+* *
+******************************************************************************/
+
+#define BBL_SET_ICON_CURSOR_PIXMAP(regbase, width, height, data) \
+{ \
+ unsigned short _bbl_row, _bbl_col; \
+ unsigned char *_bbl_ptr; \
+ \
+ /* Set the RAMDAC address up for the icon cursor pixmap area */ \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_ICON_CURSOR_RAM_START_ADDR); \
+ \
+ /* Loop through the rows */ \
+ for(_bbl_row=0, _bbl_ptr=(unsigned char *)(data); \
+ _bbl_row < (height); _bbl_row++){ \
+ \
+ /* Loop through the columns 4 at a time */ \
+ for(_bbl_col=0; _bbl_col < ((width) >> 2); _bbl_col++){ \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), \
+ (*_bbl_ptr)); \
+ _bbl_ptr++; \
+ } \
+ /* If the width < 64 pixels, send the 0x00 pixel */ \
+ /* values until width == 64 pixels */ \
+ if(_bbl_col < (BBL_RAMDAC_ICON_CURSOR_WIDTH >> 2)){ \
+ for(;_bbl_col < (BBL_RAMDAC_ICON_CURSOR_WIDTH >> 2); \
+ _bbl_col++){ \
+ \
+ BBL_SET_RAMDAC_DATA_NON_LUT \
+ ((regbase), 0x00); \
+ } \
+ } \
+ } \
+ \
+ for(; _bbl_row < BBL_RAMDAC_ICON_CURSOR_HEIGHT; _bbl_row++){ \
+ for(_bbl_col=0; \
+ _bbl_col < (BBL_RAMDAC_ICON_CURSOR_WIDTH >> 2); \
+ _bbl_col++){ \
+ \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), 0x00); \
+ } \
+ } \
+}
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_CURSOR_POSITION (regbase, x_position, y_position) *
+* caddr_t regbase; *
+* unsigned short x_position, y_position; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* x_position - Gives the x position of where to put the *
+* icon cursor on the screen *
+* y_position - Gives the y position of where to put the *
+* icon cursor on the screen *
+* *
+* Description: This macro will place the current cursor *
+* at the new screen location specified by the position *
+* parameter. *
+* *
+* Notes: None. *
+* *
+******************************************************************************/
+
+#define BBL_SET_CURSOR_POSITION(regbase, x_position, y_position) \
+ /* Set the RAMDAC address register to point to the first of */ \
+ /* four cursor position registers */ \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_CURSOR_X_POS_LOW_REG); \
+ \
+ /* Write the current cursor position out to the RAMDAC */ \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), \
+ ((x_position) & 0x00FF)); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), \
+ (((x_position) & 0xFF00) >> 8)); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), \
+ ((y_position) & 0x00FF)); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), \
+ (((y_position) & 0xFF00) >> 8))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_RAMDAC_FB_PIXEL_MASK_REG (regbase, vram_mask) *
+* caddr_t regbase; *
+* unsigned char vram_mask; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* vram_mask - Mask to apply. This is used by the RAMDAC to *
+* mask out unwanted data to the screen *
+* *
+* Description: Sets the RAMDAC frame buffer pixel mask register. This *
+* should only be set during initialization time. *
+* *
+******************************************************************************/
+
+#define BBL_SET_RAMDAC_FB_PIXEL_MASK_REG(regbase, vram_mask) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_VRAM_MASK_REG); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), (vram_mask))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_SET_RAMDAC_WID_OL_PIXEL_MASK_REG (regbase, vram_mask) *
+* caddr_t regbase; *
+* unsigned char vram_mask; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* vram_mask - Mask to apply. This is used by the RAMDAC to *
+* mask out unwanted data to the screen *
+* *
+* Description: Sets the RAMDAC WID planes and overlay planes pixel mask *
+* register. This should only be set during initialization time. *
+* *
+******************************************************************************/
+
+#define BBL_SET_RAMDAC_WID_OL_PIXEL_MASK_REG(regbase, vram_mask) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_WID_OL_MASK_REG); \
+ BBL_SET_RAMDAC_DATA_NON_LUT ((regbase), (vram_mask))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_GET_MONITOR_ID (regbase, monitor_ID) *
+* caddr_t regbase; *
+* unsigned char monitor_ID; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* monitor_ID - Is the 8bit monitor ID read from the RAMDAC *
+* *
+* Description: Reads the monitor ID register from the RAMDAC. This register *
+* is composed of 4 bits from the cable ID and 4 bits from the *
+* on-card DIP switches. *
+* *
+* Returns: monitor_ID will contain the monitor ID from the RAMDAC *
+* *
+******************************************************************************/
+
+#define BBL_GET_MONITOR_ID(regbase, monitor_ID) \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_MONITOR_ID_REG); \
+ (monitor_ID) = ((unsigned char) \
+ (BBL_GET_RAMDAC_DATA_NON_LUT(regbase)))
+
+
+/******************************************************************************
+* *
+* Macro: BBL_LOAD_FB_COLOR_PALETTE (regbase, first_entry, *
+* num_entries, color_values) *
+* caddr_t regbase; *
+* unsigned long first_entry, num_entries; *
+* unsigned char *color_values; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* first_entry - First entry in color palette to update. This *
+* value must range from 0 - 255. To load the *
+* entire color palette, this should be set to 0. *
+* num_entries - Number of entries in color palette to update. *
+* This value must range from 1 - 256. To load the *
+* entire color palette, this should be set to 256 *
+* color_values - Pointer to an array of color value which are *
+* to be loaded into the color palette. The color *
+* values are unsigned chars. *
+* *
+* Description: This macro will load the Frame Buffer color palette with the *
+* colors specified *
+* *
+******************************************************************************/
+
+#define BBL_LOAD_FB_COLOR_PALETTE(regbase, first_entry, \
+ num_entries, color_values) \
+{ \
+ short _bbl_index; \
+ unsigned char *_bbl_colors; \
+ \
+ BBL_SET_RAMDAC_ADDRESS_REGS ((regbase), \
+ BBL_RAMDAC_FB_LUT_0_START_ADDR + (first_entry)); \
+ \
+ for(_bbl_index=(first_entry), \
+ _bbl_colors=(unsigned char *)(color_values); \
+ _bbl_index<((first_entry)+(num_entries)); \
+ _bbl_index++){ \
+ \
+ BBL_SET_RAMDAC_DATA_LUT ((regbase), (*_bbl_colors)); \
+ _bbl_colors++; \
+ BBL_SET_RAMDAC_DATA_LUT ((regbase), (*_bbl_colors)); \
+ _bbl_colors++; \
+ BBL_SET_RAMDAC_DATA_LUT ((regbase), (*_bbl_colors)); \
+ _bbl_colors++; \
+ \
+ } \
+}
+
+
+#endif /* _H_BBLRMDAC */
+
+
diff --git a/private/ntos/nthals/halppc/ppc/bldef.h b/private/ntos/nthals/halppc/ppc/bldef.h
new file mode 100644
index 000000000..dbd315f6b
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/bldef.h
@@ -0,0 +1,144 @@
+
+#ifndef _H_BLDEF
+#define _H_BLDEF
+
+#include "halp.h"
+
+//#include <ntos.h>
+
+//
+// Used for debugging
+//
+
+#if defined(BL_DBG) && DBG
+#define BL_DBG_PRINT DbgPrint
+#else
+#define BL_DBG_PRINT
+#endif // !DBG
+
+//
+// Define the physical memory attribites
+//
+
+#define BL_SCANLINE_LENGTH 0x1000 // 4K
+
+
+//
+// Define the register base
+//
+
+#define BL_REG_BASE (HalpBLRegisterBase)
+
+// GXT250P/GXT255P configuration register offsets
+#define BL_PCI_ID 0x00
+#define BL_PCI_CMD 0x04
+#define BL_PCI_REV_ID 0x08
+#define BL_PCI_CONFIG_0C 0x0C
+#define BL_PCI_REG_ADDR 0x10
+#define BL_PCI_FB_ADDR 0x14
+#define BL_PCI_ROM_ADDR 0x30
+#define BL_PCI_CONFIG_3C 0x3C
+#define BL_PCI_FUNC_ENABLE 0x40
+#define BL_PCI_EXT_FUNC_ENABLE 0x44
+#define BL_PCI_CONFIG_STRAP 0x48
+
+// GXT250P/GXT255P configuration register values
+// Device Vendor ID (0x00)
+#define BL_SKY_VEN_ID 0x00001014
+#define BL_SKY_DEV_ID 0x003c
+#define BL_SKY_DEV_VEN_ID ((BL_SKY_DEV_ID << 16) | (BL_SKY_VEN_ID))
+// Command register (0x04)
+#define BL_PCI_CMD_VALUE 0x00000206
+#define BL_PCI_MEM_ENABLE BL_PCI_CMD_VALUE
+// 0x0C register value
+#define BL_CONFIG_REG_0C_VALUE 0x0000f808
+// 0x3C register value
+#define BL_CONFIG_REG_3C_VALUE 0x00000100
+// Function enables register (0x40)
+//#define BL_FUNC_VALUE 0x00001a5f
+//#define BL_FUNC_VALUE 0x00001a5C
+#define BL_FUNC_VALUE 0x00001a7C
+// Define PRISM revision levels and mask for the strapping register
+#define BL_STRAP_CHIP_REV_MASK 0xf0000000
+#define BL_STRAP_CHIP_DD2 0x10000000
+#define BL_STRAP_CHIP_DD3 0x20000000
+// Extended function enables register (0x44)
+#define BL_EXT_FUNC_VALUE_DD3 0x00000003
+#define BL_EXT_FUNC_VALUE_DD2 0x00000002
+// Offset to registers from base reg virtual address
+#define BL_REG_OFFSET 0x00004000 // Second aperture
+//#define BL_REG_OFFSET 0x00000000 // First aperture
+// Size of the two memory map spaces
+#define BL_REG_MAP_SIZE 0x00008000 // 32k total
+#define BL_FB_MAP_SIZE 0x01000000 // 16meg total
+// PRISM revision ID mask (for use with the strapping register 0x48)
+#define BL_PRISM_REV_MASK 0xf0000000
+
+// Define PRISM level specific register information for PRISM critical
+// register set
+#define MAX_CFG_PER_ADAPTER 3
+// Ramdac reset constants
+#define AR07 0x03 // VGA control
+#define AR08 0x06 // DAC control
+#define AR15 0x00 // diagnostics
+#define AR16 0x00 // MISR control reg
+// PRISM clock speed settings (aux pll on ramdac)
+// The following constants set PRISM's clock to 50.11Mhz
+#define AR25 1 // aux pll ref div
+#define AR26 13 // aux pll multiplier
+#define AR27 2 // aux pll output div
+#define AR28 5 // aux pll control
+// Control high register settings
+//#define AR00 0x08000045 // sce=8bpp
+#define AR00 0x08010044 // sce=1bpp
+// Control low registers settings
+// Previous settings: C114, C117. Set byte and half word swap bits to
+// disable (little endian format)
+//#define AR01 0x013f0000
+#define AR01 0x01170000
+// Misc PRISM register settings
+#define AR03 0x00ffffff
+#define AR04 0x00000000
+#define AR05 0x00000000
+// Misc ramdac register setting/
+#define AR10 0x00 // cursor control
+#define AR11 0x00 // crosshair control1
+#define AR17 0x03 // wat 0, byte 0
+#define AR18 0x00 // wat 0, byte 1
+#define AR19 0x00 // wat 0, byte 2
+#define AR20 0x00 // wat 0, byte 3
+#define AR21 0x04 // overlay wat 0, byte 0
+#define AR22 0x00 // overlay wat 0, byte 1
+#define AR23 0x00 // overlay wat 0, byte 2
+#define AR24 0x00 // overlay wat 0, byte 3
+// V-sync/H-sync settle time (2ms)
+#define BL_VSHS_SETTLE 2000
+
+//
+// Define the monitor ID (cable and DIP switch) masks
+//
+
+#define BL_MON_ID_DIP_SWITCHES_SHIFT 16
+#define BL_MON_ID_DIP_SWITCHES_MASK \
+ (0xF << BL_MON_ID_DIP_SWITCHES_SHIFT)
+
+#define BL_MON_ID_CABLE_ID_0 0x0
+#define BL_MON_ID_CABLE_ID_H 0x1
+#define BL_MON_ID_CABLE_ID_V 0x2
+#define BL_MON_ID_CABLE_ID_1 0x3
+
+#define BL_MON_ID_CABLE_BIT_0_SHIFT 6
+#define BL_MON_ID_CABLE_BIT_0_MASK \
+ (0x3 << BL_MON_ID_CABLE_BIT_0_SHIFT)
+#define BL_MON_ID_CABLE_BIT_1_SHIFT 4
+#define BL_MON_ID_CABLE_BIT_1_MASK \
+ (0x3 << BL_MON_ID_CABLE_BIT_1_SHIFT)
+#define BL_MON_ID_CABLE_BIT_2_SHIFT 2
+#define BL_MON_ID_CABLE_BIT_2_MASK \
+ (0x3 << BL_MON_ID_CABLE_BIT_2_SHIFT)
+#define BL_MON_ID_CABLE_BIT_3_SHIFT 0
+#define BL_MON_ID_CABLE_BIT_3_MASK \
+ (0x3 << BL_MON_ID_CABLE_BIT_3_SHIFT)
+
+#endif // _H_BLDEF
+
diff --git a/private/ntos/nthals/halppc/ppc/blfw.h b/private/ntos/nthals/halppc/ppc/blfw.h
new file mode 100644
index 000000000..65d4c1230
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/blfw.h
@@ -0,0 +1,121 @@
+
+#ifndef _H_BLFW
+#define _H_BLFW
+
+extern VOID Eieio ( VOID );
+
+#define BL_EIEIO __builtin_eieio()
+#define HIGH(a) (UCHAR)(((a)>>8) & 0xff)
+#define LOW(a) (UCHAR)((a) & 0xff)
+
+/******************************************************************************
+* *
+* The following identifies the monitor structures and definitions *
+* *
+******************************************************************************/
+
+//
+// Operating modes (8bit only for ARC and HAL)
+//
+typedef enum _BL_MODES
+{
+ m640_480_8_60, // Not used
+ m800_600_8_60, // Default for 1010 ID (SS)
+ m1024_768_8_60, // Not used
+ m1024_768_8_70, // Default for H010 ID (SS)
+ m1280_1024_8_60, // Default for 0100 ID (SOG)
+ m1280_1024_8_67, // Default for 0111 ID (SS)
+ m1280_1024_8_72 // Default for V111 ID (SOG)
+} BL_MODES;
+
+#define BL_NUM_CRT_CTRL_REC_STRUCTS 7
+
+//
+// Monitor ID (cable) values
+//
+#define BL_MT_04 0x04 // 0100
+#define BL_MT_07 0x07 // 0111
+#define BL_MT_0A 0x0A // 1010
+#define BL_MT_0F 0x0F // 1111
+#define BL_MT_1A 0x1A // H010
+#define BL_MT_17 0x17 // V111
+#define BL_MT_MASK 0x1F // Monitor ID mask
+
+// CRT information structure
+typedef struct _bl_crt_ctrl_rec_t {
+ ULONG mode; // Mode for this crt ctrl rec
+ USHORT MonID; // Monitor ID
+ USHORT width; // Number of pixels along the X axis
+ USHORT height; // Number of pixels along the Y axis
+ ULONG refresh; // Refresh rate
+ UCHAR pll_ref_divide; // RAMDAC video PLL ref divide
+ UCHAR pll_mult; // RAMDAC video PLL multiplier
+ UCHAR pll_output_divide; // RAMDAC video PLL output divide
+ UCHAR pll_ctrl; // RAMDAC video PLL control
+ UCHAR sync_ctrl; // RAMDAC sync control
+ ULONG crt_cntl_reg; // PRISM DTG control reg
+ ULONG hrz_total_reg; // PRISM he reg (pixels)
+ ULONG hrz_dsp_end_reg; // PRISM hde reg (pixels)
+ ULONG hsync_start_reg; // PRISM hss reg (pixels)
+ ULONG hsync_end1_reg; // PRISM hse1 reg (pixels)
+ ULONG hsync_end2_reg; // PRISM hse2 reg (pixels)
+ ULONG vrt_total_reg; // PRISM ve reg (scan lines)
+ ULONG vrt_dsp_end_reg; // PRISM vde reg (scan lines)
+ ULONG vsync_start_reg; // PRISM vss reg (scan lines)
+ ULONG vsync_end_reg; // PRISM vse reg (scan lines)
+} bl_crt_ctrl_rec_t;
+
+// Adapter control record structure
+typedef struct _bl_adapter_ctrl_rec_t {
+ USHORT vram; // Amount of VRAM for frame buffer
+ USHORT width; // Number of pixels along the X axis
+ USHORT height; // Number of pixels along the Y axis
+ // PRISM registers
+ ULONG PRISM_cfg; // cfg reg
+ ULONG mem_cfg; // memory cfg reg
+ ULONG DTG_ctrl; // DTG control reg
+ // RAMDAC registers
+ UCHAR pix_ctrl0; // 07:00 pix ctrl
+ UCHAR pix_ctrl1; // 15:08 pix ctrl
+ UCHAR pix_ctrl2; // 23:16 pix ctrl
+ UCHAR pix_ctrl3; // 31:24 pix ctrl
+ UCHAR wid_ctrl0; // 3:0 WID ctrl
+ UCHAR wid_ctrl1; // 7:4 WID ctrl
+ UCHAR serial_mode_ctrl; // serial mode
+ UCHAR pix_interleave; // pixel interleave
+ UCHAR misc_cfg; // misc ctrl
+ UCHAR vram_mask_0; // vram mask reg 0
+ UCHAR vram_mask_1; // vram mask reg 1
+ UCHAR vram_mask_2; // vram mask reg 2
+} bl_adapter_ctrl_rec_t;
+
+// Adapter model record structure
+typedef struct bl_adapter_model_rec_t {
+ ULONG devvend_id; // PCI device id
+ ULONG strapping; // configuration strapping
+ UCHAR prism_rev; // prism chip revision ID
+ UCHAR num_adp_ctrl_recs; // number of adp_ctrl_rec's in array
+ bl_adapter_ctrl_rec_t *adp_ctrl_rec; // pointer to adapter ctrl rec array
+} bl_adapter_model_rec_t;
+
+// Config flag defines
+// System sourced/color reg. pixel depth for DFA apeture 1 and commands
+#define BL_ENABLE_SOURCE_1_BPP (1L << 0)
+#define BL_ENABLE_SOURCE_8_BPP (1L << 1)
+#define BL_ENABLE_SOURCE_16_BPP (1L << 2)
+#define BL_ENABLE_SOURCE_24_BPP (1L << 3)
+// frame buffer pixel depth from DFA apeture 1 and commands
+#define BL_ENABLE_8_BPP (1L << 3)
+#define BL_ENABLE_16_BPP (1L << 4)
+#define BL_ENABLE_24_BPP (1L << 5)
+#define BL_ENABLE_OVERLAY (1L << 0)
+#define BL_ENABLE_DOUBLE_BUFFER (1L << 1)
+#define BL_OVERLAY_AVAILABLE (1L << 0)
+#define BL_8_BPP_DB_AVAILABLE (1L << 1)
+#define BL_16_BPP_DB_AVAILABLE (1L << 2)
+#define BL_8_BPP_AVAILABLE (1L << 3)
+#define BL_16_BPP_AVAILABLE (1L << 4)
+#define BL_24_BPP_AVAILABLE (1L << 5)
+
+#endif // _H_BLFW
+
diff --git a/private/ntos/nthals/halppc/ppc/blrastz.h b/private/ntos/nthals/halppc/ppc/blrastz.h
new file mode 100644
index 000000000..5aa0330ee
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/blrastz.h
@@ -0,0 +1,348 @@
+
+#ifndef _H_BLRASTZ
+#define _H_BLRASTZ
+
+/******************************************************************************
+* *
+* PRSM Register and Port Address *
+* *
+******************************************************************************/
+
+#define BL_PRSM_STATUS_REG 0x0000
+#define BL_PRSM_CMD_REG 0x0000
+#define BL_PRSM_CNTL_HIGH_REG 0x1000
+#define BL_PRSM_CNTL_LOW_REG 0x1004
+#define BL_PRSM_FG_COL_REG 0x1008
+#define BL_PRSM_BG_COL_REG 0x100C
+#define BL_PRSM_PIX_MASK_REG 0x1010
+#define BL_PRSM_LINE_STYLE_PAT_1_REG 0x1014
+#define BL_PRSM_LINE_STYLE_PAT_2_REG 0x1018
+#define BL_PRSM_LINE_STYLE_CUR_CNT_REG 0x101C
+#define BL_PRSM_PLANE_WR_MASK_REG 0x1020
+#define BL_PRSM_CL_TEST_REG 0x1024
+#define BL_PRSM_PIX_PROC_REG 0x1028
+#define BL_PRSM_COL_COMP_REG 0x102C
+#define BL_PRSM_HL_COL_REG 0x1030
+#define BL_PRSM_WIN_ORG_OFF_REG 0x1034
+#define BL_PRSM_SC_ENABLE_REG 0x1038
+#define BL_PRSM_SC_0_MIN_REG 0x103C
+#define BL_PRSM_SC_0_MAX_REG 0x1040
+#define BL_PRSM_SC_1_MIN_REG 0x1044
+#define BL_PRSM_SC_1_MAX_REG 0x1048
+#define BL_PRSM_SC_2_MIN_REG 0x104C
+#define BL_PRSM_SC_2_MAX_REG 0x1050
+#define BL_PRSM_SC_3_MIN_REG 0x1054
+#define BL_PRSM_SC_3_MAX_REG 0x1058
+#define BL_PRSM_STP_OFF_REG 0x105C
+#define BL_PRSM_STP_CACH_DATA_0_REG 0x1060
+#define BL_PRSM_STP_CACH_DATA_1_REG 0x1064
+#define BL_PRSM_STP_CACH_DATA_2_REG 0x1068
+#define BL_PRSM_STP_CACH_DATA_3_REG 0x106C
+#define BL_PRSM_STP_CACH_DATA_4_REG 0x1070
+#define BL_PRSM_STP_CACH_DATA_5_REG 0x1074
+#define BL_PRSM_STP_CACH_DATA_6_REG 0x1078
+#define BL_PRSM_STP_CACH_DATA_7_REG 0x107C
+#define BL_PRSM_CACH_POLL_MASK_REG 0x1080
+#define BL_PRSM_CACH_POLL_PTR_REG 0x1084
+
+#define BL_PRSM_CFG_REG 0x1400
+#define BL_PRSM_MEM_CFG_REG 0x1404
+#define BL_PRSM_RESET_CUR_CMD_REG 0x1408
+#define BL_PRSM_VGA_WIN_ORG_OFF_REG 0x140C
+#define BL_PRSM_VGA_CLIP_TEST_REG 0x1410
+
+#define BL_PRSM_INTR_STATUS_REG 0x2000
+#define BL_PRSM_CORRELATOR_REG 0x2004
+#define BL_PRSM_SOFT_RESET_REG 0x2008
+
+#define BL_PRSM_FR_START_REG 0x2400
+#define BL_PRSM_DTG_CNTL_REG 0x2404
+#define BL_PRSM_HORZ_EXTENT_REG 0x2408
+#define BL_PRSM_HORZ_DISPLAY_END_REG 0x240C
+#define BL_PRSM_HORZ_SYNC_START_REG 0x2410
+#define BL_PRSM_HORZ_SYNC_END_1_REG 0x2414
+#define BL_PRSM_HORZ_SYNC_END_2_REG 0x2418
+#define BL_PRSM_VERT_EXTENT_REG 0x241C
+#define BL_PRSM_VERT_DISPLAY_END_REG 0x2420
+#define BL_PRSM_VERT_SYNC_START_REG 0x2424
+#define BL_PRSM_VERT_SYNC_END_REG 0x2428
+
+#define BL_PRSM_RAMDAC_IMM_PORT 0x2600
+
+#define BL_PRSM_IO_SEL_IMM_PORT 0x2700
+
+#define BL_PRSM_MM_ADDR_PORT 0x2800
+#define BL_PRSM_MM_DATA_PORT 0x2804
+
+/******************************************************************************
+* *
+* Misc DFA Masks *
+* *
+******************************************************************************/
+
+#define BL_PRSM_1BPP_Y_ADDR_MASK 0x00FFF000
+#define BL_PRSM_1BPP_C_BIT_MASK 0x00000400
+#define BL_PRSM_1BPP_I_BIT_MASK 0x00000200
+#define BL_PRSM_1BPP_X_ADDR_MASK 0x000001FC
+
+#define BL_PRSM_8BPP_Y_ADDR_MASK 0x00FFF000
+#define BL_PRSM_8BPP_X_ADDR_MASK 0x00000FFF
+#define BL_PRSM_8BPP_RGB_RED_MASK 0xE0
+#define BL_PRSM_8BPP_RGB_GREEN_MASK 0x1C
+#define BL_PRSM_8BPP_RGB_BLUE_MASK 0x03
+#define BL_PRSM_8BPP_BGR_RED_MASK 0x07
+#define BL_PRSM_8BPP_BGR_GREEN_MASK 0x38
+#define BL_PRSM_8BPP_BGR_BLUE_MASK 0xC0
+
+#define BL_PRSM_16BPP_Y_ADDR_MASK 0x00FFE000
+#define BL_PRSM_16BPP_X_ADDR_MASK 0x00001FFE
+#define BL_PRSM_16BPP_RGB_RED_MASK 0xF800
+#define BL_PRSM_16BPP_RGB_GREEN_MASK 0x07E0
+#define BL_PRSM_16BPP_RGB_BLUE_MASK 0x001F
+#define BL_PRSM_16BPP_BGR_RED_MASK 0x001F
+#define BL_PRSM_16BPP_BGR_GREEN_MASK 0x07E0
+#define BL_PRSM_16BPP_BGR_BLUE_MASK 0xF800
+
+#define BL_PRSM_24BPP_Y_ADDR_MASK 0x00FFE000
+#define BL_PRSM_24BPP_X_ADDR_MASK 0x00001FFC
+#define BL_PRSM_24BPP_RGB_ALT_COL_MASK 0xFF000000
+#define BL_PRSM_24BPP_RGB_RED_MASK 0x00FF0000
+#define BL_PRSM_24BPP_RGB_GREEN_MASK 0x0000FF00
+#define BL_PRSM_24BPP_RGB_BLUE_MASK 0x000000FF
+#define BL_PRSM_24BPP_BGR_ALT_COL_MASK 0xFF000000
+#define BL_PRSM_24BPP_BGR_RED_MASK 0x000000FF
+#define BL_PRSM_24BPP_BGR_GREEN_MASK 0x0000FF00
+#define BL_PRSM_24BPP_BGR_BLUE_MASK 0x00FF0000
+#define BL_PRSM_24BPP_SPAN_WIDTH_MASK 0x0000FFFF
+
+#define BL_PRSM_32BPP_Y_ADDR_MASK 0x00FFE000
+#define BL_PRSM_32BPP_X_ADDR_MASK 0x00001FFC
+#define BL_PRSM_32BPP_RGB_ALT_COL_MASK 0xFF000000
+#define BL_PRSM_32BPP_RGB_RED_MASK 0x00FF0000
+#define BL_PRSM_32BPP_RGB_GREEN_MASK 0x0000FF00
+#define BL_PRSM_32BPP_RGB_BLUE_MASK 0x000000FF
+#define BL_PRSM_32BPP_BGR_ALT_COL_MASK 0xFF000000
+#define BL_PRSM_32BPP_BGR_RED_MASK 0x000000FF
+#define BL_PRSM_32BPP_BGR_GREEN_MASK 0x0000FF00
+#define BL_PRSM_32BPP_BGR_BLUE_MASK 0x00FF0000
+#define BL_PRSM_32BPP_SPAN_WIDTH_MASK 0x0000FFFF
+
+#define BL_PRSM_MDFA_Y_ADDR_MASK 0x00FFE000
+#define BL_PRSM_MDFA_X_ADDR_MASK 0x00001FFC
+#define BL_PRSM_MDFA_CNT_MASK 0xFF000000
+#define BL_PRSM_MDFA_MASK 0x00FFFFFF
+
+
+/******************************************************************************
+* *
+* Command Data Port Macros *
+* *
+******************************************************************************/
+
+#define BL_PRSM_CMD_DATA_PORT 0x0000
+#define BL_PRSM_CMD_DATA_PORT_START_ADDR 0x0000
+#define BL_PRSM_CMD_DATA_PORT_END_ADDR 0x0FFF
+#define BL_PRSM_CMD_DATA_PORT_LEN 0x1000
+
+
+/******************************************************************************
+* *
+* Control High Register *
+* *
+******************************************************************************/
+
+#define BL_SYS_SRC_DEPTH_A1_MASK 0x00000003
+#define BL_SYS_SRC_DEPTH_A1_1BPP 0x00000000
+#define BL_SYS_SRC_DEPTH_A1_8BPP 0x00000001
+#define BL_SYS_SRC_DEPTH_A1_16BPP 0x00000002
+#define BL_SYS_SRC_DEPTH_A1_24BPP 0x00000003
+#define BL_SYS_SRC_DEPTH_A1_32BPP 0x00000003
+
+#define BL_FB_PIX_DEPTH_A1_MASK 0x0000000C
+#define BL_FB_PIX_DEPTH_A1_8BPP 0x00000004
+#define BL_FB_PIX_DEPTH_A1_16BPP 0x00000008
+#define BL_FB_PIX_DEPTH_A1_24BPP 0x0000000C
+#define BL_FB_PIX_DEPTH_A1_32BPP 0x0000000C
+
+
+/******************************************************************************
+* *
+* Status Register *
+* *
+******************************************************************************/
+
+#define BL_PRSM_VERT_RETRACE 0x00000001
+#define BL_PRSM_HORZ_RETRACE 0x00000002
+
+#define BL_PRSM_IDLE 0x00000004
+#define BL_PRSM_BUSY 0x00000000
+
+#define BL_PRSM_DL_IDLE 0x00000008
+#define BL_PRSM_FIFO_EMPTY 0x00000010
+#define BL_PRSM_WAITING_FOR_SYS_ADDR 0x00000040
+#define BL_PRSM_ERR_DETECTED 0x00000080
+
+#define BL_PRSM_FIFO_FREE_SPACE_MASK 0x000F0000
+#define BL_PRSM_FIFO_FREE_SPACE_SHIFT 16
+
+
+/******************************************************************************
+* *
+* Interrupt Mask and Status Register *
+* *
+* Leave these definitions for possible future direct blit (DMA) support *
+* *
+******************************************************************************/
+
+#define BL_PRSM_DISABLE_RST_INTR 0x8FF3FC00
+
+/******************************************************************************
+* *
+* strapping information for memory configuration setting and detection *
+* *
+******************************************************************************/
+
+#define BL_FRAME_BUFFER_SIZE_MASK (3L << 16)
+#define BL_FRAME_BUFFER_SIZE_2_MEG (0L << 16)
+#define BL_FRAME_BUFFER_SIZE_4_MEG (1L << 16)
+#define BL_FRAME_BUFFER_SIZE_6_MEG (2L << 16)
+#define BL_FRAME_BUFFER_SIZE_8_MEG (3L << 16)
+#define BL_WID_BUFFER_SIZE_MASK (3L << 20)
+#define BL_WID_BUFFER_SIZE_0_MEG (0L << 20)
+#define BL_WID_BUFFER_SIZE_1_MEG (1L << 20)
+#define BL_WID_BUFFER_SIZE_2_MEG (2L << 20)
+#define BL_WID_BUFFER_SIZE_4_MEG (3L << 20)
+
+
+/******************************************************************************
+* *
+* misc defines *
+* *
+******************************************************************************/
+#define BL_CMD_QUEUE_SIZE 8
+
+#define BL_PRSM_NO_OP 0x0000
+
+ /* PRISM commands */
+#define BL_PRSM_BLT_SYS_TO_SCR_IND_OP 0x10000001
+#define BL_PRSM_BLT_SYS_TO_SCR_DIRECT_OP 0x0d400001
+#define BL_PRSM_BLT_SCR_TO_SCR_DIRECT_OP 0x0f030001
+#define BL_PRSM_BLT_SCR_TO_SYS_IND_OP 0x0DC00001
+#define BL_PRSM_POLY_REC 0x80020001
+#define BL_REG_DIRECT_RESTORE_FG 0xe4020001
+#define BL_REG_DIRECT_RESTORE_CTRL_HIGH 0xe4000001
+
+
+#define BL_PRISM_SPIN_PERIOD 1 /* busy spin delay in usec */
+ /* note: bl_delay() argument */
+ /* 1 yields about 1.6us */
+ /* 5 yields about 5.5us */
+ /* number of spin periods while */
+
+ /* waiting for busy to drop before */
+ /* driver asserts (time = 8 seconds) */
+ /* note: loop with bl_delay(1) and */
+ /* prism status read takes about */
+#define BL_PRISM_SPIN_TIME 4000000 /* 1.9-2.0 us */
+
+
+#define BL_DTG_NEG_SYNC 0x00000060 /* negitive sync */
+#define BL_DTG_COMP_SYNC 0x00004000 /* composite sync */
+#define BL_PRSM_NO_VIDEO 0x00000001 /* turn off video */
+#define BL_PRSM_VIDEO 0x00000002 /* turn on video */
+#define BL_PRSM_NO_VERT 0x00000400 /* hold vertical sync inactive */
+#define BL_PRSM_NO_HORZ 0x00001000 /* hold horizontal sync inactive */
+#define BL_PRSM_SYNC_MASK 0x00003e02 /* sync select / video blanking mask*/
+
+#define BL_FRAME_A 0x00000040 /* Frame buffer A select */
+#define BL_FRAME_B 0x00000080 /* Frame buffer B select */
+#define BL_FRAME_MASK 0x000000C0 /* Frame buffer select mask */
+
+#define SCL 0x00000001 /* I2C clock line (io port 2407) */
+#define SDA 0x00000020 /* I2C data line (io port 2407) */
+
+
+#define PRISM_WRT_REG(seg, reg, value) \
+ *((volatile unsigned long *)((seg) + BL_REG_OFFSET + (reg))) \
+ = (unsigned long) (value)
+
+#define PRISM_RD_REG(seg, reg) \
+ *((volatile unsigned long *)((seg) + BL_REG_OFFSET + (reg)))
+
+#define PRISM_WRT_DAC(seg, reg, value) \
+ *((volatile unsigned long *)((seg) + BL_REG_OFFSET + \
+ BL_PRSM_RAMDAC_IMM_PORT + (reg))) = (unsigned long)(value)
+
+#define PRISM_RD_DAC(seg, reg) \
+ (BL_EIEIO, \
+ (unsigned char)(*((volatile unsigned long *) \
+ ((seg) + BL_REG_OFFSET + BL_PRSM_RAMDAC_IMM_PORT + (reg)))))
+
+/******************************************************************************
+* *
+* Macro: BL_BUSY_POLL (regbase) *
+* caddr_t regbase; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* *
+* Description: Performs a busy poll on the adapter and returns when the *
+* adapter is no longer busy. In the case of a shallow bus *
+* interface FIFO on the adapter, this macro will also make *
+* sure that the FIFO is empty and that the adapter is not *
+* busy. This is a synchronous call. *
+* *
+******************************************************************************/
+
+#define BL_BUSY_POLL(regbase) \
+ while(PRISM_RD_REG((regbase), BL_PRSM_STATUS_REG) & BL_PRSM_BUSY);
+
+
+/******************************************************************************
+* *
+* Macro: PRISM_BUSY (regbase) *
+* *
+* Parameters: regbase - ptr to base addr of registers *
+* *
+* Description: Determine if PRISM rasterizer is busy or idle. *
+* *
+******************************************************************************/
+#define PRISM_BUSY(regbase) \
+ (BL_EIEIO, \
+ !(PRISM_RD_REG(regbase, BL_PRSM_STATUS_REG) & BL_PRSM_IDLE))
+
+
+/******************************************************************************
+* PRISM_FIFO_NOT_AVAIL *
+******************************************************************************/
+
+#define PRISM_FIFO_NOT_AVAIL(ptr, cnt) \
+ (((PRISM_RD_REG(ptr, BL_PRSM_STATUS_REG) >> 16) & 0x0f) < cnt)
+
+/******************************************************************************
+* *
+* Macro: BL_FILL_RECT (regbase, dst_x, dst_y, width, height) *
+* caddr_t regbase; *
+* short dst_x, dst_y; *
+* unsigned short width, height; *
+* *
+* Parameters: regbase - Address of the start of the adapter address space *
+* dst_x, dst_y - Screen coords of where to start the rect *
+* width, height - Dimensions of the rect *
+* *
+* Description: Performs a fill rectangle command to the adapter *
+* *
+******************************************************************************/
+
+#define BL_FILL_RECT(regbase, dst_x, dst_y, width, height) \
+ PRISM_WR_REG((regbase), BB_CMD_DATA_PORT, \
+ BL_POLYFILL_RECT_CMD | 0x1); \
+ PRISM_WR_REG((regbase), BL_CMD_DATA_PORT, \
+ (((unsigned short)(dst_x) << 16) | \
+ (unsigned short)(dst_y))); \
+ PRISM_WR_REG((regbase), BB_CMD_DATA_PORT, \
+ (((unsigned short)(height) << 16) | \
+ (unsigned short)(width)))
+
+
+#endif /* ! _H_BLRASTZ */
+
diff --git a/private/ntos/nthals/halppc/ppc/blrmdac.h b/private/ntos/nthals/halppc/ppc/blrmdac.h
new file mode 100644
index 000000000..33f41d64a
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/blrmdac.h
@@ -0,0 +1,152 @@
+
+/*
+ * COMPONENT_NAME: bluedd
+ *
+ * FUNCTIONS: none
+ *
+ * ORIGINS: 156
+ *
+ * IBM CONFIDENTIAL -- (IBM Confidential Restricted when
+ * combined with the aggregated modules for this product)
+ * OBJECT CODE ONLY SOURCE MATERIALS
+ *
+ * (C) COPYRIGHT International Business Machines Corp. 1996
+ * All Rights Reserved
+ * US Government Users Restricted Rights - Use, duplication or
+ * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
+ */
+
+#ifndef _H_BL_RAMDAC
+#define _H_BL_RAMDAC
+
+/******************************************************************************
+* *
+* RGB640 (Blue Bayou) *
+* *
+******************************************************************************/
+
+#define BL_RAMDAC_FB_LUT_LENGTH 256
+
+
+/* registers */
+/* WARNING: although not noted in spec, it appears that when setting */
+/* both BL_640_INDEX_LOW and BL_640_INDEX_HI, LOW should be */
+/* set before HI. */
+
+#define BL_640_PALETTE_ADDR_WRT 0x00
+#define BL_640_PALETTE_DATA 0x04
+#define BL_640_PIXEL_MASK 0x08
+#define BL_640_PALETTE_ADDR_RD 0x0C
+#define BL_640_INDEX_LOW 0x10
+#define BL_640_INDEX_HI 0x14
+#define BL_640_INDEX_DATA 0x18
+
+/* indexed registers */
+
+#define BL_640_ID_LOW 0x0000
+#define BL_640_ID_HI 0x0001
+#define BL_640_RAW_PIXEL_CTRL_00 0x0002
+#define BL_640_RAW_PIXEL_CTRL_08 0x0003
+#define BL_640_RAW_PIXEL_CTRL_16 0x0004
+#define BL_640_RAW_PIXEL_CTRL_24 0x0005
+#define BL_640_WID_OUT_CTRL_00 0x0006
+#define BL_640_WID_OUT_CTRL_04 0x0007
+#define BL_640_SERIALIZER_MODE 0x0008
+#define BL_640_PIXEL_INTERLEAVE 0x0009
+
+#define BL_640_MISC_CFG_REG 0x000A
+#define BL_640_WIDCTRL_MASK 0x07
+
+#define BL_640_VGA_CTRL 0x000B
+#define BL_640_MONITOR_ID 0x000C
+#define BL_640_DAC_CTRL 0x000D
+
+#define BL_640_UPDATE_CTRL 0x000E
+#define BL_640_AUTO_INCR 0x01
+
+#define BL_640_SYNC_CTRL 0x000F
+
+#define BL_640_SOG 0x03
+
+#define BL_640_PEDESTAL 0x01
+#define BL_640_COMP_SYNC 0x04
+#define BL_640_NEG_SYNC 0x08
+#define BL_640_POS_SYNC 0x10
+#define BL_640_PWR_LOW_SYNC 0x30
+#define BL_640_PWR_HIGH_VSYNC 0x20
+#define BL_640_PWR_HIGH_HSYNC 0x38
+#define BL_640_FLIP_VSYNC 0x01
+
+#define BL_640_VIDEO_PLL_REF_DIVIDE 0x0010
+#define BL_640_VIDEO_PLL_MULT 0x0011
+#define BL_640_VIDEO_PLL_OUTPUT_DIVIDE 0x0012
+#define BL_640_VIDEO_PLL_CTRL 0x0013
+#define BL_640_AUX_REF_DIVIDE 0x0014
+#define BL_640_AUX_PLL_MULT 0x0015
+#define BL_640_AUX_PLL_OUTPUT_DIVIDE 0x0016
+#define BL_640_AUX_PLL_CTRL 0x0017
+#define BL_640_CHROMA_KEY_REG 0 0x0020
+#define BL_640_CHROMA_KEY_MASK_0 0x0021
+#define BL_640_CHROMA_KEY_REG_1 0x0022
+#define BL_640_CHROMA_KEY_MASK_1 0x0023
+#define BL_640_CROSSHAIR CTRL 0x0030
+#define BL_640_CURSOR_BLINK_RATE 0x0031
+#define BL_640_CURSOR_BLINK_DUTY_CYCLE 0x0032
+#define BL_640_CURSOR_HORIZONTAL_POSITION_LOW 0x0040
+#define BL_640_CURSOR_HORIZONTAL_POSITION_HI 0x0041
+#define BL_640_CURSOR_VERTICAL_POSITION_LOW 0x0042
+#define BL_640_CURSOR_VERTICAL_POSITION_HI 0x0043
+#define BL_640_CURSOR_HORIZONTAL_OFFSET 0x0044
+#define BL_640_CURSOR_VERTICAL_OFFSET 0x0045
+#define BL_640_ADV_FUNC_CURSOR_COLOR_0 0x0046
+#define BL_640_ADV_FUNC_CURSOR_COLOR_1 0x0047
+#define BL_640_ADV_FUNC_CURSOR_COLOR_2 0x0048
+#define BL_640_ADV_FUNC_CURSOR_COLOR_3 0x0049
+#define BL_640_ADV_FUNC_CURSOR_ATTR_TABLE 0x004A
+#define BL_640_CURSOR_CTRL 0x004B
+#define BL_640_CROSSHAIR_HORIZONTAL_POSITION_LOW 0x0050
+#define BL_640_CROSSHAIR_HORIZONTAL_POSITION_HI 0x0051
+#define BL_640_CROSSHAIR_VERTICAL_POSITION_LOW 0x0052
+#define BL_640_CROSSHAIR_VERTICAL_POSITION_HI 0x0053
+#define BL_640_CROSSHAIR_PATTERN COLOR 0x0054
+#define BL_640_CROSSHAIR_VERTICAL_PATTERN 0x0055
+#define BL_640_CROSSHAIR_HORIZONTAL_PATTERN 0x0056
+#define BL_640_CROSSHAIR_CTRL_1 0x0057
+#define BL_640_CROSSHAIR_CTRL_2 0x0058
+#define BL_640_YUV_CONVERSION_COEF_K1 0x0070
+#define BL_640_YUV_CONVERSION_COEF_K2 0x0071
+#define BL_640_YUV_CONVERSION_COEF_K3 0x0072
+#define BL_640_YUV_CONVERSION_COEF_K4 0x0073
+#define BL_640_VRAM_MASK_REG_0 0x00F0
+#define BL_640_VRAM_MASK_REG_1 0x00F1
+#define BL_640_VRAM_MASK_REG_2 0x00F2
+#define BL_640_DIAGNOSTICS 0x00FA
+#define BL_640_MISR_CTRL_STATUS 0x00FB
+#define BL_640_MISR_SIGNATURE_0 0x00FC
+#define BL_640_MISR_SIGNATURE_1 0x00FD
+#define BL_640_MISR_SIGNATURE_2 0x00FE
+#define BL_640_MISR_SIGNATURE_3 0x00FF
+
+#define BL_640_FRAME_BUFFER_WAT 0x0100
+#define BL_640_FRAME_BUFFER_WAT_BYTES 64
+
+#define BL_640_OVERLAY_WAT 0x0200
+#define BL_640_OVERLAY_WAT_BYTES 64
+
+#define BL_640_CURSOR_PIXMAP_WRITE 0x1000
+#define BL_640_CURSOR_PIXMAP_READ 0x2000
+
+/* start of multi-cycle addresses */
+#define BL_640_MULTI_CYCLE 0x40
+
+#define BL_640_COLOR_PALETTE_WRITE 0x4000
+#define BL_640_CURSOR_PALETTE_WRITE 0x4800
+#define BL_640_CROSSHAIR_PALETTE_WRITE 0x4808
+#define BL_640_COLOR_PALETTE_READ 0x8000
+#define BL_640_CURSOR_PALETTE_READ 0x8800
+#define BL_640_CROSSHAIR_PALETTE_READ 0x8808
+
+
+#endif /* _H_BL_RAMDAC */
+
+
diff --git a/private/ntos/nthals/halppc/ppc/fwdebug.h b/private/ntos/nthals/halppc/ppc/fwdebug.h
new file mode 100644
index 000000000..de6d56cb2
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/fwdebug.h
@@ -0,0 +1,99 @@
+//
+// FWDEBUG.H
+//
+// Prototypes for FWDEBUG.C
+// (automatically generated by CPROTO)
+//
+
+#ifndef _CPROTO_FWDEBUG_
+#define _CPROTO_FWDEBUG_
+
+
+VOID
+DEBUG_START ()
+// Do whatever is required to install, start, or hook up the debugger.
+;
+
+
+VOID
+DEBUG_STOP ()
+// Stop the debugger cleanly.
+;
+
+
+VOID
+DEBUG_DISABLE ()
+// Temporarily disable DEBUG_PRINT, DEBUG_PROMPT, and DEBUG_BREAK
+;
+
+
+VOID
+DEBUG_ENABLE ()
+// Enable the DEBUG_PRINT, DEBUG_PROMPT, and DEBUG_BREAK functions.
+;
+
+
+VOID
+DEBUG_PRINT (
+ LONG DebugLevelReqd,
+ PCHAR DebugMessage,
+ ...
+);
+
+
+VOID
+DEBUG_MESSAGE (
+ PCHAR DebugMessage,
+ ...
+);
+
+
+VOID
+DEBUG_BREAK (
+ LONG DebugLevelReqd
+);
+
+
+VOID
+DEBUG_PROMPT (
+ LONG DebugLevelReqd,
+ PCHAR Prompt,
+ PCHAR Response,
+ LONG ResponseMaxLen
+);
+
+
+VOID
+DEBUG_SETLEVEL (
+ LONG NewLevel
+);
+
+
+LONG
+DEBUG_GETLEVEL (
+);
+
+
+VOID
+DEBUG_SETREGION (
+ ULONG Region
+);
+
+
+LONG
+DEBUG_GETREGION (
+);
+
+
+VOID
+DEBUG_SETREGIONMASK (
+ ULONG Mask
+);
+
+
+LONG
+DEBUG_GETREGIONMASK (
+);
+
+
+#endif // _CPROTO_FWDEBUG_
diff --git a/private/ntos/nthals/halppc/ppc/fwnvr.c b/private/ntos/nthals/halppc/ppc/fwnvr.c
new file mode 100644
index 000000000..83ef93dc4
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/fwnvr.c
@@ -0,0 +1,2033 @@
+////////////////////////////////////////////////////////////////////////// ++
+//
+// FWNVR.C
+//
+// Copyright 1991-94 IBM, Motorola, Microsoft
+//
+// Functions to access Non-Volatile Ram on PowerPC systems.
+//
+// This module is used exactly as-is by both ARC and HAL. By convention,
+// it originates in the ARC environment and is copied to the HAL tree.
+//
+////////////////////////////////////////////////////////////////////////// --
+
+/*
+YET TO DO:
+ Fix and use NVR size-sensing
+ Use nvr_set_variable() function.
+ Allocate memory even in the ARC environment, since later the size of
+ the buffers required may vary wildly. This won't be a
+ problem (for either HAL or ARC) IF we go to NVR-direct use.
+ NOTE: must handle pool-clearing problems FIRST (ARC only)
+ Q: handle buffer-size changes when nvr_read_nvram() gets actual
+ NVR size? Bufferless fixes this problem too.
+ Handle 24-bit access
+*/
+
+#ifdef _HALNVR_ /////// BUILDING FOR USE IN HAL ///////
+
+#include "halp.h"
+
+#else /////// BUILDING FOR USE IN ARC ///////
+
+#include "fwp.h"
+#define ExAllocatePool(type,size) FwAllocatePool(size)
+
+#endif // _HALNVR_ /////////////////////////////////////////
+
+
+#include "prepnvr.h"
+#include "fwstatus.h"
+
+
+typedef struct _nvr_object
+{
+ struct _nvr_object *self ;
+ HEADER * bhead ;
+ HEADER * lhead ;
+ UCHAR bend [NVSIZE*2] ;
+ UCHAR lend [NVSIZE*2] ;
+} NVR_OBJECT, *PNVR_OBJECT ;
+
+typedef NVRAM_MAP *PNVRAM_MAP ;
+
+extern PVOID HalpIoControlBase ;
+
+#define ENDSWAP_SHORT(_x) (((_x<<8)&0xff00)|((_x>>8)&0x00ff))
+#define ENDSWAP_LONG(_x)\
+ (((_x<<24)&0xff000000)|((_x<<8)&0x00ff0000)|\
+ ((_x>>8)&0x0000ff00)|((_x>>24)&0x000000ff))
+
+#define _toupr_(_c) (((_c >= 'a') && (_c <= 'z')) ? (_c - 'a' + 'A') : _c)
+
+// Define the maximum size required for fetching any item from NVRAM, which
+// is defined to be the maximum size OF the NVRAM.
+// NOTE this is a poor assumption and needs to be sensed at run-time !!
+#define MAXNVRFETCH NVSIZE*2
+
+#define MAXIMUM_ENVIRONMENT_VALUE 1024
+
+
+/////////////////////////////////////////////////////////////////////////////
+// LOCAL DATA, NOT VISIBLE TO OTHER MODULES
+/////////////////////////////////////////////////////////////////////////////
+
+static UCHAR _currentstring[MAXIMUM_ENVIRONMENT_VALUE] ;
+static UCHAR _currentfetch[MAXNVRFETCH] ;
+
+#ifndef _HALNVR_
+NVR_OBJECT nvrobj ;
+#endif // _HALNVR_
+
+PNVR_OBJECT pnvrobj = NULL ;
+
+ // The access method varies with planar construction, and is switched
+ // based on the Planar ID Register.
+#define NVR_ACCESS_UNKNOWN 0
+#define NVR_ACCESS_SANDALFOOT 1
+#define NVR_ACCESS_STANDARD 2
+LONG NvrAccessMethod = NVR_ACCESS_UNKNOWN ;
+ // The use of 24-bit NVRAM addressing is enable with this flag:
+LONG NvrAccess24bit = FALSE ;
+ // These are the ISA port addresses for NVRAM Registers
+#define NVRREG_AD0 0x74 // LS byte of address (bits 0-7)
+#define NVRREG_AD1 0x75 // next byte of address (bits 8-15)
+// Below to be added when register definition finalized
+// #define NVRREG_AD2 0x?? // MS byte of address (bits 16-23)
+#define NVRREG_STDDATA 0x76 // Data Port (R/W), standard
+#define NVRREG_SFTDATA 0x77 // Data Port (R/W), Sandalfoot only
+
+ // The size below is used for error recovery, to either set NVRAM to
+ // a default state (a dubious proposition) or to clear it entirely.
+ULONG NvrFillSize = 4096 ; // "safe" default value
+
+USHORT NvrVersion = 0 ; // MSB=version, LSB=revision
+
+//////// Bring in prototypes automatically generated by CPROTO. These
+//////// should be placed AFTER any other headers and any module data
+//////// and data definitions, and BEFORE module code begins.
+#define _CPROTO_FW_SCOPE_
+#define _CPROTO_FWNVR_STATICS_
+#include "fwdebug.h"
+#include "fwnvr.h"
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+PNVR_OBJECT
+nvr_alloc (
+ ULONG size
+)
+{
+ PNVR_OBJECT p ;
+
+#ifdef _HALNVR_
+ // HAL allocates memory for it so it doesn't sit around all the time
+ p = ExAllocatePool (NonPagedPool, size) ;
+#else
+ // FW uses static allocation (probably change later...)
+ p = &nvrobj ;
+#endif // _HALNVR_
+
+ return (p) ;
+}
+
+
+// !=
+VOID
+nvr_free (
+ PVOID p
+)
+{
+ if ( !p )
+ return ;
+
+ NvrAccessMethod = NVR_ACCESS_UNKNOWN ;
+ NvrAccess24bit = 0 ;
+
+#ifdef _HALNVR_
+ ExFreePool (p) ; // de-allocate HAL memory
+#endif // _HALNVR_
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// ==
+USHORT
+NvrGetVersion (
+ VOID
+)
+{
+ return ( NvrVersion ) ;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+// ==
+ULONG
+NvrGetSize (
+ VOID
+)
+// Performs a hardware scan of NVRAM and returns it's size in bytes.
+// The algorithm accepts the fact that the bridge will return the last
+// byte written, even if it did NOT come from a memory location (it's
+// just a latch which is left with a stale value). So in order to get
+// a new value in the latch, we write to NVRAM location 0 between other
+// accesses.
+{
+ ULONG size = 1 ;
+ UCHAR b0, b1, b2, b3, b4 ;
+
+ // Since we'll be writing to location 0 for each byte tested, we
+ // can't test byte 0 without some special gyrations. Instead, we
+ // just start the test at byte 1. Recall that this is not intended
+ // so much as a memory TEST, but more a SIZE check.
+ size = 1 ;
+
+ b4 = nvr_read (0) ; // save byte 0 so the test is non-destructive
+ while ( size < 250000 )
+ {
+ b0 = nvr_read (size) ;
+ nvr_write (size,(UCHAR)(size&0xFF)) ;
+ nvr_write (0,(UCHAR)~(size&0xFF)) ;
+ b1 = nvr_read (size) ;
+ nvr_write (size,(UCHAR)~(size&0xFF)) ;
+ nvr_write (0,(UCHAR)(size&0xFF)) ;
+ b2 = nvr_read (size) ;
+ nvr_write (size,b0) ;
+ b3 = nvr_read (size) ;
+ if ( b3!=b0 || b1 != (UCHAR)(size&0xFF) || b2 != (UCHAR)~(size&0xFF) )
+ break ;
+ size++ ;
+ }
+ nvr_write (0,b4) ; // set first byte back again
+ if ( size == 1 )
+ size = 0 ;
+ return ( size ) ;
+}
+
+
+// ==
+BOOLEAN
+NvrSetSize (
+ LONG NvramSize // size of NVRAM in bytes if non-zero
+)
+{
+ ULONG size = 1 ;
+ UCHAR b0, b1, b2, b3, b4 ;
+
+ if ( NvramSize )
+ {
+ // Caller has specified what fill size is required. Just set
+ // the global variable and return.
+ NvrFillSize = NvramSize ;
+ DEBUG_PRINT (1,"NvrSetSize: fill size caller-set to %d bytes\n",NvrFillSize) ;
+ return TRUE ;
+ }
+ else
+ {
+ // Caller didn't know how big NVRAM is. We try to find out
+ // with a hardware test, and if successful we fill in the
+ // value. If we can't find out either, we disable clearing
+ // of NVRAM by setting NvrFillSize to zero.
+
+ size = NvrGetSize() & 0xFFFFF000 ; // size modulo-4k
+ DEBUG_PRINT (1,"NvrSetSize: fill size measured at %d bytes\n",size) ;
+
+// Overridden temporarily until we decide how to handle caller issues as to
+// whether clearing NVRAM is even legitimate to do. Code above works OK.
+
+ NvrFillSize = 0 ;
+ DEBUG_PRINT (1,"NvrSetSize: fill disabled by setting size to 0 bytes\n") ;
+ }
+ return TRUE ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+// ==
+LONG
+NvrGetMethod (
+ VOID
+)
+// Returns the access method in use. If it has not yet been set, a
+// check of the hardware is made in an attempt to set it properly.
+{
+ if ( NvrAccessMethod == NVR_ACCESS_UNKNOWN )
+ NvrSetMethod (0) ;
+ return ( NvrAccessMethod ) ;
+}
+
+
+// ==
+BOOLEAN
+NvrSetMethod (
+ LONG ForcedValue // if Non-zero, set to this value regardless
+)
+// Decide how to access NVRAM, so that the nvr_read() and nvr_write()
+// functions can work properly. If a non-zero parameter is passed in,
+// the method is simply set to this value. If ZERO is passed in, then
+// local code tries to determine the proper method. Either way, the
+// operation is checked afterwards, and FALSE is returned if the access
+// method does recognize values inside NVRAM. If OK, TRUE returned.
+{
+ UCHAR PlanarID = 0;
+ UCHAR endian = '*' ;
+ HEADER *hp = (HEADER *)0;
+
+ // If caller sets it explicitly, just check the results. Otherwise,
+ // use the Planar ID Register to decide what method to use.
+
+ if ( ForcedValue )
+ NvrAccessMethod = ForcedValue ;
+ else
+ {
+ PlanarID = READ_REGISTER_UCHAR ((ULONG)HalpIoControlBase+0x852) ;
+
+ // NOTE that while the 0xDE value is documented as a
+ // Sandalfoot, it was never used as one. Instead, it is used
+ // on Woodfield. Unclear if 0xDD used, but it's defined in
+ // DAKOARCH as a Sandalfoot.
+ if ( (PlanarID >= 0xFC && PlanarID < 0xFF) // Sandalfoot
+ || (PlanarID >= 0xDC && PlanarID < 0xDE) // more Sandalfoot
+ || (PlanarID == 0x95) // Victory
+ || (PlanarID == 0x0C) // Harley
+ || (PlanarID == 0x5a) // Zapatos
+ )
+ NvrAccessMethod = NVR_ACCESS_SANDALFOOT ; // Carolina
+ else
+ NvrAccessMethod = NVR_ACCESS_STANDARD ;
+ }
+
+ endian = nvr_read((ULONG)((ULONG)(&hp->Endian)-(ULONG)hp)) ;
+
+ DEBUG_PRINT (1,"NvrSetMethod: PlanarID=0x%02X, Method set to %d (Endian shown as '%c')\n",
+ PlanarID,NvrAccessMethod,endian) ;
+
+ if ( endian != 'B' && endian != 'L' )
+ {
+ DEBUG_PRINT (0,"NvrSetMethod FAILED: Endian value was '%c'\n",
+ endian) ;
+ return FALSE ;
+ }
+
+ return TRUE ;
+}
+
+
+// ==
+UCHAR
+nvr_read (
+ ULONG addr
+)
+{
+ UCHAR uc = 0 ;
+
+ if ( !NvrAccessMethod )
+ NvrSetMethod (0) ;
+
+ switch ( NvrAccessMethod )
+ {
+ case 0:
+ DEBUG_PRINT (1,"nvr_read: NO NvrAccessMethod\n") ;
+ return 0 ;
+ case 1:
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD0,
+ (UCHAR)(addr&0xFF)) ;
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD1,
+ (UCHAR)((addr>>8)&0x1F)) ;
+ uc = READ_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_SFTDATA) ;
+ break ;
+ case 2:
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD0,
+ (UCHAR)(addr&0xFF)) ;
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD1,
+ (UCHAR)((addr>>8)&0x1F)) ;
+ uc = READ_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_STDDATA) ;
+ break ;
+ }
+
+ return ( uc ) ;
+}
+
+
+// ==
+VOID
+nvr_write (
+ ULONG addr,
+ UCHAR data
+)
+{
+ if ( !NvrAccessMethod )
+ NvrSetMethod (0) ;
+
+ switch ( NvrAccessMethod )
+ {
+ case 0:
+ DEBUG_PRINT (1,"nvr_write: NO NvrAccessMethod\n") ;
+ return ;
+ case 1:
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD0,
+ (UCHAR)(addr&0xFF)) ;
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD1,
+ (UCHAR)((addr>>8)&0x1F)) ;
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_SFTDATA,
+ data) ;
+ break ;
+ case 2:
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD0,
+ (UCHAR)(addr&0xFF)) ;
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_AD1,
+ (UCHAR)((addr>>8)&0x1F)) ;
+ WRITE_REGISTER_UCHAR((ULONG)HalpIoControlBase+NVRREG_STDDATA,
+ data) ;
+ break ;
+ }
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+VOID
+nvr_swap_Header (
+ HEADER* dest,
+ HEADER* src
+)
+{
+ ULONG i ;
+ PUCHAR cp ;
+
+ if ( !dest || !src )
+ return ; // invalid pointer
+
+ dest->Size = ENDSWAP_SHORT(src->Size) ;
+ dest->Version = src->Version ;
+ dest->Revision = src->Revision ;
+ dest->Crc1 = ENDSWAP_SHORT(src->Crc1) ;
+ dest->Crc2 = ENDSWAP_SHORT(src->Crc2) ;
+ dest->LastOS = src->LastOS ;
+ dest->Endian = src->Endian ;
+ dest->OSAreaUsage = src->OSAreaUsage ;
+ dest->PMMode = src->PMMode ;
+
+
+// NOTE THIS CHANGES WITH UPDATED PPCNVR01.H
+ /* convert NVRRESTART_BLOCK structure of Header */
+ dest->ResumeBlock.CheckSum = ENDSWAP_LONG(src->ResumeBlock.CheckSum) ;
+ dest->ResumeBlock.BootStatus = ENDSWAP_LONG(src->ResumeBlock.BootStatus) ;
+ dest->ResumeBlock.ResumeAddr =
+ (PVOID) ENDSWAP_LONG((ULONG)src->ResumeBlock.ResumeAddr) ;
+ dest->ResumeBlock.SaveAreaAddr =
+ (PVOID) ENDSWAP_LONG((ULONG)src->ResumeBlock.SaveAreaAddr) ;
+ dest->ResumeBlock.SaveAreaLength =
+ ENDSWAP_LONG((ULONG)src->ResumeBlock.SaveAreaLength) ;
+ dest->ResumeBlock.HibResumeImageRBA =
+ ENDSWAP_LONG((ULONG)src->ResumeBlock.HibResumeImageRBA) ;
+ dest->ResumeBlock.HibResumeImageRBACount =
+ ENDSWAP_LONG((ULONG)src->ResumeBlock.HibResumeImageRBACount) ;
+ dest->ResumeBlock.Reserved =
+ ENDSWAP_LONG((ULONG)src->ResumeBlock.Reserved) ;
+
+
+ /* convert SECURITY structure */
+ dest->Security.BootErrCnt =
+ ENDSWAP_LONG(src->Security.BootErrCnt) ;
+ dest->Security.ConfigErrCnt =
+ ENDSWAP_LONG(src->Security.ConfigErrCnt) ;
+ dest->Security.BootErrorDT[0] =
+ ENDSWAP_LONG(src->Security.BootErrorDT[0]) ;
+ dest->Security.BootErrorDT[1] =
+ ENDSWAP_LONG(src->Security.BootErrorDT[1]) ;
+ dest->Security.ConfigErrorDT[0] =
+ ENDSWAP_LONG(src->Security.ConfigErrorDT[0]) ;
+ dest->Security.ConfigErrorDT[1] =
+ ENDSWAP_LONG(src->Security.ConfigErrorDT[1]) ;
+ dest->Security.BootCorrectDT[0] =
+ ENDSWAP_LONG(src->Security.BootCorrectDT[0]) ;
+ dest->Security.BootCorrectDT[1] =
+ ENDSWAP_LONG(src->Security.BootCorrectDT[1]) ;
+ dest->Security.ConfigCorrectDT[0] =
+ ENDSWAP_LONG(src->Security.ConfigCorrectDT[0]) ;
+ dest->Security.ConfigCorrectDT[1] =
+ ENDSWAP_LONG(src->Security.ConfigCorrectDT[1]) ;
+ dest->Security.BootSetDT[0] =
+ ENDSWAP_LONG(src->Security.BootSetDT[0]) ;
+ dest->Security.BootSetDT[1] =
+ ENDSWAP_LONG(src->Security.BootSetDT[1]) ;
+ dest->Security.ConfigSetDT[0] =
+ ENDSWAP_LONG(src->Security.ConfigSetDT[0]) ;
+ dest->Security.ConfigSetDT[1] =
+ ENDSWAP_LONG(src->Security.ConfigSetDT[1]) ;
+ for (i = 0 ; i < 16 ; i++)
+ dest->Security.Serial[i] = src->Security.Serial[i] ;
+
+ /* convert ERROR_LOG 0 and ERROR_LOG 1 structure */
+// ASAP: use sizeof() instead of 40 below...
+ for (i = 0 ; i < 40 ; i++)
+ {
+ dest->ErrorLog[0].ErrorLogEntry[i] = src->ErrorLog[0].ErrorLogEntry[i] ;
+ dest->ErrorLog[1].ErrorLogEntry[i] = src->ErrorLog[1].ErrorLogEntry[i] ;
+ }
+
+ /* convert remainder of Header */
+ dest->GEAddress = (PVOID) ENDSWAP_LONG((ULONG)src->GEAddress) ;
+ dest->GELength = ENDSWAP_LONG((ULONG)src->GELength) ;
+ dest->GELastWriteDT[0] = ENDSWAP_LONG(src->GELastWriteDT[0]) ;
+ dest->GELastWriteDT[1] = ENDSWAP_LONG(src->GELastWriteDT[1]) ;
+
+ dest->ConfigAddress =
+ (PVOID) ENDSWAP_LONG((ULONG)src->ConfigAddress) ;
+ dest->ConfigLength = ENDSWAP_LONG(src->ConfigLength) ;
+ dest->ConfigLastWriteDT[0] =
+ ENDSWAP_LONG(src->ConfigLastWriteDT[0]) ;
+ dest->ConfigLastWriteDT[1] =
+ ENDSWAP_LONG(src->ConfigLastWriteDT[1]) ;
+ dest->ConfigCount = ENDSWAP_LONG(src->ConfigCount) ;
+
+ dest->OSAreaAddress =
+ (PVOID) ENDSWAP_LONG((ULONG)src->OSAreaAddress) ;
+ dest->OSAreaLength = ENDSWAP_LONG(src->OSAreaLength) ;
+ dest->OSAreaLastWriteDT[0] =
+ ENDSWAP_LONG(src->OSAreaLastWriteDT[0]) ;
+ dest->OSAreaLastWriteDT[1] =
+ ENDSWAP_LONG(src->OSAreaLastWriteDT[1]) ;
+}
+
+
+// !=
+VOID
+nvr_headb2l (
+ PNVR_OBJECT p
+)
+{
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ nvr_swap_Header (p->lhead,p->bhead) ;
+}
+
+
+// !=
+VOID
+nvr_headl2b (
+ PNVR_OBJECT p
+)
+{
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ nvr_swap_Header (p->bhead,p->lhead) ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+VOID
+nvr_default_nvram (
+ PNVR_OBJECT p
+)
+// Attempts to protect operation from faulty intitialization of NVRAM
+// by early versions of ROS. Called only from nvr_read_nvram() when a
+// bad 'endian' indicator or CRC is found.
+{
+ ULONG i ;
+ PUCHAR cp ;
+ HEADER * bethp ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ DEBUG_PRINT (1,"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n") ;
+ DEBUG_PRINT (1,">>>>> CAUTION: Continuing from here will attempt to CLEAR NVRAM ! >>>>>>\n") ;
+ DEBUG_PRINT (1,"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n") ;
+ DEBUG_BREAK (1) ;
+
+ if ( NvrFillSize == 0 )
+ {
+ DEBUG_PRINT (1,">>>>>>>>>> nvr_default_nvram: CAN'T SET NVRAM TO DEFAULT (NO SIZE INFO)!\n") ;
+ DEBUG_BREAK (1) ;
+ return ;
+ }
+
+ DEBUG_PRINT (1,">>>>>>>>>> nvr_default_nvram: SETTING NVRAM TO DEFAULT VALUES!\n") ;
+
+ nvr_clear_nvram () ; // empty the physical NVRAM
+
+ bethp = (HEADER *)p->bend ;
+ cp = (PUCHAR)p->bend ;
+ /* clear internal header */
+ for (i = 0 ; i < sizeof(HEADER) ; i++)
+ *cp++ = 0 ;
+
+// ASAP: interlock with the (allocated) memory space available. We have to
+// never clear more memory than we have allocated!
+
+// ASAP: save size of volatile buffer in struct itself.
+
+ /* clear internal data areas */
+ for (i = 0 ; i < NvrFillSize ; i++)
+ p->bend[i] = p->lend[i] = 0 ;
+
+ bethp->Endian = 'B' ;
+ bethp->Size = ENDSWAP_SHORT((USHORT)NvrFillSize/1024) ;
+
+ // Watch it -- these could come back and byte us !!
+ bethp->Version = 1 ;
+ bethp->Revision = 4 ;
+
+ // Global Environment starts right after header, and uses all the
+ // space not reserved for the OS and CONFIG areas below.
+ bethp->GEAddress = (PVOID) ENDSWAP_LONG((ULONG)sizeof(HEADER)) ;
+ bethp->GELength =
+ ENDSWAP_LONG((ULONG)NvrFillSize-CONFSIZE-OSAREASIZE-sizeof(HEADER)) ;
+
+ // OS Area follows, taking up a default amount of space
+ bethp->OSAreaAddress =
+ (PVOID) ENDSWAP_LONG((ULONG)(NvrFillSize-CONFSIZE-OSAREASIZE)) ;
+ bethp->OSAreaLength = ENDSWAP_LONG((ULONG)OSAREASIZE) ;
+
+ // Set the config area such that it isn't used. This leaves some
+ // free space (CONFSIZE bytes) for it to grow downward into. This is
+ // counterintuitive, but matches what ROS uses for initialization.
+ bethp->ConfigAddress = (PVOID) ENDSWAP_LONG(NvrFillSize) ;
+ bethp->ConfigLength = ENDSWAP_LONG((ULONG)0) ;
+
+ nvr_headb2l (p) ; // copy data to Little-Endian (internal) side
+ nvr_write_Header (p) ; // write header to the hardware
+}
+
+static BOOLEAN crc2_short = FALSE;
+
+USHORT
+nvr_calc2crc_read (
+ PNVR_OBJECT p
+)
+// Checksum the CONFIGURATION AREA ONLY.
+{
+ ULONG ul ;
+ PUCHAR cp ;
+ PUCHAR end ;
+
+ if ( !p || p != p->self )
+ return 0xFFFF ; // invalid pointer
+// Original version returned indeterminate value here !!
+// ASAP: check with ESW for proper resolution!
+// return ;
+
+ ul = 0xFFFF ;
+
+// ASAP: revisit the calculation size. The first Wiltwick had a "gap"
+// between the OS and CFG areas, and it may NOT have been checksummed.
+
+ cp = (PUCHAR)((ULONG)p->bhead + (ULONG)p->lhead->ConfigAddress) ;
+#if 0
+// end = (PUCHAR)((ULONG)p->bhead +
+// (ULONG)(((ULONG)p->lhead->Size << 10) - 1)) ;
+ end = (PUCHAR)((ULONG)p->bhead +
+ (ULONG)(((ULONG)p->lhead->Size << 10) )) ;
+#endif
+
+//
+// PLJ reverted to original code to avoid blowing checksum in config
+// area on sandalfoot.
+//
+
+ end = (PUCHAR)((ULONG)p->bhead +
+ (ULONG)(((ULONG)p->lhead->Size << 10) - 1)) ;
+
+// end PLJ change
+
+ for ( ; cp < end ; cp++)
+ ul = nvr_computecrc(ul, *cp) ;
+
+ //
+ // Note that we checksummed 1 byte too few, this is to
+ // allow for OLD versions of the firmware. If the checksum
+ // now == expected value, set the boolean crc2_short to TRUE
+ // so we calculate the right value when writing and return
+ // the current value. If it is not currently correct,
+ // checksum 1 more byte and return that value.
+ //
+
+ if ((USHORT)(ul & 0xFFFF) == p->lhead->Crc2) {
+ crc2_short = TRUE;
+ } else {
+ ul = nvr_computecrc(ul, *cp) ;
+ }
+
+ return ( (USHORT)(ul & 0xFFFF) ) ;
+}
+
+USHORT
+nvr_calc2crc_write (
+ PNVR_OBJECT p
+)
+// Checksum the CONFIGURATION AREA ONLY.
+{
+ ULONG ul ;
+ PUCHAR cp ;
+ PUCHAR end ;
+
+ if ( !p || p != p->self )
+ return 0xFFFF ; // invalid pointer
+// Original version returned indeterminate value here !!
+// ASAP: check with ESW for proper resolution!
+// return ;
+
+ ul = 0xFFFF ;
+
+// ASAP: revisit the calculation size. The first Wiltwick had a "gap"
+// between the OS and CFG areas, and it may NOT have been checksummed.
+
+ cp = (PUCHAR)((ULONG)p->bhead + (ULONG)p->lhead->ConfigAddress) ;
+
+// end = (PUCHAR)((ULONG)p->bhead +
+// (ULONG)(((ULONG)p->lhead->Size << 10) - 1)) ;
+ end = (PUCHAR)((ULONG)p->bhead +
+ (ULONG)(((ULONG)p->lhead->Size << 10) )) ;
+
+
+//
+// PLJ if we were short 1 byte on the read, calculate the new checksum
+// 1 byte short also. This is to support old firmware.
+//
+
+ if ( crc2_short ) {
+ end--;
+ }
+
+// end PLJ change
+
+ for ( ; cp < end ; cp++)
+ ul = nvr_computecrc(ul, *cp) ;
+
+ return ( (USHORT)(ul & 0xFFFF) ) ;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+BOOLEAN
+nvr_read_nvram (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR cp ;
+ HEADER * bhp ; // ptr to BE header
+ USHORT crc1a = 0 , crc1c = 0 ; // actual and calculated
+ USHORT crc2a = 0 , crc2c = 0 ; // values for each CRC
+ ULONG nvr_selfsize = 0 ;
+
+ DEBUG_PRINT (2,"nvr_read_nvram: entry\n") ;
+
+ if ( !p || p != p->self )
+ return FALSE ; // invalid pointer
+
+ /* read the HEADER from the NVRAM chip */
+ bhp = p->bhead ;
+ cp = (PUCHAR)p->bend ;
+ for (i = 0 ; i < sizeof(HEADER) ; i++)
+ *cp++ = nvr_read(i) ;
+
+ if ((bhp->Endian != 'B') && (bhp->Endian != 'L'))
+ goto error ;
+
+ // convert big endian header to little endian
+ nvr_headb2l (p) ;
+
+ // read the data areas. We have to do this before calculating the
+ // checksum, since these areas are checked.
+ nvr_read_GEArea(p) ;
+ nvr_read_OSArea(p) ;
+ nvr_read_CFArea(p) ;
+
+ // validate checksum 1
+ crc1a = ENDSWAP_SHORT(bhp->Crc1) ;
+ crc1c = nvr_calc1crc(p) ;
+ if ( crc1a != crc1c )
+ goto error ;
+
+ // validate checksum 2
+ crc2a = ENDSWAP_SHORT(bhp->Crc2) ;
+ crc2c = nvr_calc2crc_read(p) ;
+ if ( crc2a != crc2c )
+ goto error ;
+
+ // At this point the checksum matches, and we have good confidence of
+ // having valid data. We use the data within the NVRAM to firm up
+ // our notion of how big NVRAM is, in case we later have to clear it.
+ nvr_selfsize = ((ULONG)(ENDSWAP_SHORT(bhp->Size))) * 1024 ;
+ NvrSetSize (nvr_selfsize) ;
+
+ // Save the NVR version for later query if required
+ NvrVersion = (bhp->Version<<8) | bhp->Revision ;
+
+// ASAP: cross-check NvrFillSize with all three addresses and sizes stored
+// in NVRAM to see if the values make sense.
+
+ return TRUE ;
+
+ // We get below only if there was an error reading NVRAM. If so,
+ // show whatever we can for debugging and then go set NVRAM to the
+ // "default" state.
+error:
+ DEBUG_PRINT (1,"NVRAM READ ERROR ! Endian byte = '%c'\n",bhp->Endian) ;
+ DEBUG_PRINT (1," CRC1 as read: 0x%04X Calculated: 0x%04X\n",crc1a,crc1c) ;
+ DEBUG_PRINT (1," CRC2 as read: 0x%04X Calculated: 0x%04X\n",crc2a,crc2c) ;
+ nvr_print_object () ; // if debugging, show before deleting
+ nvr_default_nvram (p) ;
+ return FALSE ;
+}
+
+
+// !=
+VOID
+nvr_read_GEArea (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR lp ;
+ PUCHAR bp ;
+ ULONG offset ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ // Read Global Environment data into both BE and LE areas
+ offset = (ULONG)p->lhead->GEAddress ;
+ lp = (PUCHAR)((ULONG)p->lhead + offset) ;
+ bp = (PUCHAR)((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->GELength ; i++, bp++, lp++)
+ *bp = *lp = nvr_read(offset + i) ;
+}
+
+
+// !=
+VOID
+nvr_read_OSArea (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR lp ;
+ PUCHAR bp ;
+ ULONG offset ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ // Read OS-Specific Environment data into both BE and LE areas
+ offset = (ULONG)p->lhead->OSAreaAddress ;
+ lp = (PUCHAR)((ULONG)p->lhead + offset) ;
+ bp = (PUCHAR)((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->OSAreaLength ; i++, bp++, lp++)
+ *bp = *lp = nvr_read(offset + i) ;
+}
+
+
+// !=
+VOID
+nvr_read_CFArea (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR lp ;
+ PUCHAR bp ;
+ ULONG offset ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ // Read Configuration data into both BE and LE areas
+ offset = (ULONG) p->lhead->ConfigAddress ;
+ lp = (PUCHAR) ((ULONG)p->lhead + offset) ;
+ bp = (PUCHAR) ((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->ConfigLength ; i++)
+ bp[i] = lp[i] = nvr_read(offset + i) ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+VOID
+nvr_write_Header (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR cp ;
+ USHORT us ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ // We treat the LE header as the 'master', so first convert it's
+ // contents into BE format to be written ti NVRAM
+ nvr_headl2b(p) ;
+
+ // Fill in the CRC values. NOTE that changes are made to the LE
+ // header WITHOUT updating the CRC, so we have to do it before
+ // writing the header. It's the BE data that's being checksummed.
+ us = nvr_calc1crc(p) ;
+ p->bhead->Crc1 = ENDSWAP_SHORT(us) ;
+ us = nvr_calc2crc_write(p) ;
+ p->bhead->Crc2 = ENDSWAP_SHORT(us) ;
+
+ // spit out data
+ cp = (PUCHAR)p->bend ;
+ for ( i = 0 ; i < sizeof(HEADER) ; i++ )
+ nvr_write (i, *cp++) ;
+}
+
+
+// !=
+VOID
+nvr_write_GEArea (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR dest ;
+ PUCHAR src ;
+ ULONG offset ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ /* copy from little endian to big endian staging area */
+ offset = (ULONG)p->lhead->GEAddress ;
+ src = (PUCHAR)((ULONG)p->lhead + offset) ;
+ dest = (PUCHAR)((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->GELength ; i++, dest++, src++)
+ *dest = *src ;
+
+ /* convert to big endian, compute crc, and write header */
+ nvr_write_Header(p) ;
+
+ /* spit out global environment data */
+ src = (PUCHAR)((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->GELength ; i++, src++)
+ nvr_write (i+offset, *src) ;
+}
+
+
+// !=
+VOID
+nvr_write_OSArea (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ ULONG offset ;
+ PUCHAR src ;
+ PUCHAR dest ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ /* copy from little endian to big endian staging area */
+ offset = (ULONG) p->lhead->OSAreaAddress ;
+ src = (PUCHAR) ((ULONG)p->lhead + offset) ;
+ dest = (PUCHAR) ((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->OSAreaLength ; i++, dest++, src++)
+ *dest = *src ;
+
+ /* spit out OS specific data */
+ /* header not needed - no crc for OS Area in Header */
+ src = (PUCHAR)((ULONG)p->bhead + offset) ;
+ for (i = 0 ; i < p->lhead->OSAreaLength ; i++, src++)
+ nvr_write (i+offset, *src) ;
+}
+
+
+// !=
+VOID
+nvr_write_CFArea (
+ PNVR_OBJECT p
+)
+{
+ ULONG i ;
+ PUCHAR dest ;
+ PUCHAR src ;
+ ULONG offset ;
+
+ if ( !p || p != p->self )
+ return ; // invalid pointer
+
+ /* copy from little endian to big endian staging area */
+ offset = (ULONG)p->lhead->ConfigAddress ;
+ dest = (PUCHAR) ((ULONG)p->bhead + offset - 1) ;
+ src = (PUCHAR) ((ULONG)p->lhead + offset - 1) ;
+ for (i = 0 ; i < p->lhead->ConfigLength ; i++, dest--, src--)
+ *dest = *src ;
+
+ /* convert to big endian, compute crc, and write header */
+ nvr_write_Header(p) ;
+
+ /* spit out configuration data */
+ src = (PUCHAR)((ULONG)p->bhead + offset - 1) ;
+ for (i = 1 ; i <= p->lhead->ConfigLength ; i++, src--)
+ nvr_write (i+offset, *src) ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// USED_BY_HAL:
+// ==
+VOID
+nvr_delete_object (
+ VOID
+)
+{
+ if ( !pnvrobj || pnvrobj != pnvrobj->self )
+ return ;
+
+ pnvrobj->self = NULL ;
+ nvr_free (pnvrobj) ;
+ pnvrobj = NULL ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+PNVR_OBJECT
+nvr_create_object (
+ VOID
+)
+{
+ ULONG i ;
+ PUCHAR cp ;
+ UCHAR pid ;
+
+ // Allocate (or just find) memory for the local NVR Object
+ pnvrobj = nvr_alloc (sizeof(NVR_OBJECT)) ;
+ if ( !pnvrobj )
+ return NULL ; // ERROR: couldn't get memory
+
+ // Zero out the object
+ for (i = 0, cp = (PUCHAR)pnvrobj ; i < sizeof(NVR_OBJECT) ; i++, cp++)
+ *cp = 0 ;
+
+ // initialize internal elements
+ pnvrobj->self = pnvrobj ;
+ pnvrobj->bhead = (HEADER *) pnvrobj->bend ;
+ pnvrobj->lhead = (HEADER *) pnvrobj->lend ;
+
+ return (pnvrobj) ;
+}
+
+
+// USED_BY_HAL:
+
+// ==
+STATUS_TYPE
+nvr_initialize_object (
+ LONG AccessMethod,
+ ULONG Size // NVR size in bytes
+)
+// Set up everything required to be able to access and modify NVRAM.
+// The parameters are "optional" (may be zero).
+//
+// If AccessMethod == 0, the actual value will be derived from the
+// hardware (at this point the hardware test is reliable).
+//
+// If Size == 0, the program will attempt to determine the actual NVRAM
+// size by a hardware test (at this point this is in-op). After the
+// NVRAM is read successfully and the CRC checks, the value will be
+// updated based on the value found inside NVRAM itself. If the caller
+// furnishes no value AND a valid value is NOT found, clearing of NVRAM
+// will be disabled.
+//
+// NOTE that this module must somehow know the Method in order to
+// perform ANY accesses, but that Size is only used in error cases to
+// destroy the entire NVRAM.
+{
+ DEBUG_PRINT (1,"enter nvr_initialize_object\n") ;
+
+ if ( pnvrobj )
+ return stat_exist ; // object ALREADY initialized!
+
+ // create object or get static address
+ if ( !(pnvrobj = nvr_create_object()) )
+ return stat_error ;
+
+ NvrFillSize = Size ;
+
+ // Decide HOW to access NVRAM and set global variable
+ NvrSetMethod (AccessMethod) ;
+
+// ASAP: figure how to handle an error properly. If zero returned from
+// above, the endian indicator didn't show up and we probably can't
+// read NVRAM at all. What to do, what to do??
+
+ NvrSetSize (Size) ;
+
+ // read the header from NVRAM and convert to little endian
+ nvr_read_nvram (pnvrobj) ;
+
+ nvr_print_object() ; // if debugging, print the values
+
+ return stat_ok ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// !=
+VOID
+nvr_clear_nvram (
+ VOID
+)
+// Set ALL of NVRAM to zeros: header, checksum, EVERYTHING! This is
+// used to set default values in case a corrupted system is found, OR
+// from the (user-initiated) nvr_destory() function.
+{
+ ULONG i ;
+
+ for ( i = 0 ; i < NvrFillSize ; i++ )
+ nvr_write (i,0) ;
+}
+
+
+// ==
+VOID
+nvr_destroy (
+ LONG AccessMethod,
+ ULONG Size // size of NVRAM
+)
+// This is used as a debugging and recovery feature only. It is accessed
+// via a secret back door in the FWBOOT.C module, and is never executed,
+// other than manually by the user.
+{
+ if ( !pnvrobj || pnvrobj != pnvrobj->self )
+ return ; // invalid pointer
+
+ nvr_delete_object () ; // delete in case corrupt
+ nvr_initialize_object (AccessMethod,Size) ; // get new copy
+ nvr_clear_nvram () ; // EMPTY THE PHYSICAL NVRAM
+ nvr_delete_object() ; // delete local copy
+
+ // re-read so local copy matches
+ nvr_initialize_object (AccessMethod,Size) ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// The CRC computation algorithm must match that used by the resident
+// firmware (ROS). The algorithms below were obtained from the ESW Group
+// that develops Dakota Firmware. Whenever there are changes in their
+// algorithms, they must be changed here also.
+/////////////////////////////////////////////////////////////////////////////
+
+#define rol(x,y) ( ( ((x)<<(y)) | ((x)>>(16 - (y))) ) & 0x0FFFF)
+#define ror(x,y) ( ( ((x)>>(y)) | ((x)<<(16 - (y))) ) & 0x0FFFF)
+
+// !=
+ULONG
+nvr_computecrc (
+ ULONG oldcrc,
+ UCHAR data
+)
+{
+ ULONG pd, crc ;
+
+ pd = ((oldcrc>>8) ^ data) << 8 ;
+
+ crc = 0xFF00 & (oldcrc << 8) ;
+ crc |= pd >> 8 ;
+ crc ^= rol(pd,4) & 0xF00F ;
+ crc ^= ror(pd,3) & 0x1FE0 ;
+ crc ^= pd & 0xF000 ;
+ crc ^= ror(pd,7) & 0x01E0 ;
+ return crc ;
+}
+
+
+// !=
+USHORT
+nvr_calc1crc (
+ PNVR_OBJECT p
+)
+{
+ ULONG ul ;
+ ULONG i ;
+ PUCHAR cp ;
+ ULONG len1 ;
+ ULONG len2 ;
+ USHORT us ;
+
+ if ( !p || p != p->self )
+ return 0 ; // invalid pointer
+
+ ul = 0x0ffff ;
+
+ // do not include current Crc1/Crc2 in checksum
+ len1 = (sizeof(p->bhead->Size) +
+ sizeof(p->bhead->Version) +
+ sizeof(p->bhead->Revision)) ;
+ len2 = (ULONG) p->lhead->OSAreaAddress ;
+
+
+ // calculate the area before Crc1/Crc2 in the header
+ for (cp = (PUCHAR)p->bhead, i = 0 ; i < len1 ; i++)
+ ul = nvr_computecrc(ul, cp[i]) ;
+
+// NOTE: this switch was required starting with NVR 1.4 as shipped on Delmar.
+// It's unclear whether the change is really related to 1.4 format or
+// to some other ROS change, but we're switching on 1.4 anyway. If a
+// problem develops where the CRC of a new Machine or ROS goes bad,
+// check this out early. Originally this switch was done at compile-
+// time, and was labelled FIX_D852. Defining this name enabled the
+// (now) post-1.3 code.
+ if ( p->bhead->Version <= 1 && p->bhead->Revision < 4 )
+ i += (sizeof(p->bhead->Crc1) + sizeof(p->bhead->Crc2)) + 1 ;
+ else
+ i += (sizeof(p->bhead->Crc1) + sizeof(p->bhead->Crc2)) ;
+
+ for (i = i ; i < len2 ; i++)
+ ul = nvr_computecrc(ul, cp[i]) ;
+
+ us = (USHORT)(ul & 0x0ffff) ;
+
+ return (us) ;
+}
+
+
+// !=
+USHORT
+nvr_calc2crc (
+ PNVR_OBJECT p
+)
+// Checksum the CONFIGURATION AREA ONLY.
+{
+ ULONG ul ;
+ PUCHAR cp ;
+ PUCHAR end ;
+
+ if ( !p || p != p->self )
+ return 0xFFFF ; // invalid pointer
+// Original version returned indeterminate value here !!
+// ASAP: check with ESW for proper resolution!
+// return ;
+
+ ul = 0xFFFF ;
+
+// ASAP: revisit the calculation size. The first Wiltwick had a "gap"
+// between the OS and CFG areas, and it may NOT have been checksummed.
+
+ cp = (PUCHAR)((ULONG)p->bhead + (ULONG)p->lhead->ConfigAddress) ;
+#if 0
+// end = (PUCHAR)((ULONG)p->bhead +
+// (ULONG)(((ULONG)p->lhead->Size << 10) - 1)) ;
+ end = (PUCHAR)((ULONG)p->bhead +
+ (ULONG)(((ULONG)p->lhead->Size << 10) )) ;
+#endif
+
+//
+// PLJ reverted to original code to avoid blowing checksum in config
+// area on sandalfoot.
+//
+
+ end = (PUCHAR)((ULONG)p->bhead +
+ (ULONG)(((ULONG)p->lhead->Size << 10) - 1)) ;
+
+// end PLJ change
+
+ for ( ; cp < end ; cp++)
+ ul = nvr_computecrc(ul, *cp) ;
+
+ return ( (USHORT)(ul & 0xFFFF) ) ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+// FUNCTIONS PUBLIC TO THE HIGHER LAYERS OF SOFTWARE
+// The functions below operate on the little endian section of the
+// data structure internal to this file. Little endian is the internal
+// (volatile RAM) representation of the NVRAM contents. All access to
+// NVRAM data (variables, etc) are performed on this internal
+// representation. When necessary, the internal representation is
+// loaded back into NVRAM.
+/////////////////////////////////////////////////////////////////////////////
+
+// ==
+VOID
+nvr_print_object (
+ VOID
+)
+// Called by SFENVIR.C after nvr_initialize()
+{
+ PUCHAR cp ;
+ PUCHAR max ;
+ UCHAR tmp ;
+ PNVRAM_MAP mp ;
+ HEADER* hp ;
+ LONG i ;
+ CHAR buf[100] ; // buffer for string creation
+
+ if ( !pnvrobj || pnvrobj != pnvrobj->self )
+ return ; // invalid pointer
+
+ if ( DEBUG_GETLEVEL() < 1 )
+ return ;
+
+ mp = (PNVRAM_MAP) pnvrobj->lend ;
+ hp = pnvrobj->lhead ;
+
+ DEBUG_PRINT (1,"================= INTERNAL NVRAM DISPLAY ==================\n") ;
+ DEBUG_PRINT (1," Object Addr: 0x%08lx\n", (ULONG)pnvrobj->self) ;
+ DEBUG_PRINT (1," BE Header addr: 0x%08lx\n", (ULONG)pnvrobj->bhead) ;
+ DEBUG_PRINT (1," LE Header addr: 0x%08lx\n", (ULONG)pnvrobj->lhead) ;
+
+ DEBUG_PRINT (1,"=============== NVRAM LITTLE-ENDIAN DISPLAY ===============\n") ;
+ DEBUG_PRINT (1," Size: %dK, Version %d.%d CRC1=0x%04X CRC2=0x%04X Endian: '%c'\n",
+ (int)hp->Size,
+ (int)hp->Version, (int)hp->Revision,
+ (int)hp->Crc1,
+ (int)hp->Crc2,
+ hp->Endian
+ ) ;
+
+ // Show the serial number
+ for ( i=0 ;
+ i < sizeof(hp->Security.Serial)
+ && i < (sizeof(buf)-2)
+ && (tmp=hp->Security.Serial[i]) ;
+ i++
+ )
+ buf[i] = tmp ;
+ buf[i] = '\0' ; // terminate the string
+ DEBUG_PRINT (1," Serial: '%s'\n",buf) ;
+
+ DEBUG_PRINT (1," ---- GEAddress: 0x%08lx GELength: 0x%08lx\n",
+ hp->GEAddress, hp->GELength) ;
+ cp = (PUCHAR)((ULONG)hp + (ULONG)hp->GEAddress) ;
+ max = (PUCHAR)((ULONG)cp + hp->GELength) ;
+ while ((*cp) && (cp < max))
+ {
+ DEBUG_PRINT (1," '%s'\n", cp) ;
+ cp += (strlen(cp) + 1) ;
+ }
+
+ DEBUG_PRINT (1," ---- OSAreaAddress: 0x%08lx OSAreaLength: 0x%08lx\n",
+ hp->OSAreaAddress, hp->OSAreaLength) ;
+ cp = (PUCHAR)((ULONG)hp + (ULONG)hp->OSAreaAddress) ;
+ max = (PUCHAR)((ULONG)cp + hp->OSAreaLength) ;
+ while ((*cp) && (cp < max))
+ {
+ DEBUG_PRINT (1," '%s'\n", cp) ;
+ cp += (strlen(cp) + 1) ;
+ }
+
+ DEBUG_PRINT (1," ---- ConfigAddress: 0x%08lx ConfigLength: 0x%08lx Count: 0x%08lx\n",
+ hp->ConfigAddress, hp->ConfigLength, hp->ConfigCount) ;
+}
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+// NOT YET USED; other finds will be written in terms of this one ASAP
+
+// ==
+STATUS_TYPE
+nvr_find_variable (
+ PUCHAR VarName, // name of variable to find
+ PUCHAR ArrayAddr, // address of variable array
+ ULONG ArraySize, // max size of variable array
+ PULONG ni,
+ PULONG vi
+)
+{
+ PUCHAR lvar ;
+ PUCHAR cp ;
+ ULONG i ;
+
+ if ( !VarName || !(*VarName) || !ArrayAddr || !ArraySize )
+ return stat_error ; // bad input
+
+ i = 0 ;
+ while ( TRUE )
+ {
+ lvar = VarName ;
+ *ni = i ; // RETURN Name Index
+ cp = ArrayAddr ;
+
+ // does the variable we want start at this index?
+ while ( i < ArraySize )
+ {
+ /* break if mismatch */
+ if (_toupr_(cp[i]) != _toupr_(*lvar))
+ break ; // mismatch
+ lvar++, i++ ;
+ }
+
+ // if var name matches
+ if ( *lvar == 0 && cp[i] == '=' )
+ {
+ *vi = ++i ; // RETURN Value Index
+ return stat_ok ; // indicate FOUND
+ }
+
+ // no match - set index to start of the next variable
+ if ( i >= ArraySize )
+ return stat_error ;
+ while ( cp[i++] != 0 )
+ {
+ if ( i >= ArraySize )
+ return stat_error ;
+ }
+ }
+}
+
+
+// ==
+STATUS_TYPE
+nvr_set_variable (
+ PUCHAR VarName, // name of variable to add/change
+ PUCHAR VarValue, // value to be set into variable
+ PUCHAR ArrayAddr, // address of variable array
+ ULONG ArraySize // max size of variable array
+)
+{
+ PUCHAR lvar ;
+ PUCHAR cp ;
+ ULONG i ;
+ ULONG ni ;
+ ULONG vi ;
+ ULONG eos ;
+ PUCHAR str ;
+ ULONG count ;
+ CHAR c ;
+
+ if ( !VarName || !(*VarName) || !ArrayAddr || !ArraySize )
+ return stat_error ; // bad input
+
+// MORE; NOT QUITE READY FOR PRIME TIME
+// Convert to use pointers throughout instead of indexes (including
+// calling convention). At some future time this function will be one
+// of the basic blocks for dealing with NVRAM directly (no buffers),
+// IF the hardware folk say it's OK.
+
+ // find the end of the used space by looking for
+ // the first non-null character from the top
+ eos = ArraySize - 1 ;
+ while ( ArrayAddr[--eos] == 0 )
+ {
+ if ( eos == 0 )
+ break ;
+ }
+
+ // position eos to the first new character, unless
+ // environment space is empty
+ if ( eos != 0 )
+ eos += 2 ;
+
+ count = ArraySize - eos ;
+
+ // find out if the variable already has a value
+ if ( nvr_find_variable(VarName,ArrayAddr,ArraySize,&ni,&vi) == stat_ok )
+ {
+ // The VarName already exists. See if there is room to
+ // substitute it with the new one.
+
+ // count free space
+ // start with the free area at the top and add
+ // the old ni value
+ for ( str = &(ArrayAddr[vi]) ; *str != 0 ; str++ )
+ count++ ;
+
+ // if free area is not large enough to handle new value,
+ // return an error
+ for ( str = VarValue ; *str != 0 ; str++ )
+ {
+ if ( count-- == 0 )
+ return stat_error ;
+ }
+
+ // pack strings
+ // first move vi to the end of the value
+ while ( ArrayAddr[vi++] != 0 )
+ ;
+
+ // now move everything to where the variable starts
+ // covering up the old name/value pair
+ while ( vi < eos )
+ {
+ c = ArrayAddr[vi++] ;
+ ArrayAddr[ni++] = c ;
+ }
+
+ // adjust new top of environment
+ eos = ni ;
+
+ // zero to the end of OS area
+ while ( ni < ArraySize )
+ ArrayAddr[ni++] = 0 ;
+ }
+ else
+ {
+ // variable is new
+ // if free area is not large enough to handle new value return error
+ for ( str = VarValue ; *str != 0 ; str++ )
+ {
+ if ( count-- == 0 )
+ return stat_error ;
+ }
+ }
+
+ // At this point any existing variable by the name specified has been
+ // removed. If there is no new value to be added, we're done
+
+ if ( *VarValue )
+ {
+ // insert new name, converting to upper case.
+ while ( *VarName )
+ {
+ ArrayAddr[eos++] = *VarName++ ;
+ }
+ ArrayAddr[eos++] = '=' ;
+
+ // insert new value, leaving case alone
+ while ( *VarValue )
+ ArrayAddr[eos++] = *VarValue++ ;
+ }
+ return stat_ok;
+
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+// ==
+STATUS_TYPE
+nvr_find_OS_variable (
+ PUCHAR var,
+ PULONG ni,
+ PULONG vi
+)
+{
+ PUCHAR cp ;
+ HEADER * lhp ;
+
+ if ( !pnvrobj || !var || !(*var) )
+ return stat_error ;
+
+ lhp = (HEADER*)pnvrobj->lhead ;
+ cp = (PUCHAR)((ULONG)lhp + (ULONG)(lhp->OSAreaAddress)) ;
+
+ return ( nvr_find_variable(var,cp,lhp->OSAreaLength,ni,vi) ) ;
+}
+
+
+// ==
+STATUS_TYPE
+nvr_find_GE_variable (
+ PUCHAR var,
+ PULONG ni,
+ PULONG vi
+)
+{
+ PUCHAR cp ;
+ HEADER * lhp ;
+
+ if ( !pnvrobj || !var || !(*var) )
+ return stat_error ;
+
+ lhp = (HEADER*)pnvrobj->lhead ;
+ cp = (PUCHAR)((ULONG)lhp + (ULONG)(lhp->GEAddress)) ;
+
+ return ( nvr_find_variable(var,cp,lhp->GELength,ni,vi) ) ;
+}
+
+
+// ==
+PUCHAR
+nvr_get_OS_variable (
+ PUCHAR vname
+)
+{
+ ULONG ni ;
+ ULONG vi ;
+ ULONG i ;
+ PNVRAM_MAP lep ;
+ PUCHAR array ;
+
+ if ( !pnvrobj || !vname || !(*vname) )
+ return NULL ;
+
+ if (nvr_find_OS_variable(vname, &ni, &vi) != stat_ok)
+ return NULL ;
+
+ lep = (PNVRAM_MAP)pnvrobj->lend ;
+ array = (PUCHAR)((ULONG)lep + (ULONG)(lep->Header.OSAreaAddress)) ;
+
+ for ( i = 0 ; i < MAXIMUM_ENVIRONMENT_VALUE - 1 ; i++ )
+ {
+ if ( array[vi] == 0 )
+ break ;
+ _currentstring[i] = array[vi++] ;
+ }
+ _currentstring[i] = 0 ;
+
+ return ( _currentstring ) ;
+}
+
+
+// USED_BY_HAL: also SFENVIR.C
+
+// ==
+PUCHAR
+nvr_get_GE_variable (
+ PUCHAR vname
+)
+{
+ ULONG ni ;
+ ULONG vi ;
+ ULONG i ;
+ PUCHAR cp ;
+ HEADER* lhp ;
+
+ if ( !pnvrobj || !vname || !(*vname) )
+ return NULL ;
+
+ if (nvr_find_GE_variable(vname, &ni, &vi) != stat_ok)
+ return NULL ;
+
+ lhp = (HEADER*)pnvrobj->lhead ;
+ cp = (PUCHAR)((ULONG)lhp + (ULONG)lhp->GEAddress) ;
+
+ for (i = 0 ; i < MAXIMUM_ENVIRONMENT_VALUE - 1 ; i++)
+ {
+ if (cp[vi] == 0)
+ {
+ break ;
+ }
+ _currentstring[i] = cp[vi++] ;
+ }
+ _currentstring[i] = 0 ;
+
+// DEBUG_PRINT (1,"get_GE vname: '%s' value: '%s'\n", vname, _currentstring);
+
+ return (_currentstring) ;
+}
+
+
+// ==
+STATUS_TYPE
+nvr_set_OS_variable (
+ PUCHAR vname,
+ PUCHAR value
+)
+{
+ ULONG nameindex ;
+ ULONG valueindex ;
+ ULONG eos ;
+ PUCHAR str ;
+ ULONG count ;
+ CHAR c ;
+ PUCHAR aptr ;
+ HEADER* lhp ;
+
+ if ( !pnvrobj || !vname || !value || !(*vname) )
+ return stat_error ;
+
+ lhp = (HEADER*)pnvrobj->lhead ;
+
+// DEBUG_PRINT (1,"OS vname: '%s' value: '%s'\n", vname, value);
+
+ /* initialize pointer to OS area */
+ aptr = (PUCHAR)((ULONG)lhp + (ULONG)lhp->OSAreaAddress) ;
+
+ // find the end of the used OS space by looking for
+ // the first non-null character from the top
+ eos = lhp->OSAreaLength - 1 ;
+ while (aptr[--eos] == 0)
+ {
+ if (eos == 0)
+ break ;
+ }
+
+ // position eos to the first new character, unless
+ // environment space is empty
+ if (eos != 0)
+ eos += 2 ;
+
+ // find out if the variable already has a value
+ count = lhp->OSAreaLength - eos ;
+ if (nvr_find_OS_variable(vname, &nameindex, &valueindex) == stat_ok)
+ {
+ // count free space
+ // start with the free area at the top and add
+ // the old nameindex value
+ for (str = &(aptr[valueindex]) ; *str != 0 ; str++)
+ count++ ;
+
+ // if free area is not large enough to handle new value return error
+ for (str = value ; *str != 0 ; str++)
+ {
+ if ( count-- == 0 )
+ return stat_error ;
+ }
+
+ // pack strings
+ // first move valueindex to the end of the value
+ while (aptr[valueindex++] != 0)
+ ;
+
+ // now move everything to where the variable starts
+ // covering up the old name/value pair
+ while (valueindex < eos)
+ {
+ c = aptr[valueindex++] ;
+ aptr[nameindex++] = c ;
+ }
+
+ // adjust new top of environment
+ eos = nameindex ;
+
+ // zero to the end of OS area
+ while (nameindex < lhp->OSAreaLength)
+ aptr[nameindex++] = 0 ;
+ }
+ else
+ {
+ // variable is new
+ // if free area is not large enough to handle new value return error
+ for (str = value ; *str != 0 ; str++)
+ {
+ if (count-- == 0)
+ return stat_error ;
+ }
+ }
+
+ /* if value is null, we have removed the variable */
+ if (*value)
+ {
+ // insert new name, converting to upper case.
+ while ( *vname )
+ {
+ aptr[eos++] = *vname++ ;
+ }
+ aptr[eos++] = '=' ;
+
+ // insert new value
+ while ( *value )
+ {
+ aptr[eos++] = *value ;
+ value++ ;
+ }
+ }
+
+ nvr_write_OSArea(pnvrobj) ;
+
+ return stat_ok ;
+}
+
+
+// USED_BY_HAL:
+
+// ==
+STATUS_TYPE
+nvr_set_GE_variable (
+ PUCHAR vname,
+ PUCHAR value
+)
+{
+ ULONG nameindex ;
+ ULONG valueindex ;
+ ULONG toe ;
+ PUCHAR str ;
+ ULONG count ;
+ CHAR c ;
+ PUCHAR aptr ;
+ HEADER* lhp ;
+
+ if ( !pnvrobj || !vname || !(*vname) )
+ return stat_error ; // invalid input
+
+ lhp = (HEADER*)pnvrobj->lhead ;
+
+ DEBUG_PRINT (3,"set_GE vname: '%s' value: '%s'\n", vname, value) ;
+
+ /* initialize pointer to GE area */
+ aptr = (PUCHAR)((ULONG)lhp + (ULONG)lhp->GEAddress) ;
+
+ /* find the top of the used environment space by looking for */
+ /* the first non-null character from the top */
+ toe = lhp->GELength - 1 ;
+ aptr = (PUCHAR)((ULONG)lhp + (ULONG)lhp->GEAddress) ;
+ while (aptr[--toe] == 0)
+ {
+ if (toe == 0)
+ break ;
+ }
+
+ /* adjust toe to the first new character, unless */
+ /* environment space is empty */
+ if (toe != 0)
+ toe += 2 ;
+
+ /* find out if the variable already has a value */
+ count = lhp->GELength - toe ;
+
+ if (nvr_find_GE_variable(vname, &nameindex, &valueindex) == stat_ok)
+ {
+ /* count free space */
+ /* start with the free area at the top and add */
+ /* the old nameindex value */
+ for (str = &(aptr[valueindex]) ; *str != 0 ; str++)
+ count++ ;
+
+ /* if free area is not large enough to handle new value return error */
+ if (value)
+ {
+ for (str = value ; *str != 0 ; str++)
+ {
+ if (count-- == 0)
+ return stat_error ;
+ }
+ }
+
+ /* pack strings */
+ /* first move valueindex to the end of the value */
+ while (aptr[valueindex++] != 0)
+ ;
+
+ /* now move everything to where the variable starts */
+ /* covering up the old name/value pair */
+ while (valueindex < toe)
+ {
+ c = aptr[valueindex++] ;
+ aptr[nameindex++] = c ;
+ }
+
+ /* adjust new top of environment */
+ toe = nameindex ;
+
+ /* zero to the end of GE area */
+ while (nameindex < lhp->GELength)
+ aptr[nameindex++] = 0 ;
+ }
+ else
+ {
+ /* variable is new */
+ /* if free area is not large enough to handle new value return error */
+ if (value)
+ {
+ for (str = value ; *str != 0 ; str++)
+ {
+ if (count-- == 0)
+ return stat_error ;
+ }
+ }
+ }
+
+ /* if value is null or is a pointer to a 0 */
+ /* the variable has been removed */
+
+ if ( value && *value )
+ {
+ /* insert new name, converting to upper case */
+ while ( *vname )
+ {
+ aptr[toe] = *vname++ ;
+ toe++ ;
+ }
+ aptr[toe++] = '=' ;
+
+ /* insert new value */
+ while ( *value )
+ {
+ aptr[toe] = *value ;
+ value++ ;
+ toe++ ;
+ }
+ }
+
+ nvr_write_GEArea(pnvrobj) ;
+
+ return stat_ok ;
+}
+
+
+// ==
+PUCHAR
+nvr_fetch_GE (
+ VOID
+)
+{
+ ULONG i ;
+ ULONG toe ;
+ PUCHAR aptr ;
+ HEADER* lhp ;
+ PNVRAM_MAP lep ;
+
+ if (!pnvrobj)
+ return NULL ;
+
+ lep = (PNVRAM_MAP) pnvrobj->lend ;
+
+ NvrCopyFill (pnvrobj->lend + (ULONG)lep->Header.GEAddress,
+ lep->Header.GELength) ;
+
+ return (_currentfetch) ;
+}
+
+
+// ==
+ULONG
+nvr_stat_GE (
+ PULONG size
+)
+{
+ ULONG i ;
+ ULONG toe ;
+ PUCHAR aptr ;
+ HEADER* lhp ;
+ ULONG free ;
+
+ if ( !pnvrobj )
+ return 0 ;
+
+ /* initialize pointers to GE area */
+ lhp = (HEADER*) pnvrobj->lhead ;
+ aptr = (PUCHAR) ((ULONG)lhp + (ULONG)lhp->GEAddress) ;
+
+ /* return original size to caller */
+ if (size)
+ *size = lhp->GELength ;
+
+ /* find the top of the used environment space by looking for */
+ /* the first non-null character from the top */
+ toe = lhp->GELength - 1 ;
+ free = 0 ;
+ while ((aptr[--toe]) == 0)
+ {
+ free++ ;
+ if (toe == 0)
+ break ;
+ }
+
+ return ( free ) ;
+}
+
+
+// ==
+PUCHAR
+nvr_fetch_OS (
+ VOID
+)
+{
+ ULONG i ;
+ ULONG toe ;
+ PNVRAM_MAP lep ;
+
+ if ( !pnvrobj )
+ return NULL ;
+
+ lep = (PNVRAM_MAP) pnvrobj->lend ;
+
+ NvrCopyFill (pnvrobj->lend + (ULONG)lep->Header.OSAreaAddress,
+ lep->Header.OSAreaLength) ;
+
+ return ( _currentfetch ) ;
+}
+
+
+// ==
+PUCHAR
+nvr_fetch_CF (
+ VOID
+)
+{
+ ULONG i ;
+ PNVRAM_MAP lep ; // LE ptr to NVRAM volatile image
+
+ if ( !pnvrobj )
+ return NULL ;
+
+ lep = (PNVRAM_MAP) pnvrobj->lend ;
+
+ NvrCopyFill (pnvrobj->lend + (ULONG)lep->Header.ConfigAddress,
+ lep->Header.ConfigLength) ;
+
+ return ( _currentfetch ) ;
+}
+
+
+// ==
+VOID
+NvrCopyFill (
+ PVOID src,
+ ULONG srclen
+)
+// Fill the _currentfetch area from the source described, then fill the
+// remainder of the buffer with zeros. The same buffer is used to pass
+// several areas, and it is the callers responsibility to copy each one
+// if required before fetching another area.
+{
+ PUCHAR srcp = (PUCHAR)src ;
+ PUCHAR dstp = _currentfetch ;
+ ULONG dstlen = MAXNVRFETCH ;
+
+ while ( dstlen-- )
+ {
+ if ( srclen )
+ *dstp++ = *srcp++, srclen-- ;
+ else
+ *dstp++ = 0 ;
+ }
+}
+
+
+
+#ifdef _HALNVR_
+/////////////////////////////////////////////////////////////////////////////
+// Resolve references to debug functions provided by ARC that are not part
+// of the HAL environment. Currently these merely disable the debugging
+// features when used in the HAL, but could be expanded later to provide
+// the same features available in ARC.
+/////////////////////////////////////////////////////////////////////////////
+
+VOID
+DEBUG_PRINT (
+ LONG DebugLevelReqd,
+ PCHAR DebugMessage,
+ ...
+)
+{
+}
+
+VOID
+DEBUG_BREAK (
+ LONG DebugLevelReqd
+)
+{
+}
+
+LONG
+DEBUG_GETLEVEL ()
+{
+ return 0 ;
+}
+
+LONG
+DEBUG_GETREGION ()
+{
+ return 0 ;
+}
+
+#endif
+
diff --git a/private/ntos/nthals/halppc/ppc/fwnvr.h b/private/ntos/nthals/halppc/ppc/fwnvr.h
new file mode 100644
index 000000000..c326bc596
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/fwnvr.h
@@ -0,0 +1,313 @@
+//
+// FWNVR.H
+//
+// Prototypes for FWNVR.C
+// (automatically generated by CPROTO)
+//
+
+#ifndef _CPROTO_FWNVR_
+#define _CPROTO_FWNVR_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+PNVR_OBJECT
+nvr_alloc (
+ ULONG size
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_free (
+ PVOID p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+BOOLEAN
+NvrSetSize (
+ LONG NvramSize // size of NVRAM in bytes if non-zero
+);
+
+
+BOOLEAN
+NvrSetMethod (
+ LONG ForcedValue // if Non-zero, set to this value regardless
+);
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+UCHAR
+nvr_read (
+ ULONG addr
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_write (
+ ULONG addr,
+ UCHAR data
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_swap_Header (
+ HEADER* dest,
+ HEADER* src
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_headb2l (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_headl2b (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_default_nvram (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+BOOLEAN
+nvr_read_nvram (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_read_GEArea (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_read_OSArea (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_read_CFArea (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_write_Header (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_write_GEArea (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_write_OSArea (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_write_CFArea (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+VOID
+nvr_delete_object (
+ VOID
+);
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+PNVR_OBJECT
+nvr_create_object (
+ VOID
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+STATUS_TYPE
+nvr_initialize_object (
+ LONG AccessMethod,
+ ULONG Size // NVR size in bytes
+);
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+VOID
+nvr_clear_nvram (
+ VOID
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+VOID
+nvr_destroy (
+ LONG AccessMethod,
+ ULONG Size // size of NVRAM
+);
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+ULONG
+nvr_computecrc (
+ ULONG oldcrc,
+ UCHAR data
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+USHORT
+nvr_calc1crc (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+#ifdef _CPROTO_FWNVR_STATICS_
+USHORT
+nvr_calc2crc (
+ PNVR_OBJECT p
+);
+#endif // _CPROTO_FWNVR_STATICS_
+
+
+VOID
+nvr_print_object (
+ VOID
+);
+
+
+STATUS_TYPE
+nvr_find_variable (
+ PUCHAR VarName, // name of variable to find
+ PUCHAR ArrayAddr, // address of variable array
+ ULONG ArraySize, // max size of variable array
+ PULONG ni,
+ PULONG vi
+);
+
+
+STATUS_TYPE
+nvr_set_variable (
+ PUCHAR VarName, // name of variable to add/change
+ PUCHAR VarValue, // value to be set into variable
+ PUCHAR ArrayAddr, // address of variable array
+ ULONG ArraySize // max size of variable array
+);
+
+
+STATUS_TYPE
+nvr_find_OS_variable (
+ PUCHAR var,
+ PULONG ni,
+ PULONG vi
+);
+
+
+STATUS_TYPE
+nvr_find_GE_variable (
+ PUCHAR var,
+ PULONG ni,
+ PULONG vi
+);
+
+
+PUCHAR
+nvr_get_OS_variable (
+ PUCHAR vname
+);
+
+
+PUCHAR
+nvr_get_GE_variable (
+ PUCHAR vname
+);
+
+
+STATUS_TYPE
+nvr_set_OS_variable (
+ PUCHAR vname,
+ PUCHAR value
+);
+
+
+STATUS_TYPE
+nvr_set_GE_variable (
+ PUCHAR vname,
+ PUCHAR value
+);
+
+
+PUCHAR
+nvr_fetch_GE (
+ VOID
+);
+
+
+ULONG
+nvr_stat_GE (
+ PULONG size
+);
+
+
+PUCHAR
+nvr_fetch_OS (
+ VOID
+);
+
+
+PUCHAR
+nvr_fetch_CF (
+ VOID
+);
+
+
+VOID
+NvrCopyFill (
+ PVOID src,
+ ULONG srclen
+);
+
+
+#endif // _CPROTO_FWNVR_
diff --git a/private/ntos/nthals/halppc/ppc/fwstatus.h b/private/ntos/nthals/halppc/ppc/fwstatus.h
new file mode 100644
index 000000000..fd09e6363
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/fwstatus.h
@@ -0,0 +1,17 @@
+#ifndef _FWSTATUS_H_
+#define _FWSTATUS_H_
+
+typedef enum _status_type {
+ stat_ok = 0,
+ stat_warning = 1,
+ stat_exist = 2,
+ stat_error = 3,
+ stat_badptr = 4,
+ stat_notexist = 5,
+ stat_noentry = 6,
+ stat_checksum = 7,
+ stat_badlength = 8,
+ stat_last = 0x40
+ } STATUS_TYPE;
+
+#endif /* _FWSTATUS_H_ */
diff --git a/private/ntos/nthals/halppc/ppc/halp.h b/private/ntos/nthals/halppc/ppc/halp.h
new file mode 100644
index 000000000..5220e95d8
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/halp.h
@@ -0,0 +1,503 @@
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Added PPC specific includes
+ Changed paramaters to HalpProfileInterrupt
+ Added function prototype for HalpWriteCompareRegisterAndClear()
+ Added include for ppcdef.h
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#if defined(NT_UP)
+
+#undef NT_UP
+
+#endif
+
+#include "nthal.h"
+
+
+#include "ppcdef.h"
+
+#include "hal.h"
+#include "pxhalp.h"
+
+#include "xm86.h"
+#include "x86new.h"
+
+#include "pci.h"
+
+
+
+
+//
+// Resource usage information
+//
+
+#define MAXIMUM_IDTVECTOR 255
+
+typedef struct {
+ UCHAR Flags;
+ KIRQL Irql;
+ UCHAR BusReleativeVector;
+} IDTUsage;
+
+typedef struct _HalAddressUsage{
+ struct _HalAddressUsage *Next;
+ CM_RESOURCE_TYPE Type; // Port or Memory
+ UCHAR Flags; // same as IDTUsage.Flags
+ struct {
+ ULONG Start;
+ USHORT Length;
+ } Element[];
+} ADDRESS_USAGE;
+
+#define IDTOwned 0x01 // IDT is not available for others
+#define InterruptLatched 0x02 // Level or Latched
+#define InternalUsage 0x11 // Report usage on internal bus
+#define DeviceUsage 0x21 // Report usage on device bus
+
+extern IDTUsage HalpIDTUsage[];
+extern ADDRESS_USAGE *HalpAddressUsageList;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
+extern ULONG HalpPciMaxBuses; // in pxpcibus.c
+
+
+//
+// Define PER processor HAL data.
+//
+// This structure is assigned the address &PCR->HalReserved which is
+// an array of 16 ULONGs in the architectually defined section of the
+// PCR.
+//
+
+typedef struct {
+ ULONG HardPriority;
+} UNIPROCESSOR_DATA, *PUNIPROCESSOR_DATA;
+
+#define HALPCR ((PUNIPROCESSOR_DATA)&PCR->HalReserved)
+
+#define HalpGetProcessorVersion() KeGetPvr()
+
+//
+// Override standard definition of _enable/_disable for errata 15.
+//
+
+#if defined(_enable)
+
+#undef _enable
+#undef _disable
+
+#endif
+
+#if _MSC_VER < 1000
+
+//
+// MCL
+//
+
+VOID __builtin_set_msr(ULONG);
+ULONG __builtin_get_msr(VOID);
+VOID __builtin_eieio();
+VOID __builtin_isync();
+
+#define _enable() \
+ __builtin_set_msr(__builtin_get_msr() | 0x00008000)
+
+#define _disable() \
+ __builtin_set_msr(__builtin_get_msr() & 0xFFFF7FFF)
+
+#define ERRATA15WORKAROUND() __builtin_isync()
+
+#else
+
+//
+// VC++
+//
+
+#define _enable() \
+ (__sregister_set(_PPC_MSR_, __sregister_get(_PPC_MSR_) | 0x00008000))
+#define _disable() \
+ (__sregister_set(_PPC_MSR_, __sregister_get(_PPC_MSR_) & 0xffff7fff))
+
+//
+// Errata 15 can use a cror 0,0,0 instruction which is kinder/gentler
+// than an isync.
+//
+
+#define ERRATA15WORKAROUND() __emit(0x4c000382)
+
+#endif
+
+#if !defined(WOODFIELD)
+
+#define HalpEnableInterrupts() _enable()
+#define HalpDisableInterrupts() _disable()
+
+#else
+
+#define HalpEnableInterrupts() (_enable(),ERRATA15WORKAROUND())
+#define HalpDisableInterrupts() (_disable(),ERRATA15WORKAROUND())
+
+#endif
+
+#define KeFlushWriteBuffer() __builtin_eieio()
+
+//
+// Bus handlers
+//
+
+
+PBUS_HANDLER HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN BUS_DATA_TYPE ParentBusDataType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+
+#define HalpAllocateConfigSpace HalpAllocateBusHandler
+
+#define HalpHandlerForBus HaliHandlerForBus
+
+#define SPRANGEPOOL NonPagedPool // for now, until crashdump is fixed
+#define HalpHandlerForBus HaliHandlerForBus
+#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
+
+PSUPPORTED_RANGES
+HalpMergeRanges (
+ IN PSUPPORTED_RANGES Parent,
+ IN PSUPPORTED_RANGES Child
+ );
+
+VOID
+HalpMergeRangeList (
+ PSUPPORTED_RANGE NewList,
+ PSUPPORTED_RANGE Source1,
+ PSUPPORTED_RANGE Source2
+ );
+
+PSUPPORTED_RANGES
+HalpConsolidateRanges (
+ PSUPPORTED_RANGES Ranges
+ );
+
+PSUPPORTED_RANGES
+HalpAllocateNewRangeList (
+ VOID
+ );
+
+VOID
+HalpFreeRangeList (
+ PSUPPORTED_RANGES Ranges
+ );
+
+PSUPPORTED_RANGES
+HalpCopyRanges (
+ PSUPPORTED_RANGES Source
+ );
+
+VOID
+HalpAddRangeList (
+ IN OUT PSUPPORTED_RANGE DRange,
+ OUT PSUPPORTED_RANGE SRange
+ );
+
+VOID
+HalpAddRange (
+ PSUPPORTED_RANGE HRange,
+ ULONG AddressSpace,
+ LONGLONG SystemBase,
+ LONGLONG Base,
+ LONGLONG Limit
+ );
+
+VOID
+HalpRemoveRanges (
+ IN OUT PSUPPORTED_RANGES Minuend,
+ IN PSUPPORTED_RANGES Subtrahend
+ );
+
+VOID
+HalpRemoveRangeList (
+ IN OUT PSUPPORTED_RANGE Minuend,
+ IN PSUPPORTED_RANGE Subtrahend
+ );
+
+
+VOID
+HalpRemoveRange (
+ PSUPPORTED_RANGE HRange,
+ LONGLONG Base,
+ LONGLONG Limit
+ );
+
+VOID
+HalpDisplayAllBusRanges (
+ VOID
+ );
+
+
+//
+// Define function prototypes.
+//
+
+// begin POWER_MANAGEMENT
+
+VOID
+HalInitSystemPhase2(
+ VOID
+ );
+// end POWER_MANAGEMENT
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+VOID
+HalpCopyBiosShadow(
+ VOID
+ );
+
+VOID
+HalpInitializeX86DisplayAdapter(
+ ULONG VideoDeviceBusNumber,
+ ULONG VideoDeviceSlotNumber
+ );
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+BOOLEAN
+HalpCacheSweepSetup(
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+KINTERRUPT_MODE
+HalpGetInterruptMode(
+ ULONG,
+ KIRQL,
+ KINTERRUPT_MODE
+ );
+
+VOID
+HalpSetInterruptMode(
+ ULONG,
+ KIRQL
+ );
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG,
+ ULONG
+ );
+
+BOOLEAN
+HalpInitPciIsaBridge (
+ VOID
+ );
+
+VOID
+HalpHandleIoError (
+ VOID
+ );
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ );
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ );
+
+BOOLEAN
+HalpHandleProfileInterrupt (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+
+BOOLEAN
+HalpInitSuperIo(
+ VOID
+ );
+
+BOOLEAN
+HalpEnableInterruptHandler (
+ IN PKINTERRUPT Interrupt,
+ IN PKSERVICE_ROUTINE ServiceRoutine,
+ IN PVOID ServiceContext,
+ IN PKSPIN_LOCK SpinLock OPTIONAL,
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KIRQL SynchronizeIrql,
+ IN KINTERRUPT_MODE InterruptMode,
+ IN BOOLEAN ShareVector,
+ IN CCHAR ProcessorNumber,
+ IN BOOLEAN FloatingSave,
+ IN UCHAR ReportFlags,
+ IN KIRQL BusVector
+ );
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ );
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+
+NTSTATUS
+HalpAdjustResourceListLimits (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN ULONG MinimumMemoryAddress,
+ IN ULONG MaximumMemoryAddress,
+ IN ULONG MinimumPrefetchMemoryAddress,
+ IN ULONG MaximumPrefetchMemoryAddress,
+ IN BOOLEAN LimitedIOSupport,
+ IN ULONG MinimumPortAddress,
+ IN ULONG MaximumPortAddress,
+ IN PUCHAR IrqTable,
+ IN ULONG IrqTableLength,
+ IN ULONG MinimumDmaChannel,
+ IN ULONG MaximumDmaChannel
+ );
+
+NTSTATUS
+HalpGetPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+VOID
+HalpPhase0DiscoverPciBuses(
+ IN PCONFIGURATION_COMPONENT_DATA Component
+ );
+
+
+#ifdef POWER_MANAGEMENT
+VOID
+HalpInitInterruptController (
+ VOID
+ );
+
+VOID
+HalpInitDmaController (
+ VOID
+ );
+
+VOID
+HalpRemakeBeep (
+ VOID
+ );
+
+VOID
+HalpResetProfileInterval (
+ VOID
+ );
+
+#endif // POWER_MANAGEMENT
+
+VOID
+HalpProcessorIdle(
+ VOID
+ );
+
+VOID
+HalpSetDpm(
+ VOID
+ );
+
+//
+// Define external references.
+//
+
+extern KSPIN_LOCK HalpBeepLock;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+extern KAFFINITY HalpIsaBusAffinity;
+extern ULONG HalpProfileCount;
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+
+
+#define IRQ_VALID 0x01
+#define IRQ_PREFERRED 0x02
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halppc/ppc/ibmppc.h b/private/ntos/nthals/halppc/ppc/ibmppc.h
new file mode 100644
index 000000000..a110f90bf
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/ibmppc.h
@@ -0,0 +1,60 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ ibmppc.h
+
+Abstract:
+
+ This header file defines the enumerated types and "strings" used
+ to identify the various IBM PowerPC (PReP/CHRP) machines.
+
+
+Author:
+
+ Peter Johnston
+
+
+Revision History:
+
+--*/
+
+//
+// Define systems understoof by the "multi" system HAL.
+//
+
+typedef enum _IBM_SYSTEM_TYPES {
+ IBM_UNKNOWN,
+ IBM_VICTORY,
+ IBM_DORAL,
+ IBM_TIGER
+} IBM_SYSTEM_TYPE;
+
+extern IBM_SYSTEM_TYPE HalpSystemType;
+
+//
+// The following strings are passed in from ARC in the
+// SystemClass/ArcSystem registry variable.
+//
+// The following entries are examined for an EXACT match.
+
+#define SID_IBM_SANDAL "IBM-6015"
+#define SID_IBM_WOOD "IBM-6020"
+#define SID_IBM_WILTWICK "IBM-6040"
+#define SID_IBM_WOODPRIME "IBM-6042"
+#define SID_IBM_CAROLINA "IBM-6070"
+#define SID_IBM_OXFORD "IBM-6035"
+#define SID_IBM_VICTORY "IBM-VICT"
+#define SID_IBM_DORAL "IBM-7043"
+#define SID_IBM_TERLINGUA "IBM-7442"
+#define SID_IBM_HARLEY "IBM-Harley"
+#define SID_IBM_KONA "IBM-Kona"
+#define SID_IBM_ZAPATOS "IBM-Zapatos"
+#define SID_IBM_TIGER "IBM-7042"
+
+// If comparisons against the above failed, we check for
+// entries that start with the following.
+
+#define SID_IBM_DORAL_START "IBM PPS Model 7043"
+#define SID_IBM_TERLINGUA_START "IBM PPS Model 7442"
diff --git a/private/ntos/nthals/halppc/ppc/pcip.h b/private/ntos/nthals/halppc/ppc/pcip.h
new file mode 100644
index 000000000..ea4d55264
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pcip.h
@@ -0,0 +1,186 @@
+//
+// Hal specific PCI bus structures
+//
+
+typedef NTSTATUS
+(*PciIrqRange) (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+typedef struct tagPCIPBUSDATA {
+
+ //
+ // Defined PCI data
+ //
+
+ PCIBUSDATA CommonData;
+
+ //
+ // Implementation specific data
+ //
+
+ union {
+ struct {
+ PULONG Address;
+ ULONG Data;
+ } Type1;
+ struct {
+ PVOID Address;
+ PVOID Data;
+ ULONG Fill0;
+ } Type2;
+ } Config;
+
+ ULONG MaxDevice;
+ PciIrqRange GetIrqRange;
+
+ BOOLEAN BridgeConfigRead;
+ UCHAR ParentBus;
+ UCHAR reserved[2];
+ UCHAR SwizzleIn[4];
+
+ RTL_BITMAP DeviceConfigured;
+ ULONG ConfiguredBits[PCI_MAX_DEVICES * PCI_MAX_FUNCTION / 32];
+} PCIPBUSDATA, *PPCIPBUSDATA;
+
+#define PciBitIndex(Dev,Fnc) (Fnc*32 + Dev);
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+#define Is64BitBaseAddress(a) \
+ (((a & PCI_ADDRESS_IO_SPACE) == 0) && \
+ ((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+
+
+#if DBG
+#define IRQXOR 0x2B
+#else
+#define IRQXOR 0
+#endif
+
+
+//
+// Prototypes for functions in ixpcibus.c
+//
+
+VOID
+HalpInitializePciBus (
+ VOID
+ );
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+PBUS_HANDLER
+HalpAllocateAndInitPciBusHandler (
+ IN ULONG HwType,
+ IN ULONG BusNo,
+ IN BOOLEAN TestAllocation
+ );
+
+
+//
+// Prototypes for functions in ixpciint.c
+//
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ );
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+//
+// Prototypes for functions in ixpcibrd.c
+//
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ );
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ );
+
+//
+//
+//
+
+#ifdef SUBCLASSPCI
+
+VOID
+HalpSubclassPCISupport (
+ IN PBUS_HANDLER BusHandler,
+ IN ULONG HwType
+ );
+
+#endif
diff --git a/private/ntos/nthals/halppc/ppc/prepnvr.h b/private/ntos/nthals/halppc/ppc/prepnvr.h
new file mode 100644
index 000000000..93c8c09bc
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/prepnvr.h
@@ -0,0 +1,134 @@
+/* Structure map for NVRAM on PowerPC Reference Platform */
+
+/* Revision 1 changes (8/25/94):
+ - Power Management (RESTART_BLOCK struct)
+ - Normal added to PM_MODE
+ - OSIRQMask (HEADER struct) */
+
+/* All fields are either character/byte strings which are valid either
+endian or they are big-endian numbers.
+
+There are a number of Date and Time fields which are in RTC format,
+big-endian. These are stored in UT (GMT).
+
+For enum's: if given in hex then they are bit significant, i.e. only
+one bit is on for each enum.
+*/
+
+#ifndef _NVRAM_
+#define _NVRAM_
+
+#define NVSIZE 4096 /* size of NVRAM */
+#define OSAREASIZE 512 /* size of OSArea space */
+#define CONFSIZE 1024 /* guess at size of Configuration space */
+
+typedef struct _SECURITY {
+ unsigned long BootErrCnt; /* Count of boot password errors */
+ unsigned long ConfigErrCnt; /* Count of config password errors */
+ unsigned long BootErrorDT[2]; /* Date&Time from RTC of last error in pw */
+ unsigned long ConfigErrorDT[2]; /* Date&Time from RTC of last error in pw */
+ unsigned long BootCorrectDT[2]; /* Date&Time from RTC of last correct pw */
+ unsigned long ConfigCorrectDT[2]; /* Date&Time from RTC of last correct pw */
+ unsigned long BootSetDT[2]; /* Date&Time from RTC of last set of pw */
+ unsigned long ConfigSetDT[2]; /* Date&Time from RTC of last set of pw */
+ unsigned char Serial[16]; /* Box serial number */
+ } SECURITY;
+
+typedef enum _OS_ID {
+ Unknown = 0,
+ Firmware = 1,
+ AIX = 2,
+ NT = 3,
+ WPOS2 = 4,
+ WPAIX = 5,
+ Taligent = 6,
+ Solaris = 7,
+ Netware = 8,
+ USL = 9,
+ Low_End_Client = 10,
+ SCO = 11
+ } OS_ID;
+
+typedef struct _ERROR_LOG {
+ unsigned char ErrorLogEntry[40]; /* To be architected */
+ } ERROR_LOG;
+
+/*---Revision 1: Change the following struct:---*/
+typedef struct _RESUME_BLOCK {
+ /* Hibernation Resume Device will be an
+ environment variable */
+ unsigned long CheckSum; /* Checksum of RESUME_BLOCK */
+ volatile unsigned long BootStatus;
+
+ void * ResumeAddr; /* For Suspend Resume */
+ void * SaveAreaAddr; /* For Suspend Resume */
+ unsigned long SaveAreaLength; /* For Suspend Resume */
+
+ unsigned long HibResumeImageRBA; /* RBA (512B blocks) of compressed OS
+ memory image to be loaded by FW
+ on Resume from hibernation */
+ unsigned long HibResumeImageRBACount; /* Size of image in 512B blocks*/
+ unsigned long Reserved;
+ } RESUME_BLOCK;
+
+typedef enum _OSAREA_USAGE {
+ Empty = 0,
+ Used = 1
+ } OSAREA_USAGE;
+
+typedef enum _PM_MODE {
+ Suspend = 0x80, /* Part of state is in memory */
+ Hibernate = 0x40, /* Nothing in memory - state saved elsewhere */
+/* Revision 1: Normal added (actually was already here) */
+ Normal = 0x00 /* No power management in effect */
+ } PMMode;
+
+typedef struct _HEADER {
+ unsigned short Size; /* NVRAM size in K(1024) */
+ unsigned char Version; /* Structure map different */
+ unsigned char Revision; /* Structure map the same -
+ may be new values in old fields
+ in other words old code still works */
+ unsigned short Crc1; /* check sum from beginning of nvram to OSArea */
+ unsigned short Crc2; /* check sum of config */
+ unsigned char LastOS; /* OS_ID */
+ unsigned char Endian; /* B if big endian, L if little endian */
+ unsigned char OSAreaUsage; /* OSAREA_USAGE */
+ unsigned char PMMode; /* Shutdown mode */
+ RESUME_BLOCK ResumeBlock;
+ SECURITY Security;
+ ERROR_LOG ErrorLog[2];
+
+/* Global Environment information */
+ void * GEAddress;
+ unsigned long GELength;
+ /* Date&Time from RTC of last change to Global Environment */
+ unsigned long GELastWriteDT[2];
+
+/* Configuration information */
+ void * ConfigAddress;
+ unsigned long ConfigLength;
+ /* Date&Time from RTC of last change to Configuration */
+ unsigned long ConfigLastWriteDT[2];
+ unsigned long ConfigCount; /* Count of entries in Configuration */
+
+/* OS dependent temp area */
+ void * OSAreaAddress;
+ unsigned long OSAreaLength;
+ /* Date&Time from RTC of last change to OSAreaArea */
+ unsigned long OSAreaLastWriteDT[2];
+
+/* Revision 1: add this mask - function tbd */
+ /*unsigned short OSIRQMask; OS to FW IRQ Mask - "I've used this one" */
+ } HEADER;
+
+
+/* Here is the whole map of the NVRAM */
+typedef struct _NVRAM_MAP {
+ HEADER Header;
+ unsigned char GEArea[NVSIZE-CONFSIZE-OSAREASIZE-sizeof(HEADER)];
+ unsigned char OSArea[OSAREASIZE];
+ unsigned char ConfigArea[CONFSIZE];
+ } NVRAM_MAP;
+
+#endif /* ndef _NVRAM_ */
diff --git a/private/ntos/nthals/halppc/ppc/pxbbl.c b/private/ntos/nthals/halppc/ppc/pxbbl.c
new file mode 100644
index 000000000..8584c693e
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxbbl.c
@@ -0,0 +1,1546 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+
+Module Name:
+
+pxbbl.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a PowerPC system using a GXT150P (Baby Blue) video adapter.
+
+Author:
+
+ Jake Oshins
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "string.h"
+
+// Include GXT150P header file information
+#include "bblrastz.h"
+#include "bblrmdac.h"
+#include "bbldef.h"
+
+extern ULONG HalpInitPhase;
+extern PUCHAR HalpVideoMemoryBase;
+extern PUCHAR HalpVideoCoprocBase;
+
+extern ULONG HalpColumn;
+extern ULONG HalpRow;
+extern ULONG HalpHorizontalResolution;
+extern ULONG HalpVerticalResolution;
+
+
+extern USHORT HalpBytesPerRow;
+extern USHORT HalpCharacterHeight;
+extern USHORT HalpCharacterWidth;
+extern ULONG HalpDisplayText;
+extern ULONG HalpDisplayWidth;
+extern ULONG HalpScrollLength;
+extern ULONG HalpScrollLine;
+
+extern BOOLEAN HalpDisplayOwnedByHal;
+
+extern POEM_FONT_FILE_HEADER HalpFontHeader;
+extern ULONG HalpPciMaxSlots;
+
+extern UCHAR TextPalette[];
+
+
+#define TAB_SIZE 4
+
+VOID
+HalpDisplayPpcBBLSetup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterBBL (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterBBL(
+ IN PUCHAR Glyph
+ );
+
+BOOLEAN
+BBLGetConfigurationRegister (
+ IN ULONG dev_ven_id,
+ IN ULONG offset,
+ IN PULONG reg_value
+ );
+
+BOOLEAN
+BBLSetConfigurationRegister (
+ IN ULONG dev_ven_id,
+ IN ULONG offset,
+ IN ULONG reg_value
+ );
+
+VOID
+BBLScrollScreen(
+ VOID
+ );
+
+BOOLEAN
+BBLInitialize (
+ ULONG monID,
+ volatile PUCHAR HalpBBLRegisterBase
+ );
+
+BOOLEAN
+BBLGetMonitorID (
+ PULONG monID,
+ volatile PUCHAR HalpBBLRegisterBase
+ );
+
+VOID
+BBLWaitForVerticalSync (
+ volatile PUCHAR HalpBBLRegisterBase
+ );
+
+
+VOID
+HalpDisplayPpcBBLSetup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the GXT150P Graphics Adapter
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG rc, status, monID, count, value;
+ volatile PUCHAR HalpBBLRegisterBase = (PUCHAR)0;
+ ULONG buffer[(BBL_BELE_VAL + 2) >> 2];
+ PPCI_COMMON_CONFIG PciData;
+ PCI_SLOT_NUMBER PciSlot;
+ bbl_mon_data_t *bbl_mon_data_ptr;
+ BOOLEAN found, ok;
+ PHYSICAL_ADDRESS physaddr;
+
+ PHYSICAL_ADDRESS bbl_phys_address;
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+
+ //
+ // There is no need to have both the register space and the
+ // DFA space mapped at the same time. This will save us from
+ // having multiple I/O spaces mapped at the same time. Thus
+ // saving DBATs which are in very very short supply...
+ //
+
+ //
+ // Strategy:
+ //
+ // 1. Map the PCI configuration register space
+ // 2. Update the PCI configuration registers
+ // 3. Unmap the PCI configuration register space
+ // 4. Map the register space
+ // 5. Reset the device
+ // 6. Read the monitor ID to figure what resolution and refresh mode to use
+ // 7. Perform device re-initialization (rasterizer, ramdac,
+ // and color palette)
+ // 8. Unmap the register space
+ // 9. Map the DFA space
+ // 10. Clear out VRAM to the default background color
+ // 11. Now can do character blits
+ //
+
+ /*******************************************************************/
+ /* S E T P C I C O N F I G U R A T I O N R E G I S T E R S */
+ /*******************************************************************/
+
+ bbl_phys_address.HighPart = 0x0; //PCI bus devices are in a 32-bit memory space
+
+ ok = BBLGetConfigurationRegister (BBL_DEV_VEND_ID,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.BaseAddresses[0]),
+ &bbl_phys_address.LowPart );
+
+ bbl_phys_address.LowPart += PCI_MEMORY_PHYSICAL_BASE; // translate bus-relative address
+
+ if(ok == TRUE){
+ value = BBL_BELE_VAL;
+ ok = BBLSetConfigurationRegister (BBL_DEV_VEND_ID, 0x70, value );
+ }
+ if(ok == FALSE){
+ return;
+ }
+
+ /**************************************************/
+ /* M A P T H E R E G I S T E R S P A C E */
+ /**************************************************/
+
+ //
+ // Map the the adapter register range into memory. Please note that this
+ // adapter will respond to all 256meg of addresses in the address range
+ // given even though we are only temporarily mapping a small region
+ //
+
+
+ if (HalpInitPhase == 0) {
+
+ BBL_DBG_PRINT("call KePhase0MapIo() to map the reg space. Phys=0x%x Len=0x%x %d\n",
+ bbl_phys_address.LowPart + BBL_REG_ADDR_OFFSET,
+ BBL_REG_ADDR_LENGTH,
+ BBL_REG_ADDR_LENGTH);
+
+ HalpBBLRegisterBase = (PUCHAR)KePhase0MapIo(bbl_phys_address.LowPart + BBL_REG_ADDR_OFFSET,
+ BBL_REG_ADDR_LENGTH); // 4 K
+ } else {
+ physaddr.HighPart = 0;
+ physaddr.LowPart = bbl_phys_address.LowPart + BBL_REG_ADDR_OFFSET;
+ HalpBBLRegisterBase = (PUCHAR)MmMapIoSpace(physaddr,
+ BBL_REG_ADDR_LENGTH,
+ FALSE);
+ }
+
+ BBL_DBG_PRINT("HalpBBLRegisterBase = 0x%x\n", HalpBBLRegisterBase);
+
+
+ /**************************************************/
+ /* F I N D F O N T T O U S E */
+ /**************************************************/
+
+ //IBMLAN Use font file from OS Loader
+ //
+ // Compute display variables using using HalpFontHeader which is
+ // initialized in HalpInitializeDisplay().
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+
+ HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = HalpFontHeader->PixelHeight;
+ HalpCharacterWidth = HalpFontHeader->PixelWidth;
+ BBL_DBG_PRINT("PixelWidth = %d PixelHeight = %d\n HalpFontHeader = 0x%x\n",
+ HalpFontHeader->PixelWidth, HalpFontHeader->PixelHeight, HalpFontHeader);
+
+ /*********************************************/
+ /* D I S A B L E V I D E O D I S P L A Y */
+ /*********************************************/
+
+ //
+ // Turn off display outputs from the ramdac so the screen will go
+ // blank while resetting the adapter and resetting it up
+ //
+
+ /*
+ * Disable Video
+ */
+
+ BBL_DBG_PRINT ("disable video display\n");
+
+ /* Set the ramdac configuration to default values and disable */
+ /* display outputs so nothing is displayed on the screen during */
+ /* initialization */
+
+ /* Config low ... */
+ BBL_DBG_PRINT ("Write config register low = 0x%x\n", 0x00);
+ BBL_SET_RAMDAC_ADDRESS_REGS( BBL_REG_BASE, BBL_RAMDAC_CONFIG_LOW_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE, 0x00 );
+
+ /* Config high ... */
+ BBL_DBG_PRINT ("Write config register high = 0x%x\n", 0x08);
+ BBL_SET_RAMDAC_ADDRESS_REGS( BBL_REG_BASE, BBL_RAMDAC_CONFIG_HIGH_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE, 0x08 );
+
+
+ /*********************************************/
+ /* R E S E T C A R D */
+ /*********************************************/
+
+ //
+ // Attempt to reset the card. The only this can be done is to first
+ // read the status register, if the status register indicates that the
+ // FIFO is empty and the adapter is idle, then we're good-to-go. If
+ // the adapter is busy and the FIFO is empty, send a RESET_CURRENT_CMD
+ // down the FIFO and see if the adapter becomes idle. If the adapter
+ // does not become idle after a few milliseconds, send 0x0's down the
+ // command port checking status in between each time for adapter idle.
+ // If, after sending down many 0x0's, or if the adapter FIFO was originally
+ // not empty, we have a hung adapter, and there is absolutely nothing
+ // that we can do, which means we're dead, so return
+ //
+
+ status = BBL_GET_REG(BBL_REG_BASE, BBL_STATUS_REG);
+ if(status & BBL_CACHE_LINE_BUFFER_EMPTY){
+ BBL_DBG_PRINT("adapter FIFO is empty\n");
+ if(status & BBL_ADAPTER_BUSY){
+ BBL_DBG_PRINT("adapter is busy, attempting reset\n");
+ // Send down a RESET_CURRENT_COMMAND to the adapter
+ BBL_SET_REG(BBL_REG_BASE, BBL_RESET_CURRENT_CMD_REG, 0x0);
+ BBL_EIEIO;
+ // Wait to see if the adapter comes back
+ for(count=0;((count < 100000)&&(status & BBL_ADAPTER_BUSY));count++){
+ status = BBL_GET_REG(BBL_REG_BASE, BBL_STATUS_REG);
+ }
+ // If adapter still is busy, attempt sending 0x0's to the
+ // command port to force it to finish whatever it was doing last
+ if(status & BBL_ADAPTER_BUSY){
+ BBL_DBG_PRINT("adapter is still busy, attempting to send NULL command data\n");
+ for(count=0;((count < 10000)&&(status & BBL_ADAPTER_BUSY));count++){
+ BBL_SET_REG(BBL_REG_BASE, BBL_CMD_DATA_REG, 0x0);
+ status = BBL_GET_REG(BBL_REG_BASE, BBL_STATUS_REG);
+ }
+ // If we're still hung, we're dead, so just return
+ if(status & BBL_ADAPTER_BUSY){
+ BBL_DBG_PRINT("adapter hung, giving up\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return;
+ }else{
+ BBL_DBG_PRINT("adapter is NOT busy, sent NULL cmd/data down for %d loops\n", count);
+ }
+ }else{
+ BBL_DBG_PRINT("adapter is NOT busy, waited for %d loops\n", count);
+ }
+ }else{
+ BBL_DBG_PRINT("adapter is NOT busy\n");
+ }
+ }else{
+ // The adapter FIFO is not empty which indicates that it is hung, so return
+ BBL_DBG_PRINT("adapter FIFO is not empty\n");
+ BBL_DBG_PRINT("adapter hung, giving up\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+
+ /*********************************************/
+ /* G E T M O N I T O R I D */
+ /*********************************************/
+
+ //
+ // Read the monitor ID from the card to determine what resolution
+ // to use
+ //
+
+ if(BBLGetMonitorID(&monID, HalpBBLRegisterBase) == FALSE){
+ BBL_DBG_PRINT("BBLGetMonitorID() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+ //
+ // Find the correct monitor ID information structure based on
+ // the monitor ID returned from the BBLGetMonitorID() function
+ //
+
+ // Find the monitor info structure from the monitor table
+ // Search for matching monitor ID */
+ bbl_mon_data_ptr = &bbl_mon_data[0];
+ do{
+ if(bbl_mon_data_ptr->monitor_id == monID)
+ break;
+ ++bbl_mon_data_ptr;
+ }while(bbl_mon_data_ptr->monitor_id != BBL_MT_DEFAULT);
+
+ // If we did not find our ID in the table, use the default
+ // The last entry in the table is the default entry...
+
+ BBL_DBG_PRINT("&bbl_mon_data[0]=0x%x bbl_mon_data_ptr=0x%x\n",
+ &bbl_mon_data[0], bbl_mon_data_ptr);
+
+
+ /*********************************************/
+ /* S E T H A L V A R I A B L E S */
+ /*********************************************/
+
+ //
+ // set the correct horizontal and vertical resolutions for HAL
+ //
+
+ HalpHorizontalResolution = bbl_mon_data_ptr->x_res;
+ HalpVerticalResolution = bbl_mon_data_ptr->y_res;
+ BBL_DBG_PRINT("HalpHorizontalResolution = %d HalpVerticalResolution = %d\n",
+ HalpHorizontalResolution, HalpVerticalResolution);
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpVerticalResolution / HalpCharacterHeight;
+
+ // GXT150P real scanline length is hardcoded at 2048 pixels independent
+ // of the resolution on the screen
+ HalpScrollLine =
+ BBL_SCANLINE_LENGTH * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpHorizontalResolution / HalpCharacterWidth;
+ BBL_DBG_PRINT("DisplayText = %d ScrollLine = %d ScrollLength = %d DisplayWidth = %d\n",
+ HalpDisplayText, HalpScrollLine, HalpScrollLength, HalpDisplayWidth);
+
+
+ /**************************************************/
+ /* R E I N I T I A L I Z E T H E C A R D */
+ /**************************************************/
+
+ //
+ // Initialize the adapter card for the resolution found by looking
+ // at the monitor ID
+ //
+
+ if(BBLInitialize(monID, HalpBBLRegisterBase) == FALSE){
+ BBL_DBG_PRINT("BBLInitialize(monID=0x%x) failed\n", monID);
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+
+ /*********************************************/
+ /* U N M A P R E G I S T E R S P A C E */
+ /*********************************************/
+
+ //
+ // Unmap the the adapter register range from memory. Please note that this
+ // adapter will respond to all 256meg of addresses in the address range
+ // given even though we are only temporarily mapping a small region
+ //
+
+ if (HalpInitPhase == 0) {
+
+ if (HalpBBLRegisterBase) {
+ BBL_DBG_PRINT("call KePhase0DeleteIoMap() to unmap the reg space. Phys=0x%x Len=0x%x %d\n",
+ bbl_phys_address.LowPart + BBL_REG_ADDR_OFFSET, BBL_REG_ADDR_LENGTH, BBL_REG_ADDR_LENGTH);
+ KePhase0DeleteIoMap(bbl_phys_address.LowPart + BBL_REG_ADDR_OFFSET, BBL_REG_ADDR_LENGTH);
+ HalpBBLRegisterBase = 0x0;
+ }
+ }
+
+
+ /*************************************************/
+ /* M A P F R A M E B U F F E R S P A C E */
+ /*************************************************/
+
+ //
+ // Map in the frame buffer memory which is used to write characters to
+ // the screen. Please note that this adapter will respond to all 256meg
+ // of addresses in the address range
+ //
+
+ if (HalpInitPhase == 0) {
+
+ BBL_DBG_PRINT("call KePhase0MapIo() to map the FB_A space. Phys=0x%x Len=0x%x %d\n",
+ bbl_phys_address.LowPart + BBL_VIDEO_MEMORY_OFFSET,
+ BBL_VIDEO_MEMORY_LENGTH,
+ BBL_VIDEO_MEMORY_LENGTH);
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(bbl_phys_address.LowPart + BBL_VIDEO_MEMORY_OFFSET,
+ BBL_VIDEO_MEMORY_LENGTH); // 2 MB
+ }
+
+ BBL_DBG_PRINT("HalpVideoMemoryBase = 0x%x\n", HalpVideoMemoryBase);
+
+
+ /*********************************************/
+ /* M I S C A N D R E T U R N */
+ /*********************************************/
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+
+ BBL_DBG_PRINT("leaving HalpDisplayPpcBBLSetup()\n");
+ return;
+
+} //end of HalpDisplayPpcBBLSetup
+
+
+BOOLEAN
+BBLInitialize (
+ ULONG monID,
+ volatile PUCHAR HalpBBLRegisterBase
+ )
+
+/*++
+
+Routine Description:
+
+ Sets up the rasterizer and ramdac registers to the particular
+ resolution and refresh rate selected for the GXT150P card
+
+Arguments:
+
+ monID -- indicates the resolution and refresh rate to use
+
+
+Return Value:
+
+ The status of the operation (can only fail on a bad command); TRUE for
+ success, FALSE for failure.
+
+--*/
+
+{
+ bbl_mon_data_t *bbl_mon_data_ptr;
+ int i;
+ UCHAR bbl_clut[256*3];
+
+ BBL_DBG_PRINT("Entering BBLInitialize: monID = 0x%x\n", monID);
+
+ // Find the monitor info structure from the monitor table
+
+ // Search for matching monitor ID */
+ bbl_mon_data_ptr = &bbl_mon_data[0];
+ do{
+ if(bbl_mon_data_ptr->monitor_id == monID)
+ break;
+ ++bbl_mon_data_ptr;
+ }while(bbl_mon_data_ptr->monitor_id != BBL_MT_DEFAULT);
+
+ // If we did not find our ID in the table, use the default
+ // The last entry in the table is the default entry...
+
+ BBL_DBG_PRINT("&bbl_mon_data[0]=0x%x bbl_mon_data_ptr=0x%x\n",
+ &bbl_mon_data[0], bbl_mon_data_ptr);
+
+ //
+ // Card has already been RESET and the display outputs been
+ // turned off
+ //
+
+ /*************************************************************/
+ /* B E G I N R A S T R E G I S T E R S E T U P */
+ /*************************************************************/
+
+
+ /*
+ * write Memory Configuration register
+ *
+ */
+
+ BBL_DBG_PRINT ("Writing memory config register = 0x%x\n", 0x0c);
+ BBL_SET_REG( BBL_REG_BASE, BBL_CONFIG_REG, 0x0c );
+
+ /*
+ * set Interrupt Enable register
+ * disable all interrupts
+ */
+
+ BBL_DBG_PRINT ("Disable all interrupts....\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_INTR_ENABLE_STATUS_REG, 0x70);
+
+ /*
+ * set Control register
+ *
+ */
+
+ BBL_DBG_PRINT ("Writing control register = 0x%x\n", 0x01);
+ BBL_SET_REG( BBL_REG_BASE, BBL_CNTL_REG, 0x01 );
+
+
+ /****************************************/
+ /* B E G I N R A M D A C S E T U P */
+ /****************************************/
+
+ /*
+ * Turn off Hardware Cursor
+ */
+
+ BBL_DBG_PRINT ("writing ICON Cursor control reg = DISABLE\n");
+ BBL_SET_ICON_CURSOR_CNTL( BBL_REG_BASE, 0x00);
+
+
+ /***********************/
+ /* S E T U P C R T C */
+ /***********************/
+
+
+ /*
+ * setup CRTC values
+ */
+
+ BBL_DBG_PRINT ("\nSetup_CRTC:\n");
+
+
+ /*
+ * set PLL Reference register = 0x19
+ * set up PLL for reference frequency of 50Mhz.
+ */
+
+
+ BBL_DBG_PRINT ("Set PLL Reference register at offset 0x%x = 0x%x\n",
+ BBL_RAMDAC_PLL_REF_REG, 0x19);
+ BBL_SET_PLL_REF_REG(BBL_REG_BASE, 50);
+
+
+ /*
+ * PLL VCO Divider Register -
+ */
+
+ BBL_DBG_PRINT ("Set VCO_DIVIDER = 0x%x\n",
+ bbl_mon_data_ptr->pixel_freq);
+ BBL_SET_PLL_VCO_DIVIDER_REG( BBL_REG_BASE,
+ bbl_mon_data_ptr->pixel_freq );
+
+ /*
+ * CRT Control Register -
+ */
+ BBL_DBG_PRINT ("Set DTG_CNTL=0x%x\n",
+ bbl_mon_data_ptr->crt_cntl);
+ BBL_SET_CRT_CNTL_REG( BBL_REG_BASE,
+ bbl_mon_data_ptr->crt_cntl);
+
+ /*
+ * Horizontal Total Register -
+ */
+ BBL_DBG_PRINT ("Set HRZ_TOTAL=0x%x\n",
+ bbl_mon_data_ptr->hrz_total);
+ BBL_SET_HORIZONTAL_TOTAL_REG( BBL_REG_BASE,
+ bbl_mon_data_ptr->hrz_total);
+
+ /*
+ * Horizontal Display End Register -
+ */
+ BBL_DBG_PRINT ("Set HRZ_DISP_END=0x%x\n",
+ (bbl_mon_data_ptr->x_res - 1));
+ BBL_SET_HORIZONTAL_DISPLAY_END_REG( BBL_REG_BASE,
+ (bbl_mon_data_ptr->x_res - 1));
+
+ /*
+ * Horizontal Sync Start Register -
+ */
+ BBL_DBG_PRINT ("Set HRZ_SYNC_START=0x%x\n",
+ bbl_mon_data_ptr->hrz_sync_start);
+ BBL_SET_HORIZONTAL_SYNC_START_REG(BBL_REG_BASE,
+ bbl_mon_data_ptr->hrz_sync_start);
+
+ /*
+ * Horizontal Sync End1 Register -
+ */
+ BBL_DBG_PRINT ("Set HRZ_SYNC_END1=0x%x\n",
+ bbl_mon_data_ptr->hrz_sync_end1);
+ BBL_SET_HORIZONTAL_SYNC_END1_REG(BBL_REG_BASE,
+ bbl_mon_data_ptr->hrz_sync_end1);
+
+ /*
+ * Horizontal Sync End2 Register -
+ */
+ BBL_DBG_PRINT ("Set HRZ_SYNC_END2=0x%x\n",
+ bbl_mon_data_ptr->hrz_sync_end2);
+ BBL_SET_HORIZONTAL_SYNC_END2_REG(BBL_REG_BASE,
+ bbl_mon_data_ptr->hrz_sync_end2);
+
+ /*
+ * Vertical Total Register -
+ */
+ BBL_DBG_PRINT ("Set VERT_TOTAL=0x%x\n",
+ bbl_mon_data_ptr->vrt_total);
+ BBL_SET_VERTICAL_TOTAL_REG(BBL_REG_BASE,
+ bbl_mon_data_ptr->vrt_total);
+
+ /*
+ * Vertical Display End Register -
+ */
+ BBL_DBG_PRINT ("Set VRT_DISP_END=0x%x\n",
+ (bbl_mon_data_ptr->y_res - 1));
+ BBL_SET_VERTICAL_DISPLAY_END_REG( BBL_REG_BASE,
+ (bbl_mon_data_ptr->y_res - 1));
+
+ /*
+ * Vertical Sync Start Register -
+ */
+ BBL_DBG_PRINT ("Set VERT_SYNC_STRT=0x%x\n",
+ bbl_mon_data_ptr->vrt_sync_start);
+ BBL_SET_VERTICAL_SYNC_START_REG(BBL_REG_BASE,
+ bbl_mon_data_ptr->vrt_sync_start);
+
+ /*
+ * Vertical Sync End Register -
+ */
+ BBL_DBG_PRINT ("Set VERT_SYNC_END=0x%x\n",
+ bbl_mon_data_ptr->vrt_sync_end);
+ BBL_SET_VERTICAL_SYNC_END_REG(BBL_REG_BASE,
+ bbl_mon_data_ptr->vrt_sync_end);
+
+
+ /*******************************************/
+ /* F I N I S H R A M D A C S E T U P */
+ /*******************************************/
+
+
+ /*
+ * set configuration register low
+ */
+
+ BBL_DBG_PRINT ("Setting up config low register=0x%x\n", 0x31);
+ BBL_SET_RAMDAC_ADDRESS_REGS( BBL_REG_BASE, BBL_RAMDAC_CONFIG_LOW_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE, 0x31 );
+
+ /*
+ * set Configuration high register
+ */
+
+ BBL_DBG_PRINT ("Writing RAMDAC config register high = 0x%x\n", 0x68);
+ BBL_SET_RAMDAC_ADDRESS_REGS( BBL_REG_BASE, BBL_RAMDAC_CONFIG_HIGH_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE, 0x68 );
+
+ /* Set the RGB format register */
+ BBL_SET_RAMDAC_ADDRESS_REGS( BBL_REG_BASE, BBL_RAMDAC_RGB_FORMAT_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE, 0x00 );
+
+ /*
+ * set WID/OVRLY Mask register = 0x0f
+ */
+
+ BBL_DBG_PRINT ("WID/OVRLY mask register = 0x%x\n",
+ BBL_DEFAULT_WID_OL_PIXEL_MASK_VALUE);
+
+ BBL_SET_RAMDAC_ADDRESS_REGS( BBL_REG_BASE, BBL_RAMDAC_WID_OL_MASK_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE,
+ BBL_DEFAULT_WID_OL_PIXEL_MASK_VALUE );
+
+ /*
+ * Set Pixel Mask
+ */
+
+ BBL_DBG_PRINT ("Writing Pixel Mask register = 0x%x\n",
+ BBL_DEFAULT_WID_OL_PIXEL_MASK_VALUE);
+ BBL_SET_RAMDAC_FB_PIXEL_MASK_REG( BBL_REG_BASE,
+ BBL_DEFAULT_VRAM_PIXEL_MASK_VALUE );
+
+
+ /*******************/
+ /* S E T W A T S */
+ /*******************/
+
+ /*
+ * Load the default WAT
+ */
+
+ BBL_DBG_PRINT ("update WAT\n");
+
+ BBL_SET_RAMDAC_ADDRESS_REGS ( BBL_REG_BASE,
+ BBL_RAMDAC_WAT_START_ADDR );
+ for(i=0;i<BBL_RAMDAC_WAT_LENGTH;i++){
+ BBL_SET_RAMDAC_DATA_NON_LUT ( BBL_REG_BASE, 0x10);
+ BBL_SET_RAMDAC_DATA_NON_LUT ( BBL_REG_BASE, 0x00);
+ }
+
+
+ /*************************************/
+ /* S E T C O L O R P A L E T T E */
+ /*************************************/
+
+ BBL_DBG_PRINT ("update colormap\n");
+
+ /*
+ * Set the colormap
+ */
+
+ for(i=0; i<256; i++){
+ if((TextPalette[i] == 16)||
+ (TextPalette[i] == 32)||
+ (TextPalette[i] == 63)){
+ bbl_clut[i] = TextPalette[i] * 4;
+ }else{
+ bbl_clut[i] = TextPalette[i];
+ }
+ }
+
+ BBL_DBG_PRINT ("updating colormap\n");
+ BBL_LOAD_FB_COLOR_PALETTE(BBL_REG_BASE, 0,
+ BBL_RAMDAC_FB_LUT_LENGTH, &bbl_clut[0]);
+
+ /************************************************************/
+ /* F I N I S H R A S T R E G I S T E R S E T U P */
+ /************************************************************/
+
+ /*
+ * set PIXEL MASK register = 0xffffffff
+ */
+
+ BBL_DBG_PRINT ("Writing Pixel Mask register = 0xFFFFFFFF\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_PIXEL_MASK_REG, 0xFFFFFFFF);
+
+ /*
+ * set Write Plane Mask register = 0xff
+ */
+
+ BBL_DBG_PRINT ("Writing Plane Mask register = 0x%x\n", 0xFF);
+ BBL_SET_REG( BBL_REG_BASE, BBL_PLANE_MASK_REG, 0xFF);
+
+
+ /*
+ * Disable Line Style Dash 1234
+ */
+
+ BBL_DBG_PRINT ("disable line style dash 1234 register\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_LINE_STYLE_DASH_1234_REG, 0x00);
+
+ /*
+ * Disable Line Style Dash 5678
+ */
+
+ BBL_DBG_PRINT ("disable line style dash 5678 register\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_LINE_STYLE_DASH_5678_REG, 0x00);
+
+
+ /*
+ * Disable Scissors
+ */
+
+ BBL_DBG_PRINT ("Disable scissors\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_SCISSOR_ENABLE_REG, 0x0);
+
+ /*
+ * set Window Origin Offset register ( x = 0, y = 0 )
+ */
+
+ BBL_DBG_PRINT ("setting Window origin 0,0\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_WIN_ORIGIN_OFFSETS_REG, 0x0);
+
+ /*
+ * set Window ID and Clip Test register = DISABLE
+ */
+
+ BBL_DBG_PRINT ("setting Window ID and Clip Test register = DISABLE\n");
+ BBL_SET_REG( BBL_REG_BASE, BBL_WID_CLIP_TEST_REG, 0x0);
+
+ /*******************************/
+ /* C L E A R O U T V R A M */
+ /*******************************/
+
+ /*
+ * set Foreground register
+ */
+
+ BBL_DBG_PRINT ("Writing Foreground register = 0x%x\n", 0x0);
+ BBL_SET_REG( BBL_REG_BASE, BBL_FG_REG, 0x0);
+
+ /*
+ * set Background register
+ */
+
+ BBL_DBG_PRINT ("Writing Background register = 0x%x\n", 0x0);
+ BBL_SET_REG( BBL_REG_BASE, BBL_BG_REG, 0x0);
+
+ /*
+ * set destination to WID planes
+ */
+
+ BBL_SET_REG( BBL_REG_BASE, BBL_CNTL_REG, 0x201);
+
+ /*
+ * set Write Plane Mask register = 0x0f
+ */
+
+ BBL_DBG_PRINT ("Writing Plane Mask register = 0x%x\n", 0x0F);
+ BBL_SET_REG( BBL_REG_BASE, BBL_PLANE_MASK_REG, 0x0F);
+ BBL_EIEIO;
+
+ /*
+ * clear out WID planes
+ */
+
+ BBL_BUSY_POLL(BBL_REG_BASE);
+ BBL_FILL_RECT(BBL_REG_BASE, 0, 0, bbl_mon_data_ptr->x_res,
+ bbl_mon_data_ptr->y_res);
+ BBL_EIEIO;
+
+ /*
+ * set destination to FB_A
+ */
+
+ BBL_SET_REG( BBL_REG_BASE, BBL_CNTL_REG, 0x01);
+
+ /*
+ * set Write Plane Mask register = 0xff
+ */
+
+ BBL_DBG_PRINT ("Writing Plane Mask register = 0x%x\n", 0xFF);
+ BBL_SET_REG( BBL_REG_BASE, BBL_PLANE_MASK_REG, 0xFF);
+ BBL_EIEIO;
+
+ /*
+ * clear out FB_A (actually make it dark blue for HAL)
+ */
+
+ BBL_BUSY_POLL(BBL_REG_BASE);
+ BBL_SET_REG( BBL_REG_BASE, BBL_FG_REG, 0x01); // dark blue
+ BBL_FILL_RECT(BBL_REG_BASE, 0, 0, bbl_mon_data_ptr->x_res,
+ bbl_mon_data_ptr->y_res);
+
+ BBL_EIEIO;
+ BBL_BUSY_POLL(BBL_REG_BASE);
+
+
+ /*******************************************/
+ /* E N A B L E V I D E O D I S P L A Y */
+ /*******************************************/
+
+
+ /*
+ * set Configuration high register
+ */
+
+
+ BBL_DBG_PRINT ("Writing RAMDAC config register high = 0x%x\n", 0x69);
+ BBL_SET_RAMDAC_ADDRESS_REGS(BBL_REG_BASE, BBL_RAMDAC_CONFIG_HIGH_REG );
+ BBL_SET_RAMDAC_DATA_NON_LUT( BBL_REG_BASE, 0x69);
+
+ BBL_EIEIO;
+ BBL_DBG_PRINT ("Finished with BBLInitialize()\n");
+
+ return TRUE;
+}
+
+
+BOOLEAN
+BBLGetMonitorID (
+ PULONG monID,
+ volatile PUCHAR HalpBBLRegisterBase
+ )
+{
+ unsigned long switch_id, cable_id, cable_id_tmp;
+ unsigned long status_vert, status_horz, monitor_id;
+ unsigned char monitor_id_orig, monitor_id_tmp;
+
+ BBL_DBG_PRINT("Entering BBLGetMonitorID\n");
+
+ /*
+ * Disable the PLL and the DTG controllers
+ */
+
+ BBL_SET_RAMDAC_ADDRESS_REGS(BBL_REG_BASE,
+ BBL_RAMDAC_CONFIG_LOW_REG);
+ BBL_SET_RAMDAC_DATA_NON_LUT(BBL_REG_BASE, 0x00);
+ BBL_EIEIO;
+ BBL_SET_RAMDAC_ADDRESS_REGS(BBL_REG_BASE,
+ BBL_RAMDAC_CONFIG_HIGH_REG);
+ BBL_SET_RAMDAC_DATA_NON_LUT(BBL_REG_BASE, 0x08);
+ BBL_EIEIO;
+
+ /*
+ * Setup the PLL registers
+ */
+
+ BBL_SET_PLL_REF_REG(BBL_REG_BASE, 50);
+ BBL_SET_PLL_VCO_DIVIDER_REG(BBL_REG_BASE, 50 * 100);
+ BBL_EIEIO;
+
+ /*
+ * Enable the PLL
+ */
+
+ BBL_SET_RAMDAC_ADDRESS_REGS(BBL_REG_BASE,
+ BBL_RAMDAC_CONFIG_HIGH_REG);
+ BBL_SET_RAMDAC_DATA_NON_LUT(BBL_REG_BASE, 0x48);
+ BBL_EIEIO;
+
+ /*
+ * Enable positive syncs
+ */
+
+ BBL_SET_CRT_CNTL_REG(BBL_REG_BASE, 0x18);
+
+ /*
+ * Setup the horizontal DTG registers
+ */
+
+ BBL_SET_HORIZONTAL_TOTAL_REG(BBL_REG_BASE, 0x00ff);
+ BBL_SET_HORIZONTAL_DISPLAY_END_REG(BBL_REG_BASE, 0x0080);
+ BBL_SET_HORIZONTAL_SYNC_START_REG(BBL_REG_BASE, 0x0103);
+ BBL_SET_HORIZONTAL_SYNC_END1_REG(BBL_REG_BASE, 0x008f);
+ BBL_SET_HORIZONTAL_SYNC_END2_REG(BBL_REG_BASE, 0x0000);
+
+ /*
+ * Setup the vertical DTG registers
+ */
+
+ BBL_SET_VERTICAL_TOTAL_REG(BBL_REG_BASE, 0x00ff);
+ BBL_SET_VERTICAL_DISPLAY_END_REG(BBL_REG_BASE, 0x0080);
+ BBL_SET_VERTICAL_SYNC_START_REG(BBL_REG_BASE, 0x0100);
+ BBL_SET_VERTICAL_SYNC_END_REG(BBL_REG_BASE, 0x0088);
+ BBL_EIEIO;
+
+ /*
+ * Enable the DTG
+ */
+
+ BBL_SET_RAMDAC_ADDRESS_REGS(BBL_REG_BASE,
+ BBL_RAMDAC_CONFIG_HIGH_REG);
+ BBL_SET_RAMDAC_DATA_NON_LUT(BBL_REG_BASE, 0x68);
+
+ /*
+ * Delay for 35 ms
+ */
+
+ BBL_EIEIO;
+
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+
+ /*
+ * Read the monitor ID with positive going syncs
+ */
+
+ BBL_GET_MONITOR_ID(BBL_REG_BASE,monitor_id_orig);
+
+ /*
+ * Extract the raw monitor ID along with the DIP switch
+ * settings
+ */
+
+ switch_id = (monitor_id_orig >> 4 ) & 0x0f ;
+ cable_id = (monitor_id_orig & 0x0f);
+ BBL_DBG_PRINT("monitor_id_orig=0x%x switch_id=0x%x cable_id=0x%x\n",
+ monitor_id_orig, switch_id, cable_id);
+
+ /*
+ * Set VSYNC to negative logic
+ */
+ BBL_SET_CRT_CNTL_REG(BBL_REG_BASE, 0x08);
+
+ /*
+ * Delay for 35 ms
+ */
+
+ BBL_EIEIO;
+
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+
+ /*
+ * Read the monitor ID with negative VSYNC logic active
+ */
+
+ BBL_GET_MONITOR_ID(BBL_REG_BASE,monitor_id_tmp);
+
+ /*
+ * Extract the negative VSYNC monitor ID and OR in
+ * the changed bits into the monitor ID
+ */
+
+ status_vert = (monitor_id_tmp & 0x0f) ^ cable_id;
+ cable_id_tmp = monitor_id_tmp & 0x0f;
+ BBL_DBG_PRINT("monitor_id_tmp=0x%x status_vert=0x%x cable_id_tmp=0x%x\n",
+ monitor_id_tmp, status_vert, cable_id_tmp);
+
+ /*
+ * Set HSYNC to negative logic; VSYNC is still negative as well
+ */
+
+ BBL_SET_CRT_CNTL_REG(BBL_REG_BASE, 0x00);
+
+ /*
+ * Delay for 35 ms
+ */
+
+ BBL_EIEIO;
+
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+ BBLWaitForVerticalSync(BBL_REG_BASE);
+
+ /*
+ * Read the monitor ID with negative HSYNC and VSYNC logic
+ */
+
+ BBL_GET_MONITOR_ID(BBL_REG_BASE,monitor_id_tmp);
+
+ /*
+ * Extract the negative HSYNC and VSYNC value and OR in
+ * the changed bits into the monitor ID
+ */
+
+ status_horz = (monitor_id_tmp & 0x0f) ^ cable_id_tmp;
+ monitor_id = switch_id << BBL_MON_ID_DIP_SWITCHES_SHIFT;
+ BBL_DBG_PRINT("monitor_id_tmp=0x%x status_horz=0x%x monitor_id=0x%x\n",
+ monitor_id_tmp, status_horz, monitor_id);
+
+ /*
+ * Turn PLL and DTG controllers back off
+ */
+ BBL_SET_RAMDAC_ADDRESS_REGS(BBL_REG_BASE,
+ BBL_RAMDAC_CONFIG_HIGH_REG);
+ BBL_SET_RAMDAC_DATA_NON_LUT(BBL_REG_BASE, 0x08);
+ BBL_EIEIO;
+
+ /*
+ * Determine if we have a vert (V) or horz (H) value in the
+ * monitor ID based on what we read the three times above
+ */
+
+ if(status_horz & 0x08)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_H <<
+ BBL_MON_ID_CABLE_BIT_0_SHIFT);
+ else if(status_vert & 0x08)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_V <<
+ BBL_MON_ID_CABLE_BIT_0_SHIFT);
+ else if(cable_id & 0x08)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_1 <<
+ BBL_MON_ID_CABLE_BIT_0_SHIFT);
+
+ if(status_horz & 0x04)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_H <<
+ BBL_MON_ID_CABLE_BIT_1_SHIFT);
+ else if(status_vert & 0x04)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_V <<
+ BBL_MON_ID_CABLE_BIT_1_SHIFT);
+ else if(cable_id & 0x04)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_1 <<
+ BBL_MON_ID_CABLE_BIT_1_SHIFT);
+
+ if(status_horz & 0x02)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_H <<
+ BBL_MON_ID_CABLE_BIT_2_SHIFT);
+ else if(status_vert & 0x02)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_V <<
+ BBL_MON_ID_CABLE_BIT_2_SHIFT);
+ else if(cable_id & 0x02)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_1 <<
+ BBL_MON_ID_CABLE_BIT_2_SHIFT);
+
+ if(status_horz & 0x01)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_H <<
+ BBL_MON_ID_CABLE_BIT_3_SHIFT);
+ else if(status_vert & 0x01)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_V <<
+ BBL_MON_ID_CABLE_BIT_3_SHIFT);
+ else if(cable_id & 0x01)
+ monitor_id |= (BBL_MON_ID_CABLE_ID_1 <<
+ BBL_MON_ID_CABLE_BIT_3_SHIFT);
+
+ *monID = monitor_id;
+ BBL_DBG_PRINT ("Monitor id = 0x%x\n", monitor_id);
+
+ return TRUE;
+}
+
+
+VOID
+BBLWaitForVerticalSync (
+ volatile PUCHAR HalpBBLRegisterBase
+ )
+{
+ int counter = 0;
+
+ // Loop until out of Vertical Sync just in case we happened to
+ // catch the tail end of a vertical blank cycle
+ while((BBL_GET_REG(HalpBBLRegisterBase, BBL_STATUS_REG)
+ & BBL_VERTICAL_RETRACE) &&
+ (++counter < 1000000))
+ ;
+
+ counter = 0;
+ // Wait until we hit the leading edge of the Vertical Sync
+ while((!(BBL_GET_REG(HalpBBLRegisterBase, BBL_STATUS_REG)
+ & BBL_VERTICAL_RETRACE)) &&
+ (++counter < 1000000))
+ ;
+
+#ifdef DBG
+ // If counter reaches 1000000, then there is something wrong with
+ // the setup of the ramdac
+#ifdef KDB
+ if(counter == 1000000)
+ DbgBreakPoint();
+#endif
+#endif
+
+}
+
+
+VOID
+HalpDisplayCharacterBBL (
+ IN UCHAR Character
+ )
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encountered, the frame buffer is
+ scrolled. If characters extend below the end of line, they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If the character is a newline:
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ BBLScrollScreen();
+ }
+ }
+
+ //
+ // If the character is a tab:
+ //
+
+ else if( Character == '\t' ) {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= HalpDisplayWidth ) { // tab beyond end of screen?
+ HalpColumn = 0; // set to 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ BBLScrollScreen();
+ else
+ ++HalpRow;
+ }
+ }
+
+ //
+ // If the character is a return:
+ //
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ }
+
+ //
+ // If the character is a DEL:
+ //
+
+ else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ Character = 0x20 - HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterBBL((PUCHAR)HalpFontHeader +
+ HalpFontHeader->Map[Character].Offset);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ }
+
+ //
+ // If not special character:
+ //
+
+ else {
+
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter))
+ Character = HalpFontHeader->DefaultCharacter;
+ else
+ Character -= HalpFontHeader->FirstCharacter;
+
+ // Auto wrap for HalpDisplayWidth columns per line
+ if (HalpColumn >= HalpDisplayWidth) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ BBLScrollScreen();
+ }
+ }
+
+ HalpOutputCharacterBBL((PUCHAR)HalpFontHeader +
+ HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalpOutputCharacterBBL(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ //if (HalpColumn == HalpDisplayWidth) {
+ // HalpDisplayCharacterBBL('\n');
+ //}
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(HalpVideoMemoryBase +
+ (HalpRow * HalpScrollLine) +
+ (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |=
+ *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ *Destination = 0x01; // Clear out any pre-existing char
+ if (FontValue >> 31 != 0)
+ *Destination = 0x3F; // Make this pixel white (ARC color)
+
+ Destination++;
+ FontValue <<= 1;
+ }
+ Destination += (BBL_SCANLINE_LENGTH - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+ return;
+}
+
+
+VOID
+BBLScrollScreen (
+ VOID
+ )
+{
+ PULONG Destination, Source, End;
+ ULONG pix_col, Stride;
+
+ // Scroll up one line
+ Destination = (PULONG) HalpVideoMemoryBase;
+ Source = (PULONG) (HalpVideoMemoryBase + HalpScrollLine);
+ End = (PULONG) ((PUCHAR) Source + HalpScrollLength);
+ Stride = (ULONG) ((BBL_SCANLINE_LENGTH - HalpHorizontalResolution) >> 2);
+
+ while(Source < End){
+ pix_col = 0;
+ while(pix_col++ < (HalpHorizontalResolution >> 2)){
+ *Destination++ = *Source++;
+ }
+ Destination += Stride;
+ Source += Stride;
+ }
+
+ // Blue the bottom line
+ Destination = (PULONG) (HalpVideoMemoryBase + HalpScrollLength);
+ End = (PULONG) ((PUCHAR) Destination + HalpScrollLine);
+ while(Destination < End){
+ for (pix_col =0; pix_col < (HalpHorizontalResolution >> 2);
+ pix_col ++){
+ *Destination++ = 0x01010101;
+ }
+ Destination += Stride;
+ }
+}
+
+
+BOOLEAN
+BBLSetConfigurationRegister (
+ IN ULONG dev_ven_id,
+ IN ULONG offset,
+ IN ULONG reg_value
+ )
+{
+ ULONG slot = 0, bus = 0, value, i, j;
+ volatile PUCHAR HalpBBLRegisterBase;
+ BOOLEAN found;
+
+
+ if (HalpInitPhase == 0) {
+
+ if(HalpPhase0MapBusConfigSpace () == FALSE){
+ BBL_DBG_PRINT("HalpPhase0MapBusConfigSpace() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return (FALSE);
+ }
+ }
+
+ found = FALSE;
+
+ for (j=0; j < HalpPciMaxBuses; j++) {
+ for (i=0; ((i<HalpPciMaxSlots)&&(found==FALSE)); i++){
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0GetPciDataByOffset (j, i, &value, 0x0, 4);
+ } else {
+ HalGetBusDataByOffset(PCIConfiguration,
+ j,
+ i,
+ &value,
+ 0x0,
+ 4);
+
+ }
+
+ if(value == BBL_DEV_VEND_ID){
+ slot = i;
+ bus = j;
+ found = TRUE;
+ }
+ }
+ }
+
+ if(found == FALSE){
+ BBL_DBG_PRINT("Cannot find adapter!\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ if (HalpInitPhase == 0) HalpPhase0UnMapBusConfigSpace ();
+ return (FALSE);
+ }
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0SetPciDataByOffset (bus, slot, &reg_value, offset, 4);
+ HalpPhase0UnMapBusConfigSpace ();
+ } else {
+ HalSetBusDataByOffset(PCIConfiguration,
+ bus,
+ slot,
+ &reg_value,
+ offset,
+ 4);
+ }
+
+ return (TRUE);
+}
+
+BOOLEAN
+BBLGetConfigurationRegister (
+ IN ULONG dev_ven_id,
+ IN ULONG offset,
+ IN PULONG reg_value
+ )
+{
+ ULONG slot = 0, bus = 0, value, i, j;
+ volatile PUCHAR HalpBBLRegisterBase;
+ BOOLEAN found;
+
+
+ if (HalpInitPhase == 0) {
+
+ if(HalpPhase0MapBusConfigSpace () == FALSE){
+ BBL_DBG_PRINT("HalpPhase0MapBusConfigSpace() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return (FALSE);
+ }
+ }
+
+ found = FALSE;
+
+ for (j=0; j < HalpPciMaxBuses; j++) {
+ for (i=0; ((i<HalpPciMaxSlots)&&(found==FALSE)); i++){
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0GetPciDataByOffset (j, i, &value, 0x0, 4);
+ } else {
+ HalGetBusDataByOffset(PCIConfiguration,
+ j,
+ i,
+ &value,
+ 0x0,
+ 4);
+
+ }
+
+ if(value == BBL_DEV_VEND_ID){
+ slot = i;
+ bus = j;
+ found = TRUE;
+ }
+ }
+ }
+
+ if(found == FALSE){
+ BBL_DBG_PRINT("Cannot find adapter!\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ if (HalpInitPhase == 0) HalpPhase0UnMapBusConfigSpace ();
+ return (FALSE);
+ }
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0GetPciDataByOffset (bus, slot, reg_value, offset, 4);
+ HalpPhase0UnMapBusConfigSpace ();
+ } else {
+ HalGetBusDataByOffset(PCIConfiguration,
+ bus,
+ slot,
+ reg_value,
+ offset,
+ 4);
+ }
+
+ return (TRUE);
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxbeep.c b/private/ntos/nthals/halppc/ppc/pxbeep.c
new file mode 100644
index 000000000..2ac4b543c
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxbeep.c
@@ -0,0 +1,134 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ pxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a Power PC
+ system.
+
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase = HalpIoControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+ return Result;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxbl.c b/private/ntos/nthals/halppc/ppc/pxbl.c
new file mode 100644
index 000000000..c98e40913
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxbl.c
@@ -0,0 +1,1700 @@
+/*++
+
+Copyright (c) 1996 International Business Machines Corporation
+
+Module Name:
+
+pxbl.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a PowerPC system using a GXT200P/GXT250P (Sky Blue) video adapter.
+
+Author:
+
+ Tim White
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "string.h"
+
+// Include GXT250P header file information
+#include "blrastz.h"
+#include "blrmdac.h"
+#include "bldef.h"
+#include "blfw.h"
+
+extern ULONG HalpInitPhase;
+extern PUCHAR HalpVideoMemoryBase;
+extern PUCHAR HalpVideoCoprocBase;
+
+extern ULONG HalpColumn;
+extern ULONG HalpRow;
+extern ULONG HalpHorizontalResolution;
+extern ULONG HalpVerticalResolution;
+
+
+extern USHORT HalpBytesPerRow;
+extern USHORT HalpCharacterHeight;
+extern USHORT HalpCharacterWidth;
+extern ULONG HalpDisplayText;
+extern ULONG HalpDisplayWidth;
+extern ULONG HalpScrollLength;
+extern ULONG HalpScrollLine;
+
+extern BOOLEAN HalpDisplayOwnedByHal;
+
+extern POEM_FONT_FILE_HEADER HalpFontHeader;
+extern ULONG HalpPciMaxSlots;
+
+extern UCHAR TextPalette[];
+
+
+#define TAB_SIZE 4
+
+//
+// Set up the monitor data information
+//
+
+bl_crt_ctrl_rec_t bl_crt_ctrl_rec[BL_NUM_CRT_CTRL_REC_STRUCTS] =
+{
+
+/* 640x480@60Hz
+ *
+ * Vfreq: 60Hz
+ * Hfreq:
+ * Pix Clk: 25.2Mhz
+ * Sync: -H,-V
+ * Monitors:
+ */
+ { m640_480_8_60, 0,
+ 640, 480, 60,
+ 0x08, 0x5E, 0x06, 0x06,
+ 0x18, 0x00,
+ 799, 639, 655, 751, 0,
+ 524, 479, 489, 491 },
+
+/* 800x600@60Hz
+ *
+ * Vfreq: 60Hz
+ * Hfreq:
+ * Pix Clk: 40.0Mhz
+ * Sync: -H,+V
+ * Monitors:
+ */
+ { m800_600_8_60, BL_MT_0A,
+ 800, 600, 60,
+ 0x0B, 0x42, 0x02, 0x05,
+ 0x00, 0x00,
+ 1055, 799, 839, 967, 0,
+ 627, 599, 600, 604 },
+
+/* 1024x768@60Hz
+ *
+ * Vfreq: 60Hz
+ * Hfreq: 48.363Khz
+ * Pix Clk: 65Mhz
+ * Sync: vsync+, hsync+
+ * Monitors:
+ */
+ { m1024_768_8_60, 0,
+ 1024, 768, 60,
+ 0x0C, 0x75, 0x02, 0x06,
+ 0x18, 0x00,
+ 1343, 1023, 1047, 1183, 0,
+ 805, 767, 770, 776 },
+
+/* 1024x768@70Hz
+ *
+ * Vfreq: 70Hz
+ * Hfreq: 57.019Khz
+ * Pix Clk: 78Mhz
+ * Sync: SEP (vsync+, hsync+)
+ * Monitors: IBM 8517 (17" color)
+ */
+ { m1024_768_8_70, BL_MT_1A,
+ 1024, 768, 70,
+ 0x08, 0x30, 0x00, 0x05,
+ 0x00, 0x00,
+ 1367, 1023, 1031, 1311, 0,
+ 813, 767, 767, 775 },
+
+/* 1280x1024@60Hz
+ *
+ * Vfreq: 60Hz
+ * Hfreq: 109.37Khz
+ * Pix Clk: 112Mhz
+ * Sync: SOG (+)
+ * Monitors:
+ */
+ { m1280_1024_8_60, BL_MT_04,
+ 1280, 1024, 60,
+ 0x0A, 0x55, 0x00, 0x05,
+ 0x03, BL_DTG_COMP_SYNC,
+ 1759, 1279, 1299, 1455, 1103,
+ 1055, 1023, 1026, 1029 },
+
+/* 1280x1024@67Hz
+ *
+ * Vfreq: 67Hz
+ * Hfreq: 70.8Khz
+ * Pix Clk: 128Mhz
+ * Sync: SEP (vsync-, hsync-)
+ * Monitors: IBM 8508 (19" mono)
+ */
+ { m1280_1024_8_67, BL_MT_07,
+ 1280, 1024, 67,
+ 0x0C, 0x73, 0x00, 0x05,
+ 0x18, 0x00,
+ 1807, 1279, 1351, 1607, 0,
+ 1055, 1023, 1023, 1031 },
+
+/* 1280x1024@72Hz
+ *
+ * Vfreq: 71.537Hz
+ * Hfreq: 75.829Khz
+ * Pix Clk: 128Mhz
+ * Sync: SOG
+ * Monitors: IBM 1091-051 (POWERdisplay 16s)
+ */
+ { m1280_1024_8_72, BL_MT_17,
+ 1280, 1024, 72,
+ 0x0C, 0x73, 0x00, 0x05,
+ 0x03, BL_DTG_COMP_SYNC,
+ 1687, 1279, 1311, 1451, 1171,
+ 1059, 1023, 1026, 1029 }
+
+};
+
+//
+// Set up the adapter data information
+//
+
+bl_adapter_ctrl_rec_t bl_2meg_sky_0_1_adp_ctrl[] = {
+
+/* model: gxt250p */
+/* frame buffer size: 2 meg */
+/* AUX A (WID) size: 1 meg */
+/* PRISM revision: 0x1 */
+
+ {
+ 2, 1024, 1024,
+ 0x02222024, 0x01800001, 0x0023000b,
+ /* 4:1 multiplex */
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x0c,
+ 0xff, 0x00, 0x03 },
+
+ {
+ 2, 2048, 1024,
+ 0x02202040, 0x01800001, 0x0023000f,
+ /* 8:1 multiplex */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x04,
+ 0xff, 0x00, 0x0f }
+
+};
+
+bl_adapter_ctrl_rec_t bl_6meg_sky_0_1_adp_ctrl[] = {
+
+/* model: gxt250p */
+/* frame buffer size: 6 meg */
+/* AUX A (WID) size: 2 meg */
+/* PRISM revision: 0x1 */
+
+// {
+// 6, 2048, 1024,
+// 0x062b2044, 0x00810102, 0x0046000b,
+// /* 4:1 multiplex */
+// 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x01,
+// 0x00, 0x0c,
+// 0xff, 0x0f, 0x03 },
+
+ {
+ 6, 2048, 1024,
+ 0x062b2044, 0x00810003, 0x0046000b,
+ /* 4:1 multiplex */
+ 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x0c,
+ 0xff, 0x0f, 0x03 }
+
+};
+
+bl_adapter_ctrl_rec_t bl_2meg_sky_1_2_adp_ctrl[] = {
+
+/* model: gxt250p */
+/* frame buffer size: 2 meg */
+/* AUX A (WID) size: 1 meg */
+/* PRISM revision: 0x2 */
+
+ {
+ 2, 1024, 1024,
+ 0x02222024, 0x01800001, 0x0023000b,
+ /* 4:1 multiplex */
+ 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x0c,
+ 0xff, 0x00, 0x03 },
+
+ {
+ 2, 2048, 1024,
+ 0x02202040, 0x01800001, 0x0023000f,
+ /* 8:1 multiplex */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x04,
+ 0xff, 0x00, 0x0f }
+
+};
+
+bl_adapter_ctrl_rec_t bl_6meg_sky_1_2_adp_ctrl[] = {
+
+/* model: gxt250p */
+/* frame buffer size: 6 meg */
+/* AUX A (WID) size: 2 meg */
+/* PRISM revision: 0x2 */
+
+// {
+// 6, 2048, 1024,
+// 0x062b2044, 0x00810102, 0x0046000b,
+// /* 4:1 multiplex */
+// 0x00, 0x04, 0x00, 0x08, 0x00, 0x00, 0x01,
+// 0x00, 0x0c,
+// 0xff, 0x0f, 0x03 },
+
+ {
+ 6, 2048, 1024,
+ 0x062b2044, 0x00810003, 0x0046000b,
+ /* 4:1 multiplex */
+ 0x00, 0x04, 0x08, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x0c,
+ 0xff, 0x0f, 0x03 },
+
+ {
+ 6, 2048, 2048,
+ 0xb6292060, 0x00810003, 0x004a000b,
+ /* 8:1 multiplex */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x02, 0x04,
+ 0xff, 0x00, 0x0f }
+
+};
+
+//
+// Set up the adapter model information
+//
+
+bl_adapter_model_rec_t bl_model[] = {
+ {
+ BL_SKY_DEV_VEN_ID, BL_FRAME_BUFFER_SIZE_2_MEG, 1, 2,
+ bl_2meg_sky_0_1_adp_ctrl },
+
+ {
+// BL_SKY_DEV_VEN_ID, BL_FRAME_BUFFER_SIZE_6_MEG, 1, 2,
+ BL_SKY_DEV_VEN_ID, BL_FRAME_BUFFER_SIZE_6_MEG, 1, 1,
+ bl_6meg_sky_0_1_adp_ctrl },
+
+// The card_rev of 0x01 and prism rev of 0x02 are guesses only!
+// Fix up the following and/or add additional entries as needed
+
+ {
+ BL_SKY_DEV_VEN_ID, BL_FRAME_BUFFER_SIZE_2_MEG, 2, 2,
+ bl_2meg_sky_1_2_adp_ctrl },
+
+ {
+// BL_SKY_DEV_VEN_ID, BL_FRAME_BUFFER_SIZE_6_MEG, 2, 3,
+ BL_SKY_DEV_VEN_ID, BL_FRAME_BUFFER_SIZE_6_MEG, 2, 2,
+ bl_6meg_sky_1_2_adp_ctrl },
+
+ {
+ /* end of table indicator */
+ 0, 0, 0, 0, 0 }
+
+};
+
+
+
+VOID
+HalpDisplayPpcBLSetup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterBL (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterBL(
+ IN PUCHAR Glyph
+ );
+
+BOOLEAN
+BLGetConfigurationInfo (
+ IN ULONG dev_ven_id,
+ IN PULONG bus,
+ IN PULONG slot
+ );
+
+BOOLEAN
+BLGetConfigurationRegister (
+ IN ULONG bus,
+ IN ULONG slot,
+ IN ULONG offset,
+ IN PULONG reg_value
+ );
+
+BOOLEAN
+BLSetConfigurationRegister (
+ IN ULONG bus,
+ IN ULONG slot,
+ IN ULONG offset,
+ IN ULONG reg_value
+ );
+
+VOID
+BLScrollScreen(
+ VOID
+ );
+
+BOOLEAN
+BLInitialize (
+ volatile PUCHAR HalpBLRegisterBase,
+ bl_crt_ctrl_rec_t *crt_rec,
+ bl_adapter_ctrl_rec_t *adpt_rec
+ );
+
+BOOLEAN
+BLGetMonitorID (
+ volatile PUCHAR HalpBLRegisterBase,
+ PULONG monID
+ );
+
+VOID
+HalpDisplayPpcBLSetup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the GXT200P/GXT250P Graphics Adapter
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG rc, status, monID, count, value, slot, bus;
+ volatile PUCHAR HalpBLRegisterBase = (PUCHAR)0;
+ PHYSICAL_ADDRESS physaddr;
+ PHYSICAL_ADDRESS bl_phys_address;
+ PHYSICAL_ADDRESS bl_fb_phys_address;
+ ULONG Strapping, Revision, Model;
+ LONG i ;
+ USHORT match = 0, vram = 0;
+ bl_crt_ctrl_rec_t *crt_rec;
+ bl_adapter_ctrl_rec_t *adpt_rec;
+ BOOLEAN found, ok;
+
+ //
+ // There is no need to have both the register space and the
+ // DFA space mapped at the same time. This will save us from
+ // having multiple I/O spaces mapped at the same time. Thus
+ // saving DBATs which are in very very short supply...
+ //
+
+ //
+ // Strategy:
+ //
+ // 1. Map the PCI configuration register space
+ // 2. Update the PCI configuration registers
+ // 3. Unmap the PCI configuration register space
+ // 4. Map the register space
+ // 5. Reset the device
+ // 6. Read the monitor ID to figure what resolution and refresh mode to use
+ // 7. Perform device re-initialization (rasterizer, ramdac,
+ // and color palette)
+ // 8. Unmap the register space
+ // 9. Map the DFA space
+ // 10. Clear out VRAM to the default background color
+ // 11. Now can do character blits
+ //
+
+
+ BL_DBG_PRINT("HalpDisplayPpcBLSetup Enter\n");
+
+ /*******************************************************************/
+ /* S E T P C I C O N F I G U R A T I O N R E G I S T E R S */
+ /*******************************************************************/
+
+ // First find the bus and slot number based off the device/vendor ID
+ // and in the SAME ORDER that ARC searches!
+
+ ok = BLGetConfigurationInfo (BL_SKY_DEV_VEN_ID, &bus, &slot);
+ if(ok == FALSE){
+ BL_DBG_PRINT("Could not find the card! for 0x%08x\n",
+ BL_SKY_DEV_VEN_ID);
+ return;
+ }
+
+ // PCI bus devices are in a 32-bit memory space
+ bl_phys_address.HighPart = 0x0;
+
+ ok = BLGetConfigurationRegister (bus, slot,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ u.type0.BaseAddresses[0]),
+ &bl_phys_address.LowPart );
+
+ // translate bus-relative address
+ bl_phys_address.LowPart += PCI_MEMORY_PHYSICAL_BASE;
+
+ if(ok == FALSE){
+ BL_DBG_PRINT("Could not read PCI cfg reg 0x10\n");
+ return;
+ }
+
+ ok = BLGetConfigurationRegister (bus, slot,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ u.type0.BaseAddresses[1]),
+ &bl_fb_phys_address.LowPart );
+
+ // translate bus-relative address
+ bl_fb_phys_address.LowPart += PCI_MEMORY_PHYSICAL_BASE;
+
+ if(ok == FALSE){
+ BL_DBG_PRINT("Could not read PCI cfg reg 0x14\n");
+ return;
+ }
+ BL_DBG_PRINT("reg_base = 0x%08x fb_base=0x%08x\n",
+ bl_phys_address.LowPart, bl_fb_phys_address.LowPart);
+
+ /**************************************************/
+ /* M A P T H E R E G I S T E R S P A C E */
+ /**************************************************/
+
+ //
+ // Map the the adapter register range into memory.
+ //
+
+
+ if (HalpInitPhase == 0) {
+
+ BL_DBG_PRINT("call KePhase0MapIo() to map the reg space. Phys=0x%x Len=0x%x %d\n",
+ bl_phys_address.LowPart, BL_REG_MAP_SIZE, BL_REG_MAP_SIZE);
+
+ HalpBLRegisterBase = (PUCHAR)KePhase0MapIo(bl_phys_address.LowPart,
+ BL_REG_MAP_SIZE); // 32K
+ } else {
+ physaddr.HighPart = 0;
+ physaddr.LowPart = bl_phys_address.LowPart;
+ HalpBLRegisterBase = (PUCHAR)MmMapIoSpace(physaddr,
+ BL_REG_MAP_SIZE, FALSE);
+ }
+
+ BL_DBG_PRINT("HalpBLRegisterBase = 0x%x\n", HalpBLRegisterBase);
+
+
+ /**************************************************/
+ /* F I N D F O N T T O U S E */
+ /**************************************************/
+
+ //IBMLAN Use font file from OS Loader
+ //
+ // Compute display variables using using HalpFontHeader which is
+ // initialized in HalpInitializeDisplay().
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+
+ HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = HalpFontHeader->PixelHeight;
+ HalpCharacterWidth = HalpFontHeader->PixelWidth;
+ BL_DBG_PRINT("PixelWidth = %d PixelHeight = %d\n HalpFontHeader = 0x%x\n",
+ HalpFontHeader->PixelWidth, HalpFontHeader->PixelHeight,
+ HalpFontHeader);
+
+ /*********************************************/
+ /* S E T P C I C O N F I G U R A T I O N */
+ /* R E G I S T E R S */
+ /*********************************************/
+
+ BL_DBG_PRINT("BLInit: setting config registers\n") ;
+
+ // Read strapping data
+ if(BLGetConfigurationRegister(bus, slot, BL_PCI_CONFIG_STRAP,
+ &Strapping) == FALSE)
+ {
+ BL_DBG_PRINT("could not read strapping config reg\n");
+ return;
+ }
+ // Read revision data
+ if(BLGetConfigurationRegister(bus, slot, BL_PCI_REV_ID,
+ &Revision) == FALSE)
+ {
+ BL_DBG_PRINT("could not read revision config reg\n");
+ return;
+ }
+ // Set the PCI config register 0x0C
+ // Probably should alreday be set by ROS
+ value = BL_CONFIG_REG_0C_VALUE;
+ if(BLSetConfigurationRegister(bus, slot, BL_PCI_CONFIG_0C,
+ value) == FALSE)
+ {
+ BL_DBG_PRINT("could not set the 0x0c config reg\n");
+ return;
+ }
+
+ // Set the PCI config register 0x3C
+ // Probably should alreday be set by ROS
+ value = BL_CONFIG_REG_3C_VALUE;
+ if(BLSetConfigurationRegister(bus, slot, BL_PCI_CONFIG_3C,
+ value) == FALSE)
+ {
+ BL_DBG_PRINT("could not set the 0x3c config reg\n");
+ return;
+ }
+
+ // Enable memory accesses to the card (0x04)
+ if(BLGetConfigurationRegister(bus, slot, BL_PCI_CMD,
+ &value) == FALSE)
+ {
+ BL_DBG_PRINT("could not read the 0x04 config reg\n");
+ return;
+ }
+// Should we force disable VGA (i.e. through 0x46e8 before turning off
+// I/O access? Probably not as long as ROS does not use the VGA function
+ value &= 0xFE; // Disable I/O accesses
+ value |= 0x02; // Enable memory accesses
+ if(BLSetConfigurationRegister(bus, slot, BL_PCI_CMD,
+ value) == FALSE)
+ {
+ BL_DBG_PRINT("could not enable memory (0x04)\n");
+ return;
+ }
+
+ // Set the function enable PCI config register (0x40)
+ value = BL_FUNC_VALUE;
+ if(BLSetConfigurationRegister(bus, slot, BL_PCI_FUNC_ENABLE,
+ value) == FALSE)
+ {
+ BL_DBG_PRINT("could not set func enable reg 0x40\n");
+ return;
+ }
+
+ // Set the extended function enable PCI config register (0x44)
+ // Use the right value depending on whether the card is has a DD2
+ // chip or a DD3 chip on board
+ switch(Strapping & BL_STRAP_CHIP_REV_MASK){
+ case BL_STRAP_CHIP_DD2:
+ value = BL_EXT_FUNC_VALUE_DD2;
+ break;
+ case BL_STRAP_CHIP_DD3:
+ default:
+ value = BL_EXT_FUNC_VALUE_DD3;
+ break;
+ }
+ if(BLSetConfigurationRegister(bus, slot, BL_PCI_EXT_FUNC_ENABLE,
+ value) == FALSE)
+ {
+ BL_DBG_PRINT("could not set ext func enable reg 0x44\n");
+ return;
+ }
+
+ /*********************************************/
+ /* C R I T I C A L R A M D A C R E G S */
+ /*********************************************/
+
+ // Set ramdac to index auto inc
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_UPDATE_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI,
+ HIGH(BL_640_UPDATE_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ BL_640_AUTO_INCR);
+ // Turn off DAC to kill video
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_DAC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI,
+ HIGH(BL_640_DAC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, 0);
+ // Turn off sync's
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ BL_640_PWR_LOW_SYNC);
+ // Set PRISM time base using ramdac aux pll controller registers
+ // Set to run PRISM at 50Mhz
+ BL_DBG_PRINT("set prism time base (ramdac aux pll regs)\n");
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_AUX_REF_DIVIDE));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR25);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR26);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR27);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR28);
+ // Turn off ramdac VGA mode
+ BL_DBG_PRINT("turn off ramdac VGA\n");
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_VGA_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR07);
+
+ /*********************************************/
+ /* B U S Y P O L L A N D R E S E T */
+ /*********************************************/
+
+ BL_DBG_PRINT("reset PRISM and poll for idle\n");
+
+ // Disable and reset PRISM intrs
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_INTR_STATUS_REG,
+ BL_PRSM_DISABLE_RST_INTR);
+
+value = PRISM_RD_REG(HalpBLRegisterBase, BL_PRSM_STATUS_REG);
+BL_DBG_PRINT("status = 0x%08x\n", value);
+
+ // Check for PRISM busy. If busy, soft reset PRISM and poll for idle
+ if (PRISM_BUSY(HalpBLRegisterBase))
+ {
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_SOFT_RESET_REG, 0);
+ BL_EIEIO;
+ while(PRISM_BUSY(HalpBLRegisterBase))
+ ;
+ }
+
+ /*********************************************/
+ /* G E T M O N I T O R I D */
+ /*********************************************/
+
+ if(BLGetMonitorID(HalpBLRegisterBase, &monID) == FALSE){
+ BL_DBG_PRINT("BLGetMonitorID() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+
+ //
+ // Determine which adapter model rec to use
+ //
+
+ BL_DBG_PRINT("DeviceId=0x%08x Strapping=0x%08x Revision=0x%08x\n",
+ BL_SKY_DEV_VEN_ID, Strapping, Revision);
+
+ // For DD2 PRISM based cards, the DD2 model entries *MUST* be
+ // used!!! The DD3 model entries are used for DD3 PRISM based
+ // cards (and future cards). So the DD3 model entries are the
+ // default and should allow for new PRISM chips without code
+ // modification in this area of the GXT250P miniport code
+
+ for(Model=0;;Model++){
+
+ // Ensure we're not at the end of the list first off
+ if(bl_model[Model].devvend_id == 0)
+ break;
+
+ // Ensure we have the right resolution and function capabilities
+ if((Strapping & BL_FRAME_BUFFER_SIZE_MASK)
+ == bl_model[Model].strapping){
+
+ // Check to see if we're a DD2 PRISM chip (not DD2 card!)
+ if((Strapping & BL_STRAP_CHIP_REV_MASK) ==
+ BL_STRAP_CHIP_DD2){
+
+ // If we're a DD2 PRISM chip, ensure we have a
+ // DD2 PRISM level model entry
+ if(((Strapping & BL_STRAP_CHIP_REV_MASK) >> 28) ==
+ bl_model[Model].prism_rev){
+ break;
+ }
+
+ // If we're not DD2 (assume never DD1) PRISM
+ }else{
+
+ // Ensure we are using a DD3 PRISM entry
+ if(bl_model[Model].prism_rev == (BL_STRAP_CHIP_DD3 >> 28)){
+ break;
+ }
+ }
+ }
+ }
+ if (bl_model[Model].devvend_id == 0){
+ BL_DBG_PRINT("Cannot find correct adapter model rec!\n");
+ return;
+ }
+
+ BL_DBG_PRINT("Model = %d\n", Model);
+
+ for(i=0,crt_rec=&bl_crt_ctrl_rec[0];
+ ((!found)&&(i<BL_NUM_CRT_CTRL_REC_STRUCTS));
+ crt_rec++,i++)
+ {
+ if(crt_rec->MonID == (USHORT)monID){
+ found = TRUE;
+ break;
+ }
+ }
+ // If we did not find a valid CRT structure then we have
+ // a serious error since BLGetMonitorID should have already
+ // handled the case where the ID is not valid
+ if(!found){
+ BL_DBG_PRINT("Invalid monitor ID! 0x%04x\n", (USHORT)monID);
+ return;
+ }
+
+ BL_DBG_PRINT ("START MonitorID = 0x%04x\n", (USHORT)monID) ;
+ BL_DBG_PRINT ("width=%d height=%d refresh=%d\n",
+ crt_rec->width, crt_rec->height, crt_rec->refresh);
+
+ //
+ // Determine which adpt_rec to use based off the adapter model
+ // and crt_rec (from monitor ID)
+ //
+
+ adpt_rec = bl_model[Model].adp_ctrl_rec;
+
+ switch(Strapping & BL_FRAME_BUFFER_SIZE_MASK){
+ case BL_FRAME_BUFFER_SIZE_2_MEG:
+ vram = 2;
+ break;
+ case BL_FRAME_BUFFER_SIZE_4_MEG:
+ vram = 4;
+ break;
+ case BL_FRAME_BUFFER_SIZE_6_MEG:
+ vram = 6;
+ break;
+ case BL_FRAME_BUFFER_SIZE_8_MEG:
+ vram = 8;
+ break;
+ }
+
+ BL_DBG_PRINT("crt_rec = 0x%x\n", crt_rec);
+ BL_DBG_PRINT("crt_rec->MonID = %d\n",
+ crt_rec->MonID);
+ BL_DBG_PRINT("crt_rec->width, height = %d,%d\n",
+ crt_rec->width, crt_rec->height);
+
+ found = FALSE;
+ for(i=0;i<bl_model[Model].num_adp_ctrl_recs;i++){
+
+ BL_DBG_PRINT("adpt_rec->width, height = %d,%d\n",
+ adpt_rec->width, adpt_rec->height);
+ BL_DBG_PRINT("adpt_rec->vram, vram = 0x%x, 0x%x\n",
+ adpt_rec->vram, vram);
+
+ if((adpt_rec->vram == vram) &&
+ (crt_rec->width <= adpt_rec->width) &&
+ (crt_rec->height <= adpt_rec->height)){
+ found = TRUE;
+ break;
+ }
+ ++adpt_rec;
+ }
+ // If adapter record not found, then we're hosed!
+ if(!found){
+ BL_DBG_PRINT("Could not find correct adpt rec!\n");
+ return;
+ }
+
+ /*********************************************/
+ /* S E T H A L V A R I A B L E S */
+ /*********************************************/
+
+ //
+ // set the correct horizontal and vertical resolutions for HAL
+ //
+
+ HalpHorizontalResolution = crt_rec->width;
+ HalpVerticalResolution = crt_rec->height;
+ BL_DBG_PRINT("HalpHorizontalResolution = %d HalpVerticalResolution = %d\n",
+ HalpHorizontalResolution, HalpVerticalResolution);
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpVerticalResolution / HalpCharacterHeight;
+
+ // GXT200P/GXT250P real scanline length is hardcoded at 4096
+ // pixels independent
+ // of the resolution on the screen
+ HalpScrollLine =
+ BL_SCANLINE_LENGTH * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpHorizontalResolution / HalpCharacterWidth;
+ BL_DBG_PRINT("DisplayText = %d ScrollLine = %d ScrollLength = %d DisplayWidth = %d\n",
+ HalpDisplayText, HalpScrollLine, HalpScrollLength, HalpDisplayWidth);
+
+
+ /**************************************************/
+ /* R E I N I T I A L I Z E T H E C A R D */
+ /**************************************************/
+
+ //
+ // Initialize the adapter card for the resolution found by looking
+ // at the monitor ID
+ //
+
+ if(BLInitialize(HalpBLRegisterBase, crt_rec, adpt_rec) == FALSE){
+ BL_DBG_PRINT("BLInitialize(monID=0x%x) failed\n", monID);
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return;
+ }
+
+
+ /*********************************************/
+ /* U N M A P R E G I S T E R S P A C E */
+ /*********************************************/
+
+ //
+ // Unmap the the adapter register range from memory.
+ //
+
+ if (HalpInitPhase == 0) {
+
+ if (HalpBLRegisterBase) {
+ BL_DBG_PRINT("call KePhase0DeleteIoMap() to unmap the reg space. Phys=0x%x Len=0x%x %d\n",
+ bl_phys_address.LowPart, BL_REG_MAP_SIZE, BL_REG_MAP_SIZE);
+ KePhase0DeleteIoMap(bl_phys_address.LowPart, BL_REG_MAP_SIZE);
+ HalpBLRegisterBase = 0x0;
+ }
+ }
+
+
+ /*************************************************/
+ /* M A P F R A M E B U F F E R S P A C E */
+ /*************************************************/
+
+ //
+ // Map in the frame buffer memory which is used to write characters to
+ // the screen.
+ //
+
+ if (HalpInitPhase == 0) {
+
+ BL_DBG_PRINT("call KePhase0MapIo() to map the FB_A space. Phys=0x%x Len=0x%x %d\n",
+ bl_fb_phys_address.LowPart, BL_FB_MAP_SIZE, BL_FB_MAP_SIZE);
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(bl_fb_phys_address.LowPart,
+ (BL_FB_MAP_SIZE >> 1)); // 8MB (MAX BAT)
+ }
+
+ BL_DBG_PRINT("HalpVideoMemoryBase = 0x%x\n", HalpVideoMemoryBase);
+
+
+ /*********************************************/
+ /* M I S C A N D R E T U R N */
+ /*********************************************/
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+
+ BL_DBG_PRINT("leaving HalpDisplayPpcBLSetup()\n");
+ return;
+
+} //end of HalpDisplayPpcBLSetup
+
+
+BOOLEAN
+BLInitialize (
+ volatile PUCHAR HalpBLRegisterBase,
+ bl_crt_ctrl_rec_t *crt_rec,
+ bl_adapter_ctrl_rec_t *adpt_rec
+ )
+
+/*++
+
+Routine Description:
+
+ Sets up the rasterizer and ramdac registers to the particular
+ resolution and refresh rate selected for the GXT200P/GXT250P card
+
+Arguments:
+
+ monID -- indicates the resolution and refresh rate to use
+
+
+Return Value:
+
+ The status of the operation (can only fail on a bad command); TRUE for
+ success, FALSE for failure.
+
+--*/
+
+{
+ int i;
+ ULONG cfg_high_value = 0;
+ ULONG cfg_low_value = 0;
+ USHORT wat_pixel_type;
+ UCHAR bl_clut[768];
+
+
+ BL_DBG_PRINT("Entering BLInitialize\n");
+
+ // Check for PRISM busy. If busy, soft reset PRISM and poll for idle
+ if (PRISM_BUSY(HalpBLRegisterBase))
+ {
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_SOFT_RESET_REG, 0);
+ BL_EIEIO;
+ while(PRISM_BUSY(HalpBLRegisterBase))
+ ;
+ }
+
+ // Disable video display
+ BL_DBG_PRINT("BLInitialize: Disable video display\n");
+
+ // Turn off monitor syncs
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW, LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, BL_640_PWR_LOW_SYNC);
+
+
+ BL_DBG_PRINT("BLInitialize: Setting PRISM config regs to 0x%x\n",
+ adpt_rec->PRISM_cfg);
+ BL_DBG_PRINT("BLInitialize: Setting PRISM mem config regs to 0x%x\n",
+ adpt_rec->mem_cfg);
+
+ // Set PRISM config regs
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CFG_REG, adpt_rec->PRISM_cfg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_MEM_CFG_REG, adpt_rec->mem_cfg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_DTG_CNTL_REG, (adpt_rec->DTG_ctrl |
+ crt_rec->crt_cntl_reg));
+
+ // Set video clock
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_VIDEO_PLL_REF_DIVIDE));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ crt_rec->pll_ref_divide);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ crt_rec->pll_mult);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ crt_rec->pll_output_divide);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ crt_rec->pll_ctrl);
+
+ BL_DBG_PRINT("BLInitialize: Initialize multiplexers\n");
+
+ // Initialize multiplexers
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_RAW_PIXEL_CTRL_00));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->pix_ctrl0);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->pix_ctrl1);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->pix_ctrl2);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->pix_ctrl3);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->wid_ctrl0);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->wid_ctrl1);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->serial_mode_ctrl);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->pix_interleave);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->misc_cfg);
+
+ BL_DBG_PRINT("BLInitialize: Setup VRAM masks\n");
+
+ // Setup VRAM pixel masks
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_VRAM_MASK_REG_0));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->vram_mask_0);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->vram_mask_1);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->vram_mask_2);
+
+ BL_DBG_PRINT("BLInitialize: Clear diags and MISR\n");
+
+ // Clear diagnostics and MISR
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_DIAGNOSTICS));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR15);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR16);
+
+ BL_DBG_PRINT("BLInitialize: Load PRISM DTG regs\n");
+
+ BL_DBG_PRINT("BLInitialize: crt_rec stuct elements = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\n",
+ crt_rec->MonID, crt_rec->width, crt_rec->height,
+ crt_rec->pll_ref_divide, crt_rec->pll_mult,
+ crt_rec->pll_output_divide, crt_rec->pll_ctrl, crt_rec->sync_ctrl,
+ crt_rec->crt_cntl_reg, crt_rec->hrz_total_reg,
+ crt_rec->hrz_dsp_end_reg, crt_rec->hsync_start_reg,
+ crt_rec->hsync_end1_reg, crt_rec->hsync_end2_reg,
+ crt_rec->vrt_total_reg, crt_rec->vrt_dsp_end_reg,
+ crt_rec->vsync_start_reg, crt_rec->vsync_end_reg);
+
+ // Load PRISM DTG regs
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_FR_START_REG, 0);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_HORZ_EXTENT_REG,
+ crt_rec->hrz_total_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_HORZ_DISPLAY_END_REG,
+ crt_rec->hrz_dsp_end_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_HORZ_SYNC_START_REG,
+ crt_rec->hsync_start_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_HORZ_SYNC_END_1_REG,
+ crt_rec->hsync_end1_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_HORZ_SYNC_END_2_REG,
+ crt_rec->hsync_end2_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_VERT_EXTENT_REG,
+ crt_rec->vrt_total_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_VERT_DISPLAY_END_REG,
+ crt_rec->vrt_dsp_end_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_VERT_SYNC_START_REG,
+ crt_rec->vsync_start_reg);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_VERT_SYNC_END_REG,
+ crt_rec->vsync_end_reg);
+
+ // Release syncs
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ (crt_rec->sync_ctrl | BL_640_FLIP_VSYNC));
+
+ // Set PRISM config regs
+ wat_pixel_type = 0x03; // 8 bit common palette index
+ cfg_high_value = ( (AR00 &
+ (~BL_SYS_SRC_DEPTH_A1_MASK & ~BL_FB_PIX_DEPTH_A1_MASK) )
+ | (BL_SYS_SRC_DEPTH_A1_8BPP | BL_FB_PIX_DEPTH_A1_8BPP) );
+ cfg_low_value = AR01;
+
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CNTL_HIGH_REG, cfg_high_value);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CNTL_LOW_REG, cfg_low_value);
+
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_PLANE_WR_MASK_REG, AR03);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CL_TEST_REG, AR04);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_SC_ENABLE_REG, AR05);
+
+ BL_DBG_PRINT("BLInitialize: PRISM Control regs set\n");
+ BL_DBG_PRINT("BLInitialize: Turn off cursor\n");
+
+ // Turn off cursor
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_CURSOR_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR10);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_CROSSHAIR_CTRL_1));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR11);
+
+ BL_DBG_PRINT("BLInitialize: Turn off WIDS\n");
+
+ // Turn off WID's (use only WAT 0)
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_MISC_CFG_REG));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA,
+ adpt_rec->misc_cfg & ~BL_640_WIDCTRL_MASK);
+
+ BL_DBG_PRINT("BLInitialize: Initialize Framebuffer WAT 0\n");
+
+ // Initialize WAT 0
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_FRAME_BUFFER_WAT));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI,
+ HIGH(BL_640_FRAME_BUFFER_WAT));
+
+ // wat_pixel_type set in above case statement
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, wat_pixel_type);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR18);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR19);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR20);
+
+ BL_DBG_PRINT("BLInitialize: Load overlay WAT\n");
+
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_OVERLAY_WAT));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI,
+ HIGH(BL_640_OVERLAY_WAT));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR21);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR22);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR23);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR24);
+
+ // Load the default color palette
+ BL_DBG_PRINT("BLInitialize: Load default color palette\n");
+
+ /*
+ * Set the colormap
+ */
+
+ for(i=0; i<768; i++){
+ if((TextPalette[i] == 16)||
+ (TextPalette[i] == 32)||
+ (TextPalette[i] == 63)){
+ bl_clut[i] = TextPalette[i] * 4;
+ }else{
+ bl_clut[i] = TextPalette[i];
+ }
+ }
+
+ // Load color palette
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_COLOR_PALETTE_WRITE));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI,
+ HIGH(BL_640_COLOR_PALETTE_WRITE));
+
+ // Set to default values
+ for(i=0; i<(768); i++)
+ {
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, bl_clut[i]);
+ }
+
+ // Reset index back to zero
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW, 0);
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI, 0);
+
+ BL_DBG_PRINT("BLInitialize: Clear the frame buffer to background\n");
+
+ // Clear frame buffer to background (dark blue HAL color)
+ BL_EIEIO;
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_FG_COL_REG, 0x1);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_BG_COL_REG, 0x0);
+ BL_EIEIO;
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CMD_REG,BL_PRSM_POLY_REC);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CMD_REG,0);
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_CMD_REG,
+ ((crt_rec->width << 16) | (crt_rec->height)));
+ BL_EIEIO;
+
+ // Wait until clear screen completes before proceeding
+ while(PRISM_BUSY(HalpBLRegisterBase))
+ ;
+
+ // Enable video display
+ BL_DBG_PRINT("BLInitialize: Enable video\n");
+ BL_DBG_PRINT("BLInitialize: Release syncs\n");
+
+ // Release sync's
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW, LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_HI, HIGH(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, crt_rec->sync_ctrl);
+
+ BL_DBG_PRINT("BLInitialize: Turn on video\n");
+
+ // Turn on video
+ PRISM_WRT_REG(HalpBLRegisterBase, BL_PRSM_DTG_CNTL_REG,
+ (adpt_rec->DTG_ctrl | crt_rec->crt_cntl_reg));
+
+ // Turn on DAC to enable video
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW, LOW(BL_640_DAC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA, AR08);
+
+ BL_DBG_PRINT("BLInitializee: FINISH\n") ;
+
+
+ return TRUE;
+}
+
+
+VOID
+BLWaitForVerticalSync (
+ volatile PUCHAR HalpBLRegisterBase
+ )
+{
+ // This function is called by BLGetMonitorID in order to
+ // conform to the ramdac hardware specs when reading the
+ // cable ID information from the monitor ID register on
+ // the ramdac
+
+ int counter = 0;
+
+ // Loop until out of Vertical Sync just in case we happened to
+ // catch the tail end of a vertical blank cycle
+
+ while ((PRISM_RD_REG(HalpBLRegisterBase, BL_PRSM_STATUS_REG) &
+ BL_PRSM_VERT_RETRACE) && (++counter < 1000000))
+ ;
+
+ counter = 0;
+
+ // Wait until we hit the leading edge of the Vertical Sync
+ while ((!(PRISM_RD_REG(HalpBLRegisterBase, BL_PRSM_STATUS_REG) &
+ BL_PRSM_VERT_RETRACE)) && (++counter < 1000000))
+ ;
+
+}
+
+
+UCHAR
+bl_rd_cable_id (
+ ULONG HalpBLRegisterBase
+)
+{
+ UCHAR id;
+
+ PRISM_WRT_DAC(HalpBLRegisterBase, BL_640_INDEX_LOW,
+ LOW(BL_640_MONITOR_ID));
+ BL_EIEIO;
+ id = PRISM_RD_DAC(HalpBLRegisterBase, BL_640_INDEX_DATA);
+
+ BL_DBG_PRINT("bl_rd_cable_id: 0x%02x\n", id);
+ return((id>>4) & 0x0f);
+}
+
+
+BOOLEAN
+BLGetMonitorID (
+ volatile PUCHAR HalpBLRegisterBase,
+ PULONG monID
+ )
+{
+ UCHAR monitor_id, id2, id3;
+
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_LOW, LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_HI, HIGH(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_DATA, BL_640_PWR_LOW_SYNC);
+
+ // Stall
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+
+ monitor_id = bl_rd_cable_id((ULONG)HalpBLRegisterBase);
+
+ /* force V-Sync High */
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_LOW, LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_DATA, BL_640_PWR_HIGH_VSYNC);
+
+ // Stall
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+
+ id2 = bl_rd_cable_id((ULONG)HalpBLRegisterBase);
+
+ /* force V-Sync low, H-Sync high */
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_LOW, LOW(BL_640_SYNC_CTRL));
+ PRISM_WRT_DAC(HalpBLRegisterBase,
+ BL_640_INDEX_DATA, BL_640_PWR_HIGH_HSYNC);
+
+ // Stall
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+ BLWaitForVerticalSync(HalpBLRegisterBase);
+
+ id3 = bl_rd_cable_id((ULONG)HalpBLRegisterBase);
+
+ /* if V or H bit value then we must */
+
+ /* generate monitor ID */
+ if ((monitor_id != id2) || (monitor_id != id3)) {
+
+ /* make sure that V/H bit value is */
+ /* only located in bit 3 of cable ID */
+ if ((((monitor_id ^ id2) | (monitor_id ^ id3)) & 0x07) ||
+ (((monitor_id ^ id2) & 0x08) && ((monitor_id ^ id3) & 0x08))) {
+
+ /* too many bits switching, invalid ID */
+ BL_DBG_PRINT("BLGetMonitorID: Invalid ID = 0x%02x 0x%02x 0x%02x\n",
+ monitor_id, id2, id3);
+ monitor_id = 0x0F; /* set to "not connected" value */
+ }else{ /* see if cable ID bit 3 = V */
+ if ((monitor_id ^ id2) & 0x08)
+ monitor_id = (monitor_id & 0x07) | 0x10;
+ else /* cable ID bit 3 must be H */
+ monitor_id = (monitor_id & 0x07) | 0x18;
+ }
+ }
+
+ BL_DBG_PRINT("BLGetMonitorID (read) = 0x%02x\n", monitor_id);
+
+ switch(monitor_id){
+ case BL_MT_04: // 0100
+ case BL_MT_07: // 0111
+ case BL_MT_1A: // H010
+ case BL_MT_17: // V111
+ case BL_MT_0A: // 1010
+ // The above monitor ID's translate directly to a default
+ // CRT structure entry
+ break;
+ case BL_MT_0F: // 1111 (no monitor connected)
+ default: // XXXX (anything else)
+ // The above monitor ID's do not translate to a default
+ // CRT structure entry so we pick a default here
+ monitor_id = BL_MT_0A; // The default monitor ID
+ }
+
+ BL_DBG_PRINT("BLGetMonitorID (returned) = 0x%02x\n", monitor_id);
+ *monID = (ULONG) monitor_id;
+
+ return TRUE;
+}
+
+
+VOID
+HalpDisplayCharacterBL (
+ IN UCHAR Character
+ )
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encountered, the frame buffer is
+ scrolled. If characters extend below the end of line, they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If the character is a newline:
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ BLScrollScreen();
+ }
+ }
+
+ //
+ // If the character is a tab:
+ //
+
+ else if( Character == '\t' ) {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= HalpDisplayWidth ) { // tab beyond end of screen?
+ HalpColumn = 0; // set to 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ BLScrollScreen();
+ else
+ ++HalpRow;
+ }
+ }
+
+ //
+ // If the character is a return:
+ //
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ }
+
+ //
+ // If the character is a DEL:
+ //
+
+ else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ Character = 0x20 - HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterBL((PUCHAR)HalpFontHeader +
+ HalpFontHeader->Map[Character].Offset);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ }
+
+ //
+ // If not special character:
+ //
+
+ else {
+
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter))
+ Character = HalpFontHeader->DefaultCharacter;
+ else
+ Character -= HalpFontHeader->FirstCharacter;
+
+ // Auto wrap for HalpDisplayWidth columns per line
+ if (HalpColumn >= HalpDisplayWidth) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ BLScrollScreen();
+ }
+ }
+
+ HalpOutputCharacterBL((PUCHAR)HalpFontHeader +
+ HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalpOutputCharacterBL(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ //if (HalpColumn == HalpDisplayWidth) {
+ // HalpDisplayCharacterBL('\n');
+ //}
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(HalpVideoMemoryBase +
+ (HalpRow * HalpScrollLine) +
+ (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |=
+ *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ *Destination = 0x01; // Clear out any pre-existing char
+ if (FontValue >> 31 != 0)
+ *Destination = 0x3F; // Make this pixel white (ARC color)
+
+ Destination++;
+ FontValue <<= 1;
+ }
+ Destination += (BL_SCANLINE_LENGTH - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+ return;
+}
+
+
+VOID
+BLScrollScreen (
+ VOID
+ )
+{
+ PULONG Destination, Source, End;
+ ULONG pix_col, Stride;
+
+ // Scroll up one line
+ Destination = (PULONG) HalpVideoMemoryBase;
+ Source = (PULONG) (HalpVideoMemoryBase + HalpScrollLine);
+ End = (PULONG) ((PUCHAR) Source + HalpScrollLength);
+ Stride = (ULONG) ((BL_SCANLINE_LENGTH - HalpHorizontalResolution) >> 2);
+
+ while(Source < End){
+ pix_col = 0;
+ while(pix_col++ < (HalpHorizontalResolution >> 2)){
+ *Destination++ = *Source++;
+ }
+ Destination += Stride;
+ Source += Stride;
+ }
+
+ // Blue the bottom line
+ Destination = (PULONG) (HalpVideoMemoryBase + HalpScrollLength);
+ End = (PULONG) ((PUCHAR) Destination + HalpScrollLine);
+ while(Destination < End){
+ for (pix_col =0; pix_col < (HalpHorizontalResolution >> 2);
+ pix_col ++){
+ *Destination++ = 0x01010101;
+ }
+ Destination += Stride;
+ }
+}
+
+
+BOOLEAN
+BLGetConfigurationInfo (
+ IN ULONG dev_ven_id,
+ IN PULONG bus,
+ IN PULONG slot
+ )
+{
+
+ ULONG value, i, j;
+ volatile PUCHAR HalpBLRegisterBase;
+ BOOLEAN found;
+
+
+ if (HalpInitPhase == 0) {
+
+ if(HalpPhase0MapBusConfigSpace () == FALSE){
+ BL_DBG_PRINT("HalpPhase0MapBusConfigSpace() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return (FALSE);
+ }
+ }
+
+ found = FALSE;
+
+ for (j=0; j < HalpPciMaxBuses; j++) {
+ for (i=0; ((i<HalpPciMaxSlots)&&(found==FALSE)); i++){
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0GetPciDataByOffset (j, i, &value, 0x0, 4);
+ } else {
+ HalGetBusDataByOffset(PCIConfiguration,
+ j,
+ i,
+ &value,
+ 0x0,
+ 4);
+
+ }
+
+ if(value == dev_ven_id){
+ *slot = i;
+ *bus = j;
+ found = TRUE;
+ }
+ }
+ }
+
+ if(found == FALSE){
+ BL_DBG_PRINT("Cannot find adapter!\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ if (HalpInitPhase == 0) HalpPhase0UnMapBusConfigSpace ();
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+BOOLEAN
+BLSetConfigurationRegister (
+ IN ULONG bus,
+ IN ULONG slot,
+ IN ULONG offset,
+ IN ULONG reg_value
+ )
+{
+ if (HalpInitPhase == 0) {
+
+ if(HalpPhase0MapBusConfigSpace () == FALSE){
+ BL_DBG_PRINT("HalpPhase0MapBusConfigSpace() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return (FALSE);
+ }
+ }
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0SetPciDataByOffset (bus, slot, &reg_value, offset, 4);
+ HalpPhase0UnMapBusConfigSpace ();
+ } else {
+ HalSetBusDataByOffset(PCIConfiguration,
+ bus,
+ slot,
+ &reg_value,
+ offset,
+ 4);
+ }
+
+ return (TRUE);
+}
+
+BOOLEAN
+BLGetConfigurationRegister (
+ IN ULONG bus,
+ IN ULONG slot,
+ IN ULONG offset,
+ IN PULONG reg_value
+ )
+{
+ if (HalpInitPhase == 0) {
+
+ if(HalpPhase0MapBusConfigSpace () == FALSE){
+ BL_DBG_PRINT("HalpPhase0MapBusConfigSpace() failed\n");
+#ifdef KDB
+ DbgBreakPoint();
+#endif
+ return (FALSE);
+ }
+ }
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0GetPciDataByOffset (bus, slot, reg_value, offset, 4);
+ HalpPhase0UnMapBusConfigSpace ();
+ } else {
+ HalGetBusDataByOffset(PCIConfiguration,
+ bus,
+ slot,
+ reg_value,
+ offset,
+ 4);
+ }
+
+ return (TRUE);
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxbusdat.c b/private/ntos/nthals/halppc/ppc/pxbusdat.c
new file mode 100644
index 000000000..2053ab1e6
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxbusdat.c
@@ -0,0 +1,200 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Ken Reneris (kenr) July-28-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+
+--*/
+
+#include "halp.h"
+
+
+VOID HalpInitOtherBuses (VOID);
+
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+
+
+//
+// Prototype for system bus handlers
+//
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetIsaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+ Bus = HalpAllocateBusHandler (Internal, -1, 0, -1, 0, 0);
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa bus 0
+
+ Bus = HalpAllocateBusHandler (Isa, -1, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->GetInterruptVector = HalpGetIsaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustIsaResourceList;
+
+
+ HalpInitOtherBuses ();
+}
+
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusInterfaceType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ )
+/*++
+
+Routine Description:
+
+ Stub function to map old style code into new HalRegisterBusHandler code.
+
+ Note we can add our specific bus handler functions after this bus
+ handler structure has been added since this is being done during
+ hal initialization.
+
+--*/
+{
+ PBUS_HANDLER Bus;
+
+
+ //
+ // Create bus handler - new style
+ //
+
+ HaliRegisterBusHandler (
+ InterfaceType,
+ BusDataType,
+ BusNumber,
+ ParentBusInterfaceType,
+ ParentBusNumber,
+ BusSpecificData,
+ NULL,
+ &Bus
+ );
+
+ if (InterfaceType != InterfaceTypeUndefined) {
+ Bus->BusAddresses = ExAllocatePool (SPRANGEPOOL, sizeof (SUPPORTED_RANGES));
+ RtlZeroMemory (Bus->BusAddresses, sizeof (SUPPORTED_RANGES));
+ Bus->BusAddresses->Version = BUS_SUPPORTED_RANGE_VERSION;
+ Bus->BusAddresses->Dma.Limit = 7;
+ Bus->BusAddresses->Memory.Limit = 0x3EFFFFFF;
+ Bus->BusAddresses->Memory.SystemAddressSpace = 0;
+ Bus->BusAddresses->Memory.SystemBase = PCI_MEMORY_PHYSICAL_BASE;
+ Bus->BusAddresses->IO.SystemBase = 0x80000000;
+ Bus->BusAddresses->IO.Limit = 0x3F7FFFFF;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0;
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+ }
+
+
+ return Bus;
+}
+
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxcache.s b/private/ntos/nthals/halppc/ppc/pxcache.s
new file mode 100644
index 000000000..7e7a94d28
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxcache.s
@@ -0,0 +1,1188 @@
+//++
+//
+// Copyright (c) 1993, 94, 95, 96 IBM Corporation
+//
+// Module Name:
+//
+// pxcache.s
+//
+// Abstract:
+//
+// This module implements the routines to flush cache on the PowerPC.
+//
+// Author:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) September 1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 27-Dec-93 plj Added 603 support.
+// 13-Mar-94 plj Fixed problem introduced during switch to pas,
+// added 604 support.
+// 18-Jan-95 plj Add 603+, 604+ and 620 support.
+// 15-Nov-95 plj Switch to MP safe version (slightly faster too)
+// Also, support 603++ and 604++.
+//
+//--
+
+#include "kxppc.h"
+
+//
+// Override the ENABLE/DISABLE INTERRUPTS macros from kxppc.h because
+// unless this machine has a 603e/ev in it, we don't need the workaround
+// for errata 15.
+//
+
+#undef DISABLE_INTERRUPTS
+#undef ENABLE_INTERRUPTS
+
+#define DISABLE_INTERRUPTS(p0, s0) ; \
+ mfmsr p0 ; \
+ rlwinm s0,p0,0,~MASK_SPR(MSR_EE,1) ; \
+ mtmsr s0
+
+#define ENABLE_INTERRUPTS(p0) mtmsr p0
+
+ .set HID0, 1008 // H/W Implementation Dependent reg 0
+
+//
+// Define various known processor types.
+//
+
+ .set PV601, 1 // 601
+ .set PV603, 3 // 603
+ .set PV603E, 6 // 603 plus
+ .set PV603EV,7 // 603 plus plus
+ .set PV603ART,8 // Arthur (603xx desig unknown)
+ .set PV604, 4 // 604
+ .set PV604E, 9 // 604 plus
+ // 604 plus plus same as 604 plus
+ .set PV620, 20 // 620
+
+//
+// Note, in the following, the 603's "I-Cache Flash Invalidate"
+// and the 604's "I-Cache Invalidate All" basically perform the
+// same function although the usage is slightly different.
+// In the 603 case, ICFI must be cleared under program control
+// after it is set. In the 604 the bit clears automatically.
+// The 620's ICEFI behaves in the same way as the 604's ICIA.
+//
+
+ .set H0_603_ICFI, 0x0800 // I-Cache Flash Invalidate
+ .set H0_604_ICIA, 0x0800 // I-Cache Invalidate All
+ .set H0_620_ICEFI,0x0800 // I-Cache Edge Flash Invalidate
+ .set H0_603_DCFA, 0x0040 // D-Cache Flush Assist (Arthur)
+
+//
+// Cache layout
+//
+// Processor | Size (bytes) | Line | Block | Sets | PVR Processor
+// | I-Cache | D-Cache | Size | Size | | Version
+// ----------------------------------------------------------------------
+// 601 | 32KB Unified | 64B | 32B | | 0x0001xxxx
+// 603 | 8KB | 8KB | 32 | 32 | | 0x0003xxxx
+// 603+ | 16KB | 16KB | 32 | 32 | 4x128 | 0x0006xxxx
+// 603++ | 16KB | 16KB | 32 | 32 | 4x128 | 0x0007xxxx
+// Arthur | 32KB | 32KB | 32 | 32 | 8x128 | 0x0008xxxx
+// 604 | 16KB | 16KB | 32 | 32 | 4x128 | 0x0004xxxx
+// 604+ | 32KB | 32KB | 32 | 32 | 4x128 | 0x0009xxxx
+// 604++ | 32KB | 32KB | 32 | 32 | | 0x0009xxxx
+// 620 | 32KB | 32KB | 64 | 64 | | 0x0014xxxx
+//
+
+ .set DCLSZ601, 64 // 601 cache line size
+ .set DCBSZ601, 32 // 601 cache block size
+ .set DCL601, 32 * 1024 / DCLSZ601 // 601 num cache lines
+ .set DCBSZL2601, 5 // 601 log2(block size)
+
+ .set DCBSZ603, 32 // 603 cache block size
+ .set DCB603, 8 * 1024 / DCBSZ603 // 603 num cache blocks
+ .set DCBSZL2603, 5 // 603 log2(block size)
+
+ .set DCB603E, 16 * 1024 / DCBSZ603 // 603+ num cache blocks
+ .set DCB603ART, 32 * 1024 / DCBSZ603 // Arthur num cache blocks
+
+ .set DCBSZ604, 32 // 604 cache block size
+ .set DCB604, 16 * 1024 / DCBSZ604 // 604 num cache blocks
+ .set DCBSZL2604, 5 // 604 log2(block size)
+
+ .set DCB604E, 32 * 1024 / DCBSZ604 // 604+ num cache blocks
+
+ .set DCBSZ620, 64 // 620 cache block size
+ .set DCB620, 32 * 1024 / DCBSZ620 // 620 num cache blocks
+ .set DCBSZL2620, 6 // 620 log2(block size)
+
+//
+// The following variables are declared locally so their addresses
+// will appear in the TOC. During initialization, we overwrite
+// the TOC entries with the entry points for the cache flushing
+// routines appropriate for the processor we are running on.
+//
+// It is done this way rather than filling in a table to reduce the
+// number of access required to get the address at runtime.
+// (This is known as "Data in TOC" which is not very much used in
+// NT at this time).
+//
+
+ .data
+ .globl HalpSweepDcache
+HalpSweepDcache: .long 0
+ .globl HalpSweepIcache
+HalpSweepIcache: .long 0
+ .globl HalpSweepDcacheRange
+HalpSweepDcacheRange: .long 0
+ .globl HalpSweepIcacheRange
+HalpSweepIcacheRange: .long 0
+
+//++
+//
+// Routine Description:
+//
+// HalpCacheSweepSetup
+//
+// This routine is called during HAL initialization. Its function
+// is to set the branch tables for cache flushing routines according
+// to the processor type.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ LEAF_ENTRY(HalpCacheSweepSetup)
+
+ mfpvr r.3 // get processor type
+ rlwinm r.3, r.3, 16, 0xffff // remove version
+ cmpwi r.3, PV603E // binary search for the right code
+ lwz r.4, [toc].data(r.toc) // get address of local data section
+ bge hcss.high // jif 603+ or greater
+ cmpwi r.3, PV603
+ beq hcss.603 // jif 603
+ bgt hcss.604 // > 603, < 603+ must be 604
+
+//
+// processor is a 601
+//
+
+ lwz r.5, [toc]HalpSweepDcache601(r.toc)
+ mr r.7, r.5 // do nothing
+ mr r.8, r.5 // do nothing
+ mr r.6, r.5 // 601 icache use dcache routine
+
+//
+// On a 601, the routine HalFlushIoBuffers is not required because the
+// 601 has a unified cache and coherency with other system components
+// is maintained. HalpSweepDcache601 is a no-op, ie it does nothing
+// but return. HalFlushIoBuffers is only called via the TOC (ie it is
+// not used withing the HAL) so change the TOC entry for it to point to
+// HalpSweepDcache601.
+//
+ .extern HalFlushIoBuffers
+
+ stw r.5, [toc]HalFlushIoBuffers(r.toc)
+ b hcss.done
+
+//
+// processor is a 603
+//
+
+hcss.603:
+
+ lwz r.5, [toc]HalpSweepDcache603(r.toc)
+ lwz r.6, [toc]HalpSweepIcache603(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange603(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange603(r.toc)
+ b hcss.done
+
+//
+// processor is a 604
+//
+
+hcss.604:
+
+ lwz r.5, [toc]HalpSweepDcache604(r.toc)
+ lwz r.6, [toc]HalpSweepIcache604(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange604(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange604(r.toc)
+ b hcss.done
+
+//
+// Processor type >= 603+, continue isolation of processor type.
+//
+
+hcss.high:
+
+ beq hcss.603p // jif 603 plus
+ cmpwi cr.7, r.3, PV603EV
+ cmpwi cr.0, r.3, PV604E
+ cmpwi cr.1, r.3, PV620
+ cmpwi cr.6, r.3, PV603ART
+ beq cr.7, hcss.603p // treat 603++ same as 603+
+ beq cr.0, hcss.604p // jif 604 plus
+ beq cr.1, hcss.620 // jif 620
+ beq cr.6, hcss.603art // jif Arthur
+
+//
+// If we got here we are running on a processor whose cache characteristics
+// are not known. Return non-zero for error.
+//
+
+ li r.3, 1
+ blr
+
+//
+// processor is a 603 plus
+//
+
+hcss.603p:
+
+ lwz r.5, [toc]HalpSweepDcache603p(r.toc)
+ lwz r.6, [toc]HalpSweepIcache603p(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange603p(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange603p(r.toc)
+ b hcss.done
+
+//
+// Processor is an Arthur. Note: Arthur uses the 603 routines
+// for everything except SweepDcache.
+//
+
+hcss.603art:
+
+ lwz r.5, [toc]HalpSweepDcache603art(r.toc)
+ lwz r.6, [toc]HalpSweepIcache603(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange603(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange603(r.toc)
+ b hcss.done
+
+//
+// processor is a 604 plus
+//
+
+hcss.604p:
+
+ lwz r.5, [toc]HalpSweepDcache604p(r.toc)
+ lwz r.6, [toc]HalpSweepIcache604p(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange604p(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange604p(r.toc)
+ b hcss.done
+
+//
+// processor is a 620
+//
+
+hcss.620:
+
+ lwz r.5, [toc]HalpSweepDcache620(r.toc)
+ lwz r.6, [toc]HalpSweepIcache620(r.toc)
+ lwz r.7, [toc]HalpSweepDcacheRange620(r.toc)
+ lwz r.8, [toc]HalpSweepIcacheRange620(r.toc)
+ b hcss.done
+
+
+hcss.done:
+
+//
+// r.5 thru r.9 contain the address of the function descriptors
+// for the routines we really want to use. Dereference them to
+// get at the entry point addresses.
+//
+ lwz r.5, 0(r.5)
+ lwz r.6, 0(r.6)
+ lwz r.7, 0(r.7)
+ lwz r.8, 0(r.8)
+
+//
+// Store the entry point addresses directly into the TOC.
+// This is so direct linkage from within the HAL to the
+// generic cache flushing routines can get to the desired
+// routines for this processor.
+//
+
+ stw r.5, [toc]HalpSweepDcache(r.toc)
+ stw r.6, [toc]HalpSweepIcache(r.toc)
+ stw r.7, [toc]HalpSweepDcacheRange(r.toc)
+ stw r.8, [toc]HalpSweepIcacheRange(r.toc)
+
+//
+// Modify the Function Descriptors for the generic routines to
+// point directly at the target routines so that linkage from
+// other executables (eg the kernel) will be direct rather
+// than via the generic routines.
+//
+
+ lwz r.3, [toc]HalSweepDcache(r.toc)
+ lwz r.4, [toc]HalSweepIcache(r.toc)
+ stw r.5, 0(r.3)
+ stw r.6, 0(r.4)
+ lwz r.3, [toc]HalSweepDcacheRange(r.toc)
+ lwz r.4, [toc]HalSweepIcacheRange(r.toc)
+ stw r.7, 0(r.3)
+ stw r.8, 0(r.4)
+
+ li r.3, 0 // return code = success
+
+ LEAF_EXIT(HalpCacheSweepSetup)
+
+//++
+//
+// Routines HalSweepDcache
+// HalSweepIcache
+// HalSweepDcacheRange
+// HalSweepIcacheRange
+//
+// are simply dispatch points for the appropriate routine for
+// the processor being used.
+//
+//--
+
+
+ LEAF_ENTRY(HalSweepDcache)
+
+ lwz r.12, [toc]HalpSweepDcache(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepDcache)
+
+
+
+ LEAF_ENTRY(HalSweepIcache)
+
+ lwz r.12, [toc]HalpSweepIcache(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepIcache)
+
+
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+ lwz r.12, [toc]HalpSweepDcacheRange(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepDcacheRange)
+
+
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+ lwz r.12, [toc]HalpSweepIcacheRange(r.toc)
+ mtctr r.12
+ bctr
+
+ DUMMY_EXIT(HalSweepIcacheRange)
+
+
+//++
+//
+// 601 Cache Flushing Routines
+//
+// The 601 has a unified instruction/data cache and coherency is
+// maintained. For this reason these routines don't need to do
+// anything.
+//
+// HalpSweepDcache601
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcache601)
+
+ LEAF_EXIT(HalpSweepDcache601)
+
+
+
+
+//++
+//
+// HalpSweepDcacheRange603
+//
+// HalpSweepDcacheRange603p
+//
+// HalpSweepDcacheRange604
+//
+// HalpSweepDcacheRange604p
+//
+// Force data in a given address range to memory.
+//
+// Because this routine works on a range of blocks and block size
+// is the same on 601, 603, 603+, 604 and 604+ we can use the same
+// code for each of them.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheRange604)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange603)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange603p)
+
+ ALTERNATE_ENTRY(HalpSweepDcacheRange604p)
+
+ rlwinm r.5, r.3, 0, DCBSZ601-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ601-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2601 // number of blocks
+ mtctr r.4
+ sync
+hsdr601.fl:
+ dcbst 0, r.3 // flush block
+ addi r.3, r.3, DCBSZ601 // bump address
+ bdnz hsdr601.fl
+
+ LEAF_EXIT(HalpSweepDcacheRange604)
+
+
+
+
+//++
+//
+// HalpSweepIcacheRange601
+//
+// Due to the unified cache, this routine is meaningless on a 601.
+// The reason for flushing a range of instruction address is because
+// of code modification (eg breakpoints) in which case the nature
+// of the unified cache is that the *right* code is in the cache,
+// or because of a transfer of a code page in which case the unified
+// snooping cache will have done the right thing.
+//
+// Therefore this routine simply returns.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange601)
+
+ // return
+
+ LEAF_EXIT(HalpSweepIcacheRange601)
+
+//++
+//
+// 603, 603+ Cache Flushing Routines
+//
+// The 603 has seperate instruction and data caches of 8 KB each.
+// The 603+ has seperate instruction and data caches of 16 KB each.
+// Line size = Block size = 32 bytes.
+//
+// The mechanics of cache manipulation are the same for the 603 and
+// 603+.
+//
+//
+//
+// HalpSweepDcache603 HalpSweepDcache603p
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// The 603 does not have a hashed page table so we can't use the
+// hashed page table as the data range. Instead use the start of
+// KSEG0.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcache603p)
+
+ li r.4, DCB603E // size of 603+ cache in blocks
+ b hsd603
+
+ DUMMY_EXIT(HalpSweepDcache603p)
+
+
+
+ LEAF_ENTRY(HalpSweepDcache603)
+
+ li r.4, DCB603 // size of 603 cache in blocks
+hsd603:
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ cror 0,0,0 // 603e/603ev errata 15
+ sync // ensure ALL previous stores completed
+ LWI(r.3,0x80000000) // known usable virtual address
+ subi r.5, r.3, DCBSZ603 // dec addr prior to inc
+hsd603.ld:
+ lbzu r.8, DCBSZ603(r.5)
+ bdnz hsd603.ld
+ ENABLE_INTERRUPTS(r.10)
+ cror 0,0,0 // 603e/603ev errata 15
+
+ mtctr r.4
+hsd603.fl:
+ dcbst 0, r.3 // ensure block is in memory
+ addi r.3, r.3, DCBSZ603 // bump address
+ bdnz hsd603.fl
+
+ LEAF_EXIT(HalpSweepDcache603)
+
+
+
+
+//++
+//
+// HalpSweepIcache603 HalpSweepIcache603p
+//
+// Sweep the entire instruction cache. The instruction cache (by
+// definition) can never contain modified code (hence there are no
+// icbf or icbst instructions). Therefore what we really need to do
+// here is simply invalidate every block in the cache. This can be
+// done by toggling the Instruction Cache Flash Invalidate (ICFI) bit
+// in the 603's HID0 register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcache603)
+
+ ALTERNATE_ENTRY(HalpSweepIcache603p)
+
+ mfspr r.3, HID0 // 603, use Instruction
+ ori r.4, r.3, H0_603_ICFI // Cache Flash Invalidate
+
+ isync
+ mtspr HID0, r.4 // invalidate I-Cache
+ mtspr HID0, r.3 // re-enable
+
+ LEAF_EXIT(HalpSweepIcache603)
+
+
+
+//++
+//
+// HalpSweepIcacheRange603 HalpSweepIcacheRange603p
+//
+// Remove a range of instructions from the instruction cache.
+//
+// Note that if this is going to take a long time we flash
+// invalidate the I cache instead. Currently I define a
+// "long time" as greater than 4096 bytes which amounts to
+// 128 trips thru this loop (which should run in 256 clocks).
+// This number was selected without bias or forethought from
+// thin air - plj. I chose this number because gut feel tells
+// me that it will cost me more than 256 clocks in cache misses
+// trying to get back to the function that requested the cache
+// flush in the first place.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange603)
+
+ ALTERNATE_ENTRY(HalpSweepIcacheRange603p)
+
+ cmpwi r.4, 4096 // if range > 4096 bytes, flush
+ bgt- ..HalpSweepIcache603 // entire I cache
+
+ rlwinm r.5, r.3, 0, DCBSZ603-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ603-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2603 // number of blocks
+ mtctr r.4
+hsir603.fl:
+ icbi 0, r.3 // invalidate block in I cache
+ addi r.3, r.3, DCBSZ603 // bump address
+ bdnz hsir603.fl
+
+ LEAF_EXIT(HalpSweepIcacheRange603)
+
+//++
+//
+// 603 "Arthur" Cache Flushing Routines
+//
+// Arthur is similar to the 603 in most ways. Differences are:-
+//
+// Size: Arthur's caches are 32KB each.
+// Associativity: Arthur has 128 sets of 8 blocks.
+// Flash Invalidate: Arthur will automatically clear the flash
+// invalidate bit in HID0 where the 603 required
+// that you clear it manually. However, it is
+// ok to to it the old way.
+// Block Replacement Algorithm:
+// Arthur uses a Pseudo Least Recently Used algorithm
+// where other 603s use a strictly LRU mechanism. In
+// order to flush the entire D-Cache we must either
+// touch 12 individual blocks with address bits 20:26
+// that hit the same set, OR, we must set a bit in HID0
+// that causes to use a strict LRU mechanism while doing
+// the flush and turn that bit off again at the end.
+// Hashed Page Table:
+// Arthur DOES use a hashed page table.
+//
+// In light of the above, we use the standard 603 routines for all
+// Arthur's cache flushing routines except the Sweep D-Cache routine.
+//
+//
+// HalpSweepDcache603art
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// Note: Because Arthur has a Hashed Page Table, we use it in the
+// same way as the 604 for cache flushing and therefore do not need
+// the store loop that follows the load loop in the 603 routine.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcache603art)
+
+ li r.4, DCB603ART // size of Arthur cache in blocks
+ mfmsr r.10 // prep to disable ints and data xlate
+ mfspr r.9, HID0 // need to set Data Cache Flush Assist
+ mfsdr1 r.3 // fill the D cache from memory
+ // allocated to the hashed page
+ // table (it's useful and we don't
+ // have to flush it).
+ mtctr r.4
+ rlwinm r.11, r.10, 0, 0xffff7fff// clear INT Enable bit
+ sync // ensure ALL previous stores complete
+ mtmsr r.11 // disable interrupts
+ ori r.7, r.9, H0_603_DCFA
+ oris r.3, r.3, 0x8000 // make addr virtual
+ mtspr HID0,r.7 // set Data Cache Flush Assist
+ subi r.3, r.3, DCBSZ603 // dec addr prior to inc
+ isync
+hsd603art.ld:
+ lbzu r.8, DCBSZ603(r.3)
+ bdnz hsd603art.ld
+ sync
+ mtspr HID0,r.9 // clear Data Cache Flush Assist
+ mtmsr r.10 // reset previous interrupt enable
+ // state.
+
+ LEAF_EXIT(HalpSweepDcache603art)
+
+//++
+//
+// 604 Cache Flushing Routines
+//
+// The 604 has seperate instruction and data caches of 16 KB each.
+// The 604+ has seperate instruction and data caches of 32 KB each.
+// Line size = Block size = 32 bytes.
+//
+//
+//
+// HalpSweepDcache604 HalpSweepDcache604p
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// As in the 601 case, we use the Hashed Page Table for the data
+// in an effort to minimize performance lost by force feeding the
+// cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpSweepDcache604p)
+
+ li r.4, DCB604E // size of 604+ cache in blocks
+ b hsd604
+
+ DUMMY_EXIT(HalpSweepDcache604p)
+
+
+
+ LEAF_ENTRY(HalpSweepDcache604)
+
+ li r.4, DCB604 // size of cache in cache blocks
+hsd604:
+ mfsdr1 r.3 // fill the D cache from memory
+ // allocated to the hashed page
+ // table (it's something useful).
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ sync // ensure ALL previous stores completed
+ oris r.3, r.3, 0x8000 // get VA of hashed page table
+ subi r.5, r.3, DCBSZ604 // dec addr prior to inc
+hsd604.ld:
+ lbzu r.8, DCBSZ604(r.5)
+ bdnz hsd604.ld
+ ENABLE_INTERRUPTS(r.10)
+
+ sync
+
+ LEAF_EXIT(HalpSweepDcache604)
+
+
+
+
+//++
+//
+// HalpSweepIcache604 HalpSweepIcache604p
+//
+// Sweep the entire instruction cache. This routine is functionally
+// similar to the 603 version except that on the 604 the bit in HID0
+// (coincidentally the *same* bit) is called Instruction Cache Invali-
+// sate All (ICIA) and it clears automatically after being set.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcache604)
+
+ ALTERNATE_ENTRY(HalpSweepIcache604p)
+
+ mfspr r.3, HID0 // 604, use Instruction
+ ori r.3, r.3, H0_604_ICIA // Cache Invalidate All
+ isync
+ mtspr HID0, r.3 // invalidate I-Cache
+
+ LEAF_EXIT(HalpSweepIcache604)
+
+
+
+
+//++
+//
+// HalpSweepIcacheRange604 HalpSweepIcacheRange604p
+//
+// Remove a range of instructions from the instruction cache.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange604)
+
+ ALTERNATE_ENTRY(HalpSweepIcacheRange604p)
+
+ rlwinm r.5, r.3, 0, DCBSZ604-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ604-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2604 // number of blocks
+ mtctr r.4
+hsir604.fl:
+ icbi 0, r.3 // invalidate block in I cache
+ addi r.3, r.3, DCBSZ604 // bump address
+ bdnz hsir604.fl
+
+ LEAF_EXIT(HalpSweepIcacheRange604)
+
+//++
+//
+// 620 Cache Flushing Routines
+//
+// The 620 has seperate instruction and data caches of 32 KB each.
+// Line size = Block size = 64 bytes.
+//
+//
+//
+// HalpSweepDcache620
+//
+// Sweep the entire data cache. This is accomplished by loading
+// the cache with data corresponding to a known address range and
+// then ensuring that each block in the cache is not dirty.
+//
+// As in the 601 case, we use the Hashed Page Table for the data
+// in an effort to minimize performance lost by force feeding the
+// cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpSweepDcache620)
+
+ li r.4, DCB620 // size of cache in cache blocks
+hsd620:
+ mfsdr1 r.3 // fill the D cache from memory
+ // allocated to the hashed page
+ // table (it's something useful).
+ mtctr r.4
+ DISABLE_INTERRUPTS(r.10,r.11)
+ sync
+ oris r.3, r.3, 0x8000 // get VA of hashed page table
+ subi r.5, r.3, DCBSZ620 // dec addr prior to inc
+hsd620.ld:
+ lbzu r.8, DCBSZ620(r.5)
+ bdnz hsd620.ld
+ ENABLE_INTERRUPTS(r.10)
+
+ sync
+
+ LEAF_EXIT(HalpSweepDcache620)
+
+
+
+
+//++
+//
+// HalpSweepIcache620
+//
+// Sweep the entire instruction cache. This routine is functionally
+// identical to the 604 version except that on the 620 the bit in HID0
+// (coincidentally the *same* bit) is called Instruction Cache Edge
+// Flash Invalidate (ICEFI).
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcache620)
+
+ mfspr r.3, HID0 // 620, use Instruction
+ ori r.3, r.3, H0_620_ICEFI // Cache Edge Flash Invalidate
+ isync
+ mtspr HID0, r.3 // invalidate I-Cache
+
+ LEAF_EXIT(HalpSweepIcache620)
+
+
+
+
+//++
+//
+// HalpSweepIcacheRange620
+//
+// Remove a range of instructions from the instruction cache.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheRange620)
+
+ rlwinm r.5, r.3, 0, DCBSZ620-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ620-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2620 // number of blocks
+ mtctr r.4
+hsir620.fl:
+ icbi 0, r.3 // invalidate block in I cache
+ addi r.3, r.3, DCBSZ620 // bump address
+ bdnz hsir620.fl
+
+ LEAF_EXIT(HalpSweepIcacheRange620)
+
+
+
+
+//++
+//
+// HalpSweepDcacheRange620
+//
+// Force data in a given address range to memory.
+//
+// Arguments:
+//
+// r.3 Start address
+// r.4 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheRange620)
+
+ rlwinm r.5, r.3, 0, DCBSZ620-1 // isolate offset in start block
+ addi r.4, r.4, DCBSZ620-1 // bump range by block sz - 1
+ add r.4, r.4, r.5 // add start block offset
+ srwi r.4, r.4, DCBSZL2620 // number of blocks
+ mtctr r.4
+ sync
+hsdr620.fl:
+ dcbst 0, r.3 // flush block
+ addi r.3, r.3, DCBSZ620 // bump address
+ bdnz hsdr620.fl
+
+ LEAF_EXIT(HalpSweepDcacheRange620)
+
+//++
+//
+// HalpSweepPhysicalRangeInBothCaches
+//
+// Force data in a given PHYSICAL address range to memory and
+// invalidate from the block in the instruction cache.
+//
+// This implementation assumes a block size of 32 bytes. It
+// will still work on the 620.
+//
+// Arguments:
+//
+// r.3 Start physical PAGE number.
+// r.4 Starting offset within page. Cache block ALIGNED.
+// r.5 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .set PAGE_SHIFT, 12
+
+
+ LEAF_ENTRY(HalpSweepPhysicalRangeInBothCaches)
+
+//
+// Starting physical address = (PageNumber << PAGE_SHIFT) | Offset
+//
+
+ rlwimi r.4, r.3, PAGE_SHIFT, 0xfffff000
+
+ addi r.5, r.5, 31 // bump length by block size - 1
+ srwi r.5, r.5, 5 // get number of blocks
+ mflr r.0 // save return address
+ mtctr r.5 // set loop count
+
+//
+// Interrupts MUST be disabled for the duration of this function as
+// we use srr0 and srr1 which will be destroyed by any exception or
+// interrupt.
+//
+
+ DISABLE_INTERRUPTS(r.12,r.11) // r.11 <- disabled MSR
+ // r.12 <- previous MSR
+ cror 0,0,0 // N.B. 603e/ev errata 15
+//
+// Find ourselves in memory. This is needed as we must disable
+// both instruction and data translation. We do this while
+// interrupts are disabled only to try to avoid changing the
+// Link Register when an unwind might/could occur.
+//
+// The HAL is known to be in KSEG0 so its physical address is
+// its effective address with the top bit stripped off.
+//
+
+ bl hspribc
+hspribc:
+
+ mflr r.6 // r.6 <- &hspribc
+ rlwinm r.6, r.6, 0, 0x7fffffff // r.6 &= 0x7fffffff
+ addi r.6, r.6, hspribc.real - hspribc
+ // r.6 = real &hspribc.real
+
+ sync // ensure all previous loads and
+ // stores are complete.
+
+ mtsrr0 r.6 // address in real space
+
+ rlwinm r.11, r.11, 0, ~0x30 // turn off Data and Instr relocation
+ mtsrr1 r.11
+ rfi // leap to next instruction
+
+hspribc.real:
+ mtsrr0 r.0 // set return address
+ mtsrr1 r.12 // set old MSR value
+
+hspribc.loop:
+ dcbst 0, r.4 // flush data block to memory
+ icbi 0, r.4 // invalidate i-cache
+ addi r.4, r.4, 32 // point to next block
+ bdnz hspribc.loop // jif more to do
+
+ sync // ensure all translations complete
+ isync // don't even *think* about getting
+ // ahead.
+ rfi // return to caller and translated
+ // mode
+
+ DUMMY_EXIT(HalpSweepPhysicalRangeInBothCaches)
+
+//++
+//
+// HalpSweepPhysicalIcacheRange
+//
+// Invalidate a given PHYSICAL address range from the instruction
+// cache.
+//
+// This implementation assumes a block size of 32 bytes. It
+// will still work on the 620.
+//
+// Arguments:
+//
+// r.3 Start physical PAGE number.
+// r.4 Starting offset within page. Cache block ALIGNED.
+// r.5 Length (in bytes)
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpSweepPhysicalIcacheRange)
+
+//
+// Starting physical address = (PageNumber << PAGE_SHIFT) | Offset
+//
+
+ rlwimi r.4, r.3, PAGE_SHIFT, 0xfffff000
+
+ addi r.5, r.5, 31 // bump length by block size - 1
+ srwi r.5, r.5, 5 // get number of blocks
+ mflr r.0 // save return address
+ mtctr r.5 // set loop count
+
+//
+// Interrupts MUST be disabled for the duration of this function as
+// we use srr0 and srr1 which will be destroyed by any exception or
+// interrupt.
+//
+
+ DISABLE_INTERRUPTS(r.12,r.11) // r.11 <- disabled MSR
+ // r.12 <- previous MSR
+ cror 0,0,0 // N.B. 603e/ev errata 15
+//
+// Find ourselves in memory. This is needed as we must disable
+// both instruction and data translation. We do this while
+// interrupts are disabled only to try to avoid changing the
+// Link Register when an unwind might/could occur.
+//
+// The HAL is known to be in KSEG0 so its physical address is
+// its effective address with the top bit stripped off.
+//
+
+ bl hspir
+hspir:
+
+ mflr r.6 // r.6 <- &hspribc
+ rlwinm r.6, r.6, 0, 0x7fffffff // r.6 &= 0x7fffffff
+ addi r.6, r.6, hspir.real - hspir
+ // r.6 = real &hspribc.real
+
+ sync // ensure all previous loads and
+ // stores are complete.
+
+ mtsrr0 r.6 // address in real space
+
+//
+// N.B. It may not be required that Data Relocation be disabled here.
+// I can't tell from my Arch spec if ICBI works on a Data or
+// Instruction address. I believe it is probably a Data
+// address even though it would be sensible for it to be an
+// instruction address,....
+//
+
+ rlwinm r.11, r.11, 0, ~0x30 // turn off Data and Instr relocation
+ mtsrr1 r.11
+ rfi // leap to next instruction
+
+hspir.real:
+ mtsrr0 r.0 // set return address
+ mtsrr1 r.12 // set old MSR value
+
+hspir.loop:
+ icbi 0, r.4 // invalidate i-cache
+ addi r.4, r.4, 32 // point to next block
+ bdnz hspir.loop // jif more to do
+
+ sync // ensure all translations complete
+ isync // don't even *think* about getting
+ // ahead.
+ rfi // return to caller and translated
+ // mode
+
+ DUMMY_EXIT(HalpSweepPhysicalIcacheRange)
diff --git a/private/ntos/nthals/halppc/ppc/pxcalstl.c b/private/ntos/nthals/halppc/ppc/pxcalstl.c
new file mode 100644
index 000000000..9adb8c453
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxcalstl.c
@@ -0,0 +1,132 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service for a PowerPC system.
+
+
+Author:
+
+ David N. Cutler (davec) 26-Apr-1991
+ Jim Wooldridge
+ Steve Johns (Motorola)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// KeQueryPerformanceCounter & KeStallExecutionProcessor are called
+// before Phase 0 initialization, so initialize it to a reasonable value.
+//
+ULONG HalpPerformanceFrequency = 80000000/16;
+ULONG CpuFrequency;
+extern ULONG HalpClockCount;
+extern ULONG HalpFullTickClockCount;
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpCalibrateStall)
+
+#endif
+
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service.
+
+ N.B. This routine is only called during phase 1 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the calibration is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Set initial scale factor
+ //
+
+ PCR->StallScaleFactor = 1;
+
+ //
+ // Compute the clock frequency of the Time Base & Decrementer
+ //
+
+ HalpPerformanceFrequency = HalpCalibrateTB();
+
+ if (HalpPerformanceFrequency <= 718200) {
+ DbgBreakPoint();
+ while (HalpPerformanceFrequency <= 718200) {
+ HalpPerformanceFrequency = HalpCalibrateTB();
+ }
+ }
+
+ HalpPerformanceFrequency = (HalpPerformanceFrequency / 1000) * 1000;
+
+
+ //
+ // If it's the POWER architecture, then RTC is clocked at 7.8125 MHz
+ //
+ if (HalpPerformanceFrequency >= 7812000 &&
+ HalpPerformanceFrequency < 7813000) {
+ HalpPerformanceFrequency = 7812500;
+ } else {
+
+ //
+ // Compute (CPU frequency)*10
+ //
+ CpuFrequency = HalpPerformanceFrequency * 8/100000;
+
+ //
+ // Assume RTC/TB frequency = CpuFrequency/8
+ //
+ HalpPerformanceFrequency = CpuFrequency * 100000 / 8;
+
+ }
+ //
+ // Initialize the system clock variable
+ //
+ HalpClockCount = (HalpPerformanceFrequency * (MAXIMUM_INCREMENT/10000)) / 1000;
+ HalpFullTickClockCount = HalpClockCount;
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxclksup.s b/private/ntos/nthals/halppc/ppc/pxclksup.s
new file mode 100644
index 000000000..f947b0a05
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxclksup.s
@@ -0,0 +1,153 @@
+/***********************************************************************
+
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+ File Name:
+ PXCLKSUP.S
+
+ Globals:
+ none
+
+ Functions:
+ HalpUpdateDecrementer
+ KeQueryPerformanceCounter
+
+ History:
+ 11-Feb-1994 Steve Johns
+ Original Version
+ 23-Jun-1994 Steve Johns (sjohns@pets.sps.mot.com)
+ Fixed HalpZeroPerformanceCounter. Was writing to RTCU & RTCL.
+ Writes should go to SPR 20 & 21.
+***********************************************************************/
+
+#include <halppc.h>
+#define ERRATA603 TRUE
+
+
+
+
+ LEAF_ENTRY(HalpUpdateDecrementer)
+
+
+ mfpvr r.6 // Read Processor Version Register
+ rlwinm r.6,r.6,16,16,31
+ cmpli 0,0,r.6,1 // Is it an MPC601 ?
+ bne Not_601
+ rlwinm r.3,r.3,7,0,24 // Yes, Count *= 128
+Not_601:
+//
+// Read the DECREMENTER to get the interrupt latency and bias Count by
+// that amount. Otherwise, the latencies would accumulate and the time
+// of day would run slow.
+//
+ mfdec r.7 // Read the DECREMENTER
+ add r.4,r.3,r.7 // + Count
+//
+// We expect that the DECREMENTER should be near 0xFFFFFFxx, so R4 should
+// be less than r.3. If not, we don't want to cause an excessively long
+// clock tick, so just ignore the latency and use Count.
+//
+ cmpl 0,0,r.4,r.3
+ ble SetDecr
+ mr r.4,r.3
+SetDecr:
+
+ mtdec r.4 // Write to the DECREMENTER
+#if ERRATA603
+ isync
+#endif
+
+// Undocumented return value: the latency in servicing this interrupt
+ neg r.3,r.7
+
+
+ LEAF_EXIT(HalpUpdateDecrementer)
+
+
+
+ .extern HalpPerformanceFrequency
+ .extern ..HalpGetTimerRoutine
+
+
+/***********************************************************************
+ Synopsis:
+ ULARGE_INTEGER KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER PerformanceFrequency OPTIONAL)
+
+ Purpose:
+ Supplies a 64-bit realtime counter for use in evaluating performance
+ of routines.
+
+ Returns:
+ This routine returns current 64-bit performance counter and,
+ optionally, the frequency of the Performance Counter.
+
+ Global Variables Referenced:
+ HalpPerformanceFrequency
+
+***********************************************************************/
+
+//
+// Register Definitions
+//
+ .set RetPtr, r.3
+ .set Freq, r.4
+ .set TimerLo, r.4 // MUST be same as defined in PXSTALL.S
+ .set TimerHi, r.5 // MUST be same as defined in PXSTALL.S
+ .set Temp, r.7
+
+ .set RTCU, 4
+ .set RTCL, 5
+ .set TB, 284
+ .set TBU, 285
+
+
+ LEAF_ENTRY(KeQueryPerformanceCounter)
+
+ mflr r.0 // Save Link Register
+
+ cmpli 0,0,Freq,0 // Was PerformanceFrequency passed ?
+ beq GetCpuVersion
+
+ lwz Temp,[toc]HalpPerformanceFrequency(r.toc)
+ lwz Temp,0(Temp) // PerformanceFrequency.LowPart =
+ stw Temp,0(Freq) // HalpPerformanceFrequency;
+ li Temp,0 // PerformanceFrequency.HighPart = 0;
+ stw Temp,4(Freq)
+
+GetCpuVersion:
+ bl ..HalpGetTimerRoutine
+
+ bctrl // ReadPerformanceCounter();
+
+ stw TimerLo,0(RetPtr)
+ stw TimerHi,4(RetPtr)
+ mtlr r.0 // Restore Link Register
+
+ LEAF_EXIT(KeQueryPerformanceCounter)
+
+
+ LEAF_ENTRY(HalpZeroPerformanceCounter)
+
+
+ mfpvr r.4 // Read Processor Version Register
+ li r.3, 0
+ rlwinm r.4,r.4,16,16,31
+ cmpli 0,0,r.4,1 // Are we running on an MPC601 ?
+ beq ZeroRTC // Branch if yes
+
+ mtspr TB,r.3
+ mtspr TBU,r.3
+
+ blr
+
+ZeroRTC:
+ mtspr 20,r.3 // Zero the RTC registers
+ mtspr 21,r.3
+
+
+ LEAF_EXIT(HalpZeroPerformanceCounter)
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxclock.c b/private/ntos/nthals/halppc/ppc/pxclock.c
new file mode 100644
index 000000000..ace9f2d32
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxclock.c
@@ -0,0 +1,283 @@
+
+/*****************************************************************************
+
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1996 International Business Machines Corporation
+
+Module Name:
+
+ PXCLOCK.C
+
+Abstract:
+
+ This module contains the system clock interrupt handler.
+ The DECREMENTER is used to implement the system clock. The
+ handler resets the DECREMENTER to SYSTEM_TIME (accounting
+ for interrupt latency), and updates the system time.
+
+
+Author:
+
+ Steve Johns 10-Feb-1994
+
+Revision History:
+
+******************************************************************************/
+
+#include "halp.h"
+
+extern ULONG HalpPerformanceFrequency;
+
+BOOLEAN
+KdPollBreakIn (
+ VOID
+ );
+
+ULONG HalpClockCount;
+ULONG HalpFullTickClockCount;
+ULONG HalpUpdateDecrementer();
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNewTimeIncrement;
+
+#if defined(SOFT_HDD_LAMP)
+
+extern HDD_LAMP_STATUS HalpHddLamp;
+
+#endif
+
+BOOLEAN
+HalpHandleDecrementerInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ Clock interrupt handler for processor 0.
+
+Arguments:
+
+ Interrupt
+
+ ServiceContext
+
+ TrapFrame
+
+Return Value:
+
+ TRUE
+
+--*/
+{
+ KIRQL OldIrql;
+
+ //
+ // Raise irql via updating the PCR
+ //
+
+ OldIrql = PCR->CurrentIrql;
+
+ PCR->CurrentIrql = CLOCK2_LEVEL;
+
+ //
+ // Reset DECREMENTER, accounting for interrupt latency.
+ //
+
+ HalpUpdateDecrementer(HalpClockCount);
+
+ //
+ // Call the kernel to update system time
+ //
+
+ KeUpdateSystemTime(TrapFrame,HalpCurrentTimeIncrement);
+
+ HalpCurrentTimeIncrement = HalpNewTimeIncrement;
+
+#if defined(SOFT_HDD_LAMP)
+
+ //
+ // If HDD Lamp is on and there have been no new interrupts for
+ // mass storage interrupts for enough ticks that the count has
+ // gone zero, turn it off.
+ //
+
+ if ( HalpHddLamp.Count > 0 ) {
+ if ( --HalpHddLamp.Count == 0 ) {
+ *(PUCHAR)((PUCHAR)HalpIoControlBase + HDD_LAMP_PORT) = 0;
+ }
+ }
+
+#endif
+
+ //
+ // Lower Irql to original value and enable interrupts
+ //
+
+ PCR->CurrentIrql = OldIrql;
+
+#if defined(WOODFIELD)
+
+ //
+ // added read to initiate a PCI I/O cycle in order to work around
+ // woodfield prime SIO DMA bug
+ //
+
+ {
+ volatile UCHAR DataByte;
+ DataByte = READ_REGISTER_UCHAR((PUCHAR)HalpIoControlBase + 0xcf8);
+ }
+
+#endif
+
+ HalpEnableInterrupts();
+
+ if ( KdDebuggerEnabled && KdPollBreakIn() ) {
+ DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C);
+ }
+
+ return (TRUE);
+}
+
+
+#if defined(_MP_PPC_)
+
+BOOLEAN
+HalpHandleDecrementerInterrupt1(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ Clock interrupt handler for processors other than 0.
+
+Arguments:
+
+ Interrupt
+
+ ServiceContext
+
+ TrapFrame
+
+Return Value:
+
+ TRUE
+
+--*/
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise irql via updating the PCR
+ //
+
+ OldIrql = PCR->CurrentIrql;
+
+ PCR->CurrentIrql = CLOCK2_LEVEL;
+
+ //
+ // Reset DECREMENTER, accounting for interrupt latency.
+ //
+
+ HalpUpdateDecrementer(HalpFullTickClockCount);
+
+ //
+ // Call the kernel to update run time for this thread and process.
+ //
+
+ KeUpdateRunTime(TrapFrame);
+
+ //
+ // Lower Irql to original value
+ //
+
+ PCR->CurrentIrql = OldIrql;
+
+ return TRUE;
+}
+
+#endif
+
+
+ULONG
+HalSetTimeIncrement (
+ IN ULONG DesiredIncrement
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to set the clock interrupt rate to the frequency
+ required by the specified time increment value.
+
+ N.B. This function is only executed on the processor that keeps the
+ system time.
+
+Arguments:
+
+ DesiredIncrement - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ The actual time increment in 100ns units.
+
+--*/
+
+{
+
+ ULONG NewTimeIncrement;
+ ULONG NextIntervalCount;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // HalpPerformanceFrequence is the number of times the decrementer
+ // ticks in 1 second. MINIMUM_INCREMENT is the number of 100 is the
+ // number of 100ns units in 1 ms.
+ // Therefore, DesiredIncrement/MINUMUM_INCREMENT is the number of
+ // ms desired. This multiplied by the number of decrementer ticks
+ // in 1 second, divided by 1000 gives the number of ticks in the
+ // desired number of milliseconds. This value will go into the
+ // decrementer.
+ //
+
+ NextIntervalCount = (HalpPerformanceFrequency *
+ (DesiredIncrement/MINIMUM_INCREMENT)) / 1000;
+
+ //
+ // Calculate the number of 100ns units to report to the kernel every
+ // time the decrementer fires with this new period. Note, for small
+ // values of DesiredIncrement (min being 10000, ie 1ms), truncation
+ // in the above may result in a small decrement in the 5th decimal
+ // place. As we are effectively dealing with a 4 digit number, eg
+ // 10000 becomes 9999.something, we really can't do any better than
+ // the following.
+ //
+
+ NewTimeIncrement = DesiredIncrement/MINIMUM_INCREMENT * MINIMUM_INCREMENT;
+ HalpClockCount = NextIntervalCount;
+ HalpNewTimeIncrement = NewTimeIncrement;
+ KeLowerIrql(OldIrql);
+ return NewTimeIncrement;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxdakota.h b/private/ntos/nthals/halppc/ppc/pxdakota.h
new file mode 100644
index 000000000..02a2e2419
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxdakota.h
@@ -0,0 +1,67 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxdakota.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ on Dakota memory controllers.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+--*/
+
+
+//
+// define stuctures for memory control and planar register
+//
+
+
+
+typedef struct _DAKOTA_CONTROL {
+ UCHAR Reserved0[0x803]; // Offset 0x000
+ UCHAR SimmId; // Offset 0x803
+ UCHAR SimmPresent; // Offset 0x804
+ UCHAR Reserved1[3];
+ UCHAR HardfileLight; // Offset 0x808
+ UCHAR Reserved2[3];
+ UCHAR EquiptmentPresent; // Offset 0x80C
+ UCHAR Reserved3[3];
+ UCHAR PasswordProtect1; // Offset 0x810
+ UCHAR Reserved4;
+ UCHAR PasswordProtect2; // Offset 0x812
+ UCHAR Reserved5;
+ UCHAR L2Flush; // Offset 0x814
+ UCHAR Reserved6[3];
+ UCHAR Keylock; // Offset 0x818
+ UCHAR Reserved7[3];
+ UCHAR SystemControl; // Offset 0x81c
+ UCHAR Reserved8[3];
+ UCHAR MemoryController; // Offset 0x820
+ UCHAR MemoryControllerTiming; // Offset 0x821
+ UCHAR Reserved9[0x16];
+ UCHAR Eoi9; // Offset 0x838
+ UCHAR Reserved10[3];
+ UCHAR Eoi11; // Offset 0x83C
+ UCHAR Reserved11[3];
+ UCHAR MemoryParityErrorStatus; // Offset 0x840
+ UCHAR MemoryParityErrorClear; // Offset 0x841
+ UCHAR L2CacheErrorStatus; // Offset 0x842
+ UCHAR L2CacheErrorClear; // Offset 0x843
+ UCHAR TransferErrorStatus; // Offset 0x844
+ UCHAR TransferErrorClear; // Offset 0x845
+ UCHAR Reserved12[0xa];
+ UCHAR IoMap; // Offset 0x850
+ UCHAR Reserved13[3];
+} DAKOTA_CONTROL, *PDAKOTA_CONTROL;
diff --git a/private/ntos/nthals/halppc/ppc/pxdat.c b/private/ntos/nthals/halppc/ppc/pxdat.c
new file mode 100644
index 000000000..f04c00971
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxdat.c
@@ -0,0 +1,123 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg("INIT")
+#endif
+
+//
+// The following data is only valid during system initialiation
+// and the memory will be re-claimed by the system afterwards
+//
+
+ADDRESS_USAGE HalpDefaultIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ 0x000, 0x10, // SIO DMA
+ 0x0C0, 0x20, // SIO DMA
+ 0x080, 0x10, // SIO DMA
+ 0x400, 0x40, // SIO DMA
+ 0x480, 0x10, // SIO DMA
+ 0x4D6, 0x2, // SIO DMA
+
+ 0x020, 0x2, // PIC
+ 0x0A0, 0x2, // Cascaded PIC
+
+ 0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+
+ 0x061, 0x1, // NMI (system control port B)
+ 0x092, 0x1, // system control port A
+
+ 0x070, 0x2, // Cmos/NMI enable
+
+ 0x074, 0x4, // NVRAM
+
+ 0x0F0, 0x10, // coprocessor ports
+ 0,0
+ }
+};
+
+// This structure will be filled in with the address usage for
+// the MPIC interrupt controller.
+ADDRESS_USAGE HalpMpicSpace = {
+ NULL, CmResourceTypeMemory, InternalUsage,
+ {
+ 0,0,
+ 0,0,
+ 0,0,
+ 0,0,
+ 0,0
+ }
+};
+
+
+
+//
+// From usage.c
+//
+
+ADDRESS_USAGE *HalpAddressUsageList;
+
+//
+// Misc hal stuff in the registry
+//
+
+WCHAR rgzHalClassName[] = L"Hardware Abstraction Layer";
+
+
+//
+// From ixpcibus.c
+//
+
+WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+WCHAR rgzConfigurationData[] = L"Configuration Data";
+WCHAR rgzIdentifier[] = L"Identifier";
+WCHAR rgzPCIIndetifier[] = L"PCI";
+
+#ifdef POWER_MANAGEMENT
+//
+// From ixinfo.c
+//
+
+WCHAR rgzSuspendCallbackName[] = L"\\Callback\\SuspendHibernateSystem";
+
+#endif // POWER_MANAGEMENT
+
+//
+// From ixpcibrd.c
+//
+
+WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources";
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg()
+#endif
+
+//
+// IDT vector usage info
+//
+
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
diff --git a/private/ntos/nthals/halppc/ppc/pxdisp.c b/private/ntos/nthals/halppc/ppc/pxdisp.c
new file mode 100644
index 000000000..3aeac5dd8
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxdisp.c
@@ -0,0 +1,1733 @@
+
+/*++
+
+Copyright (c) 1994, 95, 96 International Business Machines Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+pxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a Sandalfoot PowerPC system using either an S3 or Weitek P9000
+ video adapter.
+
+Author:
+
+ Jim Wooldridge Sept 1994 - Ported to PowerPC Initial Version
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jess Botts S3 support in text mode Oct-1993
+ Lee Nolan Added Weitek P9000 support Feb-1994
+ Mike Haskell Added Weitek P9100 support Oct-1994
+ Tim White Added GXT150P support Feb-1995
+ Jake Oshins Rearranged everything Jun-1995
+
+--*/
+
+#include "halp.h"
+#include "pxs3.h"
+#include "pxdisp.h"
+#include "string.h"
+#include "pxP91.h"
+
+//=============================================================================
+//
+// IBMBJB added include to get text mode values for the Brooktree 485 DAC's
+// palette registers, removed definition of HDAL and added address
+// definitions for PowerPC
+
+#include "txtpalet.h"
+#include "pci.h"
+#include "pcip.h"
+
+#if defined(_PPC_)
+# define VIDEO_ROM_OFFSET 0x000C0000
+# define MEMORY_PHYSICAL_BASE VIDEO_MEMORY_BASE
+# define CONTROL_PHYSICAL_BASE VIDEO_CONTROL_BASE
+
+#endif
+
+
+
+#define READ_VRAM(port) \
+ *(HalpVideoMemoryBase + (port))
+
+#define WRITE_VRAM(port,data) \
+ *(HalpVideoMemoryBase + (port)) = (data), \
+ KeFlushWriteBuffer()
+
+//PHYSICAL ADDRESS of WEITEK P9000 video ram
+#define P9_VIDEO_MEMORY_BASE 0xC1200000
+
+//PHYSICAL ADDRESS of WEITEK P9100 video ram
+#define P91_VIDEO_MEMORY_BASE 0xC1800000
+
+//PHYSICAL ADDRESS of S3 video ram
+#define S3_VIDEO_MEMORY_BASE 0xC0000000
+
+#define S3_928_DEVICE_ID 0x88B05333
+#define S3_864_DEVICE_ID 0x88C05333
+#define P9_DEVICE_ID 0x1300100E
+#define P91_DEVICE_ID 0x9100100E
+#define BBL_DEVICE_ID 0x001B1014
+#define BL_DEVICE_ID 0x003C1014
+#define WD_90C_DEVICE_ID 0xC24A101c
+#define UNKNOWN_DEVICE_ID 0x0
+
+#define MAX_PCI_BUSSES 256
+
+//PHYSICAL ADDRESSES for GXT150P adapter
+// (in bbldef.h)
+
+// Include GXT150P header file information
+//#include "bblrastz.h"
+//#include "bblrmdac.h"
+#include "bbldef.h"
+
+#define TAB_SIZE 4
+
+
+//
+// Prototypes.
+//
+
+#if defined(_MP_PPC_)
+
+VOID
+HalpAcquireDisplayLock(
+ VOID
+ );
+
+VOID
+HalpReleaseDisplayLock(
+ VOID
+ );
+
+#endif
+
+VOID
+HalpDisplayCharacterVgaViaBios (
+ IN UCHAR Character
+ );
+
+VOID
+HalpDispCharVgaViaBios (
+ IN UCHAR Character
+ );
+
+VOID
+HalpDisplaySetupVgaViaBios (
+ VOID
+ );
+
+VOID
+HalpPositionCursorVgaViaBios (
+ IN ULONG Row,
+ IN ULONG Column
+ );
+
+VOID
+ScrollScreenVgaViaBios (
+ IN UCHAR LinesToScroll
+ );
+
+VOID
+HalpSetupAndClearScreenVgaViaBios (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterS3 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpDisplayPpcS3Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayPpcWDSetup (
+ VOID
+ );
+
+
+VOID
+HalpCopyOEMFontFile();
+
+VOID
+WaitForVSync (
+ VOID
+ );
+
+VOID
+ScreenOn (
+ VOID
+ );
+
+VOID
+ScreenOff (
+ VOID
+ );
+
+VOID
+Scroll_Screen (
+ IN UCHAR line
+ );
+
+
+#if !defined(WOODFIELD)
+
+//
+// Woodfield - IBM PowerPC LapTop machines don't support plug in PCI
+// video adapters so don't pull the init code for those adapters into
+// the HAL.
+//
+
+VOID
+HalpDisplayPpcP9Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterP91 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpDisplayPpcBBLSetup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterBBL (
+ IN UCHAR Character
+ );
+
+VOID
+HalpDisplayPpcBLSetup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterBL (
+ IN UCHAR Character
+ );
+
+#endif
+
+//
+//
+//
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+typedef
+VOID
+(*PHALP_DISPLAY_CHARACTER) (
+ UCHAR
+ );
+
+extern ULONG HalpPciMaxSlots;
+
+extern BOOLEAN
+HalpPhase0MapBusConfigSpace (
+ VOID
+ );
+
+extern VOID
+HalpPhase0UnMapBusConfigSpace (
+ VOID
+ );
+
+extern VOID
+HalpP91RelinquishDisplayOwnership();
+
+//
+// Define static data.
+//
+BOOLEAN HalpDisplayOwnedByHal;
+
+volatile PUCHAR HalpVideoMemoryBase = (PUCHAR)0;
+volatile PUCHAR HalpVideoCoprocBase = (PUCHAR)0;
+
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+PHALP_DISPLAY_CHARACTER HalpDisplayCharacter = NULL;
+
+ULONG HalpDisplayPciDeviceId;
+extern ULONG HalpInitPhase;
+//
+// Define OEM font variables.
+//
+
+USHORT HalpBytesPerRow;
+USHORT HalpCharacterHeight;
+USHORT HalpCharacterWidth;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+//
+// Define display variables.
+//
+ULONG HalpColumn;
+ULONG HalpRow;
+ULONG HalpHorizontalResolution;
+ULONG HalpVerticalResolution;
+
+
+UCHAR HalpDisplayIdentifier[256] = "";
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+
+POEM_FONT_FILE_HEADER HalpFontHeader;
+
+extern ULONG HalpEnableInt10Calls;
+#define PCI_DISPLAY_CONTROLLER 0x03
+#define PCI_PRE_REV_2 0x0
+
+BOOLEAN HalpBiosShadowed = FALSE;
+ULONG HalpVideoBiosLength = 0;
+PUCHAR HalpShadowBuffer;
+extern UCHAR HalpShadowBufferPhase0;
+
+
+BOOLEAN
+HalpInitializeDisplay (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the video memory and control registers into the user
+ part of the idle process address space, initializes the video control
+ registers, and clears the video screen.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ ULONG MatchKey;
+ LONG SlotNumber = HalpPciMaxSlots - 1;
+ LONG BusNumber = 0;
+ ULONG VideoDeviceSlotNumber = HalpPciMaxSlots + 1; // start with an impossible value
+ ULONG VideoDeviceBusNumber = 0;
+ UCHAR BaseClassCode;
+ UCHAR SubClassCode;
+ ULONG Device_Vendor_Id;
+ ULONG RomBaseAddress;
+ ULONG PCICommand;
+ ULONG AmountRead = 1;
+ ULONG DeleteIoSpace = 0;
+ ULONG VgaBiosShadowOffset = 0xffffffff;
+
+
+ //
+ // For the Weitek P9100, set the address of the font file header.
+ // Display variables are computed later in HalpDisplayPpcP9Setup.
+ //
+ // This is changed as Phase 1 init starts. The font is copied
+ // out of the LoaderBlock and into non-paged pool so that it
+ // can be used again if the machine bluescreens.
+ //
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+
+
+ //
+ // Read the Registry entry to find out which video adapter the system
+ // is configured for. This code depends on the OSLoader to put the
+ // correct value in the Registry.
+ //
+ MatchKey = 0;
+ ConfigurationEntry=KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+
+ //
+ // Determine controller setup routine, display character routine, and PCI device id
+ // via configuration tree
+ //
+
+
+
+ if (ConfigurationEntry != NULL) {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"S3_928")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterS3;
+ HalpDisplayPciDeviceId = S3_928_DEVICE_ID;
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"S3_864")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcS3Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterS3;
+ HalpDisplayPciDeviceId = S3_864_DEVICE_ID;
+
+#if !defined(WOODFIELD)
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"P9100")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcP91Setup;
+ HalpDisplayCharacter = HalpDisplayCharacterP91;
+ HalpDisplayPciDeviceId = P91_DEVICE_ID;
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"GXT150P")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcBBLSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterBBL;
+ HalpDisplayPciDeviceId = BBL_DEVICE_ID;
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"GXT250P")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcBLSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterBL;
+ HalpDisplayPciDeviceId = BL_DEVICE_ID;
+
+#endif
+
+ } else if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,"WD_90C")) {
+ HalpDisplayControllerSetup = HalpDisplayPpcWDSetup;
+ HalpDisplayCharacter = HalpDisplayCharacterS3;
+ HalpDisplayPciDeviceId = WD_90C_DEVICE_ID;
+ }
+
+ } else {
+
+ HalpDisplayControllerSetup = NULL;
+ HalpDisplayCharacter = NULL;
+ HalpDisplayPciDeviceId = UNKNOWN_DEVICE_ID;
+ }
+
+ //
+ // Check to see if BIOS exists for the display controller
+ //
+
+ if (HalpPhase0MapBusConfigSpace() == TRUE) {
+
+ while (BusNumber < (LONG)HalpPciMaxBuses) {
+ SlotNumber = HalpPciMaxSlots - 1;
+
+ while (SlotNumber >= 0) {
+
+ //
+ // Just shut off all the video chips. We will re-enable
+ // the one we want later.
+ //
+ HalpPhase0GetPciDataByOffset(BusNumber,
+ SlotNumber,
+ &BaseClassCode,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ BaseClass),
+ sizeof(BaseClassCode));
+
+ HalpPhase0GetPciDataByOffset(BusNumber,
+ SlotNumber,
+ &SubClassCode,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ SubClass),
+ sizeof(SubClassCode));
+ //
+ // Is this a display adapter?
+ //
+
+ if (((BaseClassCode == PCI_DISPLAY_CONTROLLER) && (SubClassCode == 0)) ||
+ ((BaseClassCode == PCI_PRE_REV_2) && (SubClassCode == 1))) {
+
+ HalpPhase0GetPciDataByOffset (
+ BusNumber,
+ SlotNumber,
+ &PCICommand,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PCICommand)
+ );
+ //
+ // Disble IO and Memory space decoding
+ //
+
+ PCICommand &= (~PCI_ENABLE_IO_SPACE &
+ ~PCI_ENABLE_MEMORY_SPACE &
+ ~PCI_ENABLE_BUS_MASTER);
+
+ HalpPhase0SetPciDataByOffset(BusNumber,
+ SlotNumber,
+ &PCICommand,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ Command),
+ sizeof (PCICommand)
+ );
+ }
+
+ //
+ // If we have already found a video card, skip
+ // the following section
+ //
+ if (VideoDeviceSlotNumber < HalpPciMaxSlots) {
+ SlotNumber--;
+ continue;
+ }
+
+ //
+ // Now test to see if this is the one ARC used. (This algorithm
+ // will identify either the chip with the same ID that ARC used
+ // or, in the case that we don't recognize the ID, the chip in
+ // the highest slot number that is a video device.
+
+ if (HalpDisplayPciDeviceId == UNKNOWN_DEVICE_ID) {
+
+ //
+ // Is this a display adapter?
+ //
+
+ if (((BaseClassCode == PCI_DISPLAY_CONTROLLER) && (SubClassCode == 0)) ||
+ ((BaseClassCode == PCI_PRE_REV_2) && (SubClassCode == 1))) {
+ // This is the one we want to use, so save the slot number
+ VideoDeviceSlotNumber = SlotNumber;
+ VideoDeviceBusNumber = BusNumber;
+ }
+ } else {
+
+ //
+ // Find the pci slot of the display controller
+ //
+
+ HalpPhase0GetPciDataByOffset(BusNumber,
+ SlotNumber,
+ &Device_Vendor_Id,
+ 0,
+ sizeof(Device_Vendor_Id));
+
+
+ //
+ // In the following, when we apply a mask to the
+ // Device_Vendor_Id it's to hide the chip revision.
+ //
+ if ( ((Device_Vendor_Id & 0xFFF0FFFF) == S3_928_DEVICE_ID) ||
+ ((Device_Vendor_Id & 0xFFF0FFFF) == S3_864_DEVICE_ID) ||
+ ((Device_Vendor_Id & 0xFFF0FFFF) == P9_DEVICE_ID) ||
+ ((Device_Vendor_Id & 0xFFF0FFFF) == P91_DEVICE_ID) ||
+ ( Device_Vendor_Id == BBL_DEVICE_ID) ||
+ ( Device_Vendor_Id == BL_DEVICE_ID) ||
+ ( Device_Vendor_Id == WD_90C_DEVICE_ID) ) {
+ VideoDeviceSlotNumber = SlotNumber;
+ VideoDeviceBusNumber = BusNumber;
+ }
+ }
+
+ SlotNumber--;
+
+ }
+ BusNumber++;
+ }
+
+ if (VideoDeviceSlotNumber < HalpPciMaxSlots) {
+ //
+ // Turn the video chip back on
+ //
+ HalpPhase0GetPciDataByOffset(VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &PCICommand,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,
+ Command),
+ sizeof (PCICommand)
+ );
+
+ PCICommand |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+ HalpPhase0SetPciDataByOffset (VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &PCICommand,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PCICommand)
+ );
+
+ //
+ // Determine what ROM base address should be
+ //
+
+ // Writing 0xFFFFFFFE to the register and then reading it tells us what
+ // our bounds are.
+ RomBaseAddress = 0xFFFFFFFE;
+ HalpPhase0SetPciDataByOffset(VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &RomBaseAddress,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.ROMBaseAddress),
+ sizeof(RomBaseAddress));
+ HalpPhase0GetPciDataByOffset(VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &RomBaseAddress,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.ROMBaseAddress),
+ sizeof(RomBaseAddress));
+
+ //
+ // Strip lowest bit, which is for enabling decoders.
+ //
+ RomBaseAddress &= 0xFFFFFFFE;
+
+ //
+ // This sets the least significant bit that we were able to change,
+ // which tells us how much space we need for the BIOS.
+ //
+ RomBaseAddress = ((~RomBaseAddress) + 1) & RomBaseAddress;
+
+ // If this ROM is small enough, put it in the normal VGA ROM position
+ if (RomBaseAddress <= 0x10000) {
+ RomBaseAddress = 0x00c0000;
+ }
+ else {
+ RomBaseAddress = 0;
+ }
+
+
+ RomBaseAddress = RomBaseAddress | 0x00000001; //Switch on ROM decoding
+
+ //
+ // Now write it all back
+ //
+ HalpPhase0SetPciDataByOffset(VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &RomBaseAddress,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.ROMBaseAddress),
+ sizeof(RomBaseAddress));
+
+ //
+ // Now map I/O memory space so we can look at the BIOS
+ //
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(PCI_MEMORY_PHYSICAL_BASE,
+ 0x400000); // 4 MB
+ HalpIoMemoryBase = HalpVideoMemoryBase;
+
+ //
+ // Test to see if there is a BIOS present
+ //
+ if ((*((PUSHORT)HalpIoMemoryBase + (0xc0000 / 2))) == 0xaa55) {
+
+ VgaBiosShadowOffset = 0xc0000;
+
+ } else if ((*((PUSHORT)HalpIoMemoryBase)) == 0xaa55) {
+
+ VgaBiosShadowOffset = 0x0;
+ }
+
+ if (VgaBiosShadowOffset != 0xffffffff) {
+
+ //
+ // Shadow the BIOS
+ //
+ HalpVideoBiosLength = (*((PUCHAR)HalpIoMemoryBase + VgaBiosShadowOffset + 2)) * 512;
+
+ HalpShadowBuffer = &HalpShadowBufferPhase0;
+
+ RtlCopyMemory(HalpShadowBuffer,
+ (PUCHAR)HalpIoMemoryBase + VgaBiosShadowOffset,
+ HalpVideoBiosLength);
+
+ HalpBiosShadowed = TRUE;
+
+
+ //
+ // Try INT10
+ //
+ HalpInitializeX86DisplayAdapter(VideoDeviceBusNumber,
+ VideoDeviceSlotNumber);
+
+ }
+
+ if (HalpEnableInt10Calls == TRUE) {
+ HalpDisplayControllerSetup = HalpDisplaySetupVgaViaBios;
+ HalpDisplayCharacter = HalpDisplayCharacterVgaViaBios;
+
+ } else {
+ KePhase0DeleteIoMap(PCI_MEMORY_PHYSICAL_BASE, 0x400000);
+ HalpVideoMemoryBase = NULL;
+ HalpIoMemoryBase = NULL;
+ }
+
+ //
+ // If the BIOS might be too large to leave mapped into ISA expansion
+ // space, stop decoding the BIOS because we have either shadowed it
+ // or it didn't exist in the first place.
+ //
+ // I would unmap all BIOSes, but the S3 chips seem to stop working if I do. -- Jake
+ if ((RomBaseAddress & 0xFFFFFFFE) == 0) {
+ RomBaseAddress = 0;
+ HalpPhase0SetPciDataByOffset(VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &RomBaseAddress,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.ROMBaseAddress),
+ sizeof(RomBaseAddress));
+ //
+ // Turn the video chip back on because the previous call may have turned it off
+ //
+ HalpPhase0GetPciDataByOffset (VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &PCICommand,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PCICommand)
+ );
+
+ PCICommand |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+ HalpPhase0SetPciDataByOffset (VideoDeviceBusNumber,
+ VideoDeviceSlotNumber,
+ &PCICommand,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PCICommand)
+ );
+ }
+
+ }
+
+ HalpPhase0UnMapBusConfigSpace();
+ }
+
+
+ // Save the display type in a global variable for use in the
+ // HalAcquireDisplayOwnership() function
+
+ strcpy(HalpDisplayIdentifier,
+ ConfigurationEntry->ComponentEntry.Identifier);
+
+
+ //
+ // Initialize the display controller.
+ //
+
+ if (HalpDisplayControllerSetup != NULL) {
+ HalpDisplayControllerSetup();
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpCopyBiosShadow(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine checks to see if there is a BIOS image in
+ HalpShadowBuffer and copies it to a block of non-paged
+ pool. This is done because HalpShadowBuffer will be
+ thrown away at the end of Phase 1. The idea is to
+ avoid wasting non-paged pool when we aren't using a
+ video BIOS.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ASSERT(HalpInitPhase == 1);
+
+ if (HalpBiosShadowed) {
+
+ HalpShadowBuffer = ExAllocatePool(NonPagedPool, HalpVideoBiosLength);
+
+ ASSERT(HalpShadowBuffer);
+
+ RtlCopyMemory((PVOID)HalpShadowBuffer,
+ (PVOID)&HalpShadowBufferPhase0,
+ HalpVideoBiosLength);
+
+ }
+}
+
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if !defined(WOODFIELD)
+
+ if (!strcmp(HalpDisplayIdentifier, "GXT150P")){
+
+ //
+ // Deleting access to the frame buffer here since we are about
+ // to give ownership of the display adapter to the miniport so
+ // we'll never touch the adapter again unless the system panics
+ // at which point we re-initialize anyway
+ //
+
+ // KePhase0DeleteIoMap(BBL_VIDEO_MEMORY_BASE,
+ // BBL_VIDEO_MEMORY_LENGTH);
+ }
+ else if (!strcmp(HalpDisplayIdentifier, "P9100")) {
+
+// HalpP91RelinquishDisplayOwnership();
+ }
+
+#endif
+
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+
+VOID
+HalpDisplaySetupVgaViaBios (
+ VOID
+ )
+/*++
+
+Routine Description:
+ This routine initializes a vga controller via bios reset.
+Arguments:
+ None.
+Return Value:
+ None.
+
+--*/
+{
+//
+// Routine Description:
+//
+//
+
+ ULONG DataLong;
+ PHYSICAL_ADDRESS physicalAddress;
+ XM86_CONTEXT Context ;
+
+
+ if (HalpInitPhase == 0) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(PCI_MEMORY_PHYSICAL_BASE,
+ 0x400000); // 4 MB
+ }
+
+ HalpSetupAndClearScreenVgaViaBios () ;
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 50;
+
+ HalpDisplayOwnedByHal = TRUE;
+
+ return;
+} /* end of HalpDisplaySetupVgaViaBios() */
+
+
+VOID
+HalpDisplayCharacterVgaViaBios (
+ IN UCHAR Character
+ )
+
+/*++
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ ScrollScreenVgaViaBios (1);
+ }
+ } else if( Character == '\t' ) { // tab?
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= HalpDisplayWidth ) { // tab beyond end of screen?
+ HalpColumn = 0; // next tab stop is 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) ) {
+ ScrollScreenVgaViaBios (1) ; // scroll the screen up
+ } else {
+ ++HalpRow;
+ }
+ }
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpPositionCursorVgaViaBios( HalpRow, HalpColumn ) ;
+ HalpDispCharVgaViaBios(0x20);
+ }
+ } else if (Character >= 0x20) {
+ //
+ // Auto wrap for HalpDisplayWidth columns per line
+ //
+ if (HalpColumn >= HalpDisplayWidth) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ ScrollScreenVgaViaBios (1);
+ }
+ }
+ HalpPositionCursorVgaViaBios( HalpRow, HalpColumn ) ;
+ HalpDispCharVgaViaBios (Character) ;
+ HalpColumn++ ;
+ }
+ return;
+}
+
+
+VOID
+HalpPositionCursorVgaViaBios (
+ IN ULONG Row,
+ IN ULONG Column
+ )
+
+/*++
+
+Routine Description:
+
+ This routine positions the cusor at a specified location.
+
+Arguments:
+
+ Row - row position for the cursor
+ Column - column position for the cursor
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XM86_CONTEXT Context ;
+
+ // position the cursor
+ Context.Eax = 0x0200 ;
+ Context.Ebx = 0x0000 ;
+ Context.Edx = (Row << 8) | Column ;
+ if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
+ (HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
+ )
+ {
+ DbgPrint( "HalpPositionCursorVgaViaBios: FAILED\n" ) ;
+ }
+
+ return ;
+
+}
+
+
+
+VOID
+HalpDispCharVgaViaBios (
+ IN UCHAR Character
+ )
+
+/*++
+
+Routine Description:
+
+ This routine prints a charcter at the current cursor positions.
+
+Arguments:
+
+ Character - character to be printed
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XM86_CONTEXT Context ;
+
+ // display the character
+ Context.Eax = 0x0900 | Character ;
+ Context.Ebx = 0x001f ;
+ Context.Ecx = 1 ;
+ if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
+ (HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
+ )
+ {
+ DbgPrint( "HalpDispCharVgaViaBios: Putchar Call Failed\n" ) ;
+ }
+
+ return ;
+}
+
+
+VOID
+ScrollScreenVgaViaBios (
+ IN UCHAR LinesToScroll
+ )
+
+/*++
+
+Routine Description:
+
+ This routine scrolls the screen up by "LinesToScroll" number of lines.
+
+Arguments:
+
+ LinesToScroll - number of lines to scroll up.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XM86_CONTEXT Context ;
+
+ // scroll screen up
+ Context.Eax = 0x0600 | LinesToScroll ;
+ Context.Ebx = 0x1f00 ;
+ Context.Ecx = 0 ;
+ Context.Edx = 0x314f ;
+ if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
+ (HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
+ )
+ {
+ DbgPrint( "ScrollScreenVgaViaBios: Scroll screen up Failed\n" ) ;
+ }
+
+ return;
+}
+
+
+
+
+VOID
+HalpSetupAndClearScreenVgaViaBios ( VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets up the text mode 3, loads ROM double dot set and
+ clears the screen.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ XM86_CONTEXT Context ;
+ ULONG x,y ;
+
+
+ // Switch Adaptor to text mode 3
+ Context.Eax = 0x0003 ;
+ if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
+ (HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
+ )
+ {
+ DbgPrint( "HalpSetupAndClearScreenVgaViaBios: Switch Adaptor to text mode 3 FAILED\n" ) ;
+ }
+
+ // load ROM double dot set
+ Context.Eax = 0x1112 ;
+ Context.Ebx = 0 ;
+ if ( x86BiosExecuteInterruptShadowed (0x10,&Context,HalpIoControlBase,
+ (HalpShadowBuffer - VIDEO_ROM_OFFSET), HalpIoMemoryBase) != XM_SUCCESS
+ )
+ {
+ DbgPrint( "HalpSetupAndClearScreenVgaViaBios: load ROM double dot set FAILED\n" ) ;
+ }
+
+
+
+ for ( x = 0; x < 50 ; x++ )
+ for ( y = 0; y < 80; y++ ) {
+ HalpPositionCursorVgaViaBios (x, y) ;
+ HalpDispCharVgaViaBios ( 0x20 ) ;
+ }
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpPositionCursorVgaViaBios (HalpRow, HalpColumn) ;
+
+ return ;
+}
+
+
+
+VOID
+HalDisplayString (
+ PUCHAR String
+ )
+
+/*++
+
+Routine Description:
+
+ This routine displays a character string on the display screen.
+
+Arguments:
+
+ String - Supplies a pointer to the characters that are to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, flush the TB, and map the display
+ // frame buffer into the address space of the current process.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+#if defined(_MP_PPC_)
+
+ HalpAcquireDisplayLock();
+
+#endif
+
+ //
+ // If ownership of the display has been switched to the system display
+ // driver, then reinitialize the display controller and revert ownership
+ // to the HAL.
+ //
+
+ if (HalpDisplayControllerSetup != NULL) {
+
+ if (HalpDisplayOwnedByHal == FALSE) {
+ HalpDisplayControllerSetup();
+ }
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+ }
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // and lower IRQL to its previous level.
+ //
+
+#if defined(_MP_PPC_)
+
+ HalpReleaseDisplayLock();
+
+#endif
+
+ KeLowerIrql(OldIrql);
+
+ return;
+} /* end of HalpDisplayString() */
+
+
+VOID
+HalQueryDisplayParameters (
+ OUT PULONG WidthInCharacters,
+ OUT PULONG HeightInLines,
+ OUT PULONG CursorColumn,
+ OUT PULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine return information about the display area and current
+ cursor position.
+
+Arguments:
+
+ WidthInCharacter - Supplies a pointer to a varible that receives
+ the width of the display area in characters.
+
+ HeightInLines - Supplies a pointer to a variable that receives the
+ height of the display area in lines.
+
+ CursorColumn - Supplies a pointer to a variable that receives the
+ current display column position.
+
+ CursorRow - Supplies a pointer to a variable that receives the
+ current display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ *WidthInCharacters = HalpDisplayWidth; //IBMLAN
+ *HeightInLines = HalpDisplayText;
+ *CursorColumn = HalpColumn;
+ *CursorRow = HalpRow;
+ return;
+}
+
+
+VOID
+HalSetDisplayParameters (
+ IN ULONG CursorColumn,
+ IN ULONG CursorRow
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set the current cursor position on the display area.
+
+Arguments:
+
+ CursorColumn - Supplies the new display column position.
+
+ CursorRow - Supplies a the new display row position.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set the display parameter values and return.
+ //
+
+ if (CursorColumn > HalpDisplayWidth) { //IBMLAN
+ CursorColumn = HalpDisplayWidth; //IBMLAN
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+
+VOID
+HalpCopyOEMFontFile()
+{
+ PVOID buffer;
+
+ buffer = ExAllocatePool(NonPagedPool,
+ HalpFontHeader->FileSize);
+
+ ASSERT(buffer);
+
+ RtlCopyMemory(buffer,
+ HalpFontHeader,
+ HalpFontHeader->FileSize);
+
+ HalpFontHeader = buffer;
+}
+
+//
+// HalpS3Xxx functions can now be found in pxs3.c
+//
+
+
+
+//
+// The following functions were left here in pxdisp.c
+// because they are used by multiple display modules.
+//
+VOID
+Scroll_Screen(IN UCHAR line)
+{
+UCHAR i, DataByte;
+ULONG target, stop;
+
+ for (i = 0; i < line; i ++) {
+ WaitForVSync(); // wait for vertical sync to make scroll smooth
+
+ target = 0xb8000;
+ stop = target + HalpScrollLength;
+
+ for (; target < stop; target += 2) {
+ DataByte = READ_S3_VRAM(target+HalpScrollLine);
+ WRITE_S3_VRAM(target, DataByte);
+ }
+
+ stop += HalpScrollLine;
+
+ for (; target < stop; target += 2) {
+ WRITE_S3_VRAM(target, 0x20 );
+ }
+
+ }
+}
+
+VOID
+WaitForVSync (VOID)
+{
+ UCHAR DataByte;
+ BOOLEAN test;
+
+ //
+ // Determine 3Dx or 3Bx
+ //
+
+ DataByte = READ_S3_UCHAR(MiscOutR);
+ ColorMonitor = DataByte & 0x01 ? TRUE : FALSE;
+
+ // Unlock S3 ( S3R8 )
+ // UnLockS3();
+
+ //
+ // Test Chip ID = '81h' ?
+ //
+
+ // For standard VGA text mode this action is not necessary.
+ // WRITE_S3_UCHAR(S3_3D4_Index, S3R0);
+ // if ((DataByte = READ_S3_UCHAR(S3_3D5_Data)) == 0x81) {
+ //
+ // Wait For Verttical Retrace
+ //
+
+ test = TRUE;
+ while (test) {
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+
+ test = READ_S3_UCHAR(Stat1_In) & 0x08 ? FALSE : TRUE;
+ }
+
+ // Wait for H/V blanking
+ test = TRUE;
+ while (test) {
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+ READ_S3_UCHAR(Stat1_In);
+
+ test = READ_S3_UCHAR(Stat1_In) & 0x01 ? TRUE : FALSE;
+ }
+ // }
+
+ // Lock S3 ( S3R8 )
+ // LockS3();
+
+ return;
+} /* end of WaitForVsync() */
+
+VOID ScreenOn(VOID)
+{
+ UCHAR DataByte;
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ WRITE_S3_UCHAR(Seq_Index, CLOCKING_MODE);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte = DataByte & 0xdf;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ return;
+}
+
+VOID ScreenOff(VOID)
+{
+ UCHAR DataByte;
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ WRITE_S3_UCHAR(Seq_Index, CLOCKING_MODE);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte = DataByte | 0x20;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ return;
+}
+
+// These functions are commented out because the video adapter they
+// are here to support has no support in NT anymore. I'm not
+// deleting them because we may want to add them back some day. - Jake
+
+// VOID
+// HalpDisplayPpcP9Setup (
+// VOID
+// )
+// /*++
+//
+// Routine Description:
+//
+// This routine initializes the Weitek P9000 display contoller chip.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+// --*/
+// {
+// PULONG buffer;
+// ULONG limit, index;
+// PHYSICAL_ADDRESS physicalAddress;
+//
+// // For now I'll leave the P9000 in the same state that the firmware
+// // left it in. This should be 640x480.
+//
+// HalpHorizontalResolution = 640;
+// HalpVerticalResolution = 480;
+//
+// if (HalpInitPhase == 0) {
+//
+// HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(P9_VIDEO_MEMORY_BASE,
+// 0x400000); // 4 MB
+//
+// } else {
+//
+// //
+// // Map video memory space via pte's
+// //
+//
+// physicalAddress.HighPart = 0;
+// physicalAddress.LowPart = P9_VIDEO_MEMORY_BASE;
+// HalpVideoMemoryBase = MmMapIoSpace(physicalAddress,
+// 0x400000,
+// FALSE);
+//
+// //
+// // IO control space has already been mapped in phase 1 via halpmapiospace
+// //
+//
+// }
+//
+// //IBMLAN Use font file from OS Loader
+// //
+// // Compute display variables using using HalpFontHeader which is
+// // initialized in HalpInitializeDisplay().
+// //
+// // N.B. The font information suppled by the OS Loader is used during phase
+// // 0 initialization. During phase 1 initialization, a pool buffer is
+// // allocated and the font information is copied from the OS Loader
+// // heap into pool.
+// //
+// //FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+// //HalpFontHeader = FontHeader;
+// HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+// HalpCharacterHeight = HalpFontHeader->PixelHeight;
+// HalpCharacterWidth = HalpFontHeader->PixelWidth;
+//
+// //
+// // Compute character output display parameters.
+// //
+//
+// HalpDisplayText =
+// HalpVerticalResolution / HalpCharacterHeight;
+//
+// HalpScrollLine =
+// HalpHorizontalResolution * HalpCharacterHeight;
+//
+// HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+//
+// HalpDisplayWidth =
+// HalpHorizontalResolution / HalpCharacterWidth;
+//
+//
+// //
+// // Set the video memory to address color one.
+// //
+//
+// buffer = (PULONG)HalpVideoMemoryBase;
+// limit = (HalpHorizontalResolution *
+// HalpVerticalResolution) / sizeof(ULONG);
+//
+// for (index = 0; index < limit; index += 1) {
+// *buffer++ = 0x01010101;
+// }
+//
+//
+// //
+// // Initialize the current display column, row, and ownership values.
+// //
+//
+// HalpColumn = 0;
+// HalpRow = 0;
+// HalpDisplayOwnedByHal = TRUE;
+// return;
+//
+// } //end of HalpDisplayPpcP9Setup
+//
+// VOID
+// HalpDisplayCharacterP9 (
+// IN UCHAR Character
+// )
+// /*++
+//
+// Routine Description:
+//
+// This routine displays a character at the current x and y positions in
+// the frame buffer. If a newline is encountered, the frame buffer is
+// scrolled. If characters extend below the end of line, they are not
+// displayed.
+//
+// Arguments:
+//
+// Character - Supplies a character to be displayed.
+//
+// Return Value:
+//
+// None.
+//
+// --*/
+//
+// {
+//
+// PUCHAR Destination;
+// PUCHAR Source;
+// ULONG Index;
+//
+// //
+// // If the character is a newline, then scroll the screen up, blank the
+// // bottom line, and reset the x position.
+// //
+//
+// if (Character == '\n') {
+// HalpColumn = 0;
+// if (HalpRow < (HalpDisplayText - 1)) {
+// HalpRow += 1;
+//
+// } else {
+// //RtlMoveMemory((PVOID)P9_VIDEO_MEMORY_BASE,
+// // (PVOID)(P9_VIDEO_MEMORY_BASE + HalpScrollLineP9),
+// // HalpScrollLengthP9);
+//
+// // Scroll up one line
+// Destination = HalpVideoMemoryBase;
+// Source = (PUCHAR) HalpVideoMemoryBase + HalpScrollLine;
+// for (Index = 0; Index < HalpScrollLength; Index++) {
+// *Destination++ = *Source++;
+// }
+// // Blue the bottom line
+// Destination = HalpVideoMemoryBase + HalpScrollLength;
+// for (Index = 0; Index < HalpScrollLine; Index += 1) {
+// *Destination++ = 1;
+// }
+// }
+//
+// } else if (Character == '\r') {
+// HalpColumn = 0;
+//
+// } else {
+// if ((Character < HalpFontHeader->FirstCharacter) ||
+// (Character > HalpFontHeader->LastCharacter)) {
+// Character = HalpFontHeader->DefaultCharacter;
+// }
+//
+// Character -= HalpFontHeader->FirstCharacter;
+// HalpOutputCharacterP9((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+// }
+//
+// return;
+// }
+//
+// VOID
+// HalpOutputCharacterP9(
+// IN PUCHAR Glyph
+// )
+//
+// /*++
+//
+// Routine Description:
+//
+// This routine insert a set of pixels into the display at the current x
+// cursor position. If the current x cursor position is at the end of the
+// line, then a newline is displayed before the specified character.
+//
+// Arguments:
+//
+// Character - Supplies a character to be displayed.
+//
+// Return Value:
+//
+// None.
+//
+// --*/
+//
+// {
+//
+// PUCHAR Destination;
+// ULONG FontValue;
+// ULONG tmp;
+// ULONG I;
+// ULONG J;
+//
+// //
+// // If the current x cursor position is at the end of the line, then
+// // output a line feed before displaying the character.
+// //
+//
+// if (HalpColumn == HalpDisplayWidth) {
+// HalpDisplayCharacterP9('\n');
+// }
+//
+// //
+// // Output the specified character and update the x cursor position.
+// //
+//
+// Destination = (PUCHAR)(HalpVideoMemoryBase +
+// (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+//
+// for (I = 0; I < HalpCharacterHeight; I += 1) {
+// FontValue = 0;
+// for (J = 0; J < HalpBytesPerRow; J += 1) {
+// FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+// }
+// // Move the font bits around so the characters look right.
+// tmp = (FontValue >> 3) & 0x11111111; //bits 7 and 3 to the right 3
+// tmp |= (FontValue >> 1) & 0x22222222; //bits 6 and 2 to the right 1
+// tmp |= (FontValue << 1) & 0x44444444; //bits 5 and 1 to the left 1
+// tmp |= (FontValue << 3) & 0x88888888; //bits 4 and 0 to the left 3
+// FontValue = tmp;
+//
+// Glyph += 1;
+// for (J = 0; J < HalpCharacterWidth ; J += 1) {
+// if (FontValue >> 31 != 0)
+// *Destination = 0xFF; //Make this pixel white
+//
+// Destination++;
+// //*Destination++ = (FontValue >> 31) ^ 1;
+// FontValue <<= 1;
+// }
+//
+// Destination +=
+// (HalpHorizontalResolution - HalpCharacterWidth);
+// }
+//
+// HalpColumn += 1;
+// return;
+// }
+
+//
+// HalpP91Xxx functions can now be found in pxp91.c
+//
+
+
+//
+// HalpBBLXxx functions can now be found in pxbbl.c
+//
+
diff --git a/private/ntos/nthals/halppc/ppc/pxdisp.h b/private/ntos/nthals/halppc/ppc/pxdisp.h
new file mode 100644
index 000000000..ac638fad9
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxdisp.h
@@ -0,0 +1,360 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+
+Module Name:
+
+pxdisp.c
+
+Abstract:
+
+ These are common datastructures used by video systems in the
+ HAL.
+
+Author:
+
+ Jake Oshins
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+//
+// VGA palette tables used by S3 and WD functions
+UCHAR DAC_Table[64] = {
+ // DAC for mode 3
+ 0,16, 4,20, 1,17, 5,21,
+ 32,48,36,52,33,49,37,53,
+ 8,24,12,28, 9,25,13,29,
+ 40,56,44,60,41,57,45,61,
+ 2,18, 6,22, 3,19, 7,23,
+ 34,50,38,54,35,51,39,55,
+ 10,26,14,30,11,27,15,31,
+ 42,58,46,62,43,59,47,63
+ };
+
+UCHAR DAC_Color[4] = {0x00, 0x2a, 0x15, 0x3f};
+
+//
+// CRT Controller Registers for 800 x 600 @ 60 Hz (text mode on Woodfield Prime)
+// NOTE: this is for a text mode
+//
+UCHAR CRTC_800x600x60_Text[] =
+ {
+ 0x7f,0x63,0x64,0x82,0x6d,0x1b,0x72,0xf0,0x00,0x6f,0x0,0x0,0x0,0x0,0x0,0x0,
+ 0x58,0x2c,0x57,0x32,0x00,0x58,0x71,0xa3,0xff,
+ };
+
+UCHAR CRTC_640x480x60_Text[] =
+ {
+ 0x5f,0x4f,0x50,0x82,0x53,0x9f,0x0b,0x3e,0x00,0x4f,0x0d,0x0e,0x00,
+ 0x00,0x00,0x00,0xea,0x2c,0xdf,0x28,0x1f,0xe7,0x04,0xa3,0xff,
+ };
+
+UCHAR VideoParam[62] = {
+// Mode +3 480 Lines
+// External Registers 3C3, 3C2
+0x01,0x67,
+
+//=============================================================================
+//
+// IBMBJB changed value at offset 17 (5th number on second line) from 0x8e
+// to 0xae to disable the vertical retrace interrupt
+
+// CRT Controller Registers 3D4, 3D5
+0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,
+// 0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff,
+ 0x00,0x00,0x00,0x9c,0xae,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff,
+
+//=============================================================================
+
+// Sequencer Registers 3C4, 3C5
+// 0x01,0x01,0x03,0x00,0x02,
+0x01,0x20,0x03,0x00,0x02,
+
+// Graphic Control Registers
+0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x00,0xff,
+
+// Attribute Controller Registers
+0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,
+0x3b,0x3c,0x3d,0x3e,0x3f,0x0c,0x00,0x0f,0x08,0x00};
+
+
+UCHAR VGAFont8x16[4096] = {
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 00
+0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x7E,0xFF,0xFF,0xDB,0xFF,0xFF,0xC3,0xE7,0xFF,0x7E,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // 8
+0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00, // 9
+0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF, // a
+0x00,0x00,0x3E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x30,0x38,0x3C,0x36,0x33,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00, // f
+
+0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00, // 10
+0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00, // 4
+0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 20
+0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // 1
+0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00, // 3
+0x00,0x18,0x18,0x7C,0xC6,0xC2,0x7C,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30,0x60,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, // 30
+0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x60,0x00,0x00, // b
+0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00, // 40
+0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0xC6,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 50
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00, // 1
+0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00, // d
+0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00, // f
+
+0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 60
+0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x3E,0x66,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00, // 7
+0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00, // a
+0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0xD6,0xD6,0xD6,0xC6,0xC6,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00, // 70
+0x00,0x00,0x00,0x00,0x00,0x7E,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00, // 1
+0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00, // 80
+0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 1
+0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 4
+0x00,0x60,0x30,0x18,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 5
+0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00, // 7
+0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // 9
+0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // c
+0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // d
+0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // e
+0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // f
+
+0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00, // 90
+0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00, // 2
+0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 4
+0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 5
+0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 6
+0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00, // 8
+0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 9
+0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // a
+0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00, // b
+0x00,0x38,0x6C,0x64,0x60,0xF8,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // d
+0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00, // e
+0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00, // f
+
+0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // a0
+0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00, // 1
+0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 2
+0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, // 4
+0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // 5
+0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 6
+0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00, // b
+0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00, // c
+0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, // b0
+0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA, // 1
+0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77, // 2
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 3
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 4
+0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 6
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 8
+0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 9
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // a
+0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // b
+0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // f
+
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c0
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 2
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 3
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 6
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 9
+0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // b
+0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // c
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // e
+0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d0
+0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 1
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 2
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 3
+0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 5
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 6
+0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, // 7
+0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 8
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // a
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // b
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, // c
+0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0, // d
+0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F, // e
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00, // e0
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xFC,0xC6,0xC6,0xC6,0xC6,0xDC,0xC0,0xC0,0x00,0x00, // 1
+0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00, // 3
+0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00, // 4
+0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0xC0,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, // 7
+0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00, // a
+0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00, // b
+0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00, // f
+
+0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00, // f0
+0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00, // 1
+0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00, // 2
+0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00, // 3
+0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 4
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00, // 5
+0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, // 6
+0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00, // 7
+0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 8
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 9
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // a
+0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00, // b
+0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // c
+0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // d
+0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,0x00,0x00,0x00,0x00,0x00, // e
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 // f
+ };
+
diff --git a/private/ntos/nthals/halppc/ppc/pxds1585.h b/private/ntos/nthals/halppc/ppc/pxds1585.h
new file mode 100644
index 000000000..cee3e7fd5
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxds1585.h
@@ -0,0 +1,106 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxds1585.h
+
+Abstract:
+
+ The module defines the structures, and defines for the DALLAS rtc chip.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+
+
+
+typedef struct _RTC_CONTROL {
+ UCHAR Reserved0[0x71];
+ UCHAR RtcData; // Offset 0x71
+} RTC_CONTROL, *PRTC_CONTROL;
+
+typedef struct _NVRAM_CONTROL {
+ UCHAR Reserved0[0x74];
+ UCHAR NvramIndexLo; // Offset 0x74
+ UCHAR NvramIndexHi; // Offset 0x75
+ UCHAR Reserved2[1];
+ UCHAR NvramData; // Offset 0x77
+} NVRAM_CONTROL, *PNVRAM_CONTROL;
+
+
+//
+// Define Realtime Clock register numbers.
+//
+
+#define RTC_SECOND 0 // second of minute [0..59]
+#define RTC_SECOND_ALARM 1 // seconds to alarm
+#define RTC_MINUTE 2 // minute of hour [0..59]
+#define RTC_MINUTE_ALARM 3 // minutes to alarm
+#define RTC_HOUR 4 // hour of day [0..23]
+#define RTC_HOUR_ALARM 5 // hours to alarm
+#define RTC_DAY_OF_WEEK 6 // day of week [1..7]
+#define RTC_DAY_OF_MONTH 7 // day of month [1..31]
+#define RTC_MONTH 8 // month of year [1..12]
+#define RTC_YEAR 9 // year [00..99]
+#define RTC_CONTROL_REGISTERA 10 // control register A
+#define RTC_CONTROL_REGISTERB 11 // control register B
+#define RTC_CONTROL_REGISTERC 12 // control register C
+#define RTC_CONTROL_REGISTERD 13 // control register D
+#define RTC_BATTERY_BACKED_UP_RAM 14 // battery backed up RAM [0..49]
+
+//
+// Define Control Register A structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_A {
+ UCHAR RateSelect : 4;
+ UCHAR TimebaseDivisor : 3;
+ UCHAR UpdateInProgress : 1;
+} RTC_CONTROL_REGISTER_A, *PRTC_CONTROL_REGISTER_A;
+
+//
+// Define Control Register B structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_B {
+ UCHAR DayLightSavingsEnable : 1;
+ UCHAR HoursFormat : 1;
+ UCHAR DataMode : 1;
+ UCHAR SquareWaveEnable : 1;
+ UCHAR UpdateInterruptEnable : 1;
+ UCHAR AlarmInterruptEnable : 1;
+ UCHAR TimerInterruptEnable : 1;
+ UCHAR SetTime : 1;
+} RTC_CONTROL_REGISTER_B, *PRTC_CONTROL_REGISTER_B;
+
+//
+// Define Control Register C structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_C {
+ UCHAR Fill : 4;
+ UCHAR UpdateInterruptFlag : 1;
+ UCHAR AlarmInterruptFlag : 1;
+ UCHAR TimeInterruptFlag : 1;
+ UCHAR InterruptRequest : 1;
+} RTC_CONTROL_REGISTER_C, *PRTC_CONTROL_REGISTER_C;
+
+//
+// Define Control Register D structure.
+//
+
+typedef struct _RTC_CONTROL_REGISTER_D {
+ UCHAR Fill : 7;
+ UCHAR ValidTime : 1;
+} RTC_CONTROL_REGISTER_D, *PRTC_CONTROL_REGISTER_D;
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxenviro.c b/private/ntos/nthals/halppc/ppc/pxenviro.c
new file mode 100644
index 000000000..92a3f2aa2
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxenviro.c
@@ -0,0 +1,170 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ pxenviro.c
+
+Abstract:
+
+ This module implements the interface to the HAL get and set
+ environment variable routines for a Power PC system.
+
+
+Author:
+
+ Jim Wooldridge Ported to PowerPC
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+#include "arccodes.h"
+
+#include "prepnvr.h"
+#include "fwstatus.h"
+#include "fwnvr.h"
+
+
+
+KSPIN_LOCK NVRAM_Spinlock;
+
+
+
+ARC_STATUS
+HalGetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN USHORT Length,
+ OUT PCHAR Buffer
+ )
+
+/*++
+
+Routine Description:
+
+ This function locates an environment variable and returns its value.
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated environment variable
+ name.
+
+ Length - Supplies the length of the value buffer in bytes.
+
+ Buffer - Supplies a pointer to a buffer that receives the variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the enviroment variable is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+
+{
+
+KIRQL Irql;
+PUCHAR tmpbuffer;
+
+
+ //
+ // Check input parameters
+ //
+ if (Variable == NULL ||
+ *Variable == 0 ||
+ Length < 1 ||
+ Buffer == NULL)
+ return(ENOENT);
+
+ //
+ // Grab control of NVRAM
+ //
+
+ KeAcquireSpinLock(&NVRAM_Spinlock, &Irql);
+
+ (VOID)nvr_initialize_object(0, 0);
+
+ if ((tmpbuffer = nvr_get_GE_variable(Variable)) == NULL) {
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+ return(ENOENT);
+ }
+
+ //
+ // Copy the environment variable's value to Buffer
+ //
+
+ do {
+ *Buffer = *tmpbuffer++;
+ if (*Buffer++ == 0) {
+
+ nvr_delete_object();
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+ return(ESUCCESS);
+ }
+ } while (--Length);
+
+ //
+ // Truncate the returned string. The buffer was too short.
+ //
+ *--Buffer = 0;
+
+ nvr_delete_object();
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+ return(ENOMEM);
+}
+
+ARC_STATUS
+HalSetEnvironmentVariable (
+ IN PCHAR Variable,
+ IN PCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This function creates an environment variable with the specified value.
+
+Arguments:
+
+ Variable - Supplies a pointer to an environment variable name.
+
+ Value - Supplies a pointer to the environment variable value.
+
+Return Value:
+
+ ESUCCESS is returned if the environment variable is created. Otherwise,
+ ENOMEM is returned.
+
+--*/
+
+
+{
+ ARC_STATUS ReturnValue;
+ KIRQL Irql;
+
+
+
+ if (Value == NULL) return(ENOENT);
+
+ KeAcquireSpinLock(&NVRAM_Spinlock, &Irql); // Grab control of NVRAM
+
+ (VOID)nvr_initialize_object(0, 0);
+// (VOID)nvr_initialize_object(nvr_system_type);
+
+ ReturnValue = nvr_set_GE_variable(Variable,Value);
+
+ nvr_delete_object(); // free object created by nvr_init_object
+
+ KeReleaseSpinLock(&NVRAM_Spinlock, Irql);
+
+ return(ReturnValue);
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxfirsup.c b/private/ntos/nthals/halppc/ppc/pxfirsup.c
new file mode 100644
index 000000000..4bc0014f8
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxfirsup.c
@@ -0,0 +1,1606 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxfirsup.c
+
+Abstract:
+
+ The module provides the support for the fire coral PCI-ISA bridge.
+
+Author:
+
+ Jim Wooldridge (jimw@vnet.ibm.com)
+
+
+Revision History:
+
+ Peter L Johnston (plj@vnet.ibm.com) Support Doral. Aug 95.
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "pxfirsup.h"
+#include <pxmemctl.h>
+#include "bugcodes.h"
+#include "pxmp.h"
+#include "ibmppc.h"
+
+BOOLEAN
+HalpHandleIpi(
+ IN PVOID Unused0,
+ IN PVOID Unused1,
+ IN PVOID TrapFrame
+ );
+
+#define SioId 0x04828086
+
+PVOID HalpPciIsaBridgeConfigBase;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+extern ULONG HalpPciMaxSlots;
+extern ULONG HalpPhase0GetPciDataByOffset();
+extern ULONG HalpPhase0SetPciDataByOffset();
+
+//
+// Declare the interupt structure for profile interrupt
+//
+
+KINTERRUPT HalpProfileInterrupt;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+//
+// Declare the interupt structure for machine checks
+//
+
+KINTERRUPT HalpMachineCheckInterrupt;
+
+//
+// Declare the interupt structure for the clock interrupt
+//
+
+KINTERRUPT HalpDecrementerInterrupt;
+
+
+//
+// Add spurious and bogus interrupt counts
+//
+
+#if DBG
+ULONG HalpSpuriousInterruptCount = 0;
+ULONG HalpBogusInterruptCount = 0;
+#endif
+
+//
+// The following function is called when a machine check occurs.
+//
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEnableMpicInterrupt(
+ IN ULONG Vector
+ );
+
+//
+// Define save area for ISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpIsaAdapter[8];
+
+//
+// Define save area for ISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+UCHAR HalpSioInterrupt1Mask = 0xff;
+UCHAR HalpSioInterrupt2Mask = 0xff;
+UCHAR HalpSioInterrupt1Level;
+UCHAR HalpSioInterrupt2Level;
+
+
+
+BOOLEAN
+HalpCreateSioStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for SIO operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ SIO interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+
+
+ //
+ // Initialize the Machine Check interrupt handler
+ //
+
+ if (HalpEnableInterruptHandler(&HalpMachineCheckInterrupt,
+ HalpHandleMachineCheck,
+ NULL,
+ NULL,
+ MACHINE_CHECK_VECTOR,
+ MACHINE_CHECK_LEVEL,
+ MACHINE_CHECK_LEVEL,
+ Latched,
+ FALSE,
+ 0,
+ FALSE,
+ InternalUsage,
+ MACHINE_CHECK_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ //
+ // Enable NMI IOCHK# and PCI SERR#
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus,
+ DataByte & ~DISABLE_IOCHK_NMI & ~DISABLE_PCI_SERR_NMI);
+
+ //
+ // Clear the SIO NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ DataByte
+ );
+
+ //
+ // Connect the external interrupt handler
+ //
+
+ PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleExternalInterrupt;
+
+ //
+ // register the interrupt vector
+ //
+
+ HalpRegisterVector(InternalUsage,
+ EXTERNAL_INTERRUPT_VECTOR,
+ EXTERNAL_INTERRUPT_VECTOR,
+ HIGH_LEVEL);
+
+
+
+
+ // Connect directly to the decrementer handler. This is done
+ // directly rather than thru HalpEnableInterruptHandler due to
+ // special handling required because the handler calls KdPollBreakIn().
+ //
+
+ PCR->InterruptRoutine[DECREMENT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleDecrementerInterrupt;
+#if defined(_MP_PPC_)
+
+ //
+ // Connect the Inter-Processor Interrupt (IPI) handler.
+ //
+
+ PCR->InterruptRoutine[MPIC_IPI0_VECTOR + DEVICE_VECTORS] =
+ (PKINTERRUPT_ROUTINE)HalpHandleIpi;
+
+#endif // _MP_PPC_
+
+ //
+ // Initialize and connect the Timer 1 interrupt (IRQ0)
+ //
+
+ if (HalpEnableInterruptHandler( &HalpProfileInterrupt,
+ (PKSERVICE_ROUTINE) HalpHandleProfileInterrupt,
+ (PVOID) NULL,
+ (PKSPIN_LOCK)NULL,
+ PROFILE_VECTOR,
+ PROFILE_LEVEL,
+ PROFILE_LEVEL,
+ Latched,
+ TRUE,
+ 0,
+ FALSE,
+ DeviceUsage,
+ PROFILE_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+
+ //
+ // Disable Timer 1; only used by profiling
+ //
+
+ HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
+
+ //
+ // Set default profile rate
+ //
+
+ HalSetProfileInterval(5000);
+
+
+ //
+ // Raise the IRQL while the SIO interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(CLOCK2_LEVEL, &oldIrql);
+
+
+
+ //
+ // Initialize any planar registers
+ //
+
+ HalpInitPlanar();
+
+ //
+ // Initialize the PCI/ISA bridge chip
+ //
+
+ HalpInitPciIsaBridge();
+
+
+
+ //
+ // Initialize the SIO interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a number.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpSioInterrupt1Mask = (UCHAR) ~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ HalpSioInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpSioInterrupt1Level = 0;
+ HalpSioInterrupt2Level = 0;
+
+ //
+ // Enable the clock interrupt
+ //
+
+ HalpUpdateDecrementer(1000); // Get those decrementer ticks going
+
+ //
+ // It is now safe to allow 8259 interrupts thru the MPIC.
+ //
+
+ HalpEnableMpicInterrupt(MPIC_8259_VECTOR + DEVICE_VECTORS);
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // DMA command - set assert level
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus,
+ DataByte & ~DACK_ASSERT_HIGH & ~DREQ_ASSERT_LOW);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+
+BOOLEAN
+HalpInitPciIsaBridge (
+ VOID
+ )
+
+
+{
+
+ UCHAR DataByte;
+ BOOLEAN Found;
+ ULONG SlotNumber;
+ ULONG ChipId;
+ ULONG BufferLength;
+
+
+ Found = FALSE;
+ SlotNumber = 0;
+
+ while (!Found && SlotNumber < HalpPciMaxSlots) {
+
+ BufferLength = HalpPhase0GetPciDataByOffset(0,
+ SlotNumber,
+ &ChipId,
+ 0,
+ sizeof(ChipId));
+ if (ChipId == SioId)
+ Found = TRUE;
+ else
+ SlotNumber++;
+
+
+ }
+
+ //
+ // Make sure that we found a valid chip id
+ //
+
+ if (!Found)
+ return FALSE;
+
+ //
+ // Define macros for reading and writing to the SIO config space
+ //
+
+#define READ_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalpPhase0GetPciDataByOffset( \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+#define WRITE_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalpPhase0SetPciDataByOffset( \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+
+
+ //
+ // Enable ISA Master line buffering
+ //
+
+
+
+ READ_SIO_CONFIG_UCHAR(PciControl,DataByte);
+
+ DataByte |= ENABLE_PCI_POSTED_WRITE_BUFFER
+ | ENABLE_ISA_MASTER_LINE_BUFFER
+ | EANBLE_DMA_LINE_BUFFER;
+
+ WRITE_SIO_CONFIG_UCHAR(PciControl, DataByte );
+
+ //
+ // Disable Gauranteed Access Time Mode
+ //
+
+ READ_SIO_CONFIG_UCHAR(PciArbiterControl,DataByte);
+
+ DataByte &= ~ENABLE_GAT;
+
+ WRITE_SIO_CONFIG_UCHAR(PciArbiterControl, DataByte);
+
+
+
+
+ //
+ // Initialize SuperIO chip
+ //
+
+ if (!HalpInitSuperIo())
+
+ return FALSE;
+
+
+ //
+ // Utility Bus A chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableA,DataByte);
+
+ DataByte |= ENABLE_RTC | ENABLE_KEYBOARD & ~ENABLE_IDE_DECODE;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableA, DataByte);
+
+ //
+ // Utility Bus B chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableB,DataByte);
+
+ DataByte |= ENABLE_RAM_DECODE | ENABLE_PORT92 | DISABLE_PARALLEL_PORT
+ | DISABLE_SERIAL_PORTA | DISABLE_SERIAL_PORTB;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableB, DataByte);
+
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpMapIoControlSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL SIO control space for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map SIO control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = IO_CONTROL_PHYSICAL_BASE;
+ HalpIoControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+
+ if (HalpIoControlBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+/*++
+
+Routine Description:
+
+ This function programs the SIO DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ KIRQL Irql;
+
+
+ ASSERT(Offset >= IO_CONTROL_PHYSICAL_BASE);
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ BytePtr = (PUCHAR) &Offset;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ Length >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = BytePtr[2];
+ Offset >>= 1;
+ BytePtr[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+}
+
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an ISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+ NumberofMapRegisters - number of map registers required for the adapter
+ object created
+
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG numberOfMapRegisters;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+
+ // Work around heinous Victory hardware bug:
+ if ((HalpSystemType == IBM_VICTORY) &&
+ (DeviceDescriptor->InterfaceType == Isa) &&
+ (DeviceDescriptor->Master)) {
+
+ return(NULL);
+ }
+
+
+ //
+ // Determine if the the channel number is important. Master cards
+ // do not use a channel number.
+ //
+
+
+ if ((DeviceDescriptor->Master) && (DeviceDescriptor->InterfaceType != Isa)) {
+
+ useChannel = FALSE;
+
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather &&
+ !(DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->Master)) {
+
+
+ //
+ // Scatter gather not supported in SIO
+ //
+
+ if (!DeviceDescriptor->Master)
+
+ //
+ // one map register will be required when the the SIO supports this
+ //
+ // numberOfMapRegisters = 1;
+
+ return NULL;
+
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // If the device is not a master then it only needs one map register
+ // and does scatter/Gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpIsaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpIsaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpIsaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The speicified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER ) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+
+ }
+
+
+ if (DeviceDescriptor->Master && (DeviceDescriptor->InterfaceType == Isa)) {
+
+ adapterObject->IsaBusMaster = TRUE;
+
+ } else {
+
+ adapterObject->IsaBusMaster = FALSE;
+
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR) channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ //
+ // bit 2 in the extended mode register must be set to 1 for ISA busmastering to work
+ // correctly on Firecoral
+ //
+
+ if (DeviceDescriptor->Master) {
+ extendedMode.TransferSize |= 1;
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // DMA high page must be set to 0x80 for ISA bus masters to work on
+ // FireCoral.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)adapterObject->PagePort,
+ 0x80
+ );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // DMA high page must be set to 0x80 for ISA bus masters to work on
+ // FireCoral.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)adapterObject->PagePort,
+ 0x80
+ );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+
+
+ return(count);
+}
+
+
+VOID
+HalpHandleIoError (
+ VOID
+ )
+
+{
+
+ UCHAR StatusByte;
+
+
+ //
+ // Read NMI status
+ //
+
+ StatusByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiStatus);
+
+ //
+ // Test for PCI bus error
+ //
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: IOCHK\n");
+ }
+
+ //
+ // Test for ISA IOCHK
+ //
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: PCI System Error\n");
+ }
+
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxfirsup.h b/private/ntos/nthals/halppc/ppc/pxfirsup.h
new file mode 100644
index 000000000..2b91be331
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxfirsup.h
@@ -0,0 +1,219 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxsiosup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the SIO chip set.
+ The SIO_CONTROL structure is a superset of the EISA_CONTROL stucture.
+ Differences from the Eisa control stucture are marked with comments.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+#ifndef _SIO_
+#define _SIO_
+
+
+
+
+
+BOOLEAN
+HalpInitSMCSuperIo (
+ VOID
+ );
+
+BOOLEAN
+HalpInitNationalSuperIo (
+ VOID
+ );
+
+typedef struct _SIO_CONTROL {
+ DMA1_CONTROL Dma1BasePort; // Offset 0x000
+ UCHAR Reserved0[16];
+ UCHAR Interrupt1ControlPort0; // Offset 0x020
+ UCHAR Interrupt1ControlPort1; // Offset 0x021
+ UCHAR Reserved1[32 - 2];
+ UCHAR Timer1; // Offset 0x40
+ UCHAR RefreshRequest; // Offset 0x41
+ UCHAR SpeakerTone; // Offset 0x42
+ UCHAR CommandMode1; // Offset 0x43
+ UCHAR Reserved14[28];
+ UCHAR ResetUbus; // Offset 0x60
+ UCHAR NmiStatus; // Offset 0x61
+ UCHAR Reserved15[14];
+ UCHAR NmiEnable; // Offset 0x70
+ UCHAR Reserved16[7];
+ UCHAR BiosTimer[4]; // Offset 0x78
+ UCHAR Reserved13[4];
+ DMA_PAGE DmaPageLowPort; // Offset 0x080
+ UCHAR Reserved2;
+ UCHAR AlternateReset; // Offset 0x092
+ UCHAR Reserved17[14];
+ UCHAR Interrupt2ControlPort0; // Offset 0x0a0
+ UCHAR Interrupt2ControlPort1; // Offset 0x0a1
+ UCHAR Reserved3[32-2];
+ DMA2_CONTROL Dma2BasePort; // Offset 0x0c0
+ UCHAR CoprocessorError; // Offset 0x0f0
+ UCHAR Reserved4[0x281];
+ UCHAR SecondaryFloppyOutput; // Offset 0x372
+ UCHAR Reserved18[0x27];
+ UCHAR Reserved21[0x59];
+ UCHAR PrimaryFloppyOutput; // Offset 0x3f2
+ UCHAR Reserved5[19];
+ UCHAR Dma1ExtendedModePort; // Offset 0x40b
+ UCHAR Reserved6[4];
+ UCHAR Channel0ScatterGatherCommand; // Offset 0x410
+ UCHAR Channel1ScatterGatherCommand; // Offset 0x411
+ UCHAR Channel2ScatterGatherCommand; // Offset 0x412
+ UCHAR Channel3ScatterGatherCommand; // Offset 0x413
+ UCHAR Reserved19; // Offset 0x414
+ UCHAR Channel5ScatterGatherCommand; // Offset 0x415
+ UCHAR Channel6ScatterGatherCommand; // Offset 0x416
+ UCHAR Channel7ScatterGatherCommand; // Offset 0x417
+ UCHAR Channel0ScatterGatherStatus; // Offset 0x418
+ UCHAR Channel1ScatterGatherStatus; // Offset 0x419
+ UCHAR Channel2ScatterGatherStatus; // Offset 0x41a
+ UCHAR Channel3ScatterGatherStatus; // Offset 0x41b
+ UCHAR Reserved20; // Offset 0x41c
+ UCHAR Channel5ScatterGatherStatus; // Offset 0x41d
+ UCHAR Channel6ScatterGatherStatus; // Offset 0x41e
+ UCHAR Channel7ScatterGatherStatus; // Offset 0x41f
+ UCHAR Channel0ScatterGatherTable[4]; // Offset 0x420
+ UCHAR Channel1ScatterGatherTable[4]; // Offset 0x424
+ UCHAR Channel2ScatterGatherTable[4]; // Offset 0x428
+ UCHAR Channel3ScatterGatherTable[4]; // Offset 0x42c
+ UCHAR Reserved22[4]; // Offset 0x430
+ UCHAR Channel5ScatterGatherTable[4]; // Offset 0x434
+ UCHAR Channel6ScatterGatherTable[4]; // Offset 0x438
+ UCHAR Channel7ScatterGatherTable[4]; // Offset 0x43c
+ UCHAR Reserved8[0x40];
+ DMA_PAGE DmaPageHighPort; // Offset 0x480
+ UCHAR Reserved10[70];
+ UCHAR Dma2ExtendedModePort; // Offset 0x4d6
+} SIO_CONTROL, *PSIO_CONTROL;
+
+
+
+typedef struct _SIO_CONFIG {
+ UCHAR VendorId[2]; // Offset 0x00 read-only
+ UCHAR DeviceId[2]; // Offset 0x02 read-only
+ UCHAR Command[2]; // Offset 0x04 unused
+ UCHAR DeviceStatus[2]; // Offset 0x06
+ UCHAR RevisionId; // Offset 0x08 read-only
+ UCHAR Reserved1[0x37]; // Offset 0x09
+ UCHAR PciControl; // Offset 0x40
+ UCHAR PciArbiterControl; // Offset 0x41
+ UCHAR PciArbiterPriorityControl; // Offset 0x42
+ UCHAR Reserved2; // Offset 0x43
+ UCHAR MemCsControl; // Offset 0x44
+ UCHAR MemCsBottomOfHole; // Offset 0x45
+ UCHAR MemCsTopOfHole; // Offset 0x46
+ UCHAR MemCsTopOfMemory; // Offset 0x47
+ UCHAR IsaAddressDecoderControl; // Offset 0x48
+ UCHAR IsaAddressDecoderRomEnable; // Offset 0x49
+ UCHAR IsaAddressDecoderBottomOfHole; // Offset 0x4a
+ UCHAR IsaAddressDecoderTopOfHole; // Offset 0x4b
+ UCHAR IsaControllerRecoveryTimer; // Offset 0x4c
+ UCHAR IsaClockDivisor; // Offset 0x4d
+ UCHAR UtilityBusEnableA; // Offset 0x4e
+ UCHAR UtilityBusEnableB; // Offset 0x4f
+ UCHAR Reserved3[4]; // Offset 0x50
+ UCHAR MemCsAttribute1; // Offset 0x54
+ UCHAR MemCsAttribute2; // Offset 0x55
+ UCHAR MemCsAttribute3; // Offset 0x56
+ UCHAR ScatterGatherBaseAddress; // Offset 0x57
+ UCHAR Reserved4[0x28]; // Offset 0x58
+ UCHAR BiosTimerBaseAddress[2]; // Offset 0x80
+}SIO_CONFIG, *PSIO_CONFIG;
+
+
+//
+// Define constants used by SIO config
+//
+
+
+// PCI control register - bit values
+#define ENABLE_PCI_POSTED_WRITE_BUFFER 0x04
+#define ENABLE_ISA_MASTER_LINE_BUFFER 0x02
+#define EANBLE_DMA_LINE_BUFFER 0x01
+
+// PCI Arbiter contol register - bit values
+#define ENABLE_GAT 0x01
+
+
+// ISA CLock Divisor register - bit values
+#define ENABLE_COPROCESSOR_ERROR 0x20
+#define ENABLE_MOUSE_SUPPORT 0x10
+#define RSTDRV 0x08
+#define SYSCLK_DIVISOR 0x00
+
+//Utility Bus Chip Select A - bit values
+#define ENABLE_RTC 0x01
+#define ENABLE_KEYBOARD 0x02
+#define ENABLE_IDE_DECODE 0x10
+
+//Utility Bus Chip Select B - bit values
+#define ENABLE_RAM_DECODE 0x80
+#define ENABLE_PORT92 0x40
+#define DISABLE_PARALLEL_PORT 0x30
+#define DISABLE_SERIAL_PORTB 0x0c
+#define DISABLE_SERIAL_PORTA 0x03
+
+// Interrupt controller - bit values
+#define LEVEL_TRIGGERED 0x08
+#define SINGLE_MODE 0x02
+
+// NMI status/control - bit values
+#define DISABLE_IOCHK_NMI 0x08
+#define DISABLE_PCI_SERR_NMI 0x04
+
+// NMI enable - bit values
+#define DISABLE_NMI 0x80
+
+// DMA command - bit values
+#define DACK_ASSERT_HIGH 0x80
+#define DREQ_ASSERT_LOW 0x40
+#endif
+
+//
+// Define 8259 constants
+//
+
+#define SPURIOUS_VECTOR 7
+
+//
+// Define 8254 timer constants
+//
+
+//
+// Convert the interval to rollover count for 8254 Timer1 device.
+// Since timer1 counts down a 16 bit value at a rate of 1.193M counts-per-
+// sec, the computation is:
+// RolloverCount = (Interval * 0.0000001) * (1.193 * 1000000)
+// = Interval * 0.1193
+// = Interval * 1193 / 10000
+//
+//
+// The default Interrupt interval is Interval = 15ms.
+
+
+#define TIME_INCREMENT 150000 // 15ms.
+#define ROLLOVER_COUNT 15 * 1193
+
+#define COMMAND_8254_COUNTER0 0x00 // Select count 0
+#define COMMAND_8254_RW_16BIT 0x30 // Read/Write LSB firt then MSB
+#define COMMAND_8254_MODE2 0x4 // Use mode 2
+#define COMMAND_8254_BCD 0x0 // Binary count down
+#define COMMAND_8254_LATCH_READ 0x0 // Latch read command
diff --git a/private/ntos/nthals/halppc/ppc/pxflshbf.s b/private/ntos/nthals/halppc/ppc/pxflshbf.s
new file mode 100644
index 000000000..7e9d429e2
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxflshbf.s
@@ -0,0 +1,121 @@
+#if defined(_PPC_)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxflshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a Power PC
+// system.
+//
+//
+//
+// Author:
+//
+// David N. Cutler (davec) 24-Apr-1991
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+//
+// Used PowerPC eieio instruction to flush writes
+//
+//--
+
+#include "kxppc.h"
+
+
+// SBTTL("Flush Write Buffer")
+//
+//++
+//
+// NTSTATUS
+// KeFlushWriteBuffer (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(KeFlushWriteBuffer)
+
+ eieio // synchronize I/O
+
+ LEAF_EXIT(KeFlushWriteBuffer)
+
+
+
+//
+//++
+//
+// NTSTATUS
+// HalpSynchronizeExecution()
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function flushes the write buffer on the current processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSynchronizeExecution)
+
+ sync // synchronize
+
+ LEAF_EXIT(HalpSynchronizeExecution)
+
+
+//
+//++
+//
+// VOID
+// SetSDR1(
+// ULONG HashedPageTableBase,
+// ULONG HashedPageTableSize
+// )
+//
+// HashedPageTableSize is unused because we ASSUME that the HPT is 64K
+//
+
+ LEAF_ENTRY(SetSDR1)
+
+ mtsdr1 r.3
+
+ LEAF_EXIT(SetSDR1)
+
+#endif
diff --git a/private/ntos/nthals/halppc/ppc/pxflshio.c b/private/ntos/nthals/halppc/ppc/pxflshio.c
new file mode 100644
index 000000000..681d19912
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxflshio.c
@@ -0,0 +1,197 @@
+
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ psflshio.c
+
+Abstract:
+
+ This module implements miscellaneous PowerPC HAL functions.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.ibm.com)
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "arccodes.h"
+
+//
+// Prototypes.
+//
+
+VOID
+HalpSweepPhysicalRangeInBothCaches(
+ ULONG StartingPage,
+ ULONG Offset,
+ ULONG Length
+ );
+
+VOID
+HalpSweepPhysicalIcacheRange(
+ ULONG StartingPage,
+ ULONG Offset,
+ ULONG Length
+ );
+
+
+ULONG
+HalGetDmaAlignmentRequirement (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the alignment requirements for DMA transfers on
+ host system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ The DMA alignment requirement is returned as the fucntion value.
+
+--*/
+
+{
+
+ return 1;
+}
+
+VOID
+HalFlushIoBuffers (
+ IN PMDL Mdl,
+ IN BOOLEAN ReadOperation,
+ IN BOOLEAN DmaOperation
+ )
+
+/*++
+
+Routine Description:
+
+ This function flushes the I/O buffer specified by the memory descriptor
+ list from the data cache on the current processor.
+
+Arguments:
+
+ Mdl - Supplies a pointer to a memory descriptor list that describes the
+ I/O buffer location.
+
+ ReadOperation - Supplies a boolean value that determines whether the I/O
+ operation is a read into memory.
+
+ DmaOperation - Supplies a boolean value that determines whether the I/O
+ operation is a DMA operation.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Length;
+ ULONG PartialLength;
+ ULONG Offset;
+ PULONG Page;
+ BOOLEAN DoDcache = FALSE;
+
+ Length = Mdl->ByteCount;
+
+ if ( !Length ) {
+ return;
+ }
+ //
+ // If the I/O operation is not a DMA operation,
+ // and the I/O operation is a page read operation,
+ // then sweep (index/writeback/invalidate) the data cache.
+ //
+
+ if (((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ DoDcache = TRUE;
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the range from the cache. Note it is not reasonable to sweep
+ // the entire cache on an MP system as "Flash Invalidate" doesn't
+ // broadcast the invalidate to other processors.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+
+ Offset = Mdl->ByteOffset;
+ PartialLength = PAGE_SIZE - Offset;
+ if (PartialLength > Length) {
+ PartialLength = Length;
+ }
+
+ Page = (PULONG)(Mdl + 1);
+
+ if (DoDcache == TRUE) {
+ HalpSweepPhysicalRangeInBothCaches(
+ *Page++,
+ Offset,
+ PartialLength
+ );
+ Length -= PartialLength;
+ if (Length) {
+ PartialLength = PAGE_SIZE;
+ do {
+ if (PartialLength > Length) {
+ PartialLength = Length;
+ }
+ HalpSweepPhysicalRangeInBothCaches(
+ *Page++,
+ 0,
+ PartialLength
+ );
+ Length -= PartialLength;
+ } while (Length != 0);
+ }
+ } else {
+ HalpSweepPhysicalIcacheRange(
+ *Page++,
+ Offset,
+ PartialLength
+ );
+ Length -= PartialLength;
+ if (Length) {
+ PartialLength = PAGE_SIZE;
+ do {
+ if (PartialLength > Length) {
+ PartialLength = Length;
+ }
+ HalpSweepPhysicalIcacheRange(
+ *Page++,
+ 0,
+ PartialLength
+ );
+ Length -= PartialLength;
+ } while (Length != 0);
+ }
+ }
+ }
+ return;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxhalp.h b/private/ntos/nthals/halppc/ppc/pxhalp.h
new file mode 100644
index 000000000..710ff6cad
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxhalp.h
@@ -0,0 +1,345 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1996 International Business Machines Corporation
+
+
+Module Name:
+
+ pxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ PowerPC specific interfaces, defines and structures.
+
+
+Author:
+
+ Jeff Havens (jhavens) 20-Jun-91
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Added externs for HalpInterruptBase,HalpPciConfigBase
+ Added extern for HalpIoControlBase
+ Added prototype for HalpHandleDecrementerInterrupt (was in halp.h)
+ changed adapter object structure to be compatible with the intel HAL
+
+--*/
+
+#ifndef _PXHALP_
+#define _PXHALP_
+
+
+//
+// Define global data used to locate the IO control space, the interrupt
+// acknowlege, and the Pci config base.
+//
+
+extern PVOID HalpIoControlBase;
+extern PVOID HalpIoMemoryBase;
+extern PVOID HalpInterruptBase;
+extern PVOID HalpPciConfigBase;
+extern PVOID HalpErrorAddressRegister;
+extern PVOID HalpPciIsaBridgeConfigBase;
+
+//
+// Define adapter object structure.
+//
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0x40000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0x30000
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_ISA_MAP_REGISTER 16
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+//
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000
+
+//
+// Define the scatter/gather flag for the Map Register Base.
+//
+
+#define NO_SCATTER_GATHER 0x00000001
+
+//
+// Define the copy buffer flag for the index.
+//
+
+#define COPY_BUFFER 0XFFFFFFFF
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+ BOOLEAN IsaBusMaster;
+} ADAPTER_OBJECT;
+
+#if defined(SOFT_HDD_LAMP)
+//
+// On IBM PowerPC machines the HDD (Hard Disk Drive) Lamp is software
+// controlled. HDD Lamp state is controlled in the HAL. The Lamp is
+// turned on in the HAL portion of the device interrupt and turned
+// off periodically if it hasn't been turned on recently.
+//
+// Define structure for keeping track of HDD Lamp.
+//
+
+typedef struct _HDD_LAMP_STATUS {
+ LONG Count;
+} HDD_LAMP_STATUS;
+
+//
+// Number of clock ticks the light should remain on for after an
+// interrupt.
+//
+
+#define SOFT_HDD_TICK_COUNT 3
+
+//
+// HDD Lamp is LSB of ISA port 0x808.
+//
+
+#define HDD_LAMP_PORT 0x808
+
+//
+// Indicate to common code that HDD Lamp should be software driven.
+//
+
+#if !defined(SOFT_HDD_LAMP)
+
+#define SOFT_HDD_LAMP 1
+
+#endif
+
+#endif
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ OUT PULONG NumberOfMapRegisters
+ );
+
+BOOLEAN
+HalpCreateSioStructures(
+ VOID
+ );
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpHandleExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpFieldExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpHandleDecrementerInterrupt (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpAllocateMapBuffer(
+ VOID
+ );
+
+ULONG
+HalpUpdateDecrementer(
+ ULONG
+ );
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace(
+ VOID
+ );
+
+VOID
+HalpPhase0UnMapBusConfigSpace(
+ VOID
+ );
+
+ULONG
+HalpPhase0GetPciDataByOffset(
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+ULONG
+HalpPhase0SetPciDataByOffset(
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length
+ );
+
+PVOID
+KePhase0MapIo(
+ IN ULONG MemoryBase,
+ IN ULONG MemorySize
+ );
+
+PVOID
+KePhase0DeleteIoMap(
+ IN ULONG MemoryBase,
+ IN ULONG MemorySize
+ );
+
+ULONG
+HalpCalibrateTB(
+ VOID
+ );
+
+VOID
+HalpZeroPerformanceCounter(
+ VOID
+ );
+
+VOID
+HalpResetIrqlAfterInterrupt(
+ KIRQL TargetIrql
+ );
+
+VOID
+HalpMapPlugInPciBridges(
+ UCHAR NoBuses
+ );
+
+PVOID
+HalpAssignReservedVirtualSpace(
+ ULONG BasePage,
+ ULONG LengthInPages
+ );
+
+VOID
+HalpReleaseReservedVirtualSpace(
+ PVOID VirtualAddress,
+ ULONG LengthInPages
+ );
+
+//
+// The following function is called when a machine check occurs.
+//
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Provide prototype for Decrementer Interrupts on processors other
+// than 0.
+//
+
+#if defined(_MP_PPC_)
+
+BOOLEAN
+HalpHandleDecrementerInterrupt1 (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ );
+
+BOOLEAN
+HalpHandleIpi(
+ IN PVOID Unused0,
+ IN PVOID Unused1,
+ IN PVOID TrapFrame
+ );
+
+#endif
+
+#endif // _PXHALP_
diff --git a/private/ntos/nthals/halppc/ppc/pxhwsup.c b/private/ntos/nthals/halppc/ppc/pxhwsup.c
new file mode 100644
index 000000000..2b74faa70
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxhwsup.c
@@ -0,0 +1,2188 @@
+/*++
+
+Copyright (c) 1990-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxhwsup.c
+
+Abstract:
+
+ This module contains the HalpXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would normally reside in the internal.c module.
+
+Author:
+
+ Jeff Havens (jhavens) 14-Feb-1990
+
+Environment:
+
+ Kernel mode, local to I/O system
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC Port
+ Remove support for internal bus and devices
+ Changed HalFreeCommonBuffer to support S-FOOT address inversion
+ Added PCI, PCMCIA, and ISA bus support
+ Removed support for internal DMA controller
+ Change HalTranslateBusAddress to support S-FOOTS memory map
+ Deleted HalpReadEisaBus - this code was specific to EISA buses
+ Changed IoMapTransfer to support S-FOOT address inversion
+ Added support for guaranteed contigous common buffers
+
+
+
+--*/
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+#include <pxmemctl.h>
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+//
+// Define map buffer variables
+//
+
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+ULONG HalpMapBufferSize;
+
+
+
+//
+// The DMA controller has a larger number of map registers which may be used
+// by any adapter channel. In order to pool all of the map registers a master
+// adapter object is used. This object is allocated and saved internal to this
+// file. It contains a bit map for allocation of the registers and a queue
+// for requests which are waiting for more map registers. This object is
+// allocated during the first request to allocate an adapter.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+BOOLEAN
+HalpGrowMapBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Amount
+ );
+
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = (ULONG)-1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+
+ return(STATUS_SUCCESS);
+
+}
+
+PVOID
+HalAllocateCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ OUT PPHYSICAL_ADDRESS LogicalAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function allocates the memory for a common buffer and maps so that it
+ can be accessed by a master device and the CPU.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer to be allocated.
+
+ LogicalAddress - Returns the logical address of the common buffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ Returns the virtual address of the common buffer. If the buffer cannot be
+ allocated then NULL is returned.
+
+--*/
+
+{
+ PVOID virtualAddress;
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Allocate the actual buffer.
+ //
+
+
+ physicalAddress.LowPart = 0xFFFFFFFF;
+ physicalAddress.HighPart = 0;
+
+ virtualAddress = MmAllocateContiguousMemory(
+ Length,
+ physicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+ return(NULL);
+ }
+
+
+
+
+ //
+ // Memory space inverion
+ //
+
+
+
+ *LogicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ if (!AdapterObject->IsaBusMaster) {
+ LogicalAddress->LowPart |= IO_CONTROL_PHYSICAL_BASE;
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested. If not all of
+ the registers could be allocated this field is updated to show how
+ many were.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+
+ UNREFERENCED_PARAMETER( AdapterObject );
+ UNREFERENCED_PARAMETER( Length );
+ UNREFERENCED_PARAMETER( LogicalAddress );
+ UNREFERENCED_PARAMETER( CacheEnabled );
+
+ MmFreeContiguousMemory (VirtualAddress);
+
+ return;
+
+}
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ IN OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. Three bus types are supported for the
+ system: PCI, Isa.
+
+Arguments:
+
+ DeviceDescription - Supplies a description of the deivce.
+
+ NumberOfMapRegisters - Returns the maximum number of map registers which
+ may be allocated by the device driver.
+
+Return Value:
+
+ A pointer to the requested adapter object or NULL if an adapter could not
+ be created.
+
+--*/
+
+{
+ PADAPTER_OBJECT adapterObject;
+
+ //
+ // Make sure this is the correct version.
+ //
+
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) {
+
+ return(NULL);
+
+ }
+
+
+ //
+ // If the request is for a unsupported bus then return NULL.
+ //
+
+
+ if (DeviceDescription->InterfaceType != Isa &&
+ DeviceDescription->InterfaceType != PCIBus &&
+ DeviceDescription->InterfaceType != PCMCIABus) {
+
+ //
+ // This bus type is unsupported return NULL.
+ //
+
+ return(NULL);
+ }
+
+ //
+ // Create an adapter object.
+ //
+
+ adapterObject = HalpAllocateIsaAdapter( DeviceDescription,
+ NumberOfMapRegisters);
+ return(adapterObject);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ phyically contiguous memory pages.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+
+ if (MasterAdapterObject == NULL && AdapterBaseVa != NULL ) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ NULL,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL) {
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == NULL) {
+
+ //
+ // Allocate a bit map large enough MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3);
+
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ ZwClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+ AdapterObject->PagePort = NULL;
+ AdapterObject->IsaBusMaster = FALSE;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == NULL ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE )
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+ return AdapterObject;
+
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if there
+ // are no requests in the master adapter queue, then IoFreeMapRegisters
+ // will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0
+ );
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+}
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+
+ ULONG pageOffset;
+ ULONG index;
+ ULONG transferLength;
+ PULONG pageFrame;
+ ULONG logicalAddress;
+ PTRANSLATION_ENTRY translationEntry;
+ BOOLEAN useBuffer;
+ PHYSICAL_ADDRESS returnAddress;
+
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how much of the transfer is contiguous.
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = ((*pageFrame << PAGE_SHIFT) + pageOffset) | IO_CONTROL_PHYSICAL_BASE;
+
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+
+ }
+
+
+ //
+ // Limit the transferLength to the requested Length.
+ //
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ if (MapRegisterBase != NULL) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length) {
+
+ //
+ // do the memory inversion on the logical address
+ //
+
+ logicalAddress = ( translationEntry->PhysicalAddress + pageOffset)
+ | IO_CONTROL_PHYSICAL_BASE;
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ transferLength = *Length;
+ useBuffer = TRUE;
+
+ } else {
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ useBuffer = FALSE;
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+ }
+
+ //
+ // ISA masters require memory to be at less than 16 MB.
+ // always use map buffers for ISA busmasters
+ //
+
+ if (((logicalAddress+transferLength) & ~IO_CONTROL_PHYSICAL_BASE)
+ >= MAXIMUM_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress +
+ pageOffset | IO_CONTROL_PHYSICAL_BASE;
+
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ *Length,
+ WriteToDevice
+ );
+
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ if (AdapterObject != NULL) {
+ if (AdapterObject->IsaBusMaster == TRUE) {
+ returnAddress.LowPart = logicalAddress & ~IO_CONTROL_PHYSICAL_BASE;
+ }
+ else {
+ returnAddress.LowPart = logicalAddress;
+ }
+ }
+ else {
+ returnAddress.LowPart = logicalAddress;
+ }
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ } else {
+
+
+ HalpIsaMapTransfer(
+ AdapterObject,
+ logicalAddress,
+ *Length,
+ WriteToDevice
+ );
+ }
+
+
+ return(returnAddress);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_PORT_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ }
+
+ if (MapRegisterBase == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ if (translationEntry->Index == COPY_BUFFER) {
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice
+ );
+
+ }
+
+ } else {
+
+ //
+ // Cycle through the pages of the transfer to determine if there
+ // are any which need to be copied back.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength && *pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+ }
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called by HalAllocateAdapterChannel when sufficent resources
+ are available to the driver. This routine saves the MapRegisterBase,
+ and set the event pointed to by the context parameter.
+
+Arguments:
+
+ DeviceObject - Supplies a pointer where the map register base should be
+ stored.
+
+ Irp - Unused.
+
+ MapRegisterBase - Supplied by the Io subsystem for use in IoMapTransfer.
+
+ Context - Supplies a pointer to an event which is set to indicate the
+ AdapterObject has been allocated.
+
+Return Value:
+
+ DeallocateObjectKeepRegisters - Indicates the adapter should be freed
+ and mapregisters should remain allocated after return.
+
+--*/
+
+{
+
+ UNREFERENCED_PARAMETER(Irp);
+
+ *((PVOID *) DeviceObject) = MapRegisterBase;
+
+ (VOID) KeSetEvent( (PKEVENT) Context, 0L, FALSE );
+
+ return(DeallocateObjectKeepRegisters);
+}
+
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when a PPC Machine Check interrupt occurs.
+ It print the appropriate status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Unused
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+
+{
+ KIRQL OldIrql;
+ //
+ // raise irql to machine check level
+ //
+
+ KeRaiseIrql(MACHINE_CHECK_LEVEL,&OldIrql);
+
+ //
+ // check memory controller machine check sources
+ //
+
+ HalpHandleMemoryError();
+
+ //
+ // check Bus NMI sources
+ //
+
+ HalpHandleIoError();
+
+ //
+ // Bug check
+ //
+
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+
+ KeLowerIrql(OldIrql);
+
+ return(TRUE);
+}
+
+
+BOOLEAN
+HalpAllocateMapBuffer(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates the required map buffers.
+
+
+Arguments:
+
+
+Return Value:
+
+ TRUE - success
+ FALSE - failure
+
+--*/
+
+{
+
+ PVOID virtualAddress;
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_SIZE;
+
+ HalpMapBufferPhysicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS;
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+ virtualAddress = MmAllocateContiguousMemory(
+ HalpMapBufferSize,
+ HalpMapBufferPhysicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+ return FALSE;
+
+ }
+
+ HalpMapBufferPhysicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ return TRUE;
+}
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the speicific data between the user's buffer and the
+ map register buffer. First a the user buffer is mapped if necessary, then
+ the data is copied. Finally the user buffer will be unmapped if
+ neccessary.
+
+Arguments:
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ TranslationEntry - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - The length of the transfer. This determines the number of map
+ registers that need to be written to map the transfer.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PCCHAR bufferAddress;
+ PCCHAR mapAddress;
+
+ //
+ // Get the system address of the MDL.
+ //
+
+ bufferAddress = MmGetSystemAddressForMdl(Mdl);
+
+ //
+ // Calculate the actual start of the buffer based on the system VA and
+ // the current VA.
+ //
+
+ bufferAddress += (PCCHAR) CurrentVa - (PCCHAR) MmGetMdlVirtualAddress(Mdl);
+
+ mapAddress = (PCCHAR) TranslationEntry->VirtualAddress +
+ BYTE_OFFSET(CurrentVa);
+
+ //
+ // Copy the data between the user buffer and map buffer
+ //
+
+ if (WriteToDevice) {
+
+ RtlMoveMemory( mapAddress, bufferAddress, Length);
+
+ } else {
+
+ RtlMoveMemory(bufferAddress, mapAddress, Length);
+
+ }
+
+}
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ )
+/*++
+
+Routine Description:
+
+ This function attempts to allocate additional map buffers for use by I/O
+ devices. The map register table is updated to indicate the additional
+ buffers.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ KIRQL Irql;
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the addition pages. The maximum number of
+ // slots needed is equal to NumberOfPages + Amount / 64K + 1.
+ //
+
+ i = BYTES_TO_PAGES(MAXIMUM_MAP_BUFFER_SIZE) - (NumberOfPages +
+ (NumberOfPages * PAGE_SIZE) / 0x10000 + 1 +
+ AdapterObject->NumberOfMapRegisters);
+
+ if (i < 0) {
+
+ //
+ // Reduce the allocatation amount to so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ return(FALSE);
+
+ }
+
+
+ if (AdapterObject->NumberOfMapRegisters == 0 && HalpMapBufferSize) {
+
+ NumberOfPages = BYTES_TO_PAGES(HalpMapBufferSize);
+
+ //
+ // Since this is the initial allocation, use the buffer allocated by
+ // HalInitSystem rather than allocationg a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ TRUE // Cache enable.
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+
+ return(FALSE);
+ }
+
+ } else {
+
+ //
+ // Allocate the map buffers.
+ //
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS - 1;
+ physicalAddress.HighPart = 0;
+ MapBufferVirtualAddress = MmAllocateContiguousMemory(
+ NumberOfPages * PAGE_SIZE,
+ physicalAddress
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ MapBufferPhysicalAddress = MmGetPhysicalAddress(
+ MapBufferVirtualAddress
+ ).LowPart;
+
+ }
+
+ //
+ // Initailize the map registers where memory has been allocated.
+ //
+
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; i < NumberOfPages; i++) {
+
+ //
+ // Make sure the perivous entry is physically contiguous with the next
+ // entry and that a 64K physical bountry is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress ||
+ (((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this bountry.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxidaho.h b/private/ntos/nthals/halppc/ppc/pxidaho.h
new file mode 100644
index 000000000..585078bd8
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxidaho.h
@@ -0,0 +1,139 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxidaho.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ for an Idaho memory controller.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+--*/
+
+
+//
+// define structures for the idaho memory controller
+//
+
+
+
+typedef struct _IDAHO_CONTROL {
+ UCHAR Reserved1[0x808]; // Offset 0x000
+ UCHAR HardfileLight; // Offset 0x808
+ UCHAR Reserved2[3];
+ UCHAR EquiptmentPresent; // Offset 0x80C
+ UCHAR Reserved3[3];
+ UCHAR PasswordProtect1; // Offset 0x810
+ UCHAR Reserved4;
+ UCHAR PasswordProtect2; // Offset 0x812
+ UCHAR Reserved5;
+ UCHAR L2Flush; // Offset 0x814
+ UCHAR Reserved6[7];
+ UCHAR SystemControl; // Offset 0x81c
+ UCHAR Reserved9[0x1B];
+ UCHAR Eoi9; // Offset 0x838
+ UCHAR PciInterruptMap1; // Offset 0x839
+ UCHAR Reserved10[2];
+ UCHAR Eoi11; // Offset 0x83C
+ UCHAR PciInterruptMap2; // Offset 0x83D
+ UCHAR AudioSupport; // Offset 0x83E
+ UCHAR Reserved11[0x14];
+ UCHAR Reserved12[0x2C];
+ UCHAR MemorySimmId1; // Offset 0x880
+ UCHAR Reserved13[3];
+ UCHAR MemorySimmId2; // Offset 0x884
+ UCHAR Reserved14[3];
+ UCHAR MemorySimmId3; // Offset 0x888
+ UCHAR Reserved15[3];
+ UCHAR MemorySimmId4; // Offset 0x88C
+ UCHAR Reserved16[0x46B];
+ ULONG ConfigAddress; // Offset 0xcf8
+ ULONG ConfigData; // Offset 0xcfc
+} IDAHO_CONTROL, *PIDAHO_CONTROL;
+
+typedef struct _IDAHO_CONFIG {
+
+ UCHAR VendorId[2]; // Offset 0x00 read-only
+ UCHAR DeviceId[2]; // Offset 0x02 read-only
+ UCHAR Command[2]; // Offset 0x04 unused
+ UCHAR DeviceStatus[2]; // Offset 0x06
+ UCHAR RevisionId; // Offset 0x08 read-only
+ UCHAR Reserved1; // Offset 0x09
+ UCHAR SubclassCode; // Offset 0x0A
+ UCHAR ClassCode; // Offset 0x0B
+ UCHAR Reserved2; // Offset 0x0C
+ UCHAR Reserved3; // Offset 0x0D
+ UCHAR HeaderType; // Offset 0x0E
+ UCHAR BistControl; // Offset 0x0F
+ UCHAR Reserved4[0x2C];
+ UCHAR InterruptLine; // Offset 0x3C
+ UCHAR InterruptPin; // Offset 0x3D
+ UCHAR MinGnt; // Offset 0x3E
+ UCHAR MaxGnt; // Offset 0x3F
+ UCHAR BridgeNumber; // Offset 0x40
+ UCHAR SubordBusNumber; // Offset 0x41
+ UCHAR DisconnectCounter; // Offset 0x42
+ UCHAR ReservedAnger;
+ UCHAR SpecialCycleAddress[2]; // Offset 0x44
+ UCHAR Reserved5[0x3A];
+ UCHAR StartingAddress1; // Offset 0x80
+ UCHAR StartingAddress2; // Offset 0x81
+ UCHAR StartingAddress3; // Offset 0x82
+ UCHAR StartingAddress4; // Offset 0x83
+ UCHAR StartingAddress5; // Offset 0x84
+ UCHAR StartingAddress6; // Offset 0x85
+ UCHAR StartingAddress7; // Offset 0x86
+ UCHAR StartingAddress8; // Offset 0x87
+ UCHAR Reserved6[8];
+ UCHAR EndingAddress1; // Offset 0x90
+ UCHAR EndingAddress2; // Offset 0x91
+ UCHAR EndingAddress3; // Offset 0x92
+ UCHAR EndingAddress4; // Offset 0x93
+ UCHAR EndingAddress5; // Offset 0x94
+ UCHAR EndingAddress6; // Offset 0x95
+ UCHAR EndingAddress7; // Offset 0x96
+ UCHAR EndingAddress8; // Offset 0x97
+ UCHAR Reserved7[8];
+ UCHAR MemoryBankEnable; // Offset 0xA0
+ UCHAR MemoryTiming1; // Offset 0xA1
+ UCHAR MemoryTiming2; // Offset 0xA2
+ UCHAR Reserved8;
+ UCHAR SimmBank1; // Offset 0xA4
+ UCHAR SimmBank2; // Offset 0xA5
+ UCHAR SimmBank3; // Offset 0xA6
+ UCHAR SimmBank4; // Offset 0xA7
+ UCHAR Reserved9[9];
+ UCHAR L2CacheStatus; // Offset 0xB1
+ UCHAR Reserved10[2];
+ UCHAR RefreshCycle; // Offset 0xB4
+ UCHAR RefreshTimer; // Offset 0xB5
+ UCHAR WatchdogTimer; // Offset 0xB6
+ UCHAR BusTimer; // Offset 0xB7
+ UCHAR LocalBusTimer; // Offset 0xB8
+ UCHAR LocalBusIdleTimer; // Offset 0xB9
+ UCHAR Options1; // Offset 0xBA
+ UCHAR Options2; // Offset 0xBB
+ UCHAR Reserved11[4];
+ UCHAR EnableDetection1; // Offset 0xC0
+ UCHAR ErrorDetection1; // Offset 0xC1
+ UCHAR ErrorSimulation1; // Offset 0xC2
+ UCHAR CpuBusErrorStatus; // Offset 0xC3
+ UCHAR EnableDetection2; // Offset 0xC4
+ UCHAR ErrorDetection2; // Offset 0xC5
+ UCHAR ErrorSimulation2; // Offset 0xC6
+ UCHAR PciBusErrorStatus; // Offset 0xC7
+ UCHAR ErrorAddress[4]; // Offset 0xC8
+} IDAHO_CONFIG, *PIDAHO_CONFIG;
+
diff --git a/private/ntos/nthals/halppc/ppc/pxidle.c b/private/ntos/nthals/halppc/ppc/pxidle.c
new file mode 100644
index 000000000..65e5128ec
--- /dev/null
+++ b/private/ntos/nthals/halppc/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.
+
+
+--*/
+
+{
+ HalpEnableInterrupts();
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxinfo.c b/private/ntos/nthals/halppc/ppc/pxinfo.c
new file mode 100644
index 000000000..8936197db
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxinfo.c
@@ -0,0 +1,213 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixinfo.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr) 08-Aug-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+
+#include "halp.h"
+
+#ifdef POWER_MANAGEMENT
+
+HAL_CALLBACKS HalCallback;
+
+
+VOID
+HalInitSystemPhase2 (
+ VOID
+ );
+
+VOID
+HalpLockSuspendCode (
+ IN PVOID CallbackContext,
+ IN PVOID Argument1,
+ IN PVOID Argument2
+ );
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalInitSystemPhase2)
+#pragma alloc_text(PAGE,HalpLockSuspendCode)
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+
+VOID
+HalInitSystemPhase2 (
+ VOID
+ )
+{
+ EXECUTIVE_CALLBACK_INFORMATION ExCb;
+ NTSTATUS Status;
+
+ //
+ // Create hal callbacks
+ //
+
+
+ ExOpenCallback (&HalCallback.SetSystemInformation, NULL, TRUE, TRUE);
+ ExOpenCallback (&HalCallback.BusInsertionCheck, NULL, TRUE, TRUE);
+
+ //
+ // Connect to suspend callback to lock hal hibaration code
+ //
+
+ ExQueryExecutiveInformation (
+ ExecutiveCallbacks,
+ &ExCb,
+ sizeof (ExCb),
+ NULL
+ );
+
+ ExRegisterCallback (
+ ExCb.SuspendHibernateSystem,
+ HalpLockSuspendCode,
+ NULL
+ );
+
+}
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN ULONG InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+{
+ NTSTATUS Status;
+ PVOID InternalBuffer;
+ ULONG Length;
+ union {
+ HAL_POWER_INFORMATION PowerInf;
+ HAL_PROCESSOR_SPEED_INFORMATION ProcessorInf;
+ } U;
+
+
+ PAGED_CODE();
+
+ Status = STATUS_SUCCESS;
+ *ReturnedLength = 0;
+ Length = 0;
+
+ switch (InformationClass) {
+ case HalInstalledBusInformation:
+ Status = HalpQueryInstalledBusInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength
+ );
+ break;
+
+ case HalPowerInformation:
+ RtlZeroMemory (&U.PowerInf, sizeof(HAL_POWER_INFORMATION));
+
+ InternalBuffer = &U.PowerInf;
+ Length = sizeof (HAL_POWER_INFORMATION);
+ break;
+
+
+ case HalProcessorSpeedInformation:
+ RtlZeroMemory (&U.ProcessorInf, sizeof(HAL_POWER_INFORMATION));
+
+ U.ProcessorInf.MaximumProcessorSpeed = 100;
+ U.ProcessorInf.CurrentAvailableSpeed = 100;
+ U.ProcessorInf.ConfiguredSpeedLimit = 100;
+
+ InternalBuffer = &U.PowerInf;
+ Length = sizeof (HAL_PROCESSOR_SPEED_INFORMATION);
+ break;
+
+ case HalCallbackInformation:
+ InternalBuffer = &HalCallback;
+ Length = sizeof (HAL_CALLBACKS);
+ break;
+
+ default:
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ //
+ // If non-zero Length copy data to callers buffer
+ //
+
+ if (Length) {
+ if (BufferSize < Length) {
+ Length = BufferSize;
+ }
+
+ *ReturnedLength = Length;
+ RtlCopyMemory (Buffer, InternalBuffer, Length);
+ }
+
+ return Status;
+}
+
+NTSTATUS
+HaliSetSystemInformation (
+ IN ULONG InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+{
+ PAGED_CODE();
+ return STATUS_INVALID_LEVEL;
+}
+
+
+VOID
+HalpLockSuspendCode (
+ IN PVOID CallbackContext,
+ IN PVOID Argument1,
+ IN PVOID Argument2
+ )
+{
+ static PVOID CodeLock;
+
+ switch ((ULONG) Argument1) {
+ case 0:
+ //
+ // Lock code down which might be needed to perform a suspend
+ //
+
+ ASSERT (CodeLock == NULL);
+ CodeLock = MmLockPagableCodeSection (&HaliSuspendHibernateSystem);
+ break;
+
+ case 1:
+ //
+ // Release the code lock
+ //
+
+ MmUnlockPagableImageSection (CodeLock);
+ CodeLock = NULL;
+ break;
+ }
+}
+
+#endif // POWER_MANAGEMENT
diff --git a/private/ntos/nthals/halppc/ppc/pxinithl.c b/private/ntos/nthals/halppc/ppc/pxinithl.c
new file mode 100644
index 000000000..6fbea7c9d
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxinithl.c
@@ -0,0 +1,325 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+
+Author:
+
+ David N. Cutler (davec) 25-Apr-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.ibm.com) Initial Power PC port
+
+ Removed call to HalpMapFixedTbEntries, the PPC port
+ maps all memory via calls to MmMapIoSpace().
+ Removed call to HalpInializeInterrupts - 8259 initialized in phase 1
+ Removed Cache error handler - 601 has no cache error interrupt
+ Removed call to HalpCreateDmaSturctures - it supports internal DMA
+ internal DMA contoller.
+
+--*/
+
+#include "halp.h"
+#include <pxmemctl.h>
+
+extern ADDRESS_USAGE HalpDefaultIoSpace;
+
+extern VOID HalpCopyOEMFontFile();
+
+VOID
+HalpSynchronizeExecution(
+ VOID
+ );
+
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalInitSystem)
+#pragma alloc_text(INIT, HalInitializeProcessor)
+
+#endif
+
+PVOID HalpIoControlBase = (PVOID) 0;
+PVOID HalpIoMemoryBase = (PVOID) 0;
+
+ULONG HalpInitPhase;
+
+VOID
+HalpInitBusHandlers (
+ VOID
+ );
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ Power PC system.
+
+Arguments:
+
+ Phase - Supplies the initialization phase (zero or one).
+
+ LoaderBlock - Supplies a pointer to a loader parameter block.
+
+Return Value:
+
+ A value of TRUE is returned is the initialization was successfully
+ complete. Otherwise a value of FALSE is returend.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+
+
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ HalpInitPhase = Phase;
+
+ Prcb = PCR->Prcb;
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ //
+ // Get access to I/O space, check if I/O space has already been
+ // mapped by debbuger initialization.
+ //
+
+ if (HalpIoControlBase == NULL) {
+
+ HalpIoControlBase = (PVOID)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE, 0x20000);
+
+ if ( !HalpIoControlBase ) {
+ return FALSE;
+ }
+ }
+
+ // Verify that the processor block major version number conform
+ // to the system that is being loaded.
+ //
+
+ if (Prcb->MajorVersion != PRCB_MAJOR_VERSION) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNewTimeIncrement = MAXIMUM_INCREMENT;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ //
+ // Initialize all spin locks.
+ //
+
+#if defined(_MP_PPC_)
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+
+#endif
+
+#ifdef POWER_MANAGEMENT
+ //
+ // Fill in handlers for APIs which this hal supports
+ //
+
+ HalSuspendHibernateSystem = HaliSuspendHibernateSystem;
+ HalQuerySystemInformation = HaliQuerySystemInformation;
+ HalSetSystemInformation = HaliSetSystemInformation;
+ HalRegisterBusHandler = HaliRegisterBusHandler;
+ HalHandlerForBus = HaliHandlerForBus;
+ HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
+ HalQueryBusSlots = HaliQueryBusSlots;
+ HalSlotControl = HaliSlotControl;
+ HalCompleteSlotControl = HaliCompleteSlotControl;
+#endif // POWER_MANAGEMENT
+
+ HalpRegisterAddressUsage (&HalpDefaultIoSpace);
+
+ HalpPhase0DiscoverPciBuses(LoaderBlock->ConfigurationRoot);
+
+ //
+ // Initialize the display adapter.
+ //
+
+ if (!HalpInitializeDisplay(LoaderBlock)) {
+
+ return FALSE;
+ }
+ }
+
+ //
+ // Calibrate execution stall
+ //
+
+ HalpCalibrateStall();
+
+ //
+ // InitializeInterrupts
+ //
+
+ if (!HalpInitializeInterrupts())
+
+ return FALSE;
+
+ //
+ // return success
+ //
+
+ return TRUE;
+
+
+ } else {
+
+ if (Phase != 1)
+ return(FALSE);
+
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+
+
+ HalpRegisterInternalBusHandlers ();
+
+
+ if (!HalpAllocateMapBuffer()) {
+ return FALSE;
+ }
+
+
+ //
+ // Map I/O space and create ISA data structures.
+ //
+
+ if (!HalpMapIoSpace()) {
+ return FALSE;
+ }
+
+ if (!HalpCreateSioStructures()) {
+ return FALSE;
+ }
+
+ //
+ // retain the OEM Font File for later use
+ //
+
+ HalpCopyOEMFontFile();
+ HalpCopyBiosShadow();
+
+ return TRUE;
+
+ }
+}
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If this is the first processor to do so, initialize the cache
+ // sweeping routines depending on type of processor.
+ //
+
+ if ( Number == 0 ) {
+ if ( HalpCacheSweepSetup() ) {
+ KeBugCheck(MISMATCHED_HAL);
+ }
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxintmod.c b/private/ntos/nthals/halppc/ppc/pxintmod.c
new file mode 100644
index 000000000..67c26cd44
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxintmod.c
@@ -0,0 +1,79 @@
+/*++
+
+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 Sandalfoot irq 15 is reserved for PCI interrupts and is always level sensitive
+ //
+
+ if (Vector == DEVICE_VECTORS + 15) {
+
+ return LevelSensitive;
+
+ //
+ // No other special interrupt mode translations for sandalfoot
+ //
+
+ } else {
+
+ return InterruptMode;
+
+ }
+
+}
+
+//
+// Correct the interrupt mode for the given vector.
+// On Sandalfoot 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/halppc/ppc/pxintrpt.c b/private/ntos/nthals/halppc/ppc/pxintrpt.c
new file mode 100644
index 000000000..299e0535a
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxintrpt.c
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Copyright (c) 1996 International Business Machines Corporation
+
+
+Module Name:
+
+ pxintrpt.c
+
+Abstract:
+ This is an abbreviated version of the pxintrpt.c
+ found in halvict, haldoral and haltiger. It is
+ here only so that pxsysbus.c can be the same for
+ halppc and the three mentioned above. We could,
+ in the future, make it contain all the code
+ that pxintrpt.c would in the others.
+
+Author:
+
+Environment:
+
+Revision History:
+ Jake Oshins (joshins@vnet.ibm.com) 2-2-96
+
+
+--*/
+#include "halp.h"
+
+#include "eisa.h"
+
+extern UCHAR VectorToIrqlTable[];
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+ULONG
+HalpGetSystemInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+
+ UNREFERENCED_PARAMETER( BusHandler );
+ UNREFERENCED_PARAMETER( RootHandler );
+
+ *Affinity = 1;
+
+
+//NOTE - this should probably go in pxsiosup.c since it is specific to the SIO
+ //
+ // Set the IRQL level. Map the interrupt controllers priority scheme to
+ // NT irql values. The SIO prioritizes irq's as follows:
+ //
+ // irq0, irq1, irq8, irq9 ... irq15, irq3, irq4 ... irq7.
+ //
+
+ *Irql = (KIRQL) VectorToIrqlTable[BusInterruptLevel];
+
+ //
+ // The vector is equal to the specified bus level plus the DEVICE_VECTORS.
+ //
+
+ return(BusInterruptLevel + DEVICE_VECTORS);
+
+}
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxintsup.s b/private/ntos/nthals/halppc/ppc/pxintsup.s
new file mode 100644
index 000000000..df6142aba
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxintsup.s
@@ -0,0 +1,35 @@
+// TITLE("Enable and Disable Processor Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxintsup.s
+//
+// Abstract:
+//
+// This module implements the code necessary to enable and disable
+// interrupts on a PPC system.
+//
+// Author:
+//
+// Jim Wooldridge
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 30-Dec-93 plj Added 603 support.
+//
+//--
+#include "halppc.h"
+
+.extern KiDispatchSoftwareInterrupt
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxirql.c b/private/ntos/nthals/halppc/ppc/pxirql.c
new file mode 100644
index 000000000..35e924c61
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxirql.c
@@ -0,0 +1,284 @@
+// TITLE("Manipulate Interrupt Request Level")
+//++
+//
+// Copyright (c) 1990 Microsoft Corporation
+// Copyright (c) 1996 International Business Machines Corporation
+// Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// PXIRQL.C
+//
+// Abstract:
+//
+// This module implements the code necessary to lower and raise the current
+// Interrupt Request Level (IRQL).
+//
+//
+// Author:
+//
+// Jim Wooldridge (IBM)
+// Steve Johns (Motorola)
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+// 22-Feb-94 Steve Johns (Motorola)
+// KeRaiseIrql - Disabled interrupts at PIC if IRQL >= DEVICE_LEVEL
+// KeLowerIrql - Enabled interrupts at PIC if IRQL < DEVICE_LEVEL
+// 15-Apr-94 Jim Wooldridge
+// Added irql interrupt mask table and expanded irql range from (0-8)
+// to (0-31).
+//
+//--
+
+#include "halp.h"
+#include "eisa.h"
+
+#define ISA_CONTROL ((PEISA_CONTROL) HalpIoControlBase)
+extern UCHAR HalpSioInterrupt1Mask;
+extern UCHAR HalpSioInterrupt2Mask;
+extern BOOLEAN HalpProfilingActive;
+
+UCHAR VectorToIrqlTable[] = { MAXIMUM_DEVICE_LEVEL, // irq 0
+ 26, // irq 1
+ 25, // irq 2
+ 16, // irq 3
+ 15, // irq 4
+ 14, // irq 5
+ 13, // irq 6
+ 12, // irq 7
+ 24, // irq 8
+ 23, // irq 9
+ 22, // irq 10
+ 21, // irq 11
+ 20, // irq 12
+ 19, // irq 13
+ 18, // irq 14
+ 17 // irq 15
+ };
+
+
+//
+// Initialize the 8259 irql mask table
+//
+
+USHORT Halp8259MaskTable[] = { 0x0000, // irql0 Low level
+ 0x0000, // irql1 APC
+ 0x0000, // irql2 Dispatch
+ 0x0000, // irql3
+ 0x0000, // irql4
+ 0x0000, // irql5
+ 0x0000, // irql6
+ 0x0000, // irql7
+ 0x0000, // irql8
+ 0x0000, // irql9
+ 0x0000, // irql10
+ 0x0000, // irql11
+ 0x0080, // irql12 parallel
+ 0x00C0, // irql13 floppy
+ 0x00E0, // irql14 parallel
+ 0x00F0, // irql15 com 1
+ 0x00F8, // irql16 com 2
+ 0x80F8, // irql17 pci slot
+ 0xC0F8, // irql18 isa slot
+ 0xE0F8, // irql19 scsi
+ 0xF0F8, // irql20 mouse
+ 0xF8F8, // irql21 isa slot
+ 0xFCF8, // irql22 audio
+ 0xFEF8, // irql23 isa slot
+ 0xFFF8, // irql24 rtc
+ 0xFFFA, // irql25 cascade
+ 0xFFFA, // irql26 kb
+ 0xFFFB, // irql27 timer 1/ profile
+ 0xFFFF, // irql28 clock level
+ 0xFFFF, // irql29
+ 0xFFFF, // irql30
+ 0xFFFF // irql31 High level
+ };
+
+
+#define IRQ0 1
+
+VOID
+KiDispatchSoftwareInterrupt(
+ VOID
+ );
+
+
+//
+// VOID
+// KeLowerIrql (
+// KIRQL NewIrql
+// )
+//
+// Routine Description:
+//
+// This function lowers the current IRQL to the specified value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+VOID
+KeLowerIrql(
+ KIRQL NewIrql
+ )
+
+{
+KIRQL OldIrql;
+PUCHAR PIC_Address;
+UCHAR PIC_Mask;
+
+
+ OldIrql = PCR->CurrentIrql;
+
+ //
+ // If this is a software to software transition don't change hardware
+ // interrupt state
+ //
+
+ if (OldIrql > DISPATCH_LEVEL) {
+
+ HalpDisableInterrupts();
+ PCR->CurrentIrql = NewIrql;
+
+ //
+ // If old IRQL is < CLOCK2_LEVEL then interrupt are enabled
+ // in the MSR but the 8259 mask must be updated. If not, then
+ // interrupts need to be enabled, however the 8259 does not need to
+ // be updated.
+ //
+
+ if (NewIrql < CLOCK2_LEVEL) {
+
+
+ if (OldIrql < CLOCK2_LEVEL ) {
+
+
+ //
+ // Get contoller 1 interrupt mask
+ //
+
+ HALPCR->HardPriority = NewIrql;
+
+ PIC_Mask = HalpSioInterrupt1Mask | (Halp8259MaskTable[NewIrql] & 0x00FF);
+ PIC_Address = &(ISA_CONTROL->Interrupt1ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+
+ //
+ // Get contoller 2 interrupt mask
+ //
+
+ PIC_Mask = HalpSioInterrupt2Mask | (Halp8259MaskTable[NewIrql] >> 8 );
+ PIC_Address = &(ISA_CONTROL->Interrupt2ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+ }
+ HalpEnableInterrupts();
+
+ }
+ }
+ else {
+ PCR->CurrentIrql = NewIrql;
+ }
+
+ //
+ // check for DPC's
+
+ if ((NewIrql < DISPATCH_LEVEL) && PCR->SoftwareInterrupt)
+ KiDispatchSoftwareInterrupt();
+
+}
+
+/*************************************************************************/
+
+//
+// VOID KeRaiseIrql (
+// KIRQL NewIrql,
+// PKIRQL OldIrql
+// )
+//
+// Routine Description:
+//
+// This function raises the current IRQL to the specified value and returns
+// the old IRQL value.
+//
+// Arguments:
+//
+// NewIrql - Supplies the new IRQL value.
+//
+// OldIrql - Supplies a pointer to a variable that recieves the old
+// IRQL value.
+//
+
+VOID
+KeRaiseIrql(
+ IN KIRQL NewIrql,
+ OUT PKIRQL OldIrql
+ )
+
+{
+PUCHAR PIC_Address;
+UCHAR PIC_Mask;
+
+
+
+ //
+ // If this is a software to software transition don't change hardware
+ // interrupt state
+ //
+
+ if (NewIrql > DISPATCH_LEVEL) {
+
+ HalpDisableInterrupts();
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+
+ //
+ // If new irql is >= CLOCK2_LEVEL disable interrupts in the MSR but
+ // don't touch the 8259's. If not, leave interrupts enabled and
+ // update the 8259's
+ //
+
+ if (NewIrql < CLOCK2_LEVEL) {
+
+ HALPCR->HardPriority = NewIrql;
+
+ //
+ // Get controller 1 interrupt mask
+ //
+
+ PIC_Address = &(ISA_CONTROL->Interrupt1ControlPort1);
+ PIC_Mask = HalpSioInterrupt1Mask | (Halp8259MaskTable[NewIrql] & 0x00FF);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+
+ //
+ // Get controller 2 interrupt mask
+ //
+
+ PIC_Mask = HalpSioInterrupt2Mask | (Halp8259MaskTable[NewIrql] >> 8);
+ PIC_Address = &(ISA_CONTROL->Interrupt2ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+
+ HalpEnableInterrupts();
+ }
+
+ }
+
+ else {
+ *OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = NewIrql;
+ }
+
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxisabus.c b/private/ntos/nthals/halppc/ppc/pxisabus.c
new file mode 100644
index 000000000..15cd38f5a
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxisabus.c
@@ -0,0 +1,133 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxisabus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+
+ULONG
+HalpGetIsaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetIsaInterruptVector)
+#pragma alloc_text(PAGE,HalpAdjustIsaResourceList)
+#pragma alloc_text(PAGE,HalpAdjustResourceListLimits)
+#endif
+
+
+ULONG
+HalpGetIsaInterruptVector(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system interrupt vector and IRQL level
+ corresponding to the specified bus interrupt level and/or vector. The
+ system interrupt vector and IRQL are suitable for use in a subsequent call
+ to KeInitializeInterrupt.
+
+Arguments:
+
+ BusHandle - Per bus specific structure
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the system wide irq affinity.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+{
+
+ //
+ // irq2 shows up on irq9
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ BusInterruptVector = 9;
+ }
+
+ //
+ // Get parent's translation from here..
+ //
+ return BusHandler->ParentHandler->GetInterruptVector (
+ BusHandler->ParentHandler,
+ RootHandler,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+
+ SUPPORTED_RANGE InterruptRange;
+
+ RtlZeroMemory (&InterruptRange, sizeof InterruptRange);
+
+ InterruptRange.Base = 0;
+
+#ifdef CAROLINA
+ InterruptRange.Limit = 18;
+#else
+ InterruptRange.Limit = 15;
+#endif //CAROLINA
+
+ return HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ &InterruptRange,
+ pResourceList
+ );
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxmapio.c b/private/ntos/nthals/halppc/ppc/pxmapio.c
new file mode 100644
index 000000000..edf50cc91
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmapio.c
@@ -0,0 +1,124 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space for a POWER PC
+ system.
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial PowerPC port
+
+ Map interrupt acknowledge base address
+ Map SIO config base address
+ Remove RTC map - S-FOOT mapsthe RTC into the ISA I/O space
+
+--*/
+
+#include "halp.h"
+
+//
+// Put all code for HAL initialization in the INIT section. It will be
+// deallocated by memory management when phase 1 initialization is
+// completed.
+//
+
+#if defined(ALLOC_PRAGMA)
+
+#pragma alloc_text(INIT, HalpMapIoSpace)
+
+#endif
+
+
+BOOLEAN
+HalpMapIoControlSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpMapPlanarSpace (
+ VOID
+ );
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ );
+
+//
+// Define global data used to locate the IO control space and the PCI config
+// space.
+//
+
+PVOID HalpInterruptBase;
+PVOID HalpPciConfigBase;
+PVOID HalpErrorAddressRegister;
+
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O, planar control, and bus configuration
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Map bus/bridge I/O control space
+ //
+
+ if (!HalpMapIoControlSpace())
+ return FALSE;
+
+ //
+ // Map Planar I/O control space
+ //
+
+ if (!HalpMapPlanarSpace())
+ return FALSE;
+
+ //
+ // Map Bus configuration space
+ //
+
+ if (!HalpMapBusConfigSpace())
+ return FALSE;
+
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxmemctl.c b/private/ntos/nthals/halppc/ppc/pxmemctl.c
new file mode 100644
index 000000000..9e063bb45
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmemctl.c
@@ -0,0 +1,311 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+
+
+#include "halp.h"
+#include "pxmemctl.h"
+#include "pxdakota.h"
+
+
+BOOLEAN
+HalpInitPlanar (
+ VOID
+ )
+
+{
+
+//
+// 604 ERRATA
+//
+ UCHAR DataByte;
+ ULONG ProcessorAndRev;
+
+ ProcessorAndRev = HalpGetProcessorVersion();
+
+ if ( ((ProcessorAndRev >> 16) == 4) &&
+ ((ProcessorAndRev & 0xffff) <= 0x200) ) {
+
+ //
+ // Disable TEA
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PDAKOTA_CONTROL)HalpIoControlBase)->SystemControl);
+ WRITE_REGISTER_UCHAR(&((PDAKOTA_CONTROL)HalpIoControlBase)->SystemControl,
+ DataByte & ~0x20);
+ }
+
+//
+// 604 ERRATA end
+//
+
+ 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);
+
+ //
+ // Map the error address register
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = ERROR_ADDRESS_REGISTER;
+ HalpErrorAddressRegister = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+
+ if (HalpInterruptBase == NULL || HalpErrorAddressRegister == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+
+
+}
+
+BOOLEAN
+HalpMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+
+ //
+ // Map the PCI config space.
+ //
+
+ physicalAddress.LowPart = PCI_CONFIG_PHYSICAL_BASE;
+ HalpPciConfigBase = MmMapIoSpace(physicalAddress,
+ PCI_CONFIG_SIZE,
+ FALSE);
+
+ if (HalpPciConfigBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+BOOLEAN
+HalpPhase0MapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Map the PCI config space.
+ //
+
+ HalpPciConfigBase = (PUCHAR)KePhase0MapIo(PCI_CONFIG_PHYSICAL_BASE, 0x400000);
+
+ if (HalpPciConfigBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+
+VOID
+HalpPhase0UnMapBusConfigSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL PCI config
+ spaces for a PowerPC system during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ //
+ // Unmap the PCI config space and set HalpPciConfigBase to NULL.
+ //
+
+ KePhase0DeleteIoMap(PCI_CONFIG_PHYSICAL_BASE, 0x400000);
+ HalpPciConfigBase = NULL;
+
+}
+
+
+VOID
+HalpHandleMemoryError(
+ VOID
+ )
+
+{
+
+ UCHAR StatusByte;
+ ULONG ErrorAddress;
+ UCHAR TextAddress[20];
+ ULONG Bits,Byte;
+
+ //
+ // Read the error address register first
+ //
+
+
+ ErrorAddress = READ_PORT_ULONG(HalpErrorAddressRegister);
+
+ //
+ // Convert error address to HEX characters
+ //
+
+ for (Bits=28,Byte=0 ;Byte < 8; Byte++, Bits= Bits - 4) {
+
+ TextAddress[Byte] = (UCHAR) ((((ErrorAddress >> Bits) & 0xF) > 9) ?
+ ((ErrorAddress >> Bits) & 0xF) - 10 + 'A' :
+ ((ErrorAddress >> Bits) & 0xF) + '0');
+
+ }
+
+ TextAddress[8] = '\n';
+ TextAddress[9] = '\0';
+
+
+ //
+ // Check TEA conditions
+ //
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->MemoryParityErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString ("TEA: Memory Parity Error at Address ");
+ HalDisplayString (TextAddress);
+ }
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->L2CacheErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString ("TEA: L2 Cache Parity Error\n");
+ }
+
+ StatusByte = READ_PORT_UCHAR(&((PDAKOTA_CONTROL)
+ HalpIoControlBase)->TransferErrorStatus);
+
+ if (!(StatusByte & 0x01)) {
+ HalDisplayString ("TEA: Transfer Error at Address ");
+ HalDisplayString (TextAddress);
+ }
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxmemctl.h b/private/ntos/nthals/halppc/ppc/pxmemctl.h
new file mode 100644
index 000000000..8473ddbb5
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmemctl.h
@@ -0,0 +1,38 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+
+Module Name:
+
+ pxmemctl.h
+
+Abstract:
+
+ This header file defines the structures for the planar registers
+ on Masters systems.
+
+
+
+
+Author:
+
+ Jim Wooldridge
+
+
+Revision History:
+
+--*/
+
+
+//
+// define physical base addresses of planar
+//
+
+#define INTERRUPT_PHYSICAL_BASE 0xbffffff0 // physical base of interrupt source
+#define ERROR_ADDRESS_REGISTER 0xbfffeff0
+
+#define IO_CONTROL_PHYSICAL_BASE 0x80000000 // physical base of IO control
+#define SYSTEM_IO_CONTROL_SIZE 0x00008000
+
+
+#define PCI_CONFIG_PHYSICAL_BASE 0x80800000 // physical base of PCI config space
+#define PCI_CONFIG_SIZE 0x00800000
diff --git a/private/ntos/nthals/halppc/ppc/pxmisc.s b/private/ntos/nthals/halppc/ppc/pxmisc.s
new file mode 100644
index 000000000..f8375ed2e
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmisc.s
@@ -0,0 +1,159 @@
+//++
+//
+// Copyright (c) 1995 IBM Corporation
+//
+// Module Name:
+//
+// pxmisc.s
+//
+// Abstract:
+//
+// Home for a small number of miscellaneous routines that need to
+// be in assemblu code.
+//
+// Author:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) August 1995
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "kxppc.h"
+
+#define LOCK_RETRY (64*1024*1024)
+
+ .data
+ .globl HalpDisplayLock
+HalpDisplayLock:
+ .long 0
+
+
+//++
+//
+// VOID
+// HalpAcquireDisplayLock(
+// VOID
+// );
+//
+// Routine Description:
+//
+// Acquire a spinlock to ensure only processor is writing to the
+// display (via HalDisplayString) at a time.
+//
+// If the attempt to acquire the lock fails after LOCK_RETRY attempts,
+// just TAKE it on the assumption that the other processor is dead.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpAcquireDisplayLock)
+
+ lwz r.3, [toc]HalpDisplayLock(r.toc) // get address of lock
+ LWI(r.4,LOCK_RETRY) // get retry count
+ mtctr r.4 // set loop count
+ li r.5, 1 // lock value
+
+getlk: lwarx r.4, 0, r.3 // get lock value
+ cmpwi r.4, 0 // already taken?
+ bne waitlk
+ stwcx. r.5, 0, r.3 // set locked
+ beqlr // return if store
+ // succeeded.
+waitlk: lwz r.4, 0(r.3) // wait for lock to
+ // become 0.
+ bdz failed // jif retry limit
+ // exceeded.
+ cmpwi r.4, 0
+ beq getlk // try again.
+ b waitlk // continue wait
+
+failed: stw r.5, 0(r.3)
+
+ LEAF_EXIT(HalpAcquireDisplayLock)
+
+//++
+//
+// VOID
+// HalpReleaseDisplayLock(
+// VOID
+// );
+//
+// Routine Description:
+//
+// Release the lock acquired by HalpAcquireDisplayLock.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpReleaseDisplayLock)
+
+ lwz r.3, [toc]HalpDisplayLock(r.toc) // get address of lock
+ li r.0, 0
+ stw r.0, 0(r.3) // release it
+
+ LEAF_EXIT(HalpReleaseDisplayLock)
+
+//++
+//
+// ULONG
+// HalpGetPhysicalProcessorNumber(
+// VOID
+// );
+//
+// Routine Description:
+//
+// Returns the number of this physical processor.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Processor Number.
+//
+//--
+
+ LEAF_ENTRY(HalpGetPhysicalProcessorNumber)
+
+#if defined(_MP_PPC_)
+
+ mfpvr r.0 // if 604 (or derivative)
+ rlwinm r.0, r.0, 16, 0xffff // get processor number
+ cmpwi cr.0, r.0, 4 // from SPR 1023 (PIR).
+ cmpwi cr.1, r.0, 9 //
+
+ beq cr.0, type604
+ bne cr.1, nota604
+
+type604:
+
+ mfspr r.3, 1023 // read 604 PIR register
+ blr
+
+nota604:
+
+#endif
+
+ li r.3, 0 // fake it
+
+ LEAF_EXIT(HalpGetPhysicalProcessorNumber)
diff --git a/private/ntos/nthals/halppc/ppc/pxmp.h b/private/ntos/nthals/halppc/ppc/pxmp.h
new file mode 100644
index 000000000..c71300e76
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmp.h
@@ -0,0 +1,59 @@
+/*++
+
+ Copyright 1995 International Business Machines
+
+Module Name:
+
+ pxmp.h
+
+Abstract:
+
+ Defines structures specific to IBM MP PowerPC systems/HALs.
+
+Author:
+
+ Peter L Johnston (plj@vnet.ibm.com) August 1995.
+
+--*/
+
+#ifndef __PXMP_H
+
+#define __PXMP_H
+
+#include "pxmpic2.h"
+
+//
+// Define PER processor HAL data.
+//
+// This structure is assigned the address &PCR->HalReserved which is
+// an array of 16 ULONGs in the architectually defined section of the
+// PCR.
+//
+
+typedef struct {
+ ULONG PhysicalProcessor;
+ PMPIC_PER_PROCESSOR_REGS MpicProcessorBase;
+ ULONG HardPriority;
+ ULONG PendingInterrupts;
+} PER_PROCESSOR_DATA, *PPER_PROCESSOR_DATA;
+
+#if defined(HALPCR)
+
+//
+// Remove UNI processor defn in favor of MP defn of HALPCR.
+//
+
+#undef HALPCR
+
+#endif
+
+#define HALPCR ((PPER_PROCESSOR_DATA)&PCR->HalReserved)
+
+ULONG __builtin_cntzlw(ULONG);
+
+#define HIGHEST_PENDING_IRQL() \
+ (31-__builtin_cntzlw(HALPCR->PendingInterrupts))
+
+#define MAXIMUM_PROCESSORS 32
+
+#endif
diff --git a/private/ntos/nthals/halppc/ppc/pxmpic2.h b/private/ntos/nthals/halppc/ppc/pxmpic2.h
new file mode 100644
index 000000000..e1d745a7d
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmpic2.h
@@ -0,0 +1,309 @@
+/*++
+
+ Copyright 1995 International Business Machines
+
+Module Name:
+
+ pxmpic2.h
+
+Abstract:
+
+ Defines structures and offsets to those structures of the I/O
+ space for the PowerPC MP Interrupt Controller (MPIC or OPENPIC).
+
+Author:
+
+ Peter L Johnston (plj@vnet.ibm.com) August 1995.
+
+--*/
+
+#ifndef __PXMPIC2_H
+
+#define __PXMPIC2_H
+
+#include "pci.h"
+
+//
+// Define MPIC Global Registers
+//
+
+typedef struct _MPICGLOB_FEATURE_REPORT {
+
+ ULONG VersionId :8; // Controller Version
+ ULONG NumCpu :5; // Num cpus supported by this controller
+ ULONG _res0 :3; //
+ ULONG NumIrq :11; // highest IRQ source supported
+ ULONG _res1 :5; //
+
+} MPICGLOB_FEATURE_REPORT;
+
+typedef struct _MPICGLOB_CONFIG {
+
+ ULONG _base :20; // not used in PCI systems
+ ULONG _res0 :9; //
+ ULONG Mode :2; // Cascade Mode 00 = 8259 pass thru
+ // 01 = Mixed
+ // 10 = reserved
+ ULONG Reset :1; // Reset Controller
+
+} MPICGLOB_CONFIG;
+
+#define MPIC_8259_MODE 0x0
+#define MPIC_MIXED_MODE 0x1
+
+typedef struct _MPICGLOB_VENDOR_ID {
+
+ ULONG VendorId :8; // manufacturer
+ ULONG DeviceId :8; // device id tbd
+ ULONG Stepping :8; // silicon rev
+ ULONG _res0 :8; //
+
+} MPICGLOB_VENDOR_ID;
+
+typedef struct _MPICGLOB_PROCESSOR_INIT {
+
+ ULONG SelectProcessor; // bit mask, causes processor reset
+
+} MPICGLOB_PROCESSOR_INIT;
+
+typedef struct {
+ ULONG Vector :8; // Interrupt Vector
+ ULONG _res0 :8; //
+ ULONG Priority :4; // Interrupt Priority
+ ULONG NMI :1; // Generate NMI (valid in IPI[3] only)
+ ULONG _res1 :9; //
+ ULONG Activity :1; // (RO) in use
+ ULONG Mask :1; // mask interrupt
+} MPIC_IPIVP;
+
+typedef struct _MPIGLOB_IPI {
+ MPIC_IPIVP VectorPriority;
+ UCHAR _fill0[0xc];
+} MPIGLOB_IPI;
+
+typedef struct _MPIGLOB_TIMER {
+
+ ULONG CurrentCount :31; //
+ ULONG Toggle :1; //
+
+ UCHAR _fill0[0xc];
+
+ ULONG BaseCount :31; //
+ ULONG CountInhibit :1; //
+
+ UCHAR _fill1[0xc];
+
+ ULONG Vector :8; // Interrupt Vector
+ ULONG _res0 :8; //
+ ULONG Priority :4; // Interrupt Priority
+ ULONG _res1 :10; //
+ ULONG Activity :1; // (RO) in use
+ ULONG Mask :1; // mask interrupt
+
+ UCHAR _fill2[0xc];
+
+ ULONG SelectProcessor; // destination processor (bit mask)
+
+ UCHAR _fill3[0xc];
+
+} MPIGLOB_TIMER;
+
+
+#define MPIC_SUPPORTED_IPI 4
+
+typedef struct _MPIC_GLOBAL_REGS {
+
+ MPICGLOB_FEATURE_REPORT FeatureReport; // offset 0x00
+
+ UCHAR _fill0[0x20-(0x00+sizeof(MPICGLOB_FEATURE_REPORT))];
+
+ MPICGLOB_CONFIG Configuration; // offset 0x20
+
+ UCHAR _fill1[0x80-(0x20+sizeof(MPICGLOB_CONFIG))];
+
+ MPICGLOB_VENDOR_ID VendorId; // offset 0x80
+
+ UCHAR _fill2[0x90-(0x80+sizeof(MPICGLOB_VENDOR_ID))];
+
+ MPICGLOB_PROCESSOR_INIT ProcessorInit; // offset 0x90
+
+ UCHAR _fill3[0xa0-(0x90+sizeof(MPICGLOB_PROCESSOR_INIT))];
+
+ MPIGLOB_IPI Ipi[MPIC_SUPPORTED_IPI]; // offset 0xa0
+
+ UCHAR _fill4[0xf0-(0xa0+(sizeof(MPIGLOB_IPI)*4))];
+
+ ULONG TimerFreq; // offset 0xf0
+
+ UCHAR _fill5[0x100-(0xf0+sizeof(ULONG))];
+
+ MPIGLOB_TIMER Timer[4];
+
+} MPIC_GLOBAL_REGS, *PMPIC_GLOBAL_REGS;
+
+#define MPIC_GLOBAL_OFFSET 0x01000
+
+
+//
+// Define MPIC Interrupt Source Configuration Registers
+//
+
+typedef struct {
+ ULONG Vector :8; // Interrupt Vector
+ ULONG _res0 :8; //
+ ULONG Priority:4; // Interrupt Priority
+ ULONG _res1 :1; //
+ ULONG _res2 :1; //
+ ULONG Sense :1; // 0 = edge sensitive, 1 = level sens.
+ ULONG Polarity:1; // 0 = active low, 1 = active high
+ ULONG _res3 :6; //
+ ULONG Activity:1; // (RO) in use
+ ULONG Mask :1; // mask interrupt
+} MPIC_ISVP;
+
+#define MPIC_SUPPORTED_INTS 16
+#define HYDRA_MPIC_SUPPORTED_INTS 20
+
+typedef struct _MPIC_INTERRUPT_SOURCE_REGS {
+
+ struct {
+
+ MPIC_ISVP VectorPriority;
+
+ UCHAR _fill0[0xc];
+
+ ULONG SelectProcessor; // destination processor (bit mask)
+
+ UCHAR _fill1[0xc];
+
+ } Int[1]; // really xxx_MPIC_SUPPORTED_INTS
+
+} MPIC_INTERRUPT_SOURCE_REGS, *PMPIC_INTERRUPT_SOURCE_REGS;
+
+#define MPIC_INTERRUPT_SOURCE_OFFSET 0x10000
+
+
+//
+// Define MPIC Per Processor Registers
+//
+
+typedef struct _MPIC_PER_PROCESSOR_REGS {
+
+ UCHAR _fill0[0x40];
+
+ struct {
+ ULONG SelectProcessor;
+ UCHAR _fill0[0xc];
+ } Ipi[MPIC_SUPPORTED_IPI];
+
+ ULONG TaskPriority; // current processor priority
+
+ UCHAR _fill1[0x1c];
+
+ ULONG Acknowledge; // (RO) interrupt acknowledge
+
+ UCHAR _fill2[0xc];
+
+ ULONG EndOfInterrupt;
+
+} MPIC_PER_PROCESSOR_REGS, *PMPIC_PER_PROCESSOR_REGS;
+
+#define MPIC_PROCESSOR_0_OFFSET 0x20000
+#define MPIC_PROCESSOR_REGS_SIZE 0x1000
+
+#define MPIC_MAX_PRIORITY 15
+
+//
+// Define MPIC2 and MPIC2A PCI Vendor and Device IDs
+// Note: redifine MPIC2A below when the real device id is known (plj).
+//
+
+#define MPIC2_PCI_VENDOR_DEVICE 0xffff1014
+#define MPIC2A_PCI_VENDOR_DEVICE 0x00461014
+#define HYDRA_PCI_VENDOR_DEVICE 0x000e106b
+
+extern PMPIC_GLOBAL_REGS HalpMpicGlobal;
+extern PMPIC_INTERRUPT_SOURCE_REGS HalpMpicInterruptSource;
+
+//
+// The function MPIC_SYNC() should be called to ensure writes to
+// the MPIC complete prior to initiating the next operation.
+//
+
+#define MPIC_SYNC() __builtin_eieio()
+
+//
+// Wait for activitiy bit in Interrupt Source n to clear.
+//
+// The MPIC_SYNC in the following is to FORCE MCL to treat the
+// field as volatile as no amount of changing the declaration
+// seems to cause it to reload the field before comparing it
+// again, and again, and again, ...
+//
+
+#define MPIC_WAIT_SOURCE(i) \
+ while((volatile)(HalpMpicInterruptSource->Int[i].VectorPriority.Activity)){\
+ MPIC_SYNC(); \
+ }
+
+//
+// Wait for activity bit to clear in IPI source n.
+//
+
+#define MPIC_WAIT_IPI_SOURCE(i) \
+ while ((volatile)(HalpMpicGlobal->Ipi[i].VectorPriority.Activity)) { \
+ MPIC_SYNC(); \
+ }
+
+//
+// Define MPIC IPI vectors.
+//
+
+#define MPIC_IPI0_VECTOR 36
+#define MPIC_IPI1_VECTOR 37
+#define MPIC_IPI2_VECTOR 38
+#define MPIC_IPI3_VECTOR 39
+
+//
+// Base MPIC device vector, and MAX MPIC vector.
+// Note these are s/w defined and have nothing to do with the MPIC2 h/w.
+//
+
+#define MPIC_BASE_VECTOR 16
+#define MPIC_8259_VECTOR 16
+
+// For use in interrupt routing tables.
+#define NOT_MPIC 0xFF
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PVOID ServiceContext,
+ PVOID TrapFrame
+ );
+
+
+NTSTATUS
+HalpGetPciMpicIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ );
+
+VOID
+HalpEnableMpicInterrupt(
+ IN ULONG Vector
+ );
+
+
+VOID
+HalpDisableMpicInterrupt(
+ IN ULONG Vector
+ );
+
+
+#endif
diff --git a/private/ntos/nthals/halppc/ppc/pxmpint.c b/private/ntos/nthals/halppc/ppc/pxmpint.c
new file mode 100644
index 000000000..828bd49ad
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxmpint.c
@@ -0,0 +1,323 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxmpint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a Power PC.
+
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge
+
+ Removed internal interrupt support
+ Changed irql mapping
+ Removed internal bus support
+ Removed EISA, added PCI, PCMCIA, and ISA bus support
+
+ Steve Johns
+ Changed to support Timer 1 as profile interrupt
+ Added HalAcknowledgeIpi
+
+ Peter Johnston
+ Added support for MPIC interrupt controller
+
+ Chris Karamatas
+ Fixed Hal(Dis/En)ableSystemInterrupt function
+
+ Jake Oshins
+ Renamed to pxmpint.c from pxsysint.c
+
+--*/
+
+#include "halp.h"
+#include "pxmp.h"
+#include "pxmpic2.h"
+
+#if _MSC_VER >= 1000
+
+//
+// VC++ doesn't have the same intrinsics as MCL.
+//
+// Although the MSR is not strictly a SPR, the compiler recognizes
+// all ones (~0) as being the MSR and emits the appropriate code.
+//
+
+#define __builtin_set_msr(x) __sregister_set(_PPC_MSR_,x)
+
+#endif
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ if (Vector >= DEVICE_VECTORS ) {
+ if ( Vector < DEVICE_VECTORS + MPIC_BASE_VECTOR ) {
+
+ HalpDisableSioInterrupt(Vector);
+
+ } else if ( Vector <= DEVICE_VECTORS + MPIC_MAX_VECTOR ) {
+
+ HalpDisableMpicInterrupt(Vector);
+ }
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ KINTERRUPT_MODE TranslatedInterruptMode;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ if ( Vector >= DEVICE_VECTORS ) {
+ if ( Vector < DEVICE_VECTORS + MPIC_BASE_VECTOR ) {
+
+ //
+ // It's an 8259 vector.
+ //
+ // Get translated interrupt mode
+ //
+
+
+ TranslatedInterruptMode = HalpGetInterruptMode(Vector,
+ Irql,
+ InterruptMode);
+
+
+ HalpEnableSioInterrupt(Vector, TranslatedInterruptMode);
+
+ } else if ( Vector <= DEVICE_VECTORS + MPIC_MAX_VECTOR ) {
+
+ HalpEnableMpicInterrupt(Vector);
+ }
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(_MP_PPC_)
+
+ extern ULONG Mpic2IpiBugFix;
+ extern ULONG HalpPhysicalIpiMask[];
+ ULONG BugFix = Mpic2IpiBugFix;
+ ULONG PhysicalMask = 0;
+ PULONG PhysicalIpiMask = HalpPhysicalIpiMask;
+ ULONG OldMsr = __builtin_get_msr();
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+
+ __builtin_set_msr(OldMsr & 0xffff7fff); // Disable Interrupts
+
+ //
+ // Mask is a mask of logical CPUs. Convert it to a mask of
+ // Physical CPUs so the IPI requests will be distributed
+ // properly.
+ //
+
+ do {
+ if ( Mask & 1 ) {
+ PhysicalMask |= *PhysicalIpiMask;
+ }
+ PhysicalIpiMask++;
+ Mask >>= 1;
+ } while ( Mask );
+
+ //
+ // Send the IPI interrupt(s).
+ //
+
+ HALPCR->MpicProcessorBase->Ipi[0 ^ BugFix].SelectProcessor = PhysicalMask;
+
+ __builtin_set_msr(OldMsr); // Restore previous interrupt
+ // setting.
+#endif
+
+ return;
+}
+
+BOOLEAN
+HalAcknowledgeIpi (VOID)
+
+/*++
+
+Routine Description:
+
+ This routine aknowledges an interprocessor interrupt on a set of
+ processors.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if the IPI is valid; otherwise FALSE is returned.
+
+--*/
+
+{
+ return (TRUE);
+}
+
+BOOLEAN
+HalpHandleIpi(
+ IN PVOID Unused0,
+ IN PVOID Unused1,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an Inter-Processor Interrupt
+ being received by this processor. It passes the request onto the
+ kernel.
+
+Arguments:
+
+ Unused0 - Not used.
+ Unused1 - Not used.
+ TrapFrame - Volatile context at time interrupt occured.
+
+Return Value:
+
+ Returns TRUE (this routine always succeeds).
+
+--*/
+
+{
+
+#if defined(_MP_PPC_)
+
+ KeIpiInterrupt(TrapFrame);
+
+#endif
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxnatsup.c b/private/ntos/nthals/halppc/ppc/pxnatsup.c
new file mode 100644
index 000000000..3da4d7182
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxnatsup.c
@@ -0,0 +1,80 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxnatsup.c
+
+Abstract:
+
+ The module provides the National SuperIO (PC87311) support for Power PC.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+
+
+--*/
+
+#include "halp.h"
+#include "pxnatsup.h"
+
+
+
+BOOLEAN
+HalpInitSuperIo (
+ VOID
+ )
+
+
+{
+
+ //
+ // Initialize the National SuperIO chip
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoIndexRegister,
+ FER_ACCESS);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoDataRegister,
+ FER_PARALLEL_PORT_ENABLE |
+ FER_UART1_ENABLE |
+ FER_UART2_ENABLE |
+ FER_FDC_ENABLE |
+ FER_IDE);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoIndexRegister,
+ FAR_ACCESS);
+
+ //
+ // LPT2 - irq5, uart1-com1, UART2-com2,
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoDataRegister,
+ 0x10);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoIndexRegister,
+ PTR_ACCESS);
+
+ WRITE_REGISTER_UCHAR(
+ &((PNAT_SUPERIO_CONTROL)HalpIoControlBase)->SuperIoDataRegister,
+ 0x04);
+
+ return TRUE;
+
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxnatsup.h b/private/ntos/nthals/halppc/ppc/pxnatsup.h
new file mode 100644
index 000000000..0820d65fd
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxnatsup.h
@@ -0,0 +1,57 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxnatsup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the
+ National (PC87311) SuperIO chip set.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+//
+// SuperIO configuration registers
+//
+
+//
+//index register select
+//
+
+#define FER_ACCESS 0x00
+#define FAR_ACCESS 0x01
+#define PTR_ACCESS 0x02
+
+//
+//FER register bit fields
+//
+
+#define FER_PARALLEL_PORT_ENABLE 0x01
+#define FER_UART1_ENABLE 0x02
+#define FER_UART2_ENABLE 0x04
+#define FER_FDC_ENABLE 0x08
+#define FER_FDD 0x10
+#define FER_FDC_MODE 0x20
+#define FER_IDE 0x30
+#define FER_IDE_MODE 0x40
+
+//
+// Lay the supio control registers onto the I/O control space
+//
+
+typedef struct _NAT_SUPERIO_CONTROL {
+ UCHAR Reserved1[0x398];
+ UCHAR SuperIoIndexRegister; // Offset 0x398
+ UCHAR SuperIoDataRegister; // Offset 0x399
+} NAT_SUPERIO_CONTROL, *PNAT_SUPERIO_CONTROL;
diff --git a/private/ntos/nthals/halppc/ppc/pxp91.c b/private/ntos/nthals/halppc/ppc/pxp91.c
new file mode 100644
index 000000000..0b879b37e
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxp91.c
@@ -0,0 +1,1334 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+
+Module Name:
+
+pxp91.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a PowerPC system using a Weitek P9100 video adapter.
+
+Author:
+
+ Jake Oshins
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pxP91.h"
+#include "pci.h"
+#include "pcip.h"
+
+#define MAP_PCI_CONFIG_PHASE0 \
+if (HalpInitPhase == 0) HalpPhase0MapBusConfigSpace()
+
+#define UNMAP_PCI_CONFIG_PHASE0 \
+if (HalpInitPhase == 0) HalpPhase0UnMapBusConfigSpace()
+
+#define MAP_FRAMEBUF_PHASE0 \
+if (HalpInitPhase == 0) HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(HalpP9FramebufPhysicalAddress.LowPart, 0x200000)
+
+#define UNMAP_FRAMEBUF_PHASE0 \
+if (HalpInitPhase == 0) KePhase0DeleteIoMap(HalpP9FramebufPhysicalAddress.LowPart, 0x200000)
+
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayCharacterP91 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterP91(
+ IN PUCHAR Glyph
+ );
+
+VOID
+HalpP91RelinquishDisplayOwnership();
+
+VOID
+SetupVideoBackend();
+
+VOID
+WriteIBM525(
+ USHORT index,
+ UCHAR value
+ );
+
+BOOLEAN
+IBM525SetMode();
+
+VOID
+P91_WriteTiming();
+
+VOID
+P91_SysConf();
+
+VOID
+CalcP9100MemConfig ();
+
+VOID
+ProgramClockSynth(
+ USHORT usFrequency,
+ BOOLEAN bSetMemclk,
+ BOOLEAN bUseClockDoubler
+ );
+
+VOID
+Write525PLL(
+ USHORT usFreq
+ );
+
+VOID P91WriteICD(
+ ULONG data
+ );
+
+VOID
+Write9100FreqSel(
+ ULONG cs
+ );
+
+VOID
+WriteP9ConfigRegister(
+ UCHAR index,
+ UCHAR value
+ );
+
+VOID
+VLEnableP91();
+
+UCHAR
+ReadP9ConfigRegister(
+ UCHAR index
+ );
+
+ULONG
+Read9100FreqSel();
+
+VOID
+IBM525PointerOff();
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+typedef
+VOID
+(*PHALP_DISPLAY_CHARACTER) (
+ UCHAR
+ );
+
+//
+// Define static data.
+//
+extern BOOLEAN HalpDisplayOwnedByHal;
+extern ULONG HalpPciMaxSlots;
+extern ULONG HalpInitPhase;
+
+
+extern volatile PUCHAR HalpVideoMemoryBase;
+extern volatile PUCHAR HalpVideoCoprocBase;
+
+extern PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup;
+extern PHALP_DISPLAY_CHARACTER HalpDisplayCharacter;
+
+//
+// Define OEM font variables.
+//
+
+extern USHORT HalpBytesPerRow;
+extern USHORT HalpCharacterHeight;
+extern USHORT HalpCharacterWidth;
+extern ULONG HalpDisplayText;
+extern ULONG HalpDisplayWidth;
+extern ULONG HalpScrollLength;
+extern ULONG HalpScrollLine;
+
+
+//
+// Define display variables.
+//
+extern ULONG HalpColumn;
+extern ULONG HalpRow;
+extern ULONG HalpHorizontalResolution;
+extern ULONG HalpVerticalResolution;
+
+extern POEM_FONT_FILE_HEADER HalpFontHeader;
+
+
+//
+// PCI slot number
+//
+UCHAR HalpP9SlotNumber;
+UCHAR HalpP9BusNumber;
+
+//
+// Framebuffer physical address
+//
+PHYSICAL_ADDRESS HalpP9FramebufPhysicalAddress = {0,0};
+
+//
+// Coprocessor physical address
+PHYSICAL_ADDRESS HalpP9CoprocPhysicalAddress = {0,0};
+
+
+
+VOID
+HalpP91RelinquishDisplayOwnership()
+/*++
+
+Routine Description:
+
+ This routine unmaps the BATs that allow us to function in Phase0.
+ It is called when the video miniport takes ownership of the screen.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ASSERT(HalpVideoMemoryBase);
+ ASSERT(HalpVideoCoprocBase);
+ ASSERT(HalpP9FramebufPhysicalAddress.LowPart);
+ ASSERT(HalpP9CoprocPhysicalAddress.LowPart);
+ //
+ // Delete the framebuffer
+ //
+ KePhase0DeleteIoMap(HalpP9FramebufPhysicalAddress.LowPart,
+ 0x200000);
+ HalpVideoMemoryBase = NULL;
+
+ //
+ // Unmap the control registers
+ //
+ KePhase0DeleteIoMap(HalpP9CoprocPhysicalAddress.LowPart,
+ 0x10000);
+ HalpVideoCoprocBase = NULL;
+}
+
+VOID
+HalpDisplayPpcP91Setup (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the Weitek P9100 display contoller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PULONG buffer;
+ ULONG limit, index;
+ volatile ULONG throwaway = 0;
+ ULONG i, j;
+ RGB colors[255];
+ UCHAR *pData, ucpdata;
+ ULONG pdata;
+ ULONG curDACIndex;
+ ULONG value;
+ PHYSICAL_ADDRESS busrelative;
+
+
+ if (HalpInitPhase == 0) {
+ // Discover the PCI slot number, coprocessor physical address, and
+ // frame buffer physical address
+
+ if(HalpPhase0MapBusConfigSpace () == FALSE){
+ ASSERT(FALSE);
+ }
+ else
+ {
+ //
+ // In the case that there are two P9100's in the system, this
+ // will identify the one that occupies the lowest PCI slot number.
+ //
+
+ HalpP9BusNumber=0;
+ HalpP9SlotNumber=0;
+
+ for (j=0; j < HalpPciMaxBuses; j++) {
+
+ for (i=0; i<HalpPciMaxSlots; i++) {
+
+ HalpPhase0GetPciDataByOffset (j, i, &value, 0x0, 4);
+
+ if(value == ((P91_DEV_ID_WEITEK_PCI << 16) | P91_VEN_ID_WEITEK_PCI)){
+ HalpP9SlotNumber = (UCHAR)i;
+ HalpP9BusNumber = (UCHAR)j;
+ }
+
+ }
+
+ }
+
+ if(i==HalpPciMaxSlots && HalpP9SlotNumber==0){
+ ASSERT(FALSE);
+ return;
+ }
+ }
+
+
+ HalpPhase0GetPciDataByOffset (HalpP9BusNumber,
+ HalpP9SlotNumber,
+ &busrelative.LowPart,
+ 0x10,
+ 4);
+
+ HalpPhase0UnMapBusConfigSpace();
+
+ HalpP9CoprocPhysicalAddress.LowPart = PCI_MEMORY_PHYSICAL_BASE + busrelative.LowPart;
+
+ HalpP9FramebufPhysicalAddress.LowPart = HalpP9CoprocPhysicalAddress.LowPart +
+ P9100_FRAMEBUF_OFFSET;
+
+
+ //
+ // Now map everything with BATs
+ //
+ if (HalpVideoMemoryBase == NULL) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(HalpP9FramebufPhysicalAddress.LowPart,
+ 0x200000); // 2 MB
+ }
+
+
+ if (HalpVideoCoprocBase == NULL) {
+ HalpVideoCoprocBase = (PUCHAR)KePhase0MapIo(HalpP9CoprocPhysicalAddress.LowPart,
+ 0x100000); //1MB
+ // I'm pretty sure this covers all the registers we need to hit from
+ // the HAL.
+
+ }
+ }
+ else {
+ //
+ // Map video memory space via pte's
+ //
+
+ // NT may have moved the video frame buffer since we last used it...
+ HalGetBusDataByOffset (PCIConfiguration,
+ HalpP9BusNumber,
+ HalpP9SlotNumber,
+ &busrelative.LowPart,
+ 0x10,
+ 4);
+
+ HalpP9CoprocPhysicalAddress.LowPart = PCI_MEMORY_PHYSICAL_BASE + busrelative.LowPart;
+
+ HalpP9FramebufPhysicalAddress.LowPart = HalpP9CoprocPhysicalAddress.LowPart +
+ P9100_FRAMEBUF_OFFSET;
+
+
+ ASSERT((HalpP9CoprocPhysicalAddress.LowPart != (ULONG)NULL));
+ ASSERT((HalpP9FramebufPhysicalAddress.LowPart != (ULONG)NULL));
+ ASSERT((HalpP9SlotNumber != 0));
+
+ HalpVideoMemoryBase = MmMapIoSpace(HalpP9FramebufPhysicalAddress,
+ 0x200000,
+ FALSE);
+ HalpVideoCoprocBase = MmMapIoSpace(HalpP9CoprocPhysicalAddress,
+ 0x10000,
+ FALSE);
+ }
+
+
+
+ HalpHorizontalResolution = 640;
+ HalpVerticalResolution = 480;
+
+ //
+ // Set the video mode to 640x480, 8bits, palette enabled, 60Hz
+ //
+ VLEnableP91();
+
+ // IBM_JACOBO
+ // The following section sets the palette so that the HAL writes
+ // white characters on a blue background. It insures this by setting
+ // half of the 256-color palette to blue and the other half to white.
+
+
+ //
+ // ... and now for a little black magic lifted from the ROS/IPL code
+
+ throwaway += P9_RD_REG(P91_PU_CONFIG);
+ throwaway += P9_WR_FB(0x00000200); /* hw bug */
+ P9_WR_REG(P9100_PalCurRamW ,0x00000000); /* point at beginning of table */
+ throwaway += P9_RD_REG(P91_PU_CONFIG); /* ensure 5 clocks between DAC accesses */
+
+ // Create a 256 color palette. The top half of the colors should all be white
+ // and the bottom half should all be blue.
+ for (i = 0; i < 128; i++) {
+ colors[i].red = 0;
+ colors[i].green = 0;
+ colors[i].blue = (char)0x7F;
+ }
+ for (i = 128; i < 256; i++) {
+ colors[i].red = (char)0xFF;
+ colors[i].green = (char)0xFF;
+ colors[i].blue = (char)0xFF;
+ }
+
+ pData = (char*)colors;
+
+ for (curDACIndex = 0;curDACIndex<(256*3);curDACIndex++){
+ ucpdata = *pData++;
+ pdata = (ULONG) ucpdata;
+ throwaway += P9_WR_FB(0x00000200); /* hw bug */
+ P9_WR_REG(P9100_PalData,(pdata<< 24 | pdata<<16 | pdata << 8 | pdata));
+ throwaway += P9_RD_REG(P91_PU_CONFIG); /* ensure 5 clocks between DAC accesses */
+ }
+
+ throwaway += P9_WR_FB(0x00000200); /* hw bug */
+ P9_WR_REG(P9100_PalCurRamR ,0x00000000);
+ throwaway += P9_RD_REG(P91_PU_CONFIG); /* ensure 5 clocks between DAC accesses */
+ /* Wait for Weitek controller not busy */
+
+
+
+ //IBMLAN Use font file from OS Loader
+ //
+ // Compute display variables using using HalpFontHeader which is
+ // initialized in HalpInitializeDisplay().
+ //
+ // N.B. The font information suppled by the OS Loader is used during phase
+ // 0 initialization. During phase 1 initialization, a pool buffer is
+ // allocated and the font information is copied from the OS Loader
+ // heap into pool.
+ //
+ // This means that font information is taken from the file VGAOEM.FON,
+ // which is put in memory by the OSLOADER.
+ //
+ //FontHeader = (POEM_FONT_FILE_HEADER)LoaderBlock->OemFontFile;
+ //HalpFontHeader = FontHeader;
+ HalpBytesPerRow = (HalpFontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = HalpFontHeader->PixelHeight;
+ HalpCharacterWidth = HalpFontHeader->PixelWidth;
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpVerticalResolution / HalpCharacterHeight;
+
+ HalpScrollLine =
+ HalpHorizontalResolution * HalpCharacterHeight;
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ HalpDisplayWidth =
+ HalpHorizontalResolution / HalpCharacterWidth;
+
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ buffer = (PULONG)HalpVideoMemoryBase;
+ limit = (HalpHorizontalResolution *
+ HalpVerticalResolution) / sizeof(ULONG);
+
+ for (index = 0; index < limit; index += 1) {
+ *buffer++ = 0x01010101;
+ }
+
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+
+} //end of HalpDisplayPpcP91Setup
+
+VOID
+HalpDisplayCharacterP91 (
+ IN UCHAR Character
+ )
+/*++
+
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encountered, the frame buffer is
+ scrolled. If characters extend below the end of line, they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ PUCHAR Source;
+ ULONG Index;
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+
+ } else {
+ //RtlMoveMemory((PVOID)P91_VIDEO_MEMORY_BASE,
+ // (PVOID)(P91_VIDEO_MEMORY_BASE + HalpScrollLineP9),
+ // HalpScrollLengthP9);
+
+ // Scroll up one line
+ Destination = HalpVideoMemoryBase;
+ Source = (PUCHAR) HalpVideoMemoryBase + HalpScrollLine;
+ for (Index = 0; Index < HalpScrollLength; Index++) {
+ *Destination++ = *Source++;
+ }
+ // Blue the bottom line
+ Destination = HalpVideoMemoryBase + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ } else {
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacterP91((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+VOID
+HalpOutputCharacterP91(
+ IN PUCHAR Glyph
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the current x cursor position is at the end of the
+ line, then a newline is displayed before the specified character.
+
+ This awful little chunk of code reads a font in the format that it
+ is stored in VGAOEM.FON and draws it onto the screen by iterating
+ over the pixels in the position of the cursor.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ ULONG FontValue;
+ ULONG tmp;
+ ULONG I;
+ ULONG J;
+
+ //
+ // If the current x cursor position is at the end of the line, then
+ // output a line feed before displaying the character.
+ //
+
+ if (HalpColumn == HalpDisplayWidth) {
+ HalpDisplayCharacterP91('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(HalpVideoMemoryBase +
+ (HalpRow * HalpScrollLine) + (HalpColumn * HalpCharacterWidth));
+
+ for (I = 0; I < HalpCharacterHeight; I += 1) {
+ FontValue = 0;
+ for (J = 0; J < HalpBytesPerRow; J += 1) {
+ FontValue |= *(Glyph + (J * HalpCharacterHeight)) << (24 - (J * 8));
+ }
+
+ Glyph += 1;
+ for (J = 0; J < HalpCharacterWidth ; J += 1) {
+ if (FontValue >> 31 != 0) {
+ *Destination = 0xFF; //Make this pixel white
+ } else {
+ *Destination = 0x00; //Make it black
+ }
+
+ Destination++;
+ //*Destination++ = (FontValue >> 31) ^ 1;
+ FontValue <<= 1;
+ }
+
+ Destination +=
+ (HalpHorizontalResolution - HalpCharacterWidth);
+ }
+
+ HalpColumn += 1;
+ return;
+}
+
+
+
+VOID
+VLEnableP91()
+
+/*++
+
+ Routine Description:
+
+ Perform the OEM specific tasks necessary to enable P9100 Video. These
+ include memory mapping, setting the sync polarities, and enabling the
+ P9100 video output.
+
+ This has been lifted right out of the video miniport driver weitekp9.sys.
+ I cut it down to the point where it only does what is absolutely
+ necessary to for setting the screen to 640x480x8bit at 60Hz. -- Jake
+
+ Arguments:
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ //USHORT usMemClkInUse;
+
+ //
+ // Enable native mode to: No RAMDAC shadowing, memory & I/O enabled.
+ //
+
+ UNMAP_FRAMEBUF_PHASE0;
+ MAP_PCI_CONFIG_PHASE0;
+
+ WriteP9ConfigRegister(P91_CONFIG_MODE, 0); // Native mode
+
+ UNMAP_PCI_CONFIG_PHASE0;
+ MAP_FRAMEBUF_PHASE0;
+
+ // Program MEMCLK
+
+ ProgramClockSynth(0x136f, TRUE, FALSE);
+
+ //
+ // Next setup the pixel clock frequency. We have to handle potential
+ // clock multiplicaiton by the RAMDAC. On the BT485 if the dotfreq
+ // is greater than the maximum clock freq then we will adjust the
+ // dot frequency to program the clock with.
+ //
+
+ //
+ // Program Pix clk
+ //
+
+ ProgramClockSynth(0x9d5, FALSE, TRUE);
+
+ //
+ // Determine size of Vram (ulFrameBufferSize)...
+ //
+
+ //
+ // For some reason we are calling P91SizeVideoMemory here, even
+ // though we've already done this in HwFindAdapter. In order
+ // to free the frame buffer, I have to remove this seemingly
+ // redundant call. Sizing the memory, did have the side effect
+ // of setting one of the coprocessor registers however, so I'll
+ // add code to do that here.
+ //
+
+
+ // Assume that we are working with a 2MB card for now...
+
+ //
+ // this simulates the side-effect of P91SizeVideoMemory
+ //
+ P9_WR_REG(P91_MEM_CONFIG, 0x00000005);
+
+
+
+ //
+ // Init system config & clipping registers...
+ //
+
+ P91_SysConf();
+
+ // Since I have deleted the device extention, all that was left
+ // of CalcP9100MemConfig was this call. It is probably just
+ // a side effect, but I am preserving it. -- Jake
+ ProgramClockSynth(4, TRUE, FALSE);
+
+ //
+ // Load the video timing registers...
+ //
+
+ P91_WriteTiming();
+
+ //
+ // Setup the RAMDAC to the current mode...
+ //
+
+ IBM525PointerOff();
+
+ IBM525SetMode();
+
+ //
+ // Setup MEMCONFIG and SRTCTL regs
+ //
+
+ SetupVideoBackend();
+
+ return;
+
+} // End of VLEnableP91()
+
+VOID
+SetupVideoBackend()
+{
+ // I have limited this function to write the values necessary for
+ // 640x480x256.
+ // This is taken from the miniport function of the same name. Look
+ // there for a complete explanation. -- Jake
+
+ P9_WR_REG(P91_MEM_CONFIG, 0xc818007d);
+ P9_WR_REG(P91_SRTCTL, 0x1a3);
+ P9_WR_REG(P91_SRTCTL2, P91_HSYNC_LOW_TRUE | P91_VSYNC_LOW_TRUE);
+
+
+ return;
+
+} // End of SetupVideoBackend()
+
+
+BOOLEAN
+IBM525SetMode()
+{
+ // This function is a simplified version of the one in the
+ // miniport. Look there for a good explanation -- Jake.
+
+ //
+ // Set the pixel read mask.
+ //
+
+ P9_WR_BYTE_REG(P9100_PIXELMASK, 0xff);
+
+ //
+ // Select the fast DAC slew rate for the sharpest pixels
+ //
+
+ WriteIBM525(RGB525_DAC_OPER, 0x02);
+
+ //
+ // Enable the 64-bit VRAM pixel port
+ //
+
+ WriteIBM525(RGB525_MISC_CTL1, 0x01);
+
+ WriteIBM525(RGB525_MISC_CTL2, 0x45);
+
+ //
+ // Select 8bpp
+ //
+ WriteIBM525(RGB525_MISC_CLOCK_CTL, 0x27);
+ WriteIBM525(RGB525_PIXEL_FORMAT, 0x03);
+ WriteIBM525(RGB525_8BPP_CTL, 0x00);
+
+ return(TRUE);
+}
+
+
+VOID
+P91_WriteTiming()
+{
+ ULONG ulValueRead, ulValueWritten;
+ ULONG ulHRZSR;
+ ULONG ulHRZBR;
+ ULONG ulHRZBF;
+ ULONG ulHRZT;
+
+
+ // These magic numbers come from watching the miniport set the screen to
+ // 640x480x256. -- Jake
+
+ ulHRZSR = 0xa;
+
+ ulHRZBR = 0xe;
+
+ ulHRZBF = 0x5e;
+
+ ulHRZT = 0x63;
+
+ //
+ // Write to the video timing registers
+ //
+
+ do
+ {
+ P9_WR_REG(P91_HRZSR, ulHRZSR);
+ ulValueRead = (ULONG) P9_RD_REG(P91_HRZSR);
+ } while (ulValueRead != ulHRZSR);
+
+ do
+ {
+ P9_WR_REG(P91_HRZBR, ulHRZBR);
+ ulValueRead = (ULONG) P9_RD_REG(P91_HRZBR);
+ } while (ulValueRead != ulHRZBR);
+
+ do
+ {
+ P9_WR_REG(P91_HRZBF, ulHRZBF);
+ ulValueRead = (ULONG) P9_RD_REG(P91_HRZBF);
+ } while (ulValueRead != ulHRZBF);
+
+ do
+ {
+ P9_WR_REG(P91_HRZT, ulHRZT);
+ ulValueRead = (ULONG) P9_RD_REG(P91_HRZT);
+ } while (ulValueRead != ulHRZT);
+
+ ulValueWritten = (ULONG) 4;
+
+ do
+ {
+ P9_WR_REG(P91_VRTSR, ulValueWritten);
+ ulValueRead = (ULONG) P9_RD_REG(P91_VRTSR);
+ } while (ulValueRead != ulValueWritten);
+
+ ulValueWritten = (ULONG) 0x1c;
+ do
+ {
+ P9_WR_REG(P91_VRTBR, ulValueWritten);
+ ulValueRead = (ULONG) P9_RD_REG(P91_VRTBR);
+ } while (ulValueRead != ulValueWritten);
+
+ ulValueWritten = (ULONG) 0x1fc;
+ do
+ {
+ P9_WR_REG(P91_VRTBF, ulValueWritten);
+ ulValueRead = (ULONG) P9_RD_REG(P91_VRTBF);
+ } while (ulValueRead != ulValueWritten);
+
+ ulValueWritten = (ULONG) 0x20d;
+ do
+ {
+ P9_WR_REG(P91_VRTT, ulValueWritten);
+ ulValueRead = (ULONG) P9_RD_REG(P91_VRTT);
+ } while (ulValueRead != ulValueWritten);
+
+ return;
+
+} // End of P91_WriteTimings()
+
+
+
+VOID
+P91_SysConf()
+{
+ // This function taken and simplified from the miniport.
+
+ P9_WR_REG(P91_SYSCONFIG, 0x8563000); // send data to the register
+
+ //
+ // There are two sets of clipping registers. The first takes the
+ // horizontal diemnsion in pixels and the vertical dimension in
+ // scanlines.
+ //
+ P9_WR_REG(P91_DE_P_W_MIN, 0L);
+ P9_WR_REG(P91_DE_P_W_MAX, 0x27f1998);
+
+ //
+ // The second set takes the horizontal dimension in bytes and the
+ // vertical dimension in scanlines.
+ //
+ P9_WR_REG(P91_DE_B_W_MIN, 0L);
+ P9_WR_REG(P91_DE_B_W_MAX, 0x27f1998);
+
+ return;
+
+} // End of P91_SysConf()
+
+
+
+VOID
+ProgramClockSynth(
+ USHORT usFrequency,
+ BOOLEAN bSetMemclk,
+ BOOLEAN bUseClockDoubler
+ )
+
+{
+ ULONG clockstring; // IC designs pixel dot rate shift value
+
+ if ((!bSetMemclk))
+ {
+
+ Write525PLL(usFrequency);
+
+ //
+ // Set reference frequency to 5000 Mhz...
+ //
+
+ usFrequency = 5000;
+ }
+ else
+ {
+ usFrequency = 4975;
+ }
+
+
+ UNMAP_FRAMEBUF_PHASE0;
+ MAP_PCI_CONFIG_PHASE0;
+
+ if (bSetMemclk)
+ {
+ clockstring = 0x16fc91;
+ P91WriteICD(clockstring | IC_MREG); // Memclk
+ }
+ else
+ {
+ clockstring = 0x1c841;
+ P91WriteICD(clockstring | IC_REG2); // Pixclk
+ }
+
+ //
+ // Select custom frequency
+ //
+
+ Write9100FreqSel(ICD2061_EXTSEL9100);
+
+ UNMAP_PCI_CONFIG_PHASE0;
+ MAP_FRAMEBUF_PHASE0;
+
+
+
+} // End of ProgramClockSynth()
+
+
+
+VOID
+WriteIBM525(
+ USHORT index,
+ UCHAR value
+ )
+{
+ IBM525_WR_DAC(P9100_IBM525_INDEX_LOW, (UCHAR) (index & 0x00FF));
+ IBM525_WR_DAC(P9100_IBM525_INDEX_HIGH, (UCHAR) ((index & 0xFF00) >> 8));
+ IBM525_WR_DAC(P9100_IBM525_INDEX_DATA, (UCHAR) value);
+ (void) P9_RD_REG(P91_MEM_CONFIG); // Needed for timinig...
+
+} // End of WriteIBM525()
+
+UCHAR
+ReadIBM525(
+ USHORT index
+ )
+
+{
+ UCHAR j;
+
+ IBM525_WR_DAC(P9100_IBM525_INDEX_LOW, (UCHAR) (index & 0x00FF));
+ IBM525_WR_DAC(P9100_IBM525_INDEX_HIGH, (UCHAR) ((index & 0xFF00) >> 8));
+
+ IBM525_RD_DAC(P9100_IBM525_INDEX_DATA, j);
+
+ return(j);
+
+} // End of ReadIBM525()
+
+VOID
+Write525PLL(
+ USHORT usFreq
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the IBM RGB525 Ramdac to generate and use the
+ specified frequency as its pixel clock frequency.
+
+Arguments:
+
+ Frequency.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ USHORT usRoundedFreq;
+ USHORT usVCODivCount;
+ ULONG ulValue;
+
+ usRoundedFreq = 2525;
+ usVCODivCount = 36;
+
+ //
+ // Setup for writing to the PLL Reference Divider register.
+ //
+
+ //
+ // Program REFCLK to a fixed 50MHz.
+ //
+ WriteIBM525(RGB525_FIXED_PLL_REF_DIV, IBM525_PLLD_50MHZ);
+
+ //
+ // Set up for programming frequency register 9.
+ //
+
+ WriteIBM525(RGB525_F9, (UCHAR) (usVCODivCount));
+
+ //
+ // Program PLL Control Register 2.
+ //
+
+ WriteIBM525(RGB525_PLL_CTL2, IBM525_PLL2_F9_REG);
+
+ //
+ // Program PLL Control Register 1.
+ //
+
+ WriteIBM525(RGB525_PLL_CTL1, (IBM525_PLL1_REFCLK_INPUT |
+ IBM525_PLL1_INT_FS) );
+
+ //
+ // Program DAC Operation Register.
+ //
+
+ WriteIBM525(RGB525_DAC_OPER, IBM525_DO_DSR_FAST);
+
+ //
+ // Program Miscellaneous Control Register 1.
+ //
+
+ WriteIBM525(RGB525_MISC_CTL1, IBM525_MC1_VRAM_64_BITS);
+
+ //
+ // Program Miscellaneous Clock Control Register.
+ //
+
+ ulValue = ReadIBM525(RGB525_MISC_CLOCK_CTL);
+
+ //
+ // At 8 Bpp, divide the clock by 8.
+ //
+ ulValue |= IBM525_MCC_PLL_DIV_8 | IBM525_MCC_PLL_ENABLE;
+
+ WriteIBM525(RGB525_MISC_CLOCK_CTL,
+ (UCHAR) ulValue);
+
+ return;
+
+} // End of Write525PLL()
+
+VOID P91WriteICD(
+ ULONG data
+ )
+
+/*++
+
+Routine Description:
+
+ Program the ICD2061a Frequency Synthesizer.
+
+Arguments:
+
+ HwDeviceExtension - Pointer to the miniport driver's device extension.
+ data - Data to be written.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ int i;
+ ULONG savestate;
+
+ //
+ // Note: We might have to disable interrupts to preclude the ICD's
+ // watchdog timer from expiring resulting in the ICD resetting to the
+ // idle state.
+ //
+ savestate = Read9100FreqSel();
+
+ //
+ // First, send the "Unlock sequence" to the clock chip.
+ // Raise the data bit and send 5 unlock bits.
+ //
+ Write9100FreqSel(ICD2061_DATA9100);
+ for (i = 0; i < 5; i++) // send at least 5 unlock bits
+ {
+ //
+ // Hold the data while lowering and raising the clock
+ //
+ Write9100FreqSel(ICD2061_DATA9100);
+ Write9100FreqSel( ICD2061_DATA9100 |
+ ICD2061_CLOCK9100);
+ }
+
+ //
+ // Then turn the data clock off and turn the clock on one more time...
+ //
+ Write9100FreqSel( 0);
+ Write9100FreqSel( ICD2061_CLOCK9100);
+
+ //
+ // Now send the start bit: Leave data off, adn lower the clock.
+ //
+ Write9100FreqSel( 0);
+
+ //
+ // Leave data off and raise the clock.
+ //
+ Write9100FreqSel( ICD2061_CLOCK9100);
+
+ //
+ // Localbus position for hacking bits out
+ // Next, send the 24 data bits.
+ //
+ for (i = 0; i < 24; i++)
+ {
+ //
+ // Leaving the clock high, raise the inverse of the data bit
+ //
+ Write9100FreqSel(
+ ((~data << ICD2061_DATASHIFT9100) &
+ ICD2061_DATA9100) | ICD2061_CLOCK9100);
+
+ //
+ // Leaving the inverse data in place, lower the clock.
+ //
+ Write9100FreqSel(
+ (~data << ICD2061_DATASHIFT9100) & ICD2061_DATA9100);
+
+ //
+ // Leaving the clock low, rais the data bit.
+ //
+ Write9100FreqSel(
+ (data << ICD2061_DATASHIFT9100) & ICD2061_DATA9100);
+
+ //
+ // Leaving the data bit in place, raise the clock.
+ //
+ Write9100FreqSel(
+ ((data << ICD2061_DATASHIFT9100) & ICD2061_DATA9100)
+ | ICD2061_CLOCK9100);
+
+ data >>= 1; // get the next bit of the data
+ }
+
+ //
+ // Leaving the clock high, raise the data bit.
+ //
+ Write9100FreqSel(
+ ICD2061_CLOCK9100 | ICD2061_DATA9100);
+
+ //
+ // Leaving the data high, drop the clock low, then high again.
+ //
+ Write9100FreqSel( ICD2061_DATA9100);
+ Write9100FreqSel(
+ ICD2061_CLOCK9100 | ICD2061_DATA9100);
+
+ //
+ // Note: if interrupts were disabled, enable them here.
+ // before restoring the
+ // original value or the ICD
+ // will freak out.
+ Write9100FreqSel( savestate); // restore orig register value
+
+ return;
+
+} // End of WriteICD()
+
+VOID
+Write9100FreqSel(
+ ULONG cs
+ )
+
+/*++
+
+Routine Description:
+
+ Write to the P9100 clock select register preserving the video coprocessor
+ enable bit.
+
+ Statically:
+ Bits [1:0] go to frequency select
+ Dynamically:
+ Bit 1: data
+ Bit 0: clock
+
+Arguments:
+
+ Clock select value to write.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Set the frequency select bits in the P9100 configuration
+ //
+
+ WriteP9ConfigRegister(P91_CONFIG_CKSEL,
+ (UCHAR) ((cs << 2)));
+ return;
+
+} // End of Write9100FreqSel()
+
+
+
+ULONG
+Read9100FreqSel()
+
+{
+ return((ULONG)(ReadP9ConfigRegister(P91_CONFIG_CKSEL)
+ >> 2) & 0x03);
+
+} // End of Read9100FreqSel()
+
+VOID
+WriteP9ConfigRegister(
+ UCHAR index,
+ UCHAR value
+ )
+{
+ if (HalpInitPhase == 0) {
+ HalpPhase0SetPciDataByOffset(HalpP9BusNumber,
+ HalpP9SlotNumber,
+ &value,
+ index,
+ 1);
+ }
+ else {
+ HalSetBusDataByOffset(PCIConfiguration,
+ HalpP9BusNumber,
+ HalpP9SlotNumber,
+ &value,
+ index,
+ 1);
+ }
+}
+
+UCHAR
+ReadP9ConfigRegister(
+ UCHAR index
+ )
+{
+ UCHAR retval;
+
+ if (HalpInitPhase == 0) {
+ HalpPhase0GetPciDataByOffset(HalpP9BusNumber,
+ HalpP9SlotNumber,
+ &retval,
+ index,
+ 1);
+ }
+ else {
+ HalGetBusDataByOffset(PCIConfiguration,
+ HalpP9BusNumber,
+ HalpP9SlotNumber,
+ &retval,
+ index,
+ 1);
+ }
+
+ return ( retval );
+
+}
+
+VOID
+IBM525PointerOff(
+ )
+
+/*++
+
+Routine Description:
+
+ Turn off the hardware cursor.
+
+Arguments:
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Turn the cursor off only if it was enabled.
+ //
+ if (CURS_IS_ON_IBM525())
+ {
+ CURS_OFF_IBM525();
+ }
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxp91.h b/private/ntos/nthals/halppc/ppc/pxp91.h
new file mode 100644
index 000000000..f0201a87f
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxp91.h
@@ -0,0 +1,1380 @@
+#include <ntdef.h>
+
+typedef struct {
+ char red;
+ char green;
+ char blue;
+} RGB;
+
+
+//
+// Macros to read and write P9 registers.
+//
+
+#define P9_WR_REG(index, data) \
+ *(volatile PULONG)((ULONG)HalpVideoCoprocBase + (index)) = (ULONG)(data), \
+ KeFlushWriteBuffer()
+
+#define P9_RD_REG(index) \
+ *(volatile ULONG *)((ULONG)HalpVideoCoprocBase + (index))
+
+#define P9_WR_BYTE_REG(index, data) \
+ *(volatile UCHAR *)((ULONG)HalpVideoCoprocBase + (index)) = (UCHAR)(data), \
+ KeFlushWriteBuffer()
+
+#define P9_RD_BYTE_REG(index) \
+ *(volatile UCHAR *)((ULONG)HalpVideoCoprocBase + (index))
+
+#define P9_WR_FB(index) \
+ *(volatile ULONG *)((ULONG)HalpVideoMemoryBase + (index))
+
+
+#define P9100_FRAMEBUF_OFFSET 0x00800000
+
+// These are used by the palette setup section
+#define P9100_PU_CONFIG 0x00000198
+#define P9100_PalCurRamW 0x00000200
+#define P9100_PalData 0x00000204
+#define P9100_PixelMask 0x00000208
+#define P9100_PalCurRamR 0x0000020c
+#define P9100_IndexLow 0x00000210
+#define P9100_IndexHigh 0x00000214
+#define P9100_IndexData 0x00000218
+#define P9100_IndexContr 0x0000021c
+
+//
+// P9100 relocatable memory mapped BT485 register definitions.
+//
+// Note: An extra 2 byte offset is added to the register offset in order
+// to align the offset on the byte of the Dword which contains the
+// DAC data.
+//
+#define P9100_RAMWRITE 0x00000200 + 2
+#define P9100_PALETDATA 0x00000204 + 2
+#define P9100_PIXELMASK 0x00000208 + 2
+#define P9100_RAMREAD 0x0000020C + 2
+#define P9100_COLORWRITE 0x00000210 + 2
+#define P9100_COLORDATA 0x00000214 + 2
+#define P9100_COMREG0 0x00000218 + 2
+#define P9100_COLORREAD 0x0000021C + 2
+#define P9100_COMREG1 0x00000220 + 2
+#define P9100_COMREG2 0x00000224 + 2
+#define P9100_COMREG3 0x00000228 + 2
+#define P9100_STATREG 0x00000228 + 2
+#define P9100_CURSORDATA 0x0000022C + 2
+#define P9100_CURSORX0 0x00000230 + 2
+#define P9100_CURSORX1 0x00000234 + 2
+#define P9100_CURSORY0 0x00000238 + 2
+#define P9100_CURSORY1 0x0000023C + 2
+
+//
+// IBMRGB525 Indexed registers. Those index registers marked // Referenced
+// indicate that they are reference.
+//
+#define RGB525_REVISION_LEVEL (0x00)
+#define RGB525_ID (0x01)
+#define RGB525_MISC_CLOCK_CTL (0x02) // Referenced
+#define RGB525_SYNC_CTL (0x03)
+#define RGB525_HSYNC_POS (0x04)
+#define RGB525_POWER_MGNT (0x05)
+#define RGB525_DAC_OPER (0x06) // Referenced
+#define RGB525_PAL_CTRL (0x07)
+//
+// 08h through 09h are reserved by IBM
+//
+#define RGB525_PIXEL_FORMAT (0x0A) // Referenced
+#define RGB525_8BPP_CTL (0x0B) // Referenced
+#define RGB525_16BPP_CTL (0x0C) // Referenced
+#define RGB525_24BPP_CTL (0x0D) // Referenced
+#define RGB525_32BPP_CTL (0x0E) // Referenced
+//
+// 0Fh is reserved by IBM
+//
+#define RGB525_PLL_CTL1 (0x10) // Referenced
+#define RGB525_PLL_CTL2 (0x11) // Referenced
+//
+// 12h through 13h are reserved by IBM
+//
+#define RGB525_FIXED_PLL_REF_DIV (0x14) // Referenced
+//
+// 15h through 1fh are reserved by IBM
+//
+#define RGB525_F0 (0x20) // Referenced
+#define RGB525_F1 (0x21)
+#define RGB525_F2 (0x22)
+#define RGB525_F3 (0x23)
+#define RGB525_F4 (0x24)
+#define RGB525_F5 (0x25)
+#define RGB525_F6 (0x26)
+#define RGB525_F7 (0x27)
+#define RGB525_F8 (0x28)
+#define RGB525_F9 (0x29)
+#define RGB525_F10 (0x2A)
+#define RGB525_F11 (0x2B)
+#define RGB525_F12 (0x2C)
+#define RGB525_F13 (0x2D)
+#define RGB525_F14 (0x2E)
+#define RGB525_F15 (0x2F)
+#define RGB525_CURSOR_CTL (0x30) // Referenced
+#define RGB525_CURSOR_X_LOW (0x31) // Referenced
+#define RGB525_CURSOR_X_HIGH (0x32) // Referenced
+#define RGB525_CURSOR_Y_LOW (0x33) // Referenced
+#define RGB525_CURSOR_Y_HIGH (0x34) // Referenced
+#define RGB525_CURSOR_HOT_X (0x35) // Referenced
+#define RGB525_CURSOR_HOT_Y (0x36) // Referenced
+//
+// 37h through 3fh are reserved by IBM
+//
+#define RGB525_CURSOR_1_RED (0x40) // Referenced
+#define RGB525_CURSOR_1_GREEN (0x41) // Referenced
+#define RGB525_CURSOR_1_BLUE (0x42) // Referenced
+#define RGB525_CURSOR_2_RED (0x43) // Referenced
+#define RGB525_CURSOR_2_GREEN (0x44) // Referenced
+#define RGB525_CURSOR_2_BLUE (0x45) // Referenced
+#define RGB525_CURSOR_3_RED (0x46)
+#define RGB525_CURSOR_3_GREEN (0x47)
+#define RGB525_CURSOR_3_BLUE (0x48)
+//
+// 49h through 5fh are reserved by IBM
+//
+#define RGB525_BORDER_RED (0x60)
+#define RGB525_BORDER_GREEN (0x61)
+#define RGB525_BORDER_BLUE (0x62)
+//
+// 63h through 6fh are reserved by IBM
+//
+#define RGB525_MISC_CTL1 (0x70) // Referenced
+#define RGB525_MISC_CTL2 (0x71) // Referenced
+#define RGB525_MISC_CTL3 (0x72)
+//
+// 73h through 81h are reserved by IBM
+//
+#define RGB525_DAC_SENSE (0x82)
+//
+// 83h is reserved by IBM
+//
+#define RGB525_MISR_RED (0x84)
+//
+// 85h is reserved by IBM
+//
+#define RGB525_MISR_GREEN (0x86)
+//
+// 87h is reserved by IBM
+//
+#define RGB525_MISR_BLUE (0x88)
+//
+// 89h - 8dh are reserved by IBM
+//
+#define RGB525_PLL_VCO_DIV (0x8E)
+#define RGB525_PLL_REF_DIV_IN (0x8F)
+#define RGB525_VRAM_MASK_LOW (0x90)
+#define RGB525_VRAM_MASK_HIGH (0x91)
+//
+// 92h through 0ffh are reserved by IBM
+//
+#define RGB525_CURSOR_ARRAY (0x100) // Referenced
+
+//
+// Masks used to program the ICD2061a Frequency Synthesizer.
+//
+
+#define IC_REG0 0x0l // Mask selects ICD Video Clock Reg 1
+#define IC_REG1 0x200000l // Mask selects ICD Video Clock Reg 2
+#define IC_REG2 0x400000l // Mask selects ICD Video Clock Reg 3
+#define IC_MREG 0x600000l // Mask selects ICD Mem Timing Clock
+#define IC_CNTL 0xc18000l // Mask selects ICD Control Register
+#define IC_DIV4 0xa40000l
+
+//
+// These values are used to program custom frequencies
+// and to select a custom frequency.
+//
+#define ICD2061_EXTSEL9100 (0x03)
+#define ICD2061_DATA9100 (0x02)
+#define ICD2061_DATASHIFT9100 (0x01)
+#define ICD2061_CLOCK9100 (0x01)
+
+//
+// P9100 relocatable memory mapped IBM 525 register definitions.
+//
+// Note: An extra 2 byte offset is added to the register offset in order
+// to align the offset on the byte of the Dword which contains the
+// DAC data.
+//
+#define P9100_IBM525_PAL_WRITE 0x00000200 + 2
+#define P9100_IBM525_PAL_DATA 0x00000204 + 2
+#define P9100_IBM525_PEL_MASK 0x00000208 + 2
+#define P9100_IBM525_PAL_READ 0x0000020C + 2
+#define P9100_IBM525_INDEX_LOW 0x00000210 + 2
+#define P9100_IBM525_INDEX_HIGH 0x00000214 + 2
+#define P9100_IBM525_INDEX_DATA 0x00000218 + 2
+#define P9100_IBM525_INDEX_CTL 0x0000021C + 2
+
+//
+// PLL Control 1 Register Bit Definitions. (Section 13.2.3.1)
+//
+#define IBM525_PLL1_REF_SRC_MSK 0x10
+#define IBM525_PLL1_REFCLK_INPUT 0x00
+#define IBM525_PLL1_EXTOSC_INPUT 0x10
+#define IBM525_PLL1_EXT_INT_MSK 0x07
+#define IBM525_PLL1_EXT_FS 0x00
+#define IBM525_PLL1_INT_FS 0x02
+
+//
+// PLL Control 2 Register Bit Definitions. (Section 13.2.3.2)
+//
+#define IBM525_PLL2_INT_FS_MSK 0x0F
+#define IBM525_PLL2_F0_REG 0x00
+#define IBM525_PLL2_F1_REG 0x01
+#define IBM525_PLL2_F2_REG 0x02
+#define IBM525_PLL2_F3_REG 0x03
+#define IBM525_PLL2_F4_REG 0x04
+#define IBM525_PLL2_F5_REG 0x05
+#define IBM525_PLL2_F6_REG 0x06
+#define IBM525_PLL2_F7_REG 0x07
+#define IBM525_PLL2_F8_REG 0x08
+#define IBM525_PLL2_F9_REG 0x09
+#define IBM525_PLL2_F10_REG 0x0A
+#define IBM525_PLL2_F11_REG 0x0B
+#define IBM525_PLL2_F12_REG 0x0C
+#define IBM525_PLL2_F13_REG 0x0D
+#define IBM525_PLL2_F14_REG 0x0E
+#define IBM525_PLL2_F15_REG 0x0F
+
+//
+// PLL Reference Divider Register Bit Definitions. (Section 13.2.3.3)
+//
+#define IBM525_PLLD_4MHZ 0x02
+#define IBM525_PLLD_6MHZ 0x03
+#define IBM525_PLLD_8MHZ 0x04
+#define IBM525_PLLD_10MHZ 0x05
+#define IBM525_PLLD_12MHZ 0x06
+#define IBM525_PLLD_14MHZ 0x07
+#define IBM525_PLLD_16MHZ 0x08
+#define IBM525_PLLD_18MHZ 0x09
+#define IBM525_PLLD_20MHZ 0x0A
+#define IBM525_PLLD_22MHZ 0x0B
+#define IBM525_PLLD_24MHZ 0x0C
+#define IBM525_PLLD_26MHZ 0x0D
+#define IBM525_PLLD_28MHZ 0x0E
+#define IBM525_PLLD_30MHZ 0x0F
+#define IBM525_PLLD_32MHZ 0x10
+#define IBM525_PLLD_34MHZ 0x11
+#define IBM525_PLLD_36MHZ 0x12
+#define IBM525_PLLD_38MHZ 0x13
+#define IBM525_PLLD_40MHZ 0x14
+#define IBM525_PLLD_42MHZ 0x15
+#define IBM525_PLLD_44MHZ 0x16
+#define IBM525_PLLD_46MHZ 0x17
+#define IBM525_PLLD_48MHZ 0x18
+#define IBM525_PLLD_50MHZ 0x19
+#define IBM525_PLLD_52MHZ 0x1A
+#define IBM525_PLLD_54MHZ 0x1B
+#define IBM525_PLLD_56MHZ 0x1C
+#define IBM525_PLLD_58MHZ 0x1D
+#define IBM525_PLLD_60MHZ 0x1E
+#define IBM525_PLLD_62MHZ 0x1F
+
+//
+// DAC Operation Register Bit Definitions. (Section 13.2.1.8)
+//
+#define IBM525_DO_SOG_MSK 0x08
+#define IBM525_DO_SOG_DISABLE 0x00
+#define IBM525_DO_SOG_ENABLE 0x08
+#define IBM525_DO_BRB_MSK 0x04
+#define IBM525_DO_BRB_NORMAL 0x00
+#define IBM525_DO_BRB_BLANKED 0x04
+#define IBM525_DO_DSR_MSK 0x02
+#define IBM525_DO_DSR_SLOW 0x00
+#define IBM525_DO_DSR_FAST 0x02
+#define IBM525_DO_DPE_MSK 0x01
+#define IBM525_DO_DPE_DISABLE 0x00
+#define IBM525_DO_DPE_ENABLE 0x01
+
+//
+// Miscellaneous Control 1 Register Bit Definitions. (Section 13.2.1.1)
+//
+#define IBM525_MC1_MISR_CTL_MSK 0x80
+#define IBM525_MC1_MISR_CTL_OFF 0x00
+#define IBM525_MC1_MISR_CTL_ON 0x80
+#define IBM525_MC1_VMSK_CTL_MSK 0x40
+#define IBM525_MC1_VMASK_DISABLE 0x00
+#define IBM525_MC1_VMASK_ENABLE 0x40
+#define IBM525_MC1_PADR_RFMT_MSK 0x20
+#define IBM525_MC1_GET_PAL_ADDR 0x00
+#define IBM525_MC1_GET_ACC_STATE 0x20
+#define IBM525_MC1_SENS_DSAB_MSK 0x10
+#define IBM525_MC1_SENSE_ENABLE 0x00
+#define IBM525_MC1_SENSE_DISABLE 0x10
+#define IBM525_MC1_SENS_SEL_MSK 0x08
+#define IBM525_MC1_SENS_SEL_BIT3 0x00
+#define IBM525_MC1_SENS_SEL_BIT7 0x08
+#define IBM525_MC1_VRAM_SIZE_MSK 0x01
+#define IBM525_MC1_VRAM_32_BITS 0x00
+#define IBM525_MC1_VRAM_64_BITS 0x01
+
+//
+// Miscellaneous Clock Control Register Bit Definitions. (Section 13.2.1.4)
+//
+#define IBM525_MCC_DDOT_DSAB_MSK 0x80
+#define IBM525_MCC_DDOT_ENABLE 0x00
+#define IBM525_MCC_DDOT_DISABLE 0x80
+#define IBM525_MCC_SCLK_DSAB_MSK 0x40
+#define IBM525_MCC_SCLK_ENABLE 0x00
+#define IBM525_MCC_SCLK_DISABLE 0x40
+#define IBM525_MCC_B24P_DDOT_MSK 0x20
+#define IBM525_MCC_B24P_PLL 0x00
+#define IBM525_MCC_B24P_SCLK 0x20
+#define IBM525_MCC_DDOT_DIV_MSK 0x0E
+#define IBM525_MCC_PLL_DIV_1 0x00
+#define IBM525_MCC_PLL_DIV_2 0x02
+#define IBM525_MCC_PLL_DIV_4 0x04
+#define IBM525_MCC_PLL_DIV_8 0x06
+#define IBM525_MCC_PLL_DIV_16 0x08
+#define IBM525_MCC_PLL_ENAB_MSK 0x01
+#define IBM525_MCC_PLL_DISABLE 0x00
+#define IBM525_MCC_PLL_ENABLE 0x01
+
+
+//
+// Define valid P9100 Revision ID's
+//
+
+#define WTK_9100_REV0 0x0000 //
+#define WTK_9100_REV1 0x0000 //
+#define WTK_9100_REV2 0x0002 //
+#define WTK_9100_REV3 0x0003 //
+
+//
+// Define Power 9100 I/O Space Configuration Index Registers.
+//
+
+#define P91_CONFIG_INDEX 0x9100 // Config space index register.
+#define P91_CONFIG_DATA 0x9104 // Config space data register.
+
+//
+// Define the Weitek & OEM specific IDs for P9100 board verification...
+//
+
+#define P91_VEN_ID_WEITEK_VL 0x100E // Standard Weitek VLB Design
+#define P91_VEN_ID_VIPER_VL 0x100E // Standard VIPER VLB Design
+#define P91_VEN_ID_WEITEK_PCI 0x100E // Standard Weitek PCI Design
+#define P90_DEV_ID_WEITEK_VL 0x9000 // Standard Weitek VLB Design
+#define P91_DEV_ID_WEITEK_VL 0x9100 // Standard Weitek VLB Design
+#define P91_DEV_ID_VIPER_VL 0x9100 // Standard VIPER VLB Design
+#define P91_DEV_ID_WEITEK_PCI 0x9100 // Standard Weitek PCI Design
+
+//
+// Configuration Register Definitions, all are Read-only unless specified.
+// Note: offsets are for byte reads/writes.
+//
+
+#define P91_CONFIG_VENDOR_LOW (0) // RO-Low order byte of Vendor ID
+#define P91_CONFIG_VENDOR_HIGH (1) // RO-High order byte of Vendor ID
+#define P91_CONFIG_DEVICE_LOW (2) // RO-Low order byte of Device ID
+#define P91_CONFIG_DEVICE_HIGH (3) // RO-HIGH order byte of Device ID
+#define P91_CONFIG_CONFIGURATION (4) // RW-Configuration Register
+#define P91_CONFIG_STATUS (7) // RO-Status Register
+#define P91_CONFIG_REVISION_ID (8) // RO-Revision ID
+#define P91_CONFIG_VGA_PRESENT (10) // RO-Vga Present - set by PUCONFIG
+#define P91_CONFIG_DISPLAY (11) // RO-PCI Display Controller
+#define P91_CONFIG_WBASE (19) // RW-Memory Base for Native Mode
+#define P91_CONFIG_ROM_ENABLE (48) // RW-ROM decoding enabled
+#define P91_CONFIG_ROM_BASE_0 (49) // RW-ROM Base address, Bit 0
+#define P91_CONFIG_ROM_BASE_8_1 (50) // RW-ROM Base address, Bits 8~1
+#define P91_CONFIG_ROM_BASE_16_9 (51) // RW-ROM Base address, Bits 16~9
+#define P91_CONFIG_CFBGA (64) // RO-Config: BUS, CFBGA & EEDAIN
+#define P91_CONFIG_MODE (65) // RW-Mode select
+#define P91_CONFIG_CKSEL (66) // RW-CKSEl & VCEN
+
+//
+//
+// Clock Synth IDs:
+//
+#define CLK_ID_ICD2061A (0x00) // ICD2061a
+#define CLK_ID_FIXED_MEMCLK (0x20) // Fixed MEMCLK, RAMDAC gens pixclk
+
+//
+// Define Power 9100 coprocesser address prefix bits.
+// (Page 18)
+//
+// Address format:
+//
+// 3 2 2 1 1 1 1 1 1
+// 1 4 3 9 8 7 6 5 4 0
+// ------------------------------------------------------
+// | a a a a a a a a | 0 0 0 0 0 | H | B | b | 0 | o o |
+// ------------------------------------------------------
+//
+// a - Base Address
+// H - Word Swap
+// B - Byte Swap
+// b - Bit Swap
+// o - Coprocessor register offset
+//
+
+#define P91_WORD_SWAP 0x00040000 //
+#define P91_BYTE_SWAP 0x00020000 //
+#define P91_BIT_SWAP 0x00010000 //
+
+//
+// Define Power 9100 coprocesser system control register address offsets.
+// (Page 23)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 7 6 2 1 0
+// --------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 0 0 0 0 0 0 0 | r r r r r | 0 0 |
+// --------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// r - Resiter bits (6-2):
+// 00001 - sysconfig
+// 00010 - interrupt
+// 00011 - interrupt_en
+// 00100 - alt_write_bank
+// 00101 - alt_read_bank
+//
+
+#define P91_SYSCONFIG 0x00000004 // System configuration register.
+#define P91_INTERRUPT 0x00000008 // Interrupt register.
+#define P91_INTERRUPT_EN 0x0000000C // Interrupt enable register.
+#define P91_ALT_WRITE_BANK 0x00000010 // Alternate write bank register.
+#define P91_ALT_READ_BANK 0x00000014 // Alternate read bank register.
+
+//
+// Define Power 9100 coprocesser device coordinate register address offsets.
+// (Page 27)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 8 7 6 5 4 3 2 1 0
+// -----------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 1 0 0 0 0 | r r | a | y x | 0 0 0 |
+// -----------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// r - Resiter bits (7-6):
+// 00 - X[0]/Y[0]
+// 01 - X[1]/Y[1]
+// 10 - X[2]/Y[2]
+// 11 - X[3]/Y[3]
+// a - Screen addressing bit (5):
+// 0 - Perform absolute screen addressing.
+// 1 - Perform window-relative screen addressing (write only).
+// yx - 32/16 bit read/write bits (4-3):
+// 00 - Not used.
+// 01 - Read or write 32-bit X value.
+// 10 - Read or write 32-bit Y value.
+// 11 - Read or write 16-bit X value (high 16 bits) Y value (low 16 bits).
+//
+
+#define P91_X0_32 0x00003008 // 32-bit X[0] register.
+#define P91_X1_32 0x00003048 // 32-bit X[1] register.
+#define P91_X2_32 0x00003088 // 32-bit X[2] register.
+#define P91_X3_32 0x000030C8 // 32-bit X[3] register.
+#define P91_Y0_32 0x00003010 // 32-bit Y[0] register.
+#define P91_Y1_32 0x00003050 // 32-bit Y[1] register.
+#define P91_Y2_32 0x00003090 // 32-bit Y[2] register.
+#define P91_Y3_32 0x000030D0 // 32-bit Y[3] register.
+#define P91_X0_Y0_16 0x00003018 // 16-bit X[0]/Y[0] register.
+#define P91_X1_Y1_16 0x00003058 // 16-bit X[1]/Y[1] register.
+#define P91_X2_Y2_16 0x00003098 // 16-bit X[2]/Y[1] register.
+#define P91_X3_Y3_16 0x000030D8 // 16-bit X[3]/Y[1] register.
+#define P91_WIN_REL_BIT 0x00000020 // Window relative addressing bit.
+
+//
+// Define Power 9100 coprocesser status register address offset.
+// (Page 28)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 2 1 0
+// -----------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 0 0 0 0 0 0 0 0 | 0 0 |
+// -----------------------------------------------------------------------
+//
+// p - Address prefix bits.
+//
+
+#define P91_STATUS 0x00002000 // Status register.
+
+//
+// Define Power 9100 coprocesser parameter engine control and
+// condition register address offsets.
+// (Page 29)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 7 6 2 1 0
+// --------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 0 1 1 | r r r r r | 0 0 |
+// --------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// r - Resiter bits (6-2):
+// 00000 - Not Used.
+// 00001 - oor
+// 00010 - Not Used.
+// 00011 - cindex
+// 00100 - w_off_xy
+// 00101 - p_w_min
+// 00110 - p_w_max
+// 00111 - Not Used.
+// 01000 - yclip
+// 01001 - xclip
+// 01010 - xedge_lt
+// 01011 - xedge_gt
+// 01100 - yedge_lt
+// 01101 - yedge_gt
+//
+
+#define P91_PE_OOR 0x00002184 // Out of Range Reg. (read only)
+#define P91_PE_CINDEX 0x0000218C // Index Reg.
+#define P91_PE_W_OFF_XY 0x00002190 // Window Offset Reg.
+#define P91_PE_P_W_MIN 0x00002194 // Pixel Window Min Reg. (read only)
+#define P91_PE_P_W_MAX 0x00002198 // Pixel Window Max Reg. (read only)
+#define P91_PE_YCLIP 0x000021A0 // Y Clip Register. (read only)
+#define P91_PE_XCLIP 0x000021A4 // X Clip Register. (read only)
+#define P91_PE_XEDGE_LT 0x000021A8 // (read only)
+#define P91_PE_XEDGE_GT 0x000021AC // (read only)
+#define P91_PE_YEDGE_LT 0x000021B0 // (read only)
+#define P91_PE_YEDGE_GT 0x000021B4 // (read only)
+
+//
+// Define Power 9100 coprocesser drawing engine register address offsets.
+// (Page 33)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 9 8 2 1 0
+// --------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 1 | r r r r r r r | 0 0 |
+// --------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// r - Resiter bits (8-2):
+// 0000000 - color[0]
+// 0000001 - color[1]
+// 0000010 - pmask
+// 0000011 - draw_mode
+// 0000100 - pat_originx
+// 0000101 - pat_originy
+// 0000110 - raster
+// 0000111 - pixel8
+// 0001000 - p_w_min
+// 0001001 - p_w_max
+// 0001110 - color[2]
+// 0001111 - color[3]
+// 0100000 - pattern0
+// 0100001 - pattern1
+// 0100010 - pattern2
+// 0100011 - pattern3
+// 0101000 - b_w_min
+// 0101001 - b_w_max
+//
+
+#define P91_DE_COLOR0 0x00002200 // Color register 0.
+#define P91_DE_COLOR1 0x00002204 // Color register 1.
+#define P91_DE_PMASK 0x00002208 // Plane Mask register.
+#define P91_DE_DRAW_MODE 0x0000220C // Draw Mode Register.
+#define P91_DE_PAT_ORIGINX 0x00002210 // Pattern X Origin register.
+#define P91_DE_PAT_ORIGINY 0x00002214 // Pattern Y Origin register.
+#define P91_DE_RASTER 0x00002218 // Raster Operation register.
+#define P91_DE_PIXEL8 0x0000221C // Pixel 8 register.
+#define P91_DE_P_W_MIN 0x00002220 // Pixel Window Clip Minimum.
+#define P91_DE_P_W_MAX 0x00002224 // Pixel Window Clip Maximum.
+#define P91_DE_COLOR2 0x00002238 // Color register 2.
+#define P91_DE_COLOR3 0x0000223C // Color register 3.
+#define P91_DE_PATTERN0 0x00002280 // Pattern 0 register.
+#define P91_DE_PATTERN1 0x00002284 // Pattern 1 register.
+#define P91_DE_PATTERN2 0x00002288 // Pattern 2 register.
+#define P91_DE_PATTERN3 0x0000228C // Pattern 3 register.
+#define P91_DE_B_W_MIN 0x000022A0 // Byte Window Clip Minimum.
+#define P91_DE_B_W_MAX 0x000022A4 // Byte Window Clip Maximum.
+
+//
+// Define Power 9100 coprocesser video control register address offsets.
+// Note: The offsets for these registers are the same as for the Power 9000
+// except for srtctl2 which is new on the Power 9100.
+// (Page 37)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 7 6 2 1 0
+// --------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 0 0 0 0 0 1 0 | r r r r r | 0 0 |
+// --------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// r - Resiter bits (6-2):
+// 00001 - hrzc
+// 00010 - hrzt
+// 00011 - hrzsr
+// 00100 - hrzbr
+// 00101 - hrzbf
+// 00110 - prehrzc
+// 00111 - vrtc
+// 01000 - vrtt
+// 01001 - vrtsr
+// 01010 - vrtbr
+// 01011 - vrtbf
+// 01100 - prevrtc
+// 01101 - sraddr
+// 01110 - srtctl
+// 01111 - sraddr_inc
+// 10000 - srtctl2
+//
+
+#define P91_HRZC 0x00000104 // Horiz. counter (read only).
+#define P91_HRZT 0x00000108 // Horiz. length (read/write).
+#define P91_HRZSR 0x0000010C // Horiz. sync rising edge (read/write).
+#define P91_HRZBR 0x00000110 // Horiz. blank rising edge (read/write).
+#define P91_HRZBF 0x00000114 // Horiz. blank falling edge (read/write).
+#define P91_PREHRZC 0x00000118 // Horiz. counter preload (read/write).
+#define P91_VRTC 0x0000011C // Vert. counter (read only).
+#define P91_VRTT 0x00000120 // Vert. length (read/write).
+#define P91_VRTSR 0x00000124 // Vert. sync rising edge (read/write).
+#define P91_VRTBR 0x00000128 // Vert. blank rising edge (read/write).
+#define P91_VRTBF 0x0000012C // Vert. blank falling edge (read/write).
+#define P91_PREVRTC 0x00000130 // Vert. counter preload (read/write).
+#define P91_SRADDR 0x00000134 //
+#define P91_SRTCTL 0x00000138 // Screen repaint timing control 1.
+#define P91_SRADDR_INC 0x0000013C //
+#define P91_SRTCTL2 0x00000140 // Screen repaint timing control 2.
+#define P91_SRTCTL2_N (0x00) // SRTCTL2 sync polarities...
+#define P91_SRTCTL2_P (0x01)
+#define P91_SRTCTL2_H (0x03)
+#define P91_SRTCTL2_L (0x02)
+#define P91_HSYNC_HIGH_TRUE 0x00000000
+#define P91_HSYNC_LOW_TRUE 0x00000001
+#define P91_VSYNC_HIGH_TRUE 0x00000000
+#define P91_VSYNC_LOW_TRUE 0x00000004
+
+//
+// Define Power 9100 coprocesser VRAM control register address offsets.
+// Note: The offsets for these registers are the same as for the Power 9000
+// except for pu_config which is new on the Power 9100.
+// (Page 41)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 7 6 2 1 0
+// --------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 0 0 0 0 0 1 1 | r r r r r | 0 0 |
+// --------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// r - Resiter bits (6-2):
+// 00001 - mem_config
+// 00010 - rfperiod
+// 00011 - rfcount
+// 00100 - rlmax
+// 00101 - rlcur
+// 00110 - pu_config
+//
+
+#define P91_MEM_CONFIG 0x00000184 // Memory Configuration Register.
+#define P91_RFPERIOD 0x00000188 // Refresh Period Register.
+#define P91_RFCOUNT 0x0000018C // Refresh Count Register.
+#define P91_RLMAX 0x00000190 // RAS Low Miaximum Register.
+#define P91_RLCUR 0x00000194 // RAS Low Current Register.
+#define P91_PU_CONFIG 0x00000198 // Power-Up Configuration Register.
+#define P91_EXT_IO_ID 0x00000208 // Get external board id value from here
+ // to detect Intergraph board
+//
+// Define Power 9100 coprocesser meta-coordinate pseudo-register address
+// offsets.
+// (Page 43)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 9 8 6 5 4 3 2 1 0
+// -----------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 1 0 0 1 | v v v | a | y x | 0 0 0 |
+// -----------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+// v - Vtype bits (8-6):
+// 000 - point
+// 001 - line
+// 010 - triangle
+// 011 - quad
+// 100 - rectangle
+// a - Screen addressing bit (5):
+// 0 - Perform addressing relative to the window offset.
+// 1 - Perform addressing relative to the previos vertex.
+// yx - 32/16 bit read/write bits (4-3):
+// 00 - Not used.
+// 01 - Read or write 32-bit X value.
+// 10 - Read or write 32-bit Y value.
+// 11 - Read or write 16-bit X value (high 16 bits) Y value (low 16 bits).
+//
+
+#define P91_META_X_32 0x00003208 // 32-bit X coordinate value.
+#define P91_META_Y_32 0x00003210 // 32-bit Y coordinate value.
+#define P91_META_X_Y_16 0x00003218 // 16-bit X/Y coordinate value.
+#define P91_META_POINT 0x00000000 // Point draw type bits.
+#define P91_META_LINE 0x00000040 // Line draw type bits.
+#define P91_META_TRIANGLE 0x00000080 // Triangle draw type bits.
+#define P91_META_QUAD 0x000000C0 // Quadrilateral draw type bits.
+#define P91_META_RECT 0x00000100 // Rectangle draw type bits.
+#define P91_META_WIN_REL 0x00000000 // Window relative addressing bits.
+#define P91_META_VERT_REL 0x00000020 // Vertex relative addressing bits.
+
+//
+// Define Power 9100 coprocesser quad command register address offset.
+// (Page 44)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 2 1 0
+// -----------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 0 0 0 0 0 0 1 0 | 0 0 |
+// -----------------------------------------------------------------------
+//
+// p - Address prefix bits.
+//
+
+#define P91_QUAD 0x00002008 // Quad Command Register.
+
+//
+// Define Power 9100 coprocesser blit command register address offset.
+// (Page 44)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 2 1 0
+// -----------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 0 0 0 0 0 0 0 1 | 0 0 |
+// -----------------------------------------------------------------------
+//
+// p - Address prefix bits.
+//
+
+#define P91_BLIT 0x00002004 // Blit Command Register.
+
+//
+// Define Power 9100 coprocesser pixel8 command register address offset.
+// (Page 45)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 2 1 0
+// -----------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 1 - - - - - - - - - - - - | 0 0 |
+// -----------------------------------------------------------------------
+//
+// p - Address prefix bits.
+//
+
+#define P91_PIXEL8 0x00004000 // Pixel 8 Command Register.
+
+//
+// Define Power 9100 coprocesser pixel1 command register address offset.
+// (Page 45)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 7 6 2 1 0
+// -------------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 0 0 1 | # # # # # | 0 0 |
+// -------------------------------------------------------------------------
+//
+// p - Address prefix bits.
+//
+
+#define P91_PIXEL1 0x00002080 // Pixel 1 Command Register.
+#define P91_PIXEL1_COUNT_MSK 0x0000007C // Pixel Count Mask
+#define P91_PIXEL1_32_PIXELS 0x0000007C // Maximum Pixel Count
+
+//
+// Define Power 9100 coprocesser next pixels command register address offset.
+// (Page 46)
+//
+// Address format:
+//
+// 3 1 1
+// 1 5 4 2 1 0
+// -----------------------------------------------------------------------
+// | p p p p p p p p p p p p p p p p p | 0 1 0 0 0 0 0 0 0 0 1 0 1 | 0 0 |
+// -----------------------------------------------------------------------
+//
+// p - Address prefix bits.
+//
+
+#define P91_NEXT_PIXELS 0x00002014 // Next Pixels Command Register.
+
+// 3 1
+// 1 5 0
+// -------------------------------------------------------------------
+// | 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 |
+// -------------------------------------------------------------------
+
+
+//
+// Define the Power-Up Configuration Register Bits.
+// Page (Page 13)
+// 2 1 1 1 1
+// 3 6 5 2 1 8 7 5 4 3 2 1 0
+// -------------------------------------------------
+// | 0 | - - - - | 0 | - - - | - | - | - - | - |
+// -------------------------------------------------
+// | | | | | | | | | | | | | |
+// | ------- | ----- | | --- |
+// | | | | | | | ----> Motherboard implementation.
+// | | | | | | ---------> EEProm Type
+// | | | | | --------------> VRAM SAM Size.
+// | | | | ------------------> VRAM Memory Depth.
+// | | | ------------------------> Frequency Synthesizer type.
+// | | -------------------------------> Reserved.
+// | ---------------------------------------> RAMDAC Type.
+// -----------------------------------------------> Reserved.
+//
+// 3 3 2 2 2 2 2
+// 1 0 9 7 6 5 4
+// ---------------------------
+// | - - | - - - | - | - | 0 |
+// ---------------------------
+// | | | | | | | |
+// --- ----- | | ---------------> Reserved.
+// | | | -------------------> VGA presence.
+// | | -----------------------> Initial Mode Select.
+// | -----------------------------> Configuration Registers Base Address.
+// ------------------------------------> Bus Type.
+//
+
+#define P91_PUC_IMPLEMENTATION 0x00000001 //
+#define P91_PUC_MOTHER_BOARD 0x00000000 //
+#define P91_PUC_ADD_IN_CARD 0x00000001 //
+#define P91_PUC_EEPROM_TYPE 0x00000006 //
+#define P91_PUC_EEPROM_AT24C01 0x00000000 //
+#define P91_PUC_VRAM_SAM_SIZE 0x00000008 //
+#define P91_PUC_FULL_SIZE_SHIFT 0x00000000 //
+#define P91_PUC_HALF_SIZE_SHIFT 0x00000008 //
+#define P91_PUC_MEMORY_DEPTH 0x00000010 //
+#define P91_PUC_256K_VRAMS 0x00000000 //
+#define P91_PUC_128K_VRAMS 0x00000010 //
+#define P91_PUC_FREQ_SYNTH_TYPE 0x000000E0 //
+#define P91_PUC_EXT_IO 0x00000100 // External I/O regs are on DAC interface
+#define P91_PUC_ICD_2061A 0x00000000 // ICD2061a
+#define P91_PUC_FIXED_MEMCLK 0x00000020 // Fixed MEMCLK, RAMDAC gens pixclk
+#define P91_PUC_RAMDAC_TYPE 0x0000F000 //
+#define P91_PUC_DAC_BT485 0x00000000 //
+#define P91_PUC_DAC_BT489 0x00001000 //
+#define P91_PUC_DAC_IBM525 0x00008000 //
+#define P91_PUC_VGA_PRESENCE 0x02000000 //
+#define P91_PUC_VGA_ABSENT 0x00000000 //
+#define P91_PUC_VGA_PRESENT 0x02000000 //
+#define P91_PUC_INITIAL_MODSEL 0x04000000 //
+#define P91_PUC_NATIVE_MODE 0x00000000 //
+#define P91_PUC_VGA_MODE 0x04000000 //
+#define P91_PUC_CONFIG_REG_BASE 0x38000000 //
+#define P91_PUC_BASE_9100_9104 0x00000000 //
+#define P91_PUC_BASE_9108_910C 0x08000000 //
+#define P91_PUC_BASE_9110_9114 0x10000000 //
+#define P91_PUC_BASE_9118_911C 0x18000000 //
+#define P91_PUC_BASE_9120_9124 0x20000000 //
+#define P91_PUC_BASE_9128_912C 0x28000000 //
+#define P91_PUC_BASE_9130_9134 0x30000000 //
+#define P91_PUC_BASE_9138_913C 0x38000000 //
+#define P91_PUC_BUS_TYPE 0xC0000000 //
+#define P91_PUC_BUS_PCI 0x40000000 //
+#define P91_PUC_BUS_VESA 0x80000000 //
+
+//
+// Define Power up configuration bit field positions for use in shifting
+// the various fields to bit 0.
+//
+
+#define P91_PUC_EEPROM_SHIFT_CNT 0x01
+#define P91_PUC_SYNTH_SHIFT_CNT 0X05
+#define P91_PUC_RAMDAC_SHIFT_CNT 0x0C
+#define P91_PUC_REG_SHIFT_CNT 0x1B
+#define P91_PUC_BUS_SHIFT_CNT 0x1E
+
+//
+// Define the System Configuration Register Bits.
+// (Page 24)
+// 1 1 1 1 1 1 1 1
+// 9 7 6 4 3 2 1 0 9 8 0
+// -----------------------------------------
+// | - - - | - - - | - | - | - | - | - | 0 |
+// -----------------------------------------
+// | | | | | | | | | | | |
+// ----- ----- | | | | | -> Reserved. Must be 0.
+// | | | | | | -----> Pixel write buffer selection.
+// | | | | | ---------> Pixel read buffer selection.
+// | | | | -------------> Pixel access bit swap.
+// | | | -----------------> Pixel access byte swap.
+// | | ---------------------> Pixel access half-word swap.
+// | ---------------------------> Shift control 2.
+// -----------------------------------> Shift control 1.
+//
+// 3 3 2 2 2 2 2 2 2 2
+// 1 0 9 8 6 5 4 3 2 0
+// ---------------------------------------
+// | 0 | - - | - - - | - | - | - | - - - |
+// ---------------------------------------
+// | | | | | | | | | | |
+// | | ----- | | | -----
+// | | | | | | |
+// | | | | | | -----> Shift control 0.
+// | | | | | -----------> Overide internal PLL.
+// | | | | ---------------> Frame buffer controller drive load.
+// | | | -------------------> Disable internal selftiming on FBC.
+// | | -------------------------> Pixel size for drawing engine.
+// | --------------------------------> Shift control 3.
+// -------------------------------------> Reserved. Must be 0.
+//
+
+#define P91_WRITE_BUF_1 0x00000200
+#define P91_READ_BUF_1 0x00000400
+#define P91_SWAP_BITS 0x00000800
+#define P91_SWAP_BYTES 0x00001000
+#define P91_SWAP_WORDS 0x00002000
+#define P91_SHIFT2_0 0x00000000
+#define P91_SHIFT2_32 0x00004000
+#define P91_SHIFT2_64 0x00008000
+#define P91_SHIFT2_128 0x0000C000
+#define P91_SHIFT2_256 0x00010000
+#define P91_SHIFT2_512 0x00014000
+#define P91_SHIFT2_FIELD_INC 0x00004000
+#define P91_SHIFT1_0 0x00000000
+#define P91_SHIFT1_64 0x00040000
+#define P91_SHIFT1_128 0x00060000
+#define P91_SHIFT1_256 0x00080000
+#define P91_SHIFT1_512 0x000A0000
+#define P91_SHIFT1_1024 0x000C0000
+#define P91_SHIFT1_FIELD_INC 0x00020000
+#define P91_SHIFT0_0 0x00000000
+#define P91_SHIFT0_128 0x00300000
+#define P91_SHIFT0_256 0x00400000
+#define P91_SHIFT0_512 0x00500000
+#define P91_SHIFT0_1024 0x00600000
+#define P91_SHIFT0_2048 0x00700000
+#define P91_SHIFT0_FIELD_INC 0x00100000
+#define P91_EXT_PLL_CLOCK 0x00800000
+#define P91_DBL_DRIVE_LOAD 0x01000000
+#define P91_SELFTIME_DIS 0x02000000
+#define P91_DE_8BPP 0x08000000
+#define P91_DE_16BPP 0x0C000000
+#define P91_DE_24BPP 0x1C000000
+#define P91_DE_32BPP 0x14000000
+#define P91_SHIFT3_0 0x00000000
+#define P91_SHIFT3_1024 0x20000000
+#define P91_SHIFT3_2048 0x40000000
+#define P91_SHIFT3_4096 0x60000000
+#define P91_SHIFT3_FIELD_INC 0x20000000
+
+//
+// Define the Interrupt Register Bits.
+// Note: These are exactly the same as the Power 9000 bit definitions.
+// (Page 25)
+// 3
+// 1 6 5 4 3 2 1 0
+// -------------------------
+// | 0 | - - | - - | - - |
+// -------------------------
+// | | | | | | |
+// | | | | | | -----------------> Draw Engine Idle INT.
+// | | | | | -------------------> Draw Engine Idle INT Write Enable.
+// | | | | -----------------------> Pick Done INT.
+// | | | -------------------------> Pick Done INT. Write Enable.
+// | | -----------------------------> VBlank Done INT.
+// | -------------------------------> VBlank Done INT Write Enable.
+// ------------------------------------> Reserved. Must be 0.
+//
+
+#define P91_DE_IDLE 0x00000001
+#define P91_DE_IDLE_CLEAR 0x00000002
+#define P91_PICK_DONE 0x00000004
+#define P91_PICK_DONE_CLEAR 0x00000008
+#define P91_VBLANK_DONE 0x00000010
+#define P91_VBLANK_DONE_CLEAR 0x00000020
+
+//
+// Define the Interrupt Enable Register Bits.
+// Note: These are exactly the same as the Power 9000 bit definitions.
+// Page (26)
+// 3
+// 1 8 7 6 5 4 3 2 1 0
+// -------------------------------
+// | 0 | - - | - - | - - | - - |
+// -------------------------------
+// | | | | | | | | |
+// | | | | | | | | -----------> Draw Engine Int. Enable.
+// | | | | | | | -------------> Draw Engine Write Enable.
+// | | | | | | -----------------> Pick Int. Enable.
+// | | | | | -------------------> Pick Write Enable.
+// | | | | -----------------------> VBlank Int. Enable.
+// | | | -------------------------> VBlank Write Enable.
+// | | -----------------------------> Master Int. Enable.
+// | -------------------------------> Master Enable Write Enable.
+// ------------------------------------> Reserved. Must be 0.
+//
+
+#define P91_DE_IDLE_DIS 0x00000002 // Disable Draw Engine idle INT.
+#define P91_DE_IDLE_EN 0x00000003 // Enable Draw Engine idle INT.
+#define P91_PICKED_DIS 0x00000008 // Disable Pick INT.
+#define P91_PICKED_EN 0x0000000C // Enable Pick INT.
+#define P91_VBLANKED_DIS 0x00000020 // Disable VBlank INT.
+#define P91_VBLANKED_EN 0x00000030 // Enable VBlank INT.
+#define P91_MASTER_DIS 0x00000080 // Disable all interrupts.
+#define P91_MASTER_EN 0x000000C0 // Enable INTs according to bits 5-0.
+
+//
+// Define the Status Register Bits.
+// Note: These are exactly the same as the Power 9000 bit definitions.
+// (Page 28)
+// 3 3 2
+// 1 0 9 8 7 6 5 4 3 2 1 0
+// -----------------------------------------------
+// | - | - | 0 | - | - | - | - | - | - | - | - |
+// -----------------------------------------------
+// | | | | | | | | | | |
+// | | | | | | | | | | ----> Quad intersects clip window.
+// | | | | | | | | | --------> Quad inside clip window.
+// | | | | | | | | ------------> Quad outside clip window.
+// | | | | | | | ----------------> Quad is concave.
+// | | | | | | --------------------> Quad must be done by software.
+// | | | | | ------------------------> Blit must be done by software.
+// | | | | ----------------------------> Pixel must be done by software.
+// | | | --------------------------------> Pick detected.
+// | | -------------------------------------> Reserved.
+// | ------------------------------------------> Drawing engine busy.
+// -----------------------------------------------> Quad/blit re-initiate.
+//
+
+#define P91_SR_QUAD_INTERSECT 0x00000001
+#define P91_SR_QUAD_VISIBLE 0x00000002
+#define P91_SR_QUAD_HIDDEN 0x00000004
+#define P91_SR_QUAD_CONCAVE 0x00000008
+#define P91_SR_QUAD_SOFTWARE 0x00000010
+#define P91_SR_BLIT_SOFTWARE 0x00000020
+#define P91_SR_PIXEL_SOFTWARE 0x00000040
+#define P91_SR_PICKED 0x00000080
+#define P91_SR_ENGINE_BUSY 0x40000000
+#define P91_SR_NO_REINITIATE 0x80000000
+
+//
+// Define the Draw Mode Register Bits.
+// Note: These are exactly the same as the Power 9000 bit definitions.
+// Page (34)
+// 3
+// 1 4 3 2 1 0
+// -------------------
+// | 0 | - - | - - |
+// -------------------
+// | | | | |
+// | | | | -----------------------> Pick write enable bit.
+// | | | -------------------------> Write enable Pick write enable bit.
+// | | -----------------------------> Buffer selection bit.
+// | -------------------------------> Write enable Buffer selection bit.
+// ------------------------------------> Reserved. Must be 0.
+//
+
+#define P91_WR_INSIDE_WINDOW 0x00000002
+#define P91_SUPPRESS_ALL_WRITES 0x00000003
+#define P91_DE_DRAW_BUFF_0 0x00000008
+#define P91_DE_DRAW_BUFF_1 0x0000000C
+
+//
+// Define the Raster Register Bits.
+// (Page 34)
+// 3 1 1 1 1 1 1 1
+// 1 8 7 6 5 4 3 2 8 7 0
+// ---------------------------------------------------
+// | 0 | - | - | - | - | - | 0 | - - - - - - - - |
+// ---------------------------------------------------
+// | | | | | | | | | | | | | | |
+// | | | | | | | ---------------
+// | | | | | | | |
+// | | | | | | | --------> Minterms.
+// | | | | | | --------------------> Reserved.
+// | | | | | -------------------------> Solid Color Disable.
+// | | | | -----------------------------> Pattern Depth.
+// | | | ---------------------------------> Transparent Pixel1 Enable.
+// | | -------------------------------------> Quad Draw Mode.
+// | -----------------------------------------> Transparent Pattern Enable.
+// ----------------------------------------------> Reserved.
+//
+
+#define P91_RR_SOLID_ENABLE 0x00000000
+#define P91_RR_SOLID_DISABLE 0x00002000
+#define P91_RR_2_CLR_PATTERN 0x00000000
+#define P91_RR_4_CLR_PATTERN 0x00004000
+#define P91_RR_TRANS_PIX1_DISABL 0x00000000
+#define P91_RR_TRANS_PIX1_ENABLE 0x00008000
+#define P91_RR_QUAD_X11_MODE 0x00000000
+#define P91_RR_QUAD_OVERSIZE 0x00010000
+#define P91_RR_TRANS_PAT_DISABL 0x00000000
+#define P91_RR_TRANS_PAT_ENABLE 0x00020000
+
+//
+// Define the Screen Repaint Timing Control (SRTCTL) Register Bits.
+// (Page 40)
+// 3 1 1 1
+// 1 2 1 0 9 8 7 6 5 4 3 2 0
+// -------------------------------------------------
+// | 0 | - | - - | - | - | 0 | - | - | - | - - - |
+// -------------------------------------------------
+// | | | | | | | | | | | | |
+// | | --- | | | | | | -----
+// | | | | | | | | | |
+// | | | | | | | | | -----> QSF Counter Position.
+// | | | | | | | | -----------> Buffer For Display.
+// | | | | | | | ---------------> Screen Repaint Mode.
+// | | | | | | -------------------> Enable Video.
+// | | | | | -----------------------> Reserved.
+// | | | | ---------------------------> Internal Horizontal Sync.
+// | | | -------------------------------> Internal Vertical Sync.
+// | | ------------------------------------> SRADDR Increment Value.
+// | -----------------------------------------> 24-Bit DAC Clock Skip Mode.
+// ----------------------------------------------> Reserved.
+//
+
+#define P91_SRTCTL_QSF_MSK 0x00000007
+#define P91_SRTCTL_DISP_BUFFER 0x00000004
+#define P91_SRTCTL_DISP_BUFF_0 0x00000000
+#define P91_SRTCTL_DISP_BUFF_1 0x00000004
+#define P91_SRTCTL_HBLNK_RELOAD 0x00000010
+#define P91_SRTCTL_HR_NORMAL 0x00000000
+#define P91_SRTCTL_HR_RESTRICTED 0x00000010
+#define P91_SRTCTL_ENABLE_VIDEO 0x00000020
+#define P91_SRTCTL_HSYNC 0x00000080
+#define P91_SRTCTL_HSYNC_EXT 0x00000000
+#define P91_SRTCTL_HSYNC_INT 0x00000080
+#define P91_SRTCTL_VSYNC 0x00000100
+#define P91_SRTCTL_VSYNC_EXT 0x00000000
+#define P91_SRTCTL_VSYNC_INT 0x00000100
+#define P91_SRTCTL_SRC_INCS 0x00000600
+#define P91_SRTCTL_SRC_INC_256 0x00000000
+#define P91_SRTCTL_SRC_INC_512 0x00000200
+#define P91_SRTCTL_SRC_INC_1024 0x00000400
+#define P91_SRTCTL_V_24EN 0x00000800
+#define P91_SRTCTL_24EN_DISABLE 0x00000000
+#define P91_SRTCTL_24EN_ENABLE 0x00000800
+
+//
+// Define the Screen Repaint Timing Control 2 (SRTCTL2) Register Bits.
+// (Page 40)
+// 3
+// 1 4 3 2 1 0
+// -------------------
+// | 0 | - - | - - |
+// -------------------
+// | | | | |
+// | --- ---
+// | | |
+// | | ------------------------> External VSYNC Polarity Control.
+// | ------------------------------> External HSYNC Polarity Control.
+// ------------------------------------> Reserved.
+//
+
+#define P91_SRTCTL2_EXT_VSYNC 0x00000003
+
+#if 0
+#define P91_VSYNC_LOW_TRUE 0x00000000
+#define P91_VSYNC_HIGH_TRUE 0x00000001
+#endif
+
+#define P91_VSYNC_LOW_FORCED 0x00000002
+#define P91_VSYNC_HIGH_FORCED 0x00000003
+#define P91_SRTCTL2_EXT_HSYNC 0x0000000C
+
+#if 0
+#define P91_HSYNC_LOW_TRUE 0x00000000
+#define P91_HSYNC_HIGH_TRUE 0x00000004
+#endif
+
+#define P91_HSYNC_LOW_FORCED 0x00000008
+#define P91_HSYNC_HIGH_FORCED 0x0000000C
+
+//
+// Define the Memory Configuration Register Bits.
+// (Page 42)
+// 9 8 7 6 5 4 3 2 0
+// -------------------------------------
+// | - | - | - | - | - | - | - | - - - |
+// -------------------------------------
+// | | | | | | | | | |
+// | | | | | | | -----
+// | | | | | | | |
+// | | | | | | | -------> VRAM Memory Confiuration [2..0].
+// | | | | | | -------------> VRAM Row Miss Timing Adjustment.
+// | | | | | -----------------> VRAM Read Timing Adjustment.
+// | | | | ---------------------> VRAM Write Timing Adjustment.
+// | | | -------------------------> VCP Priority Select.
+// | | -----------------------------> RAMDAC Access Adjustment.
+// | ---------------------------------> DAC Read/Write signalling mode.
+// -------------------------------------> Memory/Video Reset.
+//
+// 2 2 1 1 1 1 1 1 1 1
+// 1 0 9 8 7 6 5 3 2 0
+// ---------------------------------------
+// | - | - | - | 0 | - - | - - - | - - - |
+// ---------------------------------------
+// | | | | | | | | | | | |
+// | | | | --- ----- -----
+// | | | | | | |
+// | | | | | | -----> VRAM Shift Clock State Macine.
+// | | | | | -------------> Internal CRTC Divided Dot Clock.
+// | | | | --------------------> Muxsel pin polarity.
+// | | | -------------------------> Reserved.
+// | | -----------------------------> Clock Edge Syrchonization.
+// | ---------------------------------> Video Clock Source Selection.
+// -------------------------------------> Additional Divide for Video Transfer.
+//
+// 3 3 2 2 2 2 2 2 2 2
+// 1 0 9 8 7 6 5 4 3 2
+// -----------------------------------
+// | - | - | - | - - | 0 | - - | - - |
+// -----------------------------------
+// | | | | | | | | | |
+// | | | --- --- ---
+// | | | | | | |
+// | | | | | | --------> Shift Clock Timing Pattern Selection.
+// | | | | | --------------> Serial Output Timing Pattern Selection.
+// | | | | -------------------> Reserved.
+// | | | ------------------------> Blank Generation Delay Selection.
+// | | -----------------------------> VRAM Memory Configuration [3].
+// | ---------------------------------> Slow Host Interface Adjustment.
+// -------------------------------------> VRAM REad Timing Adjustment.
+//
+//
+//
+
+#define P91_MC_CNFG_2_0_MSK 0x00000007
+#define P91_MC_CNFG_3_MSK 0x20000000
+#define P91_MC_CNFG_MSK 0x20000007
+#define P91_MC_CNFG_1 0x00000001 // 2 banks, 128K VRAMs, 1 1Mb buffer.
+#define P91_MC_CNFG_3 0x00000003 // 4 banks, 128K VRAMs, 1 2Mb buffer.
+#define P91_MC_CNFG_4 0x00000004 // 1 bank, 256K VRAMs, 1 1Mb buffer.
+#define P91_MC_CNFG_5 0x00000005 // 2 banks, 256K VRAMs, 1 2Mb buffer.
+#define P91_MC_CNFG_7 0x00000007 // 4 banks, 256K VRAMs, 1 4Mb buffer.
+#define P91_MC_CNFG_11 0x20000003 // 4 banks, 128K VRAMs, 2 1Mb buffers.
+#define P91_MC_CNFG_14 0x20000006 // 2 banks, 256K VRAMs, 2 1Mb buffers.
+#define P91_MC_CNFG_15 0x20000007 // 4 banks, 256K VRAMs, 2 2Mb buffers.
+#define P91_MC_MISS_ADJ_0 0x00000000
+#define P91_MC_MISS_ADJ_1 0x00000008
+#define P91_MC_READ_ADJ_0 0x00000000
+#define P91_MC_READ_ADJ_1 0x00000010
+#define P91_MC_WRITE_ADJ_0 0x00000000
+#define P91_MC_WRITE_ADJ_1 0x00000020
+#define P91_MC_VCP_PRIORITY_LO 0x00000000
+#define P91_MC_VCP_PRIORITY_HI 0x00000040
+#define P91_MC_DAC_ACCESS_ADJ_0 0x00000000
+#define P91_MC_DAC_ACCESS_ADJ_1 0x00000080
+#define P91_MC_DAC_MODE_0 0x00000000
+#define P91_MC_DAC_MODE_1 0x00000100
+#define P91_MC_HOLD_RESET 0x00000200
+#define P91_MC_MEM_VID_NORMAL 0x00000000
+#define P91_MC_MEM_VID_RESET 0x00000200
+#define P91_MC_SHFT_CLK_DIV_1 0x00000000
+#define P91_MC_SHFT_CLK_DIV_2 0x00000400
+#define P91_MC_SHFT_CLK_DIV_4 0x00000800
+#define P91_MC_SHFT_CLK_DIV_8 0x00000C00
+#define P91_MC_SHFT_CLK_DIV_16 0x00001000
+#define P91_MC_CRTC_CLK_DIV_1 0x00000000
+#define P91_MC_CRTC_CLK_DIV_2 0x00002000
+#define P91_MC_CRTC_CLK_DIV_4 0x00004000
+#define P91_MC_CRTC_CLK_DIV_8 0x00006000
+#define P91_MC_CRTC_CLK_DIV_16 0x00008000
+#define P91_MC_MUXSEL_NORMAL 0x00000000
+#define P91_MC_MUXSEL_INVERT 0x00010000
+#define P91_MC_MUXSEL_LOW 0x00020000
+#define P91_MC_MUXSEL_HIGH 0x00030000
+#define P91_MC_BLANK_EDGE_MSK 0x00080000
+#define P91_MC_SYNC_RISE_EDGE 0x00000000
+#define P91_MC_SYNC_FALL_EDGE 0x00080000
+#define P91_MC_VCLK_SRC_PIXCLK 0x00000000
+#define P91_MC_VCLK_SRC_DDOTCLK 0x00100000
+#define P91_MC_VAD_DIV_1 0x00000000
+#define P91_MC_VAD_DIV_2 0x00200000
+#define P91_MC_SHFT_CLK_1_BANK 0x00000000
+#define P91_MC_SHFT_CLK_2_BANK 0x00400000
+#define P91_MC_SHFT_CLK_4_BANK 0x00800000
+#define P91_MC_SERIAL_OUT_1_BANK 0x00000000
+#define P91_MC_SERIAL_OUT_2_BANK 0x01000000
+#define P91_MC_SERIAL_OUT_4_BANK 0x02000000
+#define P91_MC_BLNKDLY_MSK 0x18000000
+#define P91_MC_BLNKDLY_0_CLK 0x00000000
+#define P91_MC_BLNKDLY_1_CLK 0x08000000
+#define P91_MC_BLNKDLY_2_CLK 0x10000000
+#define P91_MC_BLNKDLY_3_CLK 0x18000000
+#define P91_MC_SLOW_HOST_ADJ_0 0x00000000
+#define P91_MC_SLOW_HOST_ADJ_1 0x40000000
+#define P91_MC_READ_SMPL_ADJ_0 0x00000000
+#define P91_MC_READ_SMPL_ADJ_1 0x80000000
+
+//
+// Miscellaneous command register bit definitions.
+//
+
+#define P91_QUAD_BUSY 0x80000000
+#define P91_BLIT_BUSY 0x80000000
+
+
+typedef union {
+ ULONG ul;
+ USHORT aw[2];
+ UCHAR aj[4];
+} UWB ;
+
+#define IBM525_WR_DAC(index, data) \
+{ \
+ ULONG ulIndex; \
+ UWB uwb; \
+ \
+ uwb.aj[0] = (UCHAR) data; \
+ uwb.aj[1] = uwb.aj[0]; \
+ uwb.aw[1] = uwb.aw[0]; \
+ \
+ ulIndex = index & ~0x3; \
+ \
+ P9_WR_REG(ulIndex, uwb.ul); \
+}
+
+#define IBM525_RD_DAC(index, val) \
+{ \
+ ULONG ulIndex; \
+ UWB uwb; \
+ \
+ ulIndex = index & ~0x3; \
+ \
+ uwb.ul = P9_RD_REG(ulIndex); \
+ \
+ uwb.aj[3] = uwb.aj[2]; \
+ uwb.aw[0] = uwb.aw[1]; \
+ \
+ val = uwb.aj[0]; \
+}
+
+#define CURS_ACTIVE_IBM525 (0x02)
+#define ENB_CURS_IBM525 (0x02)
+#define DIS_CURS_IBM525 ~CURS_ACTIVE_IBM525
+
+#define CURS_IS_ON_IBM525() \
+ (ReadIBM525(RGB525_CURSOR_CTL) & CURS_ACTIVE_IBM525)
+
+#define CURS_ON_IBM525() \
+ WriteIBM525(RGB525_CURSOR_CTL, (UCHAR) (ReadIBM525(RGB525_CURSOR_CTL) | ENB_CURS_IBM525))
+
+#define CURS_OFF_IBM525() \
+ WriteIBM525(RGB525_CURSOR_CTL, (UCHAR) (ReadIBM525(RGB525_CURSOR_CTL) & DIS_CURS_IBM525))
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxpcibrd.c b/private/ntos/nthals/halppc/ppc/pxpcibrd.c
new file mode 100644
index 000000000..3f6c28271
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxpcibrd.c
@@ -0,0 +1,1028 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxpcibrd.c
+
+Abstract:
+
+ Get PCI-PCI bridge information
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+ Jim Wooldridge
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge (jwooldridge@austin.vnet.ibm.com)
+ Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "stdio.h"
+
+// debugging only...
+// #define INIT_PCI_BRIDGE 1
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzReservedResources[];
+
+
+#if DBG
+#define DBGMSG(a) DbgPrint(a)
+#else
+#define DBGMSG(a)
+#endif
+
+
+
+#define IsPciBridge(a) \
+ (a->VendorID != PCI_INVALID_VENDORID && \
+ PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \
+ a->SubClass == 4 && a->BaseClass == 6)
+
+
+typedef struct {
+ ULONG BusNo;
+ PBUS_HANDLER BusHandler;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER SlotNumber;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG IO, Memory, PFMemory;
+ UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
+} CONFIGBRIDGE, *PCONFIGBRIDGE;
+
+//
+// Internal prototypes
+//
+
+
+#ifdef INIT_PCI_BRIDGE
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ );
+#endif
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG Base,
+ IN ULONG Limit
+ );
+
+
+ULONG
+HalpGetBridgedPCIInterrupt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetBridgedPCIISAInt (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ );
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ );
+
+NTSTATUS
+HalpGetBridgedPCIIrqTable (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PUCHAR IrqTable
+ );
+
+
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetPciBridgeConfig)
+#pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk)
+#pragma alloc_text(INIT,HalpFixupPciSupportedRanges)
+
+#ifdef INIT_PCI_BRIDGE
+#pragma alloc_text(PAGE,HalpGetBridgedPCIInterrupt)
+//#pragma alloc_text(PAGE,HalpGetBridgedPCIIrqTable)
+#pragma alloc_text(INIT,HalpGetPciBridgeNeeds)
+#endif
+#endif
+
+
+BOOLEAN
+HalpGetPciBridgeConfig (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus
+ )
+/*++
+
+Routine Description:
+
+ Scan the devices on all known pci buses trying to locate any
+ pci to pci bridges. Record the hierarchy for the buses, and
+ which buses have what addressing limits.
+
+Arguments:
+
+ HwType - Configuration type.
+ MaxPciBus - # of PCI buses reported by the bios
+
+--*/
+{
+ PBUS_HANDLER ChildBus;
+ PPCIPBUSDATA ChildBusData;
+ ULONG d, f, i, j, BusNo;
+ UCHAR Rescan;
+ BOOLEAN FoundDisabledBridge;
+ CONFIGBRIDGE CB;
+
+ Rescan = 0;
+ FoundDisabledBridge = FALSE;
+
+ //
+ // Find each bus on a bridge and initialize it's base and limit information
+ //
+
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Read PCI configuration information
+ //
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ // next device
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge, next function
+ continue;
+ }
+
+ if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is not enabled - skip it for now
+ FoundDisabledBridge = TRUE;
+ continue;
+ }
+
+ if ((ULONG) CB.PciData->u.type1.PrimaryBus !=
+ CB.BusHandler->BusNumber) {
+
+ DBGMSG ("HAL GetPciData: bad primarybus!!!\n");
+ // what to do?
+ }
+
+ //
+ // Found a PCI-PCI bridge. Determine it's parent child
+ // releationships
+ //
+
+ ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus);
+ if (!ChildBus) {
+ DBGMSG ("HAL GetPciData: found configured pci bridge\n");
+
+ // up the number of buses
+ if (CB.PciData->u.type1.SecondaryBus > Rescan) {
+ //Rescan = CB.PciData->u.type1.SecondaryBus; JAKETEMP
+ Rescan = CB.PciData->u.type1.SecondaryBus + 1;
+ }
+ continue;
+ }
+
+ ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
+ if (ChildBusData->BridgeConfigRead) {
+ // this child buses releationships already processed
+ continue;
+ }
+
+ //
+ // Remember the limits which are programmed into this bridge
+ //
+
+ ChildBusData->BridgeConfigRead = TRUE;
+ HalpSetBusHandlerParent (ChildBus, CB.BusHandler);
+ ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber;
+ ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
+
+ ChildBus->BusAddresses->IO.Base =
+ PciBridgeIO2Base(
+ CB.PciData->u.type1.IOBase,
+ CB.PciData->u.type1.IOBaseUpper16
+ );
+
+ ChildBus->BusAddresses->IO.Limit =
+ PciBridgeIO2Limit(
+ CB.PciData->u.type1.IOLimit,
+ CB.PciData->u.type1.IOLimitUpper16
+ );
+
+ //
+ // Special VGA address remapping occuring on this bridge?
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ HalpSetPciBridgedVgaCronk (
+ ChildBus->BusNumber,
+ (ULONG) ChildBus->BusAddresses->IO.Base,
+ (ULONG) ChildBus->BusAddresses->IO.Limit
+ );
+ }
+
+ //
+ // If supported I/O ranges on this bus are limitied to
+ // 256bytes on every 1K aligned boundry within the
+ // range, then redo supported IO BusAddresses to match
+ //
+
+ if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA &&
+ ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) {
+
+ // assume Base is 1K aligned
+ i = (ULONG) ChildBus->BusAddresses->IO.Base;
+ j = (ULONG) ChildBus->BusAddresses->IO.Limit;
+
+ // convert head entry
+ ChildBus->BusAddresses->IO.Limit = i + 256;
+ i += 1024;
+
+ // add remaining ranges
+ while (i < j) {
+ HalpAddRange (
+ &ChildBus->BusAddresses->IO,
+ 1, // address space
+ 0, // system base
+ i, // bus address
+ i + 256 // bus limit
+ );
+
+ // next range
+ i += 1024;
+ }
+ }
+
+ ChildBus->BusAddresses->Memory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase);
+
+ ChildBus->BusAddresses->Memory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit);
+
+ // On x86 it's ok to clip Prefetch to 32 bits
+ // BUGBUG This is OK on existing PPCs too, but this may have to change
+ // on later implementations.
+
+ if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) {
+ ChildBus->BusAddresses->PrefetchMemory.Base =
+ PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase);
+
+
+ ChildBus->BusAddresses->PrefetchMemory.Limit =
+ PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit);
+
+ if (CB.PciData->u.type1.PrefetchLimitUpper32) {
+ ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff;
+ }
+ }
+
+ // should call HalpAssignPCISlotResources to assign
+ // baseaddresses, etc...
+ }
+ }
+ }
+
+ if (Rescan) {
+ *MaxPciBus = Rescan;
+ return TRUE;
+ }
+
+ if (!FoundDisabledBridge) {
+ return FALSE;
+ }
+
+ DBGMSG ("HAL GetPciData: found disabled pci bridge\n");
+
+#ifdef INIT_PCI_BRIDGE
+ //
+ // We've calculated all the parent's buses known bases & limits.
+ // While doing this a pci-pci bus was found that the bios didn't
+ // configure. This is not expected, and we'll make some guesses
+ // at a configuration here and enable it.
+ //
+ // (this code is primarily for testing the above code since
+ // currently no system bioses actually configure the child buses)
+ //
+
+ for (BusNo=0; BusNo < *MaxPciBus; BusNo++) {
+
+ CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (!IsPciBridge (CB.PciData)) {
+ // not a PCI-PCI bridge
+ continue;
+ }
+
+ if ((CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) {
+ // this PCI bridge is enabled
+ continue;
+ }
+
+ //
+ // We have a disabled bus - assign it a number, then
+ // determine all the requirements of all devices
+ // on the other side of this bridge
+ //
+
+ CB.BusNo = BusNo;
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ }
+ }
+ }
+ // preform Rescan
+ return TRUE;
+
+#else
+
+ return FALSE;
+
+#endif
+
+}
+
+VOID
+HalpFixupPciSupportedRanges (
+ IN ULONG MaxBuses
+ )
+/*++
+
+Routine Description:
+
+ PCI-PCI bridged buses only see addresses which their parent
+ bueses support. So adjust any PCI SUPPORT_RANGES to be
+ a complete subset of all of it's parent buses.
+
+ PCI-PCI briges use postive address decode to forward addresses.
+ So, remove any addresses from any PCI bus which are bridged to
+ a child PCI bus.
+
+--*/
+{
+ ULONG i;
+ PBUS_HANDLER Bus, ParentBus;
+ PSUPPORTED_RANGES HRanges;
+
+ //
+ // Pass 1 - shrink all PCI supported ranges to be a subset of
+ // all of it's parent buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ HRanges = Bus->BusAddresses;
+ Bus->BusAddresses = HalpMergeRanges (
+ ParentBus->BusAddresses,
+ HRanges
+ );
+
+ HalpFreeRangeList (HRanges);
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Pass 2 - remove all child PCI bus ranges from parent PCI buses
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+
+ ParentBus = Bus->ParentHandler;
+ while (ParentBus) {
+
+ if (ParentBus->InterfaceType == PCIBus) {
+ HalpRemoveRanges (
+ ParentBus->BusAddresses,
+ Bus->BusAddresses
+ );
+ }
+
+ ParentBus = ParentBus->ParentHandler;
+ }
+ }
+
+ //
+ // Cleanup
+ //
+
+ for (i = 0; i < MaxBuses; i++) {
+ Bus = HalpHandlerForBus (PCIBus, i);
+ HalpConsolidateRanges (Bus->BusAddresses);
+ }
+}
+
+
+
+VOID
+HalpSetPciBridgedVgaCronk (
+ IN ULONG BusNumber,
+ IN ULONG BaseAddress,
+ IN ULONG LimitAddress
+ )
+/*++
+
+Routine Description: .
+
+ The 'vga compatible addresses' bit is set in the bridge control regiter.
+ This causes the bridge to pass any I/O address in the range of: 10bit
+ decode 3b0-3bb & 3c0-3df, as TEN bit addresses.
+
+ As far as I can tell this "feature" is an attempt to solve some problem
+ which the folks solving it did not fully understand, so instead of doing
+ it right we have this fine mess.
+
+ The solution is to take the least of all evils which is to remove any
+ I/O port ranges which are getting remapped from any IoAssignResource
+ request. (ie, IoAssignResources will never contimplate giving any
+ I/O port out in the suspected ranges).
+
+ note: memory allocation error here is fatal so don't bother with the
+ return codes.
+
+Arguments:
+
+ Base - Base of IO address range in question
+ Limit - Limit of IO address range in question
+
+--*/
+{
+ UNICODE_STRING unicodeString;
+ OBJECT_ATTRIBUTES objectAttributes;
+ HANDLE handle;
+ ULONG Length;
+ PCM_RESOURCE_LIST ResourceList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG AddressMSBs;
+ WCHAR ValueName[80];
+ NTSTATUS status;
+
+ //
+ // Open reserved resource settings
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzReservedResources);
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ return;
+ }
+
+ //
+ // Build resource list of reseved ranges
+ //
+
+ Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 *
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) +
+ sizeof (CM_RESOURCE_LIST);
+
+ ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, Length);
+ memset (ResourceList, 0, Length);
+
+ ResourceList->Count = 1;
+ ResourceList->List[0].InterfaceType = PCIBus;
+ ResourceList->List[0].BusNumber = BusNumber;
+ Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+
+ while (BaseAddress < LimitAddress) {
+ AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr
+
+ //
+ // Add xx3b0 through xx3bb
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0;
+ Descriptor->u.Port.Length = 0xb;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Add xx3c0 through xx3df
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0;
+ Descriptor->u.Port.Length = 0x1f;
+
+ Descriptor += 1;
+ ResourceList->List[0].PartialResourceList.Count += 1;
+
+ //
+ // Next range
+ //
+
+ BaseAddress += 1024;
+ }
+
+ //
+ // Add the reserved ranges to avoid during IoAssignResource
+ //
+
+ swprintf (ValueName, L"HAL_PCI_%d", BusNumber);
+ RtlInitUnicodeString (&unicodeString, ValueName);
+
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_RESOURCE_LIST,
+ ResourceList,
+ (ULONG) Descriptor - (ULONG) ResourceList
+ );
+
+
+ ExFreePool (ResourceList);
+ ZwClose (handle);
+}
+
+
+
+#ifdef INIT_PCI_BRIDGE
+
+VOID
+HalpGetPciBridgeNeeds (
+ IN ULONG HwType,
+ IN PUCHAR MaxPciBus,
+ IN PCONFIGBRIDGE Current
+ )
+{
+ ACCESS_MASK DesiredAccess;
+ UNICODE_STRING unicodeString;
+ PUCHAR buffer;
+ HANDLE handle;
+ OBJECT_ATTRIBUTES objectAttributes;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCONFIGURATION_COMPONENT Component;
+ CONFIGBRIDGE CB;
+ ULONG mnum, d, f, i;
+ NTSTATUS status;
+
+ buffer = ExAllocatePool (PagedPool, 1024);
+
+ // init
+ CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer;
+ CB.SlotNumber.u.bits.Reserved = 0;
+ Current->IO = Current->Memory = Current->PFMemory = 0;
+
+ //
+ // Assign this bridge an ID, and turn on configuration space
+ //
+
+ Current->PciData->u.type1.PrimaryBus = (UCHAR) Current->BusNo;
+ Current->PciData->u.type1.SecondaryBus = (UCHAR) *MaxPciBus;
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) 0xFF;
+ Current->PciData->u.type1.SecondaryStatus = 0xffff;
+ Current->PciData->Status = 0xffff;
+ Current->PciData->Command = 0;
+
+ Current->PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ KeStallExecutionProcessor (100);
+
+ Current->PciData->u.type1.BridgeControl = 0;
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ KeStallExecutionProcessor (100);
+
+ //
+ // Allocate new handler for bus
+ //
+
+ CB.BusHandler = HalpAllocateAndInitPciBusHandler (HwType, *MaxPciBus, FALSE);
+ CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData;
+ CB.BusNo = *MaxPciBus;
+ *MaxPciBus += 1;
+
+ //
+ // Add another PCI bus in the registry
+ //
+
+ mnum = 0;
+ for (; ;) {
+ //
+ // Find next available MultiFunctionAdapter key
+ //
+
+ DesiredAccess = KEY_READ | KEY_WRITE;
+ swprintf ((PWCHAR) buffer, L"%s\\%d", rgzMultiFunctionAdapter, mnum);
+ RtlInitUnicodeString (&unicodeString, (PWCHAR) buffer);
+
+ InitializeObjectAttributes( &objectAttributes,
+ &unicodeString,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ status = ZwOpenKey( &handle, DesiredAccess, &objectAttributes);
+ if (!NT_SUCCESS(status)) {
+ break;
+ }
+
+ // already exists, next
+ ZwClose (handle);
+ mnum += 1;
+ }
+
+ ZwCreateKey (&handle,
+ DesiredAccess,
+ &objectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ &d
+ );
+
+ //
+ // Add needed registry values for this MultifucntionAdapter entry
+ //
+
+ RtlInitUnicodeString (&unicodeString, rgzIdentifier);
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_SZ,
+ L"PCI",
+ sizeof (L"PCI")
+ );
+
+ RtlInitUnicodeString (&unicodeString, rgzConfigurationData);
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer;
+ Descriptor->InterfaceType = PCIBus;
+ Descriptor->BusNumber = CB.BusNo;
+ Descriptor->PartialResourceList.Version = 0;
+ Descriptor->PartialResourceList.Revision = 0;
+ Descriptor->PartialResourceList.Count = 0;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_FULL_RESOURCE_DESCRIPTOR,
+ Descriptor,
+ sizeof (*Descriptor)
+ );
+
+
+ RtlInitUnicodeString (&unicodeString, L"Component Information");
+ Component = (PCONFIGURATION_COMPONENT) buffer;
+ RtlZeroMemory (Component, sizeof (*Component));
+ Component->AffinityMask = 0xffffffff;
+ ZwSetValueKey (handle,
+ &unicodeString,
+ 0L,
+ REG_BINARY,
+ Component,
+ FIELD_OFFSET (CONFIGURATION_COMPONENT, ConfigurationDataLength)
+ );
+
+ ZwClose (handle);
+
+
+ //
+ // Since the BIOS didn't configure this bridge we'll assume that
+ // the PCI interrupts are bridged. (for BIOS configured buses we
+ // assume that the BIOS put the ISA bus IRQ in the InterruptLine value)
+ //
+
+ CB.BusData->Pin2Line = (PciPin2Line) HalpPCIBridgedPin2Line;
+ CB.BusData->Line2Pin = (PciLine2Pin) HalpPCIBridgedLine2Pin;
+ //CB.BusData->GetIrqTable = (PciIrqTable) HalpGetBridgedPCIIrqTable;
+
+ if (Current->BusHandler->GetInterruptVector == HalpGetPCIIntOnISABus) {
+
+ //
+ // The parent bus'es interrupt pin to vector mappings is not
+ // a static function, and is determined by the boot firmware.
+ //
+
+ //CB.BusHandler->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetBridgedPCIISAInt;
+
+ // read each device on parent bus
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (CB.PciData->u.type0.InterruptPin &&
+ (PCI_CONFIG_TYPE (CB.PciData) == PCI_DEVICE_TYPE ||
+ PCI_CONFIG_TYPE (CB.PciData) == PCI_BRIDGE_TYPE)) {
+
+ // get bios supplied int mapping
+ i = CB.PciData->u.type0.InterruptPin + d % 4;
+ CB.BusData->SwizzleIn[i] = CB.PciData->u.type0.InterruptLine;
+ }
+ }
+ }
+
+ } else {
+ _asm int 3;
+ }
+
+ //
+ // Look at each device on the bus and determine it's resource needs
+ //
+
+ for (d = 0; d < PCI_MAX_DEVICES; d++) {
+ CB.SlotNumber.u.bits.DeviceNumber = d;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ CB.SlotNumber.u.bits.FunctionNumber = f;
+
+ HalpReadPCIConfig (
+ CB.BusHandler,
+ CB.SlotNumber,
+ CB.PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ if (CB.PciData->VendorID == PCI_INVALID_VENDORID) {
+ break;
+ }
+
+ if (IsPciBridge (CB.PciData)) {
+ // oh look - another bridge ...
+ HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB);
+ continue;
+ }
+
+ if (PCI_CONFIG_TYPE (CB.PciData) != PCI_DEVICE_TYPE) {
+ continue;
+ }
+
+ // found a device - figure out the resources it needs
+ }
+ }
+
+ //
+ // Found all sub-buses set SubordinateBus accordingly
+ //
+
+ Current->PciData->u.type1.SubordinateBus = (UCHAR) *MaxPciBus - 1;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+
+ //
+ // Set the bridges IO, Memory, and Prefetch Memory windows
+ //
+
+ // For now just pick some numbers & set everyone the same
+ // IO 0x6000 - 0xFFFF
+ // MEM 0x40000000 - 0x4FFFFFFF
+ // PFMEM 0x50000000 - 0x5FFFFFFF
+
+ Current->PciData->u.type1.IOBase = 0x6000 >> 12 << 4;
+ Current->PciData->u.type1.IOLimit = 0xffff >> 12 << 4;
+ Current->PciData->u.type1.MemoryBase = 0x40000000 >> 20 << 4;
+ Current->PciData->u.type1.MemoryLimit = 0x4fffffff >> 20 << 4;
+ Current->PciData->u.type1.PrefetchBase = 0x50000000 >> 20 << 4;
+ Current->PciData->u.type1.PrefetchLimit = 0x5fffffff >> 20 << 4;
+
+ Current->PciData->u.type1.PrefetchBaseUpper32 = 0;
+ Current->PciData->u.type1.PrefetchLimitUpper32 = 0;
+ Current->PciData->u.type1.IOBaseUpper16 = 0;
+ Current->PciData->u.type1.IOLimitUpper16 = 0;
+ Current->PciData->u.type1.BridgeControl =
+ PCI_ENABLE_BRIDGE_ISA;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ HalpReadPCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ Current->PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ // enable memory & io decodes
+
+ Current->PciData->Command =
+ PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER;
+
+ HalpWritePCIConfig (
+ Current->BusHandler,
+ Current->SlotNumber,
+ &Current->PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (Current->PciData->Command)
+ );
+
+ ExFreePool (buffer);
+}
+
+VOID
+HalpPCIBridgedPin2Line (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+ This function maps the device's InterruptPin to an InterruptLine
+ value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Convert slot Pin into Bus INTA-D.
+ //
+
+ i = (PciData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+
+VOID
+HalpPCIBridgedLine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+ test function particular to dec pci-pci bridge card
+
+--*/
+{
+ PPCIPBUSDATA BusData;
+ ULONG i;
+
+ if (!PciNewData->u.type0.InterruptPin) {
+ return ;
+ }
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ i = (PciNewData->u.type0.InterruptPin +
+ SlotNumber.u.bits.DeviceNumber - 1) % 4;
+
+ PciNewData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR;
+ PciNewData->u.type0.InterruptLine = 0x0b ^ IRQXOR;
+}
+
+#endif
diff --git a/private/ntos/nthals/halppc/ppc/pxpcibus.c b/private/ntos/nthals/halppc/ppc/pxpcibus.c
new file mode 100644
index 000000000..438d63963
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxpcibus.c
@@ -0,0 +1,2386 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft 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;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len;
+ ULONG i, bit;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue
+ // in the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested at least some data within the
+ // common header. Read the whole header, effect the
+ // fields we need to and then copy the user's requested
+ // bytes from the header
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len, cnt;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if DBG
+ cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
+#endif
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
+
+#if DBG
+ //
+ // Verify R/O fields haven't changed
+ //
+ if (PciData2->VendorID != PciData->VendorID ||
+ PciData2->DeviceID != PciData->DeviceID ||
+ PciData2->RevisionID != PciData->RevisionID ||
+ PciData2->ProgIf != PciData->ProgIf ||
+ PciData2->SubClass != PciData->SubClass ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->HeaderType != PciData->HeaderType ||
+ PciData2->BaseClass != PciData->BaseClass ||
+ PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
+ PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
+ DbgPrint ("PCI SetBusData: Read-Only configuration value changed\n");
+// DbgBreakPoint ();
+ }
+#endif
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, iBuffer2+Offset, Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and write it
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpWritePCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+VOID
+HalpReadPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigRead);
+}
+
+VOID
+HalpWritePCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ if (!HalpValidPCISlot (BusHandler, Slot)) {
+ //
+ // Invalid SlotID do nothing
+ //
+ return ;
+ }
+
+ HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
+ PCIConfigHandler.ConfigWrite);
+}
+
+BOOLEAN
+HalpValidPCISlot (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ PPCIPBUSDATA BusData;
+ UCHAR HeaderType;
+ ULONG i;
+
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ if (Slot.u.bits.Reserved != 0) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) { //IBMCPK: added =
+ return FALSE;
+ }
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Sandalfoot doesn't support Multifunction adapters
+ //
+
+// return FALSE;
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.AsULONG);
+
+
+}
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+
+}
+
+
+ULONG
+HalpPCIReadUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfg1->u.AsULONG + i));
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT)(PciCfg1->u.AsULONG + i));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfg1->u.AsULONG));
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_UCHAR (PciCfg1->u.AsULONG + i, *Buffer );
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_USHORT (PciCfg1->u.AsULONG + i, *((PUSHORT) Buffer) );
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType1 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG (PciCfg1->u.AsULONG, *((PULONG) Buffer) );
+ return sizeof (ULONG);
+}
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = HalpTranslatePciSlotNumber(BusHandler->BusNumber, Slot.u.AsULONG);
+
+ KeRaiseIrql (PROFILE_LEVEL, Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+
+
+
+}
+
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+
+}
+
+
+ULONG
+HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ union {
+ ULONG All;
+ UCHAR Bytes[4];
+ } Tmp;
+
+ i = Offset % sizeof(ULONG);
+ PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ WRITE_PORT_ULONG(BusData->Config.Type2.Address, PciCfg1->u.AsULONG);
+ Tmp.All = READ_PORT_ULONG(BusData->Config.Type2.Data);
+ *Buffer = Tmp.Bytes[i];
+
+// 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/halppc/ppc/pxpciint.c b/private/ntos/nthals/halppc/ppc/pxpciint.c
new file mode 100644
index 000000000..a67e2d109
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxpciint.c
@@ -0,0 +1,254 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpciint.c
+
+Abstract:
+
+ All PCI bus interrupt mapping is in this module, so that a real
+ system which doesn't have all the limitations which PC PCI
+ systems have can replaced this code easly.
+ (bus memory & i/o address mappings can also be fix here)
+
+Author:
+
+ Ken Reneris
+ Jim Wooldridge - Ported to PowerPC
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#endif
+
+#define PCI_DISPLAY_CONTROLLER 0x03
+#define PCI_PRE_REV_2 0x0
+#define IsVideoDevice(a) \
+ (((a->BaseClass == PCI_DISPLAY_CONTROLLER) && \
+ (a->SubClass == 0)) || \
+ (((a->BaseClass == PCI_PRE_REV_2) && \
+ (a->SubClass == 1))))
+
+#define P91_DEVICE_ID 0x9100100E
+extern PHYSICAL_ADDRESS HalpP9CoprocPhysicalAddress; // in pxp91.c
+
+ULONG
+HalpGetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+ if (BusInterruptLevel < 1) {
+ // bogus bus level
+ return 0;
+ }
+
+
+ //
+ // Current PCI buses just map their IRQs ontop of the ISA space,
+ // so foreward this to the isa handler for the isa vector
+ // (the isa vector was saved away at either HalSetBusData or
+ // IoAssignReosurces time - if someone is trying to connect a
+ // PCI interrupt without performing one of those operations first,
+ // they are broken).
+ //
+
+ return HalGetInterruptVector (
+ Internal, 0,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity
+ );
+}
+
+
+VOID
+HalpPCIPin2ISALine (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciData
+ )
+/*++
+
+// This function maps the device's InterruptPin to an InterruptLine
+// value.
+//
+// On Sandalfoot and Polo machines PCI interrupts are statically routed
+// via slot number. This routine just returns and the static routing
+// is done in HalpGetIsaFixedPCIIrq
+//
+
+--*/
+{
+
+
+}
+
+
+
+VOID
+HalpPCIISALine2Pin (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER SlotNumber,
+ IN PPCI_COMMON_CONFIG PciNewData,
+ IN PPCI_COMMON_CONFIG PciOldData
+ )
+/*++
+
+ This functions maps the device's InterruptLine to it's
+ device specific InterruptPin value.
+
+
+--*/
+{
+}
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+ Rewrite the callers requested resource list to fit within
+ the supported ranges of this bus
+--*/
+{
+ NTSTATUS Status;
+ PPCIPBUSDATA BusData;
+ PCI_SLOT_NUMBER PciSlot;
+ PSUPPORTED_RANGE Interrupt;
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG cnt;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+
+ //
+ // Determine PCI device's interrupt restrictions
+ //
+
+ Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ //
+ // Adjust resources
+ //
+
+ Status = HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ Interrupt,
+ pResourceList
+ );
+
+ ExFreePool (Interrupt);
+
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+ //
+ // This next part is a major HACK. The Weitek video
+ // adapter (which is one of IBM's favorites) needs
+ // to have its frame buffer enabled by the HAL so
+ // that the HAL can write to the screen. The device
+ // driver for this card needs to touch the frame buffer
+ // during its initialization phase, which overlaps with
+ // the period of time that the HAL is writing to the
+ // screen. So, to avoid breaking one or the other,
+ // we need to force the device driver to use the
+ // same I/O space for the frame buffer that the HAL
+ // was using. Unfortunately, this is the only place
+ // to do it. -- Jake Oshins 1/2/96
+
+ // The Baby Blue and Sky Blue video adapters from IBM
+ // have the same requirements. -- Jake Oshins 7/11/96
+
+ HalpGetPCIData(BusHandler,
+ RootHandler,
+ PciSlot,
+ PciData,
+ 0,
+ PCI_COMMON_HDR_LENGTH
+ );
+
+ //
+ // We want to do this only for certain video devices that are
+ // already decoding a range of memory.
+ //
+ if (((PciData->VendorID == 0x1014) || // IBM video devices
+ (PciData->VendorID == 0x100E)) && // Weitek video devices
+ (PciData->u.type0.BaseAddresses[0] & 0xfffffff0))
+ {
+ for (cnt = (*pResourceList)->List->Count; cnt; cnt--) {
+ switch ((*pResourceList)->List->Descriptors->Type) {
+ case CmResourceTypeInterrupt:
+ case CmResourceTypePort:
+ case CmResourceTypeDma:
+ break;
+
+ case CmResourceTypeMemory:
+
+ //
+ // Set the bottom of the range to the value in the Base Address Register
+ //
+ (*pResourceList)->List->Descriptors->u.Memory.MinimumAddress.LowPart =
+ PciData->u.type0.BaseAddresses[0];
+
+ //
+ // Set the top of the range to the BAR plus the requested length
+ //
+ (*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart =
+ PciData->u.type0.BaseAddresses[0] +
+ (*pResourceList)->List->Descriptors->u.Memory.Length;
+
+ }
+
+ }
+
+ }
+
+ return Status;
+
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxpcisup.c b/private/ntos/nthals/halppc/ppc/pxpcisup.c
new file mode 100644
index 000000000..89fc67141
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxpcisup.c
@@ -0,0 +1,326 @@
+
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1996 International Business Machines Corporation
+
+Module Name:
+
+ pxmemctl.c
+
+Abstract:
+
+ The module initializes any planar registers.
+ This module also implements machince check parity error handling.
+
+Author:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com)
+
+
+Revision History:
+
+ T. White -- Added dword I/O to allow GXT150P to work correctly
+
+Special Note:
+
+ Please make sure that the dword I/O mechanisms are carried
+ forward for any box which is to support the GXT150P graphics
+ adapter. The GXT150P graphics adapter runs in any PowerPC
+ machine with a standard PCI bus connector.
+
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+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 HalpPciConfigSlot[] = { 0x0800,
+ 0x1000,
+ 0x2000,
+ 0x4000,
+ 0x8000,
+ 0x10000,
+ 0x20000,
+ 0x40000,
+ };
+ULONG HalpPciMaxSlots = 7;
+
+ULONG
+HalpTranslatePciSlotNumber (
+ ULONG BusNumber,
+ ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+
+ This routine translate a PCI slot number to a PCI device number.
+ This is a sandalfoot memory map implementation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ //
+ // Sandalfoot only has 1 PCI bus so bus number is unused
+ //
+
+ UNREFERENCED_PARAMETER(BusNumber);
+
+ return ((ULONG) ((PUCHAR) HalpPciConfigBase + HalpPciConfigSlot[SlotNumber]));
+
+}
+
+
+ULONG
+HalpPhase0SetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes to PCI configuration space prior to bus handler installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns length of data written.
+
+--*/
+
+{
+ PUCHAR to;
+ PUCHAR from;
+ ULONG tmpLength;
+ PULONG ulong_to, ulong_from;
+
+ if (SlotNumber < HalpPciMaxSlots) {
+
+ to = (PUCHAR)HalpPciConfigBase + HalpPciConfigSlot[SlotNumber];
+ to += Offset;
+ from = Buffer;
+
+ // The GXT150P graphics adapter requires the use of dword I/O
+ // to some of its PCI configuration registers. Therefore, this
+ // code uses dword I/O when possible.
+
+ // If the bus address is not dword aligned or the length
+ // is not a multiple of 4 (dword size) bytes, then use byte I/O
+ if(((ULONG)to & 0x3)||(Length & 0x3)){
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ *to++ = *from++;
+ tmpLength--;
+ }
+ // If the bus address is dword aligned and the length is
+ // a multiple of 4 (dword size) bytes, then use dword I/O
+ }else{
+ ulong_to = (PULONG) to;
+ ulong_from = (PULONG) from;
+ tmpLength = Length >> 2;
+ while (tmpLength > 0) {
+ *ulong_to++ = *ulong_from++;
+ tmpLength--;
+ }
+ }
+
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+ULONG
+HalpPhase0GetPciDataByOffset (
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PUCHAR Buffer,
+ ULONG Offset,
+ ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads PCI config space prior to bus handlder installation.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Amount of data read.
+
+--*/
+
+{
+ PUCHAR to;
+ PUCHAR from;
+ ULONG tmpLength;
+ PULONG ulong_to, ulong_from;
+
+ if (SlotNumber < HalpPciMaxSlots) {
+
+ from = (PUCHAR)HalpPciConfigBase + HalpPciConfigSlot[SlotNumber];
+ from += Offset;
+ to = Buffer;
+
+ // The GXT150P graphics adapter requires the use of dword I/O
+ // to some of its PCI configuration registers. Therefore, this
+ // code uses dword I/O when possible.
+
+ // If the bus address is not dword aligned or the length
+ // is not a multiple of 4 (dword size) bytes, then use byte I/O
+ if(((ULONG)from & 0x3)||(Length & 0x3)){
+ tmpLength = Length;
+ while (tmpLength > 0) {
+ *to++ = *from++;
+ tmpLength--;
+ }
+ // If the bus address is dword aligned and the length is
+ // a multiple of 4 (dword size) bytes, then use dword I/O
+ }else{
+ ulong_to = (PULONG) to;
+ ulong_from = (PULONG) from;
+ tmpLength = Length >> 2;
+ while (tmpLength > 0) {
+ *ulong_to++ = *ulong_from++;
+ tmpLength--;
+ }
+ }
+
+ return(Length);
+ }
+ else {
+ return (0);
+ }
+}
+
+NTSTATUS
+HalpGetPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ ULONG buffer[PCI_COMMON_HDR_LENGTH/sizeof(ULONG)];
+ PPCI_COMMON_CONFIG PciData;
+
+#define PCI_VENDOR_NCR 0x1000
+
+ 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 (PciSlot.u.bits.DeviceNumber == 1) {
+ (*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;
+ }
+
+#if defined(SOFT_HDD_LAMP)
+
+ if ( (PciData->BaseClass == 1) ||
+ ( (PciData->VendorID == PCI_VENDOR_NCR) && (PciData->DeviceID == 1) ) ) {
+ //
+ // This device is a Mass Storage Controller, set flag to
+ // turn on the HDD Lamp when interrupts come in on this
+ // vector.
+ //
+ // N.B. We recognize NCR 810 controllers as they were implemented
+ // before class codes.
+ //
+
+ extern ULONG HalpMassStorageControllerVectors;
+
+ HalpMassStorageControllerVectors |= 1 << (*Interrupt)->Base;
+ }
+
+#endif
+
+ 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
+
+--*/
+{
+ // Sandalfoot doesn't support plug-in PCI busses!!!
+
+ return;
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxport.c b/private/ntos/nthals/halppc/ppc/pxport.c
new file mode 100644
index 000000000..005a02924
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxport.c
@@ -0,0 +1,848 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a PowerPC system.
+
+
+Author:
+
+ David N. Cutler (davec) 28-Apr-1991
+ Chuck Bauman 02-Jun-1993
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+ Steve Johns (sjohns@pets.sps.mot.com)
+ - added support for multple baud rates, alternate COM port
+ - implemented KdPortSave & KdPortRestore
+
+--*/
+
+#include "halp.h"
+#include "ppcserp.h"
+
+#include <pxmemctl.h>
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+ULONG KdCurrentBaudRate= 19200;
+ULONG KdCurrentComPort = COM1_PORT;
+ULONG HalpSavedBaudRate;
+ULONG HalpSavedComPort;
+
+extern PVOID HalpIoControlBase;
+
+//
+// Define serial port read and write addresses.
+//
+
+#define SP_READ ((PSP_READ_REGISTERS)((PUCHAR)HalpIoControlBase + KdCurrentComPort))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)((PUCHAR)HalpIoControlBase + KdCurrentComPort))
+
+
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+UCHAR HalpBaudRateDivisor = 6;
+
+//
+// Define hardware PTE's that map the serial port used by the debugger.
+//
+
+
+ULONG
+HalpGetByte (
+ IN PCHAR Input,
+ IN BOOLEAN Wait
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+ Wait - Supplies a boolean value that detemines whether a timeout
+ is applied to the input operation.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ SP_LINE_STATUS LsrByte;
+ UCHAR DataByte;
+ ULONG TimeoutCount;
+
+
+ //
+ // Attempt to read a byte from the debugger port until a byte is
+ // available or until a timeout occurs.
+ //
+
+ TimeoutCount = Wait ? TIMEOUT_COUNT : 1;
+ do {
+ TimeoutCount -= 1;
+ //
+ // Wait until data is available in the receive buffer.
+ //
+
+ KeStallExecutionProcessor(1);
+ LsrByte = KdReadLsr(TRUE);
+ if (LsrByte.DataReady == 0) {
+ continue;
+ }
+
+ //
+ // Read input byte and store in callers buffer.
+ //
+
+ *Input = READ_REGISTER_UCHAR(&SP_READ->ReceiveBuffer);
+
+ //
+ // If using modem controls, then skip any incoming data while
+ // ReceiveData not set.
+ //
+
+ if (KdUseModemControl) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect == 0) {
+ continue;
+ }
+ }
+
+ //
+ // Return function value as the not of the error indicators.
+ //
+ if (LsrByte.ParityError ||
+ LsrByte.FramingError ||
+ LsrByte.OverrunError ||
+ LsrByte.BreakIndicator) {
+ return CP_GET_ERROR;
+ }
+
+ return CP_GET_SUCCESS;
+ } while(TimeoutCount != 0);
+
+ return CP_GET_NODATA;
+}
+
+BOOLEAN
+KdPortInitialize (
+ PDEBUG_PARAMETERS DebugParameters,
+ PLOADER_PARAMETER_BLOCK LoaderBlock,
+ BOOLEAN Initialize
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the serial port used by the kernel debugger
+ and must be called during system initialization.
+
+Arguments:
+
+ DebugParameters - Supplies a pointer to the debug port parameters.
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ Initialize - Specifies a boolean value that determines whether the
+ debug port is initialized or just the debug port parameters
+ are captured.
+
+Return Value:
+
+ A value of TRUE is returned is the port was successfully initialized.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ UCHAR DataByte;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_SERIAL_DEVICE_DATA DeviceData;
+ ULONG KdPortEntry;
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+
+/*
+ //
+ // Find the configuration information for the first serial port.
+ //
+
+ if (LoaderBlock != NULL) {
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ SerialController,
+ &MatchKey);
+
+ } else {
+ ConfigurationEntry = NULL;
+ }
+
+ if (DebugParameters->BaudRate != 0) {
+ BaudRate = DebugParameters->BaudRate;
+ } else {
+ BaudRate = 19200;
+ }
+
+
+ //
+ // If the serial configuration entry was not found or the frequency
+ // specified is not supported, then default the baud clock to 800000.
+ //
+
+ BaudClock = 8000000;
+ if (ConfigurationEntry != NULL) {
+ List = (PCM_PARTIAL_RESOURCE_LIST)ConfigurationEntry->ConfigurationData;
+ Descriptor = &List->PartialDescriptors[List->Count];
+ DeviceData = (PCM_SERIAL_DEVICE_DATA)Descriptor;
+ if ((DeviceData->BaudClock == 1843200) ||
+ (DeviceData->BaudClock == 4233600) ||
+ (DeviceData->BaudClock == 8000000)) {
+ BaudClock = DeviceData->BaudClock;
+ }
+ }
+
+ HalpGetDivisorFromBaud(
+ BaudClock,
+ BaudRate,
+ &HalpBaudRateDivisor
+ );
+
+
+*/
+
+ //
+ // Map I/O space if it has not already been mapped.
+ //
+
+
+ if (HalpIoControlBase == NULL) {
+
+ HalpIoControlBase = (PVOID)KePhase0MapIo(IO_CONTROL_PHYSICAL_BASE,
+ 0x20000);
+
+ if ( !HalpIoControlBase ) {
+ return FALSE;
+ }
+ }
+
+
+
+ //
+ // Set COM parameters
+ //
+ if (DebugParameters != NULL) {
+ if (DebugParameters->BaudRate == 0)
+ KdCurrentBaudRate = 19200; // default baud rate
+ else
+ KdCurrentBaudRate = DebugParameters->BaudRate;
+
+ if (DebugParameters->CommunicationPort > 2)
+ return (FALSE);
+ KdCurrentComPort = COM1_PORT; // default COM port
+ if (DebugParameters->CommunicationPort == 1)
+ KdCurrentComPort = COM1_PORT;
+ if (DebugParameters->CommunicationPort == 2)
+ KdCurrentComPort = COM2_PORT;
+
+ }
+
+ HalpBaudRateDivisor = (UCHAR)((1843200/16) / KdCurrentBaudRate);
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+
+
+
+ KdComPortInUse=(PUCHAR)KdCurrentComPort;
+
+
+ //
+ // Clear the divisor latch, clear all interrupt enables, and reset and
+ // disable the FIFO's.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, 0x0);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+ DataByte = 0;
+ ((PSP_FIFO_CONTROL)(&DataByte))->ReceiveFifoReset = 1;
+ ((PSP_FIFO_CONTROL)(&DataByte))->TransmitFifoReset = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->FifoControl, DataByte);
+
+ //
+ // Set the divisor latch and set the baud rate to requested rate.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, HalpBaudRateDivisor);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable, 0x0);
+
+ //
+ // Clear the divisor latch and set the character size to eight bits
+ // with one stop bit and no parity checking.
+ //
+
+ DataByte = 0;
+ ((PSP_LINE_CONTROL)(&DataByte))->CharacterSize = EIGHT_BITS;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+
+ //
+ // Set data terminal ready and request to send.
+ //
+
+ DataByte = 0;
+ ((PSP_MODEM_CONTROL)(&DataByte))->DataTerminalReady = 1;
+ ((PSP_MODEM_CONTROL)(&DataByte))->RequestToSend = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->ModemControl, DataByte);
+
+ return TRUE;
+}
+
+ULONG
+KdPortGetByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error is encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ return HalpGetByte(Input, TRUE);
+}
+
+ULONG
+KdPortPollByte (
+ OUT PUCHAR Input
+ )
+
+/*++
+
+Routine Description:
+
+ This routine gets a byte from the serial port used by the kernel
+ debugger iff a byte is available.
+
+ N.B. It is assumed that the IRQL has been raised to the highest
+ level, and necessary multiprocessor synchronization has been
+ performed before this routine is called.
+
+Arguments:
+
+ Input - Supplies a pointer to a variable that receives the input
+ data byte.
+
+Return Value:
+
+ CP_GET_SUCCESS is returned if a byte is successfully read from the
+ kernel debugger line.
+
+ CP_GET_ERROR is returned if an error encountered during reading.
+
+ CP_GET_NODATA is returned if timeout occurs.
+
+--*/
+
+{
+
+ ULONG Status;
+
+ //
+ // Save port status, map the serial controller, get byte from the
+ // debugger port is one is avaliable, restore port status, unmap
+ // the serial controller, and return the operation status.
+ //
+
+
+ KdPortSave();
+ Status = HalpGetByte(Input, FALSE);
+ KdPortRestore();
+ return Status;
+}
+
+VOID
+KdPortPutByte (
+ IN UCHAR Output
+ )
+
+/*++
+
+Routine Description:
+
+ This routine puts a byte to the serial port used by the kernel debugger.
+
+ N.B. It is assumed that the IRQL has been raised to the highest level,
+ and necessary multiprocessor synchronization has been performed
+ before this routine is called.
+
+Arguments:
+
+ Output - Supplies the output data byte.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ PSP_MODEM_STATUS LsrByte;
+
+ if (KdUseModemControl) {
+ //
+ // Modem control, make sure DSR, CTS and CD are all set before
+ // sending any data.
+ //
+
+ for (; ;) {
+ DataByte = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ if ( ((PSP_MODEM_STATUS)&DataByte)->ClearToSend &&
+ ((PSP_MODEM_STATUS)&DataByte)->DataSetReady &&
+ ((PSP_MODEM_STATUS)&DataByte)->ReceiveDetect ) {
+ break;
+ }
+
+ KdReadLsr(FALSE);
+ }
+ }
+
+ //
+ // Wait for transmit ready.
+ //
+
+ while (KdReadLsr(FALSE).TransmitHoldingEmpty == 0 );
+
+ //
+ // Wait for data set ready.
+ //
+
+// do {
+// LsrByte = (PSP_MODEM_STATUS) READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+// } while (((PSP_MODEM_STATUS)(&LsrByte))->DataSetReady == 0);
+
+ //
+ // Transmit data.
+ //
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer, Output);
+ return;
+}
+
+VOID
+KdPortRestore (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine restores the state of the serial port after the kernel
+ debugger has been active.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+DEBUG_PARAMETERS ComParams;
+
+ if (HalpSavedComPort != KdCurrentComPort ||
+ HalpSavedBaudRate != KdCurrentBaudRate) {
+ ComParams.CommunicationPort = HalpSavedComPort;
+ ComParams.BaudRate = HalpSavedBaudRate;
+ KdPortInitialize(&ComParams, NULL, TRUE);
+ }
+}
+
+VOID
+KdPortSave (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine saves the state of the serial port and initializes the port
+ for use by the kernel debugger.
+
+ N.B. This routine performs no function on the Jazz system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ HalpSavedBaudRate = KdCurrentBaudRate;
+ HalpSavedComPort = KdCurrentComPort;
+ return;
+}
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ )
+
+/*++
+
+Routine Description:
+
+ Returns current line status.
+
+ If status which is being waited for is ready, then the function
+ checks the current modem status and causes a possible display update
+ of the current statuses.
+
+Arguments:
+
+ WaitReason - Supplies a boolean value that determines whether the line
+ status is required for a receive or transmit.
+
+Return Value:
+
+ The current line status is returned as the function value.
+
+--*/
+
+{
+
+ static UCHAR RingFlag = 0;
+ UCHAR DataLsr, DataMsr;
+
+
+ //
+ // Get the line status for a recevie or a transmit.
+ //
+
+ DataLsr = READ_REGISTER_UCHAR(&SP_READ->LineStatus);
+ if (WaitReason) {
+
+ //
+ // Get line status for receive data.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->DataReady) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+
+ } else {
+
+ //
+ // Get line status for transmit empty.
+ //
+
+ if (((PSP_LINE_STATUS)&DataLsr)->TransmitEmpty) {
+ return *((PSP_LINE_STATUS)&DataLsr);
+ }
+ }
+
+ DataMsr = READ_REGISTER_UCHAR(&SP_READ->ModemStatus);
+ RingFlag |= ((PSP_MODEM_STATUS)&DataMsr)->RingIndicator ? 1 : 2;
+ if (RingFlag == 3) {
+
+ //
+ // The ring indicate line has toggled, use modem control from
+ // now on.
+ //
+
+ KdUseModemControl = TRUE;
+ }
+
+
+ return *((PSP_LINE_STATUS) &DataLsr);
+}
+
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ )
+
+/*++
+
+Routine Description:
+
+ This routine will determine a divisor based on an unvalidated
+ baud rate.
+
+Arguments:
+
+ ClockRate - The clock input to the controller.
+
+ DesiredBaud - The baud rate for whose divisor we seek.
+
+ AppropriateDivisor - Given that the DesiredBaud is valid, the
+ SHORT pointed to by this parameter will be set to the appropriate
+ value. If the requested baud rate is unsupportable on the machine
+ return a divisor appropriate for 19200.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+
+ SHORT calculatedDivisor;
+ ULONG denominator;
+ ULONG remainder;
+
+ //
+ // Allow up to a 1 percent error
+ //
+
+ ULONG maxRemain18 = 18432;
+ ULONG maxRemain30 = 30720;
+ ULONG maxRemain42 = 42336;
+ ULONG maxRemain80 = 80000;
+ ULONG maxRemain;
+
+ //
+ // Reject any non-positive bauds.
+ //
+
+ denominator = DesiredBaud*(ULONG)16;
+
+ if (DesiredBaud <= 0) {
+
+ *AppropriateDivisor = -1;
+
+ } else if ((LONG)denominator < DesiredBaud) {
+
+ //
+ // If the desired baud was so huge that it cause the denominator
+ // calculation to wrap, don't support it.
+ //
+
+ *AppropriateDivisor = -1;
+
+ } else {
+
+ if (ClockRate == 1843200) {
+ maxRemain = maxRemain18;
+ } else if (ClockRate == 3072000) {
+ maxRemain = maxRemain30;
+ } else if (ClockRate == 4233600) {
+ maxRemain = maxRemain42;
+ } else {
+ maxRemain = maxRemain80;
+ }
+
+ calculatedDivisor = (SHORT)(ClockRate / denominator);
+ remainder = ClockRate % denominator;
+
+ //
+ // Round up.
+ //
+
+ if (((remainder*2) > ClockRate) && (DesiredBaud != 110)) {
+
+ calculatedDivisor++;
+ }
+
+
+ //
+ // Only let the remainder calculations effect us if
+ // the baud rate is > 9600.
+ //
+
+ if (DesiredBaud >= 9600) {
+
+ //
+ // If the remainder is less than the maximum remainder (wrt
+ // the ClockRate) or the remainder + the maximum remainder is
+ // greater than or equal to the ClockRate then assume that the
+ // baud is ok.
+ //
+
+ if ((remainder >= maxRemain) && ((remainder+maxRemain) < ClockRate)) {
+ calculatedDivisor = -1;
+ }
+
+ }
+
+ //
+ // Don't support a baud that causes the denominator to
+ // be larger than the clock.
+ //
+
+ if (denominator > ClockRate) {
+
+ calculatedDivisor = -1;
+
+ }
+
+ //
+ // Ok, Now do some special casing so that things can actually continue
+ // working on all platforms.
+ //
+
+ if (ClockRate == 1843200) {
+
+ if (DesiredBaud == 56000) {
+ calculatedDivisor = 2;
+ }
+
+ } else if (ClockRate == 3072000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 13;
+ }
+
+ } else if (ClockRate == 4233600) {
+
+ if (DesiredBaud == 9600) {
+ calculatedDivisor = 28;
+ } else if (DesiredBaud == 14400) {
+ calculatedDivisor = 18;
+ } else if (DesiredBaud == 19200) {
+ calculatedDivisor = 14;
+ } else if (DesiredBaud == 38400) {
+ calculatedDivisor = 7;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 5;
+ }
+
+ } else if (ClockRate == 8000000) {
+
+ if (DesiredBaud == 14400) {
+ calculatedDivisor = 35;
+ } else if (DesiredBaud == 56000) {
+ calculatedDivisor = 9;
+ }
+
+ }
+
+ *AppropriateDivisor = calculatedDivisor;
+
+ }
+
+
+ if (*AppropriateDivisor == -1) {
+
+ HalpGetDivisorFromBaud(
+ ClockRate,
+ 19200,
+ AppropriateDivisor
+ );
+
+ }
+
+
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxpower.s b/private/ntos/nthals/halppc/ppc/pxpower.s
new file mode 100644
index 000000000..56047c6c3
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxpower.s
@@ -0,0 +1,123 @@
+//++
+//
+// Copyright (c) 1993 IBM Corporation
+//
+// Module Name:
+//
+// pxpower.s
+//
+// Abstract:
+//
+// This module implements the routines to set Doze mode and Dynamic Power management
+// mode on the PowerPC.
+//
+// Author:
+//
+// N. Yoshiyama ( nyoshiyama@vnet.ibm.com )
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "kxppc.h"
+
+
+ .set HID0, 1008 // SPR # for HID0
+
+
+//++
+//
+// VOID
+// HalpProcessorIdle (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sets CPU into Doze mode if it is PowerPC 603 and
+// enable External interrupts.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProcessorIdle)
+
+ mfmsr r.4 // Read MSR
+ ori r.4, r.4, 0x8000 // Enable External/Decrementer interrupts
+
+ mfpvr r.3 // Read PVR
+ rlwinm r.3, r.3, 16, 16, 31
+ cmpwi cr.0, r.3, 6 // Is it a 603e ?
+ cmpwi cr.1, r.3, 7 // Is it a 603ev ?
+ cmpwi cr.7, r.3, 3 // Is it a 603 ?
+ beq cr.0, SetDozeMode //
+ beq cr.1, SetDozeMode //
+ bne cr.7, EnableInterrupts // If not, just enable interrupts
+
+SetDozeMode:
+ mfspr r.3, HID0 // Set Doze mode in HID0 (bit 8)
+ oris r.3, r.3, 0x0080
+ mtspr HID0, r.3
+
+ oris r.4, r.4, 0x0004 // Set POW in MSR (bit 13)
+ sync
+
+EnableInterrupts:
+ mtmsr r.4
+ isync
+
+ LEAF_EXIT(HalpProcessorIdle)
+
+
+//++
+//
+// VOID
+// HalpSetDpm (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function enables Dynamic Power Management if the CPU is PowerPC 603.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSetDpm)
+
+ mfpvr r.3 // Read PVR
+ rlwinm r.3, r.3, 16, 16, 31
+ cmpwi cr.0, r.3, 6 // Is it a 603e ?
+ cmpwi cr.1, r.3, 7 // Is it a 603ev ?
+ cmpwi cr.7, r.3, 3 // Is it a 603 ?
+ beq cr.0, EnableDpm //
+ beq cr.1, EnableDpm // If so, enable DPM
+ beq cr.7, EnableDpm //
+ ALTERNATE_EXIT(HalpSetDpm) // If not, just return
+
+EnableDpm:
+ mfspr r.3, HID0 // Load r.3 from HID0
+ oris r3, r3, 0x0010 // Set DPM bit
+ mtspr HID0, r3 // Update HID0
+ sync
+
+ LEAF_EXIT(HalpSetDpm)
+
diff --git a/private/ntos/nthals/halppc/ppc/pxproc.c b/private/ntos/nthals/halppc/ppc/pxproc.c
new file mode 100644
index 000000000..5ec201f37
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxproc.c
@@ -0,0 +1,212 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxproc.c
+
+Abstract:
+
+ Stub functions for UP hals.
+
+Author:
+
+ Ken Reneris (kenr) 22-Jan-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+
+UCHAR HalName[] = "PowerPC HAL";
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+extern VOID HalpInitializePciBus (VOID);
+VOID HalpInitOtherBuses (VOID);
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitMP)
+#pragma alloc_text(INIT,HalStartNextProcessor)
+#pragma alloc_text(INIT,HalAllProcessorsStarted)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(INIT,HalpInitOtherBuses)
+#endif
+
+
+
+BOOLEAN
+HalpInitMP (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+ return FALSE;
+ // do nothing
+}
+
+
+VOID
+HalpResetAllProcessors (
+ VOID
+ )
+{
+}
+
+
+BOOLEAN
+HalStartNextProcessor (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN PKPROCESSOR_STATE ProcessorState
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to start the next processor.
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+ ProcessorState - Supplies a pointer to the processor state to be
+ used to start the processor.
+
+Return Value:
+
+ If a processor is successfully started, then a value of TRUE is
+ returned. Otherwise a value of FALSE is returned. If a value of
+ TRUE is returned, then the logical processor number is stored
+ in the processor control block specified by the loader block.
+
+--*/
+
+{
+
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG Number;
+ PKPRCB Prcb;
+
+ //
+ // If there is more than one restart block then this is a multi-
+ // processor system.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+ // Scan the restart parameter blocks for a processor that is ready,
+ // but not running. If a processor is found, then fill in the restart
+ // processor state, set the logical processor number, and set start
+ // in the boot status.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ Number = 0;
+ while (NextRestartBlock != NULL) {
+ if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) &&
+ (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) {
+ RtlZeroMemory(&NextRestartBlock->u.Ppc, sizeof(PPC_RESTART_STATE));
+
+ //
+ // Set processor start address.
+ //
+
+ NextRestartBlock->u.Ppc.Iar = ProcessorState->ContextFrame.Iar;
+
+ //
+ // PowerPC linkage conventions pass parameters in registers
+ // r.3 thru r.10. Set all of them to allow as much flexibility
+ // to the kernel as possible.
+ //
+
+ NextRestartBlock->u.Ppc.IntR3 = ProcessorState->ContextFrame.Gpr3;
+ NextRestartBlock->u.Ppc.IntR4 = ProcessorState->ContextFrame.Gpr4;
+ NextRestartBlock->u.Ppc.IntR5 = ProcessorState->ContextFrame.Gpr5;
+ NextRestartBlock->u.Ppc.IntR6 = ProcessorState->ContextFrame.Gpr6;
+ NextRestartBlock->u.Ppc.IntR7 = ProcessorState->ContextFrame.Gpr7;
+ NextRestartBlock->u.Ppc.IntR8 = ProcessorState->ContextFrame.Gpr8;
+ NextRestartBlock->u.Ppc.IntR9 = ProcessorState->ContextFrame.Gpr9;
+ NextRestartBlock->u.Ppc.IntR10 = ProcessorState->ContextFrame.Gpr10;
+
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ return TRUE;
+ }
+
+ Number++;
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ }
+
+ return FALSE;
+}
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+{
+ return TRUE;
+}
+
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ INTERFACE_TYPE interfacetype;
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+ interfacetype = Internal;
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ interfacetype = Isa;
+
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ interfacetype // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+
+#ifdef POWER_MANAGEMENT
+ HalInitSystemPhase2();
+#endif
+}
+
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxprof.c b/private/ntos/nthals/halppc/ppc/pxprof.c
new file mode 100644
index 000000000..692cc302a
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxprof.c
@@ -0,0 +1,268 @@
+
+/*****************************************************************************
+
+Copyright (c) 1993 Motorola Inc.
+ Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+ contains copyrighted material. Use of this file is restricted
+ by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ PXPROF.C
+
+Abstract:
+
+ This implements the HAL profile functions:
+
+ HalSetProfileInterval
+ HalStartProfileInterrupt
+ HalStopProfileInterrupt
+ HalCalibratePerformanceCounter
+ HalpProfileInterrupt
+
+
+Author:
+
+ Steve Johns 11-Feb-1994
+
+Revision History:
+ Changed from using the DECREMENTER to 8254 Timer 1 10-Feb-94
+
+******************************************************************************/
+
+#include "halp.h"
+#include "eisa.h"
+#include "pxsiosup.h"
+
+#define TIMER ((PEISA_CONTROL)HalpIoControlBase)
+#define TIMER0_COMMAND (COMMAND_8254_COUNTER0 + COMMAND_8254_RW_16BIT + COMMAND_8254_MODE2)
+
+ULONG HalpMaxProfileInterval = 540000; // 54 ms maximum
+ULONG HalpMinProfileInterval = 10000; // 1 ms minimum
+ULONG HalpProfileCount;
+BOOLEAN HalpProfilingActive = FALSE;
+ULONG HalpProfileInts = 0;
+
+
+VOID HalStartProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine unmasks IRQ0 at the master interrupt controller,
+ enabling the profile interrupt.
+
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding
+ the profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ if (ProfileSource == ProfileTime) {
+ HalpProfilingActive = TRUE;
+ //
+ // Unmasks IRQ 0 (Timer 1)
+ //
+ HalEnableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL, Latched);
+ }
+
+}
+
+
+
+
+
+
+ULONG HalSetProfileInterval (
+ IN ULONG Interval
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the profile interrupt interval.
+
+Arguments:
+
+ Interval - Supplies the desired profile interval in 100ns units.
+
+Return Value:
+
+ The actual profile interval, rounded to the nearest 100ns units.
+
+--*/
+
+{
+ ULONG ActualInterval;
+ LARGE_INTEGER BigNumber;
+
+ //
+ // Clamp the requested profile interval between the minimum and
+ // maximum supported values.
+ //
+ if (Interval < HalpMinProfileInterval)
+ Interval = HalpMinProfileInterval;
+ else
+ if (Interval > HalpMaxProfileInterval)
+ Interval = HalpMaxProfileInterval;
+ //
+ // Compute Timer 1 counts for requested interval.
+ //
+ BigNumber.QuadPart = Int32x32To64(Interval, TIMER_CLOCK_IN);
+
+ BigNumber = RtlExtendedLargeIntegerDivide(BigNumber, 10000000, NULL);
+ HalpProfileCount = BigNumber.LowPart;
+
+ //
+ // Program Timer 1 to Mode 2 & program the timer count register.
+ //
+ WRITE_REGISTER_UCHAR (&(TIMER->CommandMode1), TIMER0_COMMAND);
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount & 0xff));
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount >> 8));
+ //
+ // Compute actual interval.
+ //
+ BigNumber.QuadPart = Int32x32To64(HalpProfileCount, 10000000);
+ BigNumber = RtlExtendedLargeIntegerDivide(BigNumber,TIMER_CLOCK_IN, NULL);
+ ActualInterval = BigNumber.LowPart;
+
+ return (ActualInterval);
+}
+
+
+
+
+BOOLEAN HalpHandleProfileInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+{
+
+ if (HalpProfilingActive)
+ KeProfileInterrupt(TrapFrame);
+
+ return (TRUE);
+}
+
+
+
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE ProfileSource
+ )
+
+/*++
+
+Routine Description:
+
+ This routine masks IRQ 0 (Timer 1) at the interrupt controller, thereby
+ stopping profile interrupts.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ if (ProfileSource == ProfileTime) {
+ HalpProfilingActive = FALSE;
+
+ //
+ // Program Timer 1 to Mode 2 & program the LSB of the timer.
+ // That should keep it from interrupting in case IRQ0 accidently
+ // gets enabled.
+ //
+ WRITE_REGISTER_UCHAR (&(TIMER->CommandMode1), TIMER0_COMMAND);
+ WRITE_REGISTER_UCHAR (&(TIMER->Timer1), (UCHAR)(HalpProfileCount & 0xff));
+
+
+ //
+ // Mask IRQ 0 (Timer 1)
+ //
+ HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
+ }
+
+}
+
+
+
+
+
+
+VOID
+HalCalibratePerformanceCounter (
+ IN volatile PLONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine resets the performance counter value for the current
+ processor to zero. The reset is done such that the resulting value
+ is closely synchronized with other processors in the configuration.
+
+Arguments:
+
+ Number - Supplies a pointer to count of the number of processors in
+ the configuration.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KSPIN_LOCK Lock;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and
+ // wait until the number is zero.
+ //
+ KeInitializeSpinLock(&Lock);
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (ExInterlockedDecrementLong(Number, &Lock) != RESULT_ZERO) {
+ do {
+ } while (*Number !=0);
+ }
+
+ //
+ // Zero the Time Base registers
+ //
+
+ HalpZeroPerformanceCounter();
+
+ //
+ // Restore IRQL to its previous value and return.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxreset.s b/private/ntos/nthals/halppc/ppc/pxreset.s
new file mode 100644
index 000000000..4c9f1259d
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxreset.s
@@ -0,0 +1,455 @@
+//++
+//
+// Copyright (c) 1993, 94, 95, 96 IBM Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxreset.s
+//
+// Abstract:
+//
+// This module implements the routine HalpPowerPcReset, which can be
+// used to return the PowerPC to Big Endian with cache flushed and
+// branches to the rom based machine reset handler.
+//
+// Author:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) September 1993
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// plj Feb 1995 Zap TLB before resetting, add 603+
+// and 604+ support.
+//
+// jlw Added eagle memory controller support
+//
+//
+//--
+
+#include "kxppc.h"
+
+ .set C_LINE_SZ, 64
+ .set C_LINE_CNT, 64
+ .set C_SETS, 8
+
+ .set C_SIZE, C_LINE_SZ * C_LINE_CNT * C_SETS
+
+ .set HID0, 1008
+ .set DISABLES, MASK_SPR(MSR_DR,1) | MASK_SPR(MSR_IR,1)
+
+
+ .set H0_603_DCE, 0x4000 // 603 Data Cache Enable
+ .set H0_603_ICE, 0x8000 // 603 Instruction Cache Enable
+ .set H0_603_ICFI, 0x0800 // 603 I-Cache Flash Invalidate
+
+ .set H0_604_DCE, 0x4000 // 604 Data Cache Enable
+ .set H0_604_ICE, 0x8000 // 604 Instruction Cache Enable
+ .set H0_604_DCIA, 0x0400 // 604 I-Cache Invalidate All
+ .set H0_604_ICIA, 0x0800 // 604 I-Cache Invalidate All
+
+ .set TLB_CLASSES_601, 128 // 601 tlb has 128 congruence classes
+ .set TLB_CLASSES_603, 32 // 603 tlb has 32 congruence classes
+ .set TLB_CLASSES_604, 64 // 604 tlb has 64 congruence classes
+
+ LEAF_ENTRY(HalpPowerPcReset)
+ LWI(r.4, 0xfff00100) // address of rom reset handler
+ mfspr r.5, HID0
+ mfpvr r.31 // determine processor type
+ li r.6, -1
+ mtdec r.6
+ isync
+ li r.6, 0
+ li r.7, 0x92
+ oris r.7, r.7, 0x8000
+ mfmsr r.8
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_EE,1) // disable interrupts
+ mtmsr r.8
+
+ //
+ // invalidate all tlb entries
+ //
+
+ li r.3, TLB_CLASSES_601 // use largest known number of
+ // congruence classes
+ mtctr r.3 // number of classes = iteration count
+zaptlb: tlbie r.3 // invalidate tlb congruence class
+ addi r.3, r.3, 4096 // increment to next class address
+ bdnz zaptlb // loop through all classes
+
+ srwi r.31, r.31, 16 // isolate processor type
+ cmpwi r.31, 1 // is 601?
+
+ bl here // get current address
+here:
+ mflr r.9 // (r.9) = &here
+ rlwinm r.9, r.9, 0, 0x7fffffff // convert address to physical
+
+ bne not_601
+
+ //
+ // processor is a 601
+ //
+
+ rlwinm r.5, r.5, 0, ~(0x0008) // turn off little endian
+
+ //
+ // disable instruction and data relocation and switch
+ // interrupt prefix to fetch from ROM
+ //
+
+ andi. r.8, r.8, ~DISABLES & 0xffff
+ ori r.8, r.8, MASK_SPR(MSR_IP,1)
+ mtsrr1 r.8 // this will also be target state
+ nop // for rfi
+
+//
+// Ensure all code from 'cachem' to 'end_little' is in cache by loading a
+// byte in each address line in that range.
+
+ addi r.9, r.9, cachem-here // (r.9) = physical &cachem
+
+ // r.9 now contains the physical address of cachem. (assuming
+ // this code was loaded as part of kernel which is loaded at
+ // physical 0 = virtual 0x80000000). We effect the switch to
+ // physical addressing thru an rfi with the target state set
+ // to resume at cachem with relocation and interrupts disabled.
+
+ mtsrr0 r.9 // address of cachem for rfi
+ addi r.10, r.9, end_little-cachem // (r.10) = &end_little
+ addi r.11, r.9, HalpPowerPcReset.end-cachem // (r.11) = &reset_end
+
+ addi r.12, r.9, -C_LINE_SZ // bias addr for 1st iteration by
+ // amount added by lbzu prior to load
+
+ rfi // switch
+cachem:
+ lbzu r.13, C_LINE_SZ(r.12) // get byte at (r.13)+C_LINE_SZ
+ cmplw r.12, r.10 // bumping r.12 by C_LINE_SZ
+ addi r.13, r.13, 1 // ensure load completed.
+ blt cachem // get all in range here-end_little.
+
+ isync
+ mtsrr0 r.4 // set rom reset target for next rfi
+ lis r.9, 0x87f0 // Segment register base 0x87f00000
+ li r.10, 0xf // Set all 16 segment registers
+
+ li r.11, 0
+ mtibatl 0, r.6 // zero bat 0-3 upper and lower
+ mtibatu 0, r.6
+ mtibatl 1, r.6
+
+ mtibatu 1, r.6
+ mtibatl 2, r.6
+ mtibatu 2, r.6
+ mtibatl 3, r.6
+
+ mtibatu 3, r.6
+setsr: rlwimi r.11, r.10, 28, 0, 3 // Shift segment reg. # to bits 0-3
+ or r.12, r.9, r.10 // Segment register value 0x87f000sr
+ mtsrin r.12, r.11
+
+ addic. r.10, r.10, -1 // Next segment register
+ bne setsr
+ nop
+ nop
+
+ nop
+ nop
+ nop
+ nop
+
+ nop
+ sync // quiet the machine down
+ sync
+ sync
+
+ sync
+ stb r.6, 0(r.7) // switch memory
+ eieio // flush io
+ sync
+
+ sync
+ sync
+ sync
+ mtspr HID0, r.5 // switch ends on the cpu
+
+ sync
+ sync
+ sync
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ mtsr 0, r.9 // Set the last segment register
+
+ rfi // head off into the reset handler
+ rfi
+ addi r.0, r.1, 0x138 // we never get here
+ oris r.0, r.0, 0x4c // rfi (big-endian)
+end_little:
+
+ b $
+
+//
+// For the 603 (and hopefully other) processor(s) things are a little
+// easier because little-endianness is controlled by the MSR. We still
+// have to change memory seperately so we still want code from the memory
+// switch thru the cpu switch in cache.
+//
+// When we get here
+// r.4 contains the address of the ROM resident Machine Reset
+// handler.
+// r.5 contains HID0 present value.
+// r.6 contains 0.
+// r.7 contains the port address (real) used to switch memory
+// endianness.
+// r.8 contains MSR present value.
+// r.9 contains the physical address of "here"
+// r.31 contains the processor type
+
+
+not_601:
+ cmpwi cr.0, r.31, 3 // is 603?
+ cmpwi cr.4, r.31, 7 // is 603ev?
+ cmpwi cr.1, r.31, 6 // is 603e?
+ cmpwi cr.2, r.31, 4 // is 604?
+ cmpwi cr.3, r.31, 9 // is 604e?
+ beq cr.0, is_603
+ beq cr.4, is_603
+ bne cr.1, not_603
+
+//
+// 603 I-Cache is invalidated by setting ICFI in HID0. Unlike
+// the 604, this bit is not self clearing.
+//
+
+is_603: rlwinm r.5, r.5, 0, ~H0_603_DCE// turn off D-cache
+ rlwinm r.10, r.5, 0, ~H0_603_ICE// turn off I-cache
+ ori r.10, r.10, H0_603_ICFI // I-Cache Flash Invalidate
+ ori r.5, r.5, H0_603_ICE // I-cache enable
+ isync
+ mtspr HID0, r.10 // invalidate/disable
+ mtspr HID0, r.5 // enable
+ b common_6034
+
+not_603:
+ beq cr.2, is_604
+// bne not_604
+
+// Note: the above branch is commented out because we don't
+// currently have any other options,... 620 will probably
+// be different.
+
+
+is_604: tlbsync // wait all processor tlb invalidate
+
+//
+// 604 caches must be enabled in order to be invalidated. It
+// is acceptable to enable and invalidate with the same move
+// to hid0. The data cache will be left disabled, the instruction
+// cache enabled.
+//
+
+ ori r.5, r.5, H0_604_DCE | H0_604_ICE
+ ori r.10, r.5, H0_604_DCIA | H0_604_ICIA
+
+ rlwinm r.5, r.5, 0, ~H0_604_DCE
+ rlwinm r.5, r.5, 0, ~H0_604_DCIA
+ rlwinm r.5, r.5, 0, ~H0_604_ICIA
+
+ mtspr HID0, r.10 // enable + invalidate
+ mtspr HID0, r.5 // disable data cache
+
+ rlwinm r.10, r.5, 0, ~H0_604_ICE // disable i-cache later
+
+// b common_6034 // join common code
+
+
+//
+// The following is common to both 603 and 604
+//
+
+common_6034:
+
+//
+// MSR bits ILE and POW must be disabled via mtmsr as rfi only moves
+// the least significant 16 bits into the MSR.
+//
+
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_DR,1) // -= Data Relocation
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_POW,1) // -= Power Management
+ rlwinm r.8, r.8, 0, ~MASK_SPR(MSR_ILE,1) // -= Interrupt Little Endian
+ sync
+ mtmsr r.8
+ isync
+
+
+//
+// Use an rfi to switch to big-endian, untranslated, interrupt prefix on
+// with a target address in the nice harmless pallindromic code below.
+// use another rfi to branch to the rom resident reset handler.
+//
+
+ li r.8, MASK_SPR(MSR_ME,1) | MASK_SPR(MSR_IP,1)
+ addi r.9, r.9, uncached_6034-here
+ mtsrr1 r.8 // state = Machine Check Enabled
+ bl here2
+here2: mflr r.28
+ rlwinm r.28, r.28, 0, 0x7fffffff // convert address to physical
+ lwz r.29, endofroutine - here2(r.28)
+ mtsrr0 r.9 // rfi to uncached_6034
+ b jumpswap
+
+memoryswap:
+ ori r.8, r.28, 0
+ addi r.8, r.8, uncached_6034-here2
+ addi r.9, 0, 0
+ li r.15, swapend - uncached_6034
+ addis r.14, 0, 0
+ addi r.14, 0, 4
+swaploop:
+ lwz r.11, 0(r.8)
+ lwz r.12, 4(r.8)
+ stwbrx r.11, r.14, r.8
+ stwbrx r.12, 0, r.8
+ addi r.8, r.8, 8
+ subi r.15, r.15, 8
+ cmpi 0, 0, r.15, 0
+ bgt swaploop
+
+jumpswap:
+
+//
+// The following bizzareness is to ensure that the memory switch thru
+// the disabling of cache is in cache. There is less than 32 bytes so
+// they must be part of either the cache line we are currently in, or
+// the one at the target of the branch. Therefore, branching over them,
+// doing a little and branching back to them should be enough to enure
+// they're cache resident.
+//
+
+ b fill_icache
+goto_bigendian:
+ sync
+ stb r.6, 0(r.7) // switch memory
+ sync
+ lwz r.30, endofroutine - here2(r.28)
+ cmp 0, 0, r.29, r.30
+ beq memoryswap
+ rfi
+fill_icache:
+ isync
+ sync // complete everything!
+ b goto_bigendian
+
+ .align 5
+
+uncached_6034:
+ .big_endian // out of cache fetches must be
+ // assembled in same mode as processor
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+
+ addi r.0, r.1, 0x138 // same both ways
+ addi r.0, r.1, 0x138 // same both ways
+ mtsrr0 r.4 // rfi target = 0xfff00100
+ mtspr HID0, r.10 // DISABLE CACHING
+
+ mtibatl 0, r.6 // invalidate/clear all bats
+ mtibatu 0, r.6
+ mtibatl 1, r.6
+ mtibatu 1, r.6
+
+ mtibatl 2, r.6
+ mtibatu 2, r.6
+ mtibatl 3, r.6
+ mtibatu 3, r.6
+
+ mtdbatl 0, r.6
+ mtdbatu 0, r.6
+ mtdbatl 1, r.6
+ mtdbatu 1, r.6
+
+ mtdbatl 2, r.6
+ mtdbatu 2, r.6
+ mtdbatl 3, r.6
+ mtdbatu 3, r.6
+
+ mtsr 0, r.6
+ mtsr 1, r.6
+ mtsr 2, r.6
+ mtsr 3, r.6
+
+ mtsr 4, r.6
+ mtsr 5, r.6
+ mtsr 6, r.6
+ mtsr 7, r.6
+
+ mtsr 8, r.6
+ mtsr 9, r.6
+ mtsr 10, r.6
+ mtsr 11, r.6
+
+ mtsr 12, r.6
+ mtsr 13, r.6
+ mtsr 14, r.6
+ mtsr 15, r.6
+
+ rfi // go to machine reset handler
+ // never get here
+ rfi // previous rfi on a dword boundary
+ // allow for word swap
+ .little_endian
+endofroutine:
+ sync
+ .globl swapend
+ .long swapend
+swapend:
+
+ LEAF_EXIT(HalpPowerPcReset)
diff --git a/private/ntos/nthals/halppc/ppc/pxreturn.c b/private/ntos/nthals/halppc/ppc/pxreturn.c
new file mode 100644
index 000000000..a59dd8087
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxreturn.c
@@ -0,0 +1,187 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1996 International Business Machines Corporation
+
+
+Module Name:
+
+ pxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+
+Author:
+
+ David N. Cutler (davec) 21-Aug-1991
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial Power PC port
+
+ Keyboard mapping code was ported to PPC.
+ This function is currently a stub since our firmware is big endian
+
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+#include "eisa.h"
+
+#if defined(VICTORY)
+
+#include "ibmppc.h"
+
+#endif
+
+//
+// Define keyboard registers structure.
+//
+
+typedef struct _KBD_REGISTERS {
+ union {
+ UCHAR Output;
+ UCHAR Input;
+ } Data;
+
+ union {
+ UCHAR Status;
+ UCHAR Command;
+ } Control;
+} KBD_REGISTERS;
+
+#define KBD_IBF_MASK 2 // input buffer full mask
+
+#define KBD_DATA_PORT 0x60
+#define KBD_COMMAND_PORT 0x64
+#define KbdGetStatus() (READ_REGISTER_UCHAR(&HalpIoControlBase + KBD_COMMAND_PORT))
+#define KbdStoreCommand(Byte) WRITE_REGISTER_UCHAR(&HalpIoControlBase + KBD_COMMAND_PORT, Byte)
+#define KbdStoreData(Byte) WRITE_REGISTER_UCHAR(&HalpIoControlBase + KBD_DATA_PORT, Byte)
+#define KbdGetData() (READ_REGISTER_UCHAR(&HalpIoControlBase + KBD_DATA_PORT))
+
+VOID
+HalpPowerPcReset(
+ VOID
+ );
+
+#if defined(VICTORY)
+
+VOID
+HalpResetUnion(
+ VOID
+ );
+
+#endif
+
+VOID
+HalReturnToFirmware(
+ IN FIRMWARE_REENTRY Routine
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the specified firmware routine.
+ In most cases it generates a soft reset by asserting the reset line
+ trough the keyboard controller.
+ The Keyboard controller is mapped using the same virtual address
+ and the same fixed entry as the DMA.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ ULONG i;
+ PCI_COMMON_CONFIG PciData;
+ PUCHAR PIC_Address;
+ UCHAR PIC_Mask=0xFF;
+
+#define ISA_CONTROL ((PEISA_CONTROL) HalpIoControlBase)
+
+ HalpUpdateDecrementer(0x7FFFFFFF);
+
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Disable interrupt controller:
+ //
+
+ PIC_Address = &(ISA_CONTROL->Interrupt1ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+ PIC_Address = &(ISA_CONTROL->Interrupt2ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+
+#if defined(SOFT_HDD_LAMP)
+ //
+ // Turn off the HDD lamp.
+ //
+
+ *((PUCHAR)HalpIoControlBase + HDD_LAMP_PORT) = 0;
+
+#endif
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+#if defined(VICTORY)
+
+ if ( HalpSystemType == IBM_DORAL ) {
+ //
+ // Poke the Union "Power On Reset" register.
+ // (This should never return).
+ //
+ HalpResetUnion();
+ }
+
+#endif
+
+ HalpPowerPcReset();
+
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxrtcsup.h b/private/ntos/nthals/halppc/ppc/pxrtcsup.h
new file mode 100644
index 000000000..c472fad77
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxrtcsup.h
@@ -0,0 +1,28 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxrtcsup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the DALLAS rtc chip.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+//
+// SandalFoot uses the Dallas 1585s RTC chip
+//
+
+#include "pxds1585.h"
+
diff --git a/private/ntos/nthals/halppc/ppc/pxs3.c b/private/ntos/nthals/halppc/ppc/pxs3.c
new file mode 100644
index 000000000..78b31675a
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxs3.c
@@ -0,0 +1,677 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+
+Module Name:
+
+pxs3.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a PowerPC system using an S3 video adapter.
+
+Author:
+
+ Jess Botts
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pxs3.h"
+#include "string.h"
+#include "pxvgaequ.h"
+
+//PHYSICAL ADDRESS of S3 video ram
+#define S3_VIDEO_MEMORY_BASE 0xC0000000
+
+
+VOID
+HalpDisplayCharacterS3 (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacterS3 (
+ IN UCHAR AsciiChar
+ );
+
+VOID
+HalpDisplayPpcS3Setup (
+ VOID
+ );
+
+// in pxdisp.c
+VOID
+WaitForVSync (
+ VOID
+ );
+
+VOID
+Scroll_Screen (
+ IN UCHAR line
+ );
+
+
+extern ULONG HalpInitPhase;
+extern PUCHAR HalpVideoMemoryBase;
+extern PUCHAR HalpVideoCoprocBase;
+
+extern ULONG HalpColumn;
+extern ULONG HalpRow;
+extern ULONG HalpHorizontalResolution;
+extern ULONG HalpVerticalResolution;
+
+
+extern USHORT HalpBytesPerRow;
+extern USHORT HalpCharacterHeight;
+extern USHORT HalpCharacterWidth;
+extern ULONG HalpDisplayText;
+extern ULONG HalpDisplayWidth;
+extern ULONG HalpScrollLength;
+extern ULONG HalpScrollLine;
+
+extern BOOLEAN HalpDisplayOwnedByHal;
+
+
+VOID
+HalpDisplayPpcS3Setup (
+ VOID
+ )
+/*++
+
+Routine Description:
+ This routine initializes the S3 display controller chip.
+Arguments:
+ None.
+Return Value:
+ None.
+
+--*/
+{
+//
+// Routine Description:
+//
+// This is the initialization routine for S3 86C911. This routine initializes
+// the S3 86C911 chip in the sequence of VGA BIOS for AT.
+//
+ ULONG DataLong;
+ USHORT i,j;
+ UCHAR DataByte;
+ UCHAR Index;
+// PVOID Index_3x4, Data_3x5;
+ ULONG MemBase;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ if (HalpInitPhase == 0) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(S3_VIDEO_MEMORY_BASE,
+ 0x400000); // 4 MB
+
+ //
+ // IO control space has already been mapped in phase 1 via halpmapiospace
+ //
+
+ }
+
+
+
+ // Enable Video Subsystem
+ // Accordint to chapter 5.4.2 regular VGA setup sequence
+ // HalDisplayString(" Enable Video Subsystem...\n");
+
+ WRITE_S3_UCHAR(SUBSYS_ENB, 0x10);
+
+ // HalDisplayString(" Subsystem Enable = 0x10...\n");
+ WRITE_S3_UCHAR(Setup_OP, 0x01);
+ WRITE_S3_UCHAR(SUBSYS_ENB, 0x08);
+
+ WRITE_S3_UCHAR(DAC_Mask, 0x0); // Set screen into blank
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ WRITE_S3_UCHAR(Seq_Data, 0x21);
+
+ //=========================================================================
+ //
+ // IBMBJB removed this section because it is not currently used, this
+ // was left commented out instead of deleting it in case we use
+ // a monochrome monitor in the future
+ //
+ // // Check monitor type to decide index address (currently not use)
+ // DataByte = READ_S3_UCHAR(MiscOutR);
+ // ColorMonitor = DataByte & 0x01 ? TRUE : FALSE;
+ //
+ // if (ColorMonitor) {
+ // Index_3x4 = (PVOID)S3_3D4_Index;
+ // Data_3x5 = (PVOID)S3_3D5_Data;
+ // } else {
+ // Index_3x4 = (PVOID)Mono_3B4;
+ // Data_3x5 = (PVOID)Mono_3B5;
+ // }
+ //
+ //=========================================================================
+
+ //
+ // -- Initialization Process Begin --
+ // According to appendix B-4 "ADVANCED PROGRAMMER'S GUIDE TO THE EGA/VGA"
+ // to set the default values to VGA +3 mode.
+ //
+ WRITE_S3_UCHAR(VSub_EnB,VideoParam[0]);
+ // Note: Synchronous reset must be done before MISC_OUT write operation
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ // For ATI card(0x63) we may want to change the frequence
+ WRITE_S3_UCHAR(MiscOutW,VideoParam[1]);
+
+ // Note: Synchronous reset must be done before CLOCKING MODE register is
+ // modified
+ WRITE_S3_UCHAR(Seq_Index, RESET); // Synchronous Reset !
+ WRITE_S3_UCHAR(Seq_Data, 0x01);
+
+ // Sequencer Register
+ for (Index = 1; Index < 5; Index++) {
+ WRITE_S3_UCHAR(Seq_Index, Index);
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+Index]);
+ }
+
+#ifdef POLO // if compiling for a Polo
+
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R0);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+
+ if((DataByte & 0xf0) == 0xc0) { // if display adaptor is an S3 864
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte |= 0x01; // use an 8 dot character clock
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+ }
+
+#endif
+
+ // Set CRT Controller
+ // out 3D4, 0x11, 00 (bit 7 must be 0 to unprotect CRT R0-R7)
+ // UnLockCR0_7();
+ WRITE_S3_UCHAR(S3_3D4_Index, VERTICAL_RETRACE_END);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte = DataByte & 0x7f;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // CRTC controller CR0 - CR18
+ for (Index = 0; Index < 25; Index++) {
+ WRITE_S3_UCHAR(S3_3D4_Index, Index);
+ WRITE_S3_UCHAR(S3_3D5_Data, VideoParam[CRT_OFFSET+Index]);
+ }
+
+ // attribute write
+ // program palettes and mode register
+ // HalDisplayString(" Program palettes ...\n");
+ for (Index = 0; Index < 21; Index++) {
+ WaitForVSync();
+
+ DataByte = READ_S3_UCHAR(Stat1_In); // Initialize Attr. F/F
+ WRITE_S3_UCHAR(Attr_Index,Index);
+ KeStallExecutionProcessor(5);
+
+ WRITE_S3_UCHAR(Attr_Data,VideoParam[ATTR_OFFSET+Index]);
+ KeStallExecutionProcessor(5);
+
+ WRITE_S3_UCHAR(Attr_Index,0x20); // Set into normal operation
+ }
+
+ WRITE_S3_UCHAR(Seq_Index, RESET); // reset to normal operation !
+ WRITE_S3_UCHAR(Seq_Data, 0x03);
+
+ // graphics controller
+ // HalDisplayString(" Graphics controller...\n");
+ for (Index = 0; Index < 9; Index++) {
+ WRITE_S3_UCHAR(GC_Index, Index);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+Index]);
+ }
+
+ // turn off the text mode cursor
+ WRITE_S3_UCHAR(S3_3D4_Index, CURSOR_START);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x2D);
+
+ // Unlock S3 specific registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x48);
+
+ // Unlock S3 SC registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0xa0);
+
+ // Disable enhanced mode
+ WRITE_S3_UCHAR(ADVFUNC_CNTL, 0x02);
+
+ // Turn off H/W Graphic Cursor
+ WRITE_S3_UCHAR(S3_3D4_Index, SC5);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ //=========================================================================
+ //
+ // IBMBJB S3 errata sheet says that CR40 can not be read correctly after
+ // power up until it has been written to, suggested workaround is
+ // to use the power on default (0xA4) Since the intent of the
+ // existing code was to reset bit 0, 0xA4 will be used to reset
+ // the bit. The other bits that are reset select the desired
+ // default configuration.
+ //
+ // If this register is written by the firmware then this fix is
+ // unneccessary. If future modifications of the firmware were to
+ // remove all writes to this register then this fix would have to
+ // be added here. This is being added now to protect this code
+ // from possible firmware changes.
+ //
+ // // Disable enhanced mode registers access
+ // WRITE_S3_UCHAR(S3_3D4_Index, SC0);
+ // DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ // DataByte &= 0xfe;
+ // DataByte ^= 0x0;
+ //
+ // WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+ //
+
+ WRITE_S3_UCHAR( S3_3D4_Index, SC0 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0xA4 );
+
+ //=========================================================================
+
+ // Set Misc 1 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R0A);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0xc7;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Set S3R1 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R1);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0x80;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Set S3R2 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R2);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Set S3R4 register
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R4);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte &= 0xec;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ //=========================================================================
+ //
+ // IBMBJB added this section to eliminate the DAC hardware cursor, this
+ // is done before setting registers 0x50 - 0x62 to default states
+ // so that R55's default state will not be undone.
+ //
+ // this sequence zeros the 2 least signifigant bits in command
+ // register 2 on the DAC
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // set RS[3:2] to 10
+ DataByte = READ_S3_UCHAR( S3_3D5_Data );
+ DataByte &= 0xfc;
+ DataByte |= 0x02;
+ WRITE_S3_UCHAR( S3_3D5_Data, DataByte );
+
+ DataByte = READ_S3_UCHAR( DAC_Data );
+ DataByte &= 0xfc; // zero CR21,20 in DAC command
+ WRITE_S3_UCHAR( DAC_Data, DataByte ); // register 2
+
+ //=========================================================================
+ //
+ // IBMBJB Added code to configure for 18 bit color mode and reload the
+ // palette registers because the firmware configures for 24 bit
+ // color. If this is done when the system driver initializes for
+ // graphics mode then the text mode colors can not be changed
+ // properly.
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // RS[3:2] = 01B to address
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x01 ); // DAC command register 0
+
+ DataByte = READ_S3_UCHAR( DAC_Mask ); // reset bit 1 in DAC command
+ DataByte &= 0xfd; // register 0 to select 6 bit
+ WRITE_S3_UCHAR( DAC_Mask, DataByte ); // operation (18 bit color)
+
+ // IBMBJB added write to SDAC PLL control register to make sure CLK0
+ // is correct if we have to reinitialize after graphics mode
+ // initialization, this does not bother the 928/Bt485 card
+ // because the Bt485 DAC looks very much like the SDAC
+
+ WRITE_S3_UCHAR( DAC_WIndex, 0x0e ); // select SDAC PLL control reg
+ WRITE_S3_UCHAR( DAC_Data, 0x00 ); // select SDAC CLK0
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 ); // select DAC color palette
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 ); // registers
+
+ WRITE_S3_UCHAR( DAC_WIndex, 0 ); // start load in register 0
+
+ for( i = 0, j = 0; i < 256; ++i ) // load all color registers
+ {
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // red intensity
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // green intensity
+ WRITE_S3_UCHAR( DAC_Data, TextPalette[j++] ); // blue intensity
+ }
+
+ //=========================================================================
+ //
+ // IBMBJB added writes to registers 0x50 - 0x62 to set them to a known
+ // state because some of them are set by the firmware and are
+ // not correct for our use
+ //
+ // NOTE: there are some writes to the DAC registers in code that
+ // executes later that depend on R55[1:0] being 00B, if the
+ // default state of R55 is changed make sure that these bits
+ // are not changed
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x50 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x51 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x52 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x53 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x54 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x55 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x56 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x57 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x58 );
+#ifdef SAM_256
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x40 );
+#else
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+#endif
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x59 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5a );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x0a );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5B );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5C );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5D );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5E );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x5F );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ // IBMBJB changed value written from 0 to 1 for an S3 864 based card to
+ // clear up bad display caused by 864->SDAC FIFO underrun
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x60 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x01 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x61 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ WRITE_S3_UCHAR( S3_3D4_Index, 0x62 );
+ WRITE_S3_UCHAR( S3_3D5_Data, 0x00 );
+
+ //=========================================================================
+ //
+ // IBMBJB added setting bits 7 and 6 of CR65, errata sheet fix for split
+ // transfer problem in parallel and continuous addressing modes
+ // Note: side effect of setting bit 7 was a garbled firmware screen after
+ // shutdown.
+
+ // Set SR65 bits 7 and 6
+ WRITE_S3_UCHAR(S3_3D4_Index, 0x65);
+ DataByte = READ_S3_UCHAR(S3_3D5_Data);
+ DataByte |= 0x40;
+// DataByte |= 0xc0;
+ WRITE_S3_UCHAR(S3_3D5_Data, DataByte);
+
+ // Lock S3 SC registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R9);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Lock S3 specific registers
+ WRITE_S3_UCHAR(S3_3D4_Index, S3R8);
+ WRITE_S3_UCHAR(S3_3D5_Data, 0x0);
+
+ // Load character fonts into plane 2 (A0000-AFFFF)
+ // HalDisplayString(" Load Fonts into Plane2 ...\n");
+ WRITE_S3_UCHAR(Seq_Index,0x02); // Enable Write Plane reg
+ WRITE_S3_UCHAR(Seq_Data,0x04); // select plane 2
+
+ WRITE_S3_UCHAR(Seq_Index,0x04); // Memory Mode Control reg
+ WRITE_S3_UCHAR(Seq_Data,0x06); // access to all planes,
+
+ WRITE_S3_UCHAR(GC_Index,0x05); // Graphic, Control Mode reg
+ WRITE_S3_UCHAR(GC_Data,0x00);
+
+ WRITE_S3_UCHAR(GC_Index,0x06);
+ WRITE_S3_UCHAR(GC_Data,0x04);
+
+ WRITE_S3_UCHAR(GC_Index,0x04);
+ WRITE_S3_UCHAR(GC_Data,0x02);
+
+
+ MemBase = 0xA0000;
+ for (i = 0; i < 256; i++) {
+ for (j = 0; j < 16; j++) {
+ WRITE_S3_VRAM(MemBase, VGAFont8x16[i*16+j]);
+ MemBase++;
+ }
+ // 32 bytes each character font
+ for (j = 16; j < 32; j++) {
+ WRITE_S3_VRAM(MemBase, 0 );
+ MemBase++;
+ }
+ }
+
+ // turn on screen
+ WRITE_S3_UCHAR(Seq_Index, 0x01);
+ DataByte = READ_S3_UCHAR(Seq_Data);
+ DataByte &= 0xdf;
+ DataByte ^= 0x0;
+ WRITE_S3_UCHAR(Seq_Data, DataByte);
+
+ WaitForVSync();
+
+ // Enable all the planes through the DAC
+ WRITE_S3_UCHAR(DAC_Mask, 0xff);
+
+ // select plane 0, 1
+ WRITE_S3_UCHAR(Seq_Index, 0x02); // Enable Write Plane reg
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x02]);
+
+ // access to planes 0, 1.
+ WRITE_S3_UCHAR(Seq_Index, 0x04); // Memory Mode Control reg
+ WRITE_S3_UCHAR(Seq_Data, VideoParam[SEQ_OFFSET+0x04]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x05); // Graphic, Control Mode reg
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x05]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x04);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x04]);
+
+ WRITE_S3_UCHAR(GC_Index, 0x06);
+ WRITE_S3_UCHAR(GC_Data, VideoParam[GRAPH_OFFSET+0x06]);
+
+ //
+ // Set screen into blue
+ //
+ // HalDisplayString(" Set Screen into Blue ...\n");
+ for (DataLong = 0xB8000; DataLong < 0xB8FA0; DataLong += 2) {
+ WRITE_S3_VRAM(DataLong, 0x20);
+ WRITE_S3_VRAM(DataLong+1, 0x1F);
+ }
+ // End of initialize S3 standard VGA +3 mode
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ //IBMLAN===============================================================
+ // Added the following so that HalQueryDisplayParameters() and
+ // HalSetDisplayParameters() work with either S3 or P9.
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ HalpScrollLine = 160;
+ HalpScrollLength =
+ HalpScrollLine * (HalpDisplayText - 1);
+
+ //end IBMLAN===========================================================
+ HalpDisplayOwnedByHal = TRUE;
+
+ return;
+} /* end of HalpDisplayPpcS3Setup() */
+
+VOID
+HalpDisplayCharacterS3 (
+ IN UCHAR Character
+ )
+
+/*++
+Routine Description:
+
+ This routine displays a character at the current x and y positions in
+ the frame buffer. If a newline is encounter, then the frame buffer is
+ scrolled. If characters extend below the end of line, then they are not
+ displayed.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ //
+ // If the character is a newline, then scroll the screen up, blank the
+ // bottom line, and reset the x position.
+ //
+
+ if (Character == '\n') {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ Scroll_Screen(1);
+ }
+ }
+
+ else if( Character == '\t' ) // tab?
+ {
+ HalpColumn += TAB_SIZE;
+ HalpColumn = (HalpColumn / TAB_SIZE) * TAB_SIZE;
+
+ if( HalpColumn >= HalpDisplayWidth ) // tab beyond end of screen?
+ {
+ HalpColumn = 0; // next tab stop is 1st column of next line
+
+ if( HalpRow >= (HalpDisplayText - 1) )
+ Scroll_Screen( 1 ); // scroll the screen up
+ else
+ ++HalpRow;
+ }
+ }
+
+ else if (Character == '\r') {
+ HalpColumn = 0;
+ } else if (Character == 0x7f) { /* DEL character */
+ if (HalpColumn != 0) {
+ HalpColumn -= 1;
+ HalpOutputCharacterS3(0);
+ HalpColumn -= 1;
+ } else /* do nothing */
+ ;
+ } else if (Character >= 0x20) {
+ // Auto wrap for 80 columns per line
+ if (HalpColumn >= HalpDisplayWidth) {
+ HalpColumn = 0;
+ if (HalpRow < (HalpDisplayText - 1)) {
+ HalpRow += 1;
+ } else { // need to scroll up the screen
+ Scroll_Screen(1);
+ }
+ }
+ HalpOutputCharacterS3(Character);
+ } else /* skip the nonprintable character */
+ ;
+
+ return;
+
+} /* end of HalpDisplayCharacterS3() */
+
+
+VOID
+HalpOutputCharacterS3 (
+ IN UCHAR AsciiChar
+ )
+
+/*++
+
+Routine Description:
+
+ This routine insert a set of pixels into the display at the current x
+ cursor position. If the x cursor position is at the end of the line,
+ then no pixels are inserted in the display.
+
+Arguments:
+
+ Character - Supplies a character to be displayed.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ ULONG I;
+
+ //
+ // If the current x cursor position is within the current line, then insert
+ // the specified pixels into the last line of the text area and update the
+ // x cursor position.
+ //
+ if (HalpColumn < HalpDisplayWidth) {
+ I = (HalpRow*HalpScrollLine+HalpColumn*2);
+ WRITE_S3_VRAM(0xb8000 + I, AsciiChar);
+
+ HalpColumn += 1;
+ } else // could expand to automatic wrap line. 9/9/92 By Andrew
+ ;
+
+ return;
+} /* end of HalpOutputCharacterS3() */
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxs3.h b/private/ntos/nthals/halppc/ppc/pxs3.h
new file mode 100644
index 000000000..1647a0159
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxs3.h
@@ -0,0 +1,445 @@
+/*++
+
+Copyright (c) 1992 ACER Labs Inc.
+
+Module Name:
+
+ pxs3.h
+
+Abstract:
+
+ This header file defines the S3 86C911 GUI accelerator registers.
+
+Author:
+
+ Version 1.0 Kevin Chen 2-Apr-1992
+ Version 2.0 Andrew Chou Nov-24-1992
+ Version 3.0 Jess Botts Oct-06-1993 Power PC Initial Version
+
+--*/
+
+#define VERTICALRESOLUTION 768
+#define HORIZONTALRESOLUTION 1024
+#define OriginalPoint 0
+#define BLUE 192
+#define WHITE 255
+#define CRT_OFFSET 2
+#define SEQ_OFFSET 27
+#define GRAPH_OFFSET 32
+#define ATTR_OFFSET 41
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+extern PVOID HalpIoControlBase;
+
+//
+// Define S3 register I/O Macros
+//
+
+//=============================================================================
+//
+// IBMBJB Changed the semicolons separating statements in the write macros to
+// commas so that if the macro is used as the only statement in a loop
+// all of the statements in the macro will be part of the loop.
+//
+// Commas were used instead of putting braces around the statements
+// because if the macro is used in the true part of a conditional the
+// braces will cause the compiler to generate a syntax error.
+
+#define WRITE_S3_UCHAR(port,data) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port)) = (UCHAR)(data), \
+ KeFlushWriteBuffer()
+
+#define WRITE_S3_USHORT(port,data) \
+ *(volatile PUSHORT)((ULONG)HalpIoControlBase + (port)) = (USHORT)(data), \
+ KeFlushWriteBuffer()
+
+#define READ_S3_UCHAR(port) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_S3_USHORT(port) \
+ *(volatile unsigned short *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_S3_VRAM(port) \
+ *(HalpVideoMemoryBase + (port))
+
+#define WRITE_S3_VRAM(port,data) \
+ *(HalpVideoMemoryBase + (port)) = (data), \
+ KeFlushWriteBuffer()
+
+//=============================================================================
+
+#define DISPLAY_BITS_PER_PIXEL 8 // display bits per pixel
+#define NUMBER_OF_COLORS 256 // number of colors
+
+#define CURSOR_WIDTH 64 // width of hardware cursor
+#define CURSOR_HEIGHT 64 // height of hardware cursor
+#define CURSOR_BITS_PER_PIXEL 2 // hardware cursor bits per pixel
+
+//
+// S3 86C911 GUI, accelerator Video Controller Definitions.
+//
+// Define video register format.
+//
+#define PosID_LO 0x100 // R/W
+#define PosID_HI 0x101 // R/W
+#define Setup_OP 0x102 // R/W
+#define Chck_Ind 0x105 // R
+#define Mono_3B4 0x3B4 // R/W
+#define Mono_3B5 0x3B5 // R/W
+#define MDA_Mode 0x3B8 // W
+#define HGC_SLPEN 0x3B9 // R/W
+#define Stat1_MonoIn 0x3BA // R
+#define FC_MonoW 0x3BA // W
+#define HGC_CLPEN 0x3BB // W
+#define HGC_Config 0x3BF // W
+#define Attr_Index 0x3C0 // R/W
+#define Attr_Data 0x3C0 // R/W
+#define Stat0_In 0x3C2 // R
+#define MiscOutW 0x3C2 // W
+#define VSub_EnB 0x3C3 // R/W
+#define Seq_Index 0x3C4 // R/W
+#define Seq_Data 0x3C5 // R/W
+#define DAC_Mask 0x3C6 // R/W
+#define DAC_RIndex 0x3C7 // W
+#define DAC_Status 0x3C7 // W
+#define DAC_WIndex 0x3C8 // R/W
+#define DAC_Data 0x3C9 // R/W
+#define FC_Read 0x3CA // R
+#define MiscOutR 0x3CC // R
+#define GC_Index 0x3CE // R/W
+#define GC_Data 0x3CF // R/W
+#define S3_3D4_Index 0x3D4 // R/W
+#define S3_3D5_Data 0x3D5 // R/W
+
+#define CGA_Mode 0x3D8 // W
+#define CGA_Color 0x3D9 // W
+#define Stat1_In 0x3DA // R
+#define FC_Write 0x3DA // W
+#define CLPEN 0x3DB
+#define SLPEN 0x3DC
+
+//
+// Define Enhanced registers for S3_86C911
+//
+
+#define SUBSYS_STAT 0x42E8 // R
+#define SUBSYS_CNTL 0x42E8 // W
+#define SUBSYS_ENB 0x46E8 // R/W
+#define ADVFUNC_CNTL 0x4AE8 // W
+#define CUR_Y 0x82E8 // R/W
+#define CUR_X 0x86E8 // R/W
+#define DESTY 0x8AE8 // W
+#define AXIAL_STEP 0x8AE8 // W
+#define DESTX 0x8EE8 // W
+#define DIAG_STEP 0x8EE8 // W
+#define ERR_TERM 0x92E8 // R
+#define MAJ_AXIS_PCNT 0x96E8 // W
+#define RWIDTH 0x96E8 // W
+#define GP_STAT 0x9AE8 // R
+#define DRAW_CMD 0x9AE8 // W
+#define SHORT_STROKE 0x9EE8 // W
+#define BKGD_COLOR 0xA2E8 // W
+#define FRGD_COLOR 0xA6E8 // W
+#define WRITE_MASK 0xAAE8 // W
+#define READ_MASK 0xAEE8 // W
+#define BKGD_MIX 0xB6E8 // W
+#define FRGD_MIX 0xBAE8 // W
+#define MULTIFUNC_CNTL 0xBEE8 // W
+#define RHEIGHT 0xBEE8 // W
+#define PIX_TRANS 0xE2E8 // W
+
+
+//
+// Define Attribute Controller Indexes : ( out 3C0, Index )
+//
+
+#define PALETTE0 0
+#define PALETTE1 1
+#define PALETTE2 2
+#define PALETTE3 3
+#define PALETTE4 4
+#define PALETTE5 5
+#define PALETTE6 6
+#define PALETTE7 7
+#define PALETTE8 8
+#define PALETTE9 9
+#define PALETTE10 10
+#define PALETTE11 11
+#define PALETTE12 12
+#define PALETTE13 13
+#define PALETTE14 14
+#define PALETTE15 15
+#define ATTR_MODE_CTRL 16
+#define BORDER_COLOR 17
+#define COLOR_PLANE_ENABLE 18
+#define HORI_PIXEL_PANNING 19
+#define PIXEL_PADDING 20
+
+//
+// Define Sequencer Indexes ( out 3C4, Index)
+//
+
+#define RESET 0
+#define CLOCKING_MODE 1
+#define ENABLE_WRITE_PLANE 2
+#define CHARACTER_FONT_SELECT 3
+#define MEMORY_MODE_CONTROL 4
+
+//
+// Define Graphics Controller Index ( out 3CE, Index )
+//
+
+#define SET_RESET 0
+#define ENABLE_SET_RESET 1
+#define COLOR_COMPARE 2
+#define DATA_ROTATE 3
+#define READ_PLANE_SELECT 4
+#define GRAPHICS_CTRL_MODE 5
+#define MEMORY_MAP_MODE 6
+#define COLOR_DONT_CARE 7
+#define BIT_MASK 8
+
+//
+// Define CRTC, VGA S3, SYS_CTRL Index : ( Out 3D4, Index )
+//
+// Define CRTC Controller Indexes
+//
+
+#define HORIZONTAL_TOTAL 0
+#define HORIZONTAL_DISPLAY_END 1
+#define START_HORIZONTAL_BLANK 2
+#define END_HORIZONTAL_BLANK 3
+#define HORIZONTAL_SYNC_POS 4
+#define END_HORIZONTAL_SYNC 5
+#define VERTICAL_TOTAL 6
+#define CRTC_OVERFLOW 7
+#define PRESET_ROW_SCAN 8
+#define MAX_SCAN_LINE 9
+#define CURSOR_START 10
+#define CURSOR_END 11
+#define START_ADDRESS_HIGH 12
+#define START_ADDRESS_LOW 13
+#define CURSOR_LOCATION_HIGH 14
+#define CURSOR_FCOLOR 14
+#define CURSOR_BCOLOR 15
+#define CURSOR_LOCATION_LOW 15
+#define VERTICAL_RETRACE_START 16
+#define VERTICAL_RETRACE_END 17
+#define VERTICAL_DISPLAY_END 18
+#define OFFSET_SCREEN_WIDTH 19
+#define UNDERLINE_LOCATION 20
+#define START_VERTICAL_BLANK 21
+#define END_VERTICAL_BLANK 22
+#define CRT_MODE_CONTROL 23
+#define LINE_COMPARE 24
+#define CPU_LATCH_DATA 34
+#define ATTRIBUTE_INDEX1 36
+#define ATTRIBUTE_INDEX2 38
+
+//
+// Define VGA S3 Indexes
+//
+#define S3R0 0x30
+#define S3R1 0x31
+#define S3R2 0x32
+#define S3R3 0x33
+#define S3R4 0x34
+#define S3R5 0x35
+#define S3R6 0x36
+#define S3R7 0x37
+#define S3R8 0x38
+#define S3R9 0x39
+#define S3R0A 0x3A
+#define S3R0B 0x3B
+#define S3R0C 0x3C
+#define SC0 0x40
+#define SC2 0x42
+#define SC3 0x43
+#define SC5 0x45
+
+//
+// Define System Control Indexes
+//
+#define SYS_CNFG 64
+#define SOFT_STATUS 65
+#define MODE_CTRL 66
+#define EXT_MODE 67
+#define HGC_MODE 69
+#define HGC_ORGX0 70
+#define HGC_ORGX1 71
+#define HGC_ORGY0 72
+#define HGC_ORGY1 73
+#define HGC_YSTART0 76
+#define HGC_YSTART1 77
+#define HGC_DISPX 78
+#define HGC_DISPY 79
+
+#define ENABLE_HARDWARE_CURSOR 1
+#define DISABLE_HARDWARE_CURSOR 0
+
+//
+// define advanced function control register structure
+//
+#define RES_640x480 0
+#define RES_1024x768 1
+#define RES_800x600 1
+
+#define ENABLE_VGA 6
+#define ENABLE_ENHANCED 7
+
+//
+// define draw command register values
+//
+#define NOP_COMMAND 0x0
+#define DRAW_LINE_COMMAND 0x2000
+#define RECTANGLE_FILL_COMMAND 0x4000
+#define BITBLT_COMMAND 0xc000
+#define BYTE_SWAP 0x1000
+#define NO_BYTE_SWAP 0x0
+#define SIXTEEN_BIT_BUS 0x0200
+#define EIGHT_BIT_BUS 0x0
+#define WAIT 0x0100
+#define NO_WAIT 0x0
+#define R0 0x0
+#define R45 0x20
+#define R90 0x40
+#define R135 0x60
+#define R180 0x80
+#define R225 0xa0
+#define R270 0xc0
+#define R315 0xe0
+#define XMAJ 0x0
+#define YMAJ 0x40
+#define XPositive 0x20
+#define YPositive 0x80
+#define XNegative 0x0
+#define YNegative 0x0
+
+#define DRAW_YES 0x10
+#define DRAW_NO 0x0
+#define RADIAL 8
+#define XY_BASE 0
+#define LAST_PIXEL_OFF 4
+#define LAST_PIXEL_ON 0
+#define MULTIPLE_PIXEL 2
+#define SINGLE_PIXEL 0
+#define DRAW_READ 0
+#define DRAW_WRITE 1
+
+#define SSV_DRAW 0x1000
+#define SSV_MOVE 0x0
+
+#define OneEmpty 0x80
+#define TwoEmpty 0x40
+#define ThreeEmpty 0x20
+#define FourEmpty 0x10
+#define FiveEmpty 0x8
+#define SixEmpty 0x4
+#define SevenEmpty 0x2
+#define EightEmpty 0x1
+
+#define BACKGROUND_COLOR 0
+#define FOREGROUND_COLOR 0x20
+#define CPU_DATA 0x40
+#define DISPLAY_MEMORTY 0x60
+#define NOT_SCREEN 0
+#define LOGICAL_ZERO 1
+#define LOGICAL_ONE 2
+#define LEAVE_ALONE 3
+#define NOT_NEW 4
+#define SCREEN_XOR_NEW 5
+#define NOT_SCREEN_XOR_NEW 6
+#define OVERPAINT 7 //( NEW )
+#define NOT_SCREEN_OR_NOT_NEW 8
+#define SCREEN_OR_NOT_NEW 9
+#define NOT_SCREEN_OR_NEW 10
+#define SCREEN_OR_NEW 11
+#define SCREEN_AND_NEW 12
+#define NOT_SCREEN_AND_NEW 13
+#define SCREEN_AND_NOT_NEW 14
+#define NOT_SCREEN_AND_NOT_NEW 15
+
+#define BEE8_1H 1
+#define BEE8_2H 2
+#define BEE8_3H 3
+#define BEE8_4H 4
+#define BEE8_0H 0
+#define L_CLIP 0x1000
+#define R_CLIP 0x2000
+#define B_CLIP 0x3000
+#define T_CLIP 0x4000
+
+#define DATA_EXTENSION 0xa000 // 10100000B
+#define CPU_EXT 0x80
+#define DISPLAY_EXT 0xc0
+#define NO_EXTENSION 0x0
+#define PACK_DATA 0x4
+#define NO_PACK_DATA 0x0
+#define SET_THIS_BIT_TO_ZERO 0;
+
+//
+// Define bits per pixel codes.
+//
+#define ONE_BIT_PER_PIXEL 0 // 1-bit per pixel
+#define TWO_BITS_PER_PIXEL 1 // 2-bits per pixel
+#define FOUR_BITS_PER_PIXEL 2 // 4-bits per pixel
+#define EIGHT_BITS_PER_PIXEL 3 // 8-bits per pixel
+
+//
+// Define address step value.
+//
+#define ADDRESS_STEP_INCREMENT 1 // vram transfer address increment
+
+//
+// Define cross hair thickness values.
+//
+#define ONE_PIXEL_THICK 0x0 // one pixel in thickness
+#define THREE_PIXELS_THICK 0x1 // three pixels in thickness
+#define FIVE_PIXELS_THICK 0x2 // five pixels in thickness
+#define SEVEN_PIXELS_THICK 0x3 // seven pixels in thickness
+
+//
+// Define multiplexer control values.
+//
+#define ONE_TO_ONE 0x0 // 1:1 multiplexing
+#define FOUR_TO_ONE 0x1 // 4:1 multiplexing
+#define FIVE_TO_ONE 0x2 // 5:1 multiplexing
+
+//
+// Define cursor origin values.
+//
+
+#define CURSOR_X_ORIGIN (((2*HORIZONAL_SYNC_VALUE)+BACK_PORCH_VALUE)*4-36)
+#define CURSOR_Y_ORIGIN ((VERTICAL_BLANK_VALUE/2)+24)
+
+ULONG HotspotX, HotspotY;
+
+// Extended VGA BIOS
+#define SUPER_VGA_SUPPORT 4FH
+#define RET_EXT_VGA_INFO 00H
+#define RET_EXT_VGA_MODE_INFO 01H
+#define SET_EXT_VGA_MODE 02H
+#define QUERY_CUR_EXT_VGA_MODE 03H
+
+#define SAVE_RESTORE_FUNCTION 04H
+// Function 04.0 Query Save/Restore Buffer Size
+#define GET_SAVE_BUFFER_SIZE 00H
+// Function 04.1 Save Extended Video state
+#define SAVE_STATE 01H
+// Function 04.2 Restore Extended VGA state
+#define RESTORE_STATE 02H
+
+#define WINDOWS_CONTROL 05H
+// Function 05.0 Set Window Control
+#define SELECT_PAGE_TO_BE_MAPPED 00H
+// fUNCTION 05.1 Get Window Control Setting
+#define GET_PAGE_MAPPED 01H
+
+#define SET_RESET_DUAL_DISPLAY_MODE FFH
+
+BOOLEAN ColorMonitor;
+PVOID S3_3x4, S3_3x5;
+
diff --git a/private/ntos/nthals/halppc/ppc/pxshadbf.s b/private/ntos/nthals/halppc/ppc/pxshadbf.s
new file mode 100644
index 000000000..ec215c2e9
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxshadbf.s
@@ -0,0 +1,37 @@
+//++
+//
+// Copyright (c) 1993, 1994, 1995 IBM Corporation
+//
+// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Module Name:
+//
+// pxshadbf.s
+//
+// Abstract:
+//
+// This file creates a 64K buffer that will be thrown away
+// at the end of init time. It is to be used for video
+// bios shadowing.
+//
+// Author:
+//
+// Peter L. Johnston (plj@vnet.ibm.com) July 1995
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+ .new_section INIT,"rcxw"
+ .section INIT,"rcxw"
+
+ .globl HalpShadowBufferPhase0
+HalpShadowBufferPhase0:
+ .space 128*1024
+
diff --git a/private/ntos/nthals/halppc/ppc/pxsiosup.c b/private/ntos/nthals/halppc/ppc/pxsiosup.c
new file mode 100644
index 000000000..64c20c2e6
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxsiosup.c
@@ -0,0 +1,2218 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Copyright (c) 1996 International Business Machines Corporation
+
+Module Name:
+
+ pxsiosup.c
+
+Abstract:
+
+ The module provides the PCI ISA bridge support.
+
+Author:
+
+ Jim Wooldridge (jimw@vnet.ibm.com)
+
+
+Revision History:
+
+
+--*/
+
+
+#include "halp.h"
+#include "eisa.h"
+#include "pxsiosup.h"
+#include <pxmemctl.h>
+#include "bugcodes.h"
+
+extern UCHAR VectorToIrqlTable[];
+
+#define SioId 0x04848086
+
+PVOID HalpPciIsaBridgeConfigBase;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+extern ULONG HalpPciMaxSlots;
+extern ULONG HalpPhase0GetPciDataByOffset();
+extern ULONG HalpPhase0SetPciDataByOffset();
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine,
+ PVOID ServiceContext,
+ PVOID TrapFrame
+ );
+
+//
+// Declare the interupt structure for profile interrupt
+//
+
+KINTERRUPT HalpProfileInterrupt;
+
+//
+// The following is the interrupt object used for DMA controller interrupts.
+// DMA controller interrupts occur when a memory parity error occurs or a
+// programming error occurs to the DMA controller.
+//
+
+//
+// Declare the interupt structure for machine checks
+//
+
+KINTERRUPT HalpMachineCheckInterrupt;
+
+//
+// Declare the interupt structure for the clock interrupt
+//
+
+KINTERRUPT HalpDecrementerInterrupt;
+
+
+//
+// Add spurious and bogus interrupt counts
+//
+
+#if DBG
+ULONG HalpSpuriousInterruptCount = 0;
+ULONG HalpBogusInterruptCount = 0;
+#endif
+
+
+//
+// Define Isa bus interrupt affinity.
+//
+
+KAFFINITY HalpIsaBusAffinity;
+
+
+//
+// The following function is called when a machine check occurs.
+//
+
+BOOLEAN
+HalpHandleMachineCheck(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+//
+// Define save area for ISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpIsaAdapter[8];
+
+//
+// Define save area for ISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+#define ISA_CONTROL ((PEISA_CONTROL) HalpIoControlBase)
+extern UCHAR HalpSioInterrupt1Mask;
+extern UCHAR HalpSioInterrupt2Mask;
+extern USHORT Halp8259MaskTable[];
+
+UCHAR HalpSioInterrupt1Mask = 0xff;
+UCHAR HalpSioInterrupt2Mask = 0xff;
+UCHAR HalpSioInterrupt1Level;
+UCHAR HalpSioInterrupt2Level;
+
+#if defined(SOFT_HDD_LAMP)
+
+//
+// On PowerPC machines the HDD lamp is software driven. We
+// turn it on any time we take an interrupt from a Mass Storage
+// Controller (assuming it isn't already on) and turn it off the 2nd
+// clock tick after we turn it on if we have not received
+// any more MSC interrupts since the first clock tick.
+//
+
+HDD_LAMP_STATUS HalpHddLamp;
+
+ULONG HalpMassStorageControllerVectors;
+
+#endif
+
+#ifdef POWER_MANAGEMENT
+//
+// Define save area for DMA channel extended mode.
+//
+
+DMA_EXTENDED_MODE Dma1ExtendedMode[4];
+DMA_EXTENDED_MODE Dma2ExtendedMode[4];
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGELK, HalpInitInterruptController)
+#pragma alloc_text(PAGELK, HalpInitDmaController)
+#endif // ALLOC_PRAGMA
+
+#endif // POWER_MANAGEMENT
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called from phase 0 initialization, it initializes the
+ 8259 interrupt controller ( currently it masks all 8259 interrupts).
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+
+--*/
+
+{
+ ULONG Vector;
+
+ //
+ // Mask all 8259 interrupts (except the cascade interrupt)
+ //
+
+ for (Vector=0;Vector<16;Vector++) {
+ if (Vector == 2)
+ continue;
+ HalpDisableSioInterrupt(Vector + DEVICE_VECTORS);
+ }
+
+ //
+ // Reserve the external interrupt vector for exclusive use by the HAL.
+ //
+
+ PCR->ReservedVectors |= (1 << EXTERNAL_INTERRUPT_VECTOR);
+
+ return TRUE;
+
+}
+
+
+BOOLEAN
+HalpCreateSioStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for SIO operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ SIO interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher is connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL oldIrql;
+
+
+ //
+ // Initialize the Machine Check interrupt handler
+ //
+
+ if (HalpEnableInterruptHandler(&HalpMachineCheckInterrupt,
+ HalpHandleMachineCheck,
+ NULL,
+ NULL,
+ MACHINE_CHECK_VECTOR,
+ MACHINE_CHECK_LEVEL,
+ MACHINE_CHECK_LEVEL,
+ Latched,
+ FALSE,
+ 0,
+ FALSE,
+ InternalUsage,
+ MACHINE_CHECK_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ //
+ // Enable NMI IOCHK# and PCI SERR#
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->NmiStatus,
+ DataByte & ~DISABLE_IOCHK_NMI & ~DISABLE_PCI_SERR_NMI);
+
+ //
+ // Clear the SIO NMI disable bit. This bit is the high order of the
+ // NMI enable register.
+ //
+
+ DataByte = 0;
+
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ DataByte
+ );
+
+ //
+ // Connect the external interrupt handler
+ //
+
+ PCR->InterruptRoutine[EXTERNAL_INTERRUPT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleExternalInterrupt;
+
+ //
+ // register the interrupt vector
+ //
+
+ HalpRegisterVector(InternalUsage,
+ EXTERNAL_INTERRUPT_VECTOR,
+ EXTERNAL_INTERRUPT_VECTOR,
+ HIGH_LEVEL);
+
+
+
+
+ // Connect directly to the decrementer handler. This is done
+ // directly rather than thru HalpEnableInterruptHandler due to
+ // special handling required because the handler calls KdPollBreakIn().
+ //
+
+ PCR->InterruptRoutine[DECREMENT_VECTOR] =
+ (PKINTERRUPT_ROUTINE)HalpHandleDecrementerInterrupt;
+
+ //
+ // Initialize and connect the Timer 1 interrupt (IRQ0)
+ //
+
+ if (HalpEnableInterruptHandler( &HalpProfileInterrupt,
+ (PKSERVICE_ROUTINE) HalpHandleProfileInterrupt,
+ (PVOID) NULL,
+ (PKSPIN_LOCK)NULL,
+ PROFILE_VECTOR,
+ PROFILE_LEVEL,
+ PROFILE_LEVEL,
+ Latched,
+ TRUE,
+ 0,
+ FALSE,
+ DeviceUsage,
+ PROFILE_VECTOR
+ ) == FALSE) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+
+ //
+ // Disable Timer 1; only used by profiling
+ //
+
+ HalDisableSystemInterrupt(PROFILE_VECTOR, PROFILE_LEVEL);
+
+ //
+ // Set default profile rate
+ //
+
+ HalSetProfileInterval(5000);
+
+
+ //
+ // Raise the IRQL while the SIO interrupt controller is initalized.
+ //
+
+ KeRaiseIrql(CLOCK2_LEVEL, &oldIrql);
+
+
+
+ //
+ // Initialize any planar registers
+ //
+
+ HalpInitPlanar();
+
+ //
+ // Initialize the PCI/ISA bridge chip
+ //
+
+ HalpInitPciIsaBridge();
+
+
+
+ //
+ // Initialize the SIO interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpSioInterrupt1Mask = (UCHAR) ~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ HalpSioInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpSioInterrupt1Level = 0;
+ HalpSioInterrupt2Level = 0;
+
+ //
+ // Enable the clock interrupt
+ //
+
+
+ HalpUpdateDecrementer(1000); // Get those decrementer ticks going
+
+
+ //
+ // Set ISA bus interrupt affinity.
+ //
+
+ HalpIsaBusAffinity = PCR->SetMember;
+
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+
+ //
+ // DMA command - set assert level
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus,
+ DataByte & ~DACK_ASSERT_HIGH & ~DREQ_ASSERT_LOW);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpInitPciIsaBridge (
+ VOID
+ )
+
+
+{
+
+ UCHAR DataByte;
+ BOOLEAN Found;
+ ULONG SlotNumber;
+ ULONG ChipId;
+ ULONG BufferLength;
+
+
+ Found = FALSE;
+ SlotNumber = 0;
+
+ while (!Found && SlotNumber < HalpPciMaxSlots) {
+
+ BufferLength = HalpPhase0GetPciDataByOffset(0,
+ SlotNumber,
+ &ChipId,
+ 0,
+ sizeof(ChipId));
+ if (ChipId == SioId)
+ Found = TRUE;
+ else
+ SlotNumber++;
+
+
+ }
+
+ //
+ // Make sure that we found a valid chip id
+ //
+
+ if (!Found)
+ return FALSE;
+
+ //
+ // Define macros for reading and writing to the SIO config space
+ //
+
+#define READ_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalpPhase0GetPciDataByOffset( \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+#define WRITE_SIO_CONFIG_UCHAR(offset,byte) \
+ ( \
+ HalpPhase0SetPciDataByOffset( \
+ 0, \
+ SlotNumber, \
+ &byte, \
+ FIELD_OFFSET(SIO_CONFIG,offset), \
+ 1 \
+ ) \
+ )
+
+
+
+ //
+ // Enable ISA Master line buffering
+ //
+
+
+
+ READ_SIO_CONFIG_UCHAR(PciControl,DataByte);
+
+ DataByte |= ENABLE_PCI_POSTED_WRITE_BUFFER
+ | ENABLE_ISA_MASTER_LINE_BUFFER
+ | EANBLE_DMA_LINE_BUFFER;
+
+ WRITE_SIO_CONFIG_UCHAR(PciControl, DataByte );
+
+ //
+ // Disable Gauranteed Access Time Mode
+ //
+
+ READ_SIO_CONFIG_UCHAR(PciArbiterControl,DataByte);
+
+ DataByte &= ~ENABLE_GAT;
+
+ WRITE_SIO_CONFIG_UCHAR(PciArbiterControl, DataByte);
+
+
+
+
+ //
+ // Initialize SuperIO chip
+ //
+
+ if (!HalpInitSuperIo())
+
+ return FALSE;
+
+
+ //
+ // Utility Bus A chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableA,DataByte);
+
+ DataByte |= ENABLE_RTC | ENABLE_KEYBOARD & ~ENABLE_IDE_DECODE;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableA, DataByte);
+
+ //
+ // Utility Bus B chip select
+ //
+
+ READ_SIO_CONFIG_UCHAR(UtilityBusEnableB,DataByte);
+
+ DataByte |= ENABLE_RAM_DECODE | ENABLE_PORT92 | DISABLE_PARALLEL_PORT
+ | DISABLE_SERIAL_PORTA | DISABLE_SERIAL_PORTB;
+
+ WRITE_SIO_CONFIG_UCHAR(UtilityBusEnableB, DataByte);
+
+ return TRUE;
+
+}
+
+
+BOOLEAN
+HalpMapIoControlSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL SIO control space for a PowerPC system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map SIO control space.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = IO_CONTROL_PHYSICAL_BASE;
+ HalpIoControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+
+ if (HalpIoControlBase == NULL)
+ return FALSE;
+ else
+ return TRUE;
+
+}
+BOOLEAN
+HalpHandleExternalInterrupt(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext,
+ IN PVOID TrapFrame
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is connected to an interrupt object that describes
+ the SIO device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the SIO
+ controller.
+
+ N.B. This routine in entered and left with external interrupts disabled.
+
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the SIO interrupt acknowledge
+ register.
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ PSECONDARY_DISPATCH SioHandler;
+ PKINTERRUPT SioInterrupt;
+ USHORT interruptVector;
+ BOOLEAN returnValue;
+ UCHAR OldIrql;
+ USHORT Isr;
+ UCHAR Irql;
+ PUCHAR PIC_Address;
+ UCHAR PIC_Mask;
+
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(HalpInterruptBase);
+
+ //
+ // check for spurious interrupt
+ //
+
+ if (interruptVector == SPURIOUS_VECTOR) {
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0,
+ 0x0B);
+ Isr = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Interrupt1ControlPort0);
+ if (!(Isr & 0x80)) {
+
+ //
+ // Spurious interrupt
+ //
+
+#if DBG
+ HalpSpuriousInterruptCount++;
+#endif
+ return(0);
+
+ }
+ }
+
+#if defined(SOFT_HDD_LAMP)
+
+ if ( HalpMassStorageControllerVectors & (1 << interruptVector) ) {
+ //
+ // On any Mass Storage Controller interrupt, light the HDD lamp.
+ // The system timer routines will turn it off again in a little
+ // while.
+ //
+
+ if ( !HalpHddLamp.Count ) {
+ *(PUCHAR)((PUCHAR)HalpIoControlBase + HDD_LAMP_PORT) = 1;
+ }
+ HalpHddLamp.Count = SOFT_HDD_TICK_COUNT;
+ }
+
+#endif
+
+ //
+ // raise irql
+ //
+
+ Irql = VectorToIrqlTable[interruptVector];
+
+ OldIrql = PCR->CurrentIrql;
+ PCR->CurrentIrql = Irql;
+
+ HalpEnableInterrupts();
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ SioHandler = (PSECONDARY_DISPATCH)
+ PCR->InterruptRoutine[DEVICE_VECTORS + interruptVector];
+ SioInterrupt = CONTAINING_RECORD(SioHandler,
+ KINTERRUPT,
+ DispatchCode[0]);
+
+ returnValue = SioHandler(SioInterrupt,
+ SioInterrupt->ServiceContext,
+ TrapFrame
+ );
+
+ //
+ // Dismiss the interrupt in the SIO interrupt controllers. We disable
+ // interrupts first so we won't get multiple interrupts at this level
+ // without popping the stack.
+ //
+
+ HalpDisableInterrupts();
+
+ //
+ // If this is a cascaded interrupt then the interrupt must be dismissed in
+ // both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ //
+ // Lower IRQL but leave external interrupts disabled.
+ // Return to caller with interrupts disabled.
+ //
+
+ PCR->CurrentIrql = OldIrql;
+
+ //
+ // Partial lazy irql - if hardware irql mask isn't what is should be
+ // set it and the interrupt controllers mask.
+ //
+
+ if (HALPCR->HardPriority != PCR->CurrentIrql) {
+
+ HALPCR->HardPriority = OldIrql;
+
+ PIC_Mask = HalpSioInterrupt1Mask | (Halp8259MaskTable[OldIrql] & 0x00FF);
+ PIC_Address = &(ISA_CONTROL->Interrupt1ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+
+ //
+ // Get contoller 2 interrupt mask
+ //
+
+ PIC_Mask = HalpSioInterrupt2Mask | (Halp8259MaskTable[OldIrql] >> 8 );
+ PIC_Address = &(ISA_CONTROL->Interrupt2ControlPort1);
+ WRITE_REGISTER_UCHAR(PIC_Address, PIC_Mask);
+ }
+
+ return(returnValue);
+
+}
+
+VOID
+HalpDisableSioInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the SIO interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ }
+
+}
+
+VOID
+HalpIsaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+/*++
+
+Routine Description:
+
+ This function programs the SIO DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed.
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes.
+
+ WriteToDevice - Indicates the direction of the transfer.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PUCHAR BytePtr;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ KIRQL Irql;
+
+
+ ASSERT(Offset >= IO_CONTROL_PHYSICAL_BASE);
+
+ adapterMode = AdapterObject->AdapterMode;
+
+ //
+ // Check to see if this request is for a master I/O card.
+ //
+
+ if (((PDMA_EISA_MODE) &adapterMode)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ //
+ // Set the mode, Disable the request and return.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ return;
+ }
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ BytePtr = (PUCHAR) &Offset;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ Length >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = BytePtr[2];
+ Offset >>= 1;
+ BytePtr[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ BytePtr[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpIoControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[3]
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((Length - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+}
+
+VOID
+HalpEnableSioInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the SIO interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the SIO interrupt vector.
+ //
+
+ Vector -= DEVICE_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2EdgeLevel,
+ HalpSioInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpSioInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpSioInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpSioInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1EdgeLevel,
+ HalpSioInterrupt1Level
+ );
+ }
+
+}
+
+PADAPTER_OBJECT
+HalpAllocateIsaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an ISA adapter object according to the
+ specification supplied in the device description. The necessary device
+ descriptor information is saved. If there is
+ no existing adapter object for this channel then a new one is allocated.
+ The saved information in the adapter object is used to set the various DMA
+ modes when the channel is allocated or a map transfer is done.
+
+Arguments:
+
+ DeviceDescription - Supplies the description of the device which want to
+ use the DMA adapter.
+
+ NumberofMapRegisters - number of map registers required for the adapter
+ object created
+
+
+Return Value:
+
+ Returns a pointer to the newly created adapter object or NULL if one
+ cannot be created.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT adapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG numberOfMapRegisters;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+#ifdef POWER_MANAGEMENT
+ PDMA_EXTENDED_MODE pointerExtendedMode;
+#endif // POWER_MANAGEMENT
+
+ //
+ // Determine if the the channel number is important. Master cards
+ // do not use a channel number.
+ //
+
+
+ if ((DeviceDescriptor->Master) && (DeviceDescriptor->InterfaceType != Isa)) {
+
+ useChannel = FALSE;
+
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if ((DeviceDescriptor->DmaChannel == 4 ||
+ DeviceDescriptor->DmaChannel > 7) && useChannel) {
+
+ return(NULL);
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather &&
+ !(DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->Master)) {
+
+
+ //
+ // Scatter gather not supported in SIO
+ //
+
+ if (!DeviceDescriptor->Master)
+
+ //
+ // one map register will be required when the the SIO supports this
+ //
+ // numberOfMapRegisters = 1;
+
+ return NULL;
+
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // If the device is not a master then it only needs one map register
+ // and does scatter/Gather.
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpIsaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpIsaAdapter[DeviceDescriptor->DmaChannel];
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpIsaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The speicified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 2;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters &&
+ MasterAdapterObject->CommittedMapRegisters -
+ MasterAdapterObject->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER ) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+
+ }
+
+
+ if (DeviceDescriptor->Master && (DeviceDescriptor->InterfaceType == Isa)) {
+
+ adapterObject->IsaBusMaster = TRUE;
+
+ } else {
+
+ adapterObject->IsaBusMaster = FALSE;
+
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ if (!useChannel) {
+ adapterObject->PagePort = (PVOID) (~0x0);
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1ExtendedModePort;
+
+#ifdef POWER_MANAGEMENT
+ pointerExtendedMode = Dma1ExtendedMode;
+#endif // POWER_MANAGEMENT
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2ExtendedModePort;
+
+#ifdef POWER_MANAGEMENT
+ pointerExtendedMode = Dma2ExtendedMode;
+#endif // POWER_MANAGEMENT
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR) channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+#ifdef POWER_MANAGEMENT
+ *(pointerExtendedMode + channelNumber) = extendedMode;
+#endif // POWER_MANAGEMENT
+
+ //
+ // Initialize the adapter mode register value to the correct parameters,
+ // and save them in the adapter object.
+ //
+
+ adapterMode = 0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = adapterObject->ChannelNumber;
+
+ if (DeviceDescriptor->Master) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = CASCADE_REQUEST_MODE;
+
+ //
+ // Set the mode, and enable the request.
+ //
+
+ if (adapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = adapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ //
+ // Unmask the DMA channel.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | adapterObject->ChannelNumber)
+ );
+
+ }
+
+ } else if (DeviceDescriptor->DemandMode) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = DEMAND_REQUEST_MODE;
+
+ } else {
+
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = SINGLE_REQUEST_MODE;
+
+ }
+
+ if (DeviceDescriptor->AutoInitialize) {
+
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 1;
+
+ }
+
+ adapterObject->AdapterMode = adapterMode;
+
+ return(adapterObject);
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ }
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+
+
+ return(count);
+}
+
+
+VOID
+HalpHandleIoError (
+ VOID
+ )
+
+{
+
+ UCHAR StatusByte;
+
+
+ //
+ // Read NMI status
+ //
+
+ StatusByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiStatus);
+
+ //
+ // Test for PCI bus error
+ //
+
+ if (StatusByte & 0x40) {
+ HalDisplayString ("NMI: IOCHK\n");
+ }
+
+ //
+ // Test for ISA IOCHK
+ //
+
+ if (StatusByte & 0x80) {
+ HalDisplayString ("NMI: PCI System Error\n");
+ }
+
+}
+
+#ifdef POWER_MANAGEMENT
+
+VOID
+HalpInitInterruptController (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine re-initializes the SIO interrupt controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR DataByte;
+
+ //
+ // Disable all of the interrupts
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ 0xFF
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ 0xFF
+ );
+
+ //
+ // Initialize the SIO interrupt controller. There are two cascaded
+ // interrupt controllers, each of which must initialized with 4 initialize
+ // control words.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->Icw4Needed = 1;
+ ((PINITIALIZATION_COMMAND_1) &DataByte)->InitializationFlag = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The thrid initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numberic.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The fourth initialization control word is used to specify normal
+ // end-of-interrupt mode and not special-fully-nested mode.
+ //
+
+ DataByte = 0;
+ ((PINITIALIZATION_COMMAND_4) &DataByte)->I80x86Mode = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // Re-enable the interrupts
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt1ControlPort1,
+ HalpSioInterrupt1Mask
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Interrupt2ControlPort1,
+ HalpSioInterrupt2Mask
+ );
+
+ return;
+}
+
+
+VOID
+HalpInitDmaController (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine re-initializes the SIO DMA controller.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR DataByte;
+ ULONG channelNumber;
+
+ //
+ // DMA command - set assert level
+ //
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus);
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL)HalpIoControlBase)->Dma1BasePort.DmaStatus,
+ DataByte & ~DACK_ASSERT_HIGH & ~DREQ_ASSERT_LOW);
+
+ //
+ // Initialize the DMA mode registers to a default value.
+ // Disable all of the DMA channels except channel 4 which is that
+ // cascade of channels 0-3.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ //
+ // Initialize the extended mode port.
+ //
+
+ for(channelNumber = 0; channelNumber < 4; channelNumber++)
+ {
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma1ExtendedModePort,
+ *((PUCHAR) (Dma1ExtendedMode + channelNumber))
+ );
+ } /* endfor */
+
+ for(channelNumber = 1; channelNumber < 4; channelNumber++)
+ {
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpIoControlBase)->Dma2ExtendedModePort,
+ *((PUCHAR) (Dma2ExtendedMode + channelNumber))
+ );
+ } /* endfor */
+
+ return;
+}
+#endif // POWER_MANAGEMENT
diff --git a/private/ntos/nthals/halppc/ppc/pxsiosup.h b/private/ntos/nthals/halppc/ppc/pxsiosup.h
new file mode 100644
index 000000000..2b91be331
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxsiosup.h
@@ -0,0 +1,219 @@
+
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ pxsiosup.h
+
+Abstract:
+
+ The module defines the structures, and defines for the SIO chip set.
+ The SIO_CONTROL structure is a superset of the EISA_CONTROL stucture.
+ Differences from the Eisa control stucture are marked with comments.
+
+Author:
+
+ Jim Wooldridge
+
+Revision History:
+
+
+--*/
+
+#ifndef _SIO_
+#define _SIO_
+
+
+
+
+
+BOOLEAN
+HalpInitSMCSuperIo (
+ VOID
+ );
+
+BOOLEAN
+HalpInitNationalSuperIo (
+ VOID
+ );
+
+typedef struct _SIO_CONTROL {
+ DMA1_CONTROL Dma1BasePort; // Offset 0x000
+ UCHAR Reserved0[16];
+ UCHAR Interrupt1ControlPort0; // Offset 0x020
+ UCHAR Interrupt1ControlPort1; // Offset 0x021
+ UCHAR Reserved1[32 - 2];
+ UCHAR Timer1; // Offset 0x40
+ UCHAR RefreshRequest; // Offset 0x41
+ UCHAR SpeakerTone; // Offset 0x42
+ UCHAR CommandMode1; // Offset 0x43
+ UCHAR Reserved14[28];
+ UCHAR ResetUbus; // Offset 0x60
+ UCHAR NmiStatus; // Offset 0x61
+ UCHAR Reserved15[14];
+ UCHAR NmiEnable; // Offset 0x70
+ UCHAR Reserved16[7];
+ UCHAR BiosTimer[4]; // Offset 0x78
+ UCHAR Reserved13[4];
+ DMA_PAGE DmaPageLowPort; // Offset 0x080
+ UCHAR Reserved2;
+ UCHAR AlternateReset; // Offset 0x092
+ UCHAR Reserved17[14];
+ UCHAR Interrupt2ControlPort0; // Offset 0x0a0
+ UCHAR Interrupt2ControlPort1; // Offset 0x0a1
+ UCHAR Reserved3[32-2];
+ DMA2_CONTROL Dma2BasePort; // Offset 0x0c0
+ UCHAR CoprocessorError; // Offset 0x0f0
+ UCHAR Reserved4[0x281];
+ UCHAR SecondaryFloppyOutput; // Offset 0x372
+ UCHAR Reserved18[0x27];
+ UCHAR Reserved21[0x59];
+ UCHAR PrimaryFloppyOutput; // Offset 0x3f2
+ UCHAR Reserved5[19];
+ UCHAR Dma1ExtendedModePort; // Offset 0x40b
+ UCHAR Reserved6[4];
+ UCHAR Channel0ScatterGatherCommand; // Offset 0x410
+ UCHAR Channel1ScatterGatherCommand; // Offset 0x411
+ UCHAR Channel2ScatterGatherCommand; // Offset 0x412
+ UCHAR Channel3ScatterGatherCommand; // Offset 0x413
+ UCHAR Reserved19; // Offset 0x414
+ UCHAR Channel5ScatterGatherCommand; // Offset 0x415
+ UCHAR Channel6ScatterGatherCommand; // Offset 0x416
+ UCHAR Channel7ScatterGatherCommand; // Offset 0x417
+ UCHAR Channel0ScatterGatherStatus; // Offset 0x418
+ UCHAR Channel1ScatterGatherStatus; // Offset 0x419
+ UCHAR Channel2ScatterGatherStatus; // Offset 0x41a
+ UCHAR Channel3ScatterGatherStatus; // Offset 0x41b
+ UCHAR Reserved20; // Offset 0x41c
+ UCHAR Channel5ScatterGatherStatus; // Offset 0x41d
+ UCHAR Channel6ScatterGatherStatus; // Offset 0x41e
+ UCHAR Channel7ScatterGatherStatus; // Offset 0x41f
+ UCHAR Channel0ScatterGatherTable[4]; // Offset 0x420
+ UCHAR Channel1ScatterGatherTable[4]; // Offset 0x424
+ UCHAR Channel2ScatterGatherTable[4]; // Offset 0x428
+ UCHAR Channel3ScatterGatherTable[4]; // Offset 0x42c
+ UCHAR Reserved22[4]; // Offset 0x430
+ UCHAR Channel5ScatterGatherTable[4]; // Offset 0x434
+ UCHAR Channel6ScatterGatherTable[4]; // Offset 0x438
+ UCHAR Channel7ScatterGatherTable[4]; // Offset 0x43c
+ UCHAR Reserved8[0x40];
+ DMA_PAGE DmaPageHighPort; // Offset 0x480
+ UCHAR Reserved10[70];
+ UCHAR Dma2ExtendedModePort; // Offset 0x4d6
+} SIO_CONTROL, *PSIO_CONTROL;
+
+
+
+typedef struct _SIO_CONFIG {
+ UCHAR VendorId[2]; // Offset 0x00 read-only
+ UCHAR DeviceId[2]; // Offset 0x02 read-only
+ UCHAR Command[2]; // Offset 0x04 unused
+ UCHAR DeviceStatus[2]; // Offset 0x06
+ UCHAR RevisionId; // Offset 0x08 read-only
+ UCHAR Reserved1[0x37]; // Offset 0x09
+ UCHAR PciControl; // Offset 0x40
+ UCHAR PciArbiterControl; // Offset 0x41
+ UCHAR PciArbiterPriorityControl; // Offset 0x42
+ UCHAR Reserved2; // Offset 0x43
+ UCHAR MemCsControl; // Offset 0x44
+ UCHAR MemCsBottomOfHole; // Offset 0x45
+ UCHAR MemCsTopOfHole; // Offset 0x46
+ UCHAR MemCsTopOfMemory; // Offset 0x47
+ UCHAR IsaAddressDecoderControl; // Offset 0x48
+ UCHAR IsaAddressDecoderRomEnable; // Offset 0x49
+ UCHAR IsaAddressDecoderBottomOfHole; // Offset 0x4a
+ UCHAR IsaAddressDecoderTopOfHole; // Offset 0x4b
+ UCHAR IsaControllerRecoveryTimer; // Offset 0x4c
+ UCHAR IsaClockDivisor; // Offset 0x4d
+ UCHAR UtilityBusEnableA; // Offset 0x4e
+ UCHAR UtilityBusEnableB; // Offset 0x4f
+ UCHAR Reserved3[4]; // Offset 0x50
+ UCHAR MemCsAttribute1; // Offset 0x54
+ UCHAR MemCsAttribute2; // Offset 0x55
+ UCHAR MemCsAttribute3; // Offset 0x56
+ UCHAR ScatterGatherBaseAddress; // Offset 0x57
+ UCHAR Reserved4[0x28]; // Offset 0x58
+ UCHAR BiosTimerBaseAddress[2]; // Offset 0x80
+}SIO_CONFIG, *PSIO_CONFIG;
+
+
+//
+// Define constants used by SIO config
+//
+
+
+// PCI control register - bit values
+#define ENABLE_PCI_POSTED_WRITE_BUFFER 0x04
+#define ENABLE_ISA_MASTER_LINE_BUFFER 0x02
+#define EANBLE_DMA_LINE_BUFFER 0x01
+
+// PCI Arbiter contol register - bit values
+#define ENABLE_GAT 0x01
+
+
+// ISA CLock Divisor register - bit values
+#define ENABLE_COPROCESSOR_ERROR 0x20
+#define ENABLE_MOUSE_SUPPORT 0x10
+#define RSTDRV 0x08
+#define SYSCLK_DIVISOR 0x00
+
+//Utility Bus Chip Select A - bit values
+#define ENABLE_RTC 0x01
+#define ENABLE_KEYBOARD 0x02
+#define ENABLE_IDE_DECODE 0x10
+
+//Utility Bus Chip Select B - bit values
+#define ENABLE_RAM_DECODE 0x80
+#define ENABLE_PORT92 0x40
+#define DISABLE_PARALLEL_PORT 0x30
+#define DISABLE_SERIAL_PORTB 0x0c
+#define DISABLE_SERIAL_PORTA 0x03
+
+// Interrupt controller - bit values
+#define LEVEL_TRIGGERED 0x08
+#define SINGLE_MODE 0x02
+
+// NMI status/control - bit values
+#define DISABLE_IOCHK_NMI 0x08
+#define DISABLE_PCI_SERR_NMI 0x04
+
+// NMI enable - bit values
+#define DISABLE_NMI 0x80
+
+// DMA command - bit values
+#define DACK_ASSERT_HIGH 0x80
+#define DREQ_ASSERT_LOW 0x40
+#endif
+
+//
+// Define 8259 constants
+//
+
+#define SPURIOUS_VECTOR 7
+
+//
+// Define 8254 timer constants
+//
+
+//
+// Convert the interval to rollover count for 8254 Timer1 device.
+// Since timer1 counts down a 16 bit value at a rate of 1.193M counts-per-
+// sec, the computation is:
+// RolloverCount = (Interval * 0.0000001) * (1.193 * 1000000)
+// = Interval * 0.1193
+// = Interval * 1193 / 10000
+//
+//
+// The default Interrupt interval is Interval = 15ms.
+
+
+#define TIME_INCREMENT 150000 // 15ms.
+#define ROLLOVER_COUNT 15 * 1193
+
+#define COMMAND_8254_COUNTER0 0x00 // Select count 0
+#define COMMAND_8254_RW_16BIT 0x30 // Read/Write LSB firt then MSB
+#define COMMAND_8254_MODE2 0x4 // Use mode 2
+#define COMMAND_8254_BCD 0x0 // Binary count down
+#define COMMAND_8254_LATCH_READ 0x0 // Latch read command
diff --git a/private/ntos/nthals/halppc/ppc/pxstall.s b/private/ntos/nthals/halppc/ppc/pxstall.s
new file mode 100644
index 000000000..501e2016e
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxstall.s
@@ -0,0 +1,324 @@
+//#***********************************************************************
+//
+// Copyright 1994 MOTOROLA, INC. All Rights Reserved. This file
+// contains copyrighted material. Use of this file is restricted
+// by the provisions of a Motorola Software License Agreement.
+//
+// Copyright 1993 International Buisness Machines Corporation.
+// All Rights Reserved.
+//
+// This file contains copyrighted material. Use of this file is
+// restricted by the provisions of a Motorola/IBM Joint Software
+// License Agreement.
+//
+// File Name:
+// PXSTALL.S
+//
+// Functions:
+// KeStallExecutionProcessor
+// HalpCalibrateStall
+//
+// History:
+// 21-Sep-1993 Steve Johns
+// Original Version
+// 24-Dec-1993 Peter Johnston
+// Adapted to 601 HAL in an attempt to avoid having different
+// versions if at all possible. Original was designed for both
+// 601 and 603 but had some 601 difficulties.
+// 17-Jan-1994 Steve Johns
+// Changed to treat 601 vs PowerPC time base differences more
+// transparently.
+//
+//#***********************************************************************
+
+
+
+#include "kxppc.h"
+
+#define ERRATA603 TRUE
+#define RTCU 4
+#define RTCL 5
+#define CMOS_INDEX 0x70
+#define CMOS_DATA 0x71
+#define RTC_SECOND 0x80
+
+
+ .extern HalpPerformanceFrequency
+ .extern HalpIoControlBase
+
+
+//
+// Register Definitions
+//
+ .set Microsecs, r.3
+ .set TimerLo , r.4 // MUST be same as defined in PXCLKSUP.S
+ .set TimerHi , r.5 // MUST be same as defined in PXCLKSUP.S
+ .set EndTimerLo, r.6
+ .set EndTimerHi, r.7
+ .set Temp , r.8
+ .set Temp2 , r.9
+ .set IO_Base , r.10
+
+//#***********************************************************************
+//
+// Synopsis:
+// VOID KeStallExecutionProcessor(
+// ULONG Microseconds)
+//
+// Purpose:
+// This function stalls the execution at least the specified number
+// of microseconds, but not substantially longer.
+//
+// Returns:
+// Nothing.
+//
+// Global Variables Referenced:
+// HalpPerformanceFrequency
+//#***********************************************************************
+
+ SPECIAL_ENTRY(KeStallExecutionProcessor)
+ mflr r.0 // Save Link Register
+ PROLOGUE_END(KeStallExecutionProcessor)
+
+ cmpli 0,0,Microsecs,0 // if (Microseconds == 0)
+ beqlr- // return;
+
+ bl ..HalpGetTimerRoutine // Get appropriate timer routine
+//
+// Read START time
+//
+ bctrl // ReadPerformanceCounter();
+
+//
+// Get PerformanceCounter frequency
+//
+ lwz Temp,[toc]HalpPerformanceFrequency(r.toc)
+ lwz Temp,0(Temp)
+//
+// Compute: (Microseconds * PerformanceFrequency) / 1,000,000
+//
+ mullw EndTimerLo,Microsecs,Temp
+ mulhwu. EndTimerHi,Microsecs,Temp
+ bne Shift20Bits
+
+ lis Temp,(1000000 >> 16) // Divide by 1,000,000
+ ori Temp,Temp,(1000000 & 0xFFFF)
+ divwu EndTimerLo,EndTimerLo,Temp
+ b Add64Bits
+
+//
+// The 32 MSBs are non-zero.
+// Instead of performing a 64-bit division, we shift right by 20
+// bits (equivalent to dividing by 1,048576). Then we add back in 1/16th
+// of the shifted amount. The accuracy achieved by this method is:
+//
+// 1,000,000
+// --------- * 1.0625 = 101.3 % of desired value.
+// 1,048,576
+//
+Shift20Bits:
+ mr Temp,EndTimerHi
+ rlwinm EndTimerLo,EndTimerLo,32-20,20,31
+ rlwinm EndTimerHi,EndTimerHi,32-20,20,31
+ rlwimi EndTimerLo,Temp,32-20,0,19
+
+ rlwinm Temp2,EndTimerLo,32-4,4,31
+ rlwinm Temp,EndTimerHi,32-4,4,31
+ rlwimi Temp2,EndTimerHi,32-4,0,3
+ addc EndTimerLo,EndTimerLo,Temp2
+ adde EndTimerHi,EndTimerHi,Temp
+
+//
+// Compute EndTimer
+//
+Add64Bits:
+ addc EndTimerLo,EndTimerLo,TimerLo
+ adde EndTimerHi,EndTimerHi,TimerHi
+//
+// while (ReadPerformanceCounter() < EndTimer);
+//
+StallLoop:
+ bctrl // ReadPerformanceCounter();
+ cmpl 0,0,TimerHi,EndTimerHi // Is TimerHi >= EndTimerHi ?
+ blt- StallLoop // No
+ bgt+ StallExit // Yes
+ cmpl 0,0,TimerLo,EndTimerLo // Is TimerLo >= EndTimerLo ?
+ blt StallLoop // Branch if not
+
+StallExit:
+ mtlr r.0 // Restore Link Register
+
+ SPECIAL_EXIT(KeStallExecutionProcessor)
+
+
+
+
+
+//
+// This routine is the ReadPerformanceCounter routine for the 601 processor.
+// The 601 RTC counts discontinuously (1 is added to RTCU when the value in
+// RTCL passes 999,999,999). This routine converts the RTC count to a
+// continuous 64-bit count by calculating:
+//
+// ((RTC.HighPart * 1,000,000,000) + RTC.LowPart) / 128
+//
+//
+ LEAF_ENTRY (ReadRTC)
+
+ mfspr TimerHi,RTCU // Read the RTC registers coherently
+ mfspr TimerLo,RTCL
+ mfspr Temp,RTCU
+ cmpl 0,0,TimerHi,Temp
+ bne- ..ReadRTC
+
+ lis Temp,(1000000000 >> 16) // RTC.HighPart * 1,000,000
+ ori Temp,Temp,(1000000000 & 0xFFFF)
+ mullw Temp2,Temp,TimerHi
+ mulhwu Temp,Temp,TimerHi
+ addc TimerLo,Temp2,TimerLo // + RTC.LowPart
+ addze TimerHi,Temp
+//
+// Each tick increments the RTC by 128, so let's divide that out.
+//
+ mr Temp,TimerHi // Divide 64-bit value by 128
+ rlwinm TimerLo,TimerLo,32-7,7,31
+ rlwinm TimerHi,TimerHi,32-7,7,31
+ rlwimi TimerLo,Temp,32-7,0,6
+
+ LEAF_EXIT (ReadRTC)
+
+
+
+
+
+//
+// This routine is the ReadPerformanceCounter routine for PowerPC
+// architectures (not the 601).
+//
+ LEAF_ENTRY (ReadTB)
+
+ mftbu TimerHi // Read the TB registers coherently
+ mftb TimerLo
+#if ERRATA603
+ mftb TimerLo
+ mftb TimerLo
+ mftb TimerLo
+#endif
+ mftbu Temp
+ cmpl 0,0,Temp,TimerHi
+ bne- ..ReadTB
+
+ LEAF_EXIT (ReadTB)
+
+
+//
+// Returns in the Count Register the entry point for the routine
+// that reads the appropriate Performance Counter (ReadRTC or ReadTB).
+//
+// Called from KeQueryPerformanceCounter and KeStallExecutionProcessor
+//
+ LEAF_ENTRY (HalpGetTimerRoutine)
+
+ mfpvr Temp // Read Processor Version Register
+ rlwinm Temp,Temp,16,16,31
+ cmpli 0,0,Temp,1 // Are we running on an MPC601 ?
+ lwz Temp,[toc]ReadTB(r.toc)
+ bne+ GetEntryPoint // Branch if not
+
+ lwz Temp,[toc]ReadRTC(r.toc)
+
+GetEntryPoint:
+ lwz Temp,0(Temp) // Get addr to ReadRTC or ReadTB
+ mtctr Temp
+
+ LEAF_EXIT (HalpGetTimerRoutine)
+
+
+
+
+
+//
+// Returns the number of performance counter ticks/second.
+//
+// The DECREMENTER is clocked at the same rate as the PowerPC Time Base (TB)
+// and the POWER RTC. The POWER RTC is supposed to be clocked at 7.8125 MHz,
+// but on early prototypes of the Sandalfoot platform, this is not true).
+// In either case, to keep the calibration routine simple and generic, we
+// will determine the DECREMENTER clock rate by counting ticks for exactly
+// 1 second (as measured against the CMOS RealTimeClock). We then use that
+// value in the KeStallExecutionProcessor() and KeQueryPerformanceCounter()
+//
+ LEAF_ENTRY(HalpCalibrateTB)
+
+ // Get base address of ISA I/O space so we can talk to the CMOS RTC
+ lwz IO_Base,[toc]HalpIoControlBase(r.toc)
+ lwz IO_Base,0(IO_Base)
+
+WaitOnUIP1:
+ li r.6,0x0A // check and wait on busy flag
+ stb r.6,CMOS_INDEX(IO_Base)
+ sync
+ lbz r.7,CMOS_DATA(IO_Base) // Read CMOS data
+ andi. r.7, r.7, 0x0080
+ bgt WaitOnUIP1
+
+
+ li r.3,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,CMOS_INDEX(IO_Base) // Write CMOS index
+ sync
+ lbz r.4,CMOS_DATA(IO_Base) // Read CMOS data
+
+
+
+WaitForTick1:
+ li r.6,0x0A // check and wait on busy flag
+ stb r.6,CMOS_INDEX(IO_Base)
+ sync
+ lbz r.7,CMOS_DATA(IO_Base) // Read CMOS data
+ andi. r.7, r.7, 0x0080
+ bgt WaitForTick1
+ li r.3,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.3,CMOS_INDEX(IO_Base) // Write CMOS index
+ sync
+ lbz r.3,CMOS_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4 // Loop until it changes
+ beq+ WaitForTick1
+
+
+ li r.4,-1 // Start the decrementer at max. count
+ mtdec r.4
+#if ERRATA603
+ isync
+#endif
+
+WaitForTick2:
+ li r.6,0x0A // check and wait on busy flag
+ stb r.6,CMOS_INDEX(IO_Base)
+ sync
+ lbz r.7,CMOS_DATA(IO_Base) // Read CMOS data
+ andi. r.7, r.7, 0x0080
+ bgt WaitForTick2
+ li r.4,RTC_SECOND // Read seconds from CMOS RTC
+ stb r.4,CMOS_INDEX(IO_Base) // Write CMOS index
+ sync
+ lbz r.4,CMOS_DATA(IO_Base) // Read CMOS data
+ cmpl 0,0,r.3,r.4
+ beq+ WaitForTick2
+
+ mfdec r.3 // Read the decrementer
+ neg r.3,r.3 // Compute delta ticks
+
+ mfpvr Temp // Read Processor Version Register
+ rlwinm Temp,Temp,16,16,31
+ cmpli 0,0,Temp,1 // if (CPU != 601)
+ bnelr // return(r.3);
+//
+// On the 601, the DECREMENTER decrements every ns, so the 7 LSBs are
+// not implemented.
+//
+ rlwinm r.3,r.3,32-7,7,31 // Divide count by 128
+
+
+ LEAF_EXIT(HalpCalibrateTB)
+
+
diff --git a/private/ntos/nthals/halppc/ppc/pxsysbus.c b/private/ntos/nthals/halppc/ppc/pxsysbus.c
new file mode 100644
index 000000000..8787ee2cd
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxsysbus.c
@@ -0,0 +1,111 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ pxsysbus.c
+
+Abstract:
+
+Author:
+
+Environment:
+
+Revision History:
+ Jim Wooldridge - ported to PowerPC
+
+
+--*/
+
+#include "halp.h"
+
+#include "eisa.h"
+#include "pxmemctl.h"
+
+ULONG HalpDefaultInterruptAffinity;
+
+BOOLEAN
+HalpTranslateSystemBusAddress(
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function translates a bus-relative address space and address into
+ a system physical address.
+
+Arguments:
+
+ BusAddress - Supplies the bus-relative address
+
+ AddressSpace - Supplies the address space number.
+ Returns the host address space number.
+
+ AddressSpace == 0 => memory space
+ AddressSpace == 1 => I/O space
+
+ TranslatedAddress - Supplies a pointer to return the translated address
+
+Return Value:
+
+ A return value of TRUE indicates that a system physical address
+ corresponding to the supplied bus relative address and bus address
+ number has been returned in TranslatedAddress.
+
+ A return value of FALSE occurs if the translation for the address was
+ not possible
+
+--*/
+
+{
+ PSUPPORTED_RANGE pRange;
+
+ pRange = NULL;
+ switch (*AddressSpace) {
+ case 0:
+ // verify memory address is within buses memory limits
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
+ *AddressSpace = pRange->SystemAddressSpace;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
diff --git a/private/ntos/nthals/halppc/ppc/pxsysint.c b/private/ntos/nthals/halppc/ppc/pxsysint.c
new file mode 100644
index 000000000..2eede0663
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxsysint.c
@@ -0,0 +1,227 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a Power PC.
+
+
+
+Author:
+
+ David N. Cutler (davec) 6-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge
+
+ Removed internal interrupt support
+ Changed irql mapping
+ Removed internal bus support
+ Removed EISA, added PCI, PCMCIA, and ISA bus support
+
+ Steve Johns
+ Changed to support Timer 1 as profile interrupt
+ Added HalAcknowledgeIpi
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrupt.
+ //
+
+ if (Vector >= DEVICE_VECTORS &&
+ Vector < DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR ) {
+ HalpDisableSioInterrupt(Vector);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+BOOLEAN
+HalEnableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This routine enables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is enabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ TRUE if the system interrupt was enabled
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ KINTERRUPT_MODE TranslatedInterruptMode;
+
+ //
+ // Raise IRQL to the highest level and acquire device enable spinlock.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrupt and set the Level/Edge register.
+ //
+
+ if (Vector >= DEVICE_VECTORS &&
+ Vector < DEVICE_VECTORS + MAXIMUM_DEVICE_VECTOR ) {
+
+ //
+ // get translated interrupt mode
+ //
+
+
+ TranslatedInterruptMode = HalpGetInterruptMode(Vector, Irql, InterruptMode);
+
+
+ HalpEnableSioInterrupt( Vector, TranslatedInterruptMode);
+ // HalpEnableSioInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // Release the device enable spin lock and lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+}
+
+VOID
+HalRequestIpi (
+ IN ULONG Mask
+ )
+
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ Mask - Supplies the set of processors that are sent an interprocessor
+ interrupt.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+
+
+ return;
+}
+
+BOOLEAN
+HalAcknowledgeIpi (VOID)
+
+/*++
+
+Routine Description:
+
+ This routine aknowledges an interprocessor interrupt on a set of
+ processors.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ TRUE if the IPI is valid; otherwise FALSE is returned.
+
+--*/
+
+{
+ return (TRUE);
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxtime.c b/private/ntos/nthals/halppc/ppc/pxtime.c
new file mode 100644
index 000000000..fad088f59
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxtime.c
@@ -0,0 +1,386 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
+contains copyrighted material. Use of this file is restricted
+by the provisions of a Motorola Software License Agreement.
+
+Module Name:
+
+ pxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a PowerPC system.
+
+Author:
+
+ David N. Cutler (davec) 5-May-1991
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Initial Power PC port
+
+ Change real time clock mapping to port 71.
+ Code assumes the DS1385S chip is compatible with existing
+ PC/AT type RTC's. The only known exception to PC/AT
+ compatibility on S-FOOT is the use of ports 810 and 812.
+ These ports provide password security for the RTC's NVRAM,
+ and are currently unused in this port since this address space
+ is available from kernel mode only in NT.
+
+ Steve Johns (sjohns@pets.sps.mot.com)
+ Changed to support years > 1999
+
+--*/
+
+#include "halp.h"
+#include "pxrtcsup.h"
+#include "eisa.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+UCHAR
+HalpReadRawClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteRawClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ );
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ );
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to query the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that receives
+ the realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are read from the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then read
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1900 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ if (TimeFields->Year < 1980) TimeFields->Year += 100;
+
+ TimeFields->Month = (CSHORT)HalpReadClockRegister(RTC_MONTH);
+ TimeFields->Day = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_MONTH);
+ TimeFields->Weekday = (CSHORT)HalpReadClockRegister(RTC_DAY_OF_WEEK) - 1;
+ TimeFields->Hour = (CSHORT)HalpReadClockRegister(RTC_HOUR);
+ TimeFields->Minute = (CSHORT)HalpReadClockRegister(RTC_MINUTE);
+ TimeFields->Second = (CSHORT)HalpReadClockRegister(RTC_SECOND);
+ TimeFields->Milliseconds = 0;
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. This routine is required to provide any synchronization necessary
+ to set the realtime clock information.
+
+Arguments:
+
+ TimeFields - Supplies a pointer to a time structure that specifies the
+ realtime clock information.
+
+Return Value:
+
+ If the power to the realtime clock has not failed, then the time
+ values are written to the realtime clock and a value of TRUE is
+ returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ UCHAR DataByte;
+ KIRQL OldIrql;
+
+ //
+ // If the realtime clock battery is still functioning, then write
+ // the realtime clock values, and return a function value of TRUE.
+ // Otherwise, return a function value of FALSE.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ DataByte = HalpReadRawClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Set the realtime clock control to set the time.
+ //
+
+ DataByte = 0;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->HoursFormat = 1;
+
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteRawClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ if (TimeFields->Year > 1999)
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 2000));
+ else
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1900));
+
+ HalpWriteClockRegister(RTC_MONTH, (UCHAR)TimeFields->Month);
+ HalpWriteClockRegister(RTC_DAY_OF_MONTH, (UCHAR)TimeFields->Day);
+ HalpWriteClockRegister(RTC_DAY_OF_WEEK, (UCHAR)(TimeFields->Weekday + 1));
+ HalpWriteClockRegister(RTC_HOUR, (UCHAR)TimeFields->Hour);
+ HalpWriteClockRegister(RTC_MINUTE, (UCHAR)TimeFields->Minute);
+ HalpWriteClockRegister(RTC_SECOND, (UCHAR)TimeFields->Second);
+
+ //
+ // Set the realtime clock control to update the time.
+ //
+
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 0;
+ HalpWriteRawClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadRawClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the SIO NMI enable register. This selects the realtime clock register
+ // that is read. Note this is a write only register and the EISA NMI
+ // is always enabled.
+ //
+
+ //
+ // TEMPTEMP Disable NMI's for now because this is causing machines in the
+ // build lab to get NMI's during boot.
+ //
+
+
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR(&((PRTC_CONTROL)HalpIoControlBase)->RtcData);
+}
+
+UCHAR
+HalpReadClockRegister (
+ UCHAR Register
+ )
+
+/*++
+
+Routine Description:
+
+ This routine reads the specified realtime clock register.
+ change return value from BCD to binary integer. I think the chip
+ can be configured to do this,... but as a quick fix I am doing it
+ here. (plj)
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is read.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ UCHAR BcdValue;
+
+
+ BcdValue = HalpReadRawClockRegister(Register);
+ return (BcdValue >> 4) * 10 + (BcdValue & 0x0f);
+}
+
+VOID
+HalpWriteRawClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the SIO NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the SIO NMI is always enabled.
+ //
+
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpIoControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR(&((PRTC_CONTROL)HalpIoControlBase)->RtcData, Value);
+ return;
+}
+
+VOID
+HalpWriteClockRegister (
+ UCHAR Register,
+ UCHAR Value
+ )
+
+/*++
+
+Routine Description:
+
+ This routine writes the specified value to the specified realtime
+ clock register.
+
+Arguments:
+
+ Register - Supplies the number of the register whose value is written.
+
+ Value - Supplies the value that is written to the specified register.
+
+Return Value:
+
+ The value of the register is returned as the function value.
+
+--*/
+
+{
+ UCHAR BcdValue;
+
+ BcdValue = ((Value / 10) << 4) | (Value % 10);
+ HalpWriteRawClockRegister(Register, BcdValue);
+ return;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxusage.c b/private/ntos/nthals/halppc/ppc/pxusage.c
new file mode 100644
index 000000000..ce4bae32e
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxusage.c
@@ -0,0 +1,499 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ pxusage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ Jim Wooldridge Ported to PowerPC
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Array to remember hal's IDT usage
+//
+
+extern ADDRESS_USAGE *HalpAddressUsageList;
+extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+
+KAFFINITY HalpActiveProcessors;
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpEnableInterruptHandler)
+#pragma alloc_text(INIT,HalpRegisterVector)
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+
+
+BOOLEAN
+HalpEnableInterruptHandler (
+ IN PKINTERRUPT Interrupt,
+ IN PKSERVICE_ROUTINE ServiceRoutine,
+ IN PVOID ServiceContext,
+ IN PKSPIN_LOCK SpinLock OPTIONAL,
+ IN ULONG Vector,
+ IN KIRQL Irql,
+ IN KIRQL SynchronizeIrql,
+ IN KINTERRUPT_MODE InterruptMode,
+ IN BOOLEAN ShareVector,
+ IN CCHAR ProcessorNumber,
+ IN BOOLEAN FloatingSave,
+ IN UCHAR ReportFlags,
+ IN KIRQL BusVector
+ )
+/*++
+
+Routine Description:
+
+ This function connects & registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+
+ KeInitializeInterrupt( Interrupt,
+ ServiceRoutine,
+ ServiceContext,
+ SpinLock,
+ Vector,
+ Irql,
+ SynchronizeIrql,
+ InterruptMode,
+ ShareVector,
+ ProcessorNumber,
+ FloatingSave
+ );
+
+ //
+ // Don't fail if the interrupt cannot be connected.
+ //
+
+ if (!KeConnectInterrupt( Interrupt )) {
+
+ return(FALSE);
+ }
+
+ HalpRegisterVector (ReportFlags, BusVector, Vector, Irql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+ return(TRUE);
+
+
+}
+
+
+
+VOID
+HalpRegisterVector (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql
+ )
+/*++
+
+Routine Description:
+
+ This registers an IDT vectors usage by the HAL.
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+#if DBG
+ // There are only 0ff IDT entries...
+ ASSERT (SystemInterruptVector <= MAXIMUM_IDTVECTOR &&
+ BusInterruptVector <= MAXIMUM_IDTVECTOR);
+#endif
+
+ //
+ // Remember which vector the hal is connecting so it can be reported
+ // later on
+ //
+
+ HalpIDTUsage[SystemInterruptVector].Flags = ReportFlags;
+ HalpIDTUsage[SystemInterruptVector].Irql = SystemIrql;
+ HalpIDTUsage[SystemInterruptVector].BusReleativeVector = (UCHAR) BusInterruptVector;
+}
+
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ )
+/*++
+
+Routine Description:
+
+ Used by HalpReportResourceUsage in order to properly sort
+ partial_resource_descriptors.
+
+Arguments:
+
+ pRCurLoc - resource descriptor
+
+Return Value:
+
+ sortscale - scaling of resource descriptor for sorting
+ sortvalue - value to sort on
+
+
+--*/
+{
+ switch (pRCurLoc->Type) {
+ case CmResourceTypeInterrupt:
+ *sortscale = 0;
+ *sortvalue = RtlConvertUlongToLargeInteger(
+ pRCurLoc->u.Interrupt.Level );
+ break;
+
+ case CmResourceTypePort:
+ *sortscale = 1;
+ *sortvalue = pRCurLoc->u.Port.Start;
+ break;
+
+ case CmResourceTypeMemory:
+ *sortscale = 2;
+ *sortvalue = pRCurLoc->u.Memory.Start;
+ break;
+
+ default:
+ *sortscale = 4;
+ *sortvalue = RtlConvertUlongToLargeInteger (0);
+ break;
+ }
+}
+
+
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ PCM_RESOURCE_LIST RawResourceList, TranslatedResourceList;
+ PCM_FULL_RESOURCE_DESCRIPTOR pRFullDesc, pTFullDesc;
+ PCM_PARTIAL_RESOURCE_LIST pRPartList, pTPartList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc, pTCurLoc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR pRSortLoc, pTSortLoc;
+ CM_PARTIAL_RESOURCE_DESCRIPTOR RPartialDesc, TPartialDesc;
+ ULONG i, j, k, ListSize, Count;
+ ULONG curscale, sortscale;
+ UCHAR pass, reporton;
+ INTERFACE_TYPE interfacetype;
+ ULONG CurrentIDT, CurrentElement;
+ ADDRESS_USAGE *CurrentAddress;
+ LARGE_INTEGER curvalue, sortvalue;
+
+
+ //
+ // Allocate some space to build the resource structure
+ //
+
+ RawResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+ TranslatedResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (NonPagedPool, PAGE_SIZE*2);
+
+ // This functions assumes unset fields are zero
+ RtlZeroMemory (RawResourceList, PAGE_SIZE*2);
+ RtlZeroMemory (TranslatedResourceList, PAGE_SIZE*2);
+
+ //
+ // Initialize the lists
+ //
+
+ RawResourceList->List[0].InterfaceType = (INTERFACE_TYPE) -1;
+
+ pRFullDesc = RawResourceList->List;
+ pRCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) RawResourceList->List;
+ pTCurLoc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) TranslatedResourceList->List;
+
+
+ for(i=0; i < DEVICE_VECTORS; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+
+ for(pass=0; pass < 2; pass++) {
+ if (pass == 0) {
+ //
+ // First pass - build resource lists for resources reported
+ // reported against device usage.
+ //
+
+ reporton = DeviceUsage & ~IDTOwned;
+ interfacetype = DeviceInterfaceToUse;
+ } else {
+
+ //
+ // Second pass = build reousce lists for resources reported
+ // as internal usage.
+ //
+
+ reporton = InternalUsage & ~IDTOwned;
+ interfacetype = Internal;
+ }
+
+ CurrentIDT = 0;
+ CurrentElement = 0;
+ CurrentAddress = HalpAddressUsageList;
+
+ for (; ;) {
+ if (CurrentIDT <= MAXIMUM_IDTVECTOR) {
+ //
+ // Check to see if CurrentIDT needs to be reported
+ //
+
+ if (!(HalpIDTUsage[CurrentIDT].Flags & reporton)) {
+ // Don't report on this one
+ CurrentIDT++;
+ continue;
+ }
+
+ //
+ // Report CurrentIDT resource
+ //
+
+ RPartialDesc.Type = CmResourceTypeInterrupt;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+ RPartialDesc.Flags =
+ HalpIDTUsage[CurrentIDT].Flags & InterruptLatched ?
+ CM_RESOURCE_INTERRUPT_LATCHED :
+ CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ RPartialDesc.u.Interrupt.Vector = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].BusReleativeVector;
+ RPartialDesc.u.Interrupt.Affinity = HalpActiveProcessors;
+
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ TPartialDesc.u.Interrupt.Vector = CurrentIDT;
+ TPartialDesc.u.Interrupt.Level = HalpIDTUsage[CurrentIDT].Irql;
+
+ CurrentIDT++;
+
+ } else {
+ //
+ // Check to see if CurrentAddress needs to be reported
+ //
+
+ if (!CurrentAddress) {
+ break; // No addresses left
+ }
+
+ if (!(CurrentAddress->Flags & reporton)) {
+ // Don't report on this list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ if (!CurrentAddress->Element[CurrentElement].Length) {
+ // End of current list, go to next list
+ CurrentElement = 0;
+ CurrentAddress = CurrentAddress->Next;
+ continue;
+ }
+
+ //
+ // Report CurrentAddress
+ //
+
+ RPartialDesc.Type = (UCHAR) CurrentAddress->Type;
+ RPartialDesc.ShareDisposition = CmResourceShareDriverExclusive;
+
+ if (RPartialDesc.Type == CmResourceTypePort) {
+ i = 1; // address space port
+ RPartialDesc.Flags = CM_RESOURCE_PORT_IO;
+ } else {
+ i = 0; // address space memory
+ RPartialDesc.Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ }
+
+ // Notice: assuming u.Memory and u.Port have the same layout
+ RPartialDesc.u.Memory.Start.HighPart = 0;
+ RPartialDesc.u.Memory.Start.LowPart =
+ CurrentAddress->Element[CurrentElement].Start;
+
+ RPartialDesc.u.Memory.Length =
+ CurrentAddress->Element[CurrentElement].Length;
+
+ // translated address = Raw address
+ RtlCopyMemory (&TPartialDesc, &RPartialDesc, sizeof TPartialDesc);
+ HalTranslateBusAddress (
+ interfacetype, // device bus or internal
+ 0, // bus number
+ RPartialDesc.u.Memory.Start, // source address
+ &i, // address space
+ &TPartialDesc.u.Memory.Start ); // translated address
+
+ if (RPartialDesc.Type == CmResourceTypePort && i == 0) {
+ TPartialDesc.Flags = CM_RESOURCE_PORT_MEMORY;
+ }
+
+ CurrentElement++;
+ }
+
+ //
+ // Include the current resource in the HALs list
+ //
+
+ if (pRFullDesc->InterfaceType != interfacetype) {
+ //
+ // Interface type changed, add another full section
+ //
+
+ RawResourceList->Count++;
+ TranslatedResourceList->Count++;
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+
+ pRFullDesc->InterfaceType = interfacetype;
+ pTFullDesc->InterfaceType = interfacetype;
+
+ pRPartList = &pRFullDesc->PartialResourceList;
+ pTPartList = &pTFullDesc->PartialResourceList;
+
+ //
+ // Bump current location pointers up
+ //
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ }
+
+
+ pRPartList->Count++;
+ pTPartList->Count++;
+ RtlCopyMemory (pRCurLoc, &RPartialDesc, sizeof RPartialDesc);
+ RtlCopyMemory (pTCurLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+ }
+
+ ListSize = (ULONG) ( ((PUCHAR) pRCurLoc) - ((PUCHAR) RawResourceList) );
+
+ //
+ // The HAL's resource usage structures have been built
+ // Sort the partial lists based on the Raw resource values
+ //
+
+ pRFullDesc = RawResourceList->List;
+ pTFullDesc = TranslatedResourceList->List;
+
+ for (i=0; i < RawResourceList->Count; i++) {
+
+ pRCurLoc = pRFullDesc->PartialResourceList.PartialDescriptors;
+ pTCurLoc = pTFullDesc->PartialResourceList.PartialDescriptors;
+ Count = pRFullDesc->PartialResourceList.Count;
+
+ for (j=0; j < Count; j++) {
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+
+ pRSortLoc = pRCurLoc;
+ pTSortLoc = pTCurLoc;
+
+ for (k=j; k < Count; k++) {
+ HalpGetResourceSortValue (pRSortLoc, &sortscale, &sortvalue);
+
+ if (sortscale < curscale ||
+ (sortscale == curscale &&
+ RtlLargeIntegerLessThan (sortvalue, curvalue)) ) {
+
+ //
+ // Swap the elements..
+ //
+
+ RtlCopyMemory (&RPartialDesc, pRCurLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRCurLoc, pRSortLoc, sizeof RPartialDesc);
+ RtlCopyMemory (pRSortLoc, &RPartialDesc, sizeof RPartialDesc);
+
+ // swap translated descriptor as well
+ RtlCopyMemory (&TPartialDesc, pTCurLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTCurLoc, pTSortLoc, sizeof TPartialDesc);
+ RtlCopyMemory (pTSortLoc, &TPartialDesc, sizeof TPartialDesc);
+
+ // get new curscale & curvalue
+ HalpGetResourceSortValue (pRCurLoc, &curscale, &curvalue);
+ }
+
+ pRSortLoc++;
+ pTSortLoc++;
+ }
+
+ pRCurLoc++;
+ pTCurLoc++;
+ }
+
+ pRFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pRCurLoc;
+ pTFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR) pTCurLoc;
+ }
+
+
+ //
+ // Inform the IO system of our resources..
+ //
+
+ IoReportHalResourceUsage (
+ HalName,
+ RawResourceList,
+ TranslatedResourceList,
+ ListSize
+ );
+
+ ExFreePool (RawResourceList);
+ ExFreePool (TranslatedResourceList);
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxvgaequ.h b/private/ntos/nthals/halppc/ppc/pxvgaequ.h
new file mode 100644
index 000000000..b8dfc9f14
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxvgaequ.h
@@ -0,0 +1,141 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+
+Module Name:
+
+pxdisp.c
+
+Abstract:
+
+ This file contains all the VGA-specific definitions. This
+ is meant to be included by all modules that implement
+ VGA support in the HAL. At this time, that includes pxs3.c
+ and pxwd.c. It does not include pxp91.c or pxbbl.c because
+ these video devices don't map VGA registers.
+
+Author:
+
+ Jake Oshins
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+
+
+
+//VGA definitions
+
+extern UCHAR DAC_Table[];
+extern UCHAR DAC_Color[];
+extern UCHAR VideoParam[];
+extern UCHAR VGAFont8x16[];
+extern UCHAR TextPalette[];
+
+#define TAB_SIZE 4
+
+
+#define VERTICALRESOLUTION 768
+#define HORIZONTALRESOLUTION 1024
+#define OriginalPoint 0
+#define BLUE 192
+#define WHITE 255
+#define CRT_OFFSET 2
+#define SEQ_OFFSET 27
+#define GRAPH_OFFSET 32
+#define ATTR_OFFSET 41
+
+
+//
+// Define CRTC, VGA S3, SYS_CTRL Index : ( Out 3D4, Index )
+//
+// Define CRTC Controller Indexes
+//
+
+#define HORIZONTAL_TOTAL 0
+#define HORIZONTAL_DISPLAY_END 1
+#define START_HORIZONTAL_BLANK 2
+#define END_HORIZONTAL_BLANK 3
+#define HORIZONTAL_SYNC_POS 4
+#define END_HORIZONTAL_SYNC 5
+#define VERTICAL_TOTAL 6
+#define CRTC_OVERFLOW 7
+#define PRESET_ROW_SCAN 8
+#define MAX_SCAN_LINE 9
+#define CURSOR_START 10
+#define CURSOR_END 11
+#define START_ADDRESS_HIGH 12
+#define START_ADDRESS_LOW 13
+#define CURSOR_LOCATION_HIGH 14
+#define CURSOR_FCOLOR 14
+#define CURSOR_BCOLOR 15
+#define CURSOR_LOCATION_LOW 15
+#define VERTICAL_RETRACE_START 16
+#define VERTICAL_RETRACE_END 17
+#define VERTICAL_DISPLAY_END 18
+#define OFFSET_SCREEN_WIDTH 19
+#define UNDERLINE_LOCATION 20
+#define START_VERTICAL_BLANK 21
+#define END_VERTICAL_BLANK 22
+#define CRT_MODE_CONTROL 23
+#define LINE_COMPARE 24
+#define CPU_LATCH_DATA 34
+#define ATTRIBUTE_INDEX1 36
+#define ATTRIBUTE_INDEX2 38
+
+//
+// Define VGA I/O address
+//
+#define PORT_GEN_MISC_RD 0x03cc // GEN - MISC (Read port)
+#define PORT_GEN_MISC_WR 0x03c2 // (Write port)
+#define PORT_GEN_ISR0 0x03c2 // GEN - ISR0
+#define PORT_GEN_ISR1_M 0x03ba // GEN - ISR1 (for Mono)
+#define PORT_GEN_ISR1_C 0x03da // (for Color)
+#define PORT_GEN_FEATURE_RD 0x03ca // GEN - FEARTURE (Read port for both)
+#define PORT_GEN_FEATURE_WR_M 0x03ba // (Write port for Mono)
+#define PORT_GEN_FEATURE_WR_C 0x03da // (Write port for Color)
+
+#define PORT_SEQ_INDEX 0x03c4 // SEQ - INDEX
+#define PORT_SEQ_DATA 0x03c5 // SEQ - DATA
+
+#define PORT_CRTC_INDEX_M 0x03b4 // CRTC - INDEX (for Mono)
+#define PORT_CRTC_INDEX_C 0x03d4 // (for Color)
+#define PORT_CRTC_DATA_M 0x03b5 // CRTC - DATA (for Mono)
+#define PORT_CRTC_DATA_C 0x03d5 // (for Color)
+
+#define PORT_GCR_INDEX 0x03ce // GCR - INDEX
+#define PORT_GCR_DATA 0x03cf // GCR - DATA
+
+#define PORT_ATTR_INDEX 0x03c0 // ATTR - INDEX
+#define PORT_ATTR_DATA_RD 0x03c1 // ATTR - DATA (Read port)
+#define PORT_ATTR_DATA_WR 0x03c0 // (Write port)
+
+#define PORT_DAC_PIX_MASK 0x03c6 //
+#define PORT_DAC_STATE 0x03c7 //
+#define PORT_DAC_READ_PIX_ADDR 0x03c7 // (Write only port) - take care !
+#define PORT_DAC_WRITE_PIX_ADDR 0x03c8 // (Read/Write port)
+#define PORT_DAC_DATA 0x03c9 // DAC - DATA port
+
+#define PORT_SYS_VGA_ENABLE 0x03c3 // SYS - VGA Enable/Disable
+#define PORT_SYS_VIDEO_SUBSYSTEM 0x46e8 // SYS - Video Subsystem Enable/Disable
+
+//
+// Define Sequencer Indexes ( out 3C4, Index)
+//
+
+#define RESET 0
+#define CLOCKING_MODE 1
+#define ENABLE_WRITE_PLANE 2
+#define CHARACTER_FONT_SELECT 3
+#define MEMORY_MODE_CONTROL 4
+
+//
+// Misc. registers
+//
+#define Setup_OP 0x102 // R/W
+
diff --git a/private/ntos/nthals/halppc/ppc/pxvm.c b/private/ntos/nthals/halppc/ppc/pxvm.c
new file mode 100644
index 000000000..b93dace23
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxvm.c
@@ -0,0 +1,297 @@
+/*++
+TITLE("Map Virtual Memory")
+
+
+Copyright (c) 1995 IBM Corporation, Microsoft Corporation.
+
+Module Name:
+
+ pxmapvm.c
+
+abstract:
+
+ This module implements a mechanism to allow the HAL to allocate
+ Virtual Addresses for physical storage (usually I/O space) within
+ the range of memory that is reserved for the HAL.
+
+ This mechanism should only be used for mappings that are required
+ prior to the availability of MmMapIoSpace during system initialization.
+
+ The theory is that the top 4MB of virtual address space are reserved
+ for the HAL. The theory is slightly blemished in that
+
+ (1) three pages of this space are in use by the system, specifically
+ 0xfffff000 Debugger
+ 0xffffe000 Pcr Page 2
+ 0xffffd000 Pcr.
+ (2) To provide unique Pcrs for each processor in the system, segment
+ f has a unique VSID on each processor. This results in there
+ being one entry per processor for any page in segment f.
+
+ The reason the two pcr pages are in the upper 32K of the address
+ space is so they can be accessed in one instruction. This is
+ true for any address in the range 0xffff8000 thru 0xffffffff
+ because the address is sign-extended from the 16 bit D field of
+ the instruction.
+
+ In the interests of maintaing good kernel relations, this module
+ will not allocate from within the uppr 32KB of memory.
+
+ The expected usage of these routines if VERY INFREQUENT and the
+ allocation routines have not been coded for efficiency.
+
+ WARNING: These routines CANNOT be expected to use prior to the
+ success of HalAllocateHPT();
+
+Author:
+
+ Peter L Johnston (plj@vnet.ibm.com) 16-Aug-95
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+//
+// Define the range of virtual addresses this routine can allocate.
+// Note that the first page is skipped because I'm paranoid (plj).
+//
+// The range is the upper 4MB of Virtual Space - the top 32KB.
+//
+
+#define BASE_VA 0xffc00000
+#define HAL_BASE 0x000ffc01
+#define HAL_TOP 0x000ffff7
+#define PAGE_MASK 0x000fffff
+#define MAX_LENGTH (HAL_TOP-HAL_BASE)
+#define ADDRESS_MASK (PAGE_MASK << 12)
+#define OFFSET_MASK 0x00000ffc
+#define MIN_VA (HAL_BASE << PAGE_SHIFT)
+#define MAX_VA ((HAL_TOP << PAGE_SHIFT) + ((1 << PAGE_SHIFT) - 1))
+
+#define PTE_INDEX(x) (((ULONG)(x) >> PAGE_SHIFT) & 0x3ff)
+
+PHARDWARE_PTE HalpReservedPtes = NULL;
+
+// STATIC
+VOID
+HalpLocateReservedPtes(
+ VOID
+ )
+/*++
+
+ Routine Description: MODULE INTERNAL
+
+ Find the Virtual Address of the Page Table Page for the last
+ 4MB of memory. This range is reserved for the HAL with the
+ exception of the last 32KB. This page table page was allocated
+ by the OSLOADER so we can derive the address within KSEG0 from
+ the physical address which we can get from the Page Directory
+ (who's address we have).
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+ None.
+
+--*/
+{
+ HARDWARE_PTE DirectoryEntry;
+
+ //
+ // Get the entry from the Page Directory for the Page Table
+ // Page for the HAL reserved space. The upper 10 bits of the
+ // base address give us the index into the Page Directory (which
+ // is a page of PTEs or 1024 entries). Basically we want the
+ // last one which the following gives us (and will still work
+ // if it moves).
+ //
+
+ DirectoryEntry = *(PHARDWARE_PTE)(PDE_BASE |
+ ((HAL_BASE >> (PDI_SHIFT - 2 - PAGE_SHIFT)) & OFFSET_MASK));
+
+ //
+ // The page number from this PTE * page size + the base address
+ // of KSEG0 gives the virtual address of the Page Table Page we
+ // want.
+ //
+
+ HalpReservedPtes = (PHARDWARE_PTE)(KSEG0_BASE |
+ (DirectoryEntry.PageFrameNumber << PAGE_SHIFT));
+}
+
+PVOID
+HalpAssignReservedVirtualSpace(
+ ULONG BasePage,
+ ULONG LengthInPages
+ )
+
+/*++
+
+ Routine Description:
+
+ This function will attempt to allocate a contiguous range of
+ virtual address to provide access to memory at the requested
+ physical address.
+
+ Arguments:
+
+ Physical page number for which a Virtual Address assignment is
+ needed.
+
+ Length (in pages) of the region to be mapped.
+
+ Return Value:
+
+ Virtual Address in the range HAL_BASE thru HAL_TOP + fff,
+
+ -or-
+
+ NULL if the assignment couldn't be made.
+
+
+--*/
+
+{
+ ULONG Length;
+ HARDWARE_PTE TempPte;
+ HARDWARE_PTE ZeroPte;
+ PHARDWARE_PTE PPte;
+ PHARDWARE_PTE StartingPte;
+
+ //
+ // Sanity Checks
+ //
+
+ if ( (LengthInPages > MAX_LENGTH) ||
+ (!LengthInPages) ||
+ (BasePage & ~PAGE_MASK) ) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ return NULL;
+ }
+
+ if ( !HalpReservedPtes ) {
+ //
+ // Not initialized yet,... fix it.
+ //
+ HalpLocateReservedPtes();
+ }
+
+ PPte = HalpReservedPtes + PTE_INDEX(MIN_VA);
+ Length = LengthInPages;
+
+ while ( PPte <= (HalpReservedPtes + PTE_INDEX(MIN_VA)) || Length ) {
+ if ( PPte->Valid ) {
+ Length = LengthInPages;
+ } else {
+ Length--;
+ }
+ PPte++;
+ }
+
+ if ( Length ) {
+ return NULL;
+ }
+
+ //
+ // Found a range of pages. PPte is pointing to the entry
+ // beyond the end of the range.
+ //
+
+ StartingPte = PPte - LengthInPages;
+ PPte = StartingPte;
+ *(PULONG)&ZeroPte = 0;
+ TempPte = ZeroPte;
+ TempPte.Write = TRUE;
+ TempPte.CacheDisable = TRUE;
+ TempPte.MemoryCoherence = TRUE;
+ TempPte.GuardedStorage = TRUE;
+ TempPte.Dirty = 0x00; // PP bits KM read/write, UM no access.
+ TempPte.Valid = TRUE;
+
+ while ( LengthInPages-- ) {
+ //
+ // The following is done in a Temp so the actual write
+ // to the page table is done in a single write.
+ //
+ TempPte.PageFrameNumber = BasePage++;
+ *PPte++ = TempPte;
+ }
+ return (PVOID)(BASE_VA |
+ ((ULONG)(StartingPte - HalpReservedPtes) << PAGE_SHIFT));
+}
+
+VOID
+HalpReleaseReservedVirtualSpace(
+ PVOID VirtualAddress,
+ ULONG LengthInPages
+ )
+
+/*++
+
+ Routine Description:
+
+ This function will release the virtual address range previously
+ allocated with HalpAssignReservedVirtualSpace and should be
+ called with a virtual address previously allocated by a call to
+ HalpAssignReservedVirtualSpace the number of pages to release.
+
+ Arguments:
+
+ VirtualAddress of a previously allocated page in the HAL reserved
+ space.
+
+ Length (in pages) to be released.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ PHARDWARE_PTE PPte;
+
+ //
+ // Sanity Checks
+ //
+
+ if ( (LengthInPages > MAX_LENGTH) ||
+ (!LengthInPages) ||
+ ((ULONG)VirtualAddress < MIN_VA) ||
+ ((ULONG)VirtualAddress > MAX_VA) ) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ return;
+ }
+
+ if ( !HalpReservedPtes ) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ return;
+ }
+
+ PPte = HalpReservedPtes + PTE_INDEX(VirtualAddress);
+
+ do {
+ if ( !PPte->Valid ) {
+ break;
+ }
+ PPte->Valid = FALSE;
+ PPte++;
+ } while ( --LengthInPages );
+
+ if ( LengthInPages ) {
+ KeBugCheck(HAL_INITIALIZATION_FAILED);
+ }
+
+ KeFlushCurrentTb();
+
+ return;
+}
diff --git a/private/ntos/nthals/halppc/ppc/pxwd.c b/private/ntos/nthals/halppc/ppc/pxwd.c
new file mode 100644
index 000000000..ac0b3a2c0
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxwd.c
@@ -0,0 +1,938 @@
+/*++
+
+Copyright (c) 1995 International Business Machines Corporation
+
+Module Name:
+
+pxwd.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a PowerPC system using a Western Digital video adapter.
+
+Author:
+
+ Jim Wooldridge
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "pxwd.h"
+#include "string.h"
+//#include "txtpalet.h"
+#include "pci.h"
+
+//
+// Data Types used only in this file
+//
+
+typedef enum _LCD_TYPE{
+ NOT_CHECKED = 0x00, // panel type has not been checked yet
+ NoLCD = 0x01, // CRT
+ IBM_F8515 = 0x02, // CRT + IBM F8515 10.4" TFT LCD
+ IBM_F8532 = 0x04, // CRT + IBM F8532 10.4" TFT SVGA LCD
+ TOSHIBA_DSTNC = 0x08, // CRT + Toshiba 10.4" Dual Scan STN Color LCD
+ UNKNOWN_LCD = 0x80 // panel not recognized
+} LCD_TYPE;
+
+typedef struct{
+ LCD_TYPE Type;
+ ULONG XResolution;
+ ULONG YResolution;
+} PANEL_REC;
+
+extern PUCHAR HalpVideoMemoryBase;
+
+extern BOOLEAN HalpDisplayOwnedByHal;
+
+extern ULONG HalpInitPhase;
+
+//
+// Define OEM font variables.
+//
+
+extern USHORT HalpBytesPerRow;
+extern USHORT HalpCharacterHeight;
+extern USHORT HalpCharacterWidth;
+extern ULONG HalpDisplayText;
+extern ULONG HalpDisplayWidth;
+extern ULONG HalpScrollLength;
+extern ULONG HalpScrollLine;
+
+//
+// Define display variables.
+//
+
+extern ULONG HalpColumn;
+extern ULONG HalpRow;
+extern ULONG HalpHorizontalResolution;
+extern ULONG HalpVerticalResolution;
+
+
+//
+// Prototypes
+//
+
+VOID
+ GetPanelType(),
+ TurnOnLCD( BOOLEAN );
+
+extern VOID WaitForVSync();
+
+//
+// Global variables
+//
+
+PANEL_REC
+ LCDPanel = {NOT_CHECKED, 0, 0};
+
+//
+// Western Digital internal functions
+//
+
+static VOID
+LockPR (
+ USHORT PRnum,
+ PUCHAR pPRval
+ )
+{
+ USHORT pIndex, pData;
+ UCHAR Index, Data;
+ switch (PRnum) {
+ case pr5:
+ pIndex = PORT_GCR_INDEX;
+ pData = PORT_GCR_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 = PORT_SEQ_INDEX;
+ pData = PORT_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 = PORT_SEQ_INDEX;
+ pData = PORT_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 );
+}
+
+static VOID
+UnlockPR (
+ USHORT PRnum,
+ PUCHAR pPRval
+ )
+{
+ USHORT pIndex, pData;
+ UCHAR Index, Data;
+ switch (PRnum) {
+ case pr5:
+ pIndex = PORT_GCR_INDEX;
+ pData = PORT_GCR_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 = PORT_SEQ_INDEX;
+ pData = PORT_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 = PORT_SEQ_INDEX;
+ pData = PORT_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 );
+
+}
+static VOID
+RestorePR (
+ USHORT PRnum,
+ PUCHAR pPRval
+ )
+{
+ USHORT pIndex, pData;
+ UCHAR Index, Data;
+ switch (PRnum) {
+ case pr5:
+ pIndex = PORT_GCR_INDEX;
+ pData = PORT_GCR_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 = PORT_SEQ_INDEX;
+ pData = PORT_SEQ_DATA;
+ Index = pr20;
+ break;
+ case pr30:
+ pIndex = WD_3D4_Index;
+ pData = WD_3D5_Data;
+ Index = pr30;
+ break;
+ case pr72_alt:
+ pIndex = PORT_SEQ_INDEX;
+ pData = PORT_SEQ_DATA;
+ Index = pr72;
+ break;
+ default:
+ return;
+ } /* endswitch */
+
+ Data = *pPRval;
+ WRITE_WD_UCHAR( pIndex, Index );
+ WRITE_WD_UCHAR( pData, Data );
+
+}
+
+static 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( PORT_SEQ_INDEX, CLOCKING_MODE );
+ Temp = READ_WD_UCHAR( PORT_SEQ_DATA );
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, (Temp | 0x01));
+
+ Temp = READ_WD_UCHAR( PORT_GEN_MISC_RD );
+ WRITE_WD_UCHAR( PORT_GEN_MISC_WR, (Temp & 0xf3));
+
+// other clocking chip selects
+ UnlockPR( pr72_alt, &SavePR72 );
+
+ RestorePR( pr72_alt, &SavePR72 );
+
+ RestorePR( pr11, &SavePR11 );
+ RestorePR( pr10, &SavePR10 );
+ LockPR( pr20, NULL );
+
+// start of WD90C24A2 both screen mode table
+
+ if( LCDPanel.Type == IBM_F8532 )
+ pPRtable = wd90c24a_both_800;
+ else
+ pPRtable = wd90c24a_both_640;
+
+ 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( PORT_SEQ_INDEX, *pPRtable++ );
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, *pPRtable++ );
+ break;
+ case W_GCR :
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, *pPRtable++ );
+ WRITE_WD_UCHAR( PORT_GCR_DATA, *pPRtable++ );
+ break;
+ default :
+ break;
+ }
+ }
+
+ // unlock FLAT registers
+
+ UnlockPR( pr1b_ual, NULL );
+
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, pr68 );
+ Temp = READ_WD_UCHAR( PORT_SEQ_DATA );
+
+ if( LCDPanel.Type == IBM_F8532 )
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, ((Temp & 0xe7) | 0x10) );
+ else
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, ((Temp & 0xe7) | 0x08) );
+
+ WRITE_WD_UCHAR( WD_3D4_Index, pr19 );
+
+ if( LCDPanel.Type == IBM_F8532 )
+ WRITE_WD_UCHAR( WD_3D5_Data, (pr19_s32 & 0xf3));
+ else
+ WRITE_WD_UCHAR( WD_3D5_Data, (pr19_s32 & 0xf3));
+
+ // lock FLAT registers
+
+ LockPR( pr1b, NULL );
+
+} /* SetWDVGAConfig */
+
+VOID
+HalpDisplayPpcWDSetup (
+ VOID
+ )
+/*++
+
+Routine Description:
+ This routine initializes the Western Digital display controller chip.
+
+Arguments:
+ None.
+
+Return Value:
+ None.
+
+--*/
+{
+
+ ULONG DataLong, stop;
+ USHORT i, j;
+ UCHAR DataByte;
+ UCHAR Index;
+ PVOID Index_3x4, Data_3x5;
+ ULONG MemBase;
+ PHYSICAL_ADDRESS physicalAddress;
+
+ if (HalpInitPhase == 0) {
+
+ HalpVideoMemoryBase = (PUCHAR)KePhase0MapIo(PCI_MEMORY_PHYSICAL_BASE,
+ 0x400000); // 4 MB
+ } else {
+
+ //
+ // Map video memory space via pte's
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = PCI_MEMORY_PHYSICAL_BASE ;
+ HalpVideoMemoryBase = MmMapIoSpace(physicalAddress,
+ 0x400000,
+ FALSE);
+
+ //
+ // IO control space has already been mapped in phase 1 via halpmapiospace
+ //
+
+ }
+
+ if( LCDPanel.Type == NOT_CHECKED )
+ GetPanelType();
+
+ // turn the panel off before configuring it (prevents blowing the fuse)
+
+ TurnOnLCD( FALSE );
+
+ // 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( PORT_SYS_VGA_ENABLE, VideoParam[0] );
+
+ SetWDVGAConfig();
+
+ // turn off the hardware cursor
+
+ WRITE_WD_USHORT( EPR_INDEX, 0x1002 );
+ WRITE_WD_USHORT( EPR_DATA, 0x0000 );
+
+ // Note: Synchronous reset must be done before MISC_OUT write operation
+
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, RESET ); // Synchronous Reset !
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x01 );
+
+ // For ATI card (0x63) we may want to change the frequence
+
+ if( LCDPanel.Type == IBM_F8532 )
+ WRITE_WD_UCHAR( PORT_GEN_MISC_WR, (VideoParam[1] & 0xf3) );
+ else
+ WRITE_WD_UCHAR( PORT_GEN_MISC_WR, VideoParam[1] );
+
+ // Note: Synchronous reset must be done before CLOCKING MODE register is
+ // modified
+
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, RESET ); // Synchronous Reset !
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x01 );
+
+ // Sequencer Register
+
+ for( Index = 1; Index < 5; Index++ )
+ {
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, Index );
+ WRITE_WD_UCHAR( PORT_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 );
+
+ if( LCDPanel.Type == IBM_F8532 )
+ WRITE_WD_UCHAR( WD_3D5_Data, CRTC_800x600x60_Text[Index] );
+ else
+ WRITE_WD_UCHAR( WD_3D5_Data, CRTC_640x480x60_Text[Index] );
+ }
+
+ // attribute write
+ // program palettes and mode register
+
+ for( Index = 0; Index < 21; Index++ )
+ {
+ WaitForVSync();
+ DataByte = READ_WD_UCHAR( PORT_GEN_FEATURE_WR_C ); // Initialize Attr. F/F
+ WRITE_WD_UCHAR( PORT_ATTR_DATA_WR, Index );
+
+// KeStallExecutionProcessor( 5 );
+ WRITE_WD_UCHAR( PORT_ATTR_INDEX, VideoParam[ATTR_OFFSET + Index] );
+
+// KeStallExecutionProcessor( 5 );
+ WRITE_WD_UCHAR( PORT_ATTR_DATA_WR, 0x20 ); // Set into normal operation
+ }
+
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, RESET ); // reset to normal operation !
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x03 );
+
+ // graphics controller
+
+ for( Index = 0; Index < 9; Index++ )
+ {
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, Index );
+ WRITE_WD_UCHAR( PORT_GCR_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( PORT_SEQ_INDEX, 0x02 ); // Enable Write Plane reg
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x04 ); // select plane 2
+
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, 0x04 ); // Memory Mode Control reg
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, 0x06 ); // access to all planes,
+
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x05 ); // Graphic, Control Mode reg
+ WRITE_WD_UCHAR( PORT_GCR_DATA, 0x00 );
+
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x06 );
+ WRITE_WD_UCHAR( PORT_GCR_DATA, 0x04 );
+
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x04 );
+ WRITE_WD_UCHAR( PORT_GCR_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( PORT_SEQ_INDEX, 0x01 );
+ DataByte = READ_WD_UCHAR( PORT_SEQ_DATA );
+ DataByte &= 0xdf;
+ DataByte ^= 0x0;
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, DataByte );
+
+ WaitForVSync();
+
+ // Enable all the planes through the DAC
+ WRITE_WD_UCHAR( PORT_DAC_PIX_MASK, 0xff );
+
+ // start loading palette in register 0
+ WRITE_WD_UCHAR( PORT_DAC_WRITE_PIX_ADDR, 0 );
+
+ for( i = 0; i < 768; i++ )
+ {
+ WRITE_WD_UCHAR( PORT_DAC_DATA, TextPalette[i] );
+ }
+
+ //
+ //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ // select plane 0, 1
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, 0x02); // Enable Write Plane reg
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, VideoParam[SEQ_OFFSET + 0x02] );
+
+ // access to planes 0, 1.
+ WRITE_WD_UCHAR( PORT_SEQ_INDEX, 0x04); // Memory Mode Control reg
+ WRITE_WD_UCHAR( PORT_SEQ_DATA, VideoParam[SEQ_OFFSET+0x04]);
+
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x05 ); // Graphic, Control Mode reg
+ WRITE_WD_UCHAR( PORT_GCR_DATA, VideoParam[GRAPH_OFFSET + 0x05] );
+
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x04);
+ WRITE_WD_UCHAR( PORT_GCR_DATA, VideoParam[GRAPH_OFFSET + 0x04] );
+
+ WRITE_WD_UCHAR( PORT_GCR_INDEX, 0x06);
+ WRITE_WD_UCHAR( PORT_GCR_DATA, VideoParam[GRAPH_OFFSET + 0x06] );
+
+ //
+ // Set screen into blue
+ //
+
+ if( LCDPanel.Type == IBM_F8532 )
+ stop = 0xb9db0;
+ else
+ stop = 0xb92c0;
+
+ for( DataLong = 0xB8000; DataLong < stop; DataLong += 2 )
+ {
+ WRITE_WD_VRAM( DataLong, 0x20 );
+ WRITE_WD_VRAM( DataLong + 1, 0x1F );
+ }
+
+ //
+ // turn the panel back on
+ //
+
+ TurnOnLCD( TRUE );
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ //IBMLAN===============================================================
+ // Added the following so that HalQueryDisplayParameters() and
+ // HalSetDisplayParameters() work with either S3 or P9.
+
+ if( LCDPanel.Type == IBM_F8532 )
+ {
+ HalpDisplayWidth = 100;
+ HalpDisplayText = 37;
+ HalpScrollLine = 200;
+ }
+ else
+ {
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ HalpScrollLine = 160;
+ }
+
+ HalpScrollLength =
+ HalpScrollLine * (HalpDisplayText - 1);
+
+ //end IBMLAN===========================================================
+ HalpDisplayOwnedByHal = TRUE;
+
+ return;
+} /* end of InitializeWD() */
+
+VOID
+GetPanelType()
+
+/*++
+
+Routine Description:
+
+ This routine get the type of attached LCD display.
+
+Arguments:
+
+ HwDeviceExtension - Pointer to the miniport driver's device extension.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ UCHAR data8;
+
+ //
+ // read the panel controller
+ //
+
+ WRITE_WD_UCHAR(0xd00, 0xff);
+ data8 = READ_WD_UCHAR(0xd01);
+
+ switch (data8 & 0x0f) {
+ case 0x0e:
+ LCDPanel.Type = IBM_F8515;
+ LCDPanel.XResolution = 640;
+ LCDPanel.YResolution = 480;
+ break;
+
+ case 0x0c:
+ LCDPanel.Type = IBM_F8532;
+ LCDPanel.XResolution = 800;
+ LCDPanel.YResolution = 600;
+ break;
+
+ case 0x0d:
+ LCDPanel.Type = TOSHIBA_DSTNC;
+ LCDPanel.XResolution = 640;
+ LCDPanel.YResolution = 480;
+ break;
+
+ default:
+ LCDPanel.Type = UNKNOWN_LCD;
+ LCDPanel.XResolution = 0;
+ LCDPanel.YResolution = 0;
+ break;
+ }
+
+} // end GetPanelType()
+
+BOOLEAN
+HalpPhase0EnablePmController()
+
+{
+
+ ULONG i, BaseAddress;
+ USHORT VendorID, DeviceID, Command;
+
+ //
+ // Locates the controller on the PCI bus, and configures it
+ //
+
+ if (HalpPhase0MapBusConfigSpace() == FALSE){
+
+ return( FALSE );
+
+ } else {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+
+ HalpPhase0GetPciDataByOffset(0,
+ i,
+ &VendorID,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,VendorID),
+ sizeof(VendorID));
+
+ HalpPhase0GetPciDataByOffset(0,
+ i,
+ &DeviceID,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,DeviceID),
+ sizeof(DeviceID));
+
+ if ((VendorID == 0x1014) && (DeviceID == 0x001C)) {
+
+ HalpPhase0GetPciDataByOffset(0,
+ i,
+ &Command,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,Command),
+ sizeof(Command));
+
+ Command |= PCI_ENABLE_IO_SPACE;
+ BaseAddress = (ULONG)0x4100;
+
+ HalpPhase0SetPciDataByOffset(0,
+ i,
+ &Command,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,Command),
+ sizeof(Command));
+
+ HalpPhase0SetPciDataByOffset(0,
+ i,
+ &BaseAddress,
+ FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.BaseAddresses[0]),
+ sizeof(BaseAddress));
+
+ break;
+ } /* endif */
+
+ } /* endfor */
+
+ } /* end if map config space succeeds */
+
+ HalpPhase0UnMapBusConfigSpace();
+
+ return( TRUE );
+
+}
+
+BOOLEAN
+HalpPhase1EnablePmController()
+
+{
+
+ ULONG i;
+ PCI_SLOT_NUMBER slot;
+ PCI_COMMON_CONFIG PCIDeviceConfig;
+
+ slot.u.AsULONG = (ULONG)0;
+
+ //
+ // Locates the controller on the PCI bus, and configures it
+ //
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+
+ slot.u.bits.DeviceNumber = i;
+
+ HalGetBusData (
+ PCIConfiguration,
+ 0,
+ slot.u.AsULONG,
+ &PCIDeviceConfig,
+ sizeof (PCIDeviceConfig)
+ );
+
+ if ((PCIDeviceConfig.VendorID == 0x1014) &&
+ (PCIDeviceConfig.DeviceID == 0x001C)) {
+
+ PCIDeviceConfig.Command |= PCI_ENABLE_IO_SPACE;
+ PCIDeviceConfig.u.type0.BaseAddresses[0] = (ULONG)0x4100;
+
+ HalSetBusData (
+ PCIConfiguration,
+ 0,
+ slot.u.AsULONG,
+ &PCIDeviceConfig,
+ sizeof (PCIDeviceConfig)
+ );
+
+ break;
+ } /* endif */
+ } /* endfor */
+
+ return( TRUE );
+
+}
+
+# define PmIoBase 0x4100
+
+VOID
+TurnOnLCD( BOOLEAN PowerState )
+/*++
+
+Routine Description:
+
+ This routine turns on/off LCD.
+
+Arguments:
+
+ HwDeviceExtension - Pointer to the miniport driver's adapter information.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ BOOLEAN found = FALSE;
+
+ if (HalpInitPhase == 0)
+ found = HalpPhase0EnablePmController();
+ else
+ found = HalpPhase1EnablePmController();
+
+ if (!found) {
+ return;
+ } /* endif */
+
+ //
+ // Turns on/off LCD
+ //
+
+ if (PowerState) {
+
+ KeStallExecutionProcessor(100 * 1000); // wait 100ms for panel protection
+
+ WRITE_WD_UCHAR(PmIoBase, 0x0C);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) | (UCHAR)0x02);
+
+ KeStallExecutionProcessor(5 * 1000); // wait 5ms for DC/DC converter
+
+ WRITE_WD_UCHAR(PmIoBase, 0x0C);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) | (UCHAR)0x0c);
+
+ KeStallExecutionProcessor(1);
+
+ WRITE_WD_UCHAR(PmIoBase, 0x00);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) & ~(UCHAR)0x80);
+
+ KeStallExecutionProcessor(1);
+
+ WRITE_WD_UCHAR(PmIoBase, 0x0C);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) | (UCHAR)0x01);
+
+ } else {
+
+ WRITE_WD_UCHAR(PmIoBase, 0x0C);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) & ~(UCHAR)0x01);
+
+ KeStallExecutionProcessor(1);
+
+ WRITE_WD_UCHAR(PmIoBase, 0x00);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) | (UCHAR)0x80);
+
+ KeStallExecutionProcessor(1);
+
+ WRITE_WD_UCHAR(PmIoBase, 0x0C);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) & ~(UCHAR)0x0C);
+
+ KeStallExecutionProcessor(1);
+
+ WRITE_WD_UCHAR(PmIoBase, 0x0C);
+ WRITE_WD_UCHAR(PmIoBase + 1,
+ READ_WD_UCHAR(PmIoBase + 1) & ~(UCHAR)0x02);
+
+ } /* endif */
+
+} // end TurnOnLCD()
diff --git a/private/ntos/nthals/halppc/ppc/pxwd.h b/private/ntos/nthals/halppc/ppc/pxwd.h
new file mode 100644
index 000000000..56e621d65
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/pxwd.h
@@ -0,0 +1,706 @@
+/*++
+
+Copyright (c) 1994 IBM Corporation
+
+Module Name:
+
+ wdvga.h
+
+Abstract:
+
+ This header file defines the WD90C24A2 GUI accelerator registers.
+
+Author:
+
+ Hiroshi Itoh 25-Feb-1994
+
+Revision History:
+
+ Peter Johnston Adapted to Woodfield HAL. Apr-1994
+
+--*/
+
+#include "pxvgaequ.h"
+
+extern UCHAR CRTC_800x600x60_Text[];
+extern UCHAR CRTC_640x480x60_Text[];
+
+//-----------------------------------------------------------------------
+// WD 90C24 PR register
+//-----------------------------------------------------------------------
+#define pr0a 0x09 // Address Offset A Reg
+#define pr0b 0x0a // Alternate Address Offset B Reg
+#define pr1 0x0b // Memory Size Reg
+#define pr2 0x0c // Video Select Reg
+#define pr3 0x0d // CRT Lock Control Reg
+#define pr4 0x0e // Video Control Reg
+#define pr5 0x0f // Unlock graphic Controller Extended
+ // Paradise Reg
+
+#define pr10 0x29 // Unlock (PR11-PR17) Reg
+#define pr11 0x2a // Configuraiton Bits Reg
+#define pr12 0x2b // Scratch Pad Reg
+#define pr13 0x2c // Interlace H/2 Start Reg
+#define pr14 0x2d // Interlace H/2 End Reg
+#define pr15 0x2e // Miscellaneous Control 1 Reg
+#define pr16 0x2f // Miscellaneous Control 2 Reg
+#define pr17 0x30 // Miscellaneous Control 3 Reg
+#define pr18 0x31 // Flat Panel Status Reg
+#define pr19 0x32 // Flat Panel Control I Reg
+#define pr1a 0x33 // Flat Panel Control II Reg
+#define pr1b 0x34 // Flat Panel Unlock Reg
+
+#define pr20 0x06 // Unlock Sequencer Extended Reg
+#define pr21 0x07 // Display Configuraiton Status &
+ // Scratch Pad Reg
+#define pr22 0x08 // Scratch Pad Reg
+#define pr23 0x09 // Scratch Pad Reg
+
+#define pr30 0x35 // Mapping RAM Unlock Reg
+
+#define pr30a 0x10 // Memory Interface & FIFO Control Reg
+#define pr31 0x11 // System Interface Control Reg
+#define pr32 0x12 // Miscellaneous Control 4 Reg
+
+#define pr33 0x38 // Mapping RAM Address Counter Reg
+#define pr34 0x39 // Mapping RAM Data Reg
+
+#define pr33a 0x13 // DRAM Timing and 0 wait state control
+#define pr34a 0x14 // Video Memory Mapping Reg
+#define pr35a 0x15 // USR0, USR1 output select
+
+#define pr35 0x3a // Mapping RAM Control Reg
+#define pr36 0x3b // LCD Panel Height Select Reg
+#define pr37 0x3c // Flat Panel Height Select Reg
+#define pr39 0x3e // Color LCD Control Reg
+#define pr41 0x37 // Vertical Expansion Initial Value Reg
+
+#define pr44 0x3f // Power Down Memory Refresh Control Reg
+
+#define pr45 0x16 // Signal Analyzer Control Reg
+#define pr45a 0x17 // Signal Analyzer Data I
+#define pr45b 0x18 // Signal Analyzer Data II
+
+#define pr18a 0x3d // CRTC Vertical Timing Overflow
+
+#define pr57 0x19 // WD90C24 Feature Reg I
+#define pr58 0x20 // WD90C24 Feature Reg II
+#define pr59 0x21 // WD90C24 Memory Arbitration Cycle Setup
+#define pr60 0x22 // Reserved
+#define pr61 0x23 // Reserved
+#define pr62 0x24 // FR Timing Reg
+#define pr63 0x25 //
+#define pr58a 0x26 //
+#define pr64 0x27 //
+#define pr65 0x28 //
+#define pr66 0x29 //
+#define pr68 0x31 //
+#define pr69 0x32 //
+#define pr70 0x33 //
+#define pr71 0x34 //
+#define pr72 0x35 //
+#define pr73 0x36 //
+
+//-----------------------------------------------------------------------
+// pr register lock/unlock pattern
+//-----------------------------------------------------------------------
+#define pr5_lock 0x00 //
+#define pr5_unlock 0x05 //
+
+#define pr10_lock 0x00 //
+#define pr10_unlock 0x85 //
+
+#define pr11_unlock 0x80 //
+#define pr11_lock 0x85 //
+
+#define pr1b_lock 0x00 //
+#define pr1b_unlock_shadow 0x06 //
+#define pr1b_unlock_pr 0xa0 //
+#define pr1b_unlock 0xa6 //
+
+#define pr20_lock 0x00 //
+#define pr20_unlock 0x48 //
+
+#define pr30_lock 0x00 //
+#define pr30_unlock 0x30 //
+
+#define pr72_lock 0x00 //
+#define pr72_unlock 0x50 //
+
+//-----------------------------------------------------------------------
+// WD 90C24 PR register < Initital Value >
+//-----------------------------------------------------------------------
+// CRT TFT Sim STN Sim STNC STNC //
+// all only only 32 only 16 sim only //
+// ---- ---- ---- ---- ---- ---- ---- ---- //
+#define pr0a_all 0x00 //
+#define pr0b_all 0x00 //
+#define pr1_all 0xc5 //
+
+#define pr2_crt 0x00 //
+#define pr2_tft 0x01 //
+#define pr2_s32 0x01 //
+#define pr2_stn 0x01 //
+#define pr2_s16 0x01 //
+#define pr2_stnc 0x01 //
+
+#define pr3_all 0x00 //
+#define pr4_all 0x40 //
+
+#define pr12_all 0x00 //
+#define pr12_244LP 0xe8 //
+
+#define pr13_all 0x00 //
+#define pr14_all 0x00 //
+#define pr15_all 0x00 //
+#define pr16_all 0x42 //
+
+#define pr17_all 0x00 //
+#define pr17_244LP 0x40 //
+
+#define pr18_crt_tft 0x43 //single panel
+#define pr18_crt_stn 0x00 //dual panel
+#define pr18_tft 0xc7 // old d7h
+#define pr18_s32 0x47 // old 57h
+#define pr18_stn 0x80 //
+#define pr18_s16 0x00 //
+#define pr18_stnc 0x00 //
+
+#define pr19_disable 0x40 //
+#define pr19_crt 0x64 //
+#define pr19_tft 0x54 //
+#define pr19_s32 0x74 //
+#define pr19_stn 0x54 //
+#define pr19_s16 0x74 //
+#define pr19_stnc 0x74 //
+#define pr19_stnc_only 0x54 //
+
+#define pr39_crt 0x04 //
+#define pr39_tft 0x20 //
+#define pr39_s32 0x24 //
+#define pr39_stn 0x00 //
+#define pr39_s16 0x04 //
+#define pr39_stnc 0x24 //
+
+#define pr1a_all 0x00 // except STNC
+#define pr1a_stnc 0x60 // STNC
+
+#define pr36_all 0xef //
+
+#define pr37_crt 0x9a //
+#define pr37_tft 0x9a //
+#define pr37_s32 0x9a //
+#define pr37_stn 0x9a //
+#define pr37_s16 0x1a //
+#define pr37_stnc 0x9a //
+
+#define pr18a_all 0x00 //
+#define pr41_all 0x00 //
+#define pr44_all 0x00 //
+#define pr33_all 0x00 //
+#define pr34_all 0x00 //
+
+#define pr35_all 0x22 // old 0a2h
+#define pr35_suspend 0xa2 //
+
+#define pr21_all 0x00 //
+#define pr22_all 0x00 //
+#define pr23_all 0x00 //
+
+#define pr30a_crt 0xc1 //
+#define pr30a_tft 0xc1 //
+#define pr30a_s32 0xc1 //
+#define pr30a_stn 0xc1 //
+#define pr30a_s16 0xe1 //
+#define pr30a_stnc 0xe1 //
+
+#define pr31_all 0x25 //
+#define pr32_all 0x00 //
+
+#define pr33a_all 0x80 //
+#define pr33a_stnc 0x83 //
+
+#define pr34a_all 0x00 //
+#define pr35a_all 0x00 //
+
+#define pr45_all 0x00 //
+#define pr45a_all 0x00 //
+#define pr45b_all 0x00 //
+#define pr57_all 0x31 //
+#define pr58_all 0x00 //
+#define pr58a_all 0x00 //
+
+#define pr59_all_sivA 0x35 //
+#define pr59_crt 0x15 // for SIV-B
+#define pr59_tft 0x15 //
+#define pr59_s32 0x15 //
+#define pr59_stn 0x35 //
+#define pr59_s16 0x35 //
+#define pr59_stnc 0x03 //
+
+#define pr60_all 0x00 //
+#define pr61_all 0x00 //
+#define pr62_all 0x3c //
+#define pr63_all 0x00 //
+
+#define pr64_all 0x03 //enhncd v-exp
+
+#define pr65_all 0x00 //
+
+#define pr66_crt 0x40 //
+#define pr66_tft 0x40 //
+#define pr66_s32 0x40 //
+#define pr66_stn 0x40 //
+#define pr66_s16 0x40 //
+#define pr66_stnc 0x40 //
+
+#define pr68_crt 0x0d //
+#define pr68_tft 0x0d //
+#define pr68_s32 0x0d // old 0bh
+#define pr68_stn 0x1d //
+#define pr68_s16 0x0d //
+#define pr68_stnc 0x0d //
+#define pr68_stnc_only 0x07 //
+
+#define pr69_all 0x00 //
+#define pr69_stnc_only 0x53 // old 3fh
+
+#define pr70_all 0x00 //
+#define pr71_all 0x00 //
+#define pr73_all 0x01 //
+
+//--------------------------------------------------------------------------
+// WD 90C24 Shadow Register < Initial Value >
+//--------------------------------------------------------------------------
+// For TFT color Only Mode
+#define crtc00_tft 0x5f //
+#define crtc02_tft 0x50 //
+#define crtc03_tft 0x82 //
+#define crtc04_tft 0x54 //
+#define crtc05_tft 0x80 //
+#define crtc06_tft 0x0b //
+#define crtc07_tft 0x3e //
+#define crtc10_tft 0xea //
+#define crtc11_tft 0x8c //
+#define crtc15_tft 0xe7 //
+#define crtc16_tft 0x04 //
+
+// For TFT color Simultaneos Mode
+#define crtc00_s32 0x5f //
+#define crtc02_s32 0x50 //
+#define crtc03_s32 0x82 //
+#define crtc04_s32 0x54 //
+#define crtc05_s32 0x80 //
+#define crtc06_s32 0x0b //
+#define crtc07_s32 0x3e //
+#define crtc10_s32 0xea //
+#define crtc11_s32 0x8c //
+#define crtc15_s32 0xe7 //
+#define crtc16_s32 0x04 //
+
+// For STN mono Only Mode
+#define crtc00_stn 0x5f //
+#define crtc02_stn 0x50 //
+#define crtc03_stn 0x82 //
+#define crtc04_stn 0x54 //
+#define crtc05_stn 0x80 //
+#define crtc06_stn 0xf2 //
+#define crtc07_stn 0x12 //
+#define crtc10_stn 0xf0 //
+#define crtc11_stn 0x82 //
+#define crtc15_stn 0xf0 //
+#define crtc16_stn 0xf2 //
+
+// For STN mono Simultaneos Mode
+#define crtc00_s16 0x5f //
+#define crtc02_s16 0x50 //
+#define crtc03_s16 0x82 //
+#define crtc04_s16 0x54 //
+#define crtc05_s16 0x80 //
+#define crtc06_s16 0x12 //
+#define crtc07_s16 0x3e //
+#define crtc10_s16 0xea //
+#define crtc11_s16 0x8c //
+#define crtc15_s16 0xe7 //
+#define crtc16_s16 0x04 //
+
+// For STN Color Simultaneos Mode //new old
+#define crtc00_stnc 0x61 // 60h
+#define crtc02_stnc 0x50 // 51h
+#define crtc03_stnc 0x84 // 82h
+#define crtc04_stnc 0x56 // 54h
+#define crtc05_stnc 0x80 //
+#define crtc06_stnc 0x0e // 0ah
+#define crtc07_stnc 0x3e //
+#define crtc10_stnc 0xea //
+#define crtc11_stnc 0x8e //
+#define crtc15_stnc 0xe7 //
+#define crtc16_stnc 0x04 //
+
+// For STN Color LCD only Mode //new old
+#define crtc00_stnc_only 0x67 // 60h
+#define crtc02_stnc_only 0x50 // 50h
+#define crtc03_stnc_only 0x82 // 82h
+#define crtc04_stnc_only 0x55 // 54h
+#define crtc05_stnc_only 0x81 // 80h
+#define crtc06_stnc_only 0xe6 // 0e6h
+#define crtc07_stnc_only 0x1f // 1fh
+#define crtc10_stnc_only 0xe0 // 0d9h
+#define crtc11_stnc_only 0x82 // 82h
+#define crtc15_stnc_only 0xe0 // 0f0h
+#define crtc16_stnc_only 0xe2 // 00h
+
+//-----------------------------------------------------------------------
+// WD 90C24 Mapping RAM Data
+//-----------------------------------------------------------------------
+#define map_00 0x00
+#define map_01 0x05
+#define map_02 0x05
+#define map_03 0x06
+#define map_04 0x06
+#define map_05 0x07
+#define map_06 0x07
+#define map_07 0x08
+#define map_08 0x08
+#define map_09 0x0a
+#define map_0a 0x0a
+#define map_0b 0x0b
+#define map_0c 0x0c
+#define map_0d 0x0d
+#define map_0e 0x0d
+#define map_0f 0x0f
+
+#define map_10 0x0f
+#define map_11 0x11
+#define map_12 0x12 // old 11h
+#define map_13 0x12 // old 13h
+#define map_14 0x15 // old 13h
+#define map_15 0x15
+#define map_16 0x17 // old 15h
+#define map_17 0x17
+#define map_18 0x19 // old 17h
+#define map_19 0x19
+#define map_1a 0x1b
+#define map_1b 0x1b
+#define map_1c 0x1d
+#define map_1d 0x1d
+#define map_1e 0x1f
+#define map_1f 0x1f
+
+#define map_20 0x20
+#define map_21 0x21
+#define map_22 0x21
+#define map_23 0x23
+#define map_24 0x25 // old 24h
+#define map_25 0x27
+#define map_26 0x27
+#define map_27 0x29
+#define map_28 0x29
+#define map_29 0x2a
+#define map_2a 0x2b
+#define map_2b 0x2b // old 2ch
+#define map_2c 0x2e
+#define map_2d 0x2e
+#define map_2e 0x2f
+#define map_2f 0x2f
+
+#define map_30 0x31
+#define map_31 0x33
+#define map_32 0x33
+#define map_33 0x34
+#define map_34 0x34
+#define map_35 0x35 // old 36h
+#define map_36 0x36
+#define map_37 0x38
+#define map_38 0x39
+#define map_39 0x39
+#define map_3a 0x3a
+#define map_3b 0x3a
+#define map_3c 0x3b
+#define map_3d 0x3b
+#define map_3e 0x3f
+#define map_3f 0x3f
+
+//-----------------------------------------------------------------------
+// Paradise register bit flag definitions
+//-----------------------------------------------------------------------
+// pr19 display position definition
+#define pr19_CENTER 0x04 // display position is CENTER
+#define pr19_TOP 0x00 // display position is TOP
+#define pr19_BOTTOM 0x04 // display position is BOTTOM (N/A)
+#define pr19_VEXP 0x0C // Vertical Expansion
+
+//-----------------------------------------------------------------------
+// Extended Paradise Regs definitions
+//-----------------------------------------------------------------------
+// Global port definitions
+#define EPR_INDEX 0x23c0 // Index Control Reg
+#define EPR_DATA 0x23c2 // Register access port
+
+//
+// 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 WD register I/O Macros
+//
+
+
+#define WRITE_WD_UCHAR(port,data) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port)) = (UCHAR)(data), \
+ KeFlushWriteBuffer()
+
+#define WRITE_WD_USHORT(port,data) \
+ *(volatile PUSHORT)((ULONG)HalpIoControlBase + (port)) = (USHORT)(data), \
+ KeFlushWriteBuffer()
+
+#define READ_WD_UCHAR(port) \
+ *(volatile unsigned char *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_WD_USHORT(port) \
+ *(volatile unsigned short *)((ULONG)HalpIoControlBase + (port))
+
+#define READ_WD_VRAM(port) \
+ *(HalpVideoMemoryBase + (port))
+
+#define WRITE_WD_VRAM(port,data) \
+ *(HalpVideoMemoryBase + (port)) = (data), \
+ KeFlushWriteBuffer()
+
+//
+// Define video register format.
+//
+#define WD_3D4_Index 0x3D4 // R/W
+#define WD_3D5_Data 0x3D5 // R/W
+
+#define SUBSYS_ENB 0x46E8 // R/W
+
+//
+// WD90C24A2 LCD/CRT both screen table
+//
+
+enum { W_SEQ, W_GCR, W_ACR, W_CRTC, R_SEQ, R_GCR, R_ACR, R_CRTC, END_PVGA } pvga_service;
+
+static
+UCHAR
+wd90c24a_both_800[] = {
+ W_CRTC , pr10, pr10_unlock , // Disable CRT/LCD by PR19
+ W_CRTC , pr11, pr11_unlock , // Disable CRT/LCD by PR19
+ W_CRTC , pr1b, pr1b_unlock , // Disable CRT/LCD by PR19
+ W_CRTC , pr19, pr19_disable ,
+//---------------------> start SEQ
+
+ W_SEQ , pr20 , pr20_unlock , // PVGA Sequencer Regs
+// W_SEQ , pr21 , pr21_all , // read only
+ W_SEQ , pr30a, pr30a_s32 ,
+ W_SEQ , pr31 , (pr31_all & ~0x24) ,
+
+ W_SEQ , pr32 , pr32_all ,
+ W_SEQ , pr33a, pr33a_all ,
+ W_SEQ , pr34a, pr34a_all ,
+ W_SEQ , pr35a, pr35a_all ,
+// W_SEQ , pr45 , pr45_all ,
+// W_SEQ , pr45a, pr45a_all ,
+// W_SEQ , pr45b, pr45b_all ,
+ W_SEQ , pr57 , pr57_all ,
+
+
+ W_SEQ , pr58 , pr58_all ,
+ W_SEQ , pr58a, pr58a_all ,
+ W_SEQ , pr59 , pr59_s32 ,
+// W_SEQ , pr60 , pr60_all ,
+// W_SEQ , pr61 , pr61_all ,
+ W_SEQ , pr62 , pr62_all ,
+// W_SEQ , pr63 , pr63_all ,
+ W_SEQ , pr64 , pr64_all ,
+// W_SEQ , pr65 , pr65_all ,
+
+
+ W_SEQ , pr66 , pr66_s32 , // old 00h
+ W_SEQ , pr72 , pr72_unlock , // unlock clock select
+ W_SEQ , pr68 , pr68_s32 , // 0d
+// W_SEQ , pr72 , pr72_lock , // lock clock select
+// W_SEQ , pr72 , pr72_lock , // lock is default
+// W_SEQ , pr69 , pr69_all ,
+// W_SEQ , pr70 , pr70_all ,
+ W_SEQ , pr70 , 0x24 ,
+// W_SEQ , pr71 , pr71_all , // disabled by PR57(1)
+// W_SEQ , pr73 , pr73_all ,
+// W_SEQ , pr20 , pr20_lock ,
+
+
+//---------------------> start GRAPH
+
+ W_GCR , pr5 , pr5_unlock , // PR0(A), PR0(B), PR1, PR2, PR3, PR4
+// W_GCR , pr0a , pr0a_all ,
+// W_GCR , pr0b , pr0b_all ,
+ W_GCR , pr1 , pr1_all ,
+ W_GCR , pr2 , pr2_s32 ,
+ W_GCR , pr3 , pr3_all ,
+ W_GCR , pr4 , pr4_all ,
+ // W_GCR , pr5 , pr5_lock ,
+
+
+//---------------------> start CRTC
+
+ W_CRTC , pr10 , pr10_unlock , // PR11, PR13, PR14, PR15, PR16, PR17
+// W_CRTC , pr11 , pr11_lock , // default is lock
+// W_CRTC , pr12 , pr12_all ,
+ W_CRTC , pr13 , pr13_all ,
+ W_CRTC , pr14 , pr14_all ,
+ W_CRTC , pr15 , pr15_all ,
+ W_CRTC , pr16 , pr16_all ,
+ W_CRTC , pr17 , pr17_all ,
+// W_CRTC , pr10 , pr10_lock ,
+
+
+ W_CRTC , pr1b , pr1b_unlock , // PR18, PR19, PR1A, PR36, PR37, PR39, PR41, PR44
+ W_CRTC , pr18 , pr18_s32 ,
+// W_CRTC , pr19 , pr19_s32 ,
+ W_CRTC , pr19 , pr19_tft & ~0x04 ,
+ W_CRTC , pr39 , pr39_s32 ,
+ W_CRTC , pr1a , 0x90 ,
+ W_CRTC , pr36 , pr36_all ,
+ W_CRTC , pr37 , pr37_s32 ,
+ W_CRTC , pr18a, pr18a_all ,
+// W_CRTC , pr41 , pr41_all ,
+ W_CRTC , pr44 , pr44_all ,
+// W_CRTC , pr1b , pr1b_lock ,
+
+ W_CRTC , pr30 , pr30_unlock , // PR35 (Mapping RAM not initialized)
+// W_CRTC , pr33 , pr33_all ,
+// W_CRTC , pr34 , pr34_all ,
+ W_CRTC , pr35 , pr35_all ,
+// W_CRTC , pr30 , pr30_lock ,
+
+ // Shadow Regs
+// CRTC shadows
+
+ W_CRTC , pr1b , pr1b_unlock_shadow ,// Unlock shadow
+ W_CRTC , 0x11 , crtc11_s32 & 0x7f , // unlock CRTC 0-7
+
+ W_CRTC , 0x00 , 0x7f ,
+ W_CRTC , 0x01 , 0x63 ,
+ W_CRTC , 0x02 , 0x64 ,
+ W_CRTC , 0x03 , 0x82 ,
+ W_CRTC , 0x04 , 0x6b ,
+ W_CRTC , 0x05 , 0x1b ,
+ W_CRTC , 0x06 , 0x72 ,
+ W_CRTC , 0x07 , 0xf0 ,
+ W_CRTC , 0x09 , 0x20 ,
+ W_CRTC , 0x10 , 0x58 ,
+ W_CRTC , 0x11 , 0x8c , // lock CRTC 0-7
+ W_CRTC , 0x15 , 0x58 ,
+ W_CRTC , 0x16 , 0x71 ,
+// W_CRTC , pr17 , 0xe3 , // Lock shadow
+// W_CRTC , pr18 , 0xff , // Lock shadow
+
+//---------------------> start CRTC
+
+ W_CRTC , pr1b, pr1b_unlock_pr ,
+ W_CRTC , pr19 ,(pr19_s32 & ~0x04), // Lock shadow
+
+ END_PVGA
+};
+
+static
+UCHAR
+wd90c24a_both_640[] = {
+ W_CRTC , pr1b, pr1b_unlock , // Disable CRT/LCD by PR19
+ W_CRTC , pr19, pr19_disable ,
+ W_CRTC , pr1b, pr1b_lock ,
+
+ W_SEQ , pr20 , pr20_unlock , // PVGA Sequencer Regs
+// W_SEQ , pr21 , pr21_all , // read only
+ W_SEQ , pr30a, pr30a_s32 ,
+ W_SEQ , pr31 , pr31_all ,
+ W_SEQ , pr32 , pr32_all ,
+ W_SEQ , pr33a, pr33a_all ,
+ W_SEQ , pr34a, pr34a_all ,
+ W_SEQ , pr35a, pr35a_all ,
+// W_SEQ , pr45 , pr45_all ,
+// W_SEQ , pr45a, pr45a_all ,
+// W_SEQ , pr45b, pr45b_all ,
+ W_SEQ , pr57 , pr57_all ,
+ W_SEQ , pr58 , pr58_all ,
+ W_SEQ , pr58a, pr58a_all ,
+ W_SEQ , pr59 , pr59_s32 ,
+// W_SEQ , pr60 , pr60_all ,
+// W_SEQ , pr61 , pr61_all ,
+ W_SEQ , pr62 , pr62_all ,
+// W_SEQ , pr63 , pr63_all ,
+ W_SEQ , pr64 , pr64_all ,
+// W_SEQ , pr65 , pr65_all ,
+ W_SEQ , pr66 , pr66_s32 , // old 00h
+ W_SEQ , pr72 , pr72_unlock , // unlock clock select
+ W_SEQ , pr68 , pr68_s32 , // 0d
+// W_SEQ , pr72 , pr72_lock , // lock clock select
+ W_SEQ , pr72 , pr72_lock , // lock is default
+// W_SEQ , pr69 , pr69_all ,
+// W_SEQ , pr70 , pr70_all ,
+// W_SEQ , pr71 , pr71_all , // disabled by PR57(1)
+// W_SEQ , pr73 , pr73_all ,
+ W_SEQ , pr20 , pr20_lock ,
+
+ W_GCR , pr5 , pr5_unlock , // PR0(A), PR0(B), PR1, PR2, PR3, PR4
+// W_GCR , pr0a , pr0a_all ,
+// W_GCR , pr0b , pr0b_all ,
+ W_GCR , pr1 , pr1_all ,
+ W_GCR , pr2 , pr2_s32 ,
+ W_GCR , pr3 , pr3_all ,
+ W_GCR , pr4 , pr4_all ,
+ W_GCR , pr5 , pr5_lock ,
+
+ W_CRTC , pr10 , pr10_unlock , // PR11, PR13, PR14, PR15, PR16, PR17
+ W_CRTC , pr11 , pr11_lock , // default is lock
+// W_CRTC , pr12 , pr12_all ,
+ W_CRTC , pr13 , pr13_all ,
+ W_CRTC , pr14 , pr14_all ,
+ W_CRTC , pr15 , pr15_all ,
+ W_CRTC , pr16 , pr16_all ,
+ W_CRTC , pr17 , pr17_all ,
+ W_CRTC , pr10 , pr10_lock ,
+
+ W_CRTC , pr1b , pr1b_unlock , // PR18, PR19, PR1A, PR36, PR37, PR39, PR41, PR44
+ W_CRTC , pr18 , pr18_s32 ,
+ W_CRTC , pr19 , pr19_s32 ,
+ W_CRTC , pr39 , pr39_s32 ,
+ W_CRTC , pr1a , pr1a_all ,
+ W_CRTC , pr36 , pr36_all ,
+ W_CRTC , pr37 , pr37_s32 ,
+ W_CRTC , pr18a, pr18a_all ,
+// W_CRTC , pr41 , pr41_all ,
+ W_CRTC , pr44 , pr44_all ,
+ W_CRTC , pr1b , pr1b_lock ,
+
+ W_CRTC , pr30 , pr30_unlock , // PR35 (Mapping RAM not initialized)
+// W_CRTC , pr33 , pr33_all ,
+// W_CRTC , pr34 , pr34_all ,
+ W_CRTC , pr35 , pr35_all ,
+ W_CRTC , pr30 , pr30_lock ,
+
+ // Shadow Regs
+ W_CRTC , pr1b , pr1b_unlock_shadow ,// Unlock shadow
+ W_CRTC , 0x11 , crtc11_s32 & 0x7f , // unlock CRTC 0-7
+ W_CRTC , 0x00 , crtc00_s32 ,
+ W_CRTC , 0x02 , crtc02_s32 ,
+ W_CRTC , 0x03 , crtc03_s32 ,
+ W_CRTC , 0x04 , crtc04_s32 ,
+ W_CRTC , 0x05 , crtc05_s32 ,
+ W_CRTC , 0x06 , crtc06_s32 ,
+ W_CRTC , 0x07 , crtc07_s32 ,
+ W_CRTC , 0x09 , 0x00 ,
+ W_CRTC , 0x10 , crtc10_s32 ,
+ W_CRTC , 0x11 , crtc11_s32 , // lock CRTC 0-7
+ W_CRTC , 0x15 , crtc15_s32 ,
+ W_CRTC , 0x16 , crtc16_s32 ,
+ W_CRTC , pr1b , pr1b_lock , // Lock shadow
+
+ END_PVGA
+};
diff --git a/private/ntos/nthals/halppc/ppc/txtpalet.h b/private/ntos/nthals/halppc/ppc/txtpalet.h
new file mode 100644
index 000000000..307464362
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/txtpalet.h
@@ -0,0 +1,97 @@
+/******************************************************************************
+
+txtpalet.h
+
+ Author: Jess Botts
+
+ This file contains the text mode palette. Most of the entries are 0
+ because they are not used. The first 8 entries are used for all
+ background colors and normal intensity foregound colors. Background
+ colors are displayed at normal intensity only. The 8 entries that
+ begin at the 56th entry are used for high intensity foreground colors.
+
+ Each entry consists of 3 values, 1 for each color gun.
+
+******************************************************************************/
+
+UCHAR
+ TextPalette[] =
+ { /*
+ Line
+ R G B R G B R G B R G B Index
+ */
+
+// all background colors and normal intensity foregound colors
+
+ 0, 0, 0, 0, 0, 32, 0, 32, 0, 0, 32, 32, // 0
+ 32, 0, 0, 32, 0, 32, 32, 32, 0, 32, 32, 32,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+// high intensity foreground colors
+
+ 16, 16, 16, 0, 0, 63, 0, 63, 0, 0, 63, 63, // 56
+ 63, 0, 0, 63, 0, 63, 63, 63, 0, 63, 63, 63,
+
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 64
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 128
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 192
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+
+/*****************************************************************************/
diff --git a/private/ntos/nthals/halppc/ppc/x86bios.c b/private/ntos/nthals/halppc/ppc/x86bios.c
new file mode 100644
index 000000000..06317109b
--- /dev/null
+++ b/private/ntos/nthals/halppc/ppc/x86bios.c
@@ -0,0 +1,359 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+Author:
+
+ David N. Cutler (davec) 17-Jun-1994
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+
+ULONG
+x86BiosGetPciDataByOffset(
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+x86BiosSetPciDataByOffset(
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+
+extern PUCHAR HalpShadowBuffer;
+extern ULONG HalpPciMaxBuses;
+extern ULONG HalpInitPhase;
+
+
+//
+// Define global data.
+//
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = FALSE;
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // If the x86 BIOS Emulator has not been initialized, then return FALSE.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // If the Video Adapter initialization failed and an Int10 command is
+ // specified, then return FALSE.
+ //
+
+ if ((BiosCommand == 0x10) && (HalpEnableInt10Calls == FALSE)) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and emulate the specified command.
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+
+ if (x86BiosExecuteInterruptShadowedPci((UCHAR)BiosCommand,
+ &Context,
+ (PVOID)HalpIoControlBase,
+ (PVOID)(HalpShadowBuffer - 0xc0000),
+ (PVOID)HalpIoMemoryBase,
+ (UCHAR)HalpPciMaxBuses,
+ x86BiosGetPciDataByOffset,
+ x86BiosSetPciDataByOffset
+ ) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and return TRUE.
+ //
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+ return TRUE;
+}
+
+VOID
+HalpInitializeX86DisplayAdapter(
+ ULONG VideoDeviceBusNumber,
+ ULONG VideoDeviceSlotNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ BiosAddress - If the BIOS is shadowed, this will be a pointer to
+ non-paged pool. If the BIOS is not shadowed, this
+ should be HalpIoMemoryBase + C0000.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // If I/O Ports or I/O memory could not be mapped, then don't
+ // attempt to initialize the display adapter.
+ //
+
+ if (HalpIoControlBase == NULL || HalpIoMemoryBase == NULL) {
+ return;
+ }
+
+ //
+ // Initialize the x86 bios emulator.
+ //
+
+ x86BiosInitializeBiosShadowedPci(HalpIoControlBase,
+ (PVOID)(HalpShadowBuffer - 0xc0000),
+ (PVOID)HalpIoMemoryBase,
+ (UCHAR)HalpPciMaxBuses,
+ x86BiosGetPciDataByOffset,
+ x86BiosSetPciDataByOffset
+ );
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Attempt to initialize the display adapter by executing its ROM bios
+ // code. The standard ROM bios code address for PC video adapters is
+ // 0xC000:0000 on the ISA bus.
+ //
+
+ // This context specifies where to find the PCI video device in the
+ // format explained in the PCI BIOS Specification.
+ Context.Eax = (VideoDeviceBusNumber << 8) | (VideoDeviceSlotNumber << 3);
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ if (x86BiosInitializeAdapterShadowedPci(0xc0000,
+ &Context,
+ (PVOID)HalpIoControlBase,
+ (PVOID)(HalpShadowBuffer - 0xc0000),
+ (PVOID)HalpIoMemoryBase,
+ (UCHAR)HalpPciMaxBuses,
+ x86BiosGetPciDataByOffset,
+ x86BiosSetPciDataByOffset
+ ) != XM_SUCCESS) {
+
+
+
+ HalpEnableInt10Calls = FALSE;
+ return;
+ }
+
+ HalpEnableInt10Calls = TRUE;
+ return;
+}
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // Initialize the x86 bios context and make the INT 10 call to initialize
+ // the display adapter to 80x25 color text mode.
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+}
+
+ULONG
+x86BiosGetPciDataByOffset(
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function is a wrapper. It exists because we don't have
+ a consistent interface to PCI config space during the boot
+ process.
+
+--*/
+{
+
+ if (HalpInitPhase == 0) {
+ return HalpPhase0GetPciDataByOffset(BusNumber,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length
+ );
+ } else {
+ return HalGetBusDataByOffset(PCIConfiguration,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length
+ );
+ }
+}
+
+ULONG
+x86BiosSetPciDataByOffset(
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ This function is a wrapper. It exists because we don't have
+ a consistent interface to PCI config space during the boot
+ process.
+
+--*/
+{
+ if (HalpInitPhase == 0) {
+ return HalpPhase0SetPciDataByOffset(BusNumber,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length
+ );
+ } else {
+ return HalSetBusDataByOffset(PCIConfiguration,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length
+ );
+ }
+}
+
+
diff --git a/private/ntos/nthals/halppc/sources b/private/ntos/nthals/halppc/sources
new file mode 100644
index 000000000..d58b5d3af
--- /dev/null
+++ b/private/ntos/nthals/halppc/sources
@@ -0,0 +1,106 @@
+!IF 0
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+
+Author:
+
+ David N. Cutler (davec) 8-Apr-1993
+
+Revision Histoy:
+
+ Jim Wooldridge (jimw@austin.vnet.ibm.com) Power PC port
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=hal
+
+TARGETNAME=halppc
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETLIBS=..\x86new\obj\*\x86new.lib \
+ $(BASEDIR)\public\sdk\lib\*\libc.lib
+
+
+!IF $(PPC)
+TARGETTYPE=HAL
+!ELSE
+TARGETTYPE=DRIVER
+!ENDIF
+
+C_DEFINES=-DDAKOTA -DSANDALFOOT -DSOFT_HDD_LAMP -D_HALNVR_
+
+INCLUDES=..\x86new;$(BASEDIR)\private\ntos\inc
+
+SOURCES=
+
+PPC_SOURCES=hal.rc \
+ drivesup.c \
+ bushnd.c \
+ rangesup.c \
+ ppc\pxbeep.c \
+ ppc\pxnatsup.c \
+ ppc\pxsiosup.c \
+ ppc\pxmemctl.c \
+ ppc\pxpcisup.c \
+ ppc\pxdisp.c \
+ ppc\pxp91.c \
+ ppc\pxshadbf.s \
+ ppc\pxwd.c \
+ ppc\pxs3.c \
+ ppc\pxbbl.c \
+ ppc\pxbl.c \
+ ppc\pxstall.s \
+ ppc\pxcache.s \
+ ppc\pxclock.c \
+ ppc\pxcalstl.c \
+ ppc\pxclksup.s \
+ ppc\pxflshbf.s \
+ ppc\pxhwsup.c \
+ ppc\pxprof.c \
+ ppc\pxenviro.c \
+ ppc\pxmapio.c \
+ ppc\pxsysint.c \
+ ppc\pxtime.c \
+ ppc\pxreset.s \
+ ppc\pxreturn.c \
+ ppc\pxintsup.s \
+ ppc\pxintrpt.c \
+ ppc\pxinithl.c \
+ ppc\pxport.c \
+ ppc\pxirql.c \
+ ppc\pxusage.c \
+ ppc\pxbusdat.c \
+ ppc\pxpcibus.c \
+ ppc\pxpciint.c \
+ ppc\pxisabus.c \
+ ppc\pxidle.c \
+ ppc\pxsysbus.c \
+ ppc\pxproc.c \
+ ppc\pxdat.c \
+ ppc\fwnvr.c \
+ ppc\pxflshio.c \
+ ppc\pxintmod.c \
+ ppc\pxpcibrd.c \
+ ppc\pxinfo.c \
+ ppc\x86bios.c
+
+DLLDEF=obj\*\hal.def
+
+!IF $(PPC)
+NTTARGETFILES=$(TARGETPATH)\ppc\hal.lib
+!ENDIF