From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/ntos/nthals/halppc/hal.rc | 11 + private/ntos/nthals/halppc/makefile | 6 + private/ntos/nthals/halppc/makefile.inc | 3 + private/ntos/nthals/halppc/ppc/bbldef.h | 446 ++++++ private/ntos/nthals/halppc/ppc/bblfont.h | 1499 ++++++++++++++++++ private/ntos/nthals/halppc/ppc/bblrastz.h | 113 ++ private/ntos/nthals/halppc/ppc/bblrmdac.h | 802 ++++++++++ private/ntos/nthals/halppc/ppc/bldef.h | 144 ++ private/ntos/nthals/halppc/ppc/blfw.h | 121 ++ private/ntos/nthals/halppc/ppc/blrastz.h | 348 +++++ private/ntos/nthals/halppc/ppc/blrmdac.h | 152 ++ private/ntos/nthals/halppc/ppc/fwdebug.h | 99 ++ private/ntos/nthals/halppc/ppc/fwnvr.c | 2033 ++++++++++++++++++++++++ private/ntos/nthals/halppc/ppc/fwnvr.h | 313 ++++ private/ntos/nthals/halppc/ppc/fwstatus.h | 17 + private/ntos/nthals/halppc/ppc/halp.h | 503 ++++++ private/ntos/nthals/halppc/ppc/ibmppc.h | 60 + private/ntos/nthals/halppc/ppc/pcip.h | 186 +++ private/ntos/nthals/halppc/ppc/prepnvr.h | 134 ++ private/ntos/nthals/halppc/ppc/pxbbl.c | 1546 +++++++++++++++++++ private/ntos/nthals/halppc/ppc/pxbeep.c | 134 ++ private/ntos/nthals/halppc/ppc/pxbl.c | 1700 ++++++++++++++++++++ private/ntos/nthals/halppc/ppc/pxbusdat.c | 200 +++ private/ntos/nthals/halppc/ppc/pxcache.s | 1188 ++++++++++++++ private/ntos/nthals/halppc/ppc/pxcalstl.c | 132 ++ private/ntos/nthals/halppc/ppc/pxclksup.s | 153 ++ private/ntos/nthals/halppc/ppc/pxclock.c | 283 ++++ private/ntos/nthals/halppc/ppc/pxdakota.h | 67 + private/ntos/nthals/halppc/ppc/pxdat.c | 123 ++ private/ntos/nthals/halppc/ppc/pxdisp.c | 1733 +++++++++++++++++++++ private/ntos/nthals/halppc/ppc/pxdisp.h | 360 +++++ private/ntos/nthals/halppc/ppc/pxds1585.h | 106 ++ private/ntos/nthals/halppc/ppc/pxenviro.c | 170 ++ private/ntos/nthals/halppc/ppc/pxfirsup.c | 1606 +++++++++++++++++++ private/ntos/nthals/halppc/ppc/pxfirsup.h | 219 +++ private/ntos/nthals/halppc/ppc/pxflshbf.s | 121 ++ private/ntos/nthals/halppc/ppc/pxflshio.c | 197 +++ private/ntos/nthals/halppc/ppc/pxhalp.h | 345 +++++ private/ntos/nthals/halppc/ppc/pxhwsup.c | 2188 ++++++++++++++++++++++++++ private/ntos/nthals/halppc/ppc/pxidaho.h | 139 ++ private/ntos/nthals/halppc/ppc/pxidle.c | 62 + private/ntos/nthals/halppc/ppc/pxinfo.c | 213 +++ private/ntos/nthals/halppc/ppc/pxinithl.c | 325 ++++ private/ntos/nthals/halppc/ppc/pxintmod.c | 79 + private/ntos/nthals/halppc/ppc/pxintrpt.c | 105 ++ private/ntos/nthals/halppc/ppc/pxintsup.s | 35 + private/ntos/nthals/halppc/ppc/pxirql.c | 284 ++++ private/ntos/nthals/halppc/ppc/pxisabus.c | 133 ++ private/ntos/nthals/halppc/ppc/pxmapio.c | 124 ++ private/ntos/nthals/halppc/ppc/pxmemctl.c | 311 ++++ private/ntos/nthals/halppc/ppc/pxmemctl.h | 38 + private/ntos/nthals/halppc/ppc/pxmisc.s | 159 ++ private/ntos/nthals/halppc/ppc/pxmp.h | 59 + private/ntos/nthals/halppc/ppc/pxmpic2.h | 309 ++++ private/ntos/nthals/halppc/ppc/pxmpint.c | 323 ++++ private/ntos/nthals/halppc/ppc/pxnatsup.c | 80 + private/ntos/nthals/halppc/ppc/pxnatsup.h | 57 + private/ntos/nthals/halppc/ppc/pxp91.c | 1334 ++++++++++++++++ private/ntos/nthals/halppc/ppc/pxp91.h | 1380 +++++++++++++++++ private/ntos/nthals/halppc/ppc/pxpcibrd.c | 1028 +++++++++++++ private/ntos/nthals/halppc/ppc/pxpcibus.c | 2386 +++++++++++++++++++++++++++++ private/ntos/nthals/halppc/ppc/pxpciint.c | 254 +++ private/ntos/nthals/halppc/ppc/pxpcisup.c | 326 ++++ private/ntos/nthals/halppc/ppc/pxport.c | 848 ++++++++++ private/ntos/nthals/halppc/ppc/pxpower.s | 123 ++ private/ntos/nthals/halppc/ppc/pxproc.c | 212 +++ private/ntos/nthals/halppc/ppc/pxprof.c | 268 ++++ private/ntos/nthals/halppc/ppc/pxreset.s | 455 ++++++ private/ntos/nthals/halppc/ppc/pxreturn.c | 187 +++ private/ntos/nthals/halppc/ppc/pxrtcsup.h | 28 + private/ntos/nthals/halppc/ppc/pxs3.c | 677 ++++++++ private/ntos/nthals/halppc/ppc/pxs3.h | 445 ++++++ private/ntos/nthals/halppc/ppc/pxshadbf.s | 37 + private/ntos/nthals/halppc/ppc/pxsiosup.c | 2218 +++++++++++++++++++++++++++ private/ntos/nthals/halppc/ppc/pxsiosup.h | 219 +++ private/ntos/nthals/halppc/ppc/pxstall.s | 324 ++++ private/ntos/nthals/halppc/ppc/pxsysbus.c | 111 ++ private/ntos/nthals/halppc/ppc/pxsysint.c | 227 +++ private/ntos/nthals/halppc/ppc/pxtime.c | 386 +++++ private/ntos/nthals/halppc/ppc/pxusage.c | 499 ++++++ private/ntos/nthals/halppc/ppc/pxvgaequ.h | 141 ++ private/ntos/nthals/halppc/ppc/pxvm.c | 297 ++++ private/ntos/nthals/halppc/ppc/pxwd.c | 938 ++++++++++++ private/ntos/nthals/halppc/ppc/pxwd.h | 706 +++++++++ private/ntos/nthals/halppc/ppc/txtpalet.h | 97 ++ private/ntos/nthals/halppc/ppc/x86bios.c | 359 +++++ private/ntos/nthals/halppc/sources | 106 ++ 87 files changed, 39012 insertions(+) create mode 100644 private/ntos/nthals/halppc/hal.rc create mode 100644 private/ntos/nthals/halppc/makefile create mode 100644 private/ntos/nthals/halppc/makefile.inc create mode 100644 private/ntos/nthals/halppc/ppc/bbldef.h create mode 100644 private/ntos/nthals/halppc/ppc/bblfont.h create mode 100644 private/ntos/nthals/halppc/ppc/bblrastz.h create mode 100644 private/ntos/nthals/halppc/ppc/bblrmdac.h create mode 100644 private/ntos/nthals/halppc/ppc/bldef.h create mode 100644 private/ntos/nthals/halppc/ppc/blfw.h create mode 100644 private/ntos/nthals/halppc/ppc/blrastz.h create mode 100644 private/ntos/nthals/halppc/ppc/blrmdac.h create mode 100644 private/ntos/nthals/halppc/ppc/fwdebug.h create mode 100644 private/ntos/nthals/halppc/ppc/fwnvr.c create mode 100644 private/ntos/nthals/halppc/ppc/fwnvr.h create mode 100644 private/ntos/nthals/halppc/ppc/fwstatus.h create mode 100644 private/ntos/nthals/halppc/ppc/halp.h create mode 100644 private/ntos/nthals/halppc/ppc/ibmppc.h create mode 100644 private/ntos/nthals/halppc/ppc/pcip.h create mode 100644 private/ntos/nthals/halppc/ppc/prepnvr.h create mode 100644 private/ntos/nthals/halppc/ppc/pxbbl.c create mode 100644 private/ntos/nthals/halppc/ppc/pxbeep.c create mode 100644 private/ntos/nthals/halppc/ppc/pxbl.c create mode 100644 private/ntos/nthals/halppc/ppc/pxbusdat.c create mode 100644 private/ntos/nthals/halppc/ppc/pxcache.s create mode 100644 private/ntos/nthals/halppc/ppc/pxcalstl.c create mode 100644 private/ntos/nthals/halppc/ppc/pxclksup.s create mode 100644 private/ntos/nthals/halppc/ppc/pxclock.c create mode 100644 private/ntos/nthals/halppc/ppc/pxdakota.h create mode 100644 private/ntos/nthals/halppc/ppc/pxdat.c create mode 100644 private/ntos/nthals/halppc/ppc/pxdisp.c create mode 100644 private/ntos/nthals/halppc/ppc/pxdisp.h create mode 100644 private/ntos/nthals/halppc/ppc/pxds1585.h create mode 100644 private/ntos/nthals/halppc/ppc/pxenviro.c create mode 100644 private/ntos/nthals/halppc/ppc/pxfirsup.c create mode 100644 private/ntos/nthals/halppc/ppc/pxfirsup.h create mode 100644 private/ntos/nthals/halppc/ppc/pxflshbf.s create mode 100644 private/ntos/nthals/halppc/ppc/pxflshio.c create mode 100644 private/ntos/nthals/halppc/ppc/pxhalp.h create mode 100644 private/ntos/nthals/halppc/ppc/pxhwsup.c create mode 100644 private/ntos/nthals/halppc/ppc/pxidaho.h create mode 100644 private/ntos/nthals/halppc/ppc/pxidle.c create mode 100644 private/ntos/nthals/halppc/ppc/pxinfo.c create mode 100644 private/ntos/nthals/halppc/ppc/pxinithl.c create mode 100644 private/ntos/nthals/halppc/ppc/pxintmod.c create mode 100644 private/ntos/nthals/halppc/ppc/pxintrpt.c create mode 100644 private/ntos/nthals/halppc/ppc/pxintsup.s create mode 100644 private/ntos/nthals/halppc/ppc/pxirql.c create mode 100644 private/ntos/nthals/halppc/ppc/pxisabus.c create mode 100644 private/ntos/nthals/halppc/ppc/pxmapio.c create mode 100644 private/ntos/nthals/halppc/ppc/pxmemctl.c create mode 100644 private/ntos/nthals/halppc/ppc/pxmemctl.h create mode 100644 private/ntos/nthals/halppc/ppc/pxmisc.s create mode 100644 private/ntos/nthals/halppc/ppc/pxmp.h create mode 100644 private/ntos/nthals/halppc/ppc/pxmpic2.h create mode 100644 private/ntos/nthals/halppc/ppc/pxmpint.c create mode 100644 private/ntos/nthals/halppc/ppc/pxnatsup.c create mode 100644 private/ntos/nthals/halppc/ppc/pxnatsup.h create mode 100644 private/ntos/nthals/halppc/ppc/pxp91.c create mode 100644 private/ntos/nthals/halppc/ppc/pxp91.h create mode 100644 private/ntos/nthals/halppc/ppc/pxpcibrd.c create mode 100644 private/ntos/nthals/halppc/ppc/pxpcibus.c create mode 100644 private/ntos/nthals/halppc/ppc/pxpciint.c create mode 100644 private/ntos/nthals/halppc/ppc/pxpcisup.c create mode 100644 private/ntos/nthals/halppc/ppc/pxport.c create mode 100644 private/ntos/nthals/halppc/ppc/pxpower.s create mode 100644 private/ntos/nthals/halppc/ppc/pxproc.c create mode 100644 private/ntos/nthals/halppc/ppc/pxprof.c create mode 100644 private/ntos/nthals/halppc/ppc/pxreset.s create mode 100644 private/ntos/nthals/halppc/ppc/pxreturn.c create mode 100644 private/ntos/nthals/halppc/ppc/pxrtcsup.h create mode 100644 private/ntos/nthals/halppc/ppc/pxs3.c create mode 100644 private/ntos/nthals/halppc/ppc/pxs3.h create mode 100644 private/ntos/nthals/halppc/ppc/pxshadbf.s create mode 100644 private/ntos/nthals/halppc/ppc/pxsiosup.c create mode 100644 private/ntos/nthals/halppc/ppc/pxsiosup.h create mode 100644 private/ntos/nthals/halppc/ppc/pxstall.s create mode 100644 private/ntos/nthals/halppc/ppc/pxsysbus.c create mode 100644 private/ntos/nthals/halppc/ppc/pxsysint.c create mode 100644 private/ntos/nthals/halppc/ppc/pxtime.c create mode 100644 private/ntos/nthals/halppc/ppc/pxusage.c create mode 100644 private/ntos/nthals/halppc/ppc/pxvgaequ.h create mode 100644 private/ntos/nthals/halppc/ppc/pxvm.c create mode 100644 private/ntos/nthals/halppc/ppc/pxwd.c create mode 100644 private/ntos/nthals/halppc/ppc/pxwd.h create mode 100644 private/ntos/nthals/halppc/ppc/txtpalet.h create mode 100644 private/ntos/nthals/halppc/ppc/x86bios.c create mode 100644 private/ntos/nthals/halppc/sources (limited to 'private/ntos/nthals/halppc') 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 + +#include + +#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 + +// +// 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 + +// +// 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;ix_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; ((iNmiStatus); + 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)&&(iMonID == (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;iwidth, 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; ((iNumber) { + // 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 +#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 +#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 + +// +// 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 + +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; iOemFontFile; + //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 + +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 + +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 +#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 -- cgit v1.2.3