summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halr98mp/mips
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halr98mp/mips
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/nthals/halr98mp/mips')
-rw-r--r--private/ntos/nthals/halr98mp/mips/allstart.c200
-rw-r--r--private/ntos/nthals/halr98mp/mips/cacherr.s196
-rw-r--r--private/ntos/nthals/halr98mp/mips/cirrus.h298
-rw-r--r--private/ntos/nthals/halr98mp/mips/cmdcnst.h105
-rw-r--r--private/ntos/nthals/halr98mp/mips/esmnvram.h687
-rw-r--r--private/ntos/nthals/halr98mp/mips/halp.h708
-rw-r--r--private/ntos/nthals/halr98mp/mips/j4cache.s1056
-rw-r--r--private/ntos/nthals/halr98mp/mips/j4flshbf.s58
-rw-r--r--private/ntos/nthals/halr98mp/mips/j4flshio.c238
-rw-r--r--private/ntos/nthals/halr98mp/mips/j4prof.c362
-rw-r--r--private/ntos/nthals/halr98mp/mips/jazznvr.h164
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxbeep.c131
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxdisp.c3132
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxebsup.c1275
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxenvirv.c818
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxhalp.h99
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxmapio.c153
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxmaptb.c84
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxport.c897
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxreturn.c189
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxsysint.c454
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxtime.c313
-rw-r--r--private/ntos/nthals/halr98mp/mips/jxusage.c497
-rw-r--r--private/ntos/nthals/halr98mp/mips/mipsdat.c144
-rw-r--r--private/ntos/nthals/halr98mp/mips/mode542x.h1302
-rw-r--r--private/ntos/nthals/halr98mp/mips/modeset.h86
-rw-r--r--private/ntos/nthals/halr98mp/mips/pcibrd.c1020
-rw-r--r--private/ntos/nthals/halr98mp/mips/pcip.h214
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98busdt.c1181
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98busdt.h142
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98clock.s471
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98def.h471
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98dspt.c704
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98eif.c801
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98esm.c1026
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98hal.h132
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98hwsup.c4771
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98info.c99
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98int.s522
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98ipint.s176
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98led.c252
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98pci.c289
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98pcibs.c3180
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98pcint.c384
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98reg.h475
-rw-r--r--private/ntos/nthals/halr98mp/mips/tga.h101
-rw-r--r--private/ntos/nthals/halr98mp/mips/x86bios.c2
-rw-r--r--private/ntos/nthals/halr98mp/mips/xxcalstl.c290
-rw-r--r--private/ntos/nthals/halr98mp/mips/xxclock.c131
-rw-r--r--private/ntos/nthals/halr98mp/mips/xxidle.s76
-rw-r--r--private/ntos/nthals/halr98mp/mips/xxinithl.c660
-rw-r--r--private/ntos/nthals/halr98mp/mips/xxinitnt.c556
-rw-r--r--private/ntos/nthals/halr98mp/mips/xxmemory.c184
53 files changed, 31956 insertions, 0 deletions
diff --git a/private/ntos/nthals/halr98mp/mips/allstart.c b/private/ntos/nthals/halr98mp/mips/allstart.c
new file mode 100644
index 000000000..480e6933f
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/allstart.c
@@ -0,0 +1,200 @@
+#pragma comment(exestr, "@(#) allstart.c 1.6 94/12/07 23:10:52 nec")
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ allstart.c
+
+Abstract:
+
+ This module implements the platform specific operations that must be
+ performed after all processors have been started.
+
+--*/
+
+/*
+ * Original source: Build Number 1.807
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 '94.10/14 T.Samezima
+ * Add HalpConnectInt1Interrupt()
+ * valiable HalpInt1Affinity.
+ * Call HalpConnectInt1Interrupt()
+ * Del Call HalpCreateEisaStructures()
+ *
+ * S002 '94.10/18 T.Samezima
+ * Chg Enable interrupt on MKR register only exist device,
+ *
+ * S003 '94.10/22 T.Samezima
+ * Chg Issue restart timer interrupt on CPU#0 to all CPU
+ *
+ * S004 '94.12/07 T.Samezima
+ * Del warning
+ *
+ */
+
+
+#include "halp.h"
+
+// S001 vvv
+//
+// Define INT1 interrupt affinity.
+//
+
+KAFFINITY HalpInt1Affinity;
+
+BOOLEAN // S004
+HalpConnectInt1Interrupt(
+ VOID
+ );
+// S001 ^^^
+
+
+BOOLEAN
+HalAllProcessorsStarted (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function executes platform specific operations that must be
+ performed after all processors have been started. It is called
+ for each processor in the host configuration.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+ // S001, S003 vvv
+ // Restart all timer interrupt. because, generate interrupt for same time
+ //
+
+ if (PCR->Number == 0) {
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TCIR.Long,
+ TCIR_ALL_CLOCK_RESTART); // S007
+ }
+ // S001, S003 ^^^
+
+ //
+ // If the number of processors in the host configuration is one,
+ // then connect EISA interrupts to that processor zero. Otherwise,
+ // connect EISA interrupts to processor one.
+ //
+
+ if (**((PULONG *)(&KeNumberProcessors)) == 1) {
+ return HalpConnectInt1Interrupt(); // S001
+
+ } else if (PCR->Number == 1) {
+ return HalpConnectInt1Interrupt(); // S001
+
+ } else {
+ return TRUE;
+ }
+}
+
+// S001 vvv
+ULONG AII1Mask;
+ULONG AII2Mask;
+
+BOOLEAN // S004
+HalpConnectInt1Interrupt(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function connect int1 interrupt on execution processor.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ return TRUE.
+
+--*/
+
+{
+
+ ULONG number;
+ ULONG pmcRegisterAddr;
+ ULONG pmcRegisterUpperPart;
+ ULONG pmcRegisterLowerPart;
+
+ //
+ // Get CPU number.
+ //
+
+ number = PCR->Number;
+
+ //
+ // Set route for notice of interrupt
+ //
+
+ AII1Mask = AII_INIT_DATA >> number;
+ AII2Mask = ( ((AII_INIT_DATA >> number) & 0xffff0000)
+ | (AII_INIT_DATA & 0x0000ffff) );
+
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII1.Long,
+ AII1Mask );
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII2.Long,
+ AII2Mask );
+
+ //
+ // Enable INT1 interrupt on PMC
+ //
+
+ pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR );
+ HalpReadLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+ pmcRegisterLowerPart = ( pmcRegisterLowerPart | MKR_INT1_DEVICE_ENABLE_LOW ); // S002
+ HalpWriteLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ PCR->ReservedVectors |= (1 << INT1_LEVEL);
+
+ //
+ // Set Int1 interrupt affinity.
+ //
+
+ HalpInt1Affinity = PCR->SetMember;
+
+ //
+ // Initialize the interrupt dispatcher for I/O interrupts.
+ //
+
+ PCR->InterruptRoutine[INT1_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt1Dispatch;
+
+ //
+ // Initialize EISA bus interrupts.
+ //
+
+ HalpCreateEisaStructures();
+
+ //
+ // Initialize PCI bus interrupts.
+ //
+
+ return HalpCreatePciStructures ();
+}
+// S001 ^^^
diff --git a/private/ntos/nthals/halr98mp/mips/cacherr.s b/private/ntos/nthals/halr98mp/mips/cacherr.s
new file mode 100644
index 000000000..95f59c0cd
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/cacherr.s
@@ -0,0 +1,196 @@
+// "@(#) NEC cacherr.s 1.2 94/10/17 11:02:44"
+// TITLE("Cache Error Handling")
+//++
+//
+// Copyright (c) 1993-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// cacherr.s
+//
+// Abstract:
+//
+// This module implements cache error handling. It is entered in KSEG1
+// directly from the cache error vector wiht ERL set in the processor
+// state.
+//
+// N.B. All the code in this routine MUST run in KSEG1 and reference
+// data only in KSEG1 until which time as any cache errors have
+// been corrected.
+//
+// N.B. This routine is NOT COMPLETE. All cache errors result in a
+// soft reset.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+//
+// Define local save area for register state.
+//
+
+ .data
+SavedAt:.space 4 // saved integer register at - a3
+SavedV0:.space 4 //
+SavedV1:.space 4 //
+SavedA0:.space 4 //
+SavedA1:.space 4 //
+SavedA2:.space 4 //
+SavedA3:.space 4 //
+
+ SBTTL("Cache Error Handling")
+//++
+//
+// VOID
+// HalpCacheErrorRoutine (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is entered from the cache error vector executing
+// in KSEG1. If the error is a single bit ECC error in the second
+// level data cache or the error is in the primary instruction cache,
+// then the error is corrected and execution is continued. Otherwise,
+// a fatal system error has occured and control is transfered to the
+// soft reset vector.
+//
+// N.B. No state has been saved when this routine is entered.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpCacheErrorRoutine)
+
+//
+// Save volatile registers needed to fix cache error.
+//
+
+ .set noreorder
+ .set noat
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ sw AT,0(k0) // save registers AT - a3
+ sw v0,4(k0) //
+ sw v1,8(k0) //
+ sw a0,12(k0) //
+ sw a1,16(k0) //
+ sw a2,20(k0) //
+
+//
+// Get the current processor state and cache error register, and check
+// if the error can be corrected.
+//
+
+ mfc0 v0,psr // get current processor state
+ mfc0 v1,cacheerr // get cache error state
+ .set at
+ .set reorder
+
+//
+// ****** temp ******
+//
+// The following code is temporary and will be removed when full cache
+// error support is included.
+//
+// ****** temp ******
+//
+
+ b SoftReset // ****** all error soft rest
+
+//
+// If the EXL bit is set in the processor state, then the error is not
+// recoverable because the EXL bit may be erroneously set (errata) and
+// it cannot be determined whether is should or should not be set, e.g.,
+// the exact addresses ranges over which EXL might be correctly set are
+// not verifiable. Also, k0 and k1 are destroyed before they are saved
+// and are used by the exception handling code (there is no way to save
+// a register in noncached memory wihtout the use of a register).
+//
+
+ sll a0,v0,31 - PSR_EXL // shift EXL bit in sign
+ bltz a0,SoftReset // if ltz, error not correctable
+
+//
+// If the error occured on the SysAd bus, then the error is not correctable.
+//
+
+ sll a0,v1,31 - CACHEERR_EE // shift EE bit into sign
+ bltz a0,SoftReset // if ltz, error not correctable
+
+//
+// Determine whether the error is in the instruction or data cache.
+//
+
+ sll a0,v1,31 - CACHEERR_ER // shift ER bit into sign
+ bgez a0,IcacheError // if gez, instruction cache error
+
+//
+// The error occured in the data cache.
+//
+// If the error is a data error in the primary cache, then the error
+// is not correctable since the cache line dirty bit is included in
+// the parity calculation and therefore may be wrong.
+//
+
+DcacheError: //
+ sll a0,v1,31 - CACHEERR_EC // shift EC bit into sign
+ bgez a0,SoftReset // if gez, error in primary cache
+ b ExitError // exit error
+
+//
+// The error occured in the instruction cache.
+//
+// If the error occured in the secondary data cache, then the error is not
+// correctable since there is not secondary instruciton cache.
+//
+
+IcacheError: //
+ sll a0,v1,31 - CACHEERR_EC // shift EC bit into sign
+ bltz a0,SoftReset // if ltz, error in secondary cache
+
+//
+// The cache error has been corrected - restore register state and continue
+// execution.
+//
+
+ExitError: //
+
+ .set noreorder
+ .set noat
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ lw AT,0(k0) // restore registers AT - a3
+ lw v0,4(k0) //
+ lw v1,8(k0) //
+ lw a0,12(k0) //
+ lw a1,16(k0) //
+ lw a2,20(k0) //
+ eret //
+ .set at
+ .set reorder
+
+//
+// Cache error cannot be corrected - transfer control to soft reset vector.
+//
+
+SoftReset: //
+ la k0,SOFT_RESET_VECTOR // get address of soft reset vector
+ j k0 // perform a soft reset
+
+ .end HalpCacheErrorRoutine
diff --git a/private/ntos/nthals/halr98mp/mips/cirrus.h b/private/ntos/nthals/halr98mp/mips/cirrus.h
new file mode 100644
index 000000000..9f9846aaf
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/cirrus.h
@@ -0,0 +1,298 @@
+#ident "@(#) NEC cirrus.h 1.2 94/11/21 13:58:39"
+/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.7 94/02/03 18:58:17" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.6 94/01/28 11:50:02" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) cirrus.h 1.4 93/10/29 12:25:02" ) */
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cirrus.h
+
+Abstract:
+
+ This module contains the definitions for the code that implements the
+ Cirrus Logic VGA 6410/6420/542x device driver.
+
+Environment:
+
+ Kernel mode
+
+Notes:
+
+ This module based on Cirrus Minport Driver. And modify for R96 MIPS
+ R4400 HAL Cirrus display initialize.
+
+Revision History:
+
+
+--*/
+
+/*
+ * M001 1993.19.28 A. Kuriyama @ oa2
+ *
+ * - Modify for R96 MIPS R4400 HAL
+ *
+ * Delete : Miniport Driver Interface
+ *
+ * M002 1994.2.2 A. Kuriyama @ oa2
+ * - Bug fix
+ *
+ * Modify : Video Memory Physical Address
+ *
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400 *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ * L002 1993.10.21 Kuroki
+ *
+ * - Warniing clear
+ *
+ ***************************************************************
+ *
+ * S001 1994.06.06 T.Samezima
+ *
+ * - Modify for R98 MIPS R4400
+ *
+ * Change : LA_MASK
+ *
+ * S002 '94.11/21 T.Samezima
+ * Chg invalid S001
+ *
+ */
+
+//
+// Change Ushort to Uchar, because R96 is mips machine.
+//
+
+
+//
+// Base address of VGA memory range. Also used as base address of VGA
+// memory when loading a font, which is done with the VGA mapped at A0000.
+//
+
+/* START L001 */
+
+/* START M002 */
+#define LA_MASK 0xe // S001, S002
+/* END M002 */
+#define MEM_VGA (LA_MASK << 20)
+#define MEM_VGA_SIZE 0x100000
+
+/* END L001 */
+
+//
+// Port definitions for filling the ACCSES_RANGES structure in the miniport
+// information, defines the range of I/O ports the VGA spans.
+// There is a break in the IO ports - a few ports are used for the parallel
+// port. Those cannot be defined in the ACCESS_RANGE, but are still mapped
+// so all VGA ports are in one address range.
+//
+
+#define VGA_BASE_IO_PORT 0x000003B0
+#define VGA_START_BREAK_PORT 0x000003BB
+#define VGA_END_BREAK_PORT 0x000003C0
+#define VGA_MAX_IO_PORT 0x000003DF
+
+//
+// VGA port-related definitions.
+//
+
+//
+// VGA register definitions
+//
+ // ports in monochrome mode
+#define CRTC_ADDRESS_PORT_MONO 0x0004 // CRT Controller Address and
+#define CRTC_DATA_PORT_MONO 0x0005 // Data registers in mono mode
+#define FEAT_CTRL_WRITE_PORT_MONO 0x000A // Feature Control write port
+ // in mono mode
+#define INPUT_STATUS_1_MONO 0x000A // Input Status 1 register read
+ // port in mono mode
+#define ATT_INITIALIZE_PORT_MONO INPUT_STATUS_1_MONO
+ // Register to read to reset
+ // Attribute Controller index/data
+#define ATT_ADDRESS_PORT 0x0010 // Attribute Controller Address and
+#define ATT_DATA_WRITE_PORT 0x0010 // Data registers share one port
+ // for writes, but only Address is
+ // readable at 0x010
+#define ATT_DATA_READ_PORT 0x0011 // Attribute Controller Data reg is
+ // readable here
+#define MISC_OUTPUT_REG_WRITE_PORT 0x0012 // Miscellaneous Output reg write
+ // port
+#define INPUT_STATUS_0_PORT 0x0012 // Input Status 0 register read
+ // port
+#define VIDEO_SUBSYSTEM_ENABLE_PORT 0x0013 // Bit 0 enables/disables the
+ // entire VGA subsystem
+#define SEQ_ADDRESS_PORT 0x0014 // Sequence Controller Address and
+#define SEQ_DATA_PORT 0x0015 // Data registers
+#define DAC_PIXEL_MASK_PORT 0x0016 // DAC pixel mask reg
+#define DAC_ADDRESS_READ_PORT 0x0017 // DAC register read index reg,
+ // write-only
+#define DAC_STATE_PORT 0x0017 // DAC state (read/write),
+ // read-only
+#define DAC_ADDRESS_WRITE_PORT 0x0018 // DAC register write index reg
+#define DAC_DATA_REG_PORT 0x0019 // DAC data transfer reg
+#define FEAT_CTRL_READ_PORT 0x001A // Feature Control read port
+#define MISC_OUTPUT_REG_READ_PORT 0x001C // Miscellaneous Output reg read
+ // port
+#define GRAPH_ADDRESS_PORT 0x001E // Graphics Controller Address
+#define GRAPH_DATA_PORT 0x001F // and Data registers
+
+ // ports in color mode
+#define CRTC_ADDRESS_PORT_COLOR 0x0024 // CRT Controller Address and
+#define CRTC_DATA_PORT_COLOR 0x0025 // Data registers in color mode
+#define FEAT_CTRL_WRITE_PORT_COLOR 0x002A // Feature Control write port
+#define INPUT_STATUS_1_COLOR 0x002A // Input Status 1 register read
+ // port in color mode
+#define ATT_INITIALIZE_PORT_COLOR INPUT_STATUS_1_COLOR
+ // Register to read to reset
+ // Attribute Controller index/data
+ // toggle in color mode
+
+//
+// Offsets in HardwareStateHeader->PortValue[] of save areas for non-indexed
+// VGA registers.
+//
+
+#define CRTC_ADDRESS_MONO_OFFSET 0x04
+#define FEAT_CTRL_WRITE_MONO_OFFSET 0x0A
+#define ATT_ADDRESS_OFFSET 0x10
+#define MISC_OUTPUT_REG_WRITE_OFFSET 0x12
+#define VIDEO_SUBSYSTEM_ENABLE_OFFSET 0x13
+#define SEQ_ADDRESS_OFFSET 0x14
+#define DAC_PIXEL_MASK_OFFSET 0x16
+#define DAC_STATE_OFFSET 0x17
+#define DAC_ADDRESS_WRITE_OFFSET 0x18
+#define GRAPH_ADDRESS_OFFSET 0x1E
+#define CRTC_ADDRESS_COLOR_OFFSET 0x24
+#define FEAT_CTRL_WRITE_COLOR_OFFSET 0x2A
+
+// toggle in color mode
+//
+// VGA indexed register indexes.
+//
+
+// CL-GD542x specific registers:
+//
+#define IND_CL_EXTS_ENB 0x06 // index in Sequencer to enable exts
+#define IND_CL_SCRATCH_PAD 0x0A // index in Seq of POST scratch pad
+#define IND_CL_ID_REG 0x27 // index in CRTC of ID Register
+//
+#define IND_CURSOR_START 0x0A // index in CRTC of the Cursor Start
+#define IND_CURSOR_END 0x0B // and End registers
+#define IND_CURSOR_HIGH_LOC 0x0E // index in CRTC of the Cursor Location
+#define IND_CURSOR_LOW_LOC 0x0F // High and Low Registers
+#define IND_VSYNC_END 0x11 // index in CRTC of the Vertical Sync
+ // End register, which has the bit
+ // that protects/unprotects CRTC
+ // index registers 0-7
+#define IND_SET_RESET_ENABLE 0x01 // index of Set/Reset Enable reg in GC
+#define IND_DATA_ROTATE 0x03 // index of Data Rotate reg in GC
+#define IND_READ_MAP 0x04 // index of Read Map reg in Graph Ctlr
+#define IND_GRAPH_MODE 0x05 // index of Mode reg in Graph Ctlr
+#define IND_GRAPH_MISC 0x06 // index of Misc reg in Graph Ctlr
+#define IND_BIT_MASK 0x08 // index of Bit Mask reg in Graph Ctlr
+#define IND_SYNC_RESET 0x00 // index of Sync Reset reg in Seq
+#define IND_MAP_MASK 0x02 // index of Map Mask in Sequencer
+#define IND_MEMORY_MODE 0x04 // index of Memory Mode reg in Seq
+#define IND_CRTC_PROTECT 0x11 // index of reg containing regs 0-7 in
+ // CRTC
+#define IND_CRTC_COMPAT 0x34 // index of CRTC Compatibility reg
+ // in CRTC
+#define START_SYNC_RESET_VALUE 0x01 // value for Sync Reset reg to start
+ // synchronous reset
+#define END_SYNC_RESET_VALUE 0x03 // value for Sync Reset reg to end
+ // synchronous reset
+
+//
+// Values for Attribute Controller Index register to turn video off
+// and on, by setting bit 5 to 0 (off) or 1 (on).
+//
+
+#define VIDEO_DISABLE 0
+#define VIDEO_ENABLE 0x20
+
+// Masks to keep only the significant bits of the Graphics Controller and
+// Sequencer Address registers. Masking is necessary because some VGAs, such
+// as S3-based ones, don't return unused bits set to 0, and some SVGAs use
+// these bits if extensions are enabled.
+//
+
+#define GRAPH_ADDR_MASK 0x0F
+#define SEQ_ADDR_MASK 0x07
+
+//
+// Mask used to toggle Chain4 bit in the Sequencer's Memory Mode register.
+//
+
+#define CHAIN4_MASK 0x08
+
+//
+// Value written to the Read Map register when identifying the existence of
+// a VGA in VgaInitialize. This value must be different from the final test
+// value written to the Bit Mask in that routine.
+//
+
+#define READ_MAP_TEST_SETTING 0x03
+
+//
+// Default text mode setting for various registers, used to restore their
+// states if VGA detection fails after they've been modified.
+//
+
+#define MEMORY_MODE_TEXT_DEFAULT 0x02
+#define BIT_MASK_DEFAULT 0xFF
+#define READ_MAP_DEFAULT 0x00
+
+
+//
+// Palette-related info.
+//
+
+//
+// Highest valid DAC color register index.
+//
+
+#define VIDEO_MAX_COLOR_REGISTER 0xFF
+
+//
+// Indices for type of memory mapping; used in ModesVGA[], must match
+// MemoryMap[].
+//
+
+typedef enum _VIDEO_MEMORY_MAP {
+ MemMap_Mono,
+ MemMap_CGA,
+ MemMap_VGA
+} VIDEO_MEMORY_MAP, *PVIDEO_MEMORY_MAP;
+
+//
+// For a mode, the type of banking supported. Controls the information
+// returned in VIDEO_BANK_SELECT. PlanarHCBanking includes NormalBanking.
+//
+
+typedef enum _BANK_TYPE {
+ NoBanking = 0,
+ NormalBanking,
+ PlanarHCBanking
+} BANK_TYPE, *PBANK_TYPE;
+
+#define CL6410 0x0001
+#define CL6420 0x0002
+#define CL542x 0x0004
+
+// bitfields for the DisplayType
+#define crt 0x0001
+#define panel 0x0002
+#define simulscan 0x0004 // this means both, but is unused for now.
diff --git a/private/ntos/nthals/halr98mp/mips/cmdcnst.h b/private/ntos/nthals/halr98mp/mips/cmdcnst.h
new file mode 100644
index 000000000..ea2bba221
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/cmdcnst.h
@@ -0,0 +1,105 @@
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ cmdcnst.h
+
+Abstract:
+
+ This is the command string interpreter definitions
+
+Environment:
+
+ kernel mode only
+
+Notes:
+
+ This module is same file on Cirrus Minport Driver.
+
+Revision History:
+
+--*/
+
+//--------------------------------------------------------------------------
+// Definition of the set/clear mode command language.
+//
+// Each command is composed of a major portion and a minor portion.
+// The major portion of a command can be found in the most significant
+// nibble of a command byte, while the minor portion is in the least
+// significant portion of a command byte.
+//
+// maj minor Description
+// ---- ----- --------------------------------------------
+// 00 End of data
+//
+// 10 in and out type commands as described by flags
+// flags:
+//
+// xxxx
+// ||||
+// |||+-------- unused
+// ||+--------- 0/1 single/multiple values to output (in's are always
+// |+---------- 0/1 8/16 bit operation single)
+// +----------- 0/1 out/in instruction
+//
+// Outs
+// ----------------------------------------------
+// 0 reg:W val:B
+// 2 reg:W cnt:W val1:B val2:B...valN:B
+// 4 reg:W val:W
+// 6 reg:W cnt:W val1:W val2:W...valN:W
+//
+// Ins
+// ----------------------------------------------
+// 8 reg:W
+// a reg:W cnt:W
+// c reg:W
+// e reg:W cnt:W
+//
+// 20 Special purpose outs
+// 00 do indexed outs for seq, crtc, and gdc
+// indexreg:W cnt:B startindex:B val1:B val2:B...valN:B
+// 01 do indexed outs for atc
+// index-data_reg:W cnt:B startindex:B val1:B val2:B...valN:B
+// 02 do masked outs
+// indexreg:W andmask:B xormask:B
+//
+// F0 Nop
+//
+//---------------------------------------------------------------------------
+
+// some useful equates - major commands
+
+#define EOD 0x000 // end of data
+#define INOUT 0x010 // do ins or outs
+#define METAOUT 0x020 // do special types of outs
+#define NCMD 0x0f0 // Nop command
+
+
+// flags for INOUT major command
+
+//#define UNUSED 0x01 // reserved
+#define MULTI 0x02 // multiple or single outs
+#define BW 0x04 // byte/word size of operation
+#define IO 0x08 // out/in instruction
+
+// minor commands for metout
+
+#define INDXOUT 0x00 // do indexed outs
+#define ATCOUT 0x01 // do indexed outs for atc
+#define MASKOUT 0x02 // do masked outs using and-xor masks
+
+
+// composite inout type commands
+
+#define OB (INOUT) // output 8 bit value
+#define OBM (INOUT+MULTI) // output multiple bytes
+#define OW (INOUT+BW) // output single word value
+#define OWM (INOUT+BW+MULTI) // output multiple words
+
+#define IB (INOUT+IO) // input byte
+#define IBM (INOUT+IO+MULTI) // input multiple bytes
+#define IW (INOUT+IO+BW) // input word
+#define IWM (INOUT+IO+BW+MULTI) // input multiple words
diff --git a/private/ntos/nthals/halr98mp/mips/esmnvram.h b/private/ntos/nthals/halr98mp/mips/esmnvram.h
new file mode 100644
index 000000000..313bec380
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/esmnvram.h
@@ -0,0 +1,687 @@
+#ident "@(#) NEC esmnvram.h 1.1 95/02/20 16:50:43"
+/****************************************************************
+ ******* Copyright (C) 1994 NEC Corporation *******
+ ****************************************************************/
+
+/*******
+
+ File Name:
+
+ envram.h
+
+ Abstract:
+
+ This module contains the definitions for the extended NVRAM.
+
+ Author:
+
+ Takehiro Ueda (tueda@oa2.kb.nec.co.jp) 12/22/1994
+
+ Modification History:
+
+ - M000 12/22/94 -
+ created.
+
+*******/
+
+
+
+/*******************************************************************************
+ ******** NVRAM¡Ê8K¥Ð¥¤¥È¡Ë¤ÎÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤ò°Ê²¼¤Ëµ­½Ò¤¹¤ë¡£ ********
+ *******************************************************************************
+ *
+ * S001 11/22/94
+ * ¥ì¥³¡¼¥É¤ÎÍ­¸ú/̵¸ú¥Õ¥é¥°¡¢Check̤/ºÑ¥Õ¥é¥°¤ò³Æ¥ì¥³¡¼¥É¤ÎÀèƬ¤Ë¤ª¤¯¤«
+ * ¤Þ¤È¤á¤Æ¥ì¥³¡¼¥É¥ê¡¼¥¸¥ç¥ó¤ÎÀèƬ¤Ë¤ª¤¯¤«¤Ç¡¢¥ì¥³¡¼¥É¤Î½èÍýÊýË¡¤¬ÊѤï¤Ã¤Æ
+ * ¤¯¤ë¡£¸å¼Ô¤Ï¥é¥ó¥À¥à¥¢¥¯¥»¥¹¡¢Á°¼Ô¤Ï¥·¡¼¥±¥ó¥·¥ã¥ë¥¢¥¯¥»¥¹¤Ë¤à¤¯¡£
+ * º£²ó¤ÏÁ°¼Ô¤òºÎÍÑ¡£
+ *
+ * ¹Ô¤ÎÀèƬ¤Ë¤¢¤ë¿ô»ú¤Ï³ä¤êÅö¤Æ¤ë¥Ð¥¤¥È¿ô¤ò¤¢¤é¤ï¤¹¡£
+ *
+ * ËÜ»ÅÍͤˤ·¤¿¤¬¤Ã¤Æ¹½Â¤ÂΤòºîÀ®Í½Äê¡£
+ *
+ * S002 11/26/94
+ * ³ÆÎΰè¡ÊECC´ØÏ¢¡¢¥Ñ¥Ë¥Ã¥¯¾ðÊó´ØÏ¢¡¢¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°´ØÏ¢¡¢etc.¡Ë
+ * ¤ÎÀèƬ¤Î¥Ø¥Ã¥ÀÉô¤òÁ´¤ÆNVRAM¤ÎÀèƬ¤Ë°Ü¤¹¡£NVRAM¤ÎÀèƬ¤Ë¤¢¤ë¥Ø¥Ã¥ÀÆâ¤Ë
+ * ³ÆÎΰè¤Î¥ì¥³¡¼¥É¤òľÀÜ¥¢¥¯¥»¥¹¤¹¤ë¤¿¤á¤Î¥ª¥Õ¥»¥Ã¥È¤ò¤â¤Ä¤è¤¦¤Ë¤¹¤ë¡£
+ *
+ * NVRAM¤Î¥¢¥¯¥»¥¹»þ¤Ë¤Ï256¥Ð¥¤¥Èñ°Ì¤Ç¥Ð¥ó¥¯Àڤ괹¤¨¤¬¤ª¤³¤Ê¤ï¤ì¤ë¤¿¤á
+ * ³Æ¥Ç¡¼¥¿¡Ê256¥Ð¥¤¥ÈĹ°Ê²¼¤Î¤â¤Î¡Ë¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤ò¤Þ¤¿¤¬¤é¤Ê¤¤¤è¤¦
+ * ¤ËÇÛθ¡£³ÆÎΰè¡ÊECC´ØÏ¢¡¢¥Ñ¥Ë¥Ã¥¯¾ðÊó´ØÏ¢¡¢etc.¡Ë¤ÎÀèƬ¤¬É¬¤º256¥Ð¥¤¥È
+ * ¥Ð¥¦¥ó¥À¥ê¤«¤é³«»Ï¤µ¤ì¤ë¤è¤¦¤Ë¤¹¤ë¡£
+ *
+ * ECC¥¨¥é¡¼¥í¥°Æâ¤ÎSIMMÆÃÄê²½¾ðÊó¤ò2¥Ð¥¤¥È¤«¤é1¥Ð¥¤¥È¤ØÊѹ¹¡£
+ *
+ * ¡É¥ª¥Õ¥»¥Ã¥È ¡É¤Ï¤¹¤Ù¤ÆNVRAM¤ÎÀèƬ¤«¤é¤Î¥ª¥Õ¥»¥Ã¥È¡£
+ *
+ * S003 12/13/94
+ * NW¥¨¡¼¥¸¥§¥ó¥È¤È¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤ò¶¦Ä̲½¤¹¤ë¤¿¤áÀèƬ512¥Ð¥¤¥È¤ò
+ * ¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤È¤·¡¢¥Õ¥©¡¼¥Þ¥Ã¥È¤òNW¥¨¡¼¥¸¥§¥ó¥È¤ÈÅý°ì¤¹¤ë¡£
+ *
+ * STEP1¤Ç¤Ï¥á¥â¥ê½ÌÂà¤ò¹Ô¤ï¤Ê¤¤¤¿¤áËÜ¥¨¥ê¥¢¤Ï»ÈÍѤ·¤Ê¤¤¡£
+ * ËÜ¥á¥â¥ê¥¨¥é¡¼¥¨¥ê¥¢¤ÏNW¥¨¡¼¥¸¥§¥ó¥È¤È¤Î¶¦Ä̲½¤Î¤¿¤á¤Ë¿·¤¿¤ËÀߤ±¤ë
+ * ¤â¤Î¤Ç¤¢¤ê¡¢°ÊÁ°¤«¤é¤ÎECC¥¨¥é¡¼¾ðÊóÎΰè¤Ï¤½¤Î¤Þ¤Þ»Ä¤ë¡£
+ *
+ * 512¥Ð¥¤¥È¤Î¥¨¥ê¥¢¤òÀèƬ¤ËÀߤ±¤ë¤¿¤á¡¢°ÊÁ°¤«¤é¤Î¤½¤Î¾Á´¤Æ¤Î¾ðÊóÎΰè¤Ï
+ * 512¥Ð¥¤¥È¥ª¥Õ¥»¥Ã¥È¤¬Â礭¤¯¤Ê¤ë¤³¤È¤Ë¤Ê¤ë¡£
+ *
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È2¥Ð¥¤¥È¤òÄɲá£
+ *
+ * ¥ª¥Õ¥»¥Ã¥È¤ÎºÆ·×»»¡£
+ *
+ * S004 12/14/94
+ * ¹½Â¤ÂκîÀ®¡£
+ *
+ * ¡Ç¥Ñ¥Ë¥Ã¥¯ ¡Ç¤ò¡Ç¥¹¥È¥Ã¥×¥¨¥é¡¼ ¡Ç¤ËÊѹ¹¡£
+ *
+ * S005 12/23/94
+ * 4byte alignment¤Ë¤½¤Ê¤¨¤Æ¥Ñ¥Ç¥£¥ó¥°¤ò°ìÉôÊѹ¹¡£
+ *
+ * ¥¹¥È¥Ã¥×¥¨¥é¡¼¤Î¥Õ¥é¥°¤Î2¥Ó¥Ã¥È¤Ë¿·¤¿¤ËÄêµÁÄɲá£
+ *
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤òNVRAM¥Ø¥Ã¥À¤Ë¤È¤ê¤³¤à¡£
+ * ¤³¤ì¤Ë¤È¤â¤Ê¤¤¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È¤ÏÉÔÍפȤʤ뤿¤á
+ * 2¥Ð¥¤¥Èʬ̤»ÈÍѤȤ¹¤ë¡£
+ *
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ¤Ë¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤òÄɲá£ÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤Î̵ͭ¤ò
+ * ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤È¥Õ¥é¥°¤Ç¥Á¥§¥Ã¥¯¤¹¤ë¤è¤¦¤Ë¤¹¤ë¡£¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼¤Ï
+ * 0xFF651026¤È¤¹¤ë¡£
+ *
+ * ¡Ç¥¹¥È¥Ã¥×¥¨¥é¡¼ ¡Ç¤ò¡Ç¥·¥¹¥Æ¥à¥¨¥é¡¼ ¡Ç¤ËÊѹ¹¡£
+ *
+ * S006 12/27/94
+ * #pragma pack() ¤òÄɲÃ
+ *
+ * char reserved[49] ¤ò char reserved[49] ¤Ë½¤Àµ¡£ËÜÊѹ¹¤Ïharmless¤Ç¤¢¤ë
+ * ¤È¿®¤¸¤ë... (^_^;
+ *
+ * unsigned short offset_ecc2err ¤ò offset_2biterr¤Ë½¤Àµ¡£ËÜÊѹ¹¤Ï
+ * harmless¤Ç¤¢¤ë¤È¿®¤¸¤ë... (^_^;
+ *
+ ******************************************************************************
+
+
+ ###################
+ # NVRAM¥Ø¥Ã¥ÀÉô #
+ ###################
+
+ ######################################################
+ # F/WÍÑ¥á¥â¥ê¡¼¥¨¥é¡¼¥¨¥ê¥¢ (NW¥¨¡¼¥¸¥§¥ó¥È¤È¶¦ÄÌ) #
+ ######################################################
+
+ 512 ¥á¥â¥ê¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(2¥Ð¥¤¥È) ¡ß 256
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ ¡¡¡¡1 ¥¹¥Æ¡¼¥¿¥¹ 0:Àµ¾ï 1:°Û¾ï(2bit¥¨¥é¡¼Í­Ìµ)
+ 1 1bit¥¨¥é¡¼¥«¥¦¥ó¥È
+
+¡¡¡¡ ######################
+ # Á´ÂΤ˴ؤ¹¤ë¤â¤Î #
+ ######################
+
+ 1 NVRAM¤Î¾õÂÖ¤ò¤¢¤é¤ï¤¹¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 NVRAMÁ´ÂÎÍ­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡1 ÏÀÍý¥Õ¥©¡¼¥Þ¥Ã¥È¤Î̵ͭ 0:̵ 1:Í­
+ ¡¡¡¡2 READ-ONLY 0:NO 1:YES
+ ¡¡¡¡3 LOCK 0:NO 1:YES
+ ¡¡¡¡4 [reserved]
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 14 NVRAM¤¬¥Õ¥©¡¼¥Þ¥Ã¥È¤µ¤ì¤¿¥¿¥¤¥à¥¹¥¿¥ó¥×
+
+ 3 [ reserved ]
+
+¡¡¡¡ ###############################
+ # ALIVE¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ###############################
+
+ 2 ALIVE¾ðÊóÎΰè¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ #######################################
+ # ECC1bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ #######################################
+
+ 2 ECC 1bit¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ECC 1bit¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ECC 1bit¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô
+ 2 ECC 1bit¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ 4 °ìÈֺǸå¤ÎECC1bit¥¨¥é¡¼»þ¤Î¥ê¡¼¥É¥Ç¡¼¥¿
+ ¡¡ 8 ECC 1bit¥¨¥é¡¼¥«¥¦¥ó¥È ¡ß ¥á¥â¥ê¥°¥ë¡¼¥×¿ô8
+
+¡¡¡¡ #######################################
+ # ECC2bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ #######################################
+
+ 2 ECC 2bit¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ECC 2bit¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ECC 2bit¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô
+ 2 ECC 2bit¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ 4 °ìÈֺǸå¤ÎECCÊ£¿ôbit¥¨¥é¡¼»þ¤Î¥ê¡¼¥É¥Ç¡¼¥¿
+ 4 SIMM¸ò´¹¥Õ¥é¥° ¡ß ¥á¥â¥ê¥°¥ë¡¼¥×¿ô4
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 ¥°¥ë¡¼¥×NÆâSIMM #0 (N=1¡Á4) 0:OK 1:NG(Í׸ò´¹)
+ ¡¡¡¡1 ¥°¥ë¡¼¥×NÆâSIMM #1 ¢¬
+ ¡¡¡¡2 ¥°¥ë¡¼¥×NÆâSIMM #2¡¡¡¡ ¢¬
+ ¡¡¡¡3 ¥°¥ë¡¼¥×NÆâSIMM #3¡¡¡¡ ¢¬
+ ¡¡¡¡4 [reserved]
+ ¡¡¡¡5 ¢¬
+ ¡¡¡¡6 ¢¬
+ ¡¡¡¡7¡¡¡¡¡¡¢¬
+ 4 [reserved]
+
+¡¡¡¡ ########################################
+ ¡¡¡¡# ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ¡¡¡¡########################################
+
+ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É¿ô
+ 2 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ ############################################
+ ¡¡¡¡# ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Îΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ############################################
+
+ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+ ¡¡ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°1¥ì¥³¡¼¥É¥µ¥¤¥º
+ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¥ì¥³¡¼¥É¿ô
+ 2 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¤ò°ìÈֺǸå¤ËÅÐÏ¿¤·¤¿¥ì¥³¡¼¥É¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ ##################################
+ ¡¡¡¡# ¤·¤­¤¤Ã;ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ##################################
+
+ 2 ¤·¤­¤¤Ã;ðÊóÉô¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+¡¡¡¡ ##############################
+ ¡¡¡¡# ¥ê¥¶¡¼¥ÖÎΰè¤Ë´Ø¤¹¤ë¤â¤Î #
+ ##############################
+
+ 2 ¥ê¥¶¡¼¥ÖÎΰè¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È
+
+
+ ########################
+ # ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ #
+ ########################
+
+¡¡¡¡¡¡¡¡ 1 ¥·¥¹¥Æ¥à¤Î¾õÂÖ¤ò¤¢¤é¤ï¤¹¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ 0 [reserved]
+ ¡¡¡¡1 ¡¡¡¡¢¬
+ ¡¡¡¡2 ¡¡¡¡¢¬
+ ¡¡¡¡3 ¡¡¡¡¢¬
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 3 [reserved]
+ 32 ¥·¥¹¥Æ¥à¤Î¾ðÊó¡Ê¥·¥¹¥Æ¥à̾¡Ë
+ 4 ¥Þ¥·¥ó¥·¥ê¥¢¥ë¥Ê¥ó¥Ð¡¼
+ 4 ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼
+ 4 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 640 ¥Ð¥¤¥È
+
+
+ #######################################
+ # ALIVE, ¥Ú¡¼¥¸¥ã¡¼¥³¡¼¥ë¾ðÊ󥨥ꥢ #
+ #######################################
+
+ 1 ¸½ºß¤ÎÄÌÊó¥ì¥Ù¥ë
+ 16 ALIVE°ì¼¡ÄÌÊóÀè
+ 16 ALIVEÆó¼¡ÄÌÊóÀè
+ 47 [reserved for pager call]
+
+-----------------------------------------------------------------------------
+TOTAL 80 ¥Ð¥¤¥È
+
+
+ ##############################################################################
+ # ¢¬¤³¤³¤Þ¤Ç720¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë #
+ # 48¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£ #
+ ##############################################################################
+
+ 48 [reserved]
+
+
+ #######################
+ # ¥á¥â¥ê¥¨¥é¡¼¥í¥°Éô #
+ #######################
+
+ 400 1bit¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(25¥Ð¥¤¥È) ¡ß 16
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1¡¡¡¡¥Õ¥é¥°
+
+ ¡¡¡¡ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 [reserved]
+ ¡¡¡¡3 ¡¡¡¡¢¬
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7¡¡¡¡ ¡¡¢¬
+ ¡¡ 4 ¥¨¥é¡¼¥¢¥É¥ì¥¹
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 4 ¥·¥ó¥É¥í¡¼¥à
+ ¡¡ 1 ¥á¥â¥ê¥°¥ë¡¼¥×
+ 1 SIMMÆÃÄê¾ðÊó
+ 100 2bit¥¨¥é¡¼¾ðÊó¥ì¥³¡¼¥É(25¥Ð¥¤¥È) ¡ß 4
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1 ¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 [reserved]
+ ¡¡¡¡3 ¡¡¡¡¢¬
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5¡¡ ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ ¡¡ 4 ¥¨¥é¡¼¥¢¥É¥ì¥¹
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 4 ¥·¥ó¥É¥í¡¼¥à
+ ¡¡ 1 ¥á¥â¥ê¥°¥ë¡¼¥×
+ 1 SIMMÆÃÄê¾ðÊó
+
+-----------------------------------------------------------------------------
+TOTAL 500 ¥Ð¥¤¥È
+
+
+ ###############################################################################
+ # ¢¬¤³¤³¤Þ¤Ç1268¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë #
+ # 12¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£ #
+ ###############################################################################
+
+ 12 [reserved]
+
+
+ ##########################
+ # ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô #
+ ##########################
+
+ 2048 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÉô (1¥ì¥³¡¼¥É512¥Ð¥¤¥È ¡ß 4 ¡á 2K)
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1 ¥Õ¥é¥°
+
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 Dump/Dump SW 0:D 1:D SW
+ ¡¡¡¡3 ÄÌÊó¤Î̵ͭ 0:̤ 1:ºÑ
+ ¡¡¡¡4 boot·ë²Ì 0:Àµ¾ï 1:°Û¾ï
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 496 ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó
+ 1 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 2048 ¥Ð¥¤¥È
+
+
+ #######################################################
+ # ¢¬¤³¤³¤Þ¤Ç3328¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê #
+ #######################################################
+
+
+ ###############################################################
+ # ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K) #
+ ###############################################################
+
+ 4096 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K)
+
+ ####################
+ # ¥ì¥³¡¼¥É¤ÎÆâÍÆ #
+ ####################
+
+ 1 ¥Õ¥é¥°
+ ##################
+ # ¥Õ¥é¥°¤ÎÆâÍÆ #
+ ##################
+
+ ¡¡¡¡0 Í­¸ú/̵¸ú 0:̵¸ú 1:Í­¸ú
+ ¡¡¡¡1 checkºÑ/̤ 0:̤ 1:ºÑ
+ ¡¡¡¡2 Panic/Shutdown 0:P 1:S
+ ¡¡¡¡3 [reserved]
+ ¡¡¡¡4 ¡¡¡¡¢¬
+ ¡¡¡¡5 ¡¡¡¡¢¬
+ ¡¡¡¡6 ¡¡¡¡¢¬
+ ¡¡¡¡7 ¡¡¡¡¢¬
+ 14 ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥×
+ 20 ¥½¡¼¥¹Ì¾
+ 80 ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊó
+ 13 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 4096 ¥Ð¥¤¥È
+
+
+ #######################################################
+ # ¢¬¤³¤³¤Þ¤Ç7424¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê #
+ #######################################################
+
+
+ ##############################
+ # ¤·¤­¤¤ÃÍȽÄêÍѥǡ¼¥¿Îΰè #
+ ##############################
+
+ ¡¡ 256 [reserved]
+
+-----------------------------------------------------------------------------
+TOTAL 256 ¥Ð¥¤¥È
+
+
+ ###############################################################
+ # ¢¬¤³¤³¤Þ¤Ç7680(7K+512)¥Ð¥¤¥È¡£¤Á¤ç¤¦¤É256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê #
+ ###############################################################
+
+
+ ##############################
+ # ¥ê¥¶¡¼¥ÖÎΰè (512¥Ð¥¤¥È) #
+ ##############################
+
+ 512 PAiNTSÍÑ?
+
+-----------------------------------------------------------------------------
+TOTAL 512 ¥Ð¥¤¥È
+
+
+ #############################################
+ # ¢¬¤³¤³¤Þ¤Ç8192(8K)¥Ð¥¤¥È¡£NVRAM¤Î¤·¤Ã¤Ý #
+ #############################################
+
+******************************************************************************/
+
+
+#pragma pack(1)
+
+/********************
+ * *
+ * ¡¡¹½Â¤ÂÎÄêµÁ *
+ * *
+ ********************/
+
+
+/*
+ * WAS & PS¶¦ÄÌFWÍÑ¥á¥â¥ê¥¨¥é¡¼¾ðÊóÎΰè
+ */
+typedef struct _MEM_ERR_REC {
+ unsigned char mem_status; /* ¥¹¥Æ¡¼¥¿¥¹ */
+ unsigned char err_count; /* 1bit¥¨¥é¡¼¥«¥¦¥ó¥È */
+} MEM_ERR_REC, *pMEM_ERR_REC;
+
+
+/*
+ * ALIVE¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _ALIVE_AREA_INFO {
+ unsigned short offset_alive;
+ /* ALIVE¾ðÊ󥨥ꥢ¥ª¥Õ¥»¥Ã¥È */
+} ALIVE_AREA_INFO, *pALIVE_AREA_INFO;
+
+
+/*
+ * ECC1bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _ECC1_ERR_AREA_INFO {
+ unsigned short offset_1biterr; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+ unsigned long read_data_latest; /* ºÇ¿·¥ê¡¼¥É¥¨¥é¡¼¥Ç¡¼¥¿ */
+ unsigned char err_count_group0; /* ¥á¥â¥êG#0 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group1; /* ¥á¥â¥êG#1 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group2; /* ¥á¥â¥êG#2 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group3; /* ¥á¥â¥êG#3 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group4; /* ¥á¥â¥êG#4 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group5; /* ¥á¥â¥êG#5 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group6; /* ¥á¥â¥êG#6 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+ unsigned char err_count_group7; /* ¥á¥â¥êG#7 ¥¨¥é¡¼¥«¥¦¥ó¥È */
+} ECC1_ERR_AREA_INFO, *pECC1_ERR_AREA_INFO;
+
+
+/*
+ * ECC2bit¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _ECC2_ERR_AREA_INFO {
+ unsigned short offset_2biterr; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+ unsigned long read_data_latest; /* ºÇ¿·¥ê¡¼¥É¥¨¥é¡¼¥Ç¡¼¥¿ */
+ unsigned char simm_flag_group1; /* ¥á¥â¥êG#1ÆâSIMM¥Õ¥é¥° */
+ unsigned char simm_flag_group2; /* ¥á¥â¥êG#2ÆâSIMM¥Õ¥é¥° */
+ unsigned char simm_flag_group3; /* ¥á¥â¥êG#3ÆâSIMM¥Õ¥é¥° */
+ unsigned char simm_flag_group4; /* ¥á¥â¥êG#4ÆâSIMM¥Õ¥é¥° */
+ char reserved[4]; /* reserved */
+} ECC2_ERR_AREA_INFO, *pECC2_ERR_AREA_INFO;
+
+
+/*
+ * ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _SYSTEM_ERR_AREA_INFO {
+ unsigned short offset_systemerr;/* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+} SYSTEM_ERR_AREA_INFO, *pSYSTEM_ERR_AREA_INFO;
+
+
+/*
+ * ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _CRITICAL_ERR_AREA_INFO {
+ unsigned short offset_critical; /* ¥¨¥ê¥¢¤ÎÀèƬ¤Ø¤Î¥ª¥Õ¥»¥Ã¥È */
+ unsigned short size_rec; /* 1¥ì¥³¡¼¥É¥µ¥¤¥º */
+ unsigned short num_rec; /* Áí¥ì¥³¡¼¥É¿ô */
+ unsigned short offset_latest; /* ºÇ¿·¥ì¥³¡¼¥É¥ª¥Õ¥»¥Ã¥È */
+} CRITICAL_ERR_AREA_INFO, *pCRITICAL_ERR_AREA_INFO;
+
+
+/*
+ * ¤·¤­¤¤ÃÍÅù¤½¤Î¾¤Î¾ðÊóÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _MISC_AREA_INFO {
+ unsigned short offset_misc;
+ /* ¤·¤­¤¤¤ÁÅù¤Î¾ðÊ󥨥ꥢÀèƬ¥ª¥Õ¥»¥Ã¥È */
+} MISC_AREA_INFO, *pMISC_AREA_INFO;
+
+
+/*
+ * ¥ê¥¶¡¼¥ÖÎΰè¤Ë´Ø¤¹¤ë¤â¤Î
+ */
+typedef struct _RESERVE_AREA_INFO {
+ unsigned short offset_reserve;
+ /* ¥ê¥¶¡¼¥Ö¥¨¥ê¥¢ÀèƬ¥ª¥Õ¥»¥Ã¥È */
+} RESERVE_AREA_INFO, *pRESERVE_AREA_INFO;
+
+
+/*
+ * ¥·¥¹¥Æ¥à¾ðÊ󥨥ꥢ
+ * 49¥Ð¥¤¥È
+ */
+
+typedef struct _SYS_INFO {
+ unsigned char system_flag; /* ¥·¥¹¥Æ¥à¾õÂ֥ե饰 */
+ char reserved1[3]; /* 4byte alignment¤Ë¤½¤Ê¤¨¤Æ */
+ char sys_description[32]; /* ¥·¥¹¥Æ¥à¤Î¾ðÊó */
+ unsigned long serical_num; /* ¥Þ¥·¥ó¥·¥ê¥¢¥ë¥Ê¥ó¥Ð¡¼ */
+ unsigned long magic; /* ¥Þ¥¸¥Ã¥¯¥Ê¥ó¥Ð¡¼ */
+ char reserved2[4]; /* reserved */
+} SYS_INFO, *pSYS_INFO;
+
+
+
+/*
+ * NVRAM¥Ø¥Ã¥ÀÉô
+ * 640¥Ð¥¤¥È
+ */
+
+typedef struct _NVRAM_HEADER {
+ MEM_ERR_REC mem_err_map[256]; /* ¥á¥â¥ê¥¨¥é¡¼¾ðÊóNT&NW¶¦ÄÌ¥¨¥ê¥¢ */
+ unsigned char nvram_flag; /* nvram¤Î¾õÂ֥ե饰 */
+ char when_formatted[14]; /* ¥Õ¥©¡¼¥Þ¥Ã¥È¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ char reserved[3]; /* 4byte alignment ¤Ë¤½¤Ê¤¨¤Æ */
+ ALIVE_AREA_INFO alive; /* ALIVE¾ðÊ󥨥ꥢ */
+ ECC1_ERR_AREA_INFO ecc1bit_err; /* ECC1bit¥¨¥é¡¼¾ðÊ󥨥ꥢ */
+ ECC2_ERR_AREA_INFO ecc2bit_err; /* ECC2bit¥¨¥é¡¼¾ðÊ󥨥ꥢ */
+ SYSTEM_ERR_AREA_INFO system_err;/* ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊ󥨥ꥢ */
+ CRITICAL_ERR_AREA_INFO critical_err_log;
+ /* ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°¥¨¥ê¥¢ */
+ MISC_AREA_INFO misc; /* ¤·¤­¤¤¤Á¾ðÊ󥨥ꥢ */
+ RESERVE_AREA_INFO reserve; /* ¥ê¥¶¡¼¥Ö¥¨¥ê¥¢¥ª¥Õ¥»¥Ã¥È */
+ SYS_INFO system; /* ¥·¥¹¥Æ¥à¾ðÊó */
+} NVRAM_HEADER, *pNVRAM_HEADER;
+
+
+
+/*
+ * ALIVE, ¥Ú¡¼¥¸¥ã¡¼¥³¡¼¥ë¾ðÊ󥨥ꥢ
+ * 80¥Ð¥¤¥È
+ */
+
+typedef struct _ALIVE_INFO {
+ unsigned char alert_level; /* ÄÌÊó¥ì¥Ù¥ë¥° */
+ char primary_destination[16]; /* °ì¼¡ÄÌÊóÀèÅÅÏÃÈÖ¹æ */
+ char secondary_destinaiton[16]; /* Æó¼¡ÄÌÊóÀèÅÅÏÃÈÖ¹æ */
+ char reserved[47]; /* reserved for pager call */
+} ALIVE_INFO, *pALIVE_INFO;
+
+
+/*
+ * ¢¬¤³¤³¤Þ¤Ç720¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë
+ * 48¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£
+ */
+
+char reserved[48];
+
+
+typedef struct _ECC1_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ unsigned long err_address; /* ¥¨¥é¡¼¥¢¥É¥ì¥¹ */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ unsigned long syndrome; /* ¥·¥ó¥É¥í¡¼¥à */
+ unsigned char specified_group; /* ¥á¥â¥ê¥°¥ë¡¼¥× */
+ unsigned char specified_simm; /* SIMMÆÃÄê¾ðÊó */
+} ECC1_ERR_REC, *pECC1_ERR_REC;
+
+
+typedef struct _ECC2_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ unsigned long err_address; /* ¥¨¥é¡¼¥¢¥É¥ì¥¹ */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ unsigned long syndrome; /* ¥·¥ó¥É¥í¡¼¥à */
+ unsigned char specified_group; /* ¥á¥â¥ê¥°¥ë¡¼¥× */
+ unsigned char specified_simm; /* SIMMÆÃÄê¾ðÊó */
+} ECC2_ERR_REC, *pECC2_ERR_REC;
+
+
+/*
+ * ¥á¥â¥ê¥¨¥é¡¼¥í¥°Éô
+ * 500 ¥Ð¥¤¥È
+ */
+
+ECC1_ERR_REC ecc1_err_rec_log[16];
+
+ECC2_ERR_REC ecc2_err_rec_log[4];
+
+
+/*
+ * ¢¬¤³¤³¤Þ¤Ç1268¥Ð¥¤¥È¡£¼¡¤ÎÎΰè¤ÎÀèƬ¤¬256¥Ð¥¤¥È¥Ð¥¦¥ó¥À¥ê¤«¤é»Ï¤Þ¤ë¤è¤¦¤Ë
+ * 12¥Ð¥¤¥È¤ò[reserved]¤È¤·¤Æ¥Ñ¥Ç¥£¥ó¥°¤¹¤ë¡£
+ */
+
+char reserved2[12];
+
+
+typedef struct _STOP_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ char err_description[496]; /* ¥·¥¹¥Æ¥à¥¨¥é¡¼¾ðÊó */
+ char reserved[1]; /* reserved */
+} STOP_ERR_REC, *pSTOP_ERR_REC;
+
+/*
+ * ¥¹¥Ã¥È¥×¥¨¥é¡¼¾ðÊóÉô
+ * 2048 ¥Ð¥¤¥È
+ */
+
+STOP_ERR_REC stop_err_rec_log[4];
+
+
+typedef struct _CRITICAL_ERR_REC {
+ unsigned char record_flag; /* ¥ì¥³¡¼¥É¥Õ¥é¥° */
+ char when_happened[14]; /* ȯÀ¸¥¿¥¤¥à¥¹¥¿¥ó¥× */
+ char source[14]; /* ¥½¡¼¥¹Ì¾ */
+ char err_description[496]; /* ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¾ðÊó */
+ char reserved[13]; /* reserved */
+} CRITICAL_ERR_REC, *pCRITICAL;
+
+
+/* ¡¡
+ * ¥¯¥ê¥Æ¥£¥«¥ë¥¨¥é¡¼¥í¥°Éô (1¥ì¥³¡¼¥É128¥Ð¥¤¥È ¡ß 32 ¡á 4K)
+ * 4096¥Ð¥¤¥È
+ */
+
+CRITICAL_ERR_REC critical_err_rec_log[32];
+
+
+/*
+ * ¤·¤­¤¤ÃÍȽÄêÍÑÅù¥Ç¡¼¥¿Îΰè.
+ * 256¥Ð¥¤¥È
+ */
+
+char reserved3[256]; /* reserved */
+
+
+/*
+ * ¥ê¥¶¡¼¥ÖÎΰè(PAiNTSÍÑ?)
+ * 512¥Ð¥¤¥È
+ */
+
+char reserved4[512]; /* reserved for paints ? */
+
+#pragma pack(4)
diff --git a/private/ntos/nthals/halr98mp/mips/halp.h b/private/ntos/nthals/halr98mp/mips/halp.h
new file mode 100644
index 000000000..f3d80fe71
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/halp.h
@@ -0,0 +1,708 @@
+#ident "@(#) NEC halp.h 1.19 95/06/19 10:53:45"
+/*++ BUILD Version: 0003 // Increment this if a change has global effects
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+--*/
+
+/*
+ * Original source: Build Number 1.531
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 3/25-5/30 T.Samezima
+ *
+ * add Spinlock HalpEifInterruptLock
+ * define function
+ * define external references
+ *
+ * change include file
+ *
+ * del '#if defined(_JAZZ_)' with content
+ * '#if defined(_DUO_)' with content
+ *
+ ***********************************************************************
+ *
+ * S002 6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***********************************************************************
+ *
+ * S003 7/7 T.Samezima
+ *
+ * Del Arbitration point variable name
+ *
+ * Add Function define
+ *
+ *
+ ***********************************************************************
+ *
+ * S004 8/22 T.Samezima on SNES
+ *
+ * Chg Register buffer size from USHORT to ULONG
+ *
+ ***********************************************************************
+ *
+ * S005 '94.9/27 T.Samezima
+ *
+ * Add Define debug Print
+ *
+ * K000 94/10/11 N.Kugimoto
+ * Fix 807 base
+ * K001 94/10/12 N.Kugimoto
+ * add halpNmihandler
+ * K002 94/10/13 N.Kugimoto
+ * add HalpEifRegisterBuffer
+ * K003 94/10/13 N.Kugimoto
+ * add HalpEisaMemoryBase
+ * chg extern
+ *
+ * S006 '94.10/14 T.Samezima
+ * Add extern valiable
+ * Chg Change condition of ifdef
+ *
+ * A001 ataka@oa2.kb.nec.co.jp
+ * add ADD001 Resource Usage Information
+ *
+ * S007 '94.10/23 T.Samezima
+ * chg variable size from ULONG to UCHAR
+ *
+ * K004 94/12/06 N.Kugimoto
+ * Add ESM NVRAM Interface Add
+ *
+ * S008 94/12/07 N.Kugimoto
+ * Add HalpDisablePciInterrupt,HalpEnablePciInterrupt
+ *
+ * S009 94/12/23 T.Samezima
+ * Add ESM function and variable.
+ *
+ * S00a 94/01/15 T.Samezima
+ * Add ESM function.
+ *
+ * S00b 94/01/16-20 T.Samezima
+ * Add ESM variable and ESM function.
+ *
+ * S00c 94/03/10 T.Samezima
+ * Add HalpNMIFlag
+ *
+ * S00d 94/03/10 T.Samezima
+ * Add HalpLRErrorInterrupt(), HalpReadAndWritePhysicalAddr()
+ *
+ * A002 95/06/13 ataka@oa2.kb.nec.co.jp
+ * Marge build 1050
+ *
+ */
+
+
+#ifndef _HALP_
+#define _HALP_
+#if defined(NT_UP)
+#undef NT_UP
+#endif
+#include "nthal.h"
+#include "hal.h" // A002
+
+#ifndef _HALI_ // A002
+#include "..\inc\hali.h"
+#endif
+
+/* Start S001 */
+#include "r98def.h"
+#include "r98reg.h"
+#include "r98hal.h" // S002
+/* End S001 */
+
+
+#if defined(USE_BIOS_EMULATOR) // A002
+#include "xm86.h"
+#include "x86new.h"
+#endif
+
+/* Start S002 */
+// #include "jxhalp.h"
+
+
+// A002
+// Define map register translation entry structure.
+//
+//typedef struct _TRANSLATION_ENTRY {
+// PVOID VirtualAddress;
+// ULONG PhysicalAddress;
+// ULONG Index;
+//} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpRealTimeClockBase;
+extern PVOID HalpEisaMemoryBase; //K003
+/* End S002 */
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+VOID
+HalpCacheErrorRoutine (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt0 (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt1 (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ );
+
+/* Start S002 */
+#if !defined(_R98_)
+BOOLEAN
+HalpDmaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+#endif
+/* End S002 */
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt (
+ VOID
+ );
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ );
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+#if defined(R4000)
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+#endif
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID //K000
+HalpInitializeX86DisplayAdapter(
+ VOID
+ );
+
+VOID //K000
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+
+/* Start S001 */
+/* Start S002 */
+VOID
+HalpInt0Dispatch(
+ VOID
+ );
+
+VOID
+HalpInt1Dispatch(
+ VOID
+ );
+
+VOID
+HalpInt2Dispatch(
+ VOID
+ );
+
+VOID
+HalpTimerDispatch(
+ VOID
+ );
+
+VOID
+HalpEifDispatch(
+ VOID
+ );
+/* End S002 */
+
+VOID
+HalpOutputSegment(
+ IN ULONG Number,
+ IN UCHAR Data
+ );
+
+VOID
+HalpDisplaySegment(
+ IN ULONG Number,
+ IN UCHAR Data
+ );
+/* End S001 */
+
+/* Start S002 */
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ );
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PINTERNAL_TRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpCreatePciStructures (
+ VOID
+ );
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+KIRQL
+HalpMapNvram (
+ IN PENTRYLO SavedPte
+ );
+
+VOID
+HalpUnmapNvram (
+ IN PENTRYLO SavedPte,
+ IN KIRQL OldIrql
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+// S008 vvv
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector
+ );
+// S008 ^^^
+
+VOID
+HalpReadLargeRegister(
+ IN ULONG VirtualAddress,
+ OUT PULONG UpperPart,
+ OUT PULONG LowerPart
+ );
+
+VOID
+HalpWriteLargeRegister(
+ IN ULONG VirtualAddress,
+ IN PULONG UpperPart,
+ IN PULONG LowerPart
+ );
+
+VOID
+HalpRegisterNmi(
+ VOID
+ );
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+/* Start S003 */
+VOID
+HalpHandleEif(
+ VOID
+ );
+
+ULONG
+HalpGetCause(
+ VOID
+ );
+/* End S003 */
+
+//K001
+VOID
+HalpNmiHandler(
+ VOID
+ );
+
+//K004 Start
+
+BOOLEAN
+HalNvramWrite(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer
+);
+
+BOOLEAN
+HalNvramRead(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer
+);
+
+BOOLEAN
+HalpNvramReadWrite(
+ ULONG Offset,
+ ULONG Count,
+ PVOID Buffer,
+ ULONG Write
+);
+
+//K004 End
+//S009 vvv
+ULONG
+HalpEccError(
+ IN ULONG EifrRegister
+ );
+
+VOID
+HalpInitDisplayStringIntoNvram(
+ VOID
+ );
+
+VOID
+HalpSetInitDisplayTimeStamp(
+ VOID
+ );
+
+VOID
+HalpSuccessOsStartUp(
+ VOID
+ );
+
+VOID
+HalpChangePanicFlag(
+ IN ULONG NewPanicFlg,
+ IN UCHAR NewLogFlg,
+ IN UCHAR CurrentLogFlgMask
+ );
+
+#if 0 // S00b
+VOID
+HalpStringIntoNvram(
+ IN ULONG Column,
+ IN ULONG Row,
+ IN PUCHAR String
+ );
+#endif // S00b
+//S009 ^^^
+
+// S00a vvv
+ULONG
+HalpReadPhysicalAddr(
+ IN ULONG PhysicalAddr
+ );
+// S00a ^^^
+// S00b vvv
+VOID
+HalStringIntoBuffer(
+ IN UCHAR Character
+ );
+
+VOID
+HalStringIntoBufferStart(
+ IN ULONG Column,
+ IN ULONG Row
+ );
+
+VOID
+HalpStringBufferCopyToNvram(
+ VOID
+ );
+// S00b ^^^
+// S00d vvv
+ULONG
+HalpReadAndWritePhysicalAddr(
+ IN ULONG PhysicalAddr
+ );
+
+BOOLEAN
+HalpLRErrorInterrupt(
+ VOID
+ );
+// S00d ^^^
+
+/* Start S005 */
+#if DBG // S006
+VOID
+R98DebugOutPut(
+ ULONG DebugPrintLevel, // Debug Level
+ PCSZ DebugMessageLed, // For LED strings. shuld be 4Byte.
+ PCSZ DebugMessage, // For DISPLAY or SIO
+ ...
+ );
+
+#define R98DbgPrint(_x_) R98DebugOutPut _x_
+#else
+#define R98DbgPrint(_x_)
+#endif
+/* End S005 */
+
+#ifdef RtlMoveMemory
+#undef RtlMoveMemory
+#undef RtlCopyMemory
+#undef RtlFillMemory
+#undef RtlZeroMemory
+
+#define RtlCopyMemory(Destination,Source,Length) RtlMoveMemory((Destination),(Source),(Length))
+VOID
+RtlMoveMemory (
+ PVOID Destination,
+ CONST VOID *Source,
+ ULONG Length
+ );
+
+VOID
+RtlFillMemory (
+ PVOID Destination,
+ ULONG Length,
+ UCHAR Fill
+ );
+
+VOID
+RtlZeroMemory (
+ PVOID Destination,
+ ULONG Length
+ );
+
+#endif // #ifdef RtlMoveMemory
+/* End S002 */
+
+//
+// Define external references.
+//
+
+extern KSPIN_LOCK HalpBeepLock;
+extern ULONG HalpBuiltinInterruptEnable; // S004
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern ULONG HalpProfileCountRate;
+extern ULONG HalpStallScaleFactor;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+/* Start S001 */
+extern KSPIN_LOCK HalpEifInterruptLock;
+/* Start S003 */
+extern ULONG HalpInt2ArbitrationPoint;
+extern ULONG HalpInt1ArbitrationPoint;
+extern ULONG HalpInt0ArbitrationPoint;
+/* End S003 */
+extern ULONG HalpUnknownInterruptCount[];
+/* Start S002 */
+extern KAFFINITY HalpEisaBusAffinity; //K000
+extern KAFFINITY HalpPCIBusAffinity; //S006
+extern KAFFINITY HalpInt1Affinity; //S006
+extern UCHAR HalpChangeIntervalFlg[]; //S006, S007
+extern ULONG HalpChangeIntervalCount;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextIntervalCount;
+extern ULONG HalpNewTimeIncrement;
+/* End S002 */
+/* End S001 */
+extern ULONG HalpEifRegisterBuffer[]; //K002,K003
+
+// S009 vvv
+extern ULONG HalpNvramValid;
+extern USHORT ErrBufferArea;
+// S009 ^^^
+// S00b vvv
+LONG HalpECC1bitDisableFlag;
+LONG HalpECC1bitDisableTime;
+ULONG HalpECC1bitScfrBuffer;
+// S00b ^^^
+extern volatile ULONG HalpNMIFlag; // R98TEMP
+
+
+// ADD001
+//
+// Resource usage information
+//
+
+#if !defined (_R98_)
+#pragma pack(1)
+#endif
+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;
+#if !defined (_R98_)
+#pragma pack()
+#endif
+
+#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;
+// CMP001
+extern ADDRESS_USAGE HalpDefaultPcIoSpace;
+extern ADDRESS_USAGE HalpEisaIoSpace;
+extern ADDRESS_USAGE HalpMapRegisterMemorySpace;
+
+#define HalpRegisterAddressUsage(a) \
+ (a)->Next = HalpAddressUsageList, HalpAddressUsageList = (a);
+
+// CMP001
+#define IRQ_PREFERRED 0x02
+#define IRQ_VALID 0x01
+
+// CMP001
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+);
+
+//
+// Temp definitions to thunk into supporting new bus extension format
+//
+// A002
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ );
+
+// A002
+PBUS_HANDLER
+HalpAllocateBusHandler (
+ IN INTERFACE_TYPE InterfaceType,
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN INTERFACE_TYPE ParentBusDataType,
+ IN ULONG ParentBusNumber,
+ IN ULONG BusSpecificData
+ );
+
+// A002
+#define HalpHandlerForBus HaliHandlerForBus
+#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
+
+
+#endif // _HALP_
diff --git a/private/ntos/nthals/halr98mp/mips/j4cache.s b/private/ntos/nthals/halr98mp/mips/j4cache.s
new file mode 100644
index 000000000..d6e9f2dd6
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/j4cache.s
@@ -0,0 +1,1056 @@
+// "@(#) NEC j4cache.s 1.5 94/12/06 10:46:13"
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// j4cache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// a MIPS R4000.
+//
+//--
+
+#include "halmips.h"
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.08/22 T.Samezima on SNES
+ *
+ * Add define _DUO_
+ *
+ * K001 94/10/11 N.Kugimoto
+ * Fix 807 Base
+ * K002 94/12/06 N.Kugimoto
+ * Fix Mem32
+ */
+
+#define _DUO_ // S001
+
+//
+// Define cache operations constants.
+//
+
+#define COLOR_BITS (7 << PAGE_SHIFT) // color bit (R4000 - 8kb cache)
+#define COLOR_MASK (0x7fff) // color mask (R4000 - 8kb cache)
+#define FLUSH_BASE 0xfffe0000 // flush base address
+#define PROTECTION_BITS ((1 << ENTRYLO_V) | (1 << ENTRYLO_D)) //
+
+ SBTTL("Change Color Page")
+//++
+//
+// VOID
+// HalChangeColorPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function changes the color of a page if the old and new colors
+// do not match.
+//
+// The algorithm used to change colors for a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page to change.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page to change.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is changed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+CpRa: .space 4 // saved return address
+CpFrameLength: // length of stack frame
+CpA0: .space 4 // (a0)
+CpA1: .space 4 // (a1)
+CpA2: .space 4 // (a2)
+CpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalChangeColorPage, CpFrameLength, zero)
+
+ subu sp,sp,CpFrameLength // allocate stack frame
+ sw ra,CpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ beq a0,a1,10f // if eq, colors match
+ sw a1,CpA1(sp) // save old color bits
+ sw a2,CpA2(sp) // save page frame
+
+//
+// Purge the instruction cache using the old page color.
+//
+
+ move a0,a1 // set color value
+ move a1,a2 // set page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeIcachePage // purge instruction cache page
+
+//
+// Flush the data cache using the old page color.
+//
+
+ lw a0,CpA1(sp) // get old color bits
+ lw a1,CpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalFlushDcachePage // purge data cache page
+10: lw ra,CpRa(sp) // get return address
+ addu sp,sp,CpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalChangeColorPage
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalFlushDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (hit/writeback/invalidate) up to a page of data
+// from the data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is flushed.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is flushed.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// flushed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalFlushDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set flush block size
+ .set at
+ .set reorder
+
+//
+// Flush a page from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Flush the primary data cache only.
+//
+
+20: cache HIT_WRITEBACK_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Flush the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalFlushDcachePage
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalPurgeDcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of data from the
+// data cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeDcachePage)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the data cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary data cache only.
+//
+
+20: cache HIT_INVALIDATE_D,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SD,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeDcachePage
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalPurgeIcachePage (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page fo data from the
+// instruction cache.
+//
+// Arguments:
+//
+// Color (a0) - Supplies the starting virtual address and color of the
+// data that is purged.
+//
+// PageFrame (a1) - Supplies the page frame number of the page that
+// is purged.
+//
+// Length (a2) - Supplies the length of the region in the page that is
+// purged.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalPurgeIcachePage)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ and a0,a0,COLOR_MASK // isolate color bits
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a0 // compute color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a0,a0,0x1000 // isolate TB entry index
+ beql zero,a0,10f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+10: mfc0 t3,wired // get TB entry index
+ lw v0,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ lw t4,KiPcr + PcFirstLevelIcacheFillSize(zero) // get 1st fill size
+ bnel zero,v0,15f // if ne, second level cache present
+ move t4,v0 // set purge block size
+ .set at
+ .set reorder
+
+//
+// Purge data from the instruction cache.
+//
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ subu t6,t4,1 // compute block size minus one
+ and t7,t0,t6 // compute offset in block
+ addu a2,a2,t6 // round up to next block
+ addu a2,a2,t7 //
+ nor t6,t6,zero // complement block size minus one
+ and a2,a2,t6 // truncate length to even number
+ beq zero,a2,30f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ bne zero,v0,40f // if ne, second level cache present
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary instruction cache only.
+//
+
+20: cache HIT_INVALIDATE_I,0(t8) // invalidate cache block
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+30: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+//
+// Purge the primary and secondary instruction caches.
+//
+
+ .set noreorder
+ .set noat
+40: cache HIT_INVALIDATE_SI,0(t8) // invalidate cache block
+ bne t8,t9,40b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalSweepDcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcache)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+ DISABLE_INTERRUPTS(t5) // disable interrupts K002
+
+ lw t0,KiPcr + PcFirstLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+
+#if defined(_MIPS_R4600) //K001
+
+ nop // fill
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+ beq zero,t1,30f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary data cache.
+//
+
+ .set noreorder
+ .set noat
+20: cache INDEX_WRITEBACK_INVALIDATE_SD,0(a0) // writeback/invalidate on index
+ bne a0,a1,20b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+30:
+ ENABLE_INTERRUPTS(t5) // enable interrupts K002
+ j ra // return
+
+ .end HalSweepDcache
+
+ SBTTL("Sweep Data Cache Range")
+//++
+//
+// VOID
+// HalSweepDcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the specified range
+// of virtual addresses from the primary data cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the data cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// data cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepDcacheRange)
+
+#if DBG
+
+ lw t0,KeDcacheFlushCount // get address of dcache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result conditionally
+
+#endif
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts K002
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelDcacheFillSize(zero) // get block size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary data cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+
+#if defined(_MIPS_R4600)
+
+ nop // fill
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts K002
+
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalSweepIcache (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcache)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t1,20f // if eq, no second level cache
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_SI,0(a0) // invalidate cache line
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: lw t0,KiPcr + PcFirstLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ li a0,KSEG0_BASE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+#if defined(_MIPS_R4600)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+#endif
+
+ .set noreorder
+ .set noat
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(_MIPS_R4600) //K001
+
+ nop // fill
+ cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(_MIPS_R4600)
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+#endif
+
+ j ra // return
+
+ .end HalSweepIcache
+
+ SBTTL("Sweep Instruction Cache Range")
+//++
+//
+// VOID
+// HalSweepIcacheRange (
+// IN PVOID BaseAddress,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the specified range of addresses
+// from the instruction cache.
+//
+// Arguments:
+//
+// BaseAddress (a0) - Supplies the base address of the range that is swept
+// from the instruction cache.
+//
+// Length (a1) - Supplies the length of the range that is swept from the
+// instruction cache.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalSweepIcacheRange)
+
+#if DBG
+
+ lw t0,KeIcacheFlushCount // get address of icache flush count
+ lw t1,0(t0) // increment the count of flushes
+ addu t1,t1,1 //
+ sw t1,0(t0) // store result
+
+#endif
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ or a0,a0,KSEG0_BASE // convert to physical address
+ lw t0,KiPcr + PcFirstLevelIcacheFillSize(zero) // get fill size
+ addu a1,a0,a1 // compute ending cache address
+ subu a1,a1,t0 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+#if defined(_MIPS_R4600)
+
+ DISABLE_INTERRUPTS(t1) // disable interrupts
+
+#endif
+
+ .set noreorder
+ .set noat
+10: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(_MIPS_R4600)
+
+ nop // fill
+ cache INDEX_INVALIDATE_I,8192(a0) // writeback/invalidate on index
+
+#endif
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t0 // compute address of next block
+ .set at
+ .set reorder
+
+#if defined(_MIPS_R4600)
+
+ ENABLE_INTERRUPTS(t1) // enable interrupts
+
+#endif
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalZeroPage (
+// IN PVOID NewColor,
+// IN PVOID OldColor,
+// IN ULONG PageFrame
+// )
+//
+// Routine Description:
+//
+// This function zeros a page of memory.
+//
+// The algorithm used to zero a page is as follows:
+//
+// 1. Purge (hit/invalidate) the page from the instruction cache
+// using the old color iff the old color is not the same as
+// the new color.
+//
+// 2. Purge (hit/invalidate) the page from the data cache using
+// the old color iff the old color is not the same as the new
+// color.
+//
+// 3. Create (create/dirty/exclusive) the page in the data cache
+// using the new color.
+//
+// 4. Write zeros to the page using the new color.
+//
+// Arguments:
+//
+// NewColor (a0) - Supplies the page aligned virtual address of the
+// new color of the page that is zeroed.
+//
+// OldColor (a1) - Supplies the page aligned virtual address of the
+// old color of the page that is zeroed.
+//
+// PageFrame (a2) - Supplies the page frame number of the page that
+// is zeroed.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+ .space 3 * 4 // fill
+ZpRa: .space 4 // saved return address
+ZpFrameLength: // length of stack frame
+ZpA0: .space 4 // (a0)
+ZpA1: .space 4 // (a1)
+ZpA2: .space 4 // (a2)
+ZpA3: .space 4 // (a3)
+
+ NESTED_ENTRY(HalZeroPage, ZpFrameLength, zero)
+
+ subu sp,sp,ZpFrameLength // allocate stack frame
+ sw ra,ZpRa(sp) // save return address
+
+ PROLOGUE_END
+
+ and a0,a0,COLOR_BITS // isolate new color bits
+ and a1,a1,COLOR_BITS // isolate old color bits
+ sw a0,ZpA0(sp) // save new color bits
+ sw a2,ZpA2(sp) // save page frame
+
+//
+// If the old page color is not equal to the new page color, then change
+// the color of the page.
+//
+
+ beq a0,a1,10f // if eq, colors match
+ jal KeChangeColorPage // chagne page color
+
+//
+// Create dirty exclusive cache blocks and zero the data.
+//
+
+10: lw a3,ZpA0(sp) // get new color bits
+ lw a1,ZpA2(sp) // get page frame number
+
+ .set noreorder
+ .set noat
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache polciy
+ li t0,FLUSH_BASE // get base flush address
+ or t0,t0,a3 // compute new color virtual address
+ sll t1,a1,ENTRYLO_PFN // shift page frame into position
+ or t1,t1,PROTECTION_BITS // merge protection bits
+ or t1,t1,v0 // merge cache policy
+ and a3,a3,0x1000 // isolate TB entry index
+ beql zero,a3,20f // if eq, first entry
+ move t2,zero // set second page table entry
+ move t2,t1 // set second page table entry
+ move t1,zero // set first page table entry
+20: mfc0 t3,wired // get TB entry index
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ lw v0,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ .set at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 t6,entryhi // get current PID and VPN2
+ srl t7,t0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t7,t7,ENTRYHI_VPN2 //
+ and t6,t6,0xff << ENTRYHI_PID // isolate current PID
+ or t7,t7,t6 // merge PID with VPN2 of virtual address
+ mtc0 t7,entryhi // set VPN2 and PID for probe
+ mtc0 t1,entrylo0 // set first PTE value
+ mtc0 t2,entrylo1 // set second PTE value
+ mtc0 t3,index // set TB index value
+ nop // fill
+ tlbwi // write TB entry - 3 cycle hazzard
+ addu t9,t0,PAGE_SIZE // compute ending address of block
+ dmtc1 zero,f0 // set write pattern
+ bne zero,v0,50f // if ne, second level cache present
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary data cache only.
+//
+
+#if defined(_DUO_)
+
+30: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,30b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+#else
+
+30: cache CREATE_DIRTY_EXCLUSIVE_D,0(t0) // create cache block
+ addu t0,t0,t4 // compute next block address
+ bne zero,t8,40f // if ne, 16-byte cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+40: bne t0,t9,30b // if ne, more blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+
+#endif
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+ .set noreorder
+ .set noat
+
+#if defined(_DUO_)
+
+50: sdc1 f0,0(t0) // zero 64-byte block
+ sdc1 f0,8(t0) //
+ sdc1 f0,16(t0) //
+ sdc1 f0,24(t0) //
+ sdc1 f0,32(t0) //
+ sdc1 f0,40(t0) //
+ sdc1 f0,48(t0) //
+ addu t0,t0,64 // advance to next 64-byte block
+ bne t0,t9,50b // if ne, more to zero
+ sdc1 f0,-8(t0) //
+
+#else
+
+50: cache CREATE_DIRTY_EXCLUSIVE_SD,0(t0) // create secondary cache block
+ addu v1,v0,t0 // compute ending primary block address
+60: addu t0,t0,t4 // compute next block address
+ bne zero,t8,70f // if ne, 16-byte primary cache line
+ sdc1 f0,-16(t0) //
+ sdc1 f0,-24(t0) // zero 16 bytes
+ sdc1 f0,-32(t0) //
+70: bne t0,v1,60b // if ne, more primary blocks to zero
+ sdc1 f0,-8(t0) // zero 16 bytes
+ bne t0,t9,50b // if ne, more secondary blocks to zero
+ nop // fill
+
+#endif
+
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ lw ra,ZpRa(sp) // get return address
+ addu sp,sp,ZpFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalZeroPage
diff --git a/private/ntos/nthals/halr98mp/mips/j4flshbf.s b/private/ntos/nthals/halr98mp/mips/j4flshbf.s
new file mode 100644
index 000000000..b9a1cda9b
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/j4flshbf.s
@@ -0,0 +1,58 @@
+// "@(#) NEC j4flshbf.s 1.2 94/10/17 11:11:16"
+#if defined(R4000)
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// j3flshbf.s
+//
+// Abstract:
+//
+// This module implements the system dependent kernel function to flush
+// the write buffer or otherwise synchronize writes on a MIPS R4000 Jazz
+// system.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.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)
+
+ sync // synchronize writes
+ j ra // return
+
+ .end KeFlushWritebuffer
+
+#endif
diff --git a/private/ntos/nthals/halr98mp/mips/j4flshio.c b/private/ntos/nthals/halr98mp/mips/j4flshio.c
new file mode 100644
index 000000000..d509d6522
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/j4flshio.c
@@ -0,0 +1,238 @@
+#pragma comment(exestr, "@(#) j4flshio.c 1.7 95/03/10 19:31:22 nec")
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ j4flshio.c
+
+Abstract:
+
+
+ This module implements the system dependent kernel function to flush
+ the data cache for I/O transfers on a MIPS R4000 Jazz, Fision, Fusion,
+ or Duo system.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ * K001 94/5/31 (Tue) N.Kugimoto
+ * Add At Dma Nothing to Do.( I/O Cache By R98 H/W)
+ * K002 94/9/26 N.Kugimoto
+ * Bug define bug
+ * K003 94/10/11 N.Kugimoto
+ * H/W Work around for LR4360
+ * K004 94/10/18 N.Kugimoto
+ * Add Flush LR4360 Read Cache at DMA READ(MemotryToDevice)
+ * K005 95/03/10 N.Kugimoto
+ * H/W flush
+ */
+
+
+#include "halp.h"
+
+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 CacheSegment;
+ ULONG Length;
+ ULONG Offset;
+ KIRQL OldIrql;
+ PULONG PageFrame;
+ ULONG Source;
+
+#if defined(_R98_)
+ // K001,K002
+ // R98 I/O Cache Supported So Nothing to Do Dma Operation!!.
+ //
+ if (DmaOperation == TRUE){
+ // LR4360 Bug. IO cache Flush!!
+ //
+ // MemoryToDevice
+ //
+ if(ReadOperation==FALSE) //K004
+ WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K003,K005
+ return;
+ }
+#endif
+ //
+ // The Jazz R4000 uses a write back data cache and, therefore, must be
+ // flushed on reads and writes.
+ //
+ // If the length of the I/O operation is greater than the size of the
+ // data cache, then sweep the entire data cache. Otherwise, flush or
+ // purge individual pages from the data cache as appropriate.
+ //
+
+ Offset = Mdl->ByteOffset & PCR->DcacheAlignment;
+ Length = (Mdl->ByteCount +
+ PCR->DcacheAlignment + Offset) & ~PCR->DcacheAlignment;
+
+ if ((Length > PCR->FirstLevelDcacheSize) &&
+ (Length > PCR->SecondLevelDcacheSize)) {
+
+ //
+ // If the I/O operation is a DMA operation, or 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 entire data cache.
+ //
+
+ if ((DmaOperation != FALSE) ||
+ ((DmaOperation == FALSE) &&
+ (ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0))) {
+ HalSweepDcache();
+ }
+
+ //
+ // If the I/O operation is a page read, then sweep (index/invalidate)
+ // the entire instruction cache.
+ //
+
+ if ((ReadOperation != FALSE) &&
+ ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0)) {
+ HalSweepIcache();
+ }
+
+ } else {
+
+ //
+ // Flush or purge the specified pages from the data cache and
+ // instruction caches as appropriate.
+ //
+ // Compute the number of pages to flush and the starting MDL page
+ // frame address.
+ //
+
+ Offset = Mdl->ByteOffset & ~PCR->DcacheAlignment;
+ PageFrame = (PULONG)(Mdl + 1);
+ Source = ((ULONG)(Mdl->StartVa) & 0xfffff000) | Offset;
+
+ //
+ // Flush or purge the specified page segments from the data and
+ // instruction caches as appropriate.
+ //
+
+ do {
+ if (Length >= (PAGE_SIZE - Offset)) {
+ CacheSegment = PAGE_SIZE - Offset;
+
+ } else {
+ CacheSegment = Length;
+ }
+
+ if (ReadOperation == FALSE) {
+
+ //
+ // The I/O operation is a write and the data only needs to
+ // to be copied back into memory if the operation is also
+ // a DMA operation.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ } else {
+
+ //
+ // If the I/O operation is a DMA operation, then purge the
+ // data cache. Otherwise, is the I/O operation is a page read
+ // operation, then flush the data cache.
+ //
+
+ if (DmaOperation != FALSE) {
+ HalPurgeDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+
+ } else if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalFlushDcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+
+ //
+ // If the I/O operation is a page read, then the instruction
+ // cache must be purged.
+ //
+
+ if ((Mdl->MdlFlags & MDL_IO_PAGE_READ) != 0) {
+ HalPurgeIcachePage((PVOID)Source, *PageFrame, CacheSegment);
+ }
+ }
+
+ PageFrame += 1;
+ Length -= CacheSegment;
+ Offset = 0;
+ Source += CacheSegment;
+ } while(Length != 0);
+ }
+
+ return;
+}
+
+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 PCR->DcacheFillSize;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/j4prof.c b/private/ntos/nthals/halr98mp/mips/j4prof.c
new file mode 100644
index 000000000..80ead3885
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/j4prof.c
@@ -0,0 +1,362 @@
+#ident "@(#) NEC j4prof.c 1.4 95/06/19 10:54:59"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ j4prof.c
+
+Abstract:
+
+ This module contains the code to start and stop the profiling interrupt
+ and to compute the profiling interval for a MIPS R4000 Jazz system.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.03/23-5/25 T.Samezima
+ *
+ * change establish interrupt interval setting
+ * init PROFILE interrupt interval
+ * range of PROFILE interrupt interval
+ *
+ * add restart interrupt
+ * calculate change of unit from 100ns to 1us
+ *
+ * del calculate from interrupt interval to clock number
+ *
+ ***********************************************************************
+ *
+ * S002 94.07/5 T.Samezima
+ *
+ * change Irql level from PROFILE_LEVEL to EIF_LEVEL
+ *
+ * A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ * - resolve compile wornings.
+ */
+
+// #include "ki.h"
+#include "halp.h"
+
+//
+// Define one second and round values.
+//
+
+#define ONE_SECOND (10 * 1000 * 1000) // 1 second in 100ns units
+#define ROUND_VALUE ((ONE_SECOND) - 1) // 1 second minus 100ns
+
+//
+// Define static data.
+//
+
+LARGE_INTEGER HalpPerformanceCounter[8];
+/* Start S001 */
+ULONG HalpProfileInterval = DEFAULT_PROFILETIMER_INTERVAL;
+/* End S001 */
+
+LARGE_INTEGER
+KeQueryPerformanceCounter (
+ OUT PLARGE_INTEGER Frequency OPTIONAL
+ )
+
+/*++
+
+Routine Description:
+
+ This routine returns the current performance counter value and the
+ performance counter frequency.
+
+Arguments:
+
+ Frequency - Supplies an optional pointer to a variable which receives
+ the performance counter frequency in Hertz.
+
+Return Value:
+
+ The current performance counter value is returned as the function
+ value.
+
+--*/
+
+{
+
+ ULONG CurrentCount;
+ KIRQL OldIrql;
+ LARGE_INTEGER PerformanceCounter;
+
+ //
+ // Raise IRQL to PROFILE_LEVEL, read the current value of the count
+ // register, read the performance counter, and lower IRQL to its
+ // previous value.
+ //
+ // N.B. The minimum, maximum, and default values for the profile
+ // count are chosen such that count register only overflows
+ // after about 20 seconds at 50mhz. Therefore, there is never
+ // a problem with the counter wrapping in the following code.
+ //
+
+ /* Start S002 */
+ KeRaiseIrql(EIF_LEVEL, &OldIrql);
+ /* End S002 */
+ CurrentCount = HalpReadCountRegister();
+ PerformanceCounter = HalpPerformanceCounter[KeGetCurrentPrcb()->Number];
+ KeLowerIrql(OldIrql);
+
+ //
+ // If the frequency parameter is specified, then return the performance
+ // counter frequency as the current system time frequency.
+ //
+
+ if (ARGUMENT_PRESENT(Frequency) != FALSE) {
+ *Frequency = RtlConvertUlongToLargeInteger(HalpProfileCountRate);
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ return RtlLargeIntegerAdd(PerformanceCounter,
+ RtlConvertUlongToLargeInteger(CurrentCount));
+}
+
+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;
+ PKPRCB Prcb;
+
+ //
+ // 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);
+ }
+
+ //
+ // Write the compare register, clear the count register, and zero the
+ // performance counter for the current processor.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILETIMER_COUNT);
+ /* Start S001 */
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR2.Long,
+ DEFAULT_PROFILETIMER_COUNT);
+ /* End S001 */
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].LowPart = 0;
+ HalpPerformanceCounter[Prcb->Number].HighPart = 0;
+ /* Start S001 */
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR2.Long, 0x3);
+ /* End S001 */
+
+ //
+ // Restore IRQL to its previous value and return.
+ //
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+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.
+
+--*/
+
+{
+
+// LARGE_INTEGER TempValue;
+
+ //
+ // If the specified profile interval is less that the minimum profile
+ // interval or greater than the maximum profile interval, then set the
+ // profile interval to the minimum or maximum as appropriate.
+ //
+
+ /* Start S001 */
+ if (Interval < MINIMUM_PROFILETIMER_INTERVAL) {
+ Interval = MINIMUM_PROFILETIMER_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILETIMER_INTERVAL) {
+ Interval = MAXIMUM_PROFILETIMER_INTERVAL;
+ }
+
+ HalpProfileInterval = Interval;
+ /* End S001 */
+
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE Reserved // A002
+ )
+
+/*++
+
+Routine Description:
+
+ This routine computes the profile count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+ /* Start S001 */
+ ULONG TempValue;
+ /* End S001 */
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ /* Start S001 */
+ TempValue = HalpProfileInterval / 10;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue);
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR2.Long, TempValue);
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR2.Long, 0x3);
+ /* End S001 */
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number] =
+ RtlLargeIntegerAdd(HalpPerformanceCounter[Prcb->Number],
+ RtlConvertUlongToLargeInteger(PreviousCount));
+
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE Reserved // A002
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the default count value, writes the compare
+ register, clears the count register, and updates the performance
+ counter.
+
+ N.B. This routine must be called at PROFILE_LEVEL while holding the
+ profile lock.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILETIMER_COUNT);
+ /* Start S001 */
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR2.Long,
+ DEFAULT_PROFILETIMER_COUNT);
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR2.Long, 0x3);
+ /* End S001 */
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number] =
+ RtlLargeIntegerAdd(HalpPerformanceCounter[Prcb->Number],
+ RtlConvertUlongToLargeInteger(PreviousCount));
+
+ return;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/jazznvr.h b/private/ntos/nthals/halr98mp/mips/jazznvr.h
new file mode 100644
index 000000000..79ab847cf
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jazznvr.h
@@ -0,0 +1,164 @@
+#ident "@(#) NEC jazznvr.h 1.2 94/10/17 12:10:14"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jazznvr.h
+
+Abstract:
+
+ This module contains definitions for the Jazz non-volatile ram structures.
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 '94.6/02 T.Samezima
+ *
+ * Change NV_CONFIGURATION structure and define
+ *
+ ***********************************************************************
+ *
+ * S002 '94.8/22 T.Samezima on SNES
+ *
+ * Chg NV_CONFIGURATION structure and define
+ *
+ *
+ */
+
+
+#ifndef _JAZZNVR_
+#define _JAZZNVR_
+
+//
+// Define the private configuration packet structure, which contains a
+// configuration component as well as pointers to the component's parent,
+// peer, child, and configuration data.
+//
+
+typedef struct _CONFIGURATION_PACKET {
+ CONFIGURATION_COMPONENT Component;
+ struct _CONFIGURATION_PACKET *Parent;
+ struct _CONFIGURATION_PACKET *Peer;
+ struct _CONFIGURATION_PACKET *Child;
+ PVOID ConfigurationData;
+} CONFIGURATION_PACKET, *PCONFIGURATION_PACKET;
+
+//
+// The compressed configuration packet structure used to store configuration
+// data in NVRAM.
+//
+
+typedef struct _COMPRESSED_CONFIGURATION_PACKET {
+ UCHAR Parent;
+ UCHAR Class;
+ UCHAR Type;
+ UCHAR Flags;
+ ULONG Key;
+ USHORT Version;
+ USHORT ConfigurationDataLength;
+ USHORT Identifier;
+ USHORT ConfigurationData;
+} COMPRESSED_CONFIGURATION_PACKET, *PCOMPRESSED_CONFIGURATION_PACKET;
+
+//
+// Defines for Identifier index.
+//
+
+#define NO_CONFIGURATION_IDENTIFIER 0xFFFF
+
+//
+// Defines for the volatile and non-volatile configuration tables.
+//
+
+#if defined(_R98_)
+
+// Start S002
+#define NUMBER_OF_ENTRIES 50 // REV 05 1994/05/23
+#define LENGTH_OF_IDENTIFIER 516 // REV 05 1994/05/23
+#define LENGTH_OF_DATA 2048 // REV 05 1994/05/23
+#define LENGTH_OF_ENVIRONMENT 1024 // R98 support 1994/01/31(REV 01)
+#define LENGTH_OF_EISA_DATA 2044 // R98 support 1994/01/31(REV 01)
+#define LENGTH_OF_PCI_DATA 512 // REV 06 1994/06/17
+#define LENGTH_OF_ITF_DATA 128 // R98 support 1994/01/31(REV 01)
+#define NUMBER_MEM_ENTRIES 90 // REV 05 1994/05/23
+#define LENGTH_MEM_IDENTIFIER 1024 // REV 05 1994/05/23
+// End S002
+
+#else // #if defined(_R98_)
+
+#define NUMBER_OF_ENTRIES 32
+#define LENGTH_OF_IDENTIFIER 504
+#define LENGTH_OF_DATA 2048
+#define LENGTH_OF_ENVIRONMENT 1024
+
+#endif // #if defined(_R98_)
+
+#define MAXIMUM_ENVIRONMENT_VALUE 128
+
+//
+// The volatile configuration table structure.
+//
+
+typedef struct _CONFIGURATION {
+ CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES];
+ UCHAR Identifier[LENGTH_OF_IDENTIFIER];
+ UCHAR Data[LENGTH_OF_DATA];
+} CONFIGURATION, *PCONFIGURATION;
+
+//
+// The non-volatile configuration table structure.
+//
+
+
+typedef struct _NV_CONFIGURATION {
+
+// Start S002
+#if defined(_R98_)
+
+ COMPRESSED_CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES]; // R98 support 1994/01/31(REV 01)
+ UCHAR Identifier[LENGTH_OF_IDENTIFIER]; // R98 support 1994/01/31(REV 01)
+ UCHAR Data[LENGTH_OF_DATA]; // R98 support 1994/01/31(REV 01)
+ UCHAR Checksum1[4]; // R98 support 1994/01/31(REV 01)
+ UCHAR Environment[LENGTH_OF_ENVIRONMENT]; // R98 support 1994/01/31(REV 01)
+ UCHAR Checksum2[4]; // R98 support 1994/01/31(REV 01)
+ UCHAR EisaData[LENGTH_OF_EISA_DATA]; // R98 support 1994/01/31(REV 01)
+ UCHAR Checksum3[4]; // R98 support 1994/01/31(REV 01)
+ UCHAR EthernetAddress[8]; // R98 support 1994/01/31(REV 01)
+ UCHAR NmiVector[4]; // R98 support 1994/01/31(REV 01)
+ UCHAR ItfUseArea[LENGTH_OF_ITF_DATA]; // R98 support 1994/01/31(REV 01)
+ UCHAR Reserved[1608]; // R98 support 1994/01/31(REV 01)
+
+#else // #if defined(_R98_)
+
+ COMPRESSED_CONFIGURATION_PACKET Packet[NUMBER_OF_ENTRIES];
+ UCHAR Identifier[LENGTH_OF_IDENTIFIER];
+ UCHAR Data[LENGTH_OF_DATA];
+ UCHAR Checksum1[4];
+ UCHAR Environment[LENGTH_OF_ENVIRONMENT];
+ UCHAR Checksum2[4];
+
+#endif // #if defined(_R98_)
+// End S002
+
+} NV_CONFIGURATION, *PNV_CONFIGURATION;
+
+//
+// Non-volatile ram layout.
+//
+
+#if defined(MIPS)
+
+#define NVRAM_CONFIGURATION NVRAM_VIRTUAL_BASE
+#define NVRAM_SYSTEM_ID NVRAM_VIRTUAL_BASE + 0x00002000
+
+#endif
+
+#endif // _JAZZNVR_
diff --git a/private/ntos/nthals/halr98mp/mips/jxbeep.c b/private/ntos/nthals/halr98mp/mips/jxbeep.c
new file mode 100644
index 000000000..d39405c78
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxbeep.c
@@ -0,0 +1,131 @@
+#ident "@(#) NEC jxbeep.c 1.2 94/10/17 11:22:04"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxbeep.c
+
+Abstract:
+
+ This module implements the HAL speaker "beep" routines for a MIPS
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+BOOLEAN
+HalMakeBeep(
+ IN ULONG Frequency
+ )
+
+/*++
+
+Routine Description:
+
+ This function sets the frequency of the speaker, causing it to sound a
+ tone. The tone will sound until the speaker is explicitly turned off,
+ so the driver is responsible for controlling the duration of the tone.
+
+Arguments:
+
+ Frequency - Supplies the frequency of the desired tone. A frequency of
+ 0 means the speaker should be shut off.
+
+Return Value:
+
+ TRUE - Operation was successful (frequency within range or zero).
+ FALSE - Operation was unsuccessful (frequency was out of range).
+ Current tone (if any) is unchanged.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ NMI_STATUS NmiStatus;
+ PEISA_CONTROL controlBase = HalpEisaControlBase;
+ TIMER_CONTROL timerControl;
+ ULONG newCount;
+ BOOLEAN Result;
+
+ //
+ // Raise IRQL to dispatch level and acquire the beep spin lock.
+ //
+
+ KeAcquireSpinLock(&HalpBeepLock, &OldIrql);
+
+ //
+ // Stop the speaker.
+ //
+
+ *((PUCHAR)&NmiStatus) = READ_REGISTER_UCHAR(&controlBase->NmiStatus);
+ NmiStatus.SpeakerGate = 0;
+ NmiStatus.SpeakerData = 0;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR)&NmiStatus));
+
+ //
+ // If the specified frequency is zero, then the speaker is to be stopped.
+ //
+
+ if (Frequency == 0) {
+ Result = TRUE;
+
+ } else {
+
+ //
+ // If the new count has a magnitude less than 65,536 (0x10000), then
+ // set the speaker time to the correct mode. Otherwise, return a value
+ // of FALSE sinc ethe frequency is out of range.
+ //
+
+ newCount = TIMER_CLOCK_IN / Frequency;
+ if (newCount >= 0x10000) {
+ Result = FALSE;
+
+ } else {
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the speaker timer to the correct mode.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount & 0xff));
+ WRITE_REGISTER_UCHAR(&controlBase->SpeakerTone, (UCHAR)(newCount >> 8));
+
+ //
+ // Start the speaker.
+ //
+
+ NmiStatus.SpeakerGate = 1;
+ NmiStatus.SpeakerData = 1;
+ WRITE_REGISTER_UCHAR(&controlBase->NmiStatus, *((PUCHAR) &NmiStatus));
+ Result = TRUE;
+ }
+ }
+
+ //
+ // Release the beep spin lock and lower IRQL to its previous value.
+ //
+
+ KeReleaseSpinLock(&HalpBeepLock, OldIrql);
+ return Result;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/jxdisp.c b/private/ntos/nthals/halr98mp/mips/jxdisp.c
new file mode 100644
index 000000000..1882d69ee
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxdisp.c
@@ -0,0 +1,3132 @@
+#ident "@(#) NEC jxdisp.c 1.19 95/07/05 16:32:19"
+/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.10 93/12/01 12:18:22" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.9 93/11/19 13:48:37" ) */
+/* #pragma comment(exestr, "@(#) NEC(MIPS) jxdisp.c 1.7 93/11/18 14:57:07" ) */
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for a MIPS R3000 or R4000 Jazz system.
+
+History:
+
+--*/
+
+/*
+ * M001 1993.10.28 A. Kuriyama@oa2
+ *
+ * - Modify for R96 MIPS R4400
+ *
+ * Add : Initialize routine for Cirrus CL5428.
+ *
+ * Notes : HalpCirrusInterpretCmdStream() based on VgaInterpretCmdStream()
+ * in Cirrus Miniport Driver.
+ *
+ * M002 1993.11.10 M. Kusano
+ *
+ * - initialize bug fixed
+ *
+ * Add : Color palette initialize sequence.
+ *
+ * - scroll bug fixed
+ *
+ * Add : 32bit Move Memory routine.
+ *
+ * M003 1993.11.18 A. Kuriyama@oa2
+ *
+ * - Exchanged HalpMoveMemory32()
+ *
+ * Add : HalpMoveMemory32()
+ *
+ * M004 1993.11.18 M. Kusano
+ *
+ * - Modefy HalpMoveMemory32()
+ *
+ * Bug fix
+ *
+ *
+ * M005 1993.11.30 M.Kusano
+ *
+ * - Modefy Display Identifier
+ * Cirrus GD5428 -> necvdfrb
+ *
+ * #if defined(DBCS) && defined(_MIPS_)
+ *
+ * M006 1994.10.29 T.Samezima
+ *
+ * - Add display mode on vga
+ *
+ * #endif // DBCS && _MIPS_
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400 in Miniport Driver
+ *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ ***************************************************************
+ *
+ * S001 1994.06/06 T.Samezima
+ *
+ * - Modify for R98 MIPS R4400
+ *
+ * Change : memory and I/O Address
+ *
+ ***********************************************************************
+ *
+ * S002 1994.6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***************************************************************
+ *
+ * S003 1994.07/12 T.Samezima
+ *
+ * Change : I/O Address
+ *
+ *
+ * K000 94/10/11 N.Kugimoto
+ * fix 807 base
+ * K001 94/10/13 N.Kugimoto
+ * Chg resest-->reset
+ *
+ * S004 94/10/25 T.Samezima
+ * Add define _DUO_
+ *
+ * S005 94/11/23 T.Samezima
+ * Add Marge TGA(DEC21030) initialize rotine (program by T.Katoh 1994.11/15)
+ *
+ * S006 94/11/29 T.Katoh
+ * Bug Fix
+ *
+ * S007 94/12/07 T.Samezima
+ * Chg Color palet change.
+ *
+ * S008 94/12/12 T.Samezima
+ * Add Config read function.
+ * Chg Change PCI configuration read function from READ_REGISTER_ULONG
+ * to PciReadConfigUlong.
+ *
+ * S009 94/12/24-95/1/9 T.Samezima
+ * Add ESM logic.
+ *
+ * S00a 95/01/14 T.Samezima
+ * Chg Display string into nvram.
+ *
+ * S00b 95/03/14 T.Samezima
+ * Chg TGA parametor change.
+ * Add stall execution.
+ * Del Warning
+ * S00c 95/04/4 T.Samezima
+ * Chg TGA parametor change for adjust standard of VESA
+ * Windows-NT 3.51
+ * K1001 '95.7.5 N.Kugimoto
+ * Chg TGA parametor change for adjust standard of VESA
+ *
+ */
+
+
+#include "halp.h"
+#include "jazzvdeo.h"
+#include "jzvxl484.h"
+#include <jaginit.h>
+/* START M001 */
+#include "cirrus.h"
+#include "modeset.h"
+#include "mode542x.h"
+/* END M001 */
+#include "string.h"
+/* START S005 */
+#include <tga.h>
+/* END S005 */
+
+#define _DUO_ // S004
+
+//
+// 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, HalpInitializeDisplay0)
+#pragma alloc_text(INIT, HalpInitializeDisplay1)
+
+#endif
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+VOID
+HalpDisplayCharacter (
+ IN UCHAR Character
+ );
+
+VOID
+HalpOutputCharacter(
+ IN PUCHAR Glyph
+ );
+
+VOID
+HalpDisplayG300Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayG364Setup (
+ VOID
+ );
+
+VOID
+HalpDisplayVxlSetup (
+ VOID
+ );
+
+/* START M001 */
+VOID
+HalpDisplayCirrusSetup (
+ VOID
+ );
+
+BOOLEAN
+HalpCirrusInterpretCmdStream (
+ PUSHORT pusCmdStream
+ );
+/* END M001 */
+
+/* START M002 */
+VOID
+Write_Dbg_Uchar(
+PUCHAR,
+UCHAR
+);
+/* END M002 */
+
+/* START M003 */
+VOID
+HalpMoveMemory32 (
+ PUCHAR Destination,
+ PUCHAR Source,
+ ULONG Length
+);
+/* END M003 */
+/* START S005 */
+VOID
+HalpDisplayTgaSetup(
+ VOID
+ );
+/* END S005 */
+
+//
+// Define virtual address of the video memory and control registers.
+//
+
+#define VIDEO_MEMORY_BASE 0x40000000
+#define G300_VIDEO_CONTROL ((PG300_VIDEO_REGISTERS)0x403ff000)
+#define G364_VIDEO_CONTROL ((PG364_VIDEO_REGISTERS)0x403ff000)
+#define G364_VIDEO_RESET ((PVIDEO_REGISTER)0x403fe000)
+
+//
+// Define memory access constants for VXL
+//
+
+#define VXL_VIDEO_MEMORY_BASE 0x40000000
+#define BT484_BASE ((PBT484_REGISTERS)0x403fd000)
+#define CLOCK_BASE ((PUCHAR)0x403fe000)
+#define JAGUAR_BASE ((PJAGUAR_REGISTERS)0x403ff000)
+/* START M001 */
+/* Start S001 */
+#define CIRRUS_BASE ((PJAGUAR_REGISTERS)0x403ff000)
+/* End S001 */
+#define CIRRUS_OFFSET ((PUSHORT)0x3b0)
+/* END M001 */
+
+/* START S005 */
+#define KSEG1_BASE 0xa0000000
+#define TGA_REGISTER_BASE ((ULONG)0x403ff000) // S006
+#define R98_PCI_SPACE_BASE ((ULONG)0xc0000000) // S006
+#define R98_PCI1_ID ((PULONG)(0x18ca8800 | KSEG1_BASE))
+#define R98_PCI1_MEM_BASE ((PULONG)(0x18ca8810 | KSEG1_BASE))
+#define R98_PCI1_CS_REG ((PULONG)(0x18ca8804 | KSEG1_BASE))
+#define R98_PCI2_ID ((PULONG)(0x18ca9000 | KSEG1_BASE))
+#define R98_PCI2_MEM_BASE ((PULONG)(0x18ca9010 | KSEG1_BASE))
+#define R98_PCI2_CS_REG ((PULONG)(0x18ca9004 | KSEG1_BASE))
+#define R98_PCI3_ID ((PULONG)(0x18ca9800 | KSEG1_BASE))
+#define R98_PCI3_MEM_BASE ((PULONG)(0x18ca9810 | KSEG1_BASE))
+#define R98_PCI3_CS_REG ((PULONG)(0x18ca9804 | KSEG1_BASE))
+
+/* END S005 */
+
+//
+// The three type of g364 boards we support
+//
+
+#define JAZZG364 1
+#define MIPSG364 2
+#define OLIVETTIG364 3
+
+//
+// Define controller setup routine type.
+//
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+//
+// Define OEM font variables.
+//
+
+ULONG HalpBytesPerRow;
+ULONG HalpCharacterHeight;
+ULONG HalpCharacterWidth;
+ULONG HalpColumn;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+POEM_FONT_FILE_HEADER HalpFontHeader;
+ULONG HalpRow;
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+
+//
+// Define display variables.
+//
+
+BOOLEAN HalpDisplayOwnedByHal;
+ENTRYLO HalpDisplayPte;
+ULONG HalpDisplayControlBase = 0;
+ULONG HalpDisplayResetRegisterBase = 0;
+ULONG HalpDisplayVxlClockRegisterBase = 0;
+ULONG HalpDisplayVxlBt484RegisterBase = 0;
+ULONG HalpDisplayVxlJaguarRegisterBase = 0;
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = NULL;
+MONITOR_CONFIGURATION_DATA HalpMonitorConfigurationData;
+BOOLEAN HalpDisplayTypeUnknown = FALSE;
+ULONG HalpG364Type = 0;
+/* START M001 */
+LARGE_INTEGER HalpCirrusPhigicalVideo = {0,0};
+/* END M001 */
+
+// S008 vvv
+ULONG
+PciReadConfigUlong(
+ PULONG Addr
+ )
+{
+ ULONG reg;
+ ULONG regTmp;
+ ULONG returnValue;
+
+ reg = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iREN );
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, (reg & 0xffbfffff));
+
+ returnValue = READ_PORT_ULONG( Addr );
+
+ regTmp = READ_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS );
+ if( regTmp & 0x80000000 ){
+ WRITE_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS, 0x80000000);
+ regTmp = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE );
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE, (regTmp & 0xffbfffff) );
+ returnValue = 0xffffffff;
+ }
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN, reg);
+ return returnValue;
+}
+// S008 ^^^
+
+BOOLEAN
+HalpInitializeDisplay0 (
+ 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 Child;
+ PCONFIGURATION_COMPONENT_DATA ConfigurationEntry;
+ POEM_FONT_FILE_HEADER FontHeader;
+ ULONG Index;
+ ULONG MatchKey;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+ PLIST_ENTRY NextEntry;
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ ULONG StartingPfn;
+
+ //
+ // Set the address of the font file header and compute display variables.
+ //
+ // 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 = (FontHeader->PixelWidth + 7) / 8;
+ HalpCharacterHeight = FontHeader->PixelHeight;
+ HalpCharacterWidth = FontHeader->PixelWidth;
+
+ //
+ // Find the configuration entry for the first display controller.
+ //
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("HalpInitializeDisplay0\n");
+#endif
+ /* END M002 */
+
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("ConfigurationEntry Found\n");
+#endif
+ /* END M002 */
+
+ if (ConfigurationEntry == NULL) {
+ /* START S005 */
+ MatchKey = 1;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+ if (ConfigurationEntry == NULL) {
+ /* END S005 */
+ return FALSE;
+ /* START S005 */
+ }
+ /* END S005 */
+ }
+
+ //
+ // Determine which video controller is present in the system.
+ // Copy the display controller and monitor parameters in case they are
+ // needed later to reinitialize the display to output a message.
+ //
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "Jazz G300")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG300Setup;
+
+ HalpDisplayControlBase =
+ ((PJAZZ_G300_CONFIGURATION_DATA)
+ (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "Jazz G364")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG364Setup;
+ HalpG364Type = JAZZG364;
+
+ HalpDisplayControlBase = 0x60080000;
+
+// HalpDisplayControlBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ HalpDisplayResetRegisterBase = 0x60180000;
+
+// HalpDisplayResetRegisterBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ResetRegister;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "Mips G364")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG364Setup;
+ HalpG364Type = MIPSG364;
+
+ HalpDisplayControlBase = 0x60080000;
+
+// HalpDisplayControlBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ HalpDisplayResetRegisterBase = 0x60180000;
+
+// HalpDisplayResetRegisterBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ResetRegister;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "OLIVETTI_G364")) {
+
+ HalpDisplayControllerSetup = HalpDisplayG364Setup;
+ HalpG364Type = OLIVETTIG364;
+
+ HalpDisplayControlBase = 0x60080000;
+
+// HalpDisplayControlBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ControlBase;
+
+ HalpDisplayResetRegisterBase = 0x60180000;
+
+// HalpDisplayResetRegisterBase =
+// ((PJAZZ_G364_CONFIGURATION_DATA)
+// (ConfigurationEntry->ConfigurationData))->ResetRegister;
+
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "VXL")) {
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("VXL config found\n");
+#endif
+ /* END M002 */
+ HalpDisplayControllerSetup = HalpDisplayVxlSetup;
+ HalpDisplayVxlBt484RegisterBase = 0x60100000;
+ HalpDisplayVxlClockRegisterBase = 0x60200000;
+ HalpDisplayVxlJaguarRegisterBase = 0x60300000;
+
+ /* START M001 */
+ } else {
+
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "necvdfrb")) { /* M005 */
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("necvdfrb Config found\n"); /* M005 */
+#endif
+ /* END M002 */
+
+ HalpDisplayControllerSetup = HalpDisplayCirrusSetup;
+ /* Start S001,S003 */
+ HalpDisplayControlBase = 0x18cc0000;
+ /* End S001,S003 */
+ /* END M001 */
+
+ } else {
+
+ /* START S005 */
+ if (!strcmp(ConfigurationEntry->ComponentEntry.Identifier,
+ "10110004")) {
+ HalpDisplayControllerSetup = HalpDisplayTgaSetup;
+
+ if (PciReadConfigUlong(R98_PCI1_ID) == 0x00041011) { // S006
+ if ((PciReadConfigUlong(R98_PCI1_CS_REG) & 0x00000002) == 2){ // S006
+ HalpDisplayControlBase
+ = (PciReadConfigUlong(R98_PCI1_MEM_BASE) & 0xfffffff0)
+ | R98_PCI_SPACE_BASE // S006
+ + TGA_REG_SPC_OFFSET;
+ } else {
+ return FALSE;
+ }
+ } else if (PciReadConfigUlong(R98_PCI2_ID) == 0x00041011) { // S006
+ if ((PciReadConfigUlong(R98_PCI2_CS_REG) & 0x00000002) == 2){ // S006
+ HalpDisplayControlBase
+ = (PciReadConfigUlong(R98_PCI2_MEM_BASE) & 0xfffffff0)
+ | R98_PCI_SPACE_BASE // S006
+ + TGA_REG_SPC_OFFSET;
+ } else {
+ return FALSE;
+ }
+ } else if (PciReadConfigUlong(R98_PCI3_ID) == 0x00041011) { // S006
+ if ((PciReadConfigUlong(R98_PCI3_CS_REG) & 0x00000002) == 2){ // S006
+ HalpDisplayControlBase
+ = (PciReadConfigUlong(R98_PCI3_MEM_BASE) & 0xfffffff0)
+ | R98_PCI_SPACE_BASE // S006
+ + TGA_REG_SPC_OFFSET;
+ } else {
+ return FALSE;
+ }
+ }
+
+ } else {
+ /* END S005 */
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("DisplayTypeUnknown\n");
+#endif
+ /* END M002 */
+
+ HalpDisplayTypeUnknown = TRUE;
+ /* START S005 */
+ }
+ /* END S005 */
+ }
+ /* START M001 */
+ }
+ /* END M001 */
+ }
+ }
+ }
+ }
+
+ Child = ConfigurationEntry->Child;
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("parameters read start\n");
+#endif
+ /* END M002 */
+
+ RtlMoveMemory((PVOID)&HalpMonitorConfigurationData,
+ Child->ConfigurationData,
+ Child->ComponentEntry.ConfigurationDataLength);
+
+ //
+ // Compute character output display parameters.
+ //
+
+ HalpDisplayText =
+ HalpMonitorConfigurationData.VerticalResolution / HalpCharacterHeight;
+
+ /* START M002 */
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ HalpScrollLine =
+ 1024 * HalpCharacterHeight;
+ }else{
+ /* END M002 */
+
+ HalpScrollLine =
+ HalpMonitorConfigurationData.HorizontalResolution * HalpCharacterHeight;
+
+ /* START M002 */
+ }
+ /* END M002 */
+
+ HalpScrollLength = HalpScrollLine * (HalpDisplayText - 1);
+
+ /* START M002 */
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ HalpDisplayWidth =
+ 1024 / HalpCharacterWidth;
+
+ }else{
+ /* END M002 */
+
+ HalpDisplayWidth =
+ HalpMonitorConfigurationData.HorizontalResolution / HalpCharacterWidth;
+ /* START M002 */
+ }
+ /* END M002 */
+
+ //
+ // Scan the memory allocation descriptors and allocate a free page
+ // to map the video memory and control registers, and initialize the
+ // PDE entry.
+ //
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("Mem get \n");
+#endif
+ /* END M002 */
+
+
+ NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) {
+ MemoryDescriptor = CONTAINING_RECORD(NextEntry,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ if ((MemoryDescriptor->MemoryType == LoaderFree) &&
+ (MemoryDescriptor->PageCount > 1)) {
+ StartingPfn = MemoryDescriptor->BasePage;
+ MemoryDescriptor->BasePage += 1;
+ MemoryDescriptor->PageCount -= 1;
+ break;
+ }
+
+ NextEntry = NextEntry->Flink;
+ }
+
+ ASSERT(NextEntry != &LoaderBlock->MemoryDescriptorListHead);
+
+ Pte.X1 = 0;
+ Pte.PFN = StartingPfn;
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Save the page table page PTE for use in displaying information and
+ // map the appropriate PTE in the current page directory page to address
+ // the display controller page table page.
+ //
+
+ HalpDisplayPte = Pte;
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = Pte;
+
+ //
+ // Initialize the page table page.
+ //
+
+ PageFrame = (PENTRYLO)(PTE_BASE |
+ (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+
+ /* START M001 */
+ if (HalpDisplayControllerSetup == HalpDisplayCirrusSetup) {
+ /* Start S001 */
+ HalpCirrusPhigicalVideo.HighPart = 0;
+ HalpCirrusPhigicalVideo.LowPart = MEM_VGA | EISA_MEMORY_PHYSICAL_BASE;
+ /* End S001 */
+ Pte.PFN = (HalpCirrusPhigicalVideo.LowPart >> PAGE_SHIFT) &
+ (0x7fffffff >> PAGE_SHIFT-1) |
+ HalpCirrusPhigicalVideo.HighPart << (32 - PAGE_SHIFT);
+ }
+ else {
+ /* END M001 */
+ /* START S005 */
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) {
+ Pte.PFN = (HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET) >> PAGE_SHIFT;
+ } else {
+ /* END S005 */
+ Pte.PFN = VIDEO_MEMORY_BASE >> PAGE_SHIFT;
+ /* START S005 */
+ }
+ /* END S005 */
+ /* START M001 */
+ }
+ /* END M001 */
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+
+ Pte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ Pte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Page table entries of the video memory.
+ //
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ if (HalpDisplayControllerSetup == HalpDisplayVxlSetup) {
+
+ //
+ // If this is VXL then map a page for the
+ // brooktree base
+ // Clock base
+ // jaguar base
+ //
+
+ Pte.PFN = ((ULONG)HalpDisplayVxlBt484RegisterBase) >> PAGE_SHIFT;
+ *(PageFrame - 2) = Pte;
+
+ Pte.PFN = ((ULONG)HalpDisplayVxlClockRegisterBase) >> PAGE_SHIFT;
+ *(PageFrame - 1) = Pte;
+
+ Pte.PFN = ((ULONG)HalpDisplayVxlJaguarRegisterBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+
+ } else {
+
+ //
+ // If we have a G364, use the page before last to map the reset register.
+ //
+
+ if (HalpDisplayControllerSetup == HalpDisplayG364Setup) {
+ Pte.PFN = ((ULONG)HalpDisplayResetRegisterBase) >> PAGE_SHIFT;
+ *(PageFrame - 1) = Pte;
+ }
+
+ //
+ // Page table for the video registers.
+ //
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+ }
+
+ //
+ // Initialize the display controller.
+ //
+
+ HalpDisplayControllerSetup();
+
+ HalpInitDisplayStringIntoNvram(); // S009
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates pool for the OEM font file and copies the font
+ information from the OS Loader heap into the allocated pool.
+
+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.
+
+--*/
+
+{
+
+ PVOID FontHeader;
+
+ //
+ // Allocate a pool block and copy the OEM font information from the
+ // OS Loader heap into the pool block.
+ //
+
+ FontHeader = ExAllocatePool(NonPagedPool, HalpFontHeader->FileSize);
+ if (FontHeader == NULL) {
+ return FALSE;
+ }
+
+ RtlMoveMemory(FontHeader, HalpFontHeader, HalpFontHeader->FileSize);
+ HalpFontHeader = (POEM_FONT_FILE_HEADER)FontHeader;
+
+ HalpSetInitDisplayTimeStamp(); // S009
+
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters //K001
+ )
+
+/*++
+
+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:
+
+ ResetDisplayParameters - if non-NULL the address of a function
+ the hal can call to reset the video card. The function returns
+ TRUE if the display was reset.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ HalpSuccessOsStartUp(); // S009
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ return;
+}
+
+VOID
+HalpDisplayG300Setup (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the G300B display controller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG BackPorch;
+ PULONG Buffer;
+ ULONG DataLong;
+ ULONG FrontPorch;
+ ULONG HalfLineTime;
+ ULONG HalfSync;
+ ULONG Index;
+ ULONG Limit;
+ ULONG MultiplierValue;
+ ULONG ScreenUnitRate;
+ ULONG VerticalBlank;
+ ULONG ShortDisplay;
+ ULONG TransferDelay;
+
+ //
+ // Disable the G300B display controller.
+ //
+
+ DataLong = 0;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->PlainWave = 1;
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Parameters.Long, DataLong);
+
+ //
+ // Initialize the G300B boot register value.
+ //
+
+ ScreenUnitRate =
+ (HalpMonitorConfigurationData.HorizontalDisplayTime * 1000 * 4) /
+ (HalpMonitorConfigurationData.HorizontalResolution);
+
+ MultiplierValue = 125000 / (ScreenUnitRate / 4);
+ DataLong = 0;
+ ((PG300_VIDEO_BOOT)(&DataLong))->Multiplier = MultiplierValue;
+ ((PG300_VIDEO_BOOT)(&DataLong))->ClockSelect = 1;
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Boot.Long, DataLong);
+
+ //
+ // Wait for phase locked loop to stablize.
+ //
+
+ KeStallExecutionProcessor(50);
+
+ //
+ // Initialize the G300B operational values.
+ //
+
+ HalfSync =
+ (HalpMonitorConfigurationData.HorizontalSync * 1000) / ScreenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->HorizonalSync.Long, HalfSync);
+
+ BackPorch =
+ (HalpMonitorConfigurationData.HorizontalBackPorch * 1000) / ScreenUnitRate;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->BackPorch.Long, BackPorch);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Display.Long,
+ HalpMonitorConfigurationData.HorizontalResolution / 4);
+
+ HalfLineTime = ((HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch +
+ HalpMonitorConfigurationData.HorizontalBackPorch +
+ HalpMonitorConfigurationData.HorizontalDisplayTime) * 1000) / ScreenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->LineTime.Long, HalfLineTime * 2);
+ FrontPorch =
+ (HalpMonitorConfigurationData.HorizontalFrontPorch * 1000) / ScreenUnitRate;
+
+ ShortDisplay = HalfLineTime - ((HalfSync * 2) + BackPorch + FrontPorch);
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ShortDisplay.Long, ShortDisplay);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->BroadPulse.Long,
+ HalfLineTime - FrontPorch);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalSync.Long,
+ HalpMonitorConfigurationData.VerticalSync * 2);
+
+ VerticalBlank = (HalpMonitorConfigurationData.VerticalFrontPorch +
+ HalpMonitorConfigurationData.VerticalBackPorch -
+ (HalpMonitorConfigurationData.VerticalSync * 2)) * 2;
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalBlank.Long,
+ VerticalBlank);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->VerticalDisplay.Long,
+ HalpMonitorConfigurationData.VerticalResolution * 2);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->LineStart.Long, LINE_START_VALUE);
+ if (BackPorch < ShortDisplay) {
+ TransferDelay = BackPorch - 1;
+ } else {
+ TransferDelay = ShortDisplay - 1;
+ }
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->TransferDelay.Long, TransferDelay);
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->DmaDisplay.Long,
+ 1024 - TransferDelay);
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->PixelMask.Long, G300_PIXEL_MASK_VALUE);
+
+ //
+ // Initialize the G300B control parameters.
+ //
+
+ DataLong = 0;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->EnableVideo = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->PlainWave = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->SeparateSync = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->DelaySync = G300_DELAY_SYNC_CYCLES;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->BlankOutput = 1;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->BitsPerPixel = EIGHT_BITS_PER_PIXEL;
+ ((PG300_VIDEO_PARAMETERS)(&DataLong))->AddressStep = 2;
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->Parameters.Long, DataLong);
+
+ //
+ // Set up the color map for two colors.
+ //
+
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ColorMapData[0], 0xffffff);
+ WRITE_REGISTER_ULONG(&G300_VIDEO_CONTROL->ColorMapData[1], 0x900000);
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+ Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / 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;
+}
+
+VOID
+HalpDisplayG364Setup(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the G364 display controller chip.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG videoClock;
+ ULONG videoPeriod;
+ ULONG backPorch;
+ ULONG dataLong;
+ ULONG frontPorch;
+ ULONG halfLineTime;
+ ULONG halfSync;
+ PULONG buffer;
+ ULONG index;
+ ULONG limit;
+ ULONG multiplierValue;
+ ULONG screenUnitRate;
+ ULONG shortDisplay;
+ ULONG transferDelay;
+ ULONG verticalBlank;
+
+ //
+ // Reset the G364 display controller.
+ //
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_RESET->Long,
+ 0);
+
+ //
+ // Initialize the G364 boot register value.
+ //
+
+ if (HalpG364Type == MIPSG364) {
+
+ videoClock = 5000000;
+
+ } else {
+
+ videoClock = 8000000;
+
+ }
+
+ videoPeriod = 1000000000 / (videoClock / 1000);
+
+ screenUnitRate = (HalpMonitorConfigurationData.HorizontalDisplayTime * 1000 * 4) /
+ (HalpMonitorConfigurationData.HorizontalResolution);
+
+ multiplierValue = videoPeriod / (screenUnitRate / 4);
+ dataLong = 0;
+ ((PG364_VIDEO_BOOT)(&dataLong))->Multiplier = multiplierValue;
+ ((PG364_VIDEO_BOOT)(&dataLong))->ClockSelect = 1;
+ ((PG364_VIDEO_BOOT)(&dataLong))->MicroPort64Bits = 1;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Boot.Long,
+ dataLong);
+
+ //
+ // Wait for phase locked loop to stablize.
+ //
+
+ KeStallExecutionProcessor(50);
+
+ //
+ // Initialize the G364 control parameters.
+ //
+
+ dataLong = 0;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->DelaySync = G364_DELAY_SYNC_CYCLES;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->BitsPerPixel = EIGHT_BITS_PER_PIXEL;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->AddressStep = G364_ADDRESS_STEP_INCREMENT;
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->DisableCursor = 1;
+
+ if (HalpG364Type == OLIVETTIG364) {
+
+ //
+ // Initialize the G364 control parameters for VDR1 with patch for HSync
+ // problem during the VBlank. The control register is set to 0xB03041
+ // according to the hardware specs. @msu, Olivetti, 5/14/92
+ //
+
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->VideoOnly = 1;
+
+ } else {
+
+ //
+ // Only set tesselated sync in non-olivetti G364 cards when
+ // vertical frontporch is set to 1
+ //
+
+ if (HalpMonitorConfigurationData.VerticalFrontPorch != 1) {
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->PlainSync = 1;
+ }
+
+ }
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Parameters.Long,
+ dataLong);
+
+ //
+ // Initialize the G364 operational values.
+ //
+
+ halfSync = (HalpMonitorConfigurationData.HorizontalSync * 1000) / screenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->HorizontalSync.Long,
+ halfSync);
+
+ backPorch = (HalpMonitorConfigurationData.HorizontalBackPorch * 1000) / screenUnitRate;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BackPorch.Long,
+ backPorch);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Display.Long,
+ HalpMonitorConfigurationData.HorizontalResolution / 4);
+
+ halfLineTime = ((HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch +
+ HalpMonitorConfigurationData.HorizontalBackPorch +
+ HalpMonitorConfigurationData.HorizontalDisplayTime) * 1000) /
+ screenUnitRate / 2;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->LineTime.Long,
+ halfLineTime * 2);
+
+ frontPorch = (HalpMonitorConfigurationData.HorizontalFrontPorch * 1000) /
+ screenUnitRate;
+
+ shortDisplay = halfLineTime - ((halfSync * 2) + backPorch + frontPorch);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ShortDisplay.Long,
+ shortDisplay);
+
+ if (HalpG364Type == OLIVETTIG364) {
+
+ //
+ // Initialize Broad Pulse, Vertical PreEqualize and Vertical
+ // PostEqualize registers to work with Olivetti monitors.
+ // @msu, Olivetti, 5/14/92
+ //
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BroadPulse.Long,
+ 0x30);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPreEqualize.Long,
+ 2);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPostEqualize.Long,
+ 2);
+
+ } else {
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->BroadPulse.Long,
+ halfLineTime - frontPorch);
+
+ // NOTE: changed the order to simplify if statement .
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPreEqualize.Long,
+ HalpMonitorConfigurationData.VerticalFrontPorch * 2);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalPostEqualize.Long,
+ 2);
+
+ }
+
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalSync.Long,
+ HalpMonitorConfigurationData.VerticalSync * 2);
+
+ verticalBlank = (HalpMonitorConfigurationData.VerticalBackPorch - 1) * 2;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalBlank.Long,
+ verticalBlank);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->VerticalDisplay.Long,
+ HalpMonitorConfigurationData.VerticalResolution * 2);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->LineStart.Long,
+ LINE_START_VALUE);
+
+ if (HalpG364Type == OLIVETTIG364) {
+
+ //
+ // Fixes for Olivetti monitors, @msu, Olivetti
+ //
+
+ transferDelay = 30; // @msu
+
+ } else {
+
+ if (backPorch < shortDisplay) {
+ transferDelay = backPorch - 1;
+ } else {
+ transferDelay = shortDisplay - 4;
+ }
+ }
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->TransferDelay.Long,
+ transferDelay);
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->DmaDisplay.Long,
+ 1024 - transferDelay);
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->PixelMask.Long,
+ 0xFFFFFF);
+
+ //
+ // Enable video
+ //
+
+ ((PG364_VIDEO_PARAMETERS)(&dataLong))->EnableVideo = 1;
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->Parameters.Long,
+ dataLong);
+
+ //
+ // Set up the color map for two colors.
+ // NOTE: this device is not RGB but BGR.
+ //
+
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ColorMapData[0], 0xffffff);
+ WRITE_REGISTER_ULONG(&G364_VIDEO_CONTROL->ColorMapData[1], 0x000090);
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ buffer = (PULONG)VIDEO_MEMORY_BASE;
+ limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / 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;
+}
+
+VOID
+HalpDisplayVxlSetup(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the JazzVxl Graphics accelerator.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+
+ UCHAR DataChar;
+ UCHAR CmdReg0;
+ ULONG Status;
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+
+
+ //
+ // Define clock value for the ICS part (pS)
+ //
+
+ LONG ClockResList[32] = { 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4,42918,40984,38760,36724,33523,31017,
+ 29197,27548,24882,23491,22482,21468,20509,19920,
+ 18692,18054,16722,15015,14773,14053,13040, 4};
+
+ JAGUAR_REG_INIT JagInitData;
+
+ LONG HorDisplayTime;
+ LONG HorResolutionDiv;
+ LONG RequestedClockPeriod;
+ LONG CurrentClockError;
+ LONG MinErrorValue;
+ USHORT MinErrorIndex;
+ LONG ShiftClockPeriod;
+
+ USHORT BoardTypeBt485;
+
+
+
+ //
+ // Determine if this is a Bt484 or Bt485 board. To do this write a 1 to command
+ // register bit 07 then write 01 to the address register 0. This will enable
+ // read/writes to command register 3 on a Bt485 but not on a Bt484. Clear
+ // Command register 3 then read it back. On a Bt485 the return value will be 0x00,
+ // on a Bt484 it will be 0x40.
+ //
+ // Get the value in command register 0, then set bit 07
+ //
+
+ DataChar = READ_REGISTER_UCHAR(&BT484_BASE->Command0.Byte);
+ DataChar |= 0x80;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,DataChar);
+
+ //
+ // Write 0x01 to the address register
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0x01);
+
+ //
+ // Clear command register 3
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Status.Byte,0x00);
+
+ //
+ // Read Command Register 3 back and compare
+ //
+
+ DataChar = READ_REGISTER_UCHAR(&BT484_BASE->Status.Byte);
+
+ if (DataChar != 0x00) {
+
+ //
+ // This is a Bt484
+ //
+
+ BoardTypeBt485 = 0;
+ JagInitData.Bt485Multiply = 0;
+
+ } else {
+
+ //
+ // This is a Bt485
+ //
+
+ BoardTypeBt485 = 1;
+ JagInitData.Bt485Multiply = 0;
+ }
+
+ //
+ // Calculate the requested clock frequency then find the closest match in the
+ // ICS clock frequency table. The requested clock frequency in picoseconds =
+ //
+ // Horizontal display time * 1000000
+ // ---------------------------------
+ // horizontal resolution
+ //
+ //
+
+ HorDisplayTime = HalpMonitorConfigurationData.HorizontalDisplayTime * 1000;
+ HorResolutionDiv = HalpMonitorConfigurationData.HorizontalResolution;
+ RequestedClockPeriod = HorDisplayTime / HorResolutionDiv;
+
+ //
+ // Check for a Bt485 frequency
+ //
+
+ if ((BoardTypeBt485 == 1) && (RequestedClockPeriod < ClockResList[30])) {
+ RequestedClockPeriod = RequestedClockPeriod * 2;
+ JagInitData.Bt485Multiply = 1;
+ }
+
+ MinErrorIndex = 0;
+
+ //
+ // Gaurentee a maximum starting error
+ //
+
+ MinErrorValue = RequestedClockPeriod + 1;
+ for (Index = 0; Index < 32; Index++) {
+
+ //
+ // Calculate the absolute value of clock error and find the
+ // closest match in the array of clock values
+ //
+
+ CurrentClockError = RequestedClockPeriod - ClockResList[Index];
+ if (CurrentClockError < 0) {
+ CurrentClockError *= -1;
+ }
+
+ if (CurrentClockError < MinErrorValue) {
+ MinErrorValue = CurrentClockError;
+ MinErrorIndex = (USHORT)Index;
+ }
+ }
+
+ //
+ // We now have a closest match in the clock array, now calculate the
+ // values for the Bt484/Bt485 register values
+ //
+
+ JagInitData.ClockFreq = (UCHAR)MinErrorIndex; // S002
+ JagInitData.BitBltControl = 1;
+ JagInitData.TopOfScreen = 0;
+ JagInitData.XferLength = 0x200;
+ JagInitData.VerticalInterruptLine = 4;
+ JagInitData.HorizontalDisplay = HalpMonitorConfigurationData.HorizontalResolution;
+
+ //
+ // All jaguar timing values are based on the brooktree shift clock value which
+ // is the clock frequency divided by 4. (period * 4) If this is a Bt485 using
+ // its internal 2x clock multiplier than is is period * 2; (freq * 2 / 4)
+ //
+
+ if (JagInitData.Bt485Multiply == 1) {
+ ShiftClockPeriod = ClockResList[MinErrorIndex] * 2;
+ } else {
+ ShiftClockPeriod = ClockResList[MinErrorIndex] * 4;
+ }
+
+ JagInitData.HorizontalBlank = (USHORT)( ((HalpMonitorConfigurationData.HorizontalBackPorch +
+ HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch) * 1000)
+ / ShiftClockPeriod); // S002
+
+ JagInitData.HorizontalBeginSync = (USHORT)((HalpMonitorConfigurationData.HorizontalFrontPorch * 1000)
+ / ShiftClockPeriod); // S002
+
+ JagInitData.HorizontalEndSync = (USHORT)(((HalpMonitorConfigurationData.HorizontalSync +
+ HalpMonitorConfigurationData.HorizontalFrontPorch) * 1000)
+ / ShiftClockPeriod); // S002
+
+ JagInitData.HorizontalLine = JagInitData.HorizontalBlank +
+ (HalpMonitorConfigurationData.HorizontalResolution / 4);
+
+ JagInitData.VerticalBlank = HalpMonitorConfigurationData.VerticalBackPorch +
+ HalpMonitorConfigurationData.VerticalSync +
+ HalpMonitorConfigurationData.VerticalFrontPorch;
+
+ JagInitData.VerticalBeginSync = HalpMonitorConfigurationData.VerticalFrontPorch;
+
+ JagInitData.VerticalEndSync = HalpMonitorConfigurationData.VerticalFrontPorch +
+ HalpMonitorConfigurationData.VerticalSync;
+
+ JagInitData.VerticalLine = HalpMonitorConfigurationData.VerticalBackPorch +
+ HalpMonitorConfigurationData.VerticalSync +
+ HalpMonitorConfigurationData.VerticalFrontPorch +
+ HalpMonitorConfigurationData.VerticalResolution;
+
+ //
+ // Start ICS Clock pll and stabilize.
+ //
+
+ WRITE_REGISTER_UCHAR(CLOCK_BASE,JagInitData.ClockFreq);
+
+ //
+ // Wait 10 uS for PLL clock to stabilize on the video board
+ //
+
+ for (Index = 0; Index < 10; Index++) {
+ READ_REGISTER_UCHAR(CLOCK_BASE);
+ }
+
+ //
+ // Initialize Bt484 Command Register 0 to:
+ //
+ // 8 Bit DAC Resolution
+ //
+
+ CmdReg0 = 0;
+ ((PBT484_COMMAND0)(&CmdReg0))->DacResolution = 1;
+ ((PBT484_COMMAND0)(&CmdReg0))->GreenSyncEnable = 1;
+ ((PBT484_COMMAND0)(&CmdReg0))->SetupEnable = 1;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,CmdReg0);
+
+ //
+ // Initialize Command Register 1 to:
+ //
+
+ DataChar = 0;
+ ((PBT484_COMMAND1)(&DataChar))->BitsPerPixel = VXL_EIGHT_BITS_PER_PIXEL;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command1.Byte,DataChar);
+
+ //
+ // Initialize Command Register 2 to:
+ //
+ // SCLK Enabled
+ // TestMode disabled
+ // PortselMask Non Masked
+ // PCLK 1
+ // NonInterlaced
+ //
+
+ DataChar = 0;
+ ((PBT484_COMMAND2)(&DataChar))->SclkDisable = 0;
+ ((PBT484_COMMAND2)(&DataChar))->TestEnable = 0;
+ ((PBT484_COMMAND2)(&DataChar))->PortselMask = 1;
+ ((PBT484_COMMAND2)(&DataChar))->PclkSelect = 1;
+ ((PBT484_COMMAND2)(&DataChar))->InterlacedDisplay = 0;
+ ((PBT484_COMMAND2)(&DataChar))->PaletteIndexing = CONTIGUOUS_PALETTE;
+ ((PBT484_COMMAND2)(&DataChar))->CursorMode = BT_CURSOR_WINDOWS;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command2.Byte,DataChar);
+
+ //
+ // if JagInitData.ClockFreq bit 8 is set then this is a Bt485 mode that requires
+ // the internal 2x clock multiplier to be enabled.
+ //
+
+ if (JagInitData.Bt485Multiply == 1) {
+
+ //
+ // To access cmd register 3, first set bit CR17 in command register 0
+ //
+
+ CmdReg0 |= 0x80;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Command0.Byte,CmdReg0);
+
+ //
+ // Write a 0x01 to Address register
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0x01);
+
+ //
+ // Write to cmd register 3 in the status register location. Cmd3 is initialized
+ // to turn on the 2x clock multiplier.
+ //
+
+ DataChar = 0;
+ ((PBT484_COMMAND3)(&DataChar))->ClockMultiplier = 1;
+ WRITE_REGISTER_UCHAR(&BT484_BASE->Status.Byte,DataChar);
+
+ //
+ // Allow 10 uS for the 2x multiplier to stabilize
+ //
+
+ for (Index = 0; Index < 10; Index++) {
+ READ_REGISTER_UCHAR(CLOCK_BASE);
+ }
+ }
+
+ //
+ // Initialize Color Palette. Only init the first 2 entries
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0);
+
+ //
+ // Entry 0 red
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff);
+
+ //
+ // Entry 0 green
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff);
+
+ //
+ // Entry 0 blue
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0xff);
+
+ //
+ // Entry 1 red
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x00);
+
+ //
+ // Entry 1 green
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x00);
+
+ //
+ // Entry 1 blue
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteColor.Byte,0x90);
+
+ //
+ // Initialize Cursor and Overscan color.
+ //
+ // Set address pointer base.
+ // Zero 4 entries.
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorColorWrAddress.Byte,0);
+ for (Index = 0; Index < 4*3; Index++) {
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorColor.Byte,0);
+ }
+
+ //
+ // Initialize cursor RAM
+ //
+ // Set address pointer to base of ram.
+ // Clear both planes
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PaletteCursorWrAddress.Byte,0);
+ for (Index = 0; Index < 256; Index++) {
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorRam.Byte,0);
+ }
+
+ //
+ // Initialize cursor position registers--cursor off.
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorXLow.Byte,0);
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorXHigh.Byte,0);
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorYLow.Byte,0);
+ WRITE_REGISTER_UCHAR(&BT484_BASE->CursorYHigh.Byte,0);
+
+ //
+ // Initialize pixel mask.
+ //
+
+ WRITE_REGISTER_UCHAR(&BT484_BASE->PixelMask.Byte,0xFF);
+
+ //
+ // Init Jaguar Registers
+ //
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->TopOfScreen.Short,
+ JagInitData.TopOfScreen);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalBlank.Short,
+ JagInitData.HorizontalBlank);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalBeginSync.Short,
+ JagInitData.HorizontalBeginSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalEndSync.Short,
+ JagInitData.HorizontalEndSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalLine.Short,
+ JagInitData.HorizontalLine);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalBlank.Short,
+ JagInitData.VerticalBlank);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalBeginSync.Short,
+ JagInitData.VerticalBeginSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalEndSync.Short,
+ JagInitData.VerticalEndSync);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalLine.Short,
+ JagInitData.VerticalLine);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->XferLength.Short,
+ JagInitData.XferLength);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->VerticalInterruptLine.Short,
+ JagInitData.VerticalInterruptLine);
+
+ WRITE_REGISTER_USHORT(&JAGUAR_BASE->HorizontalDisplay.Short,
+ JagInitData.HorizontalDisplay);
+
+ WRITE_REGISTER_UCHAR(&JAGUAR_BASE->BitBltControl.Byte,
+ JagInitData.BitBltControl);
+
+ //
+ // Enable timing.
+ //
+
+ WRITE_REGISTER_UCHAR(&JAGUAR_BASE->MonitorControl,MONITOR_TIMING_ENABLE);
+
+ //
+ // Set the video memory to address color one.
+ //
+
+ Buffer = (PULONG)VXL_VIDEO_MEMORY_BASE;
+ Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / 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;
+}
+
+/* START M001 */
+VOID
+HalpDisplayCirrusSetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the Cirrus VGA display controlleer.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+ ULONG dac_address, dac_reg;
+
+#if defined(DBCS) && defined(_MIPS_)
+ // M006 vvv
+ ULONG verticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+ //
+ // Calculate vertical frequency.
+ //
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ verticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+ switch (HalpMonitorConfigurationData.HorizontalResolution) {
+ case 640:
+ if( verticalFrequency < 66 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 640x480 60Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+#if defined (R96DBG)
+ DbgPrint("HAL: 640x480 72Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_72);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+
+ case 800:
+ if( verticalFrequency < 58 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 800x600 56Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_56);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else if( verticalFrequency < 66 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 800x600 60Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+#if defined (R96DBG)
+ DbgPrint("HAL: 800x600 72Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_800x600_256_72);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+
+ case 1024:
+ // S005 vvv
+ if( verticalFrequency < 52 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 1024x768 87Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else
+ // S005 ^^^
+ if( verticalFrequency < 65 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 1024x768 60Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else if( verticalFrequency < 78 ) {
+#if defined (R96DBG)
+ DbgPrint("HAL: 1024x768 70Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_70);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ } else {
+#if defined (R96DBG)
+ DbgPrint("HAL: 1024x768 87Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_1024x768_256_87);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ }
+ break;
+ default:
+ // S005 vvv
+#if defined (R96DBG)
+ DbgPrint("HAL: 640x480 60Hz setup\n");
+#endif
+ HalpCirrusInterpretCmdStream(CL542x_640x480_256_60);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+// return;
+ // S005 ^^^
+ }
+ // M006 ^^^
+#else // defined(DBCS) && defined(_MIPS_)
+
+ switch (HalpMonitorConfigurationData.HorizontalResolution) {
+ case 640:
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("640x480 setup\n");
+#endif
+ /* END M002 */
+
+ HalpCirrusInterpretCmdStream(HalpCirrus_640x480_256);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ break;
+ case 800:
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("800x600 setup\n");
+#endif
+ /* END M002 */
+
+ HalpCirrusInterpretCmdStream(HalpCirrus_800x600_256);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ break;
+ case 1024:
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("1024x768 setup\n");
+#endif
+ /* END M002 */
+
+ HalpCirrusInterpretCmdStream(HalpCirrus_1024x768_256);
+ HalpCirrusInterpretCmdStream(HalpCirrus_MODESET_1K_WIDE);
+ break;
+ default:
+ return;
+ }
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("color set\n");
+#endif
+
+ dac_address = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_ADDRESS_WRITE_PORT;
+ dac_reg = (ULONG)CIRRUS_BASE + 0x3b0 + DAC_DATA_REG_PORT;
+
+
+
+ Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x0);
+
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x3f);
+
+ Write_Dbg_Uchar((PUCHAR)dac_address, (UCHAR)0x1);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)0x00);
+ Write_Dbg_Uchar((PUCHAR)dac_reg, (UCHAR)(0x90 >> 2));
+ /* END M002 */
+
+ //
+ // Set the video memory to address color one.
+ //
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+// Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+// HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+ /* START M002 */
+ Limit = (1024 *
+ HalpMonitorConfigurationData.VerticalResolution) / sizeof(ULONG);
+ /* END M002 */
+
+ 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;
+}
+
+BOOLEAN
+HalpCirrusInterpretCmdStream(
+ PUSHORT pusCmdStream
+ )
+
+/*++
+
+Routine Description:
+
+ Interprets the appropriate command array to set up VGA registers for the
+ requested mode. Typically used to set the VGA into a particular mode by
+ programming all of the registers
+
+Arguments:
+
+
+ pusCmdStream - array of commands to be interpreted.
+
+Return Value:
+
+ The status of the operation (can only fail on a bad command); TRUE for
+ success, FALSE for failure.
+
+Revision History:
+--*/
+
+
+
+{
+ ULONG ulCmd;
+ ULONG ulPort;
+ UCHAR jValue;
+ USHORT usValue;
+ ULONG culCount;
+ ULONG ulIndex;
+ ULONG ulBase;
+ if (pusCmdStream == NULL) {
+
+ return TRUE;
+ }
+
+ ulBase = (ULONG)CIRRUS_BASE+0x3b0;
+
+ //
+ // Now set the adapter to the desired mode.
+ //
+
+ while ((ulCmd = *pusCmdStream++) != EOD) {
+
+ //
+ // Determine major command type
+ //
+
+ switch (ulCmd & 0xF0) {
+
+ //
+ // Basic input/output command
+ //
+
+ case INOUT:
+
+ //
+ // Determine type of inout instruction
+ //
+
+ if (!(ulCmd & IO)) {
+
+ //
+ // Out instruction. Single or multiple outs?
+ //
+
+ if (!(ulCmd & MULTI)) {
+
+ //
+ // Single out. Byte or word out?
+ //
+
+ if (!(ulCmd & BW)) {
+
+ //
+ // Single byte out
+ //
+
+ ulPort = *pusCmdStream++;
+ jValue = (UCHAR) *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort),
+ jValue);
+ /* END M002 */
+
+
+ } else {
+
+ //
+ // Single word out
+ //
+
+ ulPort = *pusCmdStream++;
+ usValue = *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort), (UCHAR)(usValue & 0x00ff));
+ /* END M002 */
+
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)(ulBase+ulPort+1 ), (UCHAR)(usValue >> 8));
+ /* END M002 */
+
+
+ }
+
+ } else {
+
+ //
+ // Output a string of values
+ // Byte or word outs?
+ //
+
+ if (!(ulCmd & BW)) {
+
+ //
+ // String byte outs. Do in a loop; can't use
+ // VideoPortWritePortBufferUchar because the data
+ // is in USHORT form
+ //
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+
+ while (culCount--) {
+ jValue = (UCHAR) *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort,
+ jValue);
+ /* END M002 */
+
+
+ }
+
+ } else {
+
+ //
+ // String word outs
+ //
+
+ ulPort = *pusCmdStream++;
+ culCount = *pusCmdStream++;
+//
+// Buffering out is not use on the Miniport Driver for R96 machine.
+//
+
+ /* START L001 */
+
+ while(culCount--)
+ {
+ usValue = *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)
+ (ulBase + ulPort), (UCHAR) (usValue & 0x00ff));
+ Write_Dbg_Uchar((PUCHAR)
+ (ulBase + ulPort+1), (UCHAR) (usValue >> 8));
+ /* END M002 */
+
+ }
+
+ /* END L001 */
+ }
+ }
+
+ } else {
+
+ // In instruction
+ //
+ // Currently, string in instructions aren't supported; all
+ // in instructions are handled as single-byte ins
+ //
+ // Byte or word in?
+ //
+
+ if (!(ulCmd & BW)) {
+ //
+ // Single byte in
+ //
+
+ ulPort = *pusCmdStream++;
+ jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort);
+
+ } else {
+
+ //
+ // Single word in
+ //
+
+ ulPort = *pusCmdStream++;
+ usValue = READ_REGISTER_USHORT((PUSHORT)
+ (ulBase+ulPort));
+ }
+
+ }
+
+ break;
+
+ //
+ // Higher-level input/output commands
+ //
+
+ case METAOUT:
+
+ //
+ // Determine type of metaout command, based on minor
+ // command field
+ //
+ switch (ulCmd & 0x0F) {
+
+ //
+ // Indexed outs
+ //
+
+ case INDXOUT:
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ ulIndex = *pusCmdStream++;
+
+ while (culCount--) {
+
+ usValue = (USHORT) (ulIndex +
+ (((ULONG)(*pusCmdStream++)) << 8));
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort, (UCHAR) (usValue & 0x00ff));
+ /* END M002 */
+
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort+1, (UCHAR) (usValue >> 8));
+ /* END M002 */
+
+
+ ulIndex++;
+
+ }
+
+ break;
+
+ //
+ // Masked out (read, AND, XOR, write)
+ //
+
+ case MASKOUT:
+
+ ulPort = *pusCmdStream++;
+ jValue = READ_REGISTER_UCHAR((PUCHAR)ulBase+ulPort);
+ jValue &= *pusCmdStream++;
+ jValue ^= *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulBase + ulPort,
+ jValue);
+ /* END M002 */
+
+ break;
+
+ //
+ // Attribute Controller out
+ //
+
+ case ATCOUT:
+
+ ulPort = ulBase + *pusCmdStream++;
+ culCount = *pusCmdStream++;
+ ulIndex = *pusCmdStream++;
+
+ while (culCount--) {
+
+ // Write Attribute Controller index
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort,
+ (UCHAR)ulIndex);
+ /* END M002 */
+
+
+ // Write Attribute Controller data
+ jValue = (UCHAR) *pusCmdStream++;
+
+ /* START M002 */
+ Write_Dbg_Uchar((PUCHAR)ulPort, jValue);
+ /* END M002 */
+
+
+ ulIndex++;
+
+ }
+
+ break;
+
+ //
+ // None of the above; error
+ //
+ default:
+
+ return FALSE;
+
+ }
+
+
+ break;
+
+ //
+ // NOP
+ //
+
+ case NCMD:
+
+ break;
+
+ //
+ // Unknown command; error
+ //
+
+ default:
+
+ return FALSE;
+
+ }
+
+ }
+
+ return TRUE;
+
+} // end HalpCirrusInterpretCmdStream()
+/* END M001 */
+
+/* START S005 */
+VOID
+HalpDisplayTgaSetup(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the Tga(DEC21030) Graphics accelerator.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PUCHAR PLLbits;
+ ULONG i, j;
+ ULONG PLLdata;
+ ULONG ColorData;
+ PULONG Buffer;
+ LONG Limit;
+ LONG Index;
+ ULONG VerticalFrequency;
+ ULONG horizontalTotal;
+ ULONG verticalTotal;
+
+ // Start S006
+ // ULONG NowDisplayControlBase;
+ // PENTRYLO PageFrame;
+ // ENTRYLO Pte;
+ // End S006
+
+ // S00b vvv
+ const UCHAR PLLbits640x480_72[7] = { 0x80, 0x04, 0x80, 0xa4, 0x51, 0x80, 0x70 };
+ const UCHAR PLLbits640x480_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0xc4, 0x10, 0x78 };
+ const UCHAR PLLbits800x600_72[7] = { 0x80, 0x08, 0x80, 0x24, 0xf1, 0x60, 0x38 }; // S00c
+ const UCHAR PLLbits800x600_60[7] = { 0x80, 0x04, 0x80, 0xa5, 0x78, 0x20, 0x08 };
+ const UCHAR PLLbits1024x768_60[7] = { 0x80, 0x00, 0x80, 0x24, 0x48, 0x20, 0x98 };
+ // S00b ^^^
+
+ const UCHAR Vga_Ini_ColorTable[48] =
+ { VGA_INI_PALETTE_HI_WHITE_R, VGA_INI_PALETTE_HI_WHITE_G, VGA_INI_PALETTE_HI_WHITE_B, // S006, S007
+ VGA_INI_PALETTE_BLUE_R, VGA_INI_PALETTE_BLUE_G, VGA_INI_PALETTE_BLUE_B, // S006
+ VGA_INI_PALETTE_GREEN_R, VGA_INI_PALETTE_GREEN_B, VGA_INI_PALETTE_GREEN_G,
+ VGA_INI_PALETTE_YELLOW_R, VGA_INI_PALETTE_YELLOW_G, VGA_INI_PALETTE_YELLOW_B,
+ VGA_INI_PALETTE_RED_R, VGA_INI_PALETTE_RED_G, VGA_INI_PALETTE_RED_B, // S006
+ VGA_INI_PALETTE_MAGENTA_R, VGA_INI_PALETTE_MAGENTA_G, VGA_INI_PALETTE_MAGENTA_B,
+ VGA_INI_PALETTE_CYAN_R, VGA_INI_PALETTE_CYAN_G, VGA_INI_PALETTE_CYAN_B,
+ VGA_INI_PALETTE_BLACK_R, VGA_INI_PALETTE_BLACK_G, VGA_INI_PALETTE_BLACK_B, // S006
+ VGA_INI_PALETTE_WHITE_R, VGA_INI_PALETTE_WHITE_G, VGA_INI_PALETTE_WHITE_B, // S006, S007
+ VGA_INI_PALETTE_HI_BLUE_R, VGA_INI_PALETTE_HI_BLUE_G, VGA_INI_PALETTE_HI_BLUE_B, // S006
+ VGA_INI_PALETTE_HI_GREEN_R, VGA_INI_PALETTE_HI_GREEN_G, VGA_INI_PALETTE_HI_GREEN_B,
+ VGA_INI_PALETTE_HI_YELLOW_R, VGA_INI_PALETTE_HI_YELLOW_G, VGA_INI_PALETTE_HI_YELLOW_B,
+ VGA_INI_PALETTE_HI_RED_R, VGA_INI_PALETTE_HI_RED_G, VGA_INI_PALETTE_HI_RED_B, // S006
+ VGA_INI_PALETTE_HI_MAGENTA_R, VGA_INI_PALETTE_HI_MAGENTA_G, VGA_INI_PALETTE_HI_MAGENTA_B,
+ VGA_INI_PALETTE_HI_CYAN_R, VGA_INI_PALETTE_HI_CYAN_G, VGA_INI_PALETTE_HI_CYAN_B,
+ VGA_INI_PALETTE_HI_BLACK_R, VGA_INI_PALETTE_HI_BLACK_G, VGA_INI_PALETTE_HI_BLACK_B // S006
+ };
+
+ // Start S006
+ ////
+ //// Check Phisical Address and reinitialize PTE
+ ////
+ //
+ //if (READ_REGISTER_ULONG(R98_PCI1_ID) == 0x10110004) {
+ // NowDisplayControlBase = (READ_REGISTER_ULONG(R98_PCI1_MEM_BASE) & 0xfffffff0)
+ // + R98_PCI_SPACE_BASE + TGA_REG_SPC_OFFSET;
+ //} else if (READ_REGISTER_ULONG(R98_PCI2_ID) == 0x10110004) {
+ // NowDisplayControlBase = (READ_REGISTER_ULONG(R98_PCI2_MEM_BASE) & 0xfffffff0)
+ // + R98_PCI_SPACE_BASE + TGA_REG_SPC_OFFSET;
+ //} else if (READ_REGISTER_ULONG(R98_PCI3_ID) == 0x10110004) {
+ // NowDisplayControlBase = (READ_REGISTER_ULONG(R98_PCI3_MEM_BASE) & 0xfffffff0)
+ // + R98_PCI_SPACE_BASE + TGA_REG_SPC_OFFSET;
+ //}
+ //
+ //if (HalpDisplayControlBase != NowDisplayControlBase){
+ // // Called by OS, so reinitialize PTE
+ // HalpDisplayControlBase = NowDisplayControlBase;
+ //
+ // Pte.G = 0;
+ // Pte.V = 1;
+ // Pte.D = 1;
+ //
+ //#if defined(R3000)
+ // Pte.N = 1;
+ //#endif
+ //#if defined(R4000)
+ // Pte.C = UNCACHED_POLICY;
+ //#endif
+ // PageFrame = (PENTRYLO)(PTE_BASE | (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+ // Pte.PFN = (HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET) >> PAGE_SHIFT;
+ //
+ // for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ // *PageFrame++ = Pte;
+ // Pte.PFN += 1;
+ // }
+ //
+ // Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT;
+ // *PageFrame = Pte;
+ //}
+ // End S006
+
+ //
+ // Calculate vertical frequency.
+ //
+
+ horizontalTotal = ( HalpMonitorConfigurationData.HorizontalDisplayTime
+ +HalpMonitorConfigurationData.HorizontalBackPorch
+ +HalpMonitorConfigurationData.HorizontalFrontPorch
+ +HalpMonitorConfigurationData.HorizontalSync );
+
+ verticalTotal = ( HalpMonitorConfigurationData.VerticalResolution
+ +HalpMonitorConfigurationData.VerticalBackPorch
+ +HalpMonitorConfigurationData.VerticalFrontPorch
+ +HalpMonitorConfigurationData.VerticalSync );
+
+ VerticalFrequency = 1000000000 / ( horizontalTotal * verticalTotal);
+
+ //
+ // Write the PLL
+ //
+
+ // Select PLL Data
+ if( HalpMonitorConfigurationData.HorizontalResolution == 640
+ && HalpMonitorConfigurationData.VerticalResolution == 480 ){
+ if( VerticalFrequency > 66 ){
+ PLLbits = (PVOID)PLLbits640x480_72; // S00b
+ } else {
+ PLLbits = (PVOID)PLLbits640x480_60; // S00b
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600 ){
+ if( VerticalFrequency > 66 ){
+ PLLbits = (PVOID)PLLbits800x600_72; // S00b
+ } else {
+ PLLbits = (PVOID)PLLbits800x600_60; // S00b
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768 ){
+ PLLbits = (PVOID)PLLbits1024x768_60; // S00b
+ } else {
+ PLLbits = (PVOID)PLLbits640x480_60; // S00b
+ }
+
+ // Set PLL Data
+ for( i = 0; i <= 6; i++ ){
+ for( j = 0; j <= 7; j++ ){
+ PLLdata = (PLLbits[i] >> (7-j)) & 1;
+ if( i == 6 && j == 7 )
+ PLLdata |= 2; // Set ~HOLD bit on last write
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + CLOCK), PLLdata);
+ }
+ }
+
+ // Verify 21030 is idle ( check busy bit on Command Status Register )
+ while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){ // S006
+ }
+
+ // Set to Deep Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + DEEP), 0x00014000 );
+
+ // Verify 21030 is idle ( check busy bit on Command Status Register )
+ while( (READ_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + COMMAND_STATUS) ) & 1) == 1 ){ // S006
+ }
+
+ // Start S006
+ // Set to Video Base Address Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_BASE), 0x00000000 );
+ // End S006
+
+ // Set to Plane Mask Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + PLANE_MASK), 0xffffffff );
+
+ // Set to Pixel Mask Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + ONE_SHOT_PIXEL_MASK), 0xffffffff );
+
+ // Set to Raster Operation
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 );
+
+ // Set to Mode Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x0000200d );
+
+ // Set to Block Color Register 0
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R0), 0x12345678 );
+
+ // Set to Block Color Register 1
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + BLK_COLOR_R1), 0x12345678 );
+
+ //
+ // Init. video timing registers for each resolution
+ //
+
+ if( HalpMonitorConfigurationData.HorizontalResolution == 640
+ && HalpMonitorConfigurationData.VerticalResolution == 480 ){
+ if( VerticalFrequency > 66 ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x3c294a0 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x070349e0 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0xe64ca0 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 );
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 800
+ && HalpMonitorConfigurationData.VerticalResolution == 600 ){
+ if( VerticalFrequency > 66 ){
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x1a7a4c8 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c6fa58 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x2681cc8 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x05c40a58 );
+ }
+ } else if( HalpMonitorConfigurationData.HorizontalResolution == 1024
+ && HalpMonitorConfigurationData.VerticalResolution == 768 ){
+ //60Hz Only
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0x4889300 ); // // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x07461b00 );
+ } else {
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + H_CONT), 0xe64ca0 ); // K1001
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + V_CONT), 0x064211e0 );
+ }
+
+ // Set to Raster Operation Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RASTER_OP), 0x03 );
+
+ // Set to Mode Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + MODE), 0x00002000 );
+
+ KeStallExecutionProcessor(10000L); // S00b
+
+ // Set to Palette and DAC Setup & Data Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x0c );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x0ca2 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x10 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1040 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x12 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1220 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x01 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x14 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x1410 );
+
+ //
+ // set pass thru on off & on again to verify operation
+ //
+
+ // EEPROM Write Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + EEPROM_WRITE), 0x00000001 );
+
+ //
+ // Fill palette
+ //
+
+ // Set to Palette and DAC Setup & Data Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x00 );
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_SETUP), 0x02 );
+
+ for( i = 0; i < 48; i++ ){
+ ColorData = Vga_Ini_ColorTable[i];
+ ColorData |= 0x200;
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), ColorData );
+ }
+
+ for( i = 48; i < 768; i++ ){ // S006
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + RAMDAC_DATA), 0x200 );
+ }
+
+ // Set to Video Valid Register
+ WRITE_REGISTER_ULONG( (PULONG)(TGA_REGISTER_BASE + VIDEO_VALID), 0x01 );
+
+ //
+ // Set Video Memory to address color one.
+ //
+
+ Buffer = (PULONG)VIDEO_MEMORY_BASE;
+ Limit = (HalpMonitorConfigurationData.HorizontalResolution *
+ HalpMonitorConfigurationData.VerticalResolution) / 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 S005 */
+
+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;
+ ENTRYLO SavedPte;
+ // Start S006
+ ULONG NowDisplayControlBase;
+ PENTRYLO PageFrame;
+ ENTRYLO Pte;
+ LONG Index;
+ // End S006
+
+ //
+ // Raise IRQL to the highest level, acquire the display adapter spin lock,
+ // flush the TB, and map the display frame buffer into the address space
+ // of the current process.
+ //
+
+ /* START M002 */
+#if defined (R96DBG)
+ DbgPrint("HalDisplayString\n");
+#endif
+ /* END M002 */
+
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+#if defined(_DUO_)
+
+ KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+#endif
+
+ SavedPte = *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc)));
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE |
+ ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = HalpDisplayPte;
+
+ // Start S006
+ if (HalpDisplayControllerSetup == HalpDisplayTgaSetup) {
+ if (PciReadConfigUlong(R98_PCI1_ID) == 0x00041011) {
+ NowDisplayControlBase = (PciReadConfigUlong(R98_PCI1_MEM_BASE) & 0xfffffff0)
+ | R98_PCI_SPACE_BASE
+ + TGA_REG_SPC_OFFSET;
+ } else if (PciReadConfigUlong(R98_PCI2_ID) == 0x00041011) {
+ NowDisplayControlBase = (PciReadConfigUlong(R98_PCI2_MEM_BASE) & 0xfffffff0)
+ | R98_PCI_SPACE_BASE
+ + TGA_REG_SPC_OFFSET;
+ } else if (PciReadConfigUlong(R98_PCI3_ID) == 0x00041011) {
+ NowDisplayControlBase = (PciReadConfigUlong(R98_PCI3_MEM_BASE) & 0xfffffff0)
+ | R98_PCI_SPACE_BASE
+ + TGA_REG_SPC_OFFSET;
+ }
+
+ if (HalpDisplayControlBase != NowDisplayControlBase){
+ HalpDisplayControlBase = NowDisplayControlBase;
+
+ Pte.G = 0;
+ Pte.V = 1;
+ Pte.D = 1;
+
+#if defined(R3000)
+ Pte.N = 1;
+#endif
+#if defined(R4000)
+ Pte.C = UNCACHED_POLICY;
+#endif
+ PageFrame = (PENTRYLO)(PTE_BASE | (VIDEO_MEMORY_BASE >> (PDI_SHIFT - PTI_SHIFT)));
+ Pte.PFN = (HalpDisplayControlBase - TGA_REG_SPC_OFFSET + TGA_DSP_BUF_OFFSET) >> PAGE_SHIFT;
+
+ for (Index = 0; Index < ((PAGE_SIZE / sizeof(ENTRYLO)) - 1); Index += 1) {
+ *PageFrame++ = Pte;
+ Pte.PFN += 1;
+ }
+
+ Pte.PFN = ((ULONG)HalpDisplayControlBase) >> PAGE_SHIFT;
+ *PageFrame = Pte;
+ }
+ }
+ // End S006
+
+ //
+ // 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 (HalpDisplayOwnedByHal == FALSE) {
+ HalpDisplayControllerSetup();
+ HalpInitDisplayStringIntoNvram(); // S009
+ HalpResetX86DisplayAdapter(); //K000
+ }
+
+// HalpStringIntoNvram(HalpColumn, HalpRow, String); // S009, S00a
+ HalStringIntoBufferStart( HalpColumn, HalpRow ); // S00a
+
+ //
+ // Display characters until a null byte is encountered.
+ //
+
+ while (*String != 0) {
+ HalpDisplayCharacter(*String++);
+ }
+
+ HalpStringBufferCopyToNvram(); // S00a
+
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // release the display adapter spin lock, and lower IRQL to its previous
+ // level.
+ //
+
+ KeFlushCurrentTb();
+ *((PENTRYLO)(PDE_BASE | ((VIDEO_MEMORY_BASE >> (PDI_SHIFT - 2)) & 0xffc))) = SavedPte;
+
+#if defined(_DUO_)
+
+ KiReleaseSpinLock(&HalpDisplayAdapterLock);
+
+#endif
+
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+VOID
+HalpDisplayCharacter (
+ 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.
+
+--*/
+
+{
+
+ PUCHAR Destination;
+ 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 {
+ /* START M002 */
+ HalpMoveMemory32((PUCHAR)VIDEO_MEMORY_BASE,
+ (PUCHAR)(VIDEO_MEMORY_BASE + HalpScrollLine),
+ HalpScrollLength);
+ /* END M002 */
+
+ Destination = (PUCHAR)VIDEO_MEMORY_BASE + HalpScrollLength;
+ for (Index = 0; Index < HalpScrollLine; Index += 1) {
+ *Destination++ = 1;
+ }
+ }
+
+ HalpStringBufferCopyToNvram(); // S00a
+ HalStringIntoBufferStart( HalpColumn, HalpRow ); // S00a
+
+ } else if (Character == '\r') {
+ HalpColumn = 0;
+
+ HalpStringBufferCopyToNvram(); // S00a
+ HalStringIntoBufferStart( HalpColumn, HalpRow ); // S00a
+
+ } else {
+ HalStringIntoBuffer( Character ); // S00a
+
+ if ((Character < HalpFontHeader->FirstCharacter) ||
+ (Character > HalpFontHeader->LastCharacter)) {
+ Character = HalpFontHeader->DefaultCharacter;
+ }
+
+ Character -= HalpFontHeader->FirstCharacter;
+ HalpOutputCharacter((PUCHAR)HalpFontHeader + HalpFontHeader->Map[Character].Offset);
+ }
+
+ return;
+}
+
+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;
+ *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) {
+ CursorColumn = HalpDisplayWidth;
+ }
+
+ if (CursorRow > HalpDisplayText) {
+ CursorRow = HalpDisplayText;
+ }
+
+ HalpColumn = CursorColumn;
+ HalpRow = CursorRow;
+ return;
+}
+
+VOID
+HalpOutputCharacter(
+ 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) {
+ HalpDisplayCharacter('\n');
+ }
+
+ //
+ // Output the specified character and update the x cursor position.
+ //
+
+ Destination = (PUCHAR)(VIDEO_MEMORY_BASE +
+ (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++ = (UCHAR)((FontValue >> 31) ^ 1); // S002
+ FontValue <<= 1;
+ }
+
+ if(HalpDisplayControllerSetup == HalpDisplayCirrusSetup){
+ Destination +=
+ (1024 - HalpCharacterWidth);
+ }else{
+ Destination +=
+ (HalpMonitorConfigurationData.HorizontalResolution - HalpCharacterWidth);
+ }
+ }
+ HalpColumn += 1;
+ return;
+}
+
+/* START M002 */
+VOID
+Write_Dbg_Uchar(
+ PUCHAR Ioadress,
+UCHAR Moji
+)
+
+{
+#if defined (R96DBG)
+ DbgPrint("Disply I/O Adress %x Char %x \n",Ioadress,Moji);
+#endif
+ WRITE_PORT_UCHAR(Ioadress,Moji);
+}
+/* END M002 */
+
+/* START M003 */
+
+VOID
+HalpMoveMemory32 (
+ PUCHAR Destination,
+ PUCHAR Source,
+ ULONG Length
+ )
+
+/*++
+ Routine Description:
+
+ This function moves blocks of memory.
+
+ Arguments:
+
+ Destination - Supplies a pointer to the destination address of
+ the move operation.
+
+ Source - Supplies a pointer to the source address of the move
+ operation.
+
+ Length - Supplies the length, in bytes, of the memory to be moved.
+
+ Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR Remainder;
+ PUCHAR Dstend; /* M004 */
+ PUCHAR Srcend; /* M004 */
+
+ if ( (Source == Destination) || (Length == 0) ) { /* M004 */
+ return;
+ }
+
+ if ((Source < Destination)&((Source + Length) > Destination)) { /* M004 vvv */
+ if((Destination - Source) > 4){
+ Remainder = (UCHAR)(Length &0x03); // S002
+ Length = Length / 4;
+ Dstend = Destination + Length - 4 ;
+ Srcend = Source + Length -4;
+
+ for (; Length > 0; Length--) {
+ *(PULONG)(Dstend) = *(PULONG)(Srcend);
+ Dstend -= 4;
+ Srcend -= 4;
+ }
+ for (; Remainder > 0; Remainder--) {
+ *Dstend = *Srcend;
+ Dstend--;
+ Srcend--;
+ }
+ return;
+ }
+ for (; Length > 0; Length--) {
+ *Dstend = *Srcend;
+ Dstend--;
+ Srcend--;
+ }
+ return;
+ }
+
+ else {
+ if( (Source - Destination) > 4 ){
+ Remainder = (UCHAR)(Length &0x03); // S002
+ Length = Length / 4;
+ for (; Length > 0; Length--) {
+ *(PULONG)(Destination) = *(PULONG)(Source);
+ Destination += 4;
+ Source += 4;
+ }
+ for (; Remainder > 0; Remainder--) {
+ *Destination = *Source;
+ Destination++;
+ Source++;
+ }
+ return;
+ }
+
+ for (; Length > 0; Length--) {
+ *Destination = *Source;
+ Destination++;
+ Source++; /* M004 ^^^*/
+ }
+ }
+}
+
+/* END M003 */
diff --git a/private/ntos/nthals/halr98mp/mips/jxebsup.c b/private/ntos/nthals/halr98mp/mips/jxebsup.c
new file mode 100644
index 000000000..464a35673
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxebsup.c
@@ -0,0 +1,1275 @@
+#ident "@(#) NEC jxebsup.c 1.13 95/06/19 11:10:34"
+/*++
+
+Copyright (c) 1990-1994 Microsoft Corporation
+
+Module Name:
+
+ jxebsup.c
+
+Abstract:
+
+ The module provides the EISA bus support for JAZZ systems.
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.03/25 T.Samezima
+ *
+ * HalpCreateEisaStructure
+ *
+ * Del #ifdef of Duo
+ * Disable NMI Interrupt
+ *
+ * Change Parameter of initialize interrupt
+ * Irql Level
+ *
+ ***********************************************************************
+ *
+ * S002 94.04/19 T.Samezima
+ *
+ * HalpEisaDispatch
+ *
+ * Del #ifdef of Duo
+ * K001 94/5/31 (Tue) N.Kugimoto
+ * Add SpinLock HalpEisaMapTransfer()
+ *
+ ***********************************************************************
+ *
+ * S003 94.06/01 T.Samezima
+ *
+ * HalHandleNMI
+ *
+ * Del display interrupt information
+ *
+ ***********************************************************************
+ *
+ * S004 94.6/13 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***********************************************************************
+ *
+ * S005 94.7/5 T.Samezima
+ *
+ * Chg base i/o address to kseg1_base
+ *
+ *
+ ***********************************************************************
+ *
+ * S006 94.8/22 T.Samezima on SNES
+ *
+ * Add Move EISA NMI enable logic from HalpInitializeInterrupts()
+ *
+ ***********************************************************************
+ *
+ * S007 94.8/23 T.Samezima
+ *
+ * Chg Register read size from long to short
+ *
+ *
+ * K001 94/9/13 N.Kugimoto
+ * Add For a spurious interrupt PIC IR7
+ * K002 94/9/13 N.Kugimoto
+ * Chg Interrupt Ack reg non USHORT.must UCHAR!!.
+ *
+ * S008 94.10/13 T.Samezima
+ * Fix Version Up at build807
+ * S009 94.11/21 T.Samezima
+ * Chg Disable EISA NMI
+ * Disable ASSERT(). because. senseless ASSERT on r98
+ *
+ * K003 95/04/24 N.Kugimoto
+ * Add DUMMDMA
+ * LR4360 workaround. can't TLB flush while dma.
+ * So ESC DMAC channel2 use.
+ * A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ * - resolve compile wornings.
+ */
+
+#include "halp.h"
+#include "eisa.h"
+#include "bugcodes.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+// Start S008
+typedef
+BOOLEAN
+(*PSECONDARY_DISPATCH)(
+ PKINTERRUPT Interrupt
+ );
+
+// End S008
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+
+//
+// Define save area for EISA interrupt mask resiters and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+// Start S008
+// Define EISA bus interrupt affinity.
+//
+
+KAFFINITY HalpEisaBusAffinity;
+// End S008
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor
+ )
+/*++
+
+Routine Description:
+
+ This function allocates an EISA 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.
+
+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 controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ BOOLEAN useChannel;
+ BOOLEAN eisaSystem;
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Eisa &&
+ DeviceDescriptor->Master) {
+
+ 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);
+ }
+
+ //
+ // 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) HalpEisaControlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ if (useChannel && HalpEisaAdapter[DeviceDescriptor->DmaChannel] != NULL) {
+
+ adapterObject = HalpEisaAdapter[DeviceDescriptor->DmaChannel];
+
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ 0,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpEisaAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ }
+
+
+ //
+ // If the channel is not used then indicate the this is an Eisa bus
+ // master by setting the page port and mode to cascade even though
+ // it is not used.
+ //
+
+ 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; // S004
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2ExtendedModePort;
+
+ }
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR)channelNumber; // S004
+
+ 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;
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ 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 );
+
+ //
+ // 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);
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ EISA 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;
+ UCHAR charBuffer; // S006
+
+ /* Start S001, S008 */
+ //
+ // Directly connect the EISA interrupt dispatcher to the level for
+ // EISA bus interrupt.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization.
+ //
+
+ PCR->InterruptRoutine[EISA_DEVICE_VECTOR] = (PKINTERRUPT_ROUTINE)HalpEisaDispatch; // A002
+ /* End S001, S008 */
+
+ //
+ // Raise the IRQL while the EISA interrupt controller is initalized.
+ //
+
+ /* Start S001 */
+ KeRaiseIrql(INT1_LEVEL, &oldIrql);
+ /* End S001 */
+
+ //
+ // Initialize the EISA 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) HalpEisaControlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the iterrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->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) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->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) HalpEisaControlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+
+ //
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpEisaInterrupt1Mask = (UCHAR)~(1 << SLAVE_IRQL_LEVEL); // S004
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ HalpEisaInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpEisaInterrupt1Level = 0;
+ HalpEisaInterrupt2Level = 0;
+
+ // Start S008
+ // Set EISA bus interrupt affinity.
+ //
+
+ HalpEisaBusAffinity = PCR->SetMember;
+ // End S008
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ /* Start S001, S008 */
+ //
+ // Enable eisa interrupt on LR4360
+ //
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ HalpBuiltinInterruptEnable |= iREN_ENABLE_EISA_INTERRUPT;
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+
+ /* End S008 */
+ //
+ // 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) HalpEisaControlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+ /* End S001 */
+
+ // Start S006
+ charBuffer = READ_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus );
+// charBuffer = (charBuffer & 0x03); // S009
+ charBuffer = ((charBuffer & 0x03) | 0X0C); // S009
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->NmiStatus,
+ charBuffer
+ );
+ /* Start S001 in xxinitnt.c */
+ charBuffer = READ_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl
+ );
+ /* End S001 in xxinitnt.c */
+// charBuffer = ( (charBuffer & 0x01) | 0x0e ); // S009
+ charBuffer = (charBuffer & 0x01); // S009
+ WRITE_REGISTER_UCHAR( &((PEISA_CONTROL) HalpEisaControlBase)->ExtendedNmiResetControl,
+ charBuffer ); // S007
+ // End S006
+
+ return(TRUE);
+}
+
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the EISA bus specified EISA bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ESIA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ }
+
+}
+//
+//
+//extern KSPIN_LOCK HalpIoMapSpinLock;
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the EISA 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;
+ KIRQL Irql; // K001
+
+ BytePtr = (PUCHAR) &Offset;
+
+// ASSERT(Offset >= 0x100000); // S009
+
+ 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 = WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER;
+
+ // K001
+ // grab the spinlock for the system DMA controller
+ //
+#if !defined(DUMMYDMA)
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+#endif
+ //
+ // Determine the controller number based on the Adapter base va.
+ //
+
+ 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) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // 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 1
+ //
+
+ 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) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+
+ //
+ // 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)
+ );
+ }
+#if !defined(DUMMYDMA)
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+#endif
+}
+
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the EISA bus specified EISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the EISA interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the EISA interrupt vector.
+ //
+
+ Vector -= EISA_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort1,
+ HalpEisaInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2EdgeLevel,
+ HalpEisaInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpEisaInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort1,
+ HalpEisaInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpEisaInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpEisaInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1EdgeLevel,
+ HalpEisaInterrupt1Level
+ );
+ }
+}
+
+// Start S008
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of an interrupt being generated
+ via the vector that is directly connected to EISA device interrupt.
+
+ N.B. This interrupt is directly connected and therefore, no argument
+ values are defined.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ PULONG dispatchCode;
+ USHORT interruptVector;
+ PKINTERRUPT interruptObject;
+ BOOLEAN returnValue;
+
+ //
+ // Read the interrupt vector.
+ //
+
+ interruptVector = (UCHAR)READ_REGISTER_UCHAR( (PVOID)(LR_PHYSICAL_PCI_INT_ACK_BASE | KSEG1_BASE));
+
+ //
+ // If the vector is nonzero, then it is either an EISA interrupt
+ // of an NMI interrupt. Otherwise, the interrupt is no longer
+ // present.
+ //
+
+ if (interruptVector != 0) {
+
+ //
+ // If the interrupt vector is 0x8000 then the interrupt is an NMI.
+ // Otherwise, dispatch the interrupt to the appropriate interrupt
+ // handler.
+ //
+
+// if (interruptVector != 0x8000) {
+ //K001 Start
+ if(interruptVector == 7|| interruptVector==15 ){
+
+ PVOID IsrPortAddr;
+ UCHAR IsrValue;
+
+#define OCW3_READ_ISR 0x0B
+#define OCW3_READ_IRR 0x0A
+
+ //
+ // Master or Slave ?
+ //
+ IsrPortAddr = (interruptVector == 7) ?
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0:
+ &((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0;
+
+ // SetUp to ISR Regsiter
+ WRITE_REGISTER_UCHAR( IsrPortAddr, OCW3_READ_ISR );
+ // Read ISR Register
+ IsrValue=READ_REGISTER_UCHAR( IsrPortAddr );
+ // Resume to IRR Register
+ WRITE_REGISTER_UCHAR( IsrPortAddr, OCW3_READ_IRR);
+
+ if(!IsrValue){
+ // This is a spurious interrupt!!. No Call Driver.
+ goto NocallDriver;
+ }
+ }
+ // K001 End
+
+ //
+ // Mask the upper bits off since the vector is only a byte and
+ // dispatch to the secondary interrupt service routine.
+ //
+
+ interruptVector &= 0xff;
+ dispatchCode = (PULONG)(PCR->InterruptRoutine[EISA_VECTORS + interruptVector]);
+ interruptObject = CONTAINING_RECORD(dispatchCode,
+ KINTERRUPT,
+ DispatchCode);
+
+ returnValue = ((PSECONDARY_DISPATCH)interruptObject->DispatchAddress)(interruptObject);
+
+NocallDriver:
+
+ //
+ // Dismiss the interrupt in the EISA interrupt controllers.
+ //
+ // If this is a cascaded interrupt then the interrupt must be
+ // dismissed in both controllers.
+ //
+
+ if (interruptVector & 0x08) {
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+ }
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT);
+
+// } else {
+// returnValue = HalHandleNMI(NULL, NULL);
+// }
+
+ } else {
+ returnValue = FALSE;
+ }
+
+ return returnValue;
+}
+// End S008
+
+BOOLEAN
+HalHandleNMI(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+
+Routine Description:
+
+ This function is called when an EISA NMI occurs. It print the appropriate
+ status information and bugchecks.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object
+
+ ServiceContext - Bug number to call bugcheck with.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ return(TRUE);
+}
diff --git a/private/ntos/nthals/halr98mp/mips/jxenvirv.c b/private/ntos/nthals/halr98mp/mips/jxenvirv.c
new file mode 100644
index 000000000..5e9446d73
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxenvirv.c
@@ -0,0 +1,818 @@
+#pragma comment(exestr, "@(#) jxenvirv.c 1.8 94/12/06 15:07:37 nec")
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ * K001 94.5/31 (Tue) N.Kugimoto
+ * Del No Map TLB. & nvram base define -->def.h
+ * Add Nvram write enable
+ * K002 94/6/10 (Fri) N.Kugimoto
+ * Chg Compile err del.
+ * K003 94/8/29 (Mon) N.Kugimoto
+ * -1 BUG HalpUnmapNvram() stsr register write value bug.
+ * -2 Chg HalpMapNvram() stsr register write value is absolute.
+ * K004 94/10/11 N.Kugimoto
+ * H/W Work Around. NVRAM can't write protect!!.
+ * K005 94/12/06 N.Kugimoto
+ * Add ESM Interface
+ * -2 Miss ;; -->,
+ */
+
+#include "halp.h"
+#include "arccodes.h"
+#include "jazznvr.h"
+#include "string.h"
+
+//
+// Define base address at which to map NVRAM.
+//
+#if !defined(_R98_) // K001
+#define NVRAM_MEMORY_BASE PTE_BASE
+#endif
+//
+// Define local upcase macro.
+//
+
+#define UpCase(c) ((c) >= 'a' && (c) <= 'z' ? (c) - ('a' - 'A') : (c))
+
+KIRQL
+HalpMapNvram (
+ IN PENTRYLO SavedPte
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to map the NVRAM into the address space of
+ the current process.
+
+Arguments:
+
+ SavedPte - Supplies a pointer to an array which receives the old NVRAM
+ PTE values.
+
+Return Value:
+
+ The previous IRQL is returned as the function value.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+#if defined(_R98_) // K001
+ //
+ // Nvram Write enable
+ // K002
+ WRITE_REGISTER_ULONG(
+ &( PMC_CONTROL1 )->STSR.Long,
+ STSR_NVWINH_ENABLE //K003-2
+ );
+
+#else // K001
+ ENTRYLO NvramPte;
+ PENTRYLO PtePointer;
+
+ //
+ // Construct a PTE to map NVRAM into the address space of the current
+ // process.
+ //
+
+ NvramPte.X1 = 0;
+ NvramPte.PFN = NVRAM_PHYSICAL_BASE >> PAGE_SHIFT;
+ NvramPte.G = 0;
+ NvramPte.V = 1;
+ NvramPte.D = 1;
+
+#if defined(R3000)
+
+ NvramPte.N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ NvramPte.C = UNCACHED_POLICY;
+
+#endif
+
+ //
+ // Raise IRQL to the highest level, flush the TB, map the NVRAM into
+ // the address space of the current process, and return the previous
+ // IRQL.
+ //
+
+ PtePointer = (PENTRYLO)PDE_BASE;
+#endif // _R98_
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+#if !defined(_R98_)
+ SavedPte[0] = PtePointer[0];
+ SavedPte[1] = PtePointer[1];
+ KeFlushCurrentTb();
+ PtePointer[0] = NvramPte;
+ NvramPte.PFN += 1;
+ PtePointer[1] = NvramPte;
+#endif //_R98_
+ return OldIrql;
+}
+
+VOID
+HalpUnmapNvram (
+ IN PENTRYLO SavedPte,
+ IN KIRQL OldIrql
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called to unmap the NVRAM from the address space of
+ the current process.
+
+Arguments:
+
+ SavedPte - Supplies a pointer to an array which contains the old NVRAM
+ PTE values.
+
+ OldIrql - Supplies the previous IRQL value.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if defined(_R98_) // K001
+#if 0 //K004 vvvvv
+ //
+ // Nvram write disable
+ // K002
+ WRITE_REGISTER_ULONG(
+ &( PMC_CONTROL1 )->STSR.Long,
+ STSR_NVWINH_DISABLE //K003-1
+ );
+
+#endif //K004 ^^^^^
+#else
+ PENTRYLO PtePointer;
+ //
+ // Restore the previous mapping for the current process, flush the TB,
+ // and lower IRQL to its previous level.
+ //
+
+ PtePointer = (PENTRYLO)PDE_BASE;
+ KeFlushCurrentTb();
+ PtePointer[0] = SavedPte[0];
+ PtePointer[1] = SavedPte[1];
+#endif //_R98_
+ KeLowerIrql(OldIrql);
+ return;
+}
+
+ARC_STATUS
+HalpEnvironmentCheckChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine checks the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ ESUCCESS is returned if the checksum matches. Otherwise, EIO is returned.
+
+--*/
+
+{
+
+ ULONG Checksum1;
+ ULONG Checksum2;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum1 = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum1 += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Merge the checksum bytes from the NVRAM and compare to computed value.
+ //
+
+ Checksum2 = (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[0]) |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[1]) << 8 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[2]) << 16 |
+ (ULONG)READ_REGISTER_UCHAR(&NvConfiguration->Checksum2[3]) << 24;
+
+ //
+ // If the checksum mismatches, then return an I/O error. Otherwise,
+ // return a success status.
+ //
+
+ if (Checksum1 != Checksum2) {
+ return EIO;
+
+ } else {
+ return ESUCCESS;
+ }
+}
+
+VOID
+HalpEnvironmentSetChecksum (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the NVRAM environment area checksum.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Checksum;
+ PUCHAR Environment;
+ ULONG Index;
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Compute the NVRAM environment area checksum.
+ //
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE;
+ Environment = &NvConfiguration->Environment[0];
+ Checksum = 0;
+ for (Index = 0; Index < LENGTH_OF_ENVIRONMENT; Index += 1) {
+ Checksum += (ULONG)READ_REGISTER_UCHAR(&Environment[Index]);
+ }
+
+ //
+ // Write the NVRAM environment area checksum.
+ //
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[0],
+ (UCHAR)(Checksum & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[1],
+ (UCHAR)((Checksum >> 8) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[2],
+ (UCHAR)((Checksum >> 16) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->Checksum2[3],
+ (UCHAR)(Checksum >> 24));
+
+ return;
+}
+
+ARC_STATUS
+HalpFindEnvironmentVariable (
+ IN PCHAR Variable,
+ OUT PULONG VariableIndex,
+ OUT PULONG ValueIndex
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs a case insensitive search of the NVRAM environment
+ area for the specified variable name.
+
+ N.B. The NVRAM must be mapped before this routine is called.
+
+
+Arguments:
+
+ Variable - Supplies a pointer to a zero terminated string containing an
+ environment variable name.
+
+Return Value:
+
+ ESUCCESS is returned if the specified variable name is located. Otherwise,
+ ENOENT is returned.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ PUCHAR Name;
+
+ //
+ // If the variable name is null, then return no entry found.
+ //
+
+ if (*Variable == 0) {
+ return ENOENT;
+ }
+
+ //
+ // Search the environment section of the NVRAM for a variable name match.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0];
+ Index = 0;
+ do {
+
+ //
+ // Set name to the beginning of the variable name and record the
+ // current index value.
+ //
+
+ Name = Variable;
+ *VariableIndex = Index;
+
+ //
+ // Search until the end of the current environment variable, the
+ // end of the specified variable name, or the end of the NVRAM is
+ // reached.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0) && (*Name != 0)) {
+ if (READ_REGISTER_UCHAR(&Environment[Index]) != UpCase(*Name)) {
+ break;
+ }
+
+ Name += 1;
+ Index += 1;
+ }
+
+ //
+ // Check for a match which is signified by the end of the variable
+ // name and the equal separator in the current environment variable.
+ //
+
+ if ((*Name == 0) && (READ_REGISTER_UCHAR(&Environment[Index]) == '=')) {
+ *ValueIndex = Index + 1;
+ return ESUCCESS;
+ }
+
+ //
+ // Advance to the start of the next variable.
+ //
+
+ while ((Index < LENGTH_OF_ENVIRONMENT) &&
+ (READ_REGISTER_UCHAR(&Environment[Index]) != 0)) {
+ Index += 1;
+ }
+
+ Index += 1;
+ } while (Index < LENGTH_OF_ENVIRONMENT);
+
+ return ENOENT;
+}
+
+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.
+
+--*/
+
+{
+
+ PUCHAR Environment;
+ ULONG Index;
+ KIRQL OldIrql;
+ ENTRYLO SavedPte[2];
+ ARC_STATUS Status;
+ ULONG ValueIndex;
+ ULONG VariableIndex;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+
+ //
+ // If the checksum does not match or the specified variable cannot
+ // be located, then set the status to no entry found. Otherwise, copy
+ // the respective variable value to the specified output buffer.
+ //
+
+ Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0];
+ if ((HalpEnvironmentCheckChecksum() != ESUCCESS) ||
+ (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) != ESUCCESS)) {
+
+ Status = ENOENT;
+
+ } else {
+
+ //
+ // Copy the specified value to the output buffer.
+ //
+
+ for (Index = 0; Index < Length; Index += 1) {
+ *Buffer = READ_REGISTER_UCHAR(&Environment[ValueIndex]);
+ if (*Buffer == 0) {
+ break;
+ }
+
+ Buffer += 1;
+ ValueIndex += 1;
+ }
+
+ //
+ // If the length terminated the loop, then return not enough memory.
+ // Otherwise, return success.
+ //
+
+ if (Index == Length) {
+ Status = ENOMEM;
+
+ } else {
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Unmap the NVRAM from the address space of the current process and
+ // return the function status.
+ //
+
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+ return Status;
+}
+
+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.
+
+--*/
+
+{
+
+ UCHAR Character;
+ PUCHAR Environment;
+ KIRQL OldIrql;
+ ENTRYLO SavedPte[2];
+ ARC_STATUS Status;
+ ULONG TopIndex;
+ ULONG VariableIndex;
+ ULONG VariableLength;
+ ULONG ValueEnd;
+ ULONG ValueIndex;
+ ULONG ValueLength;
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+ Environment = &((PNV_CONFIGURATION)NVRAM_MEMORY_BASE)->Environment[0];
+
+ //
+ // If the checksum does not match, then set status to an I/O error.
+ //
+
+ if (HalpEnvironmentCheckChecksum() != ESUCCESS) {
+ Status = EIO;
+ goto Unmap;
+ }
+
+ //
+ // Determine the top of the environment area by scanning backwards until
+ // the a non-null character is found or the beginning of the environment
+ // area is reached.
+ //
+
+ for (TopIndex = (LENGTH_OF_ENVIRONMENT - 1); TopIndex > 0; TopIndex -= 1) {
+ if (READ_REGISTER_UCHAR(&Environment[TopIndex]) != '\0') {
+ break;
+ }
+ }
+
+ //
+ // If the environment area contains any data, then adjust the top index
+ // to the first free byte.
+ //
+
+ if (TopIndex != 0) {
+ TopIndex += 2;
+ }
+
+ //
+ // Compute the length of the variable name and the variable value.
+ //
+
+ VariableLength = strlen(Variable) + 1;
+ ValueLength = strlen(Value) + 1;
+
+ //
+ // Check to determine if the specified variable is currently defined.
+ //
+
+ if (HalpFindEnvironmentVariable(Variable,
+ &VariableIndex,
+ &ValueIndex) == ESUCCESS) {
+
+ //
+ // The specified variable is currently defined. Determine the end
+ // of the variable value by scanning forward to the zero termination
+ // byte.
+ //
+
+ ValueEnd = ValueIndex;
+ while (READ_REGISTER_UCHAR(&Environment[ValueEnd]) != '\0') {
+ ValueEnd += 1;
+ }
+
+ ValueEnd += 1;
+
+ //
+ // If there is enough free space for the new variable value, then
+ // remove the current variable name and value from the environment
+ // area, insert the new variable value at the end of the environment
+ // if it is not null, and set the status to success. Otherwise, set
+ // the status to no space available.
+ //
+
+ if ((ValueEnd - ValueIndex + LENGTH_OF_ENVIRONMENT - TopIndex) >= ValueLength) {
+ while (ValueEnd != TopIndex) {
+ Character = READ_REGISTER_UCHAR(&Environment[ValueEnd]);
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], Character);
+ ValueEnd += 1;
+ VariableIndex += 1;
+ }
+
+ ValueIndex = VariableIndex;
+ while (ValueIndex != TopIndex) {
+ WRITE_REGISTER_UCHAR(&Environment[ValueIndex], '\0');
+ ValueIndex += 1;
+ }
+
+ //
+ // If the new variable value is not null, then copy the variable
+ // name and the variable value into the enviroment area.
+ //
+
+ if (*Value != '\0') {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], UpCase(*Variable));
+ VariableIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], '=');
+ VariableIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[VariableIndex], *Value);
+ VariableIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+ }
+
+ Status = ESUCCESS;
+
+ } else {
+ Status = ENOSPC;
+ }
+
+ } else {
+
+ //
+ // The specified variable does not currently have a value. If the
+ // specified variable is null or has no value, then set the status
+ // to success. Otherwise, if the free area is not large enough to
+ // hold the new variable name and its value, then set the status to
+ // no space available. Otherwise, insert the variable name and value
+ // at the end of the environment area and set the status to success.
+ //
+
+ if ((*Variable == '\0') || (*Value == '\0')) {
+ Status = ESUCCESS;
+
+ } else if ((LENGTH_OF_ENVIRONMENT - TopIndex) <
+ (VariableLength + ValueLength)) {
+ Status = ENOSPC;
+
+ } else {
+
+ //
+ // copy the variable name to the environment area.
+ //
+
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], UpCase(*Variable));
+ TopIndex += 1;
+ Variable += 1;
+ } while (*Variable != '\0');
+
+ //
+ // Insert separator character and copy variable value to the
+ // environment area.
+ //
+
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], '=');
+ TopIndex += 1;
+ do {
+ WRITE_REGISTER_UCHAR(&Environment[TopIndex], *Value);
+ TopIndex += 1;
+ Value += 1;
+ } while (*Value != '\0');
+
+ Status = ESUCCESS;
+ }
+ }
+
+ //
+ // Compute the new checksum and write to the environment area.
+ //
+
+ HalpEnvironmentSetChecksum();
+
+ //
+ // Unmap the NVRAM from the address space of the current process.
+ //
+
+Unmap:
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+ return Status;
+}
+
+
+
+#if defined(_R98_) //K005 Start VVVVV
+
+BOOLEAN
+HalNvramWrite(
+ ULONG Offset, // Offset Of ESM NVRAM
+ ULONG Count, // Write Byte Count
+ PVOID Buffer // Pointer Of Buffer Write to NVRAM
+){
+ // Write into NVRAM
+ return HalpNvramReadWrite(Offset,Count,Buffer,1);
+}
+
+BOOLEAN
+HalNvramRead(
+ ULONG Offset, // Offset Of ESM NVRAM
+ ULONG Count, // Read Byte Count
+ PVOID Buffer // Pointer Of Buffer Read From NVRAM
+){
+ // Read From NVRAM
+ return HalpNvramReadWrite(Offset,Count,Buffer,0);
+}
+
+BOOLEAN
+HalpNvramReadWrite(
+ ULONG Offset, // Read/Write offset of ESM NVRAM
+ ULONG Count, // Read/Write Byte Count
+ PVOID Buffer, // read/Write Pointer
+ ULONG Write // Operation
+){
+
+ ENTRYLO SavedPte[2];
+ KIRQL OldIrql;
+ ULONG i;
+ //
+ // Check is addr . So decrement 1
+ //
+ if(
+ Offset >=0 &&
+ Count >=0 &&
+ NVRAM_ESM_BASE+Offset <=NVRAM_ESM_END &&
+ NVRAM_ESM_BASE+Offset+Count-1 <=NVRAM_ESM_END
+
+ ){
+
+ if(Write){
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+ for(i=0;i<Count;i++){
+ WRITE_REGISTER_UCHAR((PUCHAR)(NVRAM_ESM_BASE+Offset+i),((PUCHAR)Buffer)[i]);
+ }
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+ }else{
+ for(i=0;i<Count;i++){
+ ((PUCHAR)Buffer)[i] =READ_REGISTER_UCHAR((PUCHAR)(NVRAM_ESM_BASE+Offset+i));
+
+ }
+ }
+
+ return TRUE;
+
+ }else{
+
+ //
+ // It is no ESM NVRAM Erea.
+ return FALSE;
+ }
+
+}
+
+//K005 End ^^^^^
+#endif
diff --git a/private/ntos/nthals/halr98mp/mips/jxhalp.h b/private/ntos/nthals/halr98mp/mips/jxhalp.h
new file mode 100644
index 000000000..ed8f602ec
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxhalp.h
@@ -0,0 +1,99 @@
+#ident "@(#) NEC jxhalp.h 1.2 94/10/17 11:28:33"
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ Jazz specific interfaces, defines and structures.
+
+--*/
+
+#ifndef _JXHALP_
+#define _JXHALP_
+
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpRealTimeClockBase;
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ UCHAR AdapterMode;
+ UCHAR Reserved;
+ PUCHAR SingleMaskPort;
+ PUCHAR PagePort;
+} ADAPTER_OBJECT;
+
+//
+// Define function prototypes.
+//
+
+PADAPTER_OBJECT
+HalpAllocateEisaAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescription
+ );
+
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ VOID
+ );
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+BOOLEAN
+HalpEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpEisaMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+#endif // _JXHALP_
diff --git a/private/ntos/nthals/halr98mp/mips/jxmapio.c b/private/ntos/nthals/halr98mp/mips/jxmapio.c
new file mode 100644
index 000000000..6304228b1
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxmapio.c
@@ -0,0 +1,153 @@
+#ident "@(#) NEC jxmapio.c 1.6 94/10/17 11:37:41"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space a MIPS R3000
+ or R4000 Jazz system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.06/02 T.Samezima
+ *
+ * Del I/O space mapping
+ *
+ * Add set kseg1 base I/O address
+ *
+ ***********************************************************************
+ *
+ * S002 94.6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***********************************************************************
+ *
+ * S003 94.7/5 T.Samezima
+ *
+ * Del Error check
+ *
+ * K000 94/10/11 N.Kugimoto
+ * Fix 807 Base
+ */
+
+#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
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+PVOID HalpEisaControlBase;
+PVOID HalpEisaMemoryBase; //K000
+PVOID HalpRealTimeClockBase;
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R3000 or R4000 Jazz
+ 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.
+
+--*/
+
+{
+ /* Start M001 */
+#if !defined(_R98_)
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map EISA control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = EISA_CONTROL_PHYSICAL_BASE;
+ HalpEisaControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ //
+ // Map realtime clock registers.
+ //
+
+ physicalAddress.LowPart = RTCLOCK_PHYSICAL_BASE;
+ HalpRealTimeClockBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE,
+ FALSE);
+#else // #if !defined(_R98_)
+
+ //
+ // set EISA control space.
+ //
+
+ HalpEisaControlBase = (PVOID)(KSEG1_BASE + EISA_CONTROL_PHYSICAL_BASE); // S002
+
+ //
+ // set realtime clock registers.
+ //
+
+ HalpRealTimeClockBase = (PVOID)(KSEG1_BASE + RTCLOCK_PHYSICAL_BASE); // S002
+
+#endif // #if !defined(_R98_)
+ /* End M001 */
+
+ //
+ // If either mapped address is NULL, then return FALSE as the function
+ // value. Otherwise, return TRUE.
+ //
+
+ /* Start S003 */
+// if ((HalpEisaControlBase == NULL) ||
+// (HalpRealTimeClockBase == NULL)) {
+// return FALSE;
+// } else {
+// return TRUE;
+// }
+ return TRUE;
+ /* End S003 */
+}
diff --git a/private/ntos/nthals/halr98mp/mips/jxmaptb.c b/private/ntos/nthals/halr98mp/mips/jxmaptb.c
new file mode 100644
index 000000000..cb338fb94
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxmaptb.c
@@ -0,0 +1,84 @@
+#ident "@(#) NEC jxmaptb.c 1.2 94/10/17 11:39:05"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxmaptb.c
+
+Abstract:
+
+ This module implements the mapping of fixed TB entries for a MIPS R3000
+ or R4000 Jazz system. It also sets the instruction and data cache line
+ sizes for a MIPS R3000 Jazz system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * L001 94.03/16 T.Samezima
+ *
+ * Change return only of HalpMapFixedTbEntries
+ *
+ *
+ */
+
+
+#include "halp.h"
+#define HEADER_FILE
+#include "kxmips.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, HalpMapFixedTbEntries)
+
+#endif
+
+BOOLEAN
+HalpMapFixedTbEntries (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is return only.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+
+{
+ return TRUE;
+}
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halr98mp/mips/jxport.c b/private/ntos/nthals/halr98mp/mips/jxport.c
new file mode 100644
index 000000000..a6a57ad48
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxport.c
@@ -0,0 +1,897 @@
+#pragma comment(exestr, "@(#) jxport.c 1.4 94/10/17 11:46:16 nec")
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxport.c
+
+Abstract:
+
+ This module implements the code that provides communication between
+ the kernel debugger on a MIPS R3000 or R4000 Jazz system and the host
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ * K001 94/5/31 (Tue) N.Kugimoto
+ * Del TLB mapping del. see KSEG1_BASE.
+ * K002 94/6/10 (Fri) N.Kugimoto
+ * Chg Compile err del.
+ */
+
+
+#include "halp.h"
+#include "jazzserp.h"
+
+#define HEADER_FILE
+#include "kxmips.h"
+
+
+VOID
+HalpGetDivisorFromBaud(
+ IN ULONG ClockRate,
+ IN LONG DesiredBaud,
+ OUT PSHORT AppropriateDivisor
+ );
+
+
+#pragma alloc_text(INIT,HalpGetDivisorFromBaud)
+
+
+//
+// BUGBUG Temporarily, we use counter to do the timeout
+//
+
+#define TIMEOUT_COUNT 1024*512
+
+//
+// BUGBUG Temp until we have a configuration manager.
+//
+
+PUCHAR KdComPortInUse = NULL;
+BOOLEAN KdUseModemControl = FALSE;
+
+//
+// Define serial port read and write addresses.
+//
+#if defined(_R98_) // K001 K002
+#define SP_READ ((PSP_READ_REGISTERS)(SERIAL0_PHYSICAL_BASE|KSEG1_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)(SERIAL0_PHYSICAL_BASE|KSEG1_BASE))
+#else
+#define SP_READ ((PSP_READ_REGISTERS)(SP_VIRTUAL_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)(SP_VIRTUAL_BASE))
+#endif // _R98_
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+SHORT HalpBaudRateDivisor = 0;
+
+#if !defined(_R98_) // K001
+//
+// Define hardware PTE's that map the serial port used by the debugger.
+//
+
+ENTRYLO HalpPte[2];
+#endif
+
+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:
+
+ DebugParameter - 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;
+#if !defined(_R98_)
+ ULONG KdPortEntry;
+#endif //!defined(_R98_) K002
+ PCM_PARTIAL_RESOURCE_LIST List;
+ ULONG MatchKey;
+ ULONG BaudRate;
+ ULONG BaudClock;
+
+
+ //
+ // 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
+ );
+
+ //
+ // If the debugger is not being enabled, then return.
+ //
+
+ if (Initialize == FALSE) {
+ return TRUE;
+ }
+#if !defined(_R98_) // K001
+ //
+ // Map the serial port into the system virtual address space by loading
+ // a TB entry.
+ //
+
+ HalpPte[0].PFN = SP_PHYSICAL_BASE >> PAGE_SHIFT;
+ HalpPte[0].G = 1;
+ HalpPte[0].V = 1;
+ HalpPte[0].D = 1;
+
+#if defined(R3000)
+
+ //
+ // Set the TB entry and set the noncached bit in the PTE that will
+ // map the serial controller.
+ //
+
+ KdPortEntry = KDPORT_ENTRY;
+ HalpPte[0].N = 1;
+
+#endif
+
+#if defined(R4000)
+
+ //
+ // Allocate a TB entry, set the uncached policy in the PTE that will
+ // map the serial controller, and initialize the second PTE.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+ HalpPte[0].C = UNCACHED_POLICY;
+
+ HalpPte[1].PFN = 0;
+ HalpPte[1].G = 1;
+ HalpPte[1].V = 0;
+ HalpPte[1].D = 0;
+ HalpPte[1].C = 0;
+
+#endif
+#endif // _R98_
+
+ KdComPortInUse=(PUCHAR)SERIAL0_PHYSICAL_BASE;
+
+#if !defined(_R98_) // K001
+ //
+ // Map the serial controller through a fixed TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+#endif // _R98_
+ //
+ // 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.
+ //
+ ((PSP_LINE_CONTROL)(&DataByte))->DivisorLatch = 1;
+ WRITE_REGISTER_UCHAR(&SP_WRITE->LineControl, DataByte);
+ WRITE_REGISTER_UCHAR(&SP_WRITE->TransmitBuffer,(UCHAR)(HalpBaudRateDivisor&0xFF));
+
+ WRITE_REGISTER_UCHAR(&SP_WRITE->InterruptEnable,(UCHAR)(HalpBaudRateDivisor>>8));
+
+ //
+ // 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);
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+#if !defined(_R98_) // K002
+#if defined(R4000)
+
+ HalpFreeTbEntry();
+
+#endif
+#endif
+ 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;
+
+ 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 = 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.
+
+--*/
+
+{
+
+ //
+ // Free the TB entry if one was allocated.
+ //
+#if !defined(_R98_) // K001
+#if defined(R4000)
+
+ HalpFreeTbEntry();
+
+#endif
+#endif // _R98_
+ return;
+}
+
+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.
+
+--*/
+
+{
+#if !defined(_R98_) // K001
+ ULONG KdPortEntry;
+
+#if defined(R3000)
+
+ //
+ // Set the TB entry that will be used to map the serial controller.
+ //
+
+ KdPortEntry = KDPORT_ENTRY;
+
+#endif
+
+#if defined(R4000)
+
+ //
+ // Allocate the TB entry that will be used to map the serial controller.
+ //
+
+ KdPortEntry = HalpAllocateTbEntry();
+
+#endif
+
+ //
+ // Map the serial controller through a allocated TB entry.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&HalpPte[0],
+ (PVOID)SP_VIRTUAL_BASE,
+ KdPortEntry);
+#endif // _R98_
+ 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 - Suuplies 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/halr98mp/mips/jxreturn.c b/private/ntos/nthals/halr98mp/mips/jxreturn.c
new file mode 100644
index 000000000..0afe8eed8
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxreturn.c
@@ -0,0 +1,189 @@
+#pragma comment(exestr, "@(#) jxreturn.c 1.5 94/10/17 11:47:45 nec")
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ * K001 95/5/31 (Tue) N.Kugimoto
+ * Del TLB mapping del.
+ *
+ * S002 94/6/13 (Mon) T.Samezima
+ * Chg Compile err del
+ *
+ * K002 94/10/11 (Tue) N.Kugimoto
+ * Fix 807 Base
+ */
+
+#include "halp.h"
+#define HEADER_FILE
+#include "kxmips.h"
+
+//
+// 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 KbdGetStatus() (READ_REGISTER_UCHAR(&KbdBase->Control.Status))
+#define KbdStoreCommand(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Control.Command, Byte)
+#define KbdStoreData(Byte) WRITE_REGISTER_UCHAR(&KbdBase->Data.Input, Byte)
+#define KbdGetData() (READ_REGISTER_UCHAR(&KbdBase->Data.Output))
+
+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;
+#if defined(_R98_) // K001
+ // S001
+ volatile KBD_REGISTERS * KbdBase = (KBD_REGISTERS *)(KEYBOARD_PHYSICAL_BASE|KSEG1_BASE);
+#else
+ ENTRYLO Pte[2];
+ volatile KBD_REGISTERS * KbdBase = (KBD_REGISTERS *)DMA_VIRTUAL_BASE;
+
+#endif // _R98_
+ //
+ // Disable Interrupts.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+
+ for (;;) {
+ }
+
+ case HalPowerDownRoutine:
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+ // K002
+ // Reset ISA Display Adapter to 80x25 color text mode.
+ //
+
+ HalpResetX86DisplayAdapter();
+
+#if !defined(_R98_) // K001
+ //
+ // Map the keyboard controller
+ //
+
+ Pte[0].PFN = KEYBOARD_PHYSICAL_BASE >> PAGE_SHIFT;
+ Pte[0].G = 1;
+ Pte[0].V = 1;
+ Pte[0].D = 1;
+
+ #if defined(R3000)
+
+ Pte[0].N = 1;
+
+ #endif
+
+ #if defined(R4000)
+
+ //
+ // set second page to global and not valid.
+ //
+
+ Pte[0].C = UNCACHED_POLICY;
+ Pte[1].G = 1;
+ Pte[1].V = 0;
+
+ #endif
+
+ //
+ // Map keyboard controller using virtual address of DMA controller.
+ //
+
+ KeFillFixedEntryTb((PHARDWARE_PTE)&Pte[0],
+ (PVOID)DMA_VIRTUAL_BASE,
+ DMA_ENTRY);
+#endif // K001
+
+
+ //
+ // Send WriteOutputBuffer Command to the controller.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+
+ KbdStoreCommand(0xD1);
+
+ //
+ // Write a zero to the output buffer. Causes reset line to be asserted.
+ //
+
+ while ((KbdGetStatus() & KBD_IBF_MASK) != 0) {
+ }
+
+ KbdStoreData(0);
+ for (;;) {
+ }
+
+ default:
+ KdPrint(("HalReturnToFirmware invalid argument\n"));
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
diff --git a/private/ntos/nthals/halr98mp/mips/jxsysint.c b/private/ntos/nthals/halr98mp/mips/jxsysint.c
new file mode 100644
index 000000000..5b3f855c3
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxsysint.c
@@ -0,0 +1,454 @@
+#ident "@(#) NEC jxsysint.c 1.13 94/11/08 16:20:09"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for R98
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * M001 94.03/25-5/31 T.Samezima
+ *
+ * Change Interrupt control
+ * Irql level
+ *
+ * Add Correspond to PCIBus
+ * Exchange mask data
+ * define table of ipi interrupt request
+ *
+ * Del #ifdef DUO
+ *
+ ***********************************************************************
+ *
+ * S002 94.06/02 T.Samezima
+ *
+ * Add HalGetInterruptVector
+ *
+ ***********************************************************************
+ *
+ * S003 94,6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***********************************************************************
+ *
+ * S004 94,7/5 T.Samezima
+ *
+ * Chg Mask value
+ * Maximun EISA vecter
+ *
+ ***********************************************************************
+ *
+ * S005 94,7/8 T.Samezima
+ *
+ * Chg Maximun EISA vecter
+ *
+ ***********************************************************************
+ *
+ * S006 94,7/21 T.Samezima
+ *
+ * Chg Fixd to PCI
+ *
+ *
+ ***********************************************************************
+ *
+ * S007 94,8/22 T.Samezima on SNES
+ *
+ * Chg Designate member
+ *
+ ***********************************************************************
+ *
+ * K001 94/09/26 N.Kugimoto
+ * Mov Move Source code to r98busdat.c
+ ***********************************************************************
+ *
+ * S008 94/09/30 T.Samezima
+ *
+ * Bug Miss define of PCI Interrupt vector.
+ *
+ * S009 94/11/08 T.Samezima
+ * Bug Miss define of IpiRequestMask.
+ *
+ *
+ */
+
+#include "halp.h"
+
+/* Start M001 */
+//
+// Define Ipi Interrupt Reqest value table.
+//
+/* Start S003 */
+ULONG HalpIpiIntRequestMask[] = {
+ IntIR_REQUEST_IPI | (0x00 << IntIR_CPU3_BIT) , // 0000 -> 0000
+ IntIR_REQUEST_IPI | (0x08 << IntIR_CPU3_BIT) , // 0001 -> 1000
+ IntIR_REQUEST_IPI | (0x04 << IntIR_CPU3_BIT) , // 0010 -> 0100
+ IntIR_REQUEST_IPI | (0x0c << IntIR_CPU3_BIT) , // 0011 -> 1100
+ IntIR_REQUEST_IPI | (0x02 << IntIR_CPU3_BIT) , // 0100 -> 0010
+ IntIR_REQUEST_IPI | (0x0a << IntIR_CPU3_BIT) , // 0101 -> 1010
+ IntIR_REQUEST_IPI | (0x06 << IntIR_CPU3_BIT) , // 0110 -> 0110
+ IntIR_REQUEST_IPI | (0x0e << IntIR_CPU3_BIT) , // 0111 -> 1110
+ IntIR_REQUEST_IPI | (0x01 << IntIR_CPU3_BIT) , // 1000 -> 0001
+ IntIR_REQUEST_IPI | (0x09 << IntIR_CPU3_BIT) , // 1001 -> 1001
+ IntIR_REQUEST_IPI | (0x05 << IntIR_CPU3_BIT) , // 1010 -> 0101
+ IntIR_REQUEST_IPI | (0x0d << IntIR_CPU3_BIT) , // 1011 -> 1101
+ IntIR_REQUEST_IPI | (0x03 << IntIR_CPU3_BIT) , // 1100 -> 0011 // S009
+ IntIR_REQUEST_IPI | (0x0b << IntIR_CPU3_BIT) , // 1101 -> 1011
+ IntIR_REQUEST_IPI | (0x07 << IntIR_CPU3_BIT) , // 1110 -> 0111
+ IntIR_REQUEST_IPI | (0x0f << IntIR_CPU3_BIT) // 1111 -> 1111
+ };
+/* End S003 */
+/* End M001 */
+
+
+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 builtin devices, then
+ // disable the builtin device interrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
+ HalpBuiltinInterruptEnable &= ~(1 << (Vector - DEVICE_VECTORS - 1));
+ /* Start M001 */
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+ /* End M001 */
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt.
+ //
+
+ /* Start M001 */
+ /* Start S003 */
+ if (Vector >= EISA_VECTORS &&
+ Vector <= MAXIMUM_EISA_VECTORS && // S004
+ Irql == INT1_LEVEL) {
+ HalpDisableEisaInterrupt(Vector);
+ }
+ /* End S003 */
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ /* Start S006 */
+ if (Vector == PCI_DEVICE_VECTOR && Irql == INT1_LEVEL) {
+ HalpDisablePciInterrupt(Vector);
+ }
+ /* End S006 */
+ /* End M001 */
+
+ //
+ // Release the device enable spin loc 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;
+
+ //
+ // 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 builtin devices, then
+ // enable the builtin device interrupt.
+ //
+
+ if ((Vector >= (DEVICE_VECTORS + 1)) && (Vector <= MAXIMUM_BUILTIN_VECTOR)) {
+ HalpBuiltinInterruptEnable |= (1 << (Vector - DEVICE_VECTORS - 1));
+ /* Start M001 */
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+ /* End M001 */
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt and set the Level/Edge register.
+ //
+
+ /* Start M001 */
+ /* Start S003 */
+ if (Vector >= EISA_VECTORS &&
+ Vector <= MAXIMUM_EISA_VECTORS && // S005
+ Irql == INT1_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ }
+ /* End S003 */
+
+ //
+ // If the vector number is within the range of the PCI interrupts, then
+ // disable the PCI interrrupt.
+ //
+
+ /* Start S006 */
+ if (Vector == PCI_DEVICE_VECTOR && Irql == INT1_LEVEL) {
+ HalpEnablePciInterrupt(Vector);
+ }
+ /* End S006 */
+ /* End M001 */
+
+ //
+ // Release the device enable spin loc 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.
+
+--*/
+
+{
+ /* Start M001 */
+ ULONG buffer;
+ /* End M001 */
+
+ //
+ // Request an interprocessor interrupt on each of the specified target
+ // processors.
+ //
+
+ /* Start M001 */
+ buffer = HalpIpiIntRequestMask[(Mask & 0xf)] | // S004
+ ( (((PCR->Prcb)->Number) & 0x3) << IntIR_CODE_BIT );
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->IntIR.Long, buffer); // S007
+ /* End M001 */
+
+ return;
+}
+
+#if 0 //K001
+ULONG
+HalGetInterruptVector(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ 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:
+
+ InterfaceType - Supplies the type of bus which the vector is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusInterruptLevel - Supplies the bus specific interrupt level.
+
+ BusInterruptVector - Supplies the bus specific interrupt vector.
+
+ Irql - Returns the system request priority.
+
+ Affinity - Returns the affinity for the requested vector.
+
+Return Value:
+
+ Returns the system interrupt vector corresponding to the specified device.
+
+--*/
+
+{
+
+ //
+ // N.B. On Jazz systems which are single processor systems, all interrupts
+ // go to processor 0. On Duo systems both processors could handle
+ // interrupts, but the hardware does not arbitrate and distribute
+ // interrupts, and therefore, both processors would get all interrupts.
+ //
+
+ *Affinity = 1;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ *Irql = (KIRQL)BusInterruptLevel;
+ /* Start S002 */
+ return(BusInterruptVector + DEVICE_VECTORS);
+ /* End S002 */
+ }
+
+ /* Start S002 */
+ //
+ // If this is for the pci bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == PCIBus) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ *Irql = INT1_LEVEL;
+ return(PCI_DEVICE_VECTOR); // S008
+ }
+ /* End S002 */
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *Affinity = 0;
+ *Irql = 0;
+ return(0);
+
+ }
+
+ //
+ // Jazz and Duo only have one I/O bus which is an EISA, so the bus
+ // number and the bus interrupt vector are unused.
+ //
+ // The IRQL level is always equal to the EISA level.
+ //
+
+ /* Start S001 */
+ *Irql = INT1_LEVEL;
+ /* End S001 */
+
+ //
+ // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+}
+
+#endif
diff --git a/private/ntos/nthals/halr98mp/mips/jxtime.c b/private/ntos/nthals/halr98mp/mips/jxtime.c
new file mode 100644
index 000000000..b9d543f1b
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxtime.c
@@ -0,0 +1,313 @@
+#ident "@(#) NEC jxtime.c 1.4 94/11/22 20:09:27"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ jxtime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R3000 or R4000 Jazz system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.03/23 T.Samezima
+ *
+ * Change Irql Level
+ *
+ ***********************************************************************
+ *
+ * S002 94.07/5 T.Samezima
+ *
+ * Change Register access mask
+ *
+ *
+ */
+
+#include "halp.h"
+#include "jazzrtc.h"
+#include "eisa.h"
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+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.
+ //
+
+ /* Start S001 */
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ /* End S001 */
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERD);
+ if (((PRTC_CONTROL_REGISTER_D)(&DataByte))->ValidTime == 1) {
+
+ //
+ // Wait until the realtime clock is not being updated.
+ //
+
+ do {
+ DataByte = HalpReadClockRegister(RTC_CONTROL_REGISTERA);
+ } while (((PRTC_CONTROL_REGISTER_A)(&DataByte))->UpdateInProgress == 1);
+
+ //
+ // Read the realtime clock values.
+ //
+
+ TimeFields->Year = 1980 + (CSHORT)HalpReadClockRegister(RTC_YEAR);
+ 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.
+ //
+
+ /* Start S001 */
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ /* End S001 */
+ DataByte = HalpReadClockRegister(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))->DataMode = 1;
+ ((PRTC_CONTROL_REGISTER_B)(&DataByte))->SetTime = 1;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+
+ //
+ // Write the realtime clock values.
+ //
+
+ HalpWriteClockRegister(RTC_YEAR, (UCHAR)(TimeFields->Year - 1980));
+ 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;
+ HalpWriteClockRegister(RTC_CONTROL_REGISTERB, DataByte);
+ KeLowerIrql(OldIrql);
+ return TRUE;
+
+ } else {
+ KeLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+UCHAR
+HalpReadClockRegister (
+ 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 EISA 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.
+ //
+
+ /* Start S002 */
+ Register |= 0x80;
+ /* End S002 */
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Read the realtime clock register value.
+ //
+
+ return READ_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase);
+}
+
+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.
+
+--*/
+
+{
+
+ //
+ // Insert the realtime clock register number, and write the value back
+ // to the EISA NMI enable register. This selects the realtime clock
+ // register that is written. Note this is a write only register and
+ // the EISA NMI is always enabled.
+ //
+
+ /* Start S002 */
+ Register |= 0x80;
+ /* End S002 */
+
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpEisaControlBase)->NmiEnable,
+ Register);
+
+ //
+ // Write the realtime clock register value.
+ //
+
+ WRITE_REGISTER_UCHAR((PUCHAR)HalpRealTimeClockBase, Value);
+ return;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/jxusage.c b/private/ntos/nthals/halr98mp/mips/jxusage.c
new file mode 100644
index 000000000..dd480366e
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/jxusage.c
@@ -0,0 +1,497 @@
+#ident "@(#) NEC jxusage.c 1.3 94/10/19 22:05:01"
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixusage.c
+
+Abstract:
+
+Author:
+
+ Ken Reneris (kenr)
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+ ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 22:26:38 JST 1994
+ - Change PRIMARY_VECTOR_BASE to DEVICE_VECTOTRS
+ CHG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 22:53:42 JST 1994
+ - delete HalpEnableInterruptHandler, HalpRegisterVector
+ - change IDT vector LOOP, R98 report up to DEVICE_VECTORS
+ - change MAXIMUM_IDTVECTOR to MAXIMUM_VECTOR
+ CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:53:32 JST 1994
+ - resolve compile error
+
+--*/
+
+#include "halp.h"
+
+
+//
+// Array to remember hal's IDT usage
+//
+
+#if !defined(_R98_) // CMP001
+extern ADDRESS_USAGE *HalpAddressUsageList;
+extern IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+#endif // _R98
+
+KAFFINITY HalpActiveProcessors;
+
+VOID
+HalpGetResourceSortValue (
+ IN PCM_PARTIAL_RESOURCE_DESCRIPTOR pRCurLoc,
+ OUT PULONG sortscale,
+ OUT PLARGE_INTEGER sortvalue
+ );
+
+// CMP001
+VOID
+HalpReportResourceUsage (
+ IN PUNICODE_STRING HalName,
+ IN INTERFACE_TYPE DeviceInterfaceToUse
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpGetResourceSortValue)
+#pragma alloc_text(INIT,HalpReportResourceUsage)
+#endif
+
+
+
+#if !defined (_R98_) // CHG001
+VOID
+HalpEnableInterruptHandler (
+ IN UCHAR ReportFlags,
+ IN ULONG BusInterruptVector,
+ IN ULONG SystemInterruptVector,
+ IN KIRQL SystemIrql,
+ IN VOID (*HalInterruptServiceRoutine)(VOID),
+ IN KINTERRUPT_MODE InterruptMode
+ )
+/*++
+
+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
+ //
+ HalpRegisterVector (ReportFlags, BusInterruptVector, SystemInterruptVector, SystemIrql);
+
+
+ //
+ // Connect the IDT and enable the vector now
+ //
+
+ KiSetHandlerAddressToIDT(SystemInterruptVector, HalInterruptServiceRoutine);
+ HalEnableSystemInterrupt(SystemInterruptVector, SystemIrql, InterruptMode);
+}
+
+
+
+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;
+}
+#endif // _R98_
+
+
+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;
+
+ //
+ // Make sure all vectors 00-2f are reserved
+ // 00-1E reserved by Intel
+ // 1F reserved by Intel for APIC (apc priority level)
+ // 20-2e reserved by Microsoft
+ // 2f reserved by Microsoft for APIC (dpc priority level)
+ //
+
+#if defined(_R98_) // CHG001
+ for(i=0; i < DEVICE_VECTORS; i++) { // ADD001
+ HalpIDTUsage[i].Flags = InternalUsage | InterruptLatched;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+#else
+ for(i=0; i < PRIMARY_VECTOR_BASE; i++) {
+ if (!(HalpIDTUsage[i].Flags & IDTOwned)) {
+ HalpIDTUsage[i].Flags = InternalUsage;
+ HalpIDTUsage[i].BusReleativeVector = (UCHAR) i;
+ }
+ }
+#endif
+
+ 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_VECTOR) { // CHG001
+ //
+ // 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/halr98mp/mips/mipsdat.c b/private/ntos/nthals/halr98mp/mips/mipsdat.c
new file mode 100644
index 000000000..23a92be23
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/mipsdat.c
@@ -0,0 +1,144 @@
+#ident "@(#) NEC mipsdat.c 1.2 95/06/19 11:11:45"
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ ixdat.c
+
+Abstract:
+
+ Declares various data which is initialize data, or pagable data.
+
+Author:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*++
+
+Revision History:
+
+ ADD001 ataka@oa2.kb.nec.co.jp Mon Oct 17 20:53:16 JST 1994
+ - add HalpMapRegisterMemorySpace
+ BUG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 21:49:18 JST 1994
+ - change HalpMapRegisterMemorySpace Size
+ CNG001 ataka@oa2.kb.nec.co.jp Mon Oct 17 21:58:30 JST 1994
+ - change HalpIDTUsage size to MAXIMUM_VECTOR
+ CMP001 ataka@oa2.kb.nec.co.jp Tue Oct 18 15:34:47 JST 1994
+ - resolve compile error
+ A002 ataka@oa2.kb.nec.co.jp 1995/6/17
+ - marge 1050
+--*/
+
+
+
+
+#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 HalpDefaultPcIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ EISA_CONTROL_PHYSICAL_BASE+0x000, 0x10, // ISA DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x0C0, 0x10, // ISA DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x080, 0x10, // DMA
+
+ EISA_CONTROL_PHYSICAL_BASE+0x020, 0x2, // PIC
+ EISA_CONTROL_PHYSICAL_BASE+0x0A0, 0x2, // Cascaded PIC
+
+ EISA_CONTROL_PHYSICAL_BASE+0x040, 0x4, // Timer1, Referesh, Speaker, Control Word
+ EISA_CONTROL_PHYSICAL_BASE+0x048, 0x4, // Timer2, Failsafe
+
+ EISA_CONTROL_PHYSICAL_BASE+0x061, 0x1, // NMI (system control port B)
+ EISA_CONTROL_PHYSICAL_BASE+0x092, 0x1, // system control port A
+
+ EISA_CONTROL_PHYSICAL_BASE+0x070, 0x2, // Cmos/NMI enable
+ EISA_CONTROL_PHYSICAL_BASE+0x0F0, 0x10, // coprocessor ports
+ 0,0
+ }
+};
+
+ADDRESS_USAGE HalpEisaIoSpace = {
+ NULL, CmResourceTypePort, InternalUsage,
+ {
+ EISA_CONTROL_PHYSICAL_BASE+0x0D0, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x400, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x480, 0x10, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x4C2, 0xE, // DMA
+ EISA_CONTROL_PHYSICAL_BASE+0x4D4, 0x2C, // DMA
+
+ EISA_CONTROL_PHYSICAL_BASE+0x461, 0x2, // Extended NMI
+ EISA_CONTROL_PHYSICAL_BASE+0x464, 0x2, // Last Eisa Bus Muster granted
+
+ EISA_CONTROL_PHYSICAL_BASE+0x4D0, 0x2, // edge/level control registers
+
+ EISA_CONTROL_PHYSICAL_BASE+0xC84, 0x1, // System board enable
+ 0, 0
+ }
+};
+
+#define R98_MAPREGISTER_BASE 100 // CMP001
+
+// BUG001
+ADDRESS_USAGE HalpMapRegisterMemorySpace = {
+ NULL, CmResourceTypeMemory, InternalUsage,
+ {
+ R98_MAPREGISTER_BASE, (USHORT)(DMA_TRANSLATION_LIMIT/(sizeof(TRANSLATION_ENTRY))*PAGE_SIZE), // for Map Register Area CMP001
+ 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";
+WCHAR rgzReservedResources[] = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\SystemResources\\ReservedResources"; // A002
+
+
+#ifdef ALLOC_DATA_PRAGMA
+#pragma data_seg()
+#endif
+
+//
+// IDT vector usage info
+//
+// CNG001
+#if defined(MIPS)
+IDTUsage HalpIDTUsage[MAXIMUM_VECTOR]; // Size of PCR->InterruptRoutine[]
+#else // CMP001
+IDTUsage HalpIDTUsage[MAXIMUM_IDTVECTOR];
+#endif
+
diff --git a/private/ntos/nthals/halr98mp/mips/mode542x.h b/private/ntos/nthals/halr98mp/mips/mode542x.h
new file mode 100644
index 000000000..00445a6d9
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/mode542x.h
@@ -0,0 +1,1302 @@
+#ident "@(#) NEC mode542x.h 1.3 95/07/05 13:10:57"
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Mode542x.h
+
+Abstract:
+
+ This module contains all the global data used by the Cirrus Logic
+ CL-542x driver.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+//
+// The next set of tables are for the CL542x
+// Note: all resolutions supported
+//
+
+//
+// 640x480 16-color mode (BIOS mode 12) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in 640x480 mode
+
+ EOD
+};
+
+//
+// 800x600 16-color (60Hz refresh) mode set command string for CL 542x.
+//
+
+USHORT CL542x_800x600[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in 800x600 mode
+
+ EOD
+};
+
+//
+// 1024x768 16-color (60Hz refresh) mode set command string for CL 542x.
+//
+
+USHORT CL542x_1024x768[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ EOD
+};
+
+//-----------------------------
+// standard VGA text modes here
+// 80x25 at 640x350
+//
+//-----------------------------
+
+//
+// 80x25 text mode set command string for CL 542x.
+// (720x400 pixel resolution; 9x16 character cell.)
+//
+
+USHORT CL542x_80x25Text[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in text mode
+
+ EOD
+};
+
+//
+// 80x25 text mode set command string for CL 542x.
+// (640x350 pixel resolution; 8x14 character cell.)
+//
+
+USHORT CL542x_80x25_14_Text[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+ 0x0009, 0x000a, 0x000b, // no banking in text mode
+
+ EOD
+};
+
+//
+// 1280x1024 16-color mode (BIOS mode 0x6C) set command string for CL 542x.
+//
+
+USHORT CL542x_1280x1024[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+//
+// 640x480 64k-color mode (BIOS mode 0x64) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480_64k[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 4,
+ 0x0506, // Some BIOS's set Chain Odd maps bit
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+#ifdef _X86_
+
+//
+// 640x480 256-color mode (BIOS mode 0x5F) set command string for CL 542x.
+//
+
+USHORT CL542x_640x480_256[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+//
+// 800x600 256-color mode (BIOS mode 0x5C) set command string for CL 542x.
+//
+
+USHORT CL542x_800x600_256[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+#if ONE_64K_BANK
+ 0x0009, 0x000a, 0x000b,
+#endif
+#if TWO_32K_BANKS
+ 0x0009, 0x000a, 0x010b,
+#endif
+
+ EOD
+};
+
+#else
+
+//
+// NOTE(DBCS) : Update 94/09/12 - NEC Corporation
+//
+// - Add mode set command string for NEC MIPS machine.
+//
+// - 640x480 256 color 72Hz
+// - 800x600 256 color 56 / 60Hz
+// - 1024x768 256 color 70 / 45Hz
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+//
+// For MIPS NEC machine only
+//
+
+//
+// 640x480 256-color 60Hz mode (BIOS mode 0x5F) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_640x480_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// the Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x7E0E,
+ 0x2B1B,0x2F1C,0x301D,0x331E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xE3,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x5D, 0x4F, 0x50, 0x82, 0x53, 0x9F,
+ 0x00, 0x3E, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE1, 0x83,
+ 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80,
+ 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c,
+ 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 640x480 256-color 72Hz mode (BIOS mode 0x5F) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_640x480_256_72[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// the Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x420E,
+ 0x2B1B,0x2F1C,0x301D,0x1F1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 95/06/30 - NEC Corporation (same as cirrus\mode542x.h)
+//
+// - Set Mode Type is VESA compatible. (Old Miss match)
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x61, 0x4F, 0x50, 0x82, 0x54, 0x99,
+ 0xF6, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03,
+ 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+
+// 0x63, 0x4F, 0x50, 0x82, 0x55, 0x9A, thase parameter not match
+// 0x06, 0x3E, 0x00, 0x40, 0x00, 0x00, VESA Mode.
+// 0x00, 0x00, 0x00, 0x00, 0xE8, 0x8B,
+// 0xDF, 0x50, 0x00, 0xE7, 0x04, 0xE3,
+// 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80,
+ 0x0b, 0x3e, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xea, 0x8c,
+ 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 56Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_56[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x7E0E,
+ 0x2B1B,0x2F1C,0x301D,0x331E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7B, 0x63, 0x64, 0x80, 0x69, 0x12,
+ 0x6F, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x8A,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 60Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B,0x5B0C,0x450D,0x510E,
+ 0x2B1B,0x2F1C,0x301D,0x3A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B,
+ 0x72, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x58, 0x8C,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 800x600 256-color 72Hz mode (BIOS mode 0x5C) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_800x600_256_72[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x4A0B,0x5B0C,0x450D,0x650E,
+
+#else
+
+ 0x4A0B,0x5B0C,0x450D,0x640E,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ 0x2B1B,0x2F1C,0x301D,0x3A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x96, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x81,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3,
+ 0xFF, 0x00, 0x00, 0x22,
+
+#else
+
+ 0x7D, 0x63, 0x64, 0x80, 0x6D, 0x1C,
+ 0x98, 0xF0, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7B, 0x80,
+ 0x57, 0x64, 0x00, 0x5F, 0x91, 0xe3,
+ 0xff, 0x00, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 60Hz mode (BIOS mode 0x60) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_1024x768_256_60[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x4A0B, 0x5B0C, 0x450D, 0x760E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x341E,
+
+#else
+
+ 0x4A0B, 0x5B0C, 0x450D, 0x3B0E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x1A1E,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3,
+ 0xff, 0x4A, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 70Hz mode (BIOS mode 0x60) set command string for
+// CL 542x.
+//
+
+USHORT CL542x_1024x768_256_70[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B, 0x5B0C, 0x450D, 0x6E0E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x2A1E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+ 0xEF,
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xA1, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3,
+ 0xFF, 0x4A, 0x00, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0x24, 0xFD, 0x00, 0x60, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x88,
+ 0xFF, 0x80, 0x00, 0x00, 0x24, 0xe3,
+ 0xff, 0x4A, 0x00, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+//
+// 1024x768 256-color 87Hz mode (BIOS mode 0x60) set command string for
+// CL 542x. (Interlaced)
+//
+
+USHORT CL542x_1024x768_256_87[] = {
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 2, // count
+ 0x1206, // enable extensions
+ 0x0012,
+
+ OWM, // begin setmode
+ SEQ_ADDRESS_PORT,
+ 15, // count
+ 0x100, // start sync reset
+ 0x0101,0x0F02,0x0003,0x0E04, // program up sequencer
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed Liner addressing.
+//
+
+ (LA_MASK << 12 | 0x0107),
+ 0x0008,
+ 0x4A0B, 0x5B0C, 0x450D, 0x550E,
+ 0x2B1B, 0x2F1C, 0x301D, 0x361E,
+
+ OB, // point sequencer index to ff
+ SEQ_ADDRESS_PORT,
+ 0x0F,
+
+ METAOUT+MASKOUT, // masked out.
+ SEQ_DATA_PORT,
+ 0xDF,0x20, // and mask, xor mask
+
+ OB, // misc. register
+ MISC_OUTPUT_REG_WRITE_PORT,
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0xEF,
+
+#else
+
+ 0x2F,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ OW, // text/graphics bit
+ GRAPH_ADDRESS_PORT,
+ 0x506,
+
+ OW, // end sync reset
+ SEQ_ADDRESS_PORT,
+ 0x300,
+
+ OW, // unprotect crtc 0-7
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x2011,
+
+ METAOUT+INDXOUT, // program crtc registers
+ CRTC_ADDRESS_PORT_COLOR,
+ 28,0, // count, startindex
+
+//
+// NOTE(DBCS) : Update 94/10/26 - NEC Corporation
+//
+// - Set Mode Type is VESA compatible.
+//
+
+#if defined(DBCS) && defined(_MIPS_)
+
+ 0x99, 0x7F, 0x80, 0x86, 0x83, 0x99,
+ 0x96, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x7F, 0x83,
+ 0x7F, 0x80, 0x00, 0x7F, 0x12, 0xE3,
+ 0xff, 0x4A, 0x01, 0x22,
+
+#else
+
+ 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96,
+ 0xBE, 0x1F, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x81, 0x84,
+ 0x7F, 0x80, 0x00, 0x80, 0x12, 0xE3,
+ 0xff, 0x4A, 0x01, 0x22,
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+ METAOUT+INDXOUT, // program gdc registers
+ GRAPH_ADDRESS_PORT,
+ 9,0, // count, startindex
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x05, 0x0F, 0xFF,
+
+ IB, // prepare atc for writing
+ INPUT_STATUS_1_COLOR,
+
+ METAOUT+ATCOUT, // program atc registers
+ ATT_ADDRESS_PORT,
+ 21,0, // count, startindex
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
+ 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00,
+ 0x0F, 0x00, 0x00,
+
+ OB, // turn video on.
+ ATT_ADDRESS_PORT,
+ 0x20,
+
+ OB,
+ DAC_PIXEL_MASK_PORT,
+ 0xFF,
+
+ OWM,
+ GRAPH_ADDRESS_PORT,
+ 3,
+
+//
+// The Miniport Driver for R96 machine is Liner addressing mode.
+// This set command was changed it for Liner addressing.
+//
+
+ 0x0009, 0x000a, 0x000b,
+
+ EOD
+};
+
+#endif // defined(DBCS) && defined(_MIPS_)
+
+#endif
diff --git a/private/ntos/nthals/halr98mp/mips/modeset.h b/private/ntos/nthals/halr98mp/mips/modeset.h
new file mode 100644
index 000000000..b699eacc7
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/modeset.h
@@ -0,0 +1,86 @@
+#ident "@(#) NEC modeset.h 1.1 94/07/05 14:06:24"
+/* #pragma comment(exestr, "@(#) NEC(MIPS) modeset.h 1.3 93/10/29 12:25:59" ) */
+/*++
+
+Copyright (c) 1992 Microsoft Corporation
+
+Module Name:
+
+ Modeset.h
+
+Abstract:
+
+ This module contains all the global data used by the Cirrus Logic
+ CL-6410 and CL-6420 driver.
+
+Environment:
+
+ Kernel mode
+
+Notes:
+
+ This module based on Cirrus Minport Driver. And modify for R96 MIPS
+ R4400 HAL Cirrus display initialize.
+
+Revision History:
+
+--*/
+
+/*
+ * M001 1993.19.28 A. Kuriyama @ oa2
+ *
+ * - Modify for R96 MIPS R4400 HAL
+ *
+ * Delete : Mode structure.
+ *
+ * Revision History in Cirrus Miniport Driver as follows:
+ *
+ * L001 1993.10.15 Kuroki
+ *
+ * - Modify for R96 MIPS R4400
+ *
+ * Delete : Micro channel Bus Initialize.
+ * VDM & Text, Fullscreen mode support.
+ * Banking routine.
+ * CL64xx Chip support.
+ * 16-color mode.
+ *
+ * Add : Liner Addressing.
+ *
+ *
+ *
+ */
+
+#include "cmdcnst.h"
+
+//---------------------------------------------------------------------------
+//
+// The actual register values for the supported modes are in chipset-specific
+// include files:
+//
+// mode64xx.h has values for CL6410 and CL6420
+// mode542x.h has values for CL5422, CL5424, and CL5426
+//
+
+
+USHORT HalpCirrus_MODESET_1K_WIDE[] = {
+ OW, // stretch scans to 1k
+ CRTC_ADDRESS_PORT_COLOR,
+ 0x8013,
+
+ EOD
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/private/ntos/nthals/halr98mp/mips/pcibrd.c b/private/ntos/nthals/halr98mp/mips/pcibrd.c
new file mode 100644
index 000000000..c4ea03464
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/pcibrd.c
@@ -0,0 +1,1020 @@
+#ident "@(#) NEC pcibrd.c 1.2 95/06/19 11:12:35"
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpcibrd.c
+
+Abstract:
+
+ Get PCI-PCI bridge information
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#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;
+ }
+ 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
+
+ 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/halr98mp/mips/pcip.h b/private/ntos/nthals/halr98mp/mips/pcip.h
new file mode 100644
index 000000000..b757a07a7
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/pcip.h
@@ -0,0 +1,214 @@
+#ident "@(#) NEC pcip.h 1.4 95/06/19 11:13:40"
+/*
+
+ Revision History
+
+ A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ - Marge 807-halr98mp-pcip.h to 1050-halx86-pcip.h
+*/
+
+//
+// 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 {
+ PUCHAR CSE;
+ PUCHAR Forward;
+ ULONG Base;
+ } 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
+
+#if defined(_R98_) // A002
+
+typedef struct _PCI_TYPER98_CFG_BITS {
+ union {
+ struct {
+ ULONG Reserved1:2;
+ ULONG RegisterNumber:6;
+ ULONG FunctionNumber:3;
+ ULONG SlotNumber:2;
+ ULONG BaseAddress:19;
+ } bits;
+
+ ULONG AsULONG;
+ } u;
+} PCI_TYPER98_CFG_BITS, *PPCI_TYPER98_CFG_BITS;
+
+#define PCI_CONFIG_BASE_ADDRESS 0xb8ca8000 /* N001 */
+
+#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/halr98mp/mips/r98busdt.c b/private/ntos/nthals/halr98mp/mips/r98busdt.c
new file mode 100644
index 000000000..a14d3cf4c
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98busdt.c
@@ -0,0 +1,1181 @@
+#ident "@(#) NEC r98busdt.c 1.16 95/06/19 11:30:31"
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+ Darryl E. Havens (darrylh) 11-Apr-1990
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+/*++
+
+ Modification History
+
+ N- NEW
+ D- Only For Debug
+ B- Bug Fix
+
+B001 ataka@oa2.kb.nec.co.jp Mon Oct 24 21:40:10 JST 1994
+ - add DbgPrints
+
+B002 samezima@oa2.kb.nec.co.jp MON Nov 21
+ - chg Mask translate address
+
+N005 samezima@oa2.kb.nec.co.jp MON Mar 13
+ - change PIO interrupt vector from internal to eisa.
+A002 ataka@oa2.kb.nec.co.jp 1995/6/17
+ - Marge 1050 halx86 many sources to 807 r98busdat.c
+ and named r98busdt.c
+
+--*/
+
+#include "halp.h"
+#include "string.h" // CMP001
+
+
+UCHAR HalName[] = "NEC MIPS HAL"; // N003
+
+VOID HalpInitializePciBus (VOID); // CMP001
+VOID HalpInitOtherBuses (VOID);
+
+
+//
+// Prototype for system bus handlers
+//
+
+ULONG
+HalpNoBusData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpGetSystemInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+ULONG
+HalpGetEisaInterruptVector (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+BOOLEAN
+HalpTranslateSystemBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslatePCIBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+BOOLEAN
+HalpTranslateIsaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+
+BOOLEAN
+HalpTranslateEisaBusAddress (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+
+HalpGetEisaData (
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+#if DBG // A002
+VOID
+HalpDisplayAllBusRanges (
+ VOID
+ );
+VOID
+HalpDisplayAddressRange (
+ PSUPPORTED_RANGE Address,
+ PUCHAR String
+);
+#endif
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#pragma alloc_text(PAGE,HalGetInterruptVector)
+/* B001 */
+#pragma alloc_text(INIT,HalReportResourceUsage)
+#pragma alloc_text(PAGE,HalpGetEisaInterruptVector)
+#pragma alloc_text(PAGE,HalpAdjustEisaResourceList)
+#pragma alloc_text(PAGE,HalpGetEisaData)
+#pragma alloc_text(PAGE,HalpGetSystemInterruptVector)
+#endif
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpRegisterInternalBusHandlers)
+#pragma alloc_text(INIT,HalpAllocateBusHandler)
+#endif
+
+
+VOID
+HalpRegisterInternalBusHandlers (
+ VOID
+ )
+{
+ PBUS_HANDLER Bus;
+
+ if (KeGetCurrentPrcb()->Number) {
+ // only need to do this once
+ return ;
+ }
+
+ //
+ // Initalize BusHandler data before registering any handlers
+ //
+
+ HalpInitBusHandler ();
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+
+ Bus = HalpAllocateBusHandler (
+ Internal,
+ ConfigurationSpaceUndefined,
+ 0, // Internal BusNumber 0
+ InterfaceTypeUndefined, // no parent bus
+ 0,
+ 0 // no bus specfic data
+ );
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build internal-bus 0, or system level bus
+ //
+ // B003 kugi Internal Bus was called with bus-no. 2, We have no idea.
+
+ Bus = HalpAllocateBusHandler (
+ Internal,
+ ConfigurationSpaceUndefined,
+ 1, // Internal BusNumber 1
+ InterfaceTypeUndefined, // no parent bus
+ 0,
+ 0 // no bus specfic data
+ );
+
+ Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+ Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
+
+ //
+ // Build Isa/Eisa bus #0
+ //
+
+ Bus = HalpAllocateBusHandler (Eisa, EisaConfiguration, 0, Internal, 0, 0);
+ Bus->GetBusData = HalpGetEisaData;
+ Bus->GetInterruptVector = HalpGetEisaInterruptVector;
+ Bus->AdjustResourceList = HalpAdjustEisaResourceList;
+#if defined(_R98_) // A001
+ Bus->TranslateBusAddress = HalpTranslateEisaBusAddress;
+#endif // _R98_
+ Bus = HalpAllocateBusHandler (Isa, ConfigurationSpaceUndefined, 0, Eisa, 0, 0);
+ Bus->GetBusData = HalpNoBusData;
+ Bus->BusAddresses->Memory.Limit = 0xFFFFFF;
+ Bus->TranslateBusAddress = HalpTranslateIsaBusAddress;
+
+ HalpInitOtherBuses ();
+#if DBG // A002
+ HalpDisplayAllBusRanges ();
+#endif
+}
+
+
+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
+ );
+
+ // A001
+ 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->IO.Base = 0;
+ Bus->BusAddresses->IO.SystemAddressSpace = 0;
+ Bus->BusAddresses->PrefetchMemory.Base = 1;
+
+ switch(InterfaceType) {
+ case Internal:
+ Bus->BusAddresses->Memory.Base
+ = 0x00000000;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.Limit))->LowPart
+ = 0xFFFFFFFF;
+ Bus->BusAddresses->Memory.SystemBase
+ = 0x00000000;
+ Bus->BusAddresses->IO.Base
+ = 0x00000000;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.Limit))->LowPart
+ = 0xFFFFFFFF;
+ Bus->BusAddresses->IO.SystemBase
+ = 0x00000000;
+ break;
+ case Eisa:
+ Bus->BusAddresses->Memory.Base
+ = 0x00000000;
+// = 0x01000000;
+ Bus->BusAddresses->Memory.Limit
+ = 0x03FFFFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = EISA_MEMORY_PHYSICAL_BASE;
+ Bus->BusAddresses->IO.Base
+ = 0x00000000;
+ Bus->BusAddresses->IO.Limit
+ = 0x0000FFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = EISA_CONTROL_PHYSICAL_BASE;
+ break;
+ case Isa:
+ Bus->BusAddresses->Memory.Base
+ = 0x00000000;
+ Bus->BusAddresses->Memory.Limit
+ = 0x00FFFFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = EISA_MEMORY_PHYSICAL_BASE;
+ Bus->BusAddresses->IO.Base
+ = 0x00000000;
+ Bus->BusAddresses->IO.Limit
+ = 0x0000FFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = EISA_CONTROL_PHYSICAL_BASE;
+ break;
+ case PCIBus:
+ Bus->BusAddresses->Memory.Base
+ = 0x04000000; // from 64MB
+ Bus->BusAddresses->Memory.Limit
+ = 0x0FFFFFFF; // up to 256MB
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->Memory.SystemBase))->LowPart
+ = PCI_MEMORY_PHYSICAL_BASE;
+ Bus->BusAddresses->IO.Base
+ = 0x00000000;
+ Bus->BusAddresses->IO.Limit
+ = 0x0000FFFF;
+ ((PLARGE_INTEGER)(&Bus->BusAddresses->IO.SystemBase))->LowPart
+ = PCI_CONTROL_SLOT1_PHYSICAL_BASE;
+ break;
+ }
+ }
+
+ return Bus;
+}
+
+// N003
+VOID
+HalReportResourceUsage (
+ VOID
+ )
+{
+ ANSI_STRING AHalName;
+ UNICODE_STRING UHalName;
+
+
+ // N004
+#if 0 // support next version
+ HalpRegisterAddressUsage (&HalpDefaultPcIoSpace);
+ HalpRegisterAddressUsage (&HalpEisaIoSpace);
+ HalpRegisterAddressUsage (&HalpMapRegisterMemorySpace);
+#endif
+
+ RtlInitAnsiString (&AHalName, HalName);
+ RtlAnsiStringToUnicodeString (&UHalName, &AHalName, TRUE);
+ HalpReportResourceUsage (
+ &UHalName, // descriptive name
+ Internal // device space interface type
+ );
+
+ RtlFreeUnicodeString (&UHalName);
+
+ //
+ // Registry is now intialized, see if there are any PCI buses
+ //
+
+ HalpInitializePciBus ();
+}
+
+VOID
+HalpInitOtherBuses (
+ VOID
+ )
+{
+ // no other internal buses supported
+}
+
+
+
+
+ULONG
+HalpGetEisaInterruptVector(
+ 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.
+
+--*/
+{
+ //
+ // Jazz and Duo only have one I/O bus which is an EISA, so the bus
+ // number and the bus interrupt vector are unused.
+ //
+ // The IRQL level is always equal to the EISA level.
+ //
+
+ *Affinity = HalpEisaBusAffinity; // N003
+
+ *Irql = INT1_LEVEL;
+
+ //
+ // Bus interrupt level 2 is actually mapped to bus level 9 in the Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // The vector is equal to the specified bus level plus the EISA_VECTOR.
+ //
+
+ return(BusInterruptLevel + EISA_VECTORS);
+}
+
+HalpGetEisaData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ 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.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ ULONG BusNumber;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+ PAGED_CODE (); // A001
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ DbgPrint("HAL: Open Status = %x\n",NtStatus);
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ BusNumber = BusHandler->BusNumber;
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ DbgPrint("HAL: Opening Bus Number: Status = %x\n",NtStatus);
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION) &i;
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+#if DBG
+ DbgPrint("HAL: Cannot allocate Key Value Buffer\n");
+#endif
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus)) {
+#if DBG
+ DbgPrint("HAL: Query Config Data: Status = %x\n",NtStatus);
+#endif
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+
+#if DBG
+ DbgPrint("Bad Data in registry!\n");
+#endif
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ }
+
+ if (Found) {
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+
+
+
+// N001
+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.
+
+--*/
+{
+ /* N003 vvv */
+ ULONG vector;
+
+ *Irql = (KIRQL)BusInterruptLevel;
+ vector = BusInterruptVector + DEVICE_VECTORS;
+
+ switch(vector) {
+ case SCSI1_VECTOR:
+ case SCSI0_VECTOR:
+ case ETHER_VECTOR:
+ *Affinity = HalpInt1Affinity;
+ break;
+
+ // N005 vvv
+ case PIO_VECTOR:
+ return HalpGetEisaInterruptVector( (PBUS_HANDLER)NULL,
+ (PBUS_HANDLER)NULL,
+ 1,
+ 1,
+ Irql,
+ Affinity
+ );
+ // N005 ^^^
+
+ default:
+ *Affinity = 1;
+ }
+
+ return vector;
+ /* N003 ^^^ */
+}
+
+
+// A001
+NTSTATUS
+HalpAdjustEisaResourceList (
+ 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;
+ InterruptRange.Limit = 15;
+
+ return HaliAdjustResourceListRange (
+ BusHandler->BusAddresses,
+ &InterruptRange,
+ pResourceList
+ );
+}
+
+// A001
+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
+#if DBG
+// DbgPrint("\nHalpTranslateSystemBusAddress-searching(Mem)....");
+#endif
+ for (pRange = &BusHandler->BusAddresses->PrefetchMemory; pRange; pRange = pRange->Next) {
+#if DBG
+// HalpDisplayAddressRange (pRange, "\n PrefetchMemory:");
+#endif // DBG
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+
+ if (!pRange) {
+ for (pRange = &BusHandler->BusAddresses->Memory; pRange; pRange = pRange->Next) {
+#if DBG
+// HalpDisplayAddressRange (pRange, "\n Memory:");
+#endif // DBG
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ }
+
+ break;
+
+ case 1:
+ // verify IO address is within buses IO limits
+#if DBG
+// DbgPrint("HalpTranslateSystemBusAddress-searching(Io)....\n");
+#endif
+ for (pRange = &BusHandler->BusAddresses->IO; pRange; pRange = pRange->Next) {
+#if DBG
+// HalpDisplayAddressRange (pRange, "\n Io:");
+#endif // DBG
+ if (BusAddress.QuadPart >= pRange->Base &&
+ BusAddress.QuadPart <= pRange->Limit) {
+ break;
+ }
+ }
+ break;
+ }
+
+ if (pRange) {
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + pRange->SystemBase;
+#if DBG
+// DbgPrint("\n Translated=0x%08x:%08x\nEnd of Translating Success!\n", TranslatedAddress->HighPart,
+// TranslatedAddress->LowPart);
+#endif // DBG
+ *AddressSpace = pRange->SystemAddressSpace;
+ return TRUE;
+ }
+#if DBG
+// DbgPrint("\nEnd of Translating. False!\n");
+#endif
+
+ return FALSE;
+}
+
+// A001
+BOOLEAN
+HalpTranslateIsaBusAddress(
+ 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
+
+--*/
+
+{
+ BOOLEAN Status;
+
+ //
+ // Translated normally
+ //
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+
+
+ //
+ // If it could not be translated, and it's memory space
+ // then we allow the translation as it would occur on it's
+ // corrisponding EISA bus. We're allowing this because
+ // many VLBus drivers are claiming to be ISA devices.
+ // (yes, they should claim to be VLBus devices, but VLBus is
+ // run by video cards and like everything else about video
+ // there's no hope of fixing it. (At least according to
+ // Andre))
+ //
+
+ if (Status == FALSE && *AddressSpace == 0) {
+ Status = HalTranslateBusAddress (
+ Eisa,
+ BusHandler->BusNumber,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+ }
+
+ return Status;
+}
+
+// A001
+BOOLEAN
+HalpTranslateEisaBusAddress(
+ 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
+
+--*/
+
+{
+ BOOLEAN Status;
+
+ //
+ // Translated normally
+ //
+
+ Status = HalpTranslateSystemBusAddress (
+ BusHandler,
+ RootHandler,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+
+
+ //
+ // If it could not be translated, and it's in the 640k - 1m
+ // range then (for compatibility) try translating it on the
+ // Internal bus for
+ //
+
+ if (Status == FALSE &&
+ *AddressSpace == 0 &&
+ BusAddress.HighPart == 0 &&
+ BusAddress.LowPart >= 0xA0000 &&
+ BusAddress.LowPart < 0xFFFFF) {
+
+ Status = HalTranslateBusAddress (
+ Internal,
+ 0,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress
+ );
+ }
+
+ return Status;
+}
+
+#if DBG
+VOID
+HalpDisplayAddressRange (
+ PSUPPORTED_RANGE Address,
+ PUCHAR String
+ )
+/*++
+
+Routine Description:
+
+ Debugging code. Used only by HalpDisplayAllBusRanges
+
+--*/
+{
+ ULONG i;
+
+ i = 0;
+ while (Address) {
+ if (i == 0) {
+ DbgPrint (String);
+ i = 3;
+ }
+
+ i -= 1;
+ DbgPrint (" %x:%08x - %x:%08x + %x:%08x",
+ (ULONG) (Address->Base >> 32),
+ (ULONG) (Address->Base),
+ (ULONG) (Address->Limit >> 32),
+ (ULONG) (Address->Limit),
+ (ULONG) (Address->SystemBase >> 32),
+ (ULONG) (Address->SystemBase)
+ );
+
+ Address = Address->Next;
+ }
+}
+#endif // DBG
diff --git a/private/ntos/nthals/halr98mp/mips/r98busdt.h b/private/ntos/nthals/halr98mp/mips/r98busdt.h
new file mode 100644
index 000000000..0517105f5
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98busdt.h
@@ -0,0 +1,142 @@
+#ident "@(#) NEC r98busdat.h 1.2 94/10/19 22:15:10"
+/*++
+
+Module Name:
+
+ ixhwsup.c
+
+Abstract:
+
+ This module contains the IoXxx routines for the NT I/O system that
+ are hardware dependent. Were these routines not hardware dependent,
+ they would reside in the iosubs.c module.
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+--*/
+/*++
+
+ Modification History
+
+ N- NEW
+ D- Only For Debug
+ B- Bug Fix
+
+ N001 ataka@oa2.kb.nec.co.jp Tue Oct 4 21:29:32 JST 1994
+ - (from r98busdat.h && halx86/i386/halp.h)
+
+--*/
+
+//
+// Bus handlers
+//
+
+typedef ULONG
+(*PGETSETBUSDATA)(
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+typedef ULONG
+(*PGETINTERRUPTVECTOR)(
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ );
+
+typedef BOOLEAN
+(*PTRANSLATEBUSADDRESS)(
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ );
+
+typedef NTSTATUS
+(*PADJUSTRESOURCELIST)(
+ IN PVOID BusHandler,
+ IN PVOID RootHandler,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+typedef NTSTATUS
+(*PASSIGNSLOTRESOURCES)(
+ IN PVOID BusHandler,
+ IN PVOID 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
+ );
+
+typedef struct tagBUSHANDLER {
+ struct tagBUSHANDLER *Next;
+
+ // this entry is for:
+ INTERFACE_TYPE InterfaceType;
+ BUS_DATA_TYPE ConfigurationType;
+ ULONG BusNumber;
+
+ // bus specific data:
+ struct tagBUSHANDLER *ParentHandler;
+ PVOID BusData;
+
+ // handlers for bus functions
+ PGETSETBUSDATA GetBusData;
+ PGETSETBUSDATA SetBusData;
+ PADJUSTRESOURCELIST AdjustResourceList;
+ PASSIGNSLOTRESOURCES AssignSlotResources;
+ PGETINTERRUPTVECTOR GetInterruptVector;
+ PTRANSLATEBUSADDRESS TranslateBusAddress;
+} BUSHANDLER, *PBUSHANDLER;
+
+#define HalpSetBusHandlerParent(c,p) (c)->ParentHandler = p;
+
+PBUSHANDLER 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
+
+PBUSHANDLER HalpHandlerForBus (
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber
+ );
+
+
+NTSTATUS
+HalpAdjustResourceListLimits (
+ IN PBUSHANDLER BusHandler,
+ IN PBUSHANDLER 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
+ );
diff --git a/private/ntos/nthals/halr98mp/mips/r98clock.s b/private/ntos/nthals/halr98mp/mips/r98clock.s
new file mode 100644
index 000000000..73f629f57
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98clock.s
@@ -0,0 +1,471 @@
+// "@(#) NEC r98clock.s 1.10 95/02/20 17:04:37"
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// r98clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+//--
+
+//
+// Original source: Build Number 1.612
+//
+// Modify for R98(MIPS/R4400)
+//
+//***********************************************************************
+//
+// M001 94.03/16-5/31 T.Samezima
+//
+// change header file from duo to r98
+// change value of use to update of parformance counter
+// initial value of count register
+//
+// del clear interrupt
+//
+//***********************************************************************
+//
+// S002 94.6/13 T.Samezima
+//
+// Del Compile err
+//
+//
+//***********************************************************************
+//
+// S003 94.7/19 T.Samezima
+//
+// Chg Function interface change
+//
+//***********************************************************************
+//
+// S004 94.7/19 T.Samezima
+//
+// Bug PMC register address is not change of KSEG1_BASE
+//
+//***********************************************************************
+//
+// S005 94.10/12 T.Samezima
+//
+// Fix Version Up at build807
+//
+// S006 '94.10/14 T.Samezima
+// Chg Logic of set interval count
+//
+// S007 '94.01/11 T.Samezima
+// Del delete 'if NT_UP'.
+//
+// S008 '94.01/16 T.Samezima
+// Add Check ECC 1bit err flag and enable ECC 1bit err.
+//
+//
+
+#include "halmips.h"
+// Start M001
+#if defined(_R98_)
+
+#include "r98def.h"
+// #include "r98reg.h" // S002
+
+#else // if defined(_R98_)
+
+#if defined(_DUO_)
+
+#include "duodef.h"
+
+#endif
+
+#if defined(_JAZZ_)
+
+#include "jazzdef.h"
+
+#endif
+#endif // #if !defined(_R98_)
+// End M001
+
+#define ECC_ERROR_COUNT_LIMIT 1 // S008
+
+
+ SBTTL("System Clock Interrupt - Processor 0")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt and
+// transfer control to the standard system routine to update the system
+// time and the execution time of the current thread and process.
+//
+// Arguments:
+//
+// a0 - Supplies a pointer to a trap frame. // S003
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt0, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+// Start M001
+#if !defined(_R98_)
+ .set noreorder
+
+#if defined(_DUO_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt
+
+#endif
+
+#if defined(_JAZZ_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x230 // acknowledge timer interrupt
+
+#endif
+
+ .set reorder
+#endif // #if !defined(_R98_)
+// End M001
+
+// S003
+// move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement // set current time increment
+ lw t0,__imp_KeUpdateSystemTime // update system time // S005
+ jal t0 // // S005
+
+//
+// The following code is a work around for a bug in the Fusion machines
+// where the clock interrupt is not dismissed by reading the acknowledge
+// register.
+//
+
+// Start M001
+#if !defined(_R98_)
+#if defined(_JAZZ_)
+
+ .set noreorder
+ .set noat
+ mfc0 t0,cause // read the cause register
+ lw t1,HalpEisaControlBase // get EISA control base address
+ sll t0,t0,31 - (CAUSE_INTPEND + CLOCK_LEVEL - 1) // isolate clock bit
+ bgez t0,10f // if gez, no clock interrupt pending
+ li t2,0x2 // get NMI port enable bit
+ lb t3,0x70(t1) // save EISA NMI interrupt disable
+ lb t4,0x461(t1) // save EISA extended NMI status
+ sb zero,0x70(t1) // clear EISA NMI interrupt disable
+ sb t2,0x461(t1) // set EISA NMI port enable
+ sb zero,0x462(t1) // generate EISA NMI interrupt
+ sb zero,0x461(t1) // clear EISA extended NMI status
+ sb t2,0x461(t1) //
+ lb zero,0x461(t1) // synchronize clear operatin
+ sb t3,0x70(t1) // restore EISA NMI interupt disable
+ sb t4,0x461(t1) // restore EISA exteneed NMI status
+ lb zero,0x461(t1) // synchronize restore operation
+ .set at
+ .set reorder
+
+10: //
+
+#endif
+#endif // #if !defined(_R98_)
+// End M001
+
+// S008 vvv
+//
+// Check ECC 1bit error flag.
+//
+
+ lw t0,HalpECC1bitDisableTime // get value of disable time
+ beq zero,t0,10f // if ne, check ecc 1bit
+ lw t1,HalpCurrentTimeIncrement // get current time increment
+ subu t0,t0,t1 // declement disable time
+ sw t0,HalpECC1bitDisableTime //
+ blez t0,5f // if lez, enable ecc 1bit
+ beq zero,zero,10f // not lez,
+
+5: sw zero,HalpECC1bitDisableTime // clear disable time
+ li t0,ECC_ERROR_COUNT_LIMIT // set new flag
+ sw t0,HalpECC1bitDisableFlag //
+ la t1,KSEG1_BASE+SIC_PHYSICAL_BASE+SIC_DATA_OFFSET+SIC_SET0_OFFSET
+ sw zero,0x0(t1) // enable ECC 1bit error
+ lw t0,HalpECC1bitScfrBuffer // check connect to SIC1
+ andi t0,SCFR_SIC_SET1_CONNECT //
+ bne t0,zero,10f //
+ la t1,KSEG1_BASE+SIC_PHYSICAL_BASE+SIC_DATA_OFFSET+SIC_SET1_OFFSET
+ sw zero,0x0(t1) // enable ECC 1bit error
+// S008 ^^^
+
+//
+// At each clock interrupt the next time increment is moved to the current
+// time increment to "pipeline" the update of the current increment at the
+// correct time. If the next interval count is nonzero, then the new time
+// increment is moved to the next time increment and the next interval count
+// register is loaded with the specified interval count minus one (i.e., ms).
+//
+
+10: lw t0,KdDebuggerEnabled // get address of debugger enable // S008
+ lw t1,HalpNextIntervalCount // get next interval count
+ lw t2,HalpNextTimeIncrement // get the next increment value
+ lbu t0,0(t0) // get debugger enable flag
+ lw t3,HalpNewTimeIncrement // get new new time increment value
+ lw ra,CiRa(sp) // restore return address
+ or t4,t1,t0 // set interval count or debugger?
+ sw t2,HalpCurrentTimeIncrement // set current increment value
+ bne zero,t4,20f // if ne, interval change or debugger
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+//
+// The interval count must be changed or the debugger is enabled.
+//
+
+20: sw zero,HalpNextIntervalCount // clear next interval count
+ beq zero,t1,30f // if eq, not interval count change
+ subu t1,t1,1 // compute millisecond interval count
+
+// Start M001
+ .set noreorder
+
+#if !defined(_R98_)
+#if defined(_DUO_)
+
+ sw t1,DMA_VIRTUAL_BASE + 0x1a8 // set next interval count
+
+#endif
+
+#if defined(_JAZZ_)
+
+ sw t1,DMA_VIRTUAL_BASE + 0x228 // set next interval count
+
+#endif
+# else // #if !defined(_R98_)
+
+ sw t1,KSEG1_BASE+PMC_PHYSICAL_BASE1+PMC_LOCAL_OFFSET+0x40(zero) // S004
+
+#endif // #if !defined(_R98_)
+
+ .set reorder
+// End M001
+
+ sw t3,HalpNextTimeIncrement // set next time increment value
+30: beq zero,t0,40f // if eq, debugger not enabled
+ jal KdPollBreakIn // check if breakin is requested
+ beq zero,v0,40f // if eq, no breakin requested
+ li a0,DBG_STATUS_CONTROL_C // break in and send
+ jal DbgBreakPointWithStatus // status to debugger
+40: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt0
+
+ SBTTL("System Clock Interrupt - Processor N")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the interval timer. Its function is to acknowledge the interrupt
+// and transfer control to the standard system routine to update the
+// execution time of the current thread and process.
+//
+// Arguments:
+//
+// a0 - Supplies a pointer to a trap frame. // S003
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpClockInterrupt1)
+
+#if !defined(_R98_)
+#if defined(_DUO_)
+
+ lw t0,DMA_VIRTUAL_BASE + 0x58 // acknowledge timer interrupt
+ move a0,s8 // set address of trap frame
+ j KeUpdateRunTime // update system time
+
+#endif
+#else // #if !defined(_R98_)
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+
+// S006 vvv
+ la t2,HalpChangeIntervalFlg // get change flag of timer interval
+ lbu t1,PbNumber(t1) // get processor number
+ add t2,t1,t2 // check flag
+ lb t1,0x0(t2) // get change flag of this CPU
+ beq t1,zero,10f // if eq, no change timer interval
+ sb zero,0x0(t2) // clear change flag of timer interval
+// S006 ^^^
+
+ lw t1,HalpChangeIntervalCount // get next interval count
+ sw t1,KSEG1_BASE+PMC_PHYSICAL_BASE1+PMC_LOCAL_OFFSET+0x40(zero) // S004
+
+// Start S003, S005
+//10: move a0,s8 // set address of trap frame
+10: lw t1,__imp_KeUpdateRunTime // update system runtime
+ j t1 //
+// End S003, S005
+
+#endif // #if !defined(_R98_)
+
+ .end HalpClockInterrupt1
+
+ SBTTL("Profile Clock Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by the
+// profile clock. Its function is to acknowledge the profile interrupt,
+// compute the next compare value, update the performance counter, and
+// transfer control to the standard system routine to process any active
+// profiles.
+//
+// Arguments:
+//
+// a0 - Supplies a pointer to a trap frame. // S003
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProfileInterrupt)
+
+ .set noreorder
+ .set noat
+// Start M001
+ mfc0 t0,count // get current count value
+ addu t1,zero,3 // set initial count value
+ mtc0 t1,count // set new count register value
+// End M001
+ .set at
+ .set reorder
+
+#if 0 // S007
+//#if defined(NT_UP)
+
+ la t1,HalpPerformanceCounter // get performance counter address
+
+//#else
+#endif
+
+ lw t1,KiPcr + PcPrcb(zero) // get current processor block address
+ la t2,HalpPerformanceCounter // get performance counter address
+ lbu t1,PbNumber(t1) // get processor number
+ sll t1,t1,3 // compute address of performance count
+ addu t1,t1,t2 //
+
+// #endif // S007
+
+ lw t2,LiLowPart(t1) // get low part of performance count
+ lw t3,LiHighPart(t1) // get high part of performance count
+ addu t2,t2,t0 // update low part of performance count
+ sw t2,LiLowPart(t1) // store low part of performance count
+ sltu t4,t2,t0 // generate carry into high part
+ addu t3,t3,t4 // update high part of performance count
+ sw t3,LiHighPart(t1) // store high part of performance count
+
+// move a0,s8 // set address of trap frame // S003
+ lw t4,__imp_KeProfileInterrupt // process profile interrupt // S005
+ j t4 // // S005
+
+ .end HalpProfileInterrupt
+
+ SBTTL("Read Count Register")
+//++
+//
+// ULONG
+// HalpReadCountRegister (
+// VOID
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register and
+// returns the value.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// Current value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpReadCountRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadCountRegister
+
+ SBTTL("Write Compare Register And Clear")
+//++
+//
+// ULONG
+// HalpWriteCompareRegisterAndClear (
+// IN ULONG Value
+// );
+//
+// Routine Description:
+//
+// This routine reads the current value of the count register, writes
+// the value of the compare register, clears the count register, and
+// returns the previous value of the count register.
+//
+// Arguments:
+//
+// Value - Supplies the value written to the compare register.
+//
+// Return Value:
+//
+// Previous value of the count register.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteCompareRegisterAndClear)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,count // get count register value
+ mtc0 a0,compare // set compare register value
+ li t0,7 // set lost cycle count
+ mtc0 t0,count // set count register to zero
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWriteCompareRegisterAndClear
diff --git a/private/ntos/nthals/halr98mp/mips/r98def.h b/private/ntos/nthals/halr98mp/mips/r98def.h
new file mode 100644
index 000000000..62e2aabaf
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98def.h
@@ -0,0 +1,471 @@
+#ident "@(#) NEC r98def.h 1.25 95/03/17 11:54:20"
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ r98def.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ for the r98.
+
+Author:
+
+
+Revision History:
+
+--*/
+
+/*
+ ***********************************************************************
+ *
+ * S001 6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ *
+ ***********************************************************************
+ *
+ * S002 7/5 T.Samezima
+ *
+ * Chg define miss
+ *
+ ***********************************************************************
+ *
+ * S003 7/5 T.Samezima
+ *
+ * Add define unknown counter buffer length
+ *
+ ***********************************************************************
+ *
+ * S004 7/5 T.Samezima
+ *
+ * Add define err pci and dma in iRSF
+ * define dummy single read addr
+ *
+ ***********************************************************************
+ *
+ * S005 7/12 T.Samezima
+ *
+ * Chg define miss and define change
+ *
+ ***********************************************************************
+ *
+ * S006 7/19 T.Samezima
+ *
+ * Add define PCI err interrupt vector
+ *
+ ***********************************************************************
+ *
+ * S007 7/22 T.Samezima
+ *
+ * Add define PMC Dummy single read address.
+ *
+ ***********************************************************************
+ *
+ * S008 7/23 T.Samezima
+ *
+ * Add define SIC set0/1 offset
+ * define value of enable EIF interrupt of SIC CKE0/1 register
+ *
+ ***********************************************************************
+ *
+ * S009 8/22 T.Samezima on SNES
+ *
+ * Chg RTC physical base
+ *
+ ***********************************************************************
+ *
+ * S00a 8/22 T.Samezima on SNES
+ *
+ * Chg PIO, FDC interrupt pending bit on iRSF
+ *
+ * S00B 8/29 N.Kugimoto
+ *
+ * Bug NVRAM disable logic.
+ *
+ * K00C 9/5 N.Kugimoto
+ * add PCI slot 0 addr
+ *
+ * K00D 94/9/22 N.Kugimoto
+ * -1 chg No Used!
+ *
+ * S00E 94/10/13 T.Samezima
+ * Add define EISA interrupt enable bit
+ * define all clock interrupt restart command on TCIR in PMC
+ *
+ * S00F 94/10/18 T.Samezima
+ * Add define interrupt enable bit for device only
+ *
+ * S010 94/11/21 T.Samezima
+ * Add correspond SIC3 H/W Bug on R98
+ * Chg Dummy read address change. because old address is
+ * break scsi script.
+ *
+ * S011 '94.12/06 T.Samezima
+ * Add define CKE0 disable mask. (Disable Single bit error mask on SIC)
+ * Chg CKE0 enable mask change. (Disable Single bit error mask on SIC)
+ * ERRMK enable mask change. (bit 17,22 is must be zero. )
+ *
+ * K00E 94/12/06 N.Kugimoto
+ * Add ESM NVRAM Area
+ *
+ * S012 94/12/08 T.Samezima
+ * Add Disable NMI
+ *
+ * S013 '95.01/08 T.Samezima
+ * Add Enable ECC 1bit error.
+ *
+ * S014 '95.01/13 T.Samezima
+ * Add Define Disable ECC 1bit error.
+ *
+ * S015 '95.03/13 T.Samezima
+ * Add Define LR4360 error.
+ *
+ */
+
+#ifndef _R98DEF_
+#define _R98DEF_
+
+//
+// define address map
+//
+#define PMC_PHYSICAL_BASE1 0x19900000 // Physical base of PMC registers1
+#define PMC_PHYSICAL_BASE2 0x19800000 // Physical base of PMC registers2
+#define PMC_LOCAL_OFFSET 0x80000
+
+#define IOB_PHYSICAL_BASE 0x18000000 // Physical base of IOB
+
+#define SIC_PHYSICAL_BASE 0x19000000 // Physical base of SIC registers
+#define SIC_ERR_OFFSET 0x2000 // Error registers offset of SIC
+#define SIC_DATA_OFFSET 0x3000 // Data registers offset of SIC
+#define SIC_SET0_OFFSET 0x0 // Offset SET0 of SIC // S008
+#define SIC_SET1_OFFSET 0x20000 // Offset SET1 of SIC // S008
+#define SIC_NO0_OFFSET 0x4000 // Offset No.0 of SIC
+#define SIC_NO1_OFFSET 0x8000 // Offset No.1 of SIC
+// Start S005,S008
+#define SIC_NO2_OFFSET (SIC_SET1_OFFSET+SIC_NO0_OFFSET) // Offset No.2 of SIC
+#define SIC_NO3_OFFSET (SIC_SET1_OFFSET+SIC_NO1_OFFSET) // Offset No.3 of SIC
+// End S005,S008
+
+#define LR_PHYSICAL_CMNBASE1 0x18c08000 // Physical base of LR4360 registers1 // S005
+#define LR_PHYSICAL_CMNBASE2 0x18c0a000 // Physical base of LR4360 registers2
+#define LR_PHYSICAL_PCI_INT_ACK_BASE 0x18caa000 // Physical base of LR4360 pci interrupt acknowledge
+#define LR_PHYSICAL_PCI_DEV_REG_BASE 0x18cbb000 // Physical base of LR4360 pci device registers
+
+// Bbus DMA
+#define LR_CHANNEL_BASE 0x18c08000 // LR4360 - Device Channel Register Base
+ // 0x18Cn0000 : n:channel number
+#define LR_CHANNEL_SHIFT 0x10 // LR4360 - channel shift bit
+
+#define SERIAL0_PHYSICAL_BASE 0x18c103f8 // physical base of serial port 0
+#define KEYBOARD_PHYSICAL_BASE 0x18c20060 // physical base of keyboard control
+#define RTCLOCK_PHYSICAL_BASE 0x18cc0071 // physical base of realtime clock // S005, S009
+
+#define NVRAM_PHYSICAL_BASE 0x18c70000 // physical base of nonvolatile RAM
+#define NVRAM_MEMORY_BASE (KSEG1_BASE + NVRAM_PHYSICAL_BASE)
+#define NVRAM_NMI_BASE (NVRAM_MEMORY_BASE + 0x1934)
+
+#define NVRAM_ESM_BASE NVRAM_MEMORY_BASE+1024*8 //Start of ESM Area K00E
+#define NVRAM_ESM_END NVRAM_MEMORY_BASE+1024*16-1 //End of ESM Area K00E
+
+#define MRC_PHYSICAL_BASE 0x18c80000 // physical base of MRC
+
+#define EISA_MEMORY_PHYSICAL_BASE 0xc0000000 // physical base of EISA memory
+#define EISA_CONTROL_PHYSICAL_BASE 0x18cc0000 // physical base of EISA control
+#define EISA_CONFIG_REGISTERS_MEMREGN 0x18ca8060 // MEMREG[] register
+
+#define PCI_MEMORY_PHYSICAL_BASE EISA_MEMORY_PHYSICAL_BASE // physical base of PCI memory
+
+#define PCI_MEMORY_SLOT1_PHYSICAL_BASE 0xc4000000 // PCI slot1 memory space
+#define PCI_MEMORY_SLOT2_PHYSICAL_BASE 0xc8000000 // PCI slot2 memory space
+#define PCI_MEMORY_SLOT3_PHYSICAL_BASE 0xcc000000 // PCI slot3 memory space
+
+#define PCI_CONTROL_SLOT1_PHYSICAL_BASE 0x18cd0000 // PCI slot1 I/O space
+#define PCI_CONTROL_SLOT2_PHYSICAL_BASE 0x18ce0000 // PCI slot2 I/O space
+#define PCI_CONTROL_SLOT3_PHYSICAL_BASE 0x18cf0000 // PCI slot2 I/O space
+#define PCI_LOGICAL_START_ADDRESS 0x00000000 // S001,K00D-1
+
+//
+// define IDT vector
+//
+
+#define INT0_LEVEL 3 // Define I/O interrupt Low level
+#define INT1_LEVEL 4 // Define I/O interrupt High level
+#define INT2_LEVEL 5 // Define I/O interrupt level
+#define TIMER_LEVEL 6 // Define Timer interrupt level
+#define IPI_LEVEL 7 // Define Ipi interrupt level
+#define EIF_LEVEL 8 // Define Eif interrupt level
+#define CLOCK_VECTOR 14 // Define Clock interrupt vector
+#define PROFILE_VECTOR 15 // Define Profile interrupt vector
+
+#define DEVICE_VECTORS 16 // Define starting builtin device and bus vectors
+#define EISA_DEVICE_VECTOR (2 + DEVICE_VECTORS) // Define Eisa interrupt vector
+#define KBMS_VECTOR (3 + DEVICE_VECTORS)
+#define SIO_VECTOR (4 + DEVICE_VECTORS)
+#define PIO_VECTOR (5 + DEVICE_VECTORS) // S005, S00a
+#define FDC_VECTOR (6 + DEVICE_VECTORS) // S005, S00a
+#define SCSI1_VECTOR (7 + DEVICE_VECTORS)
+#define SCSI0_VECTOR (8 + DEVICE_VECTORS)
+#define ETHER_VECTOR (9 + DEVICE_VECTORS)
+#define PCI_DEVICE_VECTOR (10+ DEVICE_VECTORS) // Define PCI interrupt vector
+#define LR_ERR_VECTOR (13+ DEVICE_VECTORS) // Define LR4360 err vector // S015
+#define PCI_ERR_VECTOR (14+ DEVICE_VECTORS) // Define PCI err vector // S006
+#define DMA_VECTOR (15+ DEVICE_VECTORS) // Define Dma interrupt vector
+
+#define EISA_VECTORS 32 // Define EISA Device interrupt vectors
+#define PCI_VECTORS 48 // Define Pci Device interrupt vectors
+
+#define MAXIMUM_BUILTIN_VECTOR ETHER_VECTOR // maximum builtin vector
+#define MAXIMUM_EISA_VECTORS (15 + EISA_VECTORS) // maximum EISA vector
+#define MAXIMUM_PCI_VECTORS (3 + PCI_VECTORS) // maximum PCI vector // S005
+
+//
+// define etc
+//
+
+#define MAXIMUM_CPU_NUMBER 3 // maximum cpu number
+// S003
+#define UNKNOWN_COUNT_BUF_LEN 64 // unknown interrupt counter buffer size
+
+/* Start S001 */
+//
+// define PMC registers value
+//
+
+#define PMC_CPU_SHIFT 0xc // S002
+
+#define MKR_DISABLE_ALL_INTERRUPT_HIGH 0x0
+#define MKR_DISABLE_ALL_INTERRUPT_LOW 0x0
+
+#define MKR_INT0_ENABLE_HIGH 0x0
+// S001
+#define MKR_INT0_ENABLE_LOW 0x00000fff
+#define MKR_INT1_ENABLE_HIGH 0x0
+#define MKR_INT1_ENABLE_LOW 0x00fff000
+#define MKR_INT2_ENABLE_HIGH 0x0
+#define MKR_INT2_ENABLE_LOW 0xff000000
+#define MKR_INT3_ENABLE_HIGH 0x00030000
+#define MKR_INT3_ENABLE_LOW 0x0
+#define MKR_INT4_ENABLE_HIGH 0x0000ffff
+#define MKR_INT4_ENABLE_LOW 0x0
+#define MKR_INT5_ENABLE_HIGH 0xff000000
+#define MKR_INT5_ENABLE_LOW 0x0
+
+// S00F vvv
+#define MKR_INT0_DEVICE_ENABLE_HIGH 0x0
+#define MKR_INT0_DEVICE_ENABLE_LOW 0x0
+#define MKR_INT1_DEVICE_ENABLE_HIGH 0x0
+#define MKR_INT1_DEVICE_ENABLE_LOW 0x00a88000
+#define MKR_INT2_DEVICE_ENABLE_HIGH 0x0
+#define MKR_INT2_DEVICE_ENABLE_LOW 0xaa000000
+// S00F ^^^
+
+#define IPR_EIF_BIT_NO 61
+#define IPR_EIF_BIT_HIGH 0x20000000
+#define IPR_EIF_BIT_LOW 0x0
+#define IPR_CLOCK_BIT_NO 49
+#define IPR_CLOCK_BIT_HIGH 0x00020000
+#define IPR_CLOCK_BIT_LOW 0x0
+#define IPR_PROFILE_BIT_NO 48
+#define IPR_PROFILE_BIT_HIGH 0x00010000
+#define IPR_PROFILE_BIT_LOW 0x0
+#define IPR_IPI0_BIT_NO 47
+#define IPR_IPI0_BIT_HIGH 0x00008000
+#define IPR_IPI0_BIT_LOW 0x0
+#define IPR_IPI1_BIT_NO 46
+#define IPR_IPI1_BIT_HIGH 0x00004000
+#define IPR_IPI1_BIT_LOW 0x0
+#define IPR_IPI2_BIT_NO 45
+#define IPR_IPI2_BIT_HIGH 0x00002000
+#define IPR_IPI2_BIT_LOW 0x0
+#define IPR_IPI3_BIT_NO 44
+#define IPR_IPI3_BIT_HIGH 0x00001000
+#define IPR_IPI3_BIT_LOW 0x0
+#define IPR_SIO_BIT_NO 31
+#define IPR_SIO_BIT_HIGH 0x0
+#define IPR_SIO_BIT_LOW 0x80000000
+#define IPR_FDC_PIO_BIT_NO 29
+#define IPR_FDC_PIO_BIT_HIGH 0x0
+#define IPR_FDC_PIO_BIT_LOW 0x20000000
+#define IPR_DMA_BIT_NO 27
+#define IPR_DMA_BIT_HIGH 0x0
+#define IPR_DMA_BIT_LOW 0x08000000
+#define IPR_KB_MS_BIT_NO 25
+#define IPR_KB_MS_BIT_HIGH 0x0
+#define IPR_KB_MS_BIT_LOW 0x02000000
+#define IPR_ETHER_BIT_NO 23
+#define IPR_ETHER_BIT_HIGH 0x0
+#define IPR_ETHER_BIT_LOW 0x00800000
+#define IPR_SCSI_BIT_NO 21
+#define IPR_SCSI_BIT_HIGH 0x0
+#define IPR_SCSI_BIT_LOW 0x00200000
+#define IPR_PCI_BIT_NO 19
+#define IPR_PCI_BIT_HIGH 0x0
+#define IPR_PCI_BIT_LOW 0x00080000
+#define IPR_EISA_BIT_NO 15
+#define IPR_EISA_BIT_HIGH 0x0
+#define IPR_EISA_BIT_LOW 0x00008000
+
+#define IntIR_REQUEST_IPI 0x00900000
+#define IntIR_CPU3_BIT 12
+#define IntIR_CODE_BIT 16
+
+#define TCIR_ALL_CLOCK_RESTART 0x000cf000 // S00E
+
+// S002
+#if defined(DISABLE_NMI)
+#define STSR_NMI_DISABLE 0x08080000 // S008
+#endif
+#define STSR_EIF_ENABLE 0x40400000
+#define STSR_NVWINH_ENABLE 0x04040000 // S005
+#define STSR_NVWINH_DISABLE 0x00040000 // S00B
+#define ERRMK_EIF_ENABLE 0xffbdfffe // S011
+
+//
+// Define the minimum and maximum system time increment values in 100ns units.
+//
+// original ntos/inc/duodef.h
+#define MAXIMUM_INCREMENT (10 * 1000 * 10)
+#define MINIMUM_INCREMENT (1 * 1000 * 10)
+
+//
+// Time increment in 1us units
+//
+#define CLOCK_INTERVAL (MAXIMUM_INCREMENT / 10)
+
+// original ntos/inc/mips.h
+#define DEFAULT_PROFILETIMER_COUNT 65000 // = 65 ms
+#define DEFAULT_PROFILETIMER_INTERVAL (500 * 10) // = 500 us (100ns units)
+#define MAXIMUM_PROFILETIMER_INTERVAL (65000 * 10) // = 65 ms (100ns units)
+#define MINIMUM_PROFILETIMER_INTERVAL (40 * 10) // = 40 us (100ns units)
+
+//
+// define IOB registers value
+//
+
+#define EIMR_DISABLE_ALL_EIF 0x0
+#define EIMR_ENABLE_ALL_EIF 0xffe00000 // S002
+#define IEMR_ENABLE_ALL_EIF 0xfffffe00 // S002
+
+#define SCFR_CPU0_CONNECT 0x8000
+#define SCFR_CPU1_CONNECT 0x4000
+#define SCFR_CPU2_CONNECT 0x2000
+#define SCFR_CPU3_CONNECT 0x1000
+#define SCFR_SIC_SET0_CONNECT 0x0800
+#define SCFR_SIC_SET1_CONNECT 0x0400
+
+#define AII_INIT_DATA 0x80008000
+
+// Start S008, S010
+//
+// define IOB registers value
+//
+#define CKE0_DISABLE_SBE 0xffffffff // S011, S013
+#define DPCM_ENABLE_MASK 0x1fffffff // S013
+#define DPCM_ECC1BIT_BIT 0x40000000 // S013, S014
+
+#define SECT_REWRITE_ENABLE 0x0000000f // S013
+
+#if defined(WORKAROUND_SIC3)
+//#define CKE0_DISABLE_SBE 0xf7ffffff // S011
+//#define CKE0_ENABLE_ALL_EIF 0xf040ff00 // S011 //R98TEMP SIC3 H/W Bug
+#define CKE0_ENABLE_ALL_EIF 0xf840ff00 // S011, S013
+#define CKE1_ENABLE_ALL_EIF 0xff700000 //R98TEMP SIC3 H/W Bug
+#else
+//#define CKE0_DISABLE_SBE 0xf7ffffff // S011
+#define CKE0_ENABLE_ALL_EIF 0xf8c0ff00 // S011, S013
+#define CKE1_ENABLE_ALL_EIF 0xfff00000
+#endif
+// End S008, S010
+
+//
+// Define NABus code
+//
+
+#define NACODE_SIO ((0x1f-IPR_SIO_BIT_NO) << 0x2)
+#define NACODE_FDC_PIO ((0x1f-IPR_FDC_PIO_BIT_NO) << 0x2)
+#define NACODE_DMA ((0x1f-IPR_DMA_BIT_NO) << 0x2)
+#define NACODE_KB_MS ((0x1f-IPR_KB_MS_BIT_NO) << 0x2)
+#define NACODE_ETHER ((0x1f-IPR_ETHER_BIT_NO) << 0x2)
+#define NACODE_SCSI ((0x1f-IPR_SCSI_BIT_NO) << 0x2)
+#define NACODE_PCI ((0x1f-IPR_PCI_BIT_NO) << 0x2)
+#define NACODE_EISA ((0x1f-IPR_EISA_BIT_NO) << 0x2)
+
+//
+// define LR4360 registers value
+//
+#define ERRS_ERROR_BIT 0x00008000 // S005
+#define iREN_DISABLE_ALL_INTERRUPT 0x0
+#define iREN_ENABLE_DMA_INTERRUPT 0x00020000
+#define iREN_ENABLE_LR_ERR_INTERRUPT 0x00010000 // S015
+#define iREN_ENABLE_PCI_INTERRUPT 0x00000200 // S006
+#define iREN_ENABLE_PCI_ERR_INTERRUPT 0x00400000 // S006
+#define iREN_ENABLE_EISA_INTERRUPT 0x00000002 // S00E
+#define iRRE_MASK 0x004203fe
+#define iRSF_CLEAR_INTERRUPT 0x000003fe // S005
+// Start S004
+#define iRSF_ERRPCI_BIT 0x00400000
+#define iRSF_DMA_BIT 0x00020000
+#define iRSF_LR_ERR_BIT 0x00010000 // S015
+// End S004
+#define iRSF_PCI_BIT 0x00000200
+#define iRSF_ETHER_BIT 0x00000100
+#define iRSF_SCSI0_BIT 0x00000080
+#define iRSF_SCSI1_BIT 0x00000040
+#define iRSF_FDC_BIT 0x00000020 // S005, S00a
+#define iRSF_PIO_BIT 0x00000010 // S005, S00a
+#define iRSF_SIO_BIT 0x0000008
+#define iRSF_KBMS_BIT 0x00000004
+#define iRSF_EISA_BIT 0x00000002
+#define LR_iRSF_REG_iNSF_SHIFT 0x11
+#define LR4360PTSZ4K 0x1
+#define LR4360PTSZ8K 0x2
+#define LR4360PTSZ16K 0x4
+#define LR4360PTSZ32K 0x8
+#define LR4360PTSZSHIFT 0xc
+#define LR_DMA_MODE_NORMAL 0x00
+
+//
+// Define dummy single read address
+//
+
+#define SIO_DUMMY_READ_ADDR KSEG1_BASE+0x018c103f1
+#define PIO_DUMMY_READ_ADDR KSEG1_BASE+0x018c103f1
+#define FDC_DUMMY_READ_ADDR KSEG1_BASE+0x018c103f1
+#define DMA_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000
+#define KBMS_DUMMY_READ_ADDR KSEG1_BASE+0x018c103f1
+#define ETHER_DUMMY_READ_ADDR KSEG1_BASE+0x018600000
+#define SCSI0_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000 // S010
+#define SCSI1_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000 // S010
+#define PCI_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000
+#define EISA_DUMMY_READ_ADDR KSEG1_BASE+0x018cc0023
+#define EIF_DUMMY_READ_ADDR KSEG1_BASE+0x018000218 // S005
+
+#define PMC_DUMMY_READ_ADDR KSEG1_BASE+0x018c0b000 // S007
+
+//
+// Define cause register bit offset
+//
+
+#define CAUSE_INT_PEND_BIT 0x8
+
+//
+// Define cause register read macro
+//
+
+#define READ_CAUSE_REGISTER(reg) \
+ .set noreorder; \
+ .set noat; \
+ mfc0 reg,cause; \
+ nop; \
+ nop; \
+ .set at; \
+ .set reorder;
+
+/* End S001 */
+
+#endif _R98DEF_
diff --git a/private/ntos/nthals/halr98mp/mips/r98dspt.c b/private/ntos/nthals/halr98mp/mips/r98dspt.c
new file mode 100644
index 000000000..3c89949ec
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98dspt.c
@@ -0,0 +1,704 @@
+#ident "@(#) NEC r98dspt.c 1.14 95/03/17 11:55:28"
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ r98dspt.c
+
+Abstract:
+
+ This module implements the interrupt dispatch routines for R98
+
+Author:
+
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+/*
+ ***********************************************************************
+ *
+ * S001 7/7 T.Samezima
+ *
+ * Chg all alteration Int0-2 dispach routine
+ *
+ * Del move some define in r98def.h
+ *
+ ***********************************************************************
+ *
+ * S002 8/22 T.Samezima on SNES
+ *
+ * Add Buffer for register save when unknown interrupt
+ * Count up at loop counter
+ *
+ * Chg Modify loop logic
+ *
+ ***********************************************************************
+ *
+ * S003 9/30 T.Samezima
+ *
+ * Bug define miss on Int1 dispatch table.
+ *
+ * S004 '94.10/14 T.Samezima
+ * Chg Display IPR and iRSF register on bugcheck
+ *
+ * S005 '94.11/8 T.Samezima
+ * Del Delete call of KeBugCheck. because of wrong interrupt ocure
+ * of LR4360 bug
+ *
+ * S006 '94.11/21 T.Samezima
+ * Chg Change size of dummy read
+ *
+ * S007 '94.12/28 T.Samezima
+ * Add interrupt clear Broadcast in Unknown interrupt
+ *
+ * S009 '95.01/11 T.Samezima
+ * Add Dummy single read on EIF interrupt.
+ *
+ * S00a '95.03/13 T.Samezima
+ * Del PIO interrupt check.
+ * Add LR4360 error check.
+ * check dummy single read
+ *
+ */
+
+#include "halp.h"
+//#include "halmips.h"
+#include "bugcodes.h"
+
+/* Start S001 */
+//
+// Define table in use interrupt dispatch routine
+//
+#define INT2_DATA_TABLE_SIZE 5
+#define INT1_DATA_TABLE_SIZE 6
+
+enum _INT_DISP_TABLE {
+ iRSF_BIT=0,
+ IPR_BIT,
+ IDT_VECTOR,
+ DUMMY_READ_ADDR,
+ DUMMY_READ_SIZE,
+ NA_CODE
+ };
+
+typedef struct _DISPATCH_DATA_TABLE {
+ ULONG IrsfMask;
+ ULONG IprMask;
+ ULONG IdtVector;
+ ULONG DummyReadAddr;
+ ULONG DummyReadSize;
+ ULONG NaCode;
+} DISPATCH_DATA_TABLE, *PDISPATCH_DATA_TABLE;
+
+DISPATCH_DATA_TABLE HalpInt2DispatchDataTable[] = {
+ {iRSF_KBMS_BIT, IPR_KB_MS_BIT_LOW, KBMS_VECTOR,
+ KBMS_DUMMY_READ_ADDR, 1, NACODE_KB_MS},
+// {iRSF_PIO_BIT, IPR_FDC_PIO_BIT_LOW, PIO_VECTOR,
+// PIO_DUMMY_READ_ADDR, 1, NACODE_FDC_PIO}, // S00a
+ {iRSF_LR_ERR_BIT,IPR_DMA_BIT_LOW, LR_ERR_VECTOR,
+ DMA_DUMMY_READ_ADDR, 4, NACODE_DMA}, // S00a
+ {iRSF_FDC_BIT, IPR_FDC_PIO_BIT_LOW, FDC_VECTOR,
+ FDC_DUMMY_READ_ADDR, 1, NACODE_FDC_PIO}, // S00a
+ {iRSF_SIO_BIT, IPR_SIO_BIT_LOW, SIO_VECTOR,
+ SIO_DUMMY_READ_ADDR, 1, NACODE_SIO},
+ {iRSF_DMA_BIT, IPR_DMA_BIT_LOW, DMA_VECTOR,
+ DMA_DUMMY_READ_ADDR, 4, NACODE_DMA}
+};
+
+DISPATCH_DATA_TABLE HalpInt1DispatchDataTable[] = {
+ {iRSF_EISA_BIT, IPR_EISA_BIT_LOW, EISA_DEVICE_VECTOR,
+ EISA_DUMMY_READ_ADDR, 1, NACODE_EISA},
+ {iRSF_SCSI1_BIT, IPR_SCSI_BIT_LOW, SCSI1_VECTOR,
+ SCSI1_DUMMY_READ_ADDR, 4, NACODE_SCSI}, // S006
+ {iRSF_ETHER_BIT, IPR_ETHER_BIT_LOW, ETHER_VECTOR,
+ ETHER_DUMMY_READ_ADDR, 2, NACODE_ETHER},
+ {iRSF_PCI_BIT, IPR_PCI_BIT_LOW, PCI_DEVICE_VECTOR,
+ PCI_DUMMY_READ_ADDR, 4, NACODE_PCI}, // S003
+ {iRSF_SCSI0_BIT, IPR_SCSI_BIT_LOW, SCSI0_VECTOR,
+ SCSI0_DUMMY_READ_ADDR, 4, NACODE_SCSI}, // S006, S00a
+ {iRSF_ERRPCI_BIT,IPR_PCI_BIT_LOW, PCI_ERR_VECTOR,
+ PCI_DUMMY_READ_ADDR, 4, NACODE_PCI} // S003
+};
+
+// DISPATCH_DATA_TABLE HalpInt0DispatchDataTable[];
+
+enum _INT_TABLE_DATA{
+ TABLE_SIZE=0,
+ MKR_MASK,
+ INT_LEVEL
+ };
+
+ULONG HalpIntData[3][3] = {
+ {0, MKR_INT0_ENABLE_LOW, INT0_LEVEL},
+ {INT1_DATA_TABLE_SIZE, MKR_INT1_ENABLE_LOW, INT1_LEVEL},
+ {INT2_DATA_TABLE_SIZE, MKR_INT2_ENABLE_LOW, INT2_LEVEL}
+};
+
+//
+// Define pointer of interrupt arbitration
+//
+ULONG HalpInt2ArbitrationPoint = 0;
+ULONG HalpInt1ArbitrationPoint = 0;
+ULONG HalpInt0ArbitrationPoint = 0;
+/* End S001 */
+
+#if DBG
+//
+// Register buffer
+//
+
+ULONG HalpUnknownCause = 0; // S002
+ULONG HalpUnknownIPRUpper = 0;
+ULONG HalpUnknownIPRLower = 0;
+ULONG HalpUnknownMKRUpper = 0;
+ULONG HalpUnknownMKRLower = 0;
+ULONG HalpUnknowniRRE = 0; // S002
+ULONG HalpUnknowniREN = 0; // S002
+ULONG HalpUnknowniRSF = 0; // S002
+ULONG HalpUnknownIprUpperBuf = 0; // S002
+ULONG HalpUnknownIprLowerBuf = 0; // S002
+ULONG HalpIoIntLoopCounter; // S002
+
+#endif
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+typedef BOOLEAN (*PTIMER_DISPATCH)(
+ ULONG TrapFrame
+ );
+
+
+VOID
+HalpUnknownInterrupt(
+ IN ULONG IprUpper,
+ IN ULONG IprLower
+ )
+/*++
+
+Routine Description:
+
+ This function is reset of unknown interrupt.
+
+Argments:
+
+ IprUpper (a0) - Supplies upper 32bit of result of "IPR & MKR" in present INT level.
+
+ IprLower (a1) - Supplies lower 32bit of result of "IPR & MKR" in present INT level.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG i;
+
+// Start S002
+#if DBG
+ HalpUnknownCause = HalpGetCause();
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &HalpUnknownIPRUpper,
+ &HalpUnknownIPRLower
+ );
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &HalpUnknownMKRUpper,
+ &HalpUnknownMKRLower
+ );
+
+ HalpUnknownIprUpperBuf = IprUpper;
+ HalpUnknownIprLowerBuf = IprLower;
+
+ HalpUnknowniRRE = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE );
+ HalpUnknowniREN = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iREN );
+ HalpUnknowniRSF = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRSF );
+
+#if 0 // S005 vvv
+ KeBugCheckEx(INTERRUPT_EXCEPTION_NOT_HANDLED,
+ IprUpper,
+ IprLower,
+ HalpUnknowniRSF,
+ HalpUnknowniRRE
+ ); // S004
+#endif // S005 ^^^
+
+#endif
+// End S002
+
+ //
+ // clear interrupt pending bit
+ //
+
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &IprUpper,
+ &IprLower
+ );
+ // S007 vvv
+ //
+ // issue broadcast of unknown interrupt clear
+ //
+
+ if( IprLower != 0 ) {
+ PDISPATCH_DATA_TABLE dataTable;
+ ULONG tableSize;
+
+ if( IprLower & MKR_INT2_ENABLE_LOW ) {
+ dataTable = HalpInt2DispatchDataTable;
+ tableSize = INT2_DATA_TABLE_SIZE;
+ } else if( IprLower & MKR_INT1_ENABLE_LOW ) {
+ dataTable = HalpInt1DispatchDataTable;
+ tableSize = INT1_DATA_TABLE_SIZE;
+ }
+
+ for( i=0; i<tableSize; i++) {
+ if( i == 1 )
+ continue;
+ if( (IprLower & dataTable[i].IprMask) != 0 ) {
+ WRITE_REGISTER_ULONG( (ULONG)( &(IOB_CONTROL)->AIMR ),
+ dataTable[i].NaCode );
+ }
+ }
+ }
+ // S007 ^^^
+
+ //
+ // count up unknown interrupt
+ //
+
+ for ( i=0 ; i < 32 ; i++ ) {
+ HalpUnknownInterruptCount[i] += (IprUpper >> i) & 1;
+ HalpUnknownInterruptCount[i+32] += (IprLower >> i) & 1;
+ }
+}
+
+VOID
+HalpEifDispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an eif interrupt.
+
+Argments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG pmcRegisterUpperPart;
+ ULONG pmcRegisterLowerPart;
+ ULONG pmcIPRRegisterUpperPart;
+ ULONG pmcIPRRegisterLowerPart;
+ ULONG zero=0;
+ ULONG buffer;
+
+ //
+ // Get interrpt pending bit
+ //
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+Loop:
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ pmcRegisterUpperPart &= pmcIPRRegisterUpperPart;
+
+ //
+ // Check eif interrupt
+ //
+
+ buffer=pmcRegisterUpperPart & IPR_EIF_BIT_HIGH;
+
+ if( buffer ){
+ //
+ // issue dummy single read
+ //
+
+ READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long );
+ READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long );
+
+ HalpHandleEif();
+
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &buffer,
+ &zero );
+ } else {
+ HalpUnknownInterrupt( pmcIPRRegisterUpperPart & MKR_INT5_ENABLE_HIGH,
+ 0 );
+ }
+
+ //
+ // Check new interrupt
+ //
+
+ do {
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+
+ if( pmcIPRRegisterUpperPart & MKR_INT5_ENABLE_HIGH ){
+ goto Loop;
+ }
+ } while( HalpGetCause() & (1 << (CAUSE_INT_PEND_BIT + EIF_LEVEL - 1)) );
+
+ return;
+}
+
+
+VOID
+HalpTimerScDispatch(
+ IN ULONG TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an timer interrupt.
+
+Argments:
+
+ TrapFrame - Supplies a pointer to a trap frame.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG pmcRegisterUpperPart;
+ ULONG pmcRegisterLowerPart;
+ ULONG pmcIPRRegisterUpperPart;
+ ULONG pmcIPRRegisterLowerPart;
+ ULONG zero=0;
+ ULONG buffer;
+
+ //
+ // read IPR register
+ //
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+
+ //
+ // read MKR register
+ //
+
+Loop:
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ pmcRegisterUpperPart &= pmcIPRRegisterUpperPart;
+
+ //
+ // check profile and clock interrupt
+ //
+
+ buffer=pmcRegisterUpperPart & IPR_PROFILE_BIT_HIGH;
+
+ if( buffer ){
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &buffer,
+ &zero );
+ WRITE_REGISTER_ULONG( (ULONG)( &(PMC_CONTROL1)->TOVCT2.Long), 0x0 ); // S002
+
+ ((PTIMER_DISPATCH) PCR->InterruptRoutine[PROFILE_VECTOR])(TrapFrame);
+ } else {
+ buffer=pmcRegisterUpperPart & IPR_CLOCK_BIT_HIGH;
+
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &buffer,
+ &zero );
+ WRITE_REGISTER_ULONG( (ULONG)( &(PMC_CONTROL1)->TOVCT1.Long), 0x0 ); // S002
+
+ ((PTIMER_DISPATCH) PCR->InterruptRoutine[CLOCK_VECTOR])(TrapFrame);
+ }
+
+ //
+ // Check new interrupt
+ //
+
+ do {
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+
+ if( pmcIPRRegisterUpperPart & MKR_INT3_ENABLE_HIGH ){
+ goto Loop;
+ }
+ } while( HalpGetCause() & (1 << (CAUSE_INT_PEND_BIT + TIMER_LEVEL - 1)) );
+
+ return;
+}
+
+
+/* Start S001 */
+VOID
+HalpIoIntDispatch(
+ IN PDISPATCH_DATA_TABLE DataTable,
+ IN OUT PULONG ArbitrationPoint,
+ IN ULONG IntNo
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an int0, int1, and int2 interrupt.
+
+Argments:
+
+ DataTable - Supplies a table useing judge interrupt factor.
+
+ ArbitrationPoint - Supplies a start point of checking interrupt.
+
+ IntNo - Supplies interrupt level.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG pmcRegisterUpperPart;
+ ULONG pmcRegisterLowerPart;
+ ULONG pmcIPRRegisterUpperPart;
+ ULONG pmcIPRRegisterLowerPart;
+ ULONG buffer;
+ ULONG counter;
+ ULONG position;
+ ULONG zero=0;
+ ULONG flag;
+
+ // Start S002
+#if DBG
+ HalpIoIntLoopCounter = 0;
+#endif
+ // End S002
+
+ //
+ // Get interrpt pending bit
+ //
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+//Loop: // S002
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ pmcRegisterLowerPart &= pmcIPRRegisterLowerPart;
+
+Loop: // S002
+ buffer = READ_REGISTER_ULONG( (ULONG)(&(LR_CONTROL2)->iRSF) );
+
+ (*ArbitrationPoint)++;
+
+ flag = FALSE;
+
+ for(counter = 0; counter < HalpIntData[IntNo][TABLE_SIZE] ; counter++){
+
+ position = ( (*ArbitrationPoint + counter) % HalpIntData[IntNo][TABLE_SIZE]);
+
+ //
+ // check interrupt
+ //
+
+ if( ((buffer & DataTable[position].IrsfMask) == 0) ||
+ ((pmcRegisterLowerPart & DataTable[position].IprMask) == 0) ) {
+ continue;
+ }
+
+ flag = TRUE;
+
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &zero,
+ &(DataTable[position].IprMask)
+ );
+ ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[DataTable[position].IdtVector])(
+ PCR->InterruptRoutine[DataTable[position].IdtVector]
+ );
+
+ // Start S002
+ //
+ // Clear Interrupt pending bit in iRSF register
+ //
+
+ WRITE_REGISTER_ULONG( (ULONG)(&(LR_CONTROL2)->iRSF),
+ DataTable[position].IrsfMask );
+ // End S002
+
+ //
+ // issue dummy single read
+ //
+
+ switch(DataTable[position].DummyReadSize){
+ case 1:
+ READ_REGISTER_UCHAR( DataTable[position].DummyReadAddr );
+ READ_REGISTER_UCHAR( DataTable[position].DummyReadAddr );
+ break;
+ case 2:
+ READ_REGISTER_USHORT( DataTable[position].DummyReadAddr );
+ READ_REGISTER_USHORT( DataTable[position].DummyReadAddr );
+ break;
+ case 4:
+ READ_REGISTER_ULONG( DataTable[position].DummyReadAddr );
+ READ_REGISTER_ULONG( DataTable[position].DummyReadAddr );
+ break;
+ }
+
+ //
+ // issue broadcast of interrupt clear
+ //
+
+ WRITE_REGISTER_ULONG( (ULONG)( &(IOB_CONTROL)->AIMR ),
+ DataTable[position].NaCode );
+
+ break; // S006
+ }
+
+ if (flag == FALSE){
+ HalpUnknownInterrupt( 0,
+ pmcIPRRegisterLowerPart & HalpIntData[IntNo][MKR_MASK]
+ );
+ }
+
+ //
+ // check new interrupt
+ //
+
+ do {
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+
+ // Start S002
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ pmcRegisterLowerPart &= pmcIPRRegisterLowerPart;
+ // end S002
+
+ if( pmcIPRRegisterLowerPart & HalpIntData[IntNo][MKR_MASK] ){
+ // Start S002
+#if DBG
+ HalpIoIntLoopCounter++;
+#endif
+ // End S002
+ goto Loop;
+ }
+ } while(HalpGetCause() & (1 << CAUSE_INT_PEND_BIT+HalpIntData[IntNo][INT_LEVEL]-1));
+
+ return;
+}
+
+
+VOID
+HalpInt2Dispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an int2 interrupt.
+
+Argments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ HalpIoIntDispatch( HalpInt2DispatchDataTable,
+ &HalpInt2ArbitrationPoint,
+ 2
+ );
+}
+
+
+VOID
+HalpInt1Dispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an int1 interrupt.
+
+Argments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ HalpIoIntDispatch( HalpInt1DispatchDataTable,
+ &HalpInt1ArbitrationPoint,
+ 1
+ );
+}
+
+
+VOID
+HalpInt0Dispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an int0 interrupt.
+
+Argments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ HalpIoIntDispatch( (PDISPATCH_DATA_TABLE)NULL,
+ &HalpInt0ArbitrationPoint,
+ 0
+ );
+}
+/* End S001 */
diff --git a/private/ntos/nthals/halr98mp/mips/r98eif.c b/private/ntos/nthals/halr98mp/mips/r98eif.c
new file mode 100644
index 000000000..98aefd3d1
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98eif.c
@@ -0,0 +1,801 @@
+#ident "@(#) NEC r98eif.c 1.16 95/03/17 11:56:21"
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ r98eif.c
+
+Abstract:
+
+ This module implements the Eif interrupt service routine for R98
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ ***********************************************************************
+ *
+ * S001 6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***********************************************************************
+ *
+ * S002 7/5 T.Samezima
+ *
+ * Chg CPU No set miss
+ *
+ ***********************************************************************
+ *
+ * S003 7/22 T.Samezima
+ *
+ * Add give the dummy read after IOB and SIC register read
+ * for PMC3 bug
+ *
+ ***********************************************************************
+ *
+ * S004 8/23 T.Samezima
+ *
+ * Chg Condition change
+ *
+ ***********************************************************************
+ *
+ * S005 8/24 T.Samezima
+ *
+ * Chg Change a form of display on eif status
+ * Define buffer name
+ *
+ ***********************************************************************
+ *
+ * S006 9/22 T.Samezima
+ *
+ * Add Execution owner flag
+ * Lower the Irql level to TIMER_LEVEL. Because KdPrint
+ * use to inter processor interrupt.
+ *
+ * Chg buffer size
+ *
+ ***********************************************************************
+ *
+ * S007 9/27 T.Samezima
+ *
+ * Chg Arg miss
+ *
+ ***********************************************************************
+ *
+ * S008 9/27 T.Samezima
+ *
+ * Chg Init value
+ *
+ * S009 10/25 T.Samezima
+ * Add Variable of KeBugCheckEx()
+ *
+ * S00a 11/29 T.Samezima
+ * Add Enable _R98DBG_
+ *
+ * S00b 12/07 T.Samezima
+ * Chg print format.
+ *
+ * S00c 12/24 T.Samezima
+ * Add ESM logic.
+ * Del move EIFR_REGISTER define to r98reg.h
+ *
+ * S00d '95.01/11 T.Samezima
+ * Add Disable EIF interrupt in wait loop.
+ *
+ * S00e '95.01/13 T.Samezima
+ * Add Wait for all processers in wait loop.
+ *
+ * S00f '95.01/16-25 T.Samezima
+ * Add Check ECC 1bit flag.
+ *
+ * S010 '95.03/10 T.Samezima
+ * Add NMI switch check.
+ *
+ * S011 '95.03/14 T.Samezima
+ * Add HalpLRErrorInterrupt()
+ *
+ */
+
+#include "halp.h"
+/* Start S001 */
+#include "bugcodes.h"
+#include "eisa.h"
+#include "stdio.h"
+/* End S001 */
+
+#define _R98DBG_ 1 // S00a
+
+// Start S005
+
+//
+// define buffer name
+//
+
+enum _EIF_BUFFER {
+ PMC0_ERR=0, // 0
+ PMC0_AERR,
+ PMC1_ERR,
+ PMC1_AERR,
+ PMC2_ERR,
+ PMC2_AERR, // 5
+ PMC3_ERR,
+ PMC3_AERR,
+ PMC_EADRH,
+ PMC_EADRL,
+ IOB_IERR, // 10
+ IOB_AMAH,
+ IOB_AMAL,
+ IOB_ANAH,
+ IOB_ANAL,
+ IOB_MPER, // 15
+ IOB_EIFR,
+ SIC_N0_EIF0,
+ SIC_N1_EIF0,
+ SIC_N0_EIF1,
+ SIC_N1_EIF1, // 20
+ SIC_N0_STS1,
+ SIC_N1_STS1,
+ SIC_N0_STS2,
+ SIC_N1_STS2,
+ SIC_N0_DSRG, // 25
+ SIC_N1_DSRG,
+ SIC_N2_EIF0,
+ SIC_N3_EIF0,
+ SIC_N2_EIF1,
+ SIC_N3_EIF1, // 30
+ SIC_N2_STS1,
+ SIC_N3_STS1,
+ SIC_N2_STS2,
+ SIC_N3_STS2,
+ SIC_N2_DSRG, // 35
+ SIC_N3_DSRG,
+ LR_ERRS,
+ LR_PEAR,
+ LR_AEAR,
+ EISA_NMI, // 40
+ MAXMUM_EIF_BUFFER
+};
+
+#if 0 // S00c
+typedef struct _EIFR_REGISTER {
+ ULONG Reserved : 21;
+ ULONG MPDISCN : 1;
+ ULONG IOBERR : 1;
+ ULONG Reserved2 : 1;
+ ULONG EISANMI : 1;
+ ULONG LRERR : 1;
+ ULONG SIC1ERR : 1;
+ ULONG SIC0ERR : 1;
+ ULONG PMC3ERR : 1;
+ ULONG PMC2ERR : 1;
+ ULONG PMC1ERR : 1;
+ ULONG PMC0ERR : 1;
+} EIFR_REGISTER, *PEIFR_REGISTER;
+#endif
+
+// End S005
+
+//
+// define buffer size
+//
+
+#define REG_BUFFER_SIZE MAXMUM_EIF_BUFFER // S005
+
+//
+// buffer
+//
+
+ULONG HalpEifRegisterBuffer[REG_BUFFER_SIZE];
+
+// Start S006
+//
+// Owner flag
+//
+
+volatile ULONG EifOwnFlg=0;
+// End S006
+
+volatile ULONG CpuCount=0; // S00e
+volatile ULONG EccOccurFlag[4]={0,0,0,0}; // S00f
+
+// S010 vvv
+#define NMI_BUFFER_SIZE 32
+
+volatile ULONG HalpNMIFlag=0;
+ULONG HalpNMIBuf[NMI_BUFFER_SIZE*4];
+// S010 ^^^
+
+// S011 vvv
+ULONG HalpLRErrorFlag=0;
+
+BOOLEAN
+HalpLRErrorInterrupt(
+ VOID
+ )
+{
+ //
+ // LR4360 error flag set.
+ //
+ HalpLRErrorFlag=1;
+
+ //
+ // Issue EIF interrupt.
+ //
+ WRITE_REGISTER_ULONG( 0xb9980100, 0x0082f000 );
+
+ return TRUE;
+}
+// S011 ^^^
+
+
+VOID
+HalpHandleEif(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine manage the eif interrupt
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ UCHAR charBuffer; // S001
+ ULONG buffer;
+ ULONG errsBuffer;
+ UCHAR messageBuffer[REG_BUFFER_SIZE*12+16]; // S006
+ ULONG counter;
+ UCHAR EisaPort;
+ ULONG port;
+
+ ULONG cpuNo; // S006
+ ULONG EifFlg=0; // S006, S007
+ KIRQL oldIrql; // S006
+ ULONG i; // S00f
+
+ // Start S005
+#if defined(_R98DBG_)
+ PEIFR_REGISTER eifrbuf;
+#endif
+ // End S005
+
+ //
+ // Acquire eif interrupt spin lock.
+ //
+
+ KiAcquireSpinLock(&HalpEifInterruptLock);
+
+ // Start S006
+ //
+ // Get CPU Number.
+ //
+
+ cpuNo=(PCR->Prcb)->Number;
+
+ if(EifOwnFlg == 0) {
+// CpuCount=**((PULONG *)(&KeNumberProcessors)); // S00e, S00f
+ EifOwnFlg = 1;
+ EifFlg = 1;
+ }
+
+// CpuCount--; // S00e, S00f
+
+ KiReleaseSpinLock(&HalpEifInterruptLock);
+
+ if(EifFlg == 0) {
+//#ifdef DBG
+ WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKRR.Long,
+ 63-IPR_EIF_BIT_NO ); // S00d
+ KeRaiseIrql(TIMER_LEVEL, &oldIrql);
+ while( EifOwnFlg == 1 );
+ KeLowerIrql(oldIrql);
+ WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKSR.Long,
+ 63-IPR_EIF_BIT_NO ); // S00d
+//#else
+// while( EifOwnFlg == 1 );
+//#endif
+ EccOccurFlag[cpuNo]=0; // S00f
+ return;
+ }
+
+ // S00c vvv
+ buffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long );
+
+ if( (HalpNMIFlag == 0) && (HalpLRErrorFlag == 0) && // S010, S011
+ ((((PEIFR_REGISTER)&buffer)->SIC0ERR == 1) ||
+ (((PEIFR_REGISTER)&buffer)->SIC1ERR == 1)) ){
+ buffer = HalpEccError(buffer);
+ if(buffer == 1){
+// while( CpuCount != 0 ); // S00e
+ // S00f vvv
+ for( i=0; i<4; i++) {
+ EccOccurFlag[i]=1;
+ }
+ EccOccurFlag[cpuNo]=0;
+ // S00f ^^^
+ EifOwnFlg = 0;
+ return;
+ }
+ }
+ // S00c ^^^
+ // S00f vvv
+ else if( (HalpNMIFlag == 0) && (HalpLRErrorFlag == 0) &&
+ ((buffer & 0xff600000) == 0) && (EccOccurFlag[cpuNo] == 1) ){ // S010, S011
+ EccOccurFlag[cpuNo]=0;
+ EifOwnFlg = 0;
+ return;
+ }
+ // S00f ^^^
+
+ // S010 vvv
+ if( HalpNMIFlag == 0 ) {
+ HalDisplayString("\nEIF interrupt status: "); // S005
+#ifdef DBG
+ sprintf( (char *)messageBuffer, "Exe CPU=No.%1d\n", cpuNo ); // S007
+#else
+ sprintf( (char *)messageBuffer, "\n" ); // S007
+#endif
+ HalDisplayString( (char *)messageBuffer );
+ } else {
+ HalDisplayString("\nNMI occur: \n");
+ }
+ // S010 ^^^
+ // End S006
+
+ //
+ // Check LR4360 status.
+ //
+
+ errsBuffer = READ_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS );
+
+ if( (errsBuffer & ERRS_ERROR_BIT) != 0 ) {
+ WRITE_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS,
+ ERRS_ERROR_BIT );
+ }
+
+ buffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->SCFR.Long );
+ IOB_DUMMY_READ; // S003
+
+ //
+ // get register value on ERR, AERR, EADRH and EADRL registers of PMC
+ //
+
+ for(counter=0 ; counter<REG_BUFFER_SIZE ; counter++) {
+ HalpEifRegisterBuffer[counter]=0;
+ }
+
+ if( (buffer & SCFR_CPU0_CONNECT) == 0 ) { // S004
+ /* Start S001 */
+ HalpEifRegisterBuffer[PMC0_ERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 0<<PMC_CPU_SHIFT ) )->ERR.Long
+ );
+ HalpEifRegisterBuffer[PMC0_AERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 0<<PMC_CPU_SHIFT ) )->AERR.Long
+ );
+ /* End S001 */
+ }
+
+ if( (buffer & SCFR_CPU1_CONNECT) == 0 ) { // S004
+ /* Start S001,S002 */
+ HalpEifRegisterBuffer[PMC1_ERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 1<<PMC_CPU_SHIFT ) )->ERR.Long
+ );
+ HalpEifRegisterBuffer[PMC1_AERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 1<<PMC_CPU_SHIFT ) )->AERR.Long
+ );
+ /* End S001,S002 */
+ }
+
+ if( (buffer & SCFR_CPU2_CONNECT) == 0 ) { // S004
+ /* Start S001,S002 */
+ HalpEifRegisterBuffer[PMC2_ERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 2<<PMC_CPU_SHIFT ) )->ERR.Long
+ );
+ HalpEifRegisterBuffer[PMC2_AERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 2<<PMC_CPU_SHIFT ) )->AERR.Long
+ );
+ /* End S001,S002 */
+ }
+
+ if( (buffer & SCFR_CPU3_CONNECT) == 0 ) { // S004
+ /* Start S001,S002 */
+ HalpEifRegisterBuffer[PMC3_ERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 3<<PMC_CPU_SHIFT ) )->ERR.Long
+ );
+ HalpEifRegisterBuffer[PMC3_AERR] = READ_REGISTER_ULONG( // S005
+ &( PMC_GLOBAL_CONTROL1_OR( 3<<PMC_CPU_SHIFT ) )->AERR.Long
+ );
+ /* End S001,S002 */
+ }
+
+ /* Start S001 */
+ HalpEifRegisterBuffer[PMC_EADRH] = READ_REGISTER_ULONG( // S005
+ &( PMC_CONTROL2 )->EADRH.Long
+ );
+ HalpEifRegisterBuffer[PMC_EADRL] = READ_REGISTER_ULONG( // S005
+ &( PMC_CONTROL2 )->EADRL.Long
+ );
+ /* End S001 */
+
+ //
+ // get register value on IERR, AMAH, AMAL, ANAH, ANAL,MPER and EIFR
+ // registers of IOB.
+ //
+
+ HalpEifRegisterBuffer[IOB_IERR] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->IERR.Long,
+ );
+ IOB_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[IOB_AMAH] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->AMAH.Long,
+ );
+ IOB_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[IOB_AMAL] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->AMAL.Long,
+ );
+ IOB_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[IOB_ANAH] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->ANAH.Long,
+ );
+ IOB_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[IOB_ANAL] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->ANAL.Long,
+ );
+ IOB_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[IOB_MPER] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->MPER.Long,
+ );
+ IOB_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[IOB_EIFR] = READ_REGISTER_ULONG( // S005
+ &( IOB_CONTROL )->EIFR.Long,
+ );
+ IOB_DUMMY_READ; // S003
+
+ //
+ // get register value on EIF0, EIF1, STS1, STS2 and DSRG registers of SIC.
+ //
+
+ if( (buffer & SCFR_SIC_SET0_CONNECT) == 0 ) { // S004
+ /* Start S001 */
+ HalpEifRegisterBuffer[SIC_N0_EIF0] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->EIF0.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N1_EIF0] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO1_OFFSET ) )->EIF0.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N0_EIF1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->EIF1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N1_EIF1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO1_OFFSET ) )->EIF1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N0_STS1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->STS1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N1_STS1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO1_OFFSET ) )->STS1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N0_STS2] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->STS2.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N1_STS2] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO1_OFFSET ) )->STS2.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N0_DSRG] = READ_REGISTER_ULONG( // S005
+ &( SIC_DATA_CONTROL_OR( SIC_NO0_OFFSET ) )->DSRG.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N1_DSRG] = READ_REGISTER_ULONG( // S005
+ &( SIC_DATA_CONTROL_OR( SIC_NO1_OFFSET ) )->DSRG.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ /* End S001 */
+ }
+
+ if( (buffer & SCFR_SIC_SET1_CONNECT) == 0 ) { // S004
+ /* Start S001 */
+ HalpEifRegisterBuffer[SIC_N2_EIF0] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->EIF0.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N3_EIF0] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO3_OFFSET ) )->EIF0.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N2_EIF1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->EIF1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N3_EIF1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO3_OFFSET ) )->EIF1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N2_STS1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->STS1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N3_STS1] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO3_OFFSET ) )->STS1.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N2_STS2] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->STS2.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N3_STS2] = READ_REGISTER_ULONG( // S005
+ &( SIC_ERR_CONTROL_OR( SIC_NO3_OFFSET ) )->STS2.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N2_DSRG] = READ_REGISTER_ULONG( // S005
+ &( SIC_DATA_CONTROL_OR( SIC_NO2_OFFSET ) )->DSRG.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ HalpEifRegisterBuffer[SIC_N3_DSRG] = READ_REGISTER_ULONG( // S005
+ &( SIC_DATA_CONTROL_OR( SIC_NO3_OFFSET ) )->DSRG.Long,
+ );
+ SIC_DUMMY_READ; // S003
+ /* End S001 */
+ }
+
+ //
+ // get register value on ERRS, PEAR and AEAR registers of LR4360.
+ //
+
+ HalpEifRegisterBuffer[LR_ERRS] = errsBuffer; // S005
+ HalpEifRegisterBuffer[LR_PEAR] = READ_REGISTER_ULONG( // S005
+ &( LR_PCI_DEV_REG_CONTROL )->PEAR,
+ );
+ HalpEifRegisterBuffer[LR_AEAR] = READ_REGISTER_ULONG( // S005
+ &( LR_PCI_DEV_REG_CONTROL )->AEAR,
+ );
+
+ //
+ // Display EISA Nmi status.
+ //
+
+ charBuffer = READ_REGISTER_UCHAR( &((PEISA_CONTROL)HalpEisaControlBase )->NmiStatus);
+ HalpEifRegisterBuffer[EISA_NMI] = charBuffer << 24; // S001, S005
+
+ charBuffer = READ_REGISTER_UCHAR(
+ &( (PEISA_CONTROL)HalpEisaControlBase )->ExtendedNmiResetControl
+ );
+ HalpEifRegisterBuffer[EISA_NMI] |= charBuffer << 16; // S001, S005
+
+ //
+ // Look for any Eisa expansion board. See if it asserted NMI.
+ //
+
+ for (EisaPort = 0; EisaPort <= 0xf; EisaPort++) {
+ port = (EisaPort << 12) + 0xC80;
+ port += (ULONG) HalpEisaControlBase;
+ WRITE_PORT_UCHAR ((PUCHAR) port, 0xff);
+ charBuffer = READ_PORT_UCHAR ((PUCHAR) port);
+
+ if ((charBuffer & 0x80) == 0) {
+ //
+ // Found valid Eisa board, Check to see if it's
+ // if IOCHKERR is asserted.
+ //
+ charBuffer = READ_PORT_UCHAR ((PUCHAR) port+4);
+ if (charBuffer & 0x2) {
+ HalpEifRegisterBuffer[EISA_NMI] |= EisaPort; // S005
+ }
+ }
+ }
+
+#ifdef DBG // R98TEMP
+ KdPrint(("HAL: EIF Interrupt\n"));
+#endif // R98TEMP
+
+ // Start S005
+ for( counter=0 ; counter<REG_BUFFER_SIZE ; counter++) {
+ sprintf( (char *)messageBuffer, "0x%08lX,", HalpEifRegisterBuffer[counter] );
+ HalDisplayString( (char *)messageBuffer );
+#ifdef DBG // R98TEMP
+ KdPrint(( (char *)messageBuffer ));
+#endif // R98TEMP
+ if( (counter % 7) == 6 ) {
+ sprintf( (char *)messageBuffer, "\n");
+ HalDisplayString( (char *)messageBuffer );
+#ifdef DBG // R98TEMP
+ KdPrint(( (char *)messageBuffer ));
+#endif // R98TEMP
+ }
+ }
+
+#if defined(_R98DBG_)
+ sprintf( (char *)messageBuffer, "\n");
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+
+ HalpChangePanicFlag( 16, 0x01, 0x10); // S00c
+
+ eifrbuf = (PEIFR_REGISTER)(&(HalpEifRegisterBuffer[IOB_EIFR]));
+
+ if( eifrbuf->PMC0ERR == 1){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from PMC0: ERR=0x%08lX, AERR=0x%08lX\n"
+ " EADRH=0x%08lX, EADRL=0x%08lX\n",
+ HalpEifRegisterBuffer[PMC0_ERR],
+ HalpEifRegisterBuffer[PMC0_AERR],
+ HalpEifRegisterBuffer[PMC_EADRH],
+ HalpEifRegisterBuffer[PMC_EADRL]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( eifrbuf->PMC1ERR == 1){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from PMC1: ERR=0x%08lX, AERR=0x%08lX\n"
+ " EADRH=0x%08lX, EADRL=0x%08lX\n",
+ HalpEifRegisterBuffer[PMC1_ERR],
+ HalpEifRegisterBuffer[PMC1_AERR],
+ HalpEifRegisterBuffer[PMC_EADRH],
+ HalpEifRegisterBuffer[PMC_EADRL]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( eifrbuf->PMC2ERR == 1){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from PMC2: ERR=0x%08lX, AERR=0x%08lX\n"
+ " EADRH=0x%08lX, EADRL=0x%08lX\n",
+ HalpEifRegisterBuffer[PMC2_ERR],
+ HalpEifRegisterBuffer[PMC2_AERR],
+ HalpEifRegisterBuffer[PMC_EADRH],
+ HalpEifRegisterBuffer[PMC_EADRL]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( eifrbuf->PMC3ERR == 1){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from PMC3: ERR=0x%08lX, AERR=0x%08lX\n"
+ " EADRH=0x%08lX, EADRL=0x%08lX\n",
+ HalpEifRegisterBuffer[PMC3_ERR],
+ HalpEifRegisterBuffer[PMC3_AERR],
+ HalpEifRegisterBuffer[PMC_EADRH],
+ HalpEifRegisterBuffer[PMC_EADRL]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( eifrbuf->SIC0ERR == 1){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from SIC SET0\n"
+ " No0 Status: EIF0=0x%08lX, EIF1=0x%08lX, DSRG=0x%08lX\n"
+ " STS1=0x%08lX, STS2=0x%08lX\n"
+ " No1 Status: EIF0=0x%08lX, EIF1=0x%08lX, DSRG=0x%08lX\n"
+ " STS1=0x%08lX, STS2=0x%08lX\n",
+ HalpEifRegisterBuffer[SIC_N0_EIF0],
+ HalpEifRegisterBuffer[SIC_N0_EIF1],
+ HalpEifRegisterBuffer[SIC_N0_DSRG],
+ HalpEifRegisterBuffer[SIC_N0_STS1],
+ HalpEifRegisterBuffer[SIC_N0_STS2],
+ HalpEifRegisterBuffer[SIC_N1_EIF0],
+ HalpEifRegisterBuffer[SIC_N1_EIF1],
+ HalpEifRegisterBuffer[SIC_N1_DSRG],
+ HalpEifRegisterBuffer[SIC_N1_STS1],
+ HalpEifRegisterBuffer[SIC_N1_STS2]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( eifrbuf->SIC1ERR == 1){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from SIC SET1\n"
+ " No2 Status: EIF0=0x%08lX, EIF1=0x%08lX, DSRG=0x%08lX\n"
+ " STS1=0x%08lX, STS2=0x%08lX\n"
+ " No3 Status: EIF0=0x%08lX, EIF1=0x%08lX, DSRG=0x%08lX\n"
+ " STS1=0x%08lX, STS2=0x%08lX\n",
+ HalpEifRegisterBuffer[SIC_N2_EIF0],
+ HalpEifRegisterBuffer[SIC_N2_EIF1],
+ HalpEifRegisterBuffer[SIC_N2_DSRG],
+ HalpEifRegisterBuffer[SIC_N2_STS1],
+ HalpEifRegisterBuffer[SIC_N2_STS2],
+ HalpEifRegisterBuffer[SIC_N3_EIF0],
+ HalpEifRegisterBuffer[SIC_N3_EIF1],
+ HalpEifRegisterBuffer[SIC_N3_DSRG],
+ HalpEifRegisterBuffer[SIC_N3_STS1],
+ HalpEifRegisterBuffer[SIC_N3_STS2]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( HalpLRErrorFlag == 1 ){ // S011
+ sprintf( (char *)messageBuffer,
+ "LR4360 Error Acknowledge Interrupt:\n" // S011
+ " ERRS=0x%08lX, PEAR=0x%08lX, AEAR=0x%08lX\n", // S011
+ HalpEifRegisterBuffer[LR_ERRS],
+ HalpEifRegisterBuffer[LR_PEAR],
+ HalpEifRegisterBuffer[LR_AEAR]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( (eifrbuf->IOBERR == 1) || (eifrbuf->MPDISCN == 1) ){
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from IOB: IERR=0x%08lX, AMAH=0x%08lX, AMAL=0x%08lX\n"
+ " ANAH=0x%08lX, ANAL=0x%08lX, EIFR=0x%08lX, MPER=0x%08lX\n",
+ HalpEifRegisterBuffer[IOB_IERR],
+ HalpEifRegisterBuffer[IOB_AMAH],
+ HalpEifRegisterBuffer[IOB_AMAL],
+ HalpEifRegisterBuffer[IOB_ANAH],
+ HalpEifRegisterBuffer[IOB_ANAL],
+ HalpEifRegisterBuffer[IOB_EIFR],
+ HalpEifRegisterBuffer[IOB_MPER]
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if( eifrbuf->EISANMI == 1){
+
+ sprintf( (char *)messageBuffer,
+ "EIF Interrupt from EISA NMI: NmiStatus=0x%02lX\n"
+ " ExtendedNmiResetControl=0x%02lX, Port=%d\n",
+ ((HalpEifRegisterBuffer[EISA_NMI] >> 24) & 0xff),
+ ((HalpEifRegisterBuffer[EISA_NMI] >> 16) & 0xff),
+ (HalpEifRegisterBuffer[EISA_NMI] & 0xff)
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ // S010 vvv
+ if( (HalpNMIFlag & 0x0000008) != 0 ) {
+ sprintf( (char *)messageBuffer,
+ "NMI from MRC\n"
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+ // S010 ^^^
+#endif
+ // End S005
+
+ EifOwnFlg == 0;
+
+ KeBugCheckEx(NMI_HARDWARE_FAILURE,
+ HalpEifRegisterBuffer[IOB_EIFR],
+ HalpNMIFlag, // S010
+ HalpLRErrorFlag ? HalpEifRegisterBuffer[LR_ERRS] : 0, // S011
+ 0
+ ); // S009
+}
diff --git a/private/ntos/nthals/halr98mp/mips/r98esm.c b/private/ntos/nthals/halr98mp/mips/r98esm.c
new file mode 100644
index 000000000..bf98bf092
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98esm.c
@@ -0,0 +1,1026 @@
+#ident "@(#) NEC r98esm.c 1.1 95/02/20 17:21:21"
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ r98esm.c
+
+Abstract:
+
+ This module implements the ESM service routine for R98
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+/*
+ *
+ * S001 '95.01/13 T.Samezima
+ * Add disable ECC 1bit error for a few second.
+ * Chg ECC 1bit error interrupt clear logic.
+ *
+ * S002 '95.01/14 T.Samezima
+ * Chg Entirely change logic to display String into nvram
+ * Entirely change logic to ECC error log into nvram
+ *
+ * S003 '95.01/15-24 T.Samezima
+ * Add wait from ECC 1bit error disable to enable.
+ * disable ECC 1bit error with SIC set 1 and SIC set 2.
+ * rewrite data on ECC 1bit error.
+ *
+ * S004 '95.01/26 T.Samezima
+ * Add wait to clear of register.
+ *
+ */
+
+#include "halp.h"
+#include "esmnvram.h"
+#include "bugcodes.h"
+#include "stdio.h"
+
+//
+// define offset.
+//
+#define NVRAM_STATE_FLG_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag)
+#define NVRAM_MAGIC_NO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system.magic)
+#define ECC_1BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_1biterr)
+#define ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err.offset_latest)
+#define ECC_2BIT_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_2biterr)
+#define ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err.offset_latest)
+#define SYSTEM_ERROR_LOG_INFO_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_systemerr)
+#define SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET (USHORT)&(((pNVRAM_HEADER)0)->system_err.offset_latest)
+
+
+#define STOP_ERR_LOG_AREA_HEADER_SIZE (USHORT)&(((pSTOP_ERR_REC)0)->err_description)
+#define TIME_STAMP_SIZE 14
+
+//
+// define value
+//
+#define NVRAM_VALID 3
+#define NVRAM_MAGIC 0xff651026
+#define ECC_LOG_VALID_FLG 1
+
+#define SIC_ECC_1BIT_ERROR 1
+#define SIC_ECC_2BIT_ERROR 2
+#define SIC_OTHER_ERROR 0
+
+#define SDCR_SET0_ADDR 0xb9100030
+#define SDCR_SET1_ADDR 0xb9120030
+
+#define STRING_BUFFER_SIZE 512
+
+#define ECC_1BIT_ERROR_DISABLE_TIME 5*1000*1000*10
+
+//
+// Define global variable. This variable use in display string into nvram.
+//
+ULONG HalpNvramValid=FALSE;
+ULONG CallCountOfInitDisplay=0;
+USHORT ErrBufferLatest;
+USHORT ErrBufferArea;
+USHORT ErrBufferStart;
+USHORT ErrBufferEnd;
+USHORT ErrBufferCurrent;
+ULONG HalpPanicFlg=0;
+UCHAR HalpNvramStringBuffer[STRING_BUFFER_SIZE];
+ULONG HalpNvramStringBufferCounter=0;
+
+LONG HalpECC1bitDisableFlag=1; // S001
+LONG HalpECC1bitDisableTime=0; // S003
+ULONG HalpECC1bitScfrBuffer=0; // S003
+
+UCHAR KernelPanicMessage[]="*** STOP: 0x"; // S002
+
+//
+// Define macro
+//
+
+#define GET_PADDR(addr,sts2,SicSet) { \
+ (addr) = ( ( ((PSTS2_REGISTER)&(sts2) )->COL0_9 << 4 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->LOW0_9 << 14 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->SIMN << 24 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->COL10 << 25 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->LOW10 << 26 ) \
+ + ( ((PSTS2_REGISTER)&(sts2) )->ARE << 27 ) \
+ + ( (SicSet) << 30 ) ); \
+}
+
+#define GET_TIME(Buffer) { \
+ TIME_FIELDS timeBuffer; \
+ WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKRR.Long, \
+ 63-IPR_EIF_BIT_NO ); \
+ HalQueryRealTimeClock( &timeBuffer ); \
+ WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKSR.Long, \
+ 63-IPR_EIF_BIT_NO ); \
+ sprintf( (Buffer), \
+ "%04d%02d%02d%02d%02d%02d", \
+ timeBuffer.Year, \
+ timeBuffer.Month, \
+ timeBuffer.Day, \
+ timeBuffer.Hour, \
+ timeBuffer.Minute, \
+ timeBuffer.Second \
+ ); \
+}
+
+// S002, S003 vvv
+#define NOTIFY_ECC1BIT(Scfr) { \
+ ULONG buffer; \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO0_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer &= DPCM_ENABLE_MASK; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET0_OFFSET)))->DPCM.Long,buffer); \
+ if( ((Scfr) & SCFR_SIC_SET1_CONNECT) == 0 ) { \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO2_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer &= DPCM_ENABLE_MASK; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET1_OFFSET)))->DPCM.Long, \
+ buffer); \
+ } \
+}
+
+#define DONT_NOTIFY_ECC1BIT(Scfr) { \
+ ULONG buffer; \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO0_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer |= DPCM_ECC1BIT_BIT; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET0_OFFSET)))->DPCM.Long, \
+ buffer); \
+ if( ((Scfr) & SCFR_SIC_SET1_CONNECT) == 0 ) { \
+ buffer=READ_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_NO2_OFFSET)))->DPCM.Long); \
+ SIC_DUMMY_READ; \
+ buffer |= DPCM_ECC1BIT_BIT; \
+ WRITE_REGISTER_ULONG(&(SIC_DATA_CONTROL_OR((SIC_SET1_OFFSET)))->DPCM.Long, \
+ buffer); \
+ } \
+}
+// S002, S003 ^^^
+
+
+ULONG
+HalpEccError(
+ IN ULONG EifrRegister
+ )
+
+/*++
+
+Routine Description:
+
+ This routine check ecc error and error log put in NVRAM.
+
+Arguments:
+
+ EifrRegister - EIFR register value in IOB.
+
+Return Value:
+
+ return value is the following error occured.
+ 1: ecc 1bit error.
+ 2: ecc 2bit error.
+ 0: other error.
+
+--*/
+
+{
+ ULONG returnValue;
+ ULONG sicSet;
+ ULONG sicOffset;
+ USHORT infoOffset;
+ USHORT writeOffset;
+ ULONG eif0Buffer;
+ ULONG sts2Buffer;
+ ULONG sdlmBuffer;
+ ULONG buffer; // S001
+ ULONG i; // S002
+ ULONG errAddr; // S002
+ UCHAR dataBuf[36];
+ UCHAR infoBuf[24];
+ UCHAR tempBuf[24];
+
+ HalpECC1bitScfrBuffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->SCFR.Long );
+ IOB_DUMMY_READ;
+
+ //
+ // check interrupt from where.
+ //
+
+ if ( ((PEIFR_REGISTER)&EifrRegister)->SIC1ERR == 1){
+ sicSet = 1;
+ eif0Buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( SIC_NO2_OFFSET ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+ if(eif0Buffer & 0x000000c0){
+ sicOffset = SIC_NO2_OFFSET;
+ } else {
+ sicOffset = SIC_NO3_OFFSET;
+ }
+ }else{
+ sicSet = 0;
+ eif0Buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( SIC_NO0_OFFSET ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+ if(eif0Buffer & 0x000000c0){
+ sicOffset = SIC_NO0_OFFSET;
+ } else {
+ sicOffset = SIC_NO1_OFFSET;
+ }
+ }
+
+ //
+ // read diagnosis registers.
+ //
+
+ eif0Buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+ sts2Buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( sicOffset ) )->STS2.Long );
+ SIC_DUMMY_READ;
+ sdlmBuffer = READ_REGISTER_ULONG(
+ &( SIC_DATA_CONTROL_OR( sicOffset ) )->SDLM.Long );
+ SIC_DUMMY_READ;
+
+ //
+ // Check ECC 1bit or 2bit err
+ //
+
+ if( (eif0Buffer & 0x08000000) &&
+ ((eif0Buffer & 0xf0000000) == 0) &&
+ ((EifrRegister & 0xf3600000) == 0) ){
+ returnValue= SIC_ECC_1BIT_ERROR;
+ infoOffset=ECC_1BIT_ERROR_LOG_INFO_OFFSET;
+ } else if (eif0Buffer & 0x00000040){
+ returnValue= SIC_ECC_2BIT_ERROR;
+ infoOffset=ECC_2BIT_ERROR_LOG_INFO_OFFSET;
+ } else {
+ return(SIC_OTHER_ERROR);
+ }
+
+ HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, dataBuf );
+ HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, tempBuf );
+
+ // S002 vvv
+ switch(returnValue) {
+
+ case SIC_ECC_2BIT_ERROR:
+ if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){
+
+ HalNvramRead( (ULONG)infoOffset, 20, infoBuf);
+
+ ((pECC2_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG;
+
+ GET_PADDR( (((pECC2_ERR_REC)dataBuf)->err_address), sts2Buffer, sicSet);
+
+ GET_TIME(tempBuf);
+ RtlMoveMemory( (PVOID)( ((pECC2_ERR_REC)dataBuf)->when_happened ),
+ (PVOID)tempBuf,
+ TIME_STAMP_SIZE
+ );
+
+ ((pECC2_ERR_REC)dataBuf)->syndrome = sdlmBuffer;
+
+ ((pECC2_ERR_REC)dataBuf)->specified_group =
+ (UCHAR)( ((PSTS2_REGISTER)&sts2Buffer)->ARE + sicSet * 4);
+
+ ((pECC2_ERR_REC)dataBuf)->specified_simm =
+ (UCHAR)( ((PSTS2_REGISTER)&sts2Buffer)->SIMN );
+
+ writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_latest
+ +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec;
+
+ if( writeOffset >= ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr
+ +((pECC2_ERR_AREA_INFO)infoBuf)->size_rec
+ *((pECC2_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ writeOffset = ((pECC2_ERR_AREA_INFO)infoBuf)->offset_2biterr;
+ }
+
+ HalNvramWrite( (ULONG)writeOffset,
+ sizeof(ECC2_ERR_REC),
+ (PVOID)dataBuf);
+
+ HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_LATEST_OFFSET,
+ sizeof(USHORT),
+ (PVOID)&writeOffset);
+ }
+ break;
+
+
+ case SIC_ECC_1BIT_ERROR:
+
+ if( ((dataBuf[0] & 0xff) == NVRAM_VALID) && ( *(PULONG)tempBuf == NVRAM_MAGIC ) ){
+
+ HalNvramRead( (ULONG)infoOffset, 20, infoBuf);
+
+ //
+ // Disable and clear ECC 1bit error.
+ //
+
+ DONT_NOTIFY_ECC1BIT(HalpECC1bitScfrBuffer); // S003
+
+ if(sicSet == 0){
+ WRITE_REGISTER_ULONG( SDCR_SET0_ADDR, 0x0 );
+ } else {
+ WRITE_REGISTER_ULONG( SDCR_SET1_ADDR, 0x0 );
+ }
+
+ do {
+ buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+ } while ( (buffer & 0x08000000) != 0 );
+
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long,
+ EifrRegister & 0x0c000000 );
+
+ //
+ // Check New error or Old error.
+ //
+
+ GET_PADDR( errAddr, sts2Buffer, sicSet);
+ HalpReadAndWritePhysicalAddr( errAddr ); // S003
+
+ for( i=0; i<((pECC1_ERR_AREA_INFO)infoBuf)->num_rec; i++) {
+ HalNvramRead( (ULONG)( ((pECC1_ERR_AREA_INFO)infoBuf)->size_rec * i
+ +((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr),
+ sizeof(ECC1_ERR_REC),
+ (PVOID)dataBuf);
+ if ( (errAddr == ((pECC1_ERR_REC)dataBuf)->err_address) &&
+ ( (((pECC1_ERR_REC)dataBuf)->record_flag & 0x1) != 0) ) {
+ break;
+ }
+ }
+
+ if( i != ((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ break;
+ }
+
+ //
+ // wait 20 us.
+ //
+
+ KeStallExecutionProcessor(20);
+
+ //
+ // Enable ECC 1bit error.
+ //
+
+ NOTIFY_ECC1BIT(HalpECC1bitScfrBuffer); // S003
+
+ //
+ // Check ECC 1bit error.
+ //
+
+ HalpReadPhysicalAddr( errAddr );
+
+ buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+
+ if( (buffer & 0x08000000) == 0 ) {
+ break;
+ }
+
+ //
+ // ECC 1bit error occur again.
+ //
+
+ ((pECC1_ERR_REC)dataBuf)->record_flag = ECC_LOG_VALID_FLG;
+
+ ((pECC1_ERR_REC)dataBuf)->err_address = errAddr;
+
+ GET_TIME(tempBuf);
+ RtlMoveMemory( (PVOID)( ((pECC1_ERR_REC)dataBuf)->when_happened ),
+ (PVOID)tempBuf,
+ TIME_STAMP_SIZE
+ );
+
+ ((pECC1_ERR_REC)dataBuf)->syndrome = sdlmBuffer;
+
+ ((pECC1_ERR_REC)dataBuf)->specified_group =
+ (UCHAR)( ((PSTS2_REGISTER)&sts2Buffer)->ARE + sicSet * 4);
+
+ ((pECC1_ERR_REC)dataBuf)->specified_simm =
+ (UCHAR)( ((PSTS2_REGISTER)&sts2Buffer)->SIMN );
+
+ writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_latest
+ +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec;
+
+ if( writeOffset >= ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr
+ +((pECC1_ERR_AREA_INFO)infoBuf)->size_rec
+ *((pECC1_ERR_AREA_INFO)infoBuf)->num_rec ) {
+ writeOffset = ((pECC1_ERR_AREA_INFO)infoBuf)->offset_1biterr;
+ }
+
+ HalNvramWrite( (ULONG)writeOffset,
+ sizeof(ECC1_ERR_REC),
+ (PVOID)dataBuf);
+ HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_LATEST_OFFSET,
+ sizeof(USHORT),
+ (PVOID)&writeOffset);
+ }
+
+ break;
+ }
+
+ if(returnValue == SIC_ECC_1BIT_ERROR) {
+
+ DONT_NOTIFY_ECC1BIT(HalpECC1bitScfrBuffer); // S003
+
+ if(sicSet == 0){
+ WRITE_REGISTER_ULONG( SDCR_SET0_ADDR, 0x0 );
+ } else {
+ WRITE_REGISTER_ULONG( SDCR_SET1_ADDR, 0x0 );
+ }
+
+ do {
+ eif0Buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+ } while ( (eif0Buffer & 0x08000000) != 0 );
+
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long,
+ EifrRegister & 0x0c000000 );
+ // S004 vvv
+ do {
+ eif0Buffer = READ_REGISTER_ULONG(
+ &( SIC_ERR_CONTROL_OR( sicOffset ) )->EIF0.Long );
+ SIC_DUMMY_READ;
+ buffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long );
+ IOB_DUMMY_READ;
+ } while ( ((buffer & 0x0c000000) != 0) && ((eif0Buffer & 0xf8000000) == 0) );
+ // S004 ^^^
+
+ if(HalpECC1bitDisableFlag > 0) {
+ HalpECC1bitDisableFlag--;
+ if(HalpECC1bitDisableFlag > 0) {
+ NOTIFY_ECC1BIT(HalpECC1bitScfrBuffer); // S003
+ }
+ // S003 vvv
+ else {
+ HalpECC1bitDisableTime = ECC_1BIT_ERROR_DISABLE_TIME;
+ HalpECC1bitDisableFlag = 0;
+ }
+ // S003 ^^^
+ }
+ }
+ // S002 ^^^
+
+ return(returnValue);
+}
+
+
+VOID
+HalpInitDisplayStringIntoNvram(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is initialize variable of use when write display data in
+ HalDisplayString into NVRAM.
+
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ SYSTEM_ERR_AREA_INFO infoBuf;
+ UCHAR recordFlg;
+ UCHAR buf[8];
+ UCHAR buf2[8];
+
+ CallCountOfInitDisplay++;
+ if(CallCountOfInitDisplay == 1){
+
+ //
+ // Check NVRAM status
+ //
+
+ HalNvramRead( NVRAM_STATE_FLG_OFFSET, 1, buf );
+ HalNvramRead( NVRAM_MAGIC_NO_OFFSET, 4, buf2 );
+
+ if( ((buf[0] & 0xff) != NVRAM_VALID) || (*(PULONG)buf2 != NVRAM_MAGIC) ){
+ HalpNvramValid=FALSE;
+ return;
+ }
+
+ HalpNvramValid=TRUE;
+
+ //
+ // Get log area infomation.
+ //
+
+ HalNvramRead(SYSTEM_ERROR_LOG_INFO_OFFSET,
+ sizeof(SYSTEM_ERR_AREA_INFO),
+ &infoBuf);
+
+ ErrBufferLatest = infoBuf.offset_latest;
+
+ HalNvramRead( infoBuf.offset_latest, 1, &recordFlg);
+
+ //
+ // Check current record flg.
+ //
+
+ if( (recordFlg & 0x01) == 1 ) {
+ infoBuf.offset_latest += infoBuf.size_rec;
+ if( infoBuf.offset_latest >=
+ infoBuf.offset_systemerr + (infoBuf.size_rec * infoBuf.num_rec) ){
+ infoBuf.offset_latest = infoBuf.offset_systemerr;
+ }
+ HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET,
+ 2,
+ &infoBuf.offset_latest);
+ }
+
+ //
+ // initialize variable. this value use log area access.
+ //
+
+ ErrBufferArea = infoBuf.offset_latest;
+ ErrBufferStart = infoBuf.offset_latest + STOP_ERR_LOG_AREA_HEADER_SIZE;
+ ErrBufferEnd = infoBuf.offset_latest + infoBuf.size_rec-1;
+ ErrBufferCurrent = ErrBufferStart;
+
+ //
+ // status flg set.
+ //
+
+ HalpPanicFlg = 0;
+
+ recordFlg = 0x11;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+
+ //
+ // buffer initialize.
+ //
+
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else {
+
+ //
+ // start Panic log.
+ //
+
+ HalpChangePanicFlag( 1, 1, 0);
+ }
+}
+
+VOID
+HalpSetInitDisplayTimeStamp(
+ VOID
+ )
+{
+ UCHAR buf[24];
+
+ //
+ // Set time stamp on initialize display.
+ //
+
+ if(HalpNvramValid == TRUE) {
+ GET_TIME(buf);
+ HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf );
+ }
+}
+
+
+VOID
+HalpSuccessOsStartUp(
+ VOID
+ )
+{
+ UCHAR recordFlg;
+
+ if(HalpNvramValid == TRUE) {
+ recordFlg = 0;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+ HalNvramWrite( SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET, 2, &ErrBufferLatest );
+ }
+}
+
+
+VOID
+HalpChangePanicFlag(
+ IN ULONG NewPanicFlg,
+ IN UCHAR NewLogFlg,
+ IN UCHAR CurrentLogFlgMask
+ )
+{
+ UCHAR recordFlg;
+ UCHAR buf[24];
+
+ if( (HalpNvramValid == FALSE) || (NewPanicFlg <= HalpPanicFlg) ) {
+ return;
+ }
+
+ HalNvramWrite(SYSTEM_ERROR_LOG_INFO_LATEST_OFFSET,
+ 2,
+ &ErrBufferArea);
+
+ //
+ // initialize currernt buffer address
+ //
+
+ ErrBufferCurrent = ErrBufferStart;
+
+ //
+ // set panic flag
+ //
+
+ HalNvramRead( ErrBufferArea, 1, &recordFlg );
+ recordFlg = (recordFlg & CurrentLogFlgMask) | NewLogFlg;
+ HalNvramWrite( ErrBufferArea, 1, &recordFlg );
+
+ GET_TIME(buf);
+ HalNvramWrite( ErrBufferArea+1, TIME_STAMP_SIZE, buf );
+
+ //
+ // set new flag of panic level
+ //
+
+ HalpPanicFlg = NewPanicFlg;
+
+ //
+ // initialize log buffer.
+ //
+
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+}
+
+
+// S002 vvv
+VOID
+HalStringIntoBuffer(
+ IN UCHAR Character
+ )
+{
+ if( (HalpNvramStringBufferCounter + 1) < STRING_BUFFER_SIZE - 1 ) {
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=Character;
+ }
+}
+
+
+VOID
+HalStringIntoBufferStart(
+ IN ULONG Column,
+ IN ULONG Row
+ )
+{
+ ULONG i;
+
+ //
+ // Initialize buffer
+ //
+
+ for(i=0; i<STRING_BUFFER_SIZE; i++) {
+ HalpNvramStringBuffer[i] = 0;
+ }
+
+ HalpNvramStringBufferCounter=0;
+
+ //
+ // set string position
+ //
+
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=(UCHAR)Column;
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]=(UCHAR)Row;
+}
+
+
+VOID
+HalpStringBufferCopyToNvram(
+ VOID
+ )
+{
+ UCHAR buf[4];
+ USHORT count;
+
+ //
+ // check nvram status.
+ //
+
+ if(HalpNvramValid == FALSE) {
+ return;
+ }
+
+ //
+ // if data size is zero, when return
+ //
+
+ if( HalpNvramStringBufferCounter <= 2 ) {
+ return;
+ }
+
+ HalpNvramStringBuffer[HalpNvramStringBufferCounter++]='\0';
+
+ //
+ // check panic message
+ //
+
+ for( count=0; ; count++) {
+ if( KernelPanicMessage[count] == '\0' ){
+ HalpChangePanicFlag( 8, 0x01, 0x10);
+ break;
+ }
+ if( KernelPanicMessage[count] != HalpNvramStringBuffer[count+2] ){
+ break;
+ }
+ }
+
+ //
+ // check message length
+ //
+
+ for( count=2; ; count++) {
+ if( HalpNvramStringBuffer[count] == '\0' ){
+ count++;
+ break;
+ }
+ }
+
+loop:
+ if( ErrBufferCurrent + count + 2 < ErrBufferEnd ) {
+ HalNvramWrite( ErrBufferCurrent, count, HalpNvramStringBuffer );
+ ErrBufferCurrent += count;
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else if( (count + 2 > ErrBufferEnd - ErrBufferStart) && (HalpPanicFlg == 0) ) {
+ return;
+ } else {
+ if( HalpPanicFlg == 0 ) {
+ ErrBufferCurrent = ErrBufferStart;
+ goto loop;
+ } else if(ErrBufferCurrent >= ErrBufferEnd){
+ return;
+ }
+
+ for(count=0;;count++) {
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent, 1, HalpNvramStringBuffer+count );
+ }
+ ErrBufferCurrent++;
+ if( (HalpNvramStringBuffer[count]=='\0') && (count>=2) ) {
+ break;
+ }
+ }
+
+ buf[0]=0xff;
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ }
+}
+
+#if 0
+VOID
+HalpStringIntoNvram(
+ IN ULONG Column,
+ IN ULONG Row,
+ IN PUCHAR String
+ )
+{
+ UCHAR buf[4];
+ USHORT count;
+
+ //
+ // check nvram status.
+ //
+
+ if(HalpNvramValid == FALSE) {
+ return;
+ }
+
+ //
+ // check panic message
+ //
+
+ for(count=0; 1; count++) {
+ if( KernelPanicMessage[count] == '\0' ){
+ HalpChangePanicFlag( 8, 0x01, 0x10);
+ break;
+ }
+ if( KernelPanicMessage[count] != String[count] ){
+ break;
+ }
+ }
+
+ //
+ // check message length
+ //
+
+ for(count=0;;count++) {
+ if(String[count]=='\0'){
+ count++;
+ break;
+ }
+ }
+
+loop:
+ if( ErrBufferCurrent + count + 4 < ErrBufferEnd ) {
+ buf[0]=(UCHAR)Column;
+ buf[1]=(UCHAR)Row;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+ ErrBufferCurrent += 2;
+ HalNvramWrite( ErrBufferCurrent, count, String );
+ ErrBufferCurrent += count;
+ buf[0]=0xff;
+ buf[1]=0xff;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+
+ } else if( count + 4 > ErrBufferEnd - ErrBufferStart ) {
+ return;
+ } else {
+ if( HalpPanicFlg == 0 ) {
+ ErrBufferCurrent = ErrBufferStart;
+ goto loop;
+ } else if(ErrBufferCurrent >= ErrBufferEnd){
+ return;
+ }
+
+ buf[0]=(UCHAR)Column;
+ buf[1]=(UCHAR)Row;
+ HalNvramWrite( ErrBufferCurrent, 2, buf );
+ ErrBufferCurrent += 2;
+
+ for(count=0;;count++) {
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent, 1, String+count );
+ }
+ ErrBufferCurrent++;
+ if(String[count]=='\0') {
+ break;
+ }
+ }
+
+ buf[0]=0xff;
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ if(ErrBufferCurrent < ErrBufferEnd) {
+ HalNvramWrite( ErrBufferCurrent++, 1, buf );
+ }
+ }
+}
+#endif
+// S002 ^^^
+
+
+//
+// test code
+//
+
+int
+printNvramData(void)
+{
+ UCHAR buf[256];
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->nvram_flag), 1, buf );
+ DbgPrint("Nvram Flag: 0x%02lx\n", buf[0]);
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->when_formatted), 14, buf );
+ buf[14]=0;
+ DbgPrint("Nvram TimeStamp: %s\n", buf);
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->ecc1bit_err),
+ sizeof(ECC1_ERR_AREA_INFO),
+ buf );
+ DbgPrint("Nvram ECC1: offset=0x%04lx\n", *(PUSHORT)buf );
+ DbgPrint("Nvram ECC1: size =0x%04lx\n", *(PUSHORT)(buf+2) );
+ DbgPrint("Nvram ECC1: number=0x%04lx\n", *(PUSHORT)(buf+4) );
+ DbgPrint("Nvram ECC1: latest=0x%04lx\n", *(PUSHORT)(buf+6) );
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->ecc2bit_err),
+ sizeof(ECC2_ERR_AREA_INFO),
+ buf );
+ DbgPrint("Nvram ECC2: offset=0x%04lx\n", *(PUSHORT)buf );
+ DbgPrint("Nvram ECC2: size =0x%04lx\n", *(PUSHORT)(buf+2) );
+ DbgPrint("Nvram ECC2: number=0x%04lx\n", *(PUSHORT)(buf+4) );
+ DbgPrint("Nvram ECC2: latest=0x%04lx\n", *(PUSHORT)(buf+6) );
+
+ HalNvramRead( (USHORT)&(((pNVRAM_HEADER)0)->system_err),
+ sizeof(SYSTEM_ERR_AREA_INFO),
+ buf );
+ DbgPrint("Nvram SYSTEM: offset=0x%04lx\n", *(PUSHORT)buf );
+ DbgPrint("Nvram SYSTEM: size =0x%04lx\n", *(PUSHORT)(buf+2) );
+ DbgPrint("Nvram SYSTEM: number=0x%04lx\n", *(PUSHORT)(buf+4) );
+ DbgPrint("Nvram SYSTEM: latest=0x%04lx\n", *(PUSHORT)(buf+6) );
+
+ return(0);
+}
+
+
+int
+TmpInitNvram(void)
+{
+ UCHAR buf[256];
+ ULONG i;
+
+ buf[0]=0xff;
+ for(i=0; i<8*1024; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make nvram flg
+ //
+
+ buf[0]=0x03;
+ HalNvramWrite( NVRAM_STATE_FLG_OFFSET, 1, buf);
+
+ i = NVRAM_MAGIC;
+ HalNvramWrite( NVRAM_MAGIC_NO_OFFSET, 1, (PUCHAR)&i);
+
+ //
+ // Make 1bit err log info
+ //
+
+ ((pECC1_ERR_AREA_INFO)buf)->offset_1biterr=768;
+ ((pECC1_ERR_AREA_INFO)buf)->size_rec=25;
+ ((pECC1_ERR_AREA_INFO)buf)->num_rec=16;
+ ((pECC1_ERR_AREA_INFO)buf)->offset_latest=768;
+
+ ((pECC1_ERR_AREA_INFO)buf)->read_data_latest=0;
+
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group0=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group1=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group2=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group3=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group4=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group5=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group6=0;
+ ((pECC1_ERR_AREA_INFO)buf)->err_count_group7=0;
+
+ HalNvramWrite( ECC_1BIT_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC1_ERR_AREA_INFO),
+ buf);
+
+ buf[0]=0;
+ for(i=768; i<768+25*16; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make 2bit err log info
+ //
+
+ ((pECC2_ERR_AREA_INFO)buf)->offset_2biterr=768+400;
+ ((pECC2_ERR_AREA_INFO)buf)->size_rec=25;
+ ((pECC2_ERR_AREA_INFO)buf)->num_rec=4;
+ ((pECC2_ERR_AREA_INFO)buf)->offset_latest=768+400;
+
+ ((pECC2_ERR_AREA_INFO)buf)->read_data_latest=0;
+
+ HalNvramWrite( ECC_2BIT_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC2_ERR_AREA_INFO),
+ buf);
+
+ buf[0]=0;
+ for(i=768+400; i<768+400+25*4; i++)
+ HalNvramWrite( i, 1, buf);
+
+ //
+ // Make system err log info
+ //
+
+ ((pSYSTEM_ERR_AREA_INFO)buf)->offset_systemerr=1280;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->size_rec=512;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->num_rec=4;
+ ((pSYSTEM_ERR_AREA_INFO)buf)->offset_latest=1280;
+
+ HalNvramWrite( SYSTEM_ERROR_LOG_INFO_OFFSET,
+ sizeof(ECC2_ERR_AREA_INFO),
+ buf);
+
+ buf[0]=0;
+ for(i=1280; i<1280+512*4; i++)
+ HalNvramWrite( i, 1, buf);
+
+ return(0);
+}
diff --git a/private/ntos/nthals/halr98mp/mips/r98hal.h b/private/ntos/nthals/halr98mp/mips/r98hal.h
new file mode 100644
index 000000000..63bfa51df
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98hal.h
@@ -0,0 +1,132 @@
+#ident "@(#) NEC r98hal.h 1.4 94/09/22 16:56:52"
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ r98hal.h
+
+
+Abstract:
+
+ This module is the header that dma structure and etc.
+
+Author:
+
+
+Revision History:
+
+--*/
+
+/*
+ ***********************************************************************
+ *
+ * S001 7/12 T.Samezima
+ *
+ * Chg define chenge
+ *
+ * K001 94/09/22 N.Kugimoto
+ * Chg DMA logcal addres sapce 4M--->16M
+ */
+
+#ifndef _R98HAL_
+#define _R98HAL_
+
+// Start S001
+//
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+extern ULONG HalpMapBufferSize;
+// End S001
+
+//
+// define structure of adapter object
+//
+typedef struct _ADAPTER_OBJECT { // (= ntos/hal/i386/ixisa.h)
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters; // new add
+ 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;
+ UCHAR AdapterMode;
+} ADAPTER_OBJECT; // del duo's SingleMaskPort
+
+//
+// Define map register translation entry structure For Internal.
+//
+
+typedef struct _INTERNAL_TRANSLATION_ENTRY {
+ PVOID VirtualAddress;
+ ULONG PhysicalAddress;
+ ULONG Index;
+} INTERNAL_TRANSLATION_ENTRY, *PINTERNAL_TRANSLATION_ENTRY;
+
+// Start S001
+typedef struct _TRANSLATION_ENTRY {
+ ULONG PageFrame;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+// End S001
+
+//
+// define dma
+//
+
+#define MACHINE_TYPE_ISA 0
+#define MACHINE_TYPE_EISA 1
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0x40000 // 64 page
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE MAXIMUM_MAP_BUFFER_SIZE
+#define INITIAL_MAP_BUFFER_LARGE_SIZE MAXIMUM_MAP_BUFFER_SIZE
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000 // 16 page
+#define MAXIMUM_ISA_MAP_REGISTER (MAXIMUM_MAP_BUFFER_SIZE/(PAGE_SIZE*2))
+ // 32 page
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x60000000 // max : 16MB // S001
+
+#define COPY_BUFFER 0xFFFFFFFF
+#define NO_SCATTER_GATHER 0x00000001
+#define DMA_TRANSLATION_LIMIT 0x4000 // TLB alloc size K001
+
+//
+// Define pointer to DMA control registers.
+//
+// Start S001
+#define DMA_CONTROL(x) ((volatile PDMA_CHANNEL)((ULONG)(KSEG1_BASE | LR_CHANNEL_BASE |(x))))
+// End S001
+
+//
+// Define MRC register structure.
+//
+typedef struct _MRC_REGISTERS { // offset(H)
+ UCHAR Reserved1[48]; // 0-2f
+ UCHAR SwReset; // 30
+ UCHAR Reserved2[19]; // 31-43
+ UCHAR LedData0; // 44
+ UCHAR LedData1; // 45
+ UCHAR LedData2; // 46
+ UCHAR LedData3; // 47
+} MRC_REGISTERS, *PMRC_REGISTERS;
+
+//
+// Define pointer to MRC registers.
+//
+#define MRC_CONTROL ((volatile PMRC_REGISTERS)(KSEG1_BASE | MRC_PHYSICAL_BASE))
+
+#endif _R98HAL_
diff --git a/private/ntos/nthals/halr98mp/mips/r98hwsup.c b/private/ntos/nthals/halr98mp/mips/r98hwsup.c
new file mode 100644
index 000000000..4cee934f9
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98hwsup.c
@@ -0,0 +1,4771 @@
+#ident "@(#) NEC r98hwsup.c 1.41 95/06/19 11:31:38"
+/*++
+
+Copyright (c) 1990-1994 Microsoft Corporation
+
+Module Name:
+
+ r98hwsup.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.
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * HalpCreateDmaStructures()
+ *
+ * L001 94.03/24 T.Samezima
+ *
+ * Change Interrupt service routine
+ *
+ * Add Call initialize of PCI interrupt
+ * Interrupt enable
+ *
+ * K001 '94.5/30 (Mon) N.Kugimoto
+ * -1 Add HalAllocateAdapterChannel():
+ * -2 Add HalAllocateCommonBuffer():
+ * -3 Non HalFlushCommonBuffer()
+ * -4 Add HalFreeCommonBuffer(): For Internal Device
+ * -5 Chg HalGetAdapter(): New!!
+ * -6 Mix HalpAllocateAdapter(): mix halfxs,halx86
+ * -7 Add IoFreeMapRegisters(): For Internal Device
+ * -8 Add IoFreeAdapterChannel(): For Internal Device
+ * -9 FRM HalpAllocateMapRegisters() From halx86
+ * -A Mix IoMapTransfer() mix halfxs,halx86
+ * -B Mix IoFlushAdapterBuffers() mix halfxs,halx86
+ * -C FRM HalpAllocationRoutine () From halfxs
+ * -D FRM HalReadDmaCounter() From halfxs
+ * -E Del HalpDmaInterrupt() allways retrun 1
+ * -F FRM HalpGrowMapBuffers() halx86
+ * -G FRM HalpCopyBufferMap() from halx86 and Argument chg.
+ *
+ * K002 Add MasterAdapterObjectForInternal
+ * K003 Chg HalpInternalAdapters[5]: LR4360 DMA have 5 channel
+ * K004 Add HalpDmaInterrupt()
+ * K005 fix spell miss
+ * K006 FRM global value define!! From halx86
+ * K007 Chg if def chg
+ * K008 94/5/31 N.Kugimoto
+ * Chg HalTranslateBusAddress()
+ * N.B. Pci trans addr is per slot ??.
+ * K009 94/5/31 N.Kugimoto
+ * BUG AddressSpace!!
+ * K00A 94/6/2 (Thu) N.Kugimoto
+ * Chg HalAllocateCrashDumpRegisters()
+ * N.B. check is OK??
+ *
+ * S002 94.03/24 T.Samezima
+ *
+ * Add HalpNmiHandler()
+ * HalpRegisterNmi() ???
+ *
+ * K00B 94/6/3 (Fri) N.Kugimoto
+ * Del
+ * K00C 94/6/6 (Mon) N.Kugimoto
+ * Chg K007 enable
+ * K00D 94/6/9 (Thu) N.kugimoto
+ * Chg Compile err del.
+ * K00E 94/7/1 (Fri) N.Kugimoto
+ * -1 Chg IoFlushAdapterBuffers()
+ * -2 Add IoFlushAdapterBuffers() Reserved Bit set 0.
+ * -3 Del HalAllocateCrashDumpRegisters() limit check del.
+ * -4 Bug IoMapTransfer() transferLength is Bad!!.
+ * -5 Bug MasterAdapterObject ==> AdapterObject.
+ * -6 Bug at this line. LR4360 dma
+ * -7 Bug enable #if 0 and eisadma is del.
+ * -8 Del This code is never use. so del.
+ * K00F 94/7/6 (Wed) N.Kugimoto
+ * Mov HalGetAdapter() CnDC->FiFoF Flush LR4360 DMA FiFo Move IoMapTransfer()
+ * Per DMA Translation.
+ * K010 94/7/8 (Fri) N.Kugimoto
+ * -1 Chg enable check logic.
+ * -2 Add comment add. LR4360 DMA Byte Count Register 64M. Bit25-Bit0.
+ * -3 Add Comment add. This value use only as flag. Not Port Addr.
+ * K011 94/8/22 (Mon) N.Kugimoto
+ * -1 Bug if {} else not match!!. Debug On SNES.
+ * -2 Bug HalpDmaInterrupt() enable Because First run rather than
+ * IoFlushAdapterBuffers().Debug On SNES.
+ * K012 94/9/22 N.Kugimoto
+ * -1 Bug MasterAdapterObject->NumberOfMapRegiser is Non Initialize.
+ * K013 94/9/22 N.Kugimoto
+ * -1 Chg Externl logical addr first allocation 1M align.
+ * second allocaton is start offset 0.
+ * -2 Bug MasterAdapter can't use this line.
+ * K014 94/9/22 N.Kugimoto
+ * compile err
+ * K015 94/09/26 N.Kugimoto
+ * Mov move code to r98busdat.c
+ * K016 94/09/29 N.Kugimoto
+ * -1 Chg allocate memory is less than 512M. To see from KSEG1_BASE.
+ * -2 Add cast ULONG .
+ * K017 94/10/05 N.Kugimoto
+ * -1 Bug must be () .
+ * K018 94/10/07 N.Kugimoto
+ * -1 Bug align 1m Logic Bug.
+ * K019 94/10/06 N.Kugimoto
+ * -1 Bug LR4360 PTBARn Register must be PFN. Not KSEG1_BASE value.
+ * K020 94/10/11 N.Kugimoto
+ * -1 Fix Version Up At 807 Base.
+ * K021 94/10/11 N.Kugimoto
+ * -1 Add page table clear
+ * -2 Add tlb flush
+ * K022 94/10/11 N.Kugimoto
+ * Add NMI Logic
+ * K023 94/10/12 N.Kugimoto
+ * K024 94/10/13 N.Kugimoto
+ * Chg Compile err
+ * S025 94/10/14 T.Samezima
+ * Del Move logic on connect int1 interrupt to allstart.c
+ * K025 94/10/17 N.Kugimoto
+ * Bug K020-1 miss
+ * K026 94/10/18 N.Kugimoto
+ * -1 Bug LR4360 Page Table is KSEG0_BASE
+ * -2 Chg Page table Entry Invalidate.
+ * -3 Chg tlb flush timing chg
+ * K027 94/11/11 N.Kugimoto
+ * -1 Chg cache enable
+ * -2 Chg Som Logical addr range not Used.
+ *
+ * K028 95/2/22 N.Kugimoto
+ * Chg PCEB Prefetch sycle caused LR4360 page fault
+ * K029 95/2/22 N.Kugimoto
+ * Add LR4360 TLB RoundUp.
+ * K030 95/2/22 N.Kugimoto
+ * Chg LR4360 TLB No Flush. Because At DMA ....
+ * K031 95/2/22 N.Kugimoto
+ * Add LR4360 I/O Read Cache Flush
+ * K032 95/3/13 N.Kugimoto
+ * Chg #if #else fix Miss.
+ *
+ * S003 95/3/14 T.Samezima
+ * Add Add HalpLRErrorInterrupt() at dispatch table.
+ * K034 95/04/12 N.Kugimoto
+ * Del NOTLBFLUSH
+ * Add DUMMYDMA This is Work around.
+ * LR4360 can't TLB flush while dma. So ESC DMAC channel 2 use
+ * Dummy dma 1byte. It't cause TLB flush .
+ * S004 95/5/15 T.Samezima
+ * Chg vaild page table on LR4360
+ * A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ * - resolve compile error.
+ * -------------------------------------------------------------------
+ * K035 95/6/16 N.Kugimoto
+ * Up version Up 3.51
+ */
+
+#include "halp.h"
+#include "bugcodes.h"
+#include "eisa.h"
+
+#include "jazznvr.h" //K00D
+
+//
+// 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, HalpCreateDmaStructures)
+#pragma alloc_text(PAGE,HalpGrowMapBuffers) //K035
+
+#endif
+
+extern POBJECT_TYPE IoAdapterObjectType;
+
+//
+// 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;
+//
+// K002
+//
+PADAPTER_OBJECT MasterAdapterObjectForInternal;
+
+
+// K006
+// Map buffer prameters. These are initialized in HalInitSystem
+//
+
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+ULONG HalpMapBufferSize;
+
+//
+// Pointer to phyiscal memory for map registers.
+//
+
+ULONG HalpMapRegisterPhysicalBase;
+
+
+// PCEB Prefetch sycle cause LR4360 Page Fault
+// So reserved DummyPhysicalPage
+ULONG HalpNec0DummyPhysicalBase; // K028
+ULONG HalpNec1DummyPhysicalBase; // K028
+
+ULONG HalpLogicalAddrArbPoint=0;
+KSPIN_LOCK HalpIoMapSpinLock;
+
+// K004
+// The following function is called when a DMA channel interrupt occurs.
+//
+
+BOOLEAN
+HalpDmaInterrupt(
+ VOID //K00D
+ );
+
+
+//
+// The following is an array of adapter object structures for the internal DMA
+// channels.
+// K003
+// N.B: Internal Device without Scatter/Gather not use this array.
+//
+
+PADAPTER_OBJECT HalpInternalAdapters[5];
+
+
+IO_ALLOCATION_ACTION
+HalpAllocationRoutine (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PVOID MapRegisterBase,
+ IN PVOID Context
+ );
+
+// A002
+PVOID
+RtlFillMemoryUlong (
+ IN PVOID Destination,
+ IN ULONG Length,
+ IN ULONG Pattern
+ );
+// A002
+VOID
+HalpDummyTlbFlush(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+BOOLEAN
+HalpCreateDmaStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for DMA operations
+ and connects the intermediate interrupt dispatcher. It also connects
+ an interrupt handler to the DMA channel interrupt.
+
+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.
+
+--*/
+
+{
+ /* Start L001 */
+ ULONG buffer;
+
+ //
+ // Initialize the interrupt dispatcher for I/O interrupts.
+ //
+ // N.B. This vector is reserved for exclusive use by the HAL (see
+ // interrupt initialization).
+ //
+
+ PCR->InterruptRoutine[INT2_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt2Dispatch;
+// PCR->InterruptRoutine[INT1_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt1Dispatch; // S025
+
+ PCR->InterruptRoutine[INT0_LEVEL] = (PKINTERRUPT_ROUTINE) HalpInt0Dispatch;
+
+ //
+ // Directly connect the local device interrupt dispatcher to the local
+ // device interrupt vector.
+ //
+
+ PCR->InterruptRoutine[DMA_VECTOR] = (PKINTERRUPT_ROUTINE) HalpDmaInterrupt;
+
+ // S003
+ PCR->InterruptRoutine[LR_ERR_VECTOR] = (PKINTERRUPT_ROUTINE) HalpLRErrorInterrupt;
+
+ //
+ //
+ //
+
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ HalpBuiltinInterruptEnable |=
+ (iREN_ENABLE_DMA_INTERRUPT | iREN_ENABLE_LR_ERR_INTERRUPT ); // S003
+
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+
+#if 0 // Start S025
+ //
+ // Initialize EISA bus interrupts.
+ //
+
+ HalpCreateEisaStructures();
+
+ //
+ // Initialize PCI bus interrupts.
+ //
+
+ return HalpCreatePciStructures ();
+#else
+ return TRUE;
+#endif // End S025
+ /* End L001 */
+}
+
+// K001:
+//
+//
+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;
+ LONG MapRegisterNumber;
+ KIRQL Irql;
+ ULONG srachPoint;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ // dicide MasterAdapter whitch Intrenal Scatter/gathero or PCI,EISA,ISA
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // 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 )){
+
+ //
+ // The adapter was not busy so it has been allocated. Now 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.
+ //
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ //
+ //
+ //
+ if (NumberOfMapRegisters != 0 && AdapterObject->MasterAdapter != NULL) {
+
+ if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){ //K011-1
+ //
+ // At Internal check adapterobject itself.
+ //
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+ }else{
+ //
+ // At PCI,EISA,ISA check with Masteradapter
+ //
+ if (NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ } //K011-1
+ //
+ // 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)) {
+
+ if(MasterAdapter == MasterAdapterObject){
+ srachPoint = HalpLogicalAddrArbPoint;
+ HalpLogicalAddrArbPoint = (HalpLogicalAddrArbPoint+256) %
+ (DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY));
+ } else {
+ srachPoint = 0;
+ }
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ MasterAdapter ==
+ MasterAdapterObject ? NumberOfMapRegisters+1 : NumberOfMapRegisters, //K028
+ srachPoint
+
+ );
+
+ }
+ 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 {
+
+ if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PINTERNAL_TRANSLATION_ENTRY) MasterAdapter->MapRegisterBase
+ + MapRegisterNumber);
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported on Internal Device.
+ // ~~~~~~~
+ //
+
+ AdapterObject->MapRegisterBase =
+ (PVOID)((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }else{
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase
+ + MapRegisterNumber ); //add1 non
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ }else {
+ AdapterObject->MapRegisterBase = NULL;
+
+ }
+
+ //
+ // 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) {
+
+ Action = ExecutionRoutine( 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)
+ IoFreeAdapterChannel( AdapterObject );
+
+ }
+ }
+ return(STATUS_SUCCESS);
+}
+
+// K001-2
+//
+//
+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;
+ PVOID mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mappedLength;
+ WAIT_CONTEXT_BLOCK wcb;
+ KEVENT allocationEvent;
+ NTSTATUS status;
+ PMDL mdl;
+ KIRQL irql;
+
+
+ PHYSICAL_ADDRESS physicalAddress;
+
+ CacheEnabled =TRUE; //K027-1
+ // Is it Internal Device ?.
+ //
+
+
+ if(AdapterObject->MasterAdapter==MasterAdapterObjectForInternal ||
+ (AdapterObject->MasterAdapter==NULL ) // K00B
+ ){
+ //
+ // Internal Device Not use LR4360 TLB.
+ // LowPart is Any.
+ //
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS-1;
+ physicalAddress.HighPart = 0;
+ virtualAddress = MmAllocateContiguousMemory(
+ Length,
+ physicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+ return(NULL);
+ }
+
+ *LogicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ return(virtualAddress);
+ }
+
+ //
+ // PCI,EISA,ISA Device use LR4360 TLB.
+ //
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ //
+ // Allocate the actual buffer.
+ //
+ if (CacheEnabled != FALSE) { //K020-1
+
+ virtualAddress = ExAllocatePool(NonPagedPoolCacheAligned, Length);
+ } else {
+ virtualAddress = MmAllocateNonCachedMemory(Length);
+ }
+
+ if (virtualAddress == NULL) {
+
+ return(virtualAddress);
+
+ }
+
+ //
+ // Initialize an event.
+ //
+
+ KeInitializeEvent( &allocationEvent, NotificationEvent, FALSE);
+
+ //
+ // Initialize the wait context block. Use the device object to indicate
+ // where the map register base should be stored.
+ //
+
+ wcb.DeviceObject = &mapRegisterBase;
+ wcb.CurrentIrp = NULL;
+ wcb.DeviceContext = &allocationEvent;
+
+ //
+ // Allocate the adapter and the map registers.
+ //
+
+ KeRaiseIrql(DISPATCH_LEVEL, &irql);
+
+ status = HalAllocateAdapterChannel(
+ AdapterObject,
+ &wcb,
+ numberOfMapRegisters,
+ HalpAllocationRoutine
+ );
+
+ KeLowerIrql(irql);
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+
+ if (CacheEnabled != FALSE) { //K020-1
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Wait for the map registers to be allocated.
+ //
+
+ status = KeWaitForSingleObject(
+ &allocationEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL
+ );
+
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Cleanup and return NULL.
+ //
+ if (CacheEnabled != FALSE) { //K020-1
+ ExFreePool(virtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(virtualAddress, Length);
+ }
+
+ return(NULL);
+
+ }
+
+ //
+ // Create an mdl to use with call to I/O map transfer.
+ //
+
+ mdl = IoAllocateMdl(
+ virtualAddress,
+ Length,
+ FALSE,
+ FALSE,
+ NULL
+ );
+
+ MmBuildMdlForNonPagedPool(mdl);
+
+ //
+ // Map the transfer so that the controller can access the memory.
+ //
+ // mapRegisterBase was set up at HalAllocateAdapterChannel()-->ExecutionRoutine()-->
+ // HalpAllocationRoutine() (value same MapRegisterBase)
+ //
+ //
+ mappedLength = Length;
+ *LogicalAddress = IoMapTransfer(
+ NULL,
+ mdl,
+ mapRegisterBase,
+ virtualAddress,
+ &mappedLength,
+ TRUE
+ );
+
+ //DbgPrint("\n Common Logical = 0x %x \n",*LogicalAddress);
+ IoFreeMdl(mdl);
+
+ if (mappedLength < Length) {
+
+ //
+ // Cleanup and indicate that the allocation failed.
+ //
+
+ HalFreeCommonBuffer(
+ AdapterObject,
+ Length,
+ *LogicalAddress,
+ virtualAddress,
+ CacheEnabled //K020-1
+ );
+
+ return(NULL);
+ }
+
+ //
+ // The allocation completed successfully.
+ //
+
+ return(virtualAddress);
+
+}
+
+// K00A
+//
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters //K020-1
+ )
+/*++
+
+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 and update to show
+ number actually allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+//K020-1 ULONG NumberOfMapRegisters;
+ ULONG MapRegisterNumber;
+#if !defined(_R98_)
+ ULONG Hint;
+#endif
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ if (AdapterObject->MasterAdapter) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+#if defined(_R98_)
+ // MasterAdapter==NULL This is Internal Device with Scatter/Gather.
+ // So Nothing to Do. Never Use Mapregisters for contigus memory.
+ // N.B. MasterAdapterObject[ForInternal] does not come here!!.
+ // So No check !!.
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ return AdapterObject->MapRegisterBase;
+#else
+ MasterAdapter = AdapterObject;
+#endif
+
+
+ }
+
+ //
+ // Set the number of map registers required.
+ //
+
+//K020-1 *NumberOfMapRegisters = 16;
+
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+#if 1 // K010-1
+ // K00E-3
+ //
+ if(MasterAdapter == MasterAdapterObjectForInternal){
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) { //K020-1
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+ }else{
+ // PCI,EISA,ISA device's limit is MasterAdapter.
+ //
+ if (*NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) { //K020-1
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ }
+#endif
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed. Note that once again the map registers to be allocated
+ // must be above the 1MB range if this is an EISA bus device.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+#if !defined(_R98_)
+ Hint = AdapterObject->PagePort ? (0x100000 / PAGE_SIZE) : 0;
+#endif
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ MasterAdapter == MasterAdapterObject ? *NumberOfMapRegisters+1 : *NumberOfMapRegisters, //K028
+#if defined(_R98_)
+ 0
+#else
+ Hint
+#endif
+ );
+
+#if !defined(_R98_)
+ //
+ // Ensure that any allocated map registers are valid for this adapter.
+ //
+
+ if ((ULONG) MapRegisterNumber < Hint) {
+
+ //
+ // Make it appear as if there are no map registers.
+ //
+
+ RtlClearBits(
+ MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ *NumberOfMapRegisters //K020-1
+ );
+
+ MapRegisterNumber = (ULONG) -1;
+ }
+#endif
+ 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,
+#if defined(_R98_)
+ 0, // 0M was reserved
+#else
+ Hint,
+#endif // K00D
+ *NumberOfMapRegisters+1
+ );
+#if defined(_R98_)
+ MapRegisterNumber = 0x0;
+#else
+ MapRegisterNumber = Hint;
+#endif
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+#if defined(_R98_)
+ if(MasterAdapter == MasterAdapterObjectForInternal){
+ AdapterObject->MapRegisterBase = ((PINTERNAL_TRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ //
+ // Set the no scatter/gather flag .
+ // in there R98 Internal Device is Not always Scatter/Gather supported.
+ //
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+ }else
+#endif
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ return AdapterObject->MapRegisterBase;
+}
+
+
+
+// K001-3
+//
+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.
+
+--*/
+
+{
+ UNREFERENCED_PARAMETER( AdapterObject );
+ UNREFERENCED_PARAMETER( Length );
+ UNREFERENCED_PARAMETER( LogicalAddress );
+ UNREFERENCED_PARAMETER( VirtualAddress );
+
+ return(TRUE);
+
+}
+
+// K001-4
+//
+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
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase;
+ ULONG numberOfMapRegisters;
+ ULONG mapRegisterNumber;
+ CacheEnabled = TRUE; //K027-1
+
+ if(AdapterObject->MasterAdapter==MasterAdapterObjectForInternal||
+ (AdapterObject->MasterAdapter==NULL ) // K00B
+ ){
+ //
+ // Internal Device
+ //
+ MmFreeContiguousMemory (VirtualAddress);
+ }else{
+
+ //
+ // PCI,EISA,ISA.
+ //
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ //
+ // For PCI,EISA,ISA Logical address started at PCI_LOGICAL_START_ADDRESS
+ // See. IoMapTransfer!!.
+ //
+ mapRegisterNumber = (LogicalAddress.LowPart - PCI_LOGICAL_START_ADDRESS) >> PAGE_SHIFT;
+
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase
+ + mapRegisterNumber;
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) mapRegisterBase,
+ numberOfMapRegisters
+ );
+
+ //
+ // Free the memory for the common buffer.
+ //
+
+ if (CacheEnabled != FALSE) { //K020-1
+ ExFreePool(VirtualAddress);
+
+ } else {
+ MmFreeNonCachedMemory(VirtualAddress, Length);
+ }
+
+
+ }
+
+ return;
+}
+
+// K001-5
+// As PCI,EISA,ISA Device is used TLB of LR4360.
+// Scatter/Gather is supported By Hal.
+//
+// Internal Device Never use TLB of LR4360.
+// So Device without Scatter/Gather is use continuguas memory.
+//
+// Internal Device at Bbus Device is used LR4360 DMA.
+// LR4360's DMA have Scatter/Gather .But Not use this version hal.
+// So use continuguas memory.
+//
+//
+//
+//
+// Source Base 612 halfxs/mips/jxhwsup.c,halx86/i386/ixisasup.c
+//
+//
+//
+//
+//
+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: Internal, Isa, and Eisa.
+
+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;
+ ULONG maximumLength;
+ ULONG numberOfMapRegisters;
+ ULONG value; //K00D
+ //
+ // Make sure this is the correct version.
+ //
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION1) //K020-1,K025
+ return(NULL);
+
+ //
+ // Return number of map registers requested based on the maximum
+ // transfer length.
+ //
+
+ *NumberOfMapRegisters = BYTES_TO_PAGES(DeviceDescription->MaximumLength) + 1;
+#if 0
+ //
+ // 612 halfx code not use. Because Number of R98 PCI,EISA device is 8 and
+ // Limit By MasterAdapterObject->MapRegisterPerChannel / 8
+ //
+ if (*NumberOfMapRegisters > DMA_REQUEST_LIMIT) {
+ *NumberOfMapRegisters = DMA_REQUEST_LIMIT;
+ }
+#endif
+
+ //
+ // Get AdapterObject
+ // At 1 st call HalpAllocateAdapter() Allocateted MasterAdapterObject or
+ // MasterAdapterObjectForInternal.
+
+ switch(DeviceDescription->InterfaceType){
+ case Internal:
+ //
+ // Return the adapter pointer for internal adapters.
+ // such as SCSI,SONIC,Floppy LR4360
+ // K00D
+
+ if(DeviceDescription->Master){ // Bus Master Device
+ if(DeviceDescription->ScatterGather){ // Device is Scatter/Gather support!!
+ numberOfMapRegisters=0; // then no use Mapregister.
+ }else{
+ numberOfMapRegisters=1; // else use 1 Mapregister.
+ }
+
+#if defined(NONARB)
+ if (((HalpInternalAdapters[3] == NULL) && DeviceDescription->ScatterGather) ||
+ ( (HalpInternalAdapters[4] == NULL) && (DeviceDescription->ScatterGather==0)) ) {
+
+#endif
+
+ adapterObject=
+ HalpAllocateAdapter(
+ numberOfMapRegisters,
+ NULL,
+ (PVOID)-1 // K00D
+ );
+#if defined(NONARB)
+ if(DeviceDescription->ScatterGather ){
+ HalpInternalAdapters[3] = adapterObject; //SCSI0,SCSI1
+ adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters;
+ return(adapterObject); // K005
+
+
+ }else{
+ HalpInternalAdapters[4] = adapterObject; //SONIC
+
+ }
+ }else{
+ if(DeviceDescription->ScatterGather){
+ return(HalpInternalAdapters[3]);
+ }else{
+ adapterObject=HalpInternalAdapters[4];
+ }
+
+ }
+
+#endif
+
+ // K00D K00E-6
+ }else if (HalpInternalAdapters[DeviceDescription->DmaChannel] != NULL ) {
+ //
+ // If necessary allocate an adapter; otherwise,
+ // just return the adapter for the requested channel.
+ //
+ // LR4360 DMA channel 1 is floppy.
+ //
+ // K00D
+ adapterObject = HalpInternalAdapters[DeviceDescription->DmaChannel];
+ //
+ // Limit of one allocate request MAXIMUM_ISA_MAP_REGISTER =16==>64K
+ //
+ *NumberOfMapRegisters = *NumberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : *NumberOfMapRegisters;
+
+
+ }else{
+ //
+ // Limit of one allocate request MAXIMUM_ISA_MAP_REGISTER =16==>64K
+ //
+
+ *NumberOfMapRegisters = *NumberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : *NumberOfMapRegisters;
+
+ adapterObject=
+ HalpAllocateAdapter(
+ 1,
+ // KSEG1_BASE K00D
+ // K010-3 This value use only as flag.
+ &(DMA_CONTROL ( DeviceDescription->DmaChannel << LR_CHANNEL_SHIFT))->CnDC, // K00D
+ (PVOID)-1 // K00D
+ );
+
+ //
+ // Driver of use LR4360 DMA
+ // HalpInternalAdapters[]
+ //
+ HalpInternalAdapters[DeviceDescription->DmaChannel] = adapterObject;
+
+ adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters;
+ }
+#if !defined(NONARB)
+ //
+ // Bus Master of Internal Device with Scatter/gather then Nothing to Do.
+ // K00D
+ if(DeviceDescription->Master && DeviceDescription->ScatterGather){
+ //
+ // No Limit Because MapRegisters were not used.
+ //
+ adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters;
+ return(adapterObject); // K005
+
+ }
+#endif
+ //
+ // new request > primiry request
+ //
+ if (*NumberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+ adapterObject->MapRegistersPerChannel = *NumberOfMapRegisters;
+ }
+ // K00D
+ if(DeviceDescription->Master){
+ //
+ // Internal device Master without Scatter/Gather.
+ //
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObjectForInternal->CommittedMapRegisters +=
+ (*NumberOfMapRegisters) * 2;
+
+ }else{
+ //
+ // Internal device with LR4360 DMA. etc floppy
+ //
+
+ MasterAdapterObjectForInternal->CommittedMapRegisters +=
+ (*NumberOfMapRegisters);
+ }
+ //
+ // See MasterAdapterObjectForInternal and
+ // Grow--!!. && Link To MapRegister.
+ //
+ if (MasterAdapterObjectForInternal->CommittedMapRegisters >
+ MasterAdapterObjectForInternal->NumberOfMapRegisters &&
+ MasterAdapterObjectForInternal->CommittedMapRegisters -
+ MasterAdapterObjectForInternal->NumberOfMapRegisters >
+ MAXIMUM_ISA_MAP_REGISTER)
+ {
+ //
+ // increment INCREMENT_MAP_BUFFER_SIZE=64K
+ // Number of Mapregister is 64K*4 /4K
+ //
+ HalpGrowMapBuffers(
+ MasterAdapterObjectForInternal,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+ //
+ // check LR4360 DMA Channel
+ // K00D
+ if(!DeviceDescription->Master){
+ adapterObject->ChannelNumber =(UCHAR)DeviceDescription->DmaChannel; //K00D
+ //
+ // LR4360 DMA have Scatter/Gather But not support this version.
+ // Set Up DMA default value.
+ //
+ // 1.DMA mode :Normal mode
+ //
+ // K00D ULONG value;
+
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL(
+ (DeviceDescription->DmaChannel << LR_CHANNEL_SHIFT))
+ )->CnDF
+ );
+
+ ((PLR_DMA_CONFIG)&value)->Reserved1=0;
+ ((PLR_DMA_CONFIG)&value)->Reserved2=0;
+
+ ((PLR_DMA_CONFIG)&value)->TMODE=LR_DMA_MODE_NORMAL;
+ ((PLR_DMA_CONFIG)&value)->iNEDi=1; //K00D
+ ((PLR_DMA_CONFIG)&value)->iNEDE=1;
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (DeviceDescription->DmaChannel << LR_CHANNEL_SHIFT))
+ )->CnDF,
+ value
+ );
+
+
+ // K00F Under Code Move IoMapTransfer()
+
+ }
+ return(adapterObject); // K005 K00D
+
+ case Isa:
+ case Eisa:
+ //
+ // Create an adapter object For Pci Device
+ //
+
+ adapterObject = HalpAllocateEisaAdapter( DeviceDescription );
+ //DbgPrint("\nEISA: = 0x%x\n",adapterObject);
+
+ break;
+
+ case PCIBus:
+ //
+ // Create an adapter object For Pci Device.
+ //
+
+ adapterObject = HalpAllocateAdapter( 0,NULL,NULL );
+ break;
+
+ default:
+ // Another Bus Not Suport !!
+ return(NULL);
+ }
+#if defined(DUMMYDMA) // K034 vvv
+ // Max is 1M-2: 0xffe000
+ //
+ //
+ if (*NumberOfMapRegisters > 0x100 -2)
+ *NumberOfMapRegisters = 0x100-2;
+
+#else
+ //
+ // PCI,EISA,ISA Device use LR4360 TLB.(PCI<-->ASOBus)
+ // Max Limit Of MapRegister Per Channel For PCI,EISA,ISA Device Set beyond MasterRegisterPerChannel
+ //
+ if (*NumberOfMapRegisters > MasterAdapterObject->MapRegistersPerChannel / 8)
+ *NumberOfMapRegisters = MasterAdapterObject->MapRegistersPerChannel / 8;
+#endif // K034 ^^^
+ // Check By HalAllocateAdapterChannel for MasterAdapter.
+ // adapterObject->NeedsMapRegisters = TRUE;
+ //
+ return(adapterObject);
+}
+
+#if 0 //K015
+BOOLEAN
+HalTranslateBusAddress(
+ IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the system physical address for a specified I/O bus
+ address. The return value is suitable for use in a subsequent call to
+ MmMapIoSpace.
+
+Arguments:
+
+ InterfaceType - Supplies the type of bus which the address is for.
+
+ BusNumber - Supplies the bus number for the device.
+
+ BusAddress - Supplies the bus relative address.
+
+ AddressSpace - Supplies the address space number for the device: 0 for
+ memory and 1 for I/O space. Returns the address space on this system.
+
+ 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
+
+--*/
+
+{
+ //
+ // R98 HighPart never carry!!
+ //
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ return(TRUE);
+ }
+
+#if defined(_R98_) // K008
+
+ switch(InterfaceType){
+
+ case PCIBus:
+ if(*AddressSpace){ // I/O
+ // N.B. Pci trans addr is per slot ??.
+ // So How get slot number!!.
+ //
+ TranslatedAddress->LowPart = BusAddress.LowPart+PCI_CONTROL_SLOT1_PHYSICAL_BASE;
+
+ }else{ // Memory
+ TranslatedAddress->LowPart = BusAddress.LowPart+PCI_MEMORY_PHYSICAL_BASE;
+
+ }
+ break;
+ case Eisa:
+ case Isa:
+ if(*AddressSpace){ // I/O
+ TranslatedAddress->LowPart = BusAddress.LowPart+EISA_CONTROL_PHYSICAL_BASE;
+
+ }else{ // Memory
+ TranslatedAddress->LowPart = BusAddress.LowPart+EISA_MEMORY_PHYSICAL_BASE;
+
+ }
+ break;
+
+ default: // UnKnow K00D
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+ *AddressSpace = 0; // K009
+ return(TRUE);
+
+#else // _R98_
+ if (InterfaceType != Isa && InterfaceType != Eisa && InterfaceType != Pci) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // There is only one I/O bus which is an EISA, so the bus number is unused.
+ //
+ // Determine the address based on whether the bus address is in I/O space
+ // or bus memory space.
+ //
+
+ if (*AddressSpace) {
+
+ //
+ // The address is in I/O space.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_CONTROL_PHYSICAL_BASE;
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ } else {
+
+ //
+ // The address is in memory space.
+ //
+
+ *AddressSpace = 0;
+
+#if !defined(_DUO_)
+
+ if (DMA_CONTROL->RevisionLevel.Long < 2) {
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_PHYSICAL_BASE;
+ } else {
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW;
+ TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH;
+
+ }
+#else
+
+ TranslatedAddress->LowPart = BusAddress.LowPart + EISA_MEMORY_VERSION2_LOW;
+ TranslatedAddress->HighPart = EISA_MEMORY_VERSION2_HIGH;
+
+#endif
+
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+ return(TRUE);
+
+ }
+
+#endif // _R98_
+}
+#endif //K015
+
+
+// K00-6
+// MapRegistersPerChannel,AdapterBaseVa,MapRegisterBase
+//--------------------+-----------------------+-------------+---------------+
+// Internal with S/G 0 0 -1
+// Internal no S/G 1 0 -1
+// Internal DMA 1 XX -1
+// Internal MasterAdp 1 -1 -1
+// EISA 0 XX 0
+// PCI 0 0 0
+// MasterAdp 0 -1 -1
+//
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system.
+
+Arguments:
+
+ MapRegistersPerChannel - Unused.
+
+ AdapterBaseVa - Base virtual address of the adapter itself. If AdapterBaseVa
+ is NULL then the MasterAdapterObject is allocated.
+
+ MapRegisterBase - If (PVOID) -1 then Not MasterAdapter allocate.
+
+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;
+ ULONG i; //K021-2
+ //
+ // Internal without Scatter/Gather or LR4360 DMA
+ // then allocate MasterAdapterObjectForInternal
+ //
+
+ if (MasterAdapterObjectForInternal == NULL && AdapterBaseVa !=(PVOID)-1
+ && MapRegistersPerChannel
+ ){
+
+ MasterAdapterObjectForInternal
+ = HalpAllocateAdapter(
+ 1,
+ (PVOID) -1,
+ (PVOID) -1
+ );
+
+ //
+ // If we could not allocate the master adapter For Internal then give up.
+ //
+
+ if (MasterAdapterObjectForInternal == NULL)
+ return(NULL);
+
+ }else if (MasterAdapterObject == NULL && MapRegisterBase !=(PVOID)-1) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ 0,
+ (PVOID)-1,
+ (PVOID)-1
+ );
+ //
+ // 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 == (PVOID)-1 && MapRegistersPerChannel) {
+ //
+ // MasterAdapterForInternal
+ //
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3);
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ }else if(AdapterBaseVa == (PVOID)-1 && MapRegistersPerChannel==0) {
+ //
+ // MasterAdapter
+ //
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ ((DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) + 7 >> 3))
+ + 3) & ~3);
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+ } else
+ //
+ // Not Master Adapter.(Have not Bit Map)
+ //
+ Size = sizeof( ADAPTER_OBJECT );
+
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject(
+ KernelMode,
+ *((POBJECT_TYPE *)IoAdapterObjectType),
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject
+ );
+ // This code is 612 base.
+ // 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 )) {
+
+ RtlZeroMemory (AdapterObject, sizeof (ADAPTER_OBJECT)); //K035
+
+ 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->AdapterBaseVa = AdapterBaseVa;
+ AdapterObject->PagePort = NULL;
+ //
+ // Set ->MasterAdapter
+ //
+
+ if(AdapterBaseVa == (PVOID)-1)
+ // I am
+ // Masteradpter or MasterAdapterForInternal.
+ //
+ AdapterObject->MasterAdapter = NULL;
+ else if(MapRegistersPerChannel)
+ // I am
+ // Bbus (LR4360 DMA)or ASOBus with No Scatter/Gather.
+ //
+ AdapterObject->MasterAdapter = MasterAdapterObjectForInternal;
+ else if(MapRegisterBase ==NULL){
+ //
+ // I am PCI or EISA or ISA.
+ //
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ // Limit was Set End of HalGetAdapter().
+ //AdapterObject->MapRegistersPerChannel =
+ // DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY);
+ //
+ }else
+ // I am
+ // Internal Device With Scatter/Gather.
+ //
+ 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 == (PVOID)-1){
+ //
+ // MasterAdapterObject and MasterAdapterObjectForInternal.
+ //
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+ AdapterObject->NumberOfMapRegisters = 0; //K012
+ if(MapRegistersPerChannel) {
+ //
+ // MasterAdapterObjectForInternal.
+ // (For Bbus LR4360 DMA and Internal Device without Scatter/Gather
+ // may be continuguas memory)
+ //
+ AdapterObject->MapRegistersPerChannel =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 );
+
+ // K012 AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase =
+ ExAllocatePool(
+ NonPagedPool,
+ (MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE) *
+ sizeof(INTERNAL_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(INTERNAL_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{
+ // Not use R98
+ //ULONG MapRegisterSize;
+ //
+ PULONG Map;
+ //
+ // Limit is This code.
+ // The Number of MapRegisters For PCI,EISA,ISA use LR4360 TLB.
+ //
+ AdapterObject->MapRegistersPerChannel =
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters))
+ + sizeof( RTL_BITMAP )),
+ DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)
+ );
+ RtlClearAllBits( AdapterObject->MapRegisters );
+
+ //
+ // The memory for the map registers was allocated by
+ // HalpAllocateMapRegisters during phase 0 initialization.
+ //
+ // On PCI,EISA,ISA Set Up LR4360TLB Mapping and
+ // PECB EISA->PCI Mapping.
+ //
+ //
+
+ // Not use R98
+ //MapRegisterSize = DMA_TRANSLATION_LIMIT;
+ //MapRegisterSize = ROUND_TO_PAGES(MapRegisterSize);
+
+ //
+ // Convert the physical address to a non-cached virtual address.
+ //
+ // HalpMapRegisterPhysicalBase is Set up HalpAllocateMapRegisters().
+ // area of KSEG1_BASE is 512M. So get less than Physical addr 512M
+ // by HalpAllocateMapRegisters().
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ (HalpMapRegisterPhysicalBase | KSEG0_BASE); //K026-1
+
+ // dummy page data is "CEN CEN CEN". for What happend!!. K028
+ RtlFillMemoryUlong( (PULONG)((HalpNec0DummyPhysicalBase) |KSEG0_BASE),
+ PAGE_SIZE,0x4E454320); // A002
+
+ RtlFillMemoryUlong( (PULONG)((HalpNec1DummyPhysicalBase) |KSEG0_BASE),
+ PAGE_SIZE,0x4E454e20); // A002
+ // LR4360 Page table Set DumyPhysicalBase.
+ // LR4360 Page Table Size is DMA_TRANSLATION_LIMIT. K028
+ // Set to InValid.
+ RtlFillMemoryUlong( AdapterObject->MapRegisterBase,
+#if defined(PTEINVALID) // S004 vvv
+ DMA_TRANSLATION_LIMIT,(HalpNec0DummyPhysicalBase | 0x1));
+#else
+ DMA_TRANSLATION_LIMIT,HalpNec0DummyPhysicalBase );
+#endif // S004 ^^^
+
+#if defined(DUMMYDMA) // K034 vvv
+ // 256 is Number of page teble entry per 1 TLB
+ // 1M Align Logical Last Page is DUMYY page for TLB FLush!!.
+ //
+ Map =AdapterObject->MapRegisterBase;
+ for(i=0;i<(DMA_TRANSLATION_LIMIT / sizeof( TRANSLATION_ENTRY)) / 256;i++){
+
+ RtlSetBits (
+ AdapterObject->MapRegisters,
+ 0xff+0x100*i,//1M*i-1 page. Start
+ 0x1 //1 page DUMMY
+ );
+ Map[i* 0x100+0xff] =HalpNec1DummyPhysicalBase;
+
+ }
+#else
+ // Reserved For PCEB PreFetch cycle Cause LR4360 TLB miss.
+ RtlSetBits (
+ AdapterObject->MapRegisters,
+ 0xfff, //0xFFFFFF
+ 0x1
+ );
+
+#endif // K034 ^^^
+ // 1M Low del
+ RtlSetBits (
+ AdapterObject->MapRegisters,
+ 0x0, //0x0
+ 0xff
+ );
+
+ // eisa vram del
+ RtlSetBits (
+ AdapterObject->MapRegisters,
+ 0xE00, //0xe00000
+ 0xff
+ );
+
+ // 16M Low del
+ RtlSetBits (
+ AdapterObject->MapRegisters,
+ 0xf00, //0xf00000
+ 0xff
+
+ );
+
+ //
+ // LR4360 TLB Set Up
+ // LR4360:PTBAR0
+ // ( Use 0M-4M-1 Logical address) K013
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->PTBAR0,
+ (ULONG)HalpMapRegisterPhysicalBase
+ );//K013-2,K016-2,K019-1
+
+ //
+ // LR4360:PTBAR1 ( Use 4M-8M-1 Logical address)
+ //
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->PTBAR1,
+ // K013
+ (ULONG)HalpMapRegisterPhysicalBase+PAGE_SIZE //K019-1
+ );
+
+ //
+ // LR4360:PTBAR2 ( Use 8M-12M-1 Logical address)
+ // K013
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->PTBAR2,
+ (ULONG)HalpMapRegisterPhysicalBase+PAGE_SIZE*2 //K019-1
+ );
+ //
+ // LR4360:PTBAR3 ( Use 12M-12M-1 Logical address)
+ // K013
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->PTBAR3,
+ (ULONG)HalpMapRegisterPhysicalBase+PAGE_SIZE*3 //K019-1
+ );
+
+ //
+ // LR4360:PTSZR (Set Page Table Size is 4K)
+ // K00D
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->PTSZR,
+ LR4360PTSZ4K << LR4360PTSZSHIFT
+ );
+
+ //
+ // LR4360:PABAR Logical addr start 0x00000000(0M)
+ // Logical addr end 0x00ffffff(16M-1)
+ //
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->PABAR,0x0);
+
+
+ //K021-2 Flush TLB all ,K0026-3
+ for (i = 0;i < 16; i++) { //K024
+
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->TFLR,i);
+ }
+
+
+#if 0 //snes 302
+
+ // K007, K00C, K013
+ // EISA-->PCI map 0M-16M
+ // PCEB MEMREGN[4:1]
+ //
+ WRITE_REGISTER_ULONG(
+ &((volatile PULONG )
+ (KSEG1_BASE|EISA_CONFIG_REGISTERS_MEMREGN))[0],
+ 0xff0000|0x00
+ );
+#endif
+ WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f);
+
+#if defined(DUMMYDMA) // K034 vvv
+ {
+ UCHAR adapterMode;
+ DMA_EXTENDED_MODE extendedMode;
+ PVOID adapterBaseVa;
+ PDMA1_CONTROL dmaControl;
+ //
+ // SetUp Ext Mode reg.
+ adapterBaseVa =
+ &((PEISA_CONTROL) HalpEisaControlBase)->Dma1ExtendedModePort;
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = 2; //2 is floppy
+ extendedMode.TimingMode = COMPATIBLITY_TIMING; //ISA compati
+ extendedMode.TransferSize = BY_BYTE_8_BITS; //8bit DMA
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ //
+ // SetUp Mode reg
+ dmaControl = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+ adapterMode=0;
+ ((PDMA_EISA_MODE) &adapterMode)->Channel = 2;
+ ((PDMA_EISA_MODE) &adapterMode)->RequestMode = BLOCK_REQUEST_MODE;
+ ((PDMA_EISA_MODE) &adapterMode)->AutoInitialize = 0;
+ //
+ // Determine the mode based on the transfer direction.
+ // Read From The Device. it is little first.
+
+// ((PDMA_EISA_MODE) &adapterMode)->TransferType = READ_TRANSFER;
+ // it is safety.
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = WRITE_TRANSFER;
+
+ //
+ // This request is for DMA controller 1
+ //
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+ KeInitializeSpinLock (&HalpIoMapSpinLock);
+
+ }
+
+#endif // K034 ^^^
+
+ } // MasterAdapterObject (For PCI,EISA,ISA)
+
+
+ } // MasterAdapterObject and MasterAdapterObjectForInternal.
+
+ } 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;
+ // K00E-8
+ // return (PADAPTER_OBJECT) NULL;
+}
+
+// K001-7
+//
+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;
+#if defined(DUMMYDMA)
+ ULONG i;
+ PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase;
+#endif
+ //
+ // 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.
+ //
+ //
+ // Internal Master Device with Scatter/Gather.
+ // Mapregister Not Used.
+ //
+ return;
+ }
+
+ if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){
+ //
+ // Internal Device without Scatter/Gather.
+ // Strip no scatter/gather flag.
+ //
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PINTERNAL_TRANSLATION_ENTRY) MapRegisterBase -
+ (PINTERNAL_TRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+ }else{
+ 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.
+ //
+
+#if defined(DUMMYDMA)
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ MasterAdapter == MasterAdapterObject ?
+ NumberOfMapRegisters+1 :NumberOfMapRegisters //K028
+ );
+ //
+ // LR4360 PTE InValid.
+ if(MasterAdapter==MasterAdapterObject){
+ for (i = 0; i < NumberOfMapRegisters+1; i++) {
+#if defined(PTEINVALID) // S004 vvv
+ (DmaMapRegister)->PageFrame = (HalpNec0DummyPhysicalBase | 0x1);
+#else
+ (DmaMapRegister)->PageFrame = HalpNec0DummyPhysicalBase;
+#endif // S004 ^^^
+ DmaMapRegister++;
+ }
+ }
+
+#else
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ MasterAdapter == MasterAdapterObject ?
+ NumberOfMapRegisters+1 :NumberOfMapRegisters //K028
+ );
+#endif
+ //
+ // 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->MasterAdapter == MasterAdapterObject ?
+ AdapterObject->NumberOfMapRegisters+1 : AdapterObject->NumberOfMapRegisters, //K028
+ 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 );
+
+ if (AdapterObject->MasterAdapter == MasterAdapterObjectForInternal){
+
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PINTERNAL_TRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ //
+ // Set the no scatter/gather flag.
+ // if there device Not Sactter/Gather
+ //
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }else{
+ // DbgPrint("\nIoFreeMapRegisters = 0x%x\n",MapRegisterNumber+1);
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber );//add1 non
+
+ }
+
+ //
+ // 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->MasterAdapter == MasterAdapterObject ?
+ AdapterObject->NumberOfMapRegisters+1 : AdapterObject->NumberOfMapRegisters //K028
+ );
+#if defined(DUMMYDMA)
+
+ if(MasterAdapter == MasterAdapterObject){
+ DmaMapRegister= (PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber;
+ for (i = 0; i < AdapterObject->NumberOfMapRegisters+1; i++) {
+#if defined(PTEINVALID) // S004 vvv
+ (DmaMapRegister)->PageFrame = (HalpNec0DummyPhysicalBase | 0x1);
+#else
+ (DmaMapRegister)->PageFrame = HalpNec0DummyPhysicalBase;
+#endif // S004 ^^^
+ DmaMapRegister++;
+ }
+ }
+
+#endif
+
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+}
+
+
+// K001-8
+//
+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;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+ ULONG Hint;
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL) {
+ MasterAdapter = AdapterObject->MasterAdapter;
+ } else {
+ MasterAdapter = AdapterObject;
+ }
+
+ //
+ // 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.
+ //
+ //
+ // CASE:
+ // Internal Master Device without Scatter/Gather.
+ // Internal Device with LR4360 DMA(Always without Scatter/Gather)
+ // PCI,EISA,ISA Device with LR4360 TLB.
+ //
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter!=NULL)
+ {
+ // K00D
+ // MasterAdapterObject??
+ //
+ if ( MasterAdapter== MasterAdapterObject)
+ //
+ // PCI,EISA,ISA Device with LR4360 TLB.
+ //
+ if (Wcb->NumberOfMapRegisters > MasterAdapter->MapRegistersPerChannel) {
+ KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS );
+ }
+
+ //
+ // 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,
+ MasterAdapter == MasterAdapterObject ?
+ Wcb->NumberOfMapRegisters+1:Wcb->NumberOfMapRegisters, //K028
+ 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 {
+ if (MasterAdapter == MasterAdapterObjectForInternal){
+ //
+ // Internal Device without Sactter/Gather.
+ //
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PINTERNAL_TRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }else{
+
+ //
+ // PCI,EISA,ISA with LR4360 TLB
+ //
+ AdapterObject->MapRegisterBase =
+ (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ }
+
+ }
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }else{
+ //
+ // Only Internal Master Device with Scatter/Gather.
+ // Always AdapterObject->MasterAdapter ==NULL.
+ //
+ 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;
+ }
+ }
+}
+
+// K001-9
+//
+VOID
+HalpAllocateMapRegisters(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates memory for map registers directly from the loader
+ block information. This memory must be non-cached and contiguous.
+
+Arguments:
+
+ LoaderBlock - Pointer to the loader block which contains the memory descriptors.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+ ULONG MapRegisterSize;
+
+ MapRegisterSize = PAGE_SIZE*2+DMA_TRANSLATION_LIMIT; //K028
+ MapRegisterSize = BYTES_TO_PAGES(MapRegisterSize);
+
+ //
+ // The address must be in KSEG 0.
+ //
+
+ //MaxPageAddress = (KSEG1_BASE >> PAGE_SHIFT) - 1 ;
+ // less than 512M.
+ MaxPageAddress = (0x20000000 >> PAGE_SHIFT) - 1 ; //K016
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= MapRegisterSize) &&
+ (Descriptor->BasePage + MapRegisterSize < MaxPageAddress)) {
+
+ PhysicalAddress = Descriptor->BasePage << PAGE_SHIFT;
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ Descriptor->BasePage += MapRegisterSize;
+ Descriptor->PageCount -= MapRegisterSize;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ //K028
+ //
+ // Save the map register base.
+ //
+
+ HalpNec0DummyPhysicalBase =PhysicalAddress;
+ HalpNec1DummyPhysicalBase =HalpNec0DummyPhysicalBase+PAGE_SIZE;
+ HalpMapRegisterPhysicalBase=HalpNec0DummyPhysicalBase+PAGE_SIZE*2;
+
+}
+
+#if defined(DUMMYDMA) // K034 vvv
+VOID
+HalpDummyTlbFlush(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This function programs the EISA DMA controller for a transfer.
+
+Arguments:
+
+ Adapter - Supplies the DMA adapter object to be programed. DUMMY DUMMY DUMMY DUMMY
+
+ Offset - Supplies the logical address to use for the transfer.
+
+ Length - Supplies the length of the transfer in bytes. DUMMY DUMMY DUMMY DUMMY
+
+ WriteToDevice - Indicates the direction of the transfer. DUMMY DUMMY DUMMY DUMMY
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ volatile UCHAR Status;
+// volatile UCHAR Mask;
+ UCHAR adapterMode;
+ PUCHAR PagePort;
+ PUCHAR BytePtr;
+ volatile PUCHAR BytePtr2;
+ volatile ULONG Count;
+ PDMA1_CONTROL dmaControl;
+// PDMA2_CONTROL dmaControl2;
+ BytePtr2 = (PUCHAR) &Count;
+ BytePtr = (PUCHAR) &Offset;
+ PagePort = &((PDMA_PAGE) 0)->Channel2;
+ dmaControl = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1BasePort;
+// dmaControl2 = (PVOID) &((PEISA_CONTROL) HalpEisaControlBase)->Dma2BasePort;
+
+// Mask=READ_REGISTER_UCHAR( &dmaControl2->AllMask );
+// WRITE_REGISTER_UCHAR( &dmaControl2->AllMask, (UCHAR) (0xf) );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+ WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseAddress,BytePtr[0] );
+ WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseAddress,BytePtr[1] );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageLowPort) +
+ (ULONG)PagePort,
+ BytePtr[2]
+ );
+
+ //
+ // Write the high page register with zero value. This enable a special mode
+ // which allows ties the page register and base count into a single 24 bit
+ // address register.
+ //
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->DmaPageHighPort) +
+ (ULONG)PagePort,
+ 0
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ // transfer Count is 1 Byte . So Set 1-1=0
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+ WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount,(UCHAR) 0x1);
+ WRITE_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount,(UCHAR) 0);
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1CountHigh[5]),
+ (UCHAR) 0
+ );
+
+
+ //Flush LR4360 Read Cache.
+ WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K031
+ //
+ // SoftWare DMA Request, channel 2
+ //
+ WRITE_REGISTER_UCHAR( &dmaControl->DmaRequest, (UCHAR) (0x4 | 0x2) );
+ //
+ // check dma transfer was finished!!.
+ //
+ do{
+ Count=0;
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+ BytePtr2[0]= READ_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount);
+ BytePtr2[1]= READ_REGISTER_UCHAR( &dmaControl->DmaAddressCount[2].DmaBaseCount);
+ BytePtr2[2]=
+ READ_REGISTER_UCHAR(
+ ((PUCHAR) &((PEISA_CONTROL) HalpEisaControlBase)->Dma1CountHigh[5])
+ );
+ if((Count & 0xffffff)== 0xffffff)
+ break;
+ }while(1);
+
+// WRITE_REGISTER_UCHAR( &dmaControl->DmaRequest, (UCHAR) (0x0 | 0x2) );
+// WRITE_REGISTER_UCHAR( &dmaControl2->AllMask, 0x0 );
+
+}
+
+#endif // K034 ^^^
+
+
+// K001-A
+//
+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 to be used by bus masters.
+
+--*/
+
+{
+#if defined(DUMMYDMA) // K034 vvv
+ KIRQL Irql;
+#endif // K034 ^^^
+ ULONG value;
+ //
+ // May be check Bus Master: AdapterObject==NULL!!.
+ // Internal Device:
+ // ASOBus with Scatter/Gather:MapRegisterBase ==NULL
+ // without Scatter/Gather always allocate MapRegister
+ // So check As if use MapRegister.
+ //
+ // ASOBus without Scatter/Gather:MapRegisterBase & NO_SCATTER_GATHER=1
+ // BBus without Scatter/Gather:MapRegisterBase & NO_SCATTER_GATHER=1
+ //
+ //
+ PTRANSLATION_ENTRY DmaMapRegister = MapRegisterBase;
+ PULONG PageFrameNumber;
+ ULONG NumberOfPages;
+ ULONG Offset;
+ ULONG i;
+ ULONG logicalAddress;
+ ULONG transferLength;
+ PINTERNAL_TRANSLATION_ENTRY translationEntry;
+ ULONG index; //K00D
+
+ //K00E-4
+ transferLength=PAGE_SIZE - BYTE_OFFSET((PUCHAR) CurrentVa );
+ Offset = BYTE_OFFSET( (PCHAR) CurrentVa - (PCHAR) Mdl->StartVa );
+ PageFrameNumber = (PULONG) (Mdl + 1);
+ PageFrameNumber += (((PCHAR) CurrentVa - (PCHAR) Mdl->StartVa) >> PAGE_SHIFT);
+ logicalAddress = (*PageFrameNumber << PAGE_SHIFT) + Offset;
+ //K00D
+ if((MapRegisterBase== NULL) || ((ULONG)MapRegisterBase & NO_SCATTER_GATHER) ){
+
+ // BusMaster with Scatter/gather || witout Scatter/Gather
+ //
+
+ while(transferLength < *Length ){
+
+ if (*PageFrameNumber + 1 != *(PageFrameNumber + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ PageFrameNumber++;
+ }
+
+ //
+ // Limit the transferLength to the requested Length.
+ //
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ //
+ // ASOBus Master without Scatter/Gather && contigous < request
+ // or
+ // Bbus Device Floppy use LR4360 DMA(it's not use Scatter/Gater) && contigous < request
+ //
+ //
+ if ( (ULONG)MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length ){
+
+ translationEntry = (PINTERNAL_TRANSLATION_ENTRY)
+ ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ logicalAddress = translationEntry->PhysicalAddress + Offset;
+ //
+ // It's means I have not Scatter/Gather && contigous < request then I use buffer
+ // At IoFlushAdapterBuffers() Do ?Hal Buffer-->user mem
+ //
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ // Do Copy So avaleable transfer is request size
+ transferLength = *Length;
+
+ // When Memory --> Device, Copy From memory to conigous buffer
+ //
+ if ( WriteToDevice)
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ *Length,
+ WriteToDevice
+ );
+ }
+
+ *Length=transferLength;
+ //
+ // ASOBus Master without Scatter/Gather. ||
+ // ASOBus Master with Scatter/Gather
+ //
+ // (Thus ASObus Master Don't use LR4360 DMA.)
+ //
+ if ( AdapterObject == NULL || MapRegisterBase ==NULL)
+ return(RtlConvertUlongToLargeInteger(logicalAddress));
+
+ //
+ // Bbus DMA used Device etc..Floppy
+ // Then Set Up LR4360 DMA Controlor
+ //
+
+ //K00F From HalGetAdapter()
+ // Flush LR4360 FiFo.
+ // Note: LR4360 DMA Set up Do Drain. So At this time
+ // FiFo have Never Data.....
+
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+ ((PLR_DMA_CONTROL)&value)->Reserved1=0;
+ ((PLR_DMA_CONTROL)&value)->FiFoF=1;
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+
+ //
+ // Sleep till CnDC->iNED =1 ??
+ //
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+
+ //K00D
+ if(((PLR_DMA_CONTROL)&value)->iNEDS){
+ //
+ // what sec to wait !!
+ // K00D N.B microsecond
+ KeStallExecutionProcessor(100);
+
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+ //
+ // the die .....
+ // K00D
+ if(((PLR_DMA_CONTROL)&value)->iNEDS)
+ KeBugCheck( INSUFFICIENT_SYSTEM_MAP_REGS );
+ }
+ //
+ // transfer count set
+ //K010-2
+ // N.B *Length must be below 0x03ffffff.(64M)
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnBC,
+ *Length
+ );
+ //
+ // transfer addr set
+ //
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnMA,
+ // K00D RtlConvertUlongToLargeInteger(logicalAddress)
+ logicalAddress
+ );
+ //
+ // direction set
+ //
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+ //K00D
+ ((PLR_DMA_CONTROL)&value)->Reserved1=0;
+ ((PLR_DMA_CONTROL)&value)->MEMWE=1;
+
+ if ( WriteToDevice) {
+ ((PLR_DMA_CONTROL)&value)->MEMWT=0;
+ //
+ // For End of DMA function .see HalpDmaInterrupt()
+ //
+ //
+ // Memory --> Device
+ //
+ //
+ // AdapterObject->TransferType = WRITE_TRANSFER;
+ //
+
+ }else{
+ ((PLR_DMA_CONTROL)&value)->MEMWT=1;
+ //
+ // Device --> Memory
+ //
+ // AdapterObject->TransferType = READ_TRANSFER;
+ //
+ }
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+ //
+ // Enable Input BREQ line
+ //
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+
+ ((PLR_DMA_CONTROL)&value)->Reserved1=0; //K00D
+
+ ((PLR_DMA_CONTROL)&value)->REQWE=1; //K00D
+ ((PLR_DMA_CONTROL)&value)->REQiE=1; //K00D
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+ //
+ // End of LR4360 DMA Set Up.
+ //
+ return(RtlConvertUlongToLargeInteger(logicalAddress));
+ }else{
+#if defined(DUMMYDMA) // K034 vvv
+ KeAcquireSpinLock(&HalpIoMapSpinLock,&Irql);
+#endif
+
+ //
+ // Determine the maximum number of pages required to satisfy this request.
+ //
+ NumberOfPages = (Offset + *Length + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+ //
+ // Set up phys addr in LR4360 Page table entry.
+ //
+ for (i = 0; i < NumberOfPages; i++) {
+ (DmaMapRegister++)->PageFrame = (ULONG) *PageFrameNumber++ << PAGE_SHIFT;
+ }
+
+ //
+ // PCI,EISA,ISA is used TLB of LR4360.
+ // So There is Inside Logical address Pci.
+ // K00D offset -->Offset
+ Offset += (
+ (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase
+ ) << PAGE_SHIFT;
+
+ // Not use LR4360 PTBA0 Register ( 0-4M)
+ //
+ // use only 4M-8M. !!!!
+ //
+ Offset += PCI_LOGICAL_START_ADDRESS;
+
+#if defined(DUMMYDMA) // K034
+ // If PTE is InValid. Set to DummyPage for PCEB Prefetch.
+ // else It was seted by another IoMapTransfer.
+#if defined(PTEINVALID) // S004 vvv
+ if((DmaMapRegister)->PageFrame & 0x1)
+ (DmaMapRegister)->PageFrame = HalpNec0DummyPhysicalBase;
+#endif // S004 ^^^
+
+
+ HalpDummyTlbFlush((PADAPTER_OBJECT)NULL,(Offset & 0x00f00000) | 0x000ff800,(ULONG)NULL,(BOOLEAN)NULL); // A002
+
+#else
+ //
+ // Flush Translation Look a Side Buffer.
+ // ( 1 Entry is 1M )
+ for (i = Offset >>20 ; i <= ((Offset+NumberOfPages*PAGE_SIZE)>>20); i++) {
+
+ WRITE_REGISTER_ULONG(
+ &LR_PCI_DEV_REG_CONTROL->TFLR,i);
+ }
+
+#endif // K034 ^^^
+ if ( AdapterObject != NULL) //K00D
+ //
+ // Set Up ESC DMA of EISA,ISA.
+ //
+ HalpEisaMapTransfer(
+ AdapterObject,
+ Offset,
+ *Length,
+ WriteToDevice
+ );
+ //
+ // BUS Master
+ // else PCI(always Master) or EISA,ISA Busmaster.
+ //
+ }
+#if defined(DUMMYDMA) // K034 vvv
+ KeReleaseSpinLock( &HalpIoMapSpinLock, Irql );
+#endif
+ return(RtlConvertUlongToLargeInteger(Offset));
+}
+
+//
+// K001-B
+//
+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 and 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 - If the transfer was successful.
+
+ FALSE - If there was an error in the transfer.
+
+--*/
+
+{
+ // case: Not use Mapregister.
+ // 1. Internal Master with Scatter/Gather. Never use Mapregiter.
+ // 2. Internal Master without Scatter/Gather But Not use Mapregister.
+ // When contigus buffer > request
+ // 3. Internal Slave with LR4360 DMA (Floppy)But Not use Mapregister.
+ // When contigus buffer > request
+ //
+ // Internal or external device and use Mapregister.
+ // Case:
+ // 4. Internal Master without Scatter/Gather use Mapregister.
+ // When contigus buffer <request (use copy buffer)
+ // 5. Internal Slave LR4360 DMA(Floppy)
+ // When contigus buffer <request (use copy buffer)
+ // 6. PCI,EISA,ISA Master Device is used Mapregister For LR4360
+ // TLB.(Page Table)
+ // 7. EISA,ISA Slave(ESC DMA) Device is used Mapregister For LR4360
+ // TLB.(Page Table)
+
+ ULONG DataWord;
+ ULONG Channel;
+ ULONG value;
+
+
+ PINTERNAL_TRANSLATION_ENTRY translationEntry;
+
+ ULONG i;
+ UCHAR DataByte;
+ //
+ //
+ if ( MapRegisterBase == NULL ) {
+
+ // Case:
+ // 1. Internal Master with Scatter/Gather. Never use Mapregiter.
+ // So MaregisterBase allways NULL
+ //if(AdapterObject == NULL )
+ //
+ //
+ //
+ return(TRUE);
+ }else{
+ //
+ // Case: 2,3,4,5,6,7
+ //
+ if(AdapterObject==NULL){
+ if( ((ULONG)MapRegisterBase & NO_SCATTER_GATHER) == 0){ //K00D,K017
+ WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K031
+ //
+ // Case: 6
+ //
+ return(TRUE);
+ }
+ }
+ }
+ //
+ // At This Point case is 2,3,4,5,7
+ //
+ //
+ if (AdapterObject->PagePort) {
+
+ WRITE_REGISTER_ULONG( 0xb8cba01c,0x0008000f); //K031
+
+
+ //
+ // case 7.
+ //
+ //
+ // If this is a master channel, then just return since the DMA
+ // request does not need to be disabled.
+ //
+
+ DataByte = AdapterObject->AdapterMode;
+
+ if (((PDMA_EISA_MODE) &DataByte)->RequestMode == CASCADE_REQUEST_MODE) {
+
+ return(TRUE);
+
+ }
+
+ //
+ // Clear the EISA DMA adapter.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_SETMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+ return(TRUE);
+ }
+
+ //
+ // At case 2,3,4,5
+ // ~ ~
+
+
+ if(AdapterObject != NULL){
+ // Master Device is allways NULL
+ //
+ // case 3,5 use LR4360 DMA
+ //
+ // this line it's may be HalpDmaInterrupt(). but it is not good that
+ // two End of DMA function (this func,and HalpDmaInterrupt()).
+ // Because Work at Interrupt from LR4360DMA is Not first (100%)
+ //
+
+ //
+ // Read CnDC register.
+ //
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+ // K00E-2
+ // Do Write then Reserved Bit must be 0.
+ //
+ ((PLR_DMA_CONTROL)&value)->Reserved1=0;
+ ((PLR_DMA_CONTROL)&value)->Reserved2=0;
+ //
+ // At Memory-->Device Do drain So Not FiFo flush !!.
+ //
+ //
+ // Device --> Memory
+ // K00D
+ if(!WriteToDevice){
+ if( ((PLR_DMA_CONTROL)&value)->FiFoV){
+ //
+ // FiFo have valid Data So Flush!!
+ // K00D
+ ((PLR_DMA_CONTROL)&value)->FiFoD=1;
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+
+ }
+ }
+ //
+ // iNEDS is clear by set 1 write
+ // K00D
+ ((PLR_DMA_CONTROL)&value)->iNEDS=1;
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+
+ }
+
+ //
+ // 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.
+
+ //
+ // Device --> Memory.
+ //
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PINTERNAL_TRANSLATION_ENTRY)
+ ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+ //
+ // case: 2,3,4,5
+ //
+ if (translationEntry->Index == COPY_BUFFER) {
+ //
+ // case: 4,5
+ //
+ if(AdapterObject != NULL)
+ //
+ // case: 5 used DMA
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ //
+ // case: 4,5
+ //
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ Length,
+ WriteToDevice
+ );
+ }
+ //else
+ //
+ // case: 2,3
+ // Not Used Copy Buffer then Nothing to Do. through !!.
+ //
+ //
+ // Strip no scatter/gather flag.
+ // K00D
+ }
+
+ }
+ translationEntry = (PINTERNAL_TRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+ //
+ // Clear index in map register.
+ //
+ translationEntry->Index = 0;
+ return( TRUE );
+}
+
+
+
+// K001-C
+//
+
+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);
+}
+
+// K001-D
+//
+//
+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.
+
+--*/
+
+{
+#if defined(DUMMYDMA)
+ KIRQL Irql;
+#endif
+ ULONG i;
+ ULONG saveEnable;
+ ULONG count;
+ ULONG high;
+
+ if (AdapterObject->PagePort) {
+ //
+ // PCI,EISA,ISA
+ //
+ //
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+#if defined(DUMMYDMA)
+ KeAcquireSpinLock(&HalpIoMapSpinLock,&Irql);
+#endif
+ 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_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_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_PORT_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_PORT_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_PORT_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;
+#if defined(DUMMYDMA)
+ KeReleaseSpinLock( &HalpIoMapSpinLock, Irql );
+#endif
+ } else {
+ //
+ // Internal Device With LR4360 DMA.
+ //
+ //
+ // read CnBC register.
+ //
+ count=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnBC
+ );
+
+ }
+
+ return(count);
+}
+
+
+//
+// K001-E
+// always return 1: See IoFlushAdapterBuffers()
+//
+BOOLEAN
+HalpDmaInterrupt(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is called when a DMA channel interrupt occurs.
+ LR4360 DMA
+Arguments:
+
+Return Value:
+
+ Returns TRUE.
+
+--*/
+{
+#if 0 //K011-2
+ return(TRUE);
+#else
+ PADAPTER_OBJECT AdapterObject;
+ ULONG DataWord;
+ ULONG Channel;
+ ULONG value;
+ //
+ // Read the Inerrupt Service Factor Register.
+ //
+
+ DataWord = READ_REGISTER_ULONG(&(LR_CONTROL2)->iRSF);
+
+ for (Channel = 0; Channel < 5; Channel++) {
+
+ //
+ // Determine which channel is interrupting.
+ //
+
+ if (!(DataWord & ( 1 << (Channel+LR_iRSF_REG_iNSF_SHIFT)))) {
+ continue;
+ }
+
+ //
+ // DMA Channel LR4360 is 1 origin.
+ //
+ if((AdapterObject=HalpInternalAdapters[Channel+1])==NULL){
+#if 0
+ DmaChannelMsg[18] = (CHAR) Channel+ '1';
+ HalDisplayString(DmaChannelMsg);
+#endif
+ //
+ //
+ //
+ KeBugCheck(NMI_HARDWARE_FAILURE);
+ }
+ //
+ // read CnDC register.
+ //
+ value=READ_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC
+ );
+ //
+ // At Memory-->Device drain So Don't FiFo flush.
+ //
+ //
+ // Device --> Memory
+ //
+ if( ((PLR_DMA_CONTROL)&value)->MEMWT==0){
+ if( ((PLR_DMA_CONTROL)&value)->FiFoV){
+
+ ((PLR_DMA_CONTROL)&value)->Reserved1=0;
+ ((PLR_DMA_CONTROL)&value)->Reserved2=0;
+ //
+ // FiFo Data is valid So Flush.
+ //
+ ((PLR_DMA_CONTROL)&value)->FiFoD=1;
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+
+ }
+ }
+ //
+ // iNEDS is clear by 1 write
+ // K00D
+ ((PLR_DMA_CONTROL)&value)->iNEDS=1;
+ WRITE_REGISTER_ULONG(
+ &(DMA_CONTROL (
+ (AdapterObject->ChannelNumber << LR_CHANNEL_SHIFT))
+ )->CnDC,
+ value
+ );
+ return(TRUE);
+ }
+#endif
+}
+
+// K001-F
+//
+//
+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;
+ PINTERNAL_TRANSLATION_ENTRY TranslationEntry ;
+ LONG NumberOfPages;
+ LONG i;
+
+ KIRQL Irql;
+ PHYSICAL_ADDRESS physicalAddress;
+ PVOID CodeLockHandle; //K035
+
+ 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.
+ //
+ CodeLockHandle = MmLockPagableCodeSection (&HalpGrowMapBuffers);
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql ); //K025
+
+ TranslationEntry = ((PINTERNAL_TRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ for (i = 0; (LONG)i < NumberOfPages; i++) { //K00D K035
+
+#if 1 // Enable K00E-7
+ //
+ // Use at R98: LR4360 DMA Not boundry 64K. But per Grow size is 64K incremnet!!.
+ //
+ //
+ // 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 )) {
+
+ //
+ // 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++;
+ }
+#endif
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PINTERNAL_TRANSLATION_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 );
+ MmUnlockPagableImageSection (CodeLockHandle); //K035
+ return(TRUE);
+}
+
+// K001-G
+//
+//
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PINTERNAL_TRANSLATION_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);
+
+ }
+
+}
+#if 0 //K023 move to r98int.s
+/* Start S002 */
+VOID
+HalpNmiHandler(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is call from ROM at NMI
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ // K022
+ // NMI was not happend!!.
+ //
+ HalpResetNmi();
+ //
+ // Cause EIF !!
+ //
+ WRITE_REGISTER_UCHAR(0xB9980100,0x00828000);
+ return;
+}
+#endif
+
+VOID
+HalpRegisterNmi(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine set NMI handler to nvRAM.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+// VOID (*funcAddr)();
+ ULONG funcAddr; // K00D
+ KIRQL OldIrql;
+ ENTRYLO SavedPte[2];
+ PNV_CONFIGURATION NvConfiguration;
+
+ //
+ // Get address of HalpNmiHandler
+ //
+
+ funcAddr = (ULONG)HalpNmiHandler; // K00D
+// funcAddr += (KSEG1_BASE - KSEG0_BASE); //K023
+
+ ASSERT( ((ULONG)&HalpNmiHandler >= KSEG0_BASE) &&
+ ((ULONG)&HalpNmiHandler < KSEG2_BASE) );
+
+ //
+ // Map the NVRAM into the address space of the current process.
+ //
+
+ OldIrql = HalpMapNvram(&SavedPte[0]);
+
+ NvConfiguration = (PNV_CONFIGURATION)NVRAM_MEMORY_BASE;
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[0],
+ (UCHAR)(funcAddr >> 24));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[1],
+ (UCHAR)((funcAddr >> 16) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[2],
+ (UCHAR)((funcAddr >> 8) & 0xFF));
+
+ WRITE_REGISTER_UCHAR(&NvConfiguration->NmiVector[3],
+ (UCHAR)(funcAddr & 0xFF));
+
+ //
+ // Unmap the NVRAM from the address space of the current process.
+ //
+
+ HalpUnmapNvram(&SavedPte[0], OldIrql);
+ return;
+}
+/* End S002 */
+
+#if 0 //K015
+//
+// K00D form halfxs/mips/jxhwsup.c
+//
+//
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Eisa bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ 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.
+
+--*/
+
+{
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ OBJECT_ATTRIBUTES BusObjectAttributes;
+ PWSTR EisaPath = L"\\Registry\\Machine\\Hardware\\Description\\System\\EisaAdapter";
+ PWSTR ConfigData = L"Configuration Data";
+ ANSI_STRING TmpString;
+ UCHAR BusString[] = "00";
+ UNICODE_STRING RootName, BusName;
+ UNICODE_STRING ConfigDataName;
+ NTSTATUS NtStatus;
+ PKEY_VALUE_FULL_INFORMATION ValueInformation;
+ PCM_FULL_RESOURCE_DESCRIPTOR Descriptor;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialResource;
+ PCM_EISA_SLOT_INFORMATION SlotInformation;
+ ULONG PartialCount;
+ ULONG TotalDataSize, SlotDataSize;
+ HANDLE EisaHandle, BusHandle;
+ ULONG BytesWritten, BytesNeeded;
+ PUCHAR KeyValueBuffer;
+ ULONG i;
+ ULONG DataLength = 0;
+ PUCHAR DataBuffer = Buffer;
+ BOOLEAN Found = FALSE;
+
+
+ RtlInitUnicodeString(
+ &RootName,
+ EisaPath
+ );
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &RootName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)NULL,
+ NULL
+ );
+
+ //
+ // Open the EISA root
+ //
+
+ NtStatus = ZwOpenKey(
+ &EisaHandle,
+ KEY_READ,
+ &ObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Open Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // Init bus number path
+ //
+
+ if (BusNumber > 99) {
+ return (0);
+ }
+
+ if (BusNumber > 9) {
+ BusString[0] += (UCHAR) (BusNumber/10);
+ BusString[1] += (UCHAR) (BusNumber % 10);
+ } else {
+ BusString[0] += (UCHAR) BusNumber;
+ BusString[1] = '\0';
+ }
+
+ RtlInitAnsiString(
+ &TmpString,
+ BusString
+ );
+
+ RtlAnsiStringToUnicodeString(
+ &BusName,
+ &TmpString,
+ TRUE
+ );
+
+
+ InitializeObjectAttributes(
+ &BusObjectAttributes,
+ &BusName,
+ OBJ_CASE_INSENSITIVE,
+ (HANDLE)EisaHandle,
+ NULL
+ );
+
+ //
+ // Open the EISA root + Bus Number
+ //
+
+ NtStatus = ZwOpenKey(
+ &BusHandle,
+ KEY_READ,
+ &BusObjectAttributes
+ );
+
+ if (!NT_SUCCESS(NtStatus)) {
+ KdPrint(("HAL: Opening Bus Number: Status = %x\n",NtStatus));
+ return(0);
+ }
+
+ //
+ // opening the configuration data. This first call tells us how
+ // much memory we need to allocate
+ //
+
+ RtlInitUnicodeString(
+ &ConfigDataName,
+ ConfigData
+ );
+
+ //
+ // This should fail. We need to make this call so we can
+ // get the actual size of the buffer to allocate.
+ //
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ 0,
+ &BytesNeeded
+ );
+
+ KeyValueBuffer = ExAllocatePool(
+ NonPagedPool,
+ BytesNeeded
+ );
+
+ if (KeyValueBuffer == NULL) {
+ KdPrint(("HAL: Cannot allocate Key Value Buffer\n"));
+ ZwClose(BusHandle);
+ return(0);
+ }
+
+ ValueInformation = (PKEY_VALUE_FULL_INFORMATION)KeyValueBuffer;
+
+ NtStatus = ZwQueryValueKey(
+ BusHandle,
+ &ConfigDataName,
+ KeyValueFullInformation,
+ ValueInformation,
+ BytesNeeded,
+ &BytesWritten
+ );
+
+
+ ZwClose(BusHandle);
+
+ if (!NT_SUCCESS(NtStatus) || ValueInformation->DataLength == 0) {
+ KdPrint(("HAL: Query Config Data: Status = %x\n",NtStatus));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+
+
+ //
+ // We get back a Full Resource Descriptor List
+ //
+
+ Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)((PUCHAR)ValueInformation +
+ ValueInformation->DataOffset);
+
+ PartialResource = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
+ &(Descriptor->PartialResourceList.PartialDescriptors);
+ PartialCount = Descriptor->PartialResourceList.Count;
+
+ for (i = 0; i < PartialCount; i++) {
+
+ //
+ // Do each partial Resource
+ //
+
+ switch (PartialResource->Type) {
+ case CmResourceTypeNull:
+ case CmResourceTypePort:
+ case CmResourceTypeInterrupt:
+ case CmResourceTypeMemory:
+ case CmResourceTypeDma:
+
+ //
+ // We dont care about these.
+ //
+
+ PartialResource++;
+
+ break;
+
+ case CmResourceTypeDeviceSpecific:
+
+ //
+ // Bingo!
+ //
+
+ TotalDataSize = PartialResource->u.DeviceSpecificData.DataSize;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)PartialResource +
+ sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+
+ while (((LONG)TotalDataSize) > 0) {
+
+ if (SlotInformation->ReturnCode == EISA_EMPTY_SLOT) {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION);
+
+ } else {
+
+ SlotDataSize = sizeof(CM_EISA_SLOT_INFORMATION) +
+ SlotInformation->NumberFunctions *
+ sizeof(CM_EISA_FUNCTION_INFORMATION);
+ }
+
+ if (SlotDataSize > TotalDataSize) {
+
+ //
+ // Something is wrong again
+ //
+
+ ExFreePool(KeyValueBuffer);
+ return(0);
+
+ }
+
+ if (SlotNumber != 0) {
+
+ SlotNumber--;
+
+ SlotInformation = (PCM_EISA_SLOT_INFORMATION)
+ ((PUCHAR)SlotInformation + SlotDataSize);
+
+ TotalDataSize -= SlotDataSize;
+
+ continue;
+
+ }
+
+ //
+ // This is our slot
+ //
+
+ Found = TRUE;
+ break;
+
+ }
+
+ //
+ // End loop
+ //
+
+ i = PartialCount;
+
+ break;
+
+ default:
+ KdPrint(("Bad Data in registry!\n"));
+ ExFreePool(KeyValueBuffer);
+ return(0);
+ }
+ }
+
+ if (Found) {
+
+ i = Length + Offset;
+ if (i > SlotDataSize) {
+ i = SlotDataSize;
+ }
+
+ DataLength = i - Offset;
+ RtlMoveMemory (Buffer, ((PUCHAR)SlotInformation + Offset), DataLength);
+
+ }
+
+ ExFreePool(KeyValueBuffer);
+ return DataLength;
+}
+
+ULONG
+HalGetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ switch (BusDataType) {
+ case EisaConfiguration:
+ DataLength = HalpReadEisaData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+ }
+
+ return(DataLength);
+
+}
+ULONG
+HalGetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalGetBusDataByOffset (
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+ULONG
+HalSetBusDataByOffset(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function sets the bus data for a slot or address.
+
+Arguments:
+
+ BusDataType - Supplies the type of bus.
+
+ BusNumber - Indicates which bus.
+
+ Buffer - Supplies the space to store the data.
+
+ Offset - Offset in the BusData buffer
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+
+{
+
+ ULONG DataLength = 0;
+
+ return(DataLength);
+}
+
+ULONG
+HalSetBusData(
+ IN BUS_DATA_TYPE BusDataType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ Subset of HalGetBusDataByOffset, just pass the request along.
+
+--*/
+{
+ return HalSetBusDataByOffset(
+ BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length
+ );
+}
+
+NTSTATUS
+HalAssignSlotResources (
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject OPTIONAL,
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources
+ )
+/*++
+
+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:
+
+ RegistryPath - Passed to IoAssignResources.
+ A device specific registry path in the current-control-set, used
+ to check for pre-assigned settings and to track various resource
+ assignment information for this device.
+
+ DriverClassName Used to report the assigned resources for the driver/device
+ DriverObject - Used to report the assigned resources for the driver/device
+ DeviceObject - Used to report the assigned resources for the driver/device
+ (ie, IoReportResoruceUsage)
+ BusType
+ BusNumber
+ SlotNumber - Together BusType,BusNumber,SlotNumber uniquely
+ indentify the device to be queried & set.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // This HAL doesn't support any buses which support
+ // HalAssignSlotResources
+ //
+
+ return STATUS_NOT_SUPPORTED;
+
+}
+
+NTSTATUS
+HalAdjustResourceList (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+/*++
+
+Routine Description:
+
+ Takes the pResourceList and limits any requested resource to
+ it's corrisponding bus requirements.
+
+Arguments:
+
+ pResourceList - The resource list to adjust.
+
+Return Value:
+
+ STATUS_SUCCESS or error
+
+--*/
+{
+ //
+ // BUGBUG: This function should verify that the resoruces fit
+ // the bus requirements - for now we will assume that the bus
+ // can support anything the device may ask for.
+ //
+
+ return STATUS_SUCCESS;
+}
+
+
+#endif //K015
diff --git a/private/ntos/nthals/halr98mp/mips/r98info.c b/private/ntos/nthals/halr98mp/mips/r98info.c
new file mode 100644
index 000000000..c574c0a6c
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98info.c
@@ -0,0 +1,99 @@
+#ident "@(#) NEC r98info.c 1.1 95/06/19 11:34:28"
+/*++
+
+Copyright (C) 1991-1995 Microsoft Corporation
+All rights reserved.
+
+Module Name:
+
+ ixinfo.c
+
+Abstract:
+
+Environment:
+
+ Kernel mode only.
+
+Revision History
+
+ A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ - Marge 807-halr98mp-ixinfo.h to 1050-halx86-r98info.h
+
+--*/
+
+
+#include "halp.h"
+
+NTSTATUS
+HalpQueryInstalledBusInformation (
+ OUT PVOID Buffer,
+ IN ULONG BufferLength,
+ OUT PULONG ReturnedLength
+ );
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HaliQuerySystemInformation)
+#pragma alloc_text(PAGE,HaliSetSystemInformation)
+#endif
+
+NTSTATUS
+HaliQuerySystemInformation(
+ IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ OUT PVOID Buffer,
+ OUT PULONG ReturnedLength
+ )
+{
+ NTSTATUS Status;
+ PVOID InternalBuffer;
+ ULONG Length;
+
+ PAGED_CODE();
+
+ Status = STATUS_SUCCESS;
+ *ReturnedLength = 0;
+ Length = 0;
+
+ switch (InformationClass) {
+ case HalInstalledBusInformation:
+ Status = HalpQueryInstalledBusInformation (
+ Buffer,
+ BufferSize,
+ ReturnedLength
+ );
+ 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 HAL_SET_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN PVOID Buffer
+ )
+{
+ PAGED_CODE();
+ return STATUS_INVALID_LEVEL;
+}
+
+
diff --git a/private/ntos/nthals/halr98mp/mips/r98int.s b/private/ntos/nthals/halr98mp/mips/r98int.s
new file mode 100644
index 000000000..d5d05d25d
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98int.s
@@ -0,0 +1,522 @@
+// "@(#) NEC r98int.s 1.14 95/06/19 11:35:43"
+// TITLE("Interrupts service routine")
+//++
+//
+// Copyright (c) 1994 Kobe NEC Software
+//
+// Module Name:
+//
+// r98int.s
+//
+// Abstract:
+//
+//
+// Author:
+//
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+// S001 '94.6/03 T.Samezima
+//
+// Del iRSF interrupt clear
+//
+//**************************************************************
+//
+// S002 94.6/13 T.Samezima
+//
+// Del Compile err
+//
+//**************************************************************
+//
+// S003 94.7/15 T.Samezima
+//
+// Chg change register access from 8byte access to 4byte access
+//
+//**************************************************************
+//
+// S004 94.7/20 T.Samezima
+//
+// Del Compile err
+// K001 94/10/11 N.Kugimoto
+// Add.chg HalpNmiHandler() from r98hwsup.c and chg
+//
+// S005 94/01/15 T.Samezima
+// Add HalpReadPhysicalAddr()
+//
+// S006 94/01/24 T.Samezima
+// Add HalpWritePhysicalAddr(),HalpReadAndWritePhysicalAddr(),
+//
+// S007 94/03/10-17 T.Samezima
+// Chg HalpNMIHandler().
+//
+// A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+// - resolve compile error or logic error?
+//--
+
+#include "halmips.h"
+#include "r98def.h"
+
+
+ SBTTL("Timer Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is enterd as the result of an timer interrupt.
+//
+// Argments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpTimerDispatch)
+
+ move a0,s8
+ j HalpTimerScDispatch
+
+ .end HalpTimerDispatch
+
+
+ SBTTL("Read Large Register")
+//++
+//
+// Routine Description:
+//
+// This routine is read of large register
+//
+// Argments:
+//
+// a0 - Virtual address
+//
+// a1 - pointer to buffer of upper 32bit large register
+//
+// a2 - pointer to buffer of lower 32bit large register
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpReadLargeRegister)
+
+// Start S003
+#if 0
+ DISABLE_INTERRUPTS(t7) // disable interrupts
+
+ mfc1 t0,f0 // save f0 register
+ mfc1 t1,f1 // save f1 register
+
+ ldc1 f0,0x0(a0) // read register
+ mfc1 t2,f0 // get register(upper)
+ mfc1 t3,f1 // get register(lower)
+#endif
+
+ lw t2,0x0(a0) // get register(upper)
+ lw t3,0x4(a0) // get register(lower)
+
+ sw t2,0x0(a1) // set upper register value
+ sw t3,0x0(a2) // set lower register value
+
+#if 0
+ mtc1 t0,f0 // restore f0 register
+ mtc1 t1,f1 // restore f1 register
+
+ sync //
+
+ ENABLE_INTERRUPTS(t7) // enable interrupts
+#endif
+// End S003
+ j ra // return
+
+ .end HalpReadLargeRegister
+
+
+
+ SBTTL("Write Large Register")
+//++
+//
+// Routine Description:
+//
+// This routine is write of large register
+//
+// Argments:
+//
+// a0 - Virtual address
+//
+// a1 - pointer to value of upper 32bit of large register
+//
+// a2 - pointer to value of lower 32bit of large register
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpWriteLargeRegister)
+
+// Start S003
+#if 0
+ DISABLE_INTERRUPTS(t7) // disable interrupts
+
+ mfc1 t0,f0 // save f0 register
+ mfc1 t1,f1 // save f1 register
+#endif
+
+ lw t2,0x0(a1) // load upper register value
+ lw t3,0x0(a2) // load lower register value
+
+ sw t2,0x0(a0) // set upper register value
+ sw t3,0x4(a0) // set lower register value
+
+#if 0
+ mtc1 t2,f0 // set register(upper)
+ mtc1 t3,f1 // set register(lower)
+ sdc1 f0,0x0(a0) // write register
+
+ mtc1 t0,f0 // restore f0 register
+ mtc1 t1,f1 // restore f1 register
+#endif
+
+ sync //
+
+// ENABLE_INTERRUPTS(t7) // enable interrupts
+// End S003
+
+ j ra // return
+
+ .end HalpWriteLargeRegister
+
+
+ SBTTL("Read Cause Register")
+//++
+// S005
+// Routine Description:
+//
+// This routine is get of cause register
+//
+// Argments:
+//
+// None.
+//
+// Return Value:
+//
+// cause rezister value.
+//
+//--
+
+ LEAF_ENTRY(HalpGetCause)
+
+ READ_CAUSE_REGISTER(v0)
+
+ j ra // return
+
+ .end HalpGetCause
+
+
+// S005 vvv
+ SBTTL("Read Physical Address")
+//++
+//
+// Routine Description:
+//
+// This routine is read of physical address.
+//
+// Argments:
+//
+// a0 - Physical address
+//
+// Return Value:
+//
+// read data.
+//
+//--
+
+ LEAF_ENTRY(HalpReadPhysicalAddr)
+
+ li t1,0x90000000
+
+ .set noreorder
+ .set noat
+ li t6,1 << PSR_CU1 // disable interrupt
+ ori t6,t6,1 << PSR_KX // use 64bit address mode
+ mfc0 t7,psr //
+ mtc0 t6,psr //
+ nop
+ nop
+ .set at
+ .set reorder
+
+ and t0,zero,zero
+ dsll t0,t1,32 // shift entry address to upper 32-bits
+ or t0,t0,a0 // make access address
+ lw v0,0(t0)
+
+ .set noreorder
+ .set noat
+ mtc0 t7,psr // enable interrupt
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadPhysicalAddress
+// S005 ^^^
+// S006 vvv
+ SBTTL("Write Physical Address")
+//++
+//
+// Routine Description:
+//
+// This routine is Write of physical address.
+//
+// Argments:
+//
+// a0 - Physical address
+//
+// a1 - Write Data
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpWritePhysicalAddr)
+
+ li t1,0x90000000
+
+ .set noreorder
+ .set noat
+ li t6,1 << PSR_CU1 // disable interrupt
+ ori t6,t6,1 << PSR_KX // use 64bit address mode
+ mfc0 t7,psr //
+ mtc0 t6,psr //
+ nop
+ nop
+ .set at
+ .set reorder
+
+ and t0,zero,zero
+ dsll t0,t1,32 // shift entry address to upper 32-bits
+ or t0,t0,a0 // make access address
+ sw a1,0(t0)
+
+ .set noreorder
+ .set noat
+ mtc0 t7,psr // enable interrupt
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpWritePhysicalAddress
+
+
+ SBTTL("Read And Write Physical Address")
+//++
+//
+// Routine Description:
+//
+// This routine is read and write of physical address.
+//
+// Argments:
+//
+// a0 - Physical address
+//
+// Return Value:
+//
+// read data.
+//
+//--
+
+ LEAF_ENTRY(HalpReadAndWritePhysicalAddr)
+
+ li t1,0x90000000
+
+ .set noreorder
+ .set noat
+ li t6,1 << PSR_CU1 // disable interrupt
+ ori t6,t6,1 << PSR_KX // use 64bit address mode
+ mfc0 t7,psr //
+ mtc0 t6,psr //
+ nop
+ nop
+ .set at
+ .set reorder
+
+ and t0,zero,zero
+ dsll t0,t1,32 // shift entry address to upper 32-bits
+ or t0,t0,a0 // make access address
+ lw v0,0(t0)
+ sw v0,0(t0)
+
+ .set noreorder
+ .set noat
+ mtc0 t7,psr // enable interrupt
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpReadAndWritePhysicalAddress
+// S006 ^^^
+
+ SBTTL("HalpNmiHandler")
+//++
+// K001
+// Routine Description:
+//
+// This routine is reset status Register on NMI.
+// Return from this function EIF Interrupt Occur!!
+// Argments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpNmiHandler)
+ .set noat
+
+// S007 vvv
+ //
+ // reset NMIR register, set NMI flag and save CPU register.
+ //
+
+ li k0,0xb9980308 // Set STSR address
+ li k1,0x08080000 // Disable NMI
+ sw k1,0x0(k0) //
+
+ la k0,HalpNMIFlag // set NMI flag address
+// li k1,0xa0000000 // KSEG1_ACCESS
+// or k0,k0,k1 //
+ li k1,0xb9980030 // set NMIR address
+ lw k1,(k1) // get NMIR register
+ addi k1,k1,1 // set NMI flag
+ sw k1,(k0) //
+
+ li k1,0xb8c80000 // Reset NMI
+ sb zero,0x0(k1) //
+
+#if 1
+// lw k0,KiPcr + PcPrcb(zero) // get current processor block address
+// la k1,HalpNMIBuf // get performance counter address
+// lbu k0,PbNumber(k0) // get processor number
+// sll k0,k0,7 // compute address of nmi buffer
+// addu k0,k0,k1 //
+
+ li k0,0xb9980300 // get CNFG Register Addr of PMC
+ li k1,0x00007000 // Mask Node Of CPU0-CPU3
+ lw k0 ,0x0(k0) // get value of etc of PMC
+ and k0,k0,k1 // get value of NODE
+ la k1,HalpNMIBuf // get performance counter address
+ srl k0,k0,5 // shift right 7 bit for offset
+ addu k0,k0,k1 // compute address of nmi buffer
+
+// sw at,0x0(k0) // register save.
+ sw v0,0x4(k0) //
+ sw v1,0x8(k0) //
+ sw a0,0xc(k0) //
+ sw a1,0x10(k0) //
+ sw a2,0x14(k0) //
+ sw a3,0x18(k0) //
+ sw t0,0x1c(k0) //
+ sw t1,0x20(k0) //
+ sw t2,0x24(k0) //
+ sw t3,0x28(k0) //
+ sw t4,0x2c(k0) //
+ sw t5,0x30(k0) //
+ sw t6,0x34(k0) //
+ sw t7,0x38(k0) //
+ sw t8,0x3c(k0) //
+ sw t9,0x40(k0) //
+ sw gp,0x44(k0) //
+ sw sp,0x48(k0) //
+ sw s8,0x4c(k0) //
+ sw ra,0x50(k0) //
+
+ .set noreorder
+
+ mfc0 k1,psr //
+ sw k1,0x54(k0) //
+ mfc0 k1,cause //
+ sw k1,0x58(k0) //
+ mfc0 k1,epc //
+ sw k1,0x5c(k0) //
+ mfc0 k1,errorepc //
+ sw k1,0x60(k0) //
+
+ .set reorder
+
+#endif
+
+ li k0,0xb9980038 // set NMIRST address
+ li k1,0x8 // it is DUMP Key NMI
+ sw k1,(k0) // reset nmi
+ .set noreorder // A002
+ nop
+//
+// This is a test code.
+// We must clear BEV bit of psr register.
+//
+
+ mfc0 k1,psr // get psr
+ li k0,0xffafffff // BEV bit clear
+ nop // fill
+ and k1,k1,k0 //
+ nop //
+ mtc0 k1,psr // set psr
+ nop // fill
+ nop //
+ nop //
+
+// li k0,0xb9980308 // Read STSR Register
+// lw k1,(k0) //
+// or k1,k1,0x80800000// make eif
+// sw k1,(k0) //
+// nop
+
+ li k0,0xb9980100 // IntIR Register addr
+ li k1,0x0082f000 // Do eif to CPU0 only.
+ sw k1,(k0) //
+
+ nop
+ eret // return to errorepc
+ nop
+ nop
+ nop
+ eret // errata
+ nop
+#if 0
+ mfc0 k0,epc // As if behave No Nmi
+ nop
+ nop
+ j k0 // As if behave No Nmi.
+#endif // I Hope EIF Interrut
+ // Occur later!!.
+ //
+// S007 ^^^
+
+ .set at
+ .set reorder
+
+
+ .end HalpNmiHandler
+
diff --git a/private/ntos/nthals/halr98mp/mips/r98ipint.s b/private/ntos/nthals/halr98mp/mips/r98ipint.s
new file mode 100644
index 000000000..b6176b490
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98ipint.s
@@ -0,0 +1,176 @@
+// "@(#) NEC r98ipint.s 1.5 94/10/11 23:04:02"
+// TITLE("Interprocessor Interrupts")
+//++
+//
+//
+// Module Name:
+//
+// r98ipint.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interprocessor interrupts on a r98
+//
+// Author:
+//
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//
+// S001 94.6/13 T.Samezima
+//
+// Del Compile err
+//
+// S002 94.7/14 T.Samezima
+//
+// Chg define register base address
+// change register access from 8byte access to 4byte access
+//
+// S003 94.7/20 T.Samezima
+//
+// Del Compile err del
+//
+// S004 94.10/11 T.Samezima
+//
+// Fix Version Up at build807
+//
+//
+//--
+
+#include "halmips.h"
+#include "r98def.h"
+//#include "r98reg.h" // S001
+
+// Start S002
+//
+// Define interrupt control registers base
+//
+
+#define PMC_BASE PMC_PHYSICAL_BASE1+PMC_LOCAL_OFFSET+KSEG1_BASE
+// End S002
+
+
+ SBTTL("Interprocessor Interrupt")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interprocessor interrupt.
+// Its function is to acknowledge the interrupt and transfer control to
+// the standard system routine to process interprocessor requrests.
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .struct 0
+IiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+IiRa: .space 4 // saved return address
+IiFrameLength: //
+
+ NESTED_ENTRY(HalpIpiInterrupt, IiFrameLength, zero)
+
+ subu sp,sp,IiFrameLength // allocate stack frame
+ sw ra,IiRa(sp) // save return address
+
+ PROLOGUE_END
+
+// Start S002
+// mfc1 t5,f0 // save f0 register
+// sw t5,IiF0(sp) //
+// mfc1 t6,f1 // save f1 register
+// sw t6,IiF1(sp) //
+// End S002
+
+ li t7,PMC_BASE // get register address // S002
+
+// Start S002
+ lw t0,0x0(t7) // get upper 32bit of IPR register
+
+// ldc1 f0,0x0(t7) // read IPR register
+// mfc1 t0,f0 // get upper 32bit of IPR register
+
+10: lw t1,0x8(t7) // get upper 32bit of MKR register
+
+// ldc1 f0,0x8(t7) // read MKR register
+// mfc1 t1,f0 // get upper 32bit of MKR register
+// End S002
+
+ and t1,t0,t1 // calculate upper 32bit of 'IPR & MKR'
+ andi t2,t1,IPR_IPI0_BIT_HIGH // check IPI0 bit
+ bne t2,zero,20f // if not eq, ip interrupt from processor0
+ andi t2,t1,IPR_IPI1_BIT_HIGH // check IPI1 bit
+ bne t2,zero,20f // if not eq, ip interrupt from processor1
+ andi t2,t1,IPR_IPI2_BIT_HIGH // check IPI2 bit
+ bne t2,zero,20f // if not eq, ip interrupt from processor2
+ andi t2,t1,IPR_IPI3_BIT_HIGH // check IPI3 bit
+ bne t2,zero,20f // if not eq, ip interrupt from processor3
+
+//
+// Unknown interrupt.
+//
+
+ li t4,MKR_INT4_ENABLE_HIGH // make argument
+ and a0,t1,t4 //
+ and a1,zero,a1 //
+ jal HalpUnknownInterrupt // call unknown interrupt handler
+ b 30f
+
+//
+// Interprocessor interrupt.
+//
+
+// Start S002
+20: sw t2,0x10(t7) // set IPRR register
+ sw zero,0x14(t7) //
+
+// mtc1 t2,f0 // set IPRR register
+// mtc1 zero,f1 //
+// sdc1 f0,0x10(t7) //
+// End S002
+
+ lw t1,__imp_KeIpiInterrupt // process interprocessor requests // S004
+ jal t1 // // S004
+
+//
+// check other interrupt.
+//
+
+30: li t7,PMC_BASE // get register address // S002
+// Start S002
+ lw t0,0x0(t7) // get upper 32bit of IPR register
+// ldc1 f0,0x0(t7) // read IPR register
+// mfc1 t0,f0 // get upper 32bit of IPR register
+// End S002
+ andi t1,t0,MKR_INT4_ENABLE_HIGH // check interrupt of int4 level
+ bne t1,zero,10b // if neq, occur new interrupt.
+
+ READ_CAUSE_REGISTER(t2) // get cause // S002
+
+ andi t3,t2,1 << (CAUSE_INTPEND + IPI_LEVEL - 1 ) // check interrupt
+ bne t3,zero,30b // if neq, check new interrupt
+
+// Start S003
+// lw t0,IiF0(sp) // restore f0 register
+// mtc1 t0,f0 //
+// lw t1,IiF1(sp) // restore f1 register
+// mtc1 t1,f1 //
+// End S003
+
+ lw ra,IiRa(sp) // save return address
+ addu sp,sp,IiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpIpiInterrupt
diff --git a/private/ntos/nthals/halr98mp/mips/r98led.c b/private/ntos/nthals/halr98mp/mips/r98led.c
new file mode 100644
index 000000000..219d3abd9
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98led.c
@@ -0,0 +1,252 @@
+#ident "@(#) NEC r98led.c 1.5 95/06/19 11:36:14"
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ r98led.c
+
+Abstract:
+
+ This module implements the Led output routines for R98
+
+Author:
+
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ S001 9/26/94 By T.Samezima
+
+ Add Debug Print
+ A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ - resolve compile error.
+
+--*/
+
+#include "halp.h"
+
+//
+// Set table size
+//
+#define SEGMENT_TABLE_SIZE 16
+
+//
+// Define spin lock
+//
+KSPIN_LOCK HalpLedLock;
+
+//
+// Define flag of initialize led
+//
+ULONG HalpLedInitFlg = 0;
+
+//
+// Buffer of output data at port
+//
+UCHAR HalpSegmentDisplayData[4] = { 0, 0, 0, 0 };
+
+//
+// Define character table
+//
+UCHAR HalpSegmentCharTableL[] = "0123456789abcdef";
+UCHAR HalpSegmentCharTableU[] = "0123456789ABCDEF";
+
+//
+// Define table of change from output character data to output port data
+//
+UCHAR HalpSegmentPatternTable[] = { 0xfa, 0x30, 0xdc, 0x7c, //0-3
+ 0x36, 0x6e, 0xee, 0x3a, //4-7
+ 0xfe, 0x7e, 0xfc, 0xe6, //8-b
+ 0xc4, 0xf4, 0xce, 0x8e, //c-f
+ 0x04 }; //err
+
+
+VOID
+HalpOutputSegment(
+ IN ULONG Number,
+ IN UCHAR Data
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is output a character data in led segment.
+
+Arguments:
+
+ Number - Segment number(range 0-3.)
+
+ Data - Output data on port.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ ULONG lednumber;
+
+ //
+ // Get segment number.
+ //
+
+ lednumber = Number & 0x3;
+
+ if(HalpLedInitFlg == 0){
+ KeInitializeSpinLock(&HalpLedLock);
+ HalpLedInitFlg = 1;
+ }
+
+ KiAcquireSpinLock(&HalpLedLock);
+
+ //
+ // Display data.
+ //
+
+ HalpSegmentDisplayData[Number] = Data;
+
+ WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData3,
+ HalpSegmentDisplayData[3] );
+ WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData2,
+ HalpSegmentDisplayData[2] );
+ WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData1,
+ HalpSegmentDisplayData[1] );
+ WRITE_REGISTER_UCHAR( &MRC_CONTROL->LedData0,
+ HalpSegmentDisplayData[0] );
+
+ KiReleaseSpinLock(&HalpLedLock);
+
+ return;
+}
+
+VOID
+HalpDisplaySegment(
+ IN ULONG Number,
+ IN UCHAR Data
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is display a character in led segment.
+
+Arguments:
+
+ Number - Segment number(range 0-3.)
+
+ Data - Output data character on port.
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ ULONG counter;
+
+ //
+ // Search character data.
+ //
+
+ for( counter=0 ; counter<SEGMENT_TABLE_SIZE ; counter++ ) {
+ if( ( Data == HalpSegmentCharTableL[counter])
+ | ( Data == HalpSegmentCharTableU[counter]) ) {
+ break;
+ }
+ }
+
+ HalpOutputSegment( Number, HalpSegmentPatternTable[counter]);
+ return;
+}
+
+// Start S001
+#if 1
+
+#include "stdarg.h"
+#include "stdio.h"
+
+#define DBG_SERIAL 0x0001 // For Debugger
+#define DBG_COLOR 0x0002 // For Display
+#define DBG_LED 0x0004 // For Led
+ULONG R98DebugLevel=8;
+ULONG DebugOutput = (DBG_LED | DBG_SERIAL);
+//ULONG DebugOutput = (DBG_LED | DBG_COLOR | DBG_SERIAL);
+//ULONG DebugOutput = (DBG_LED | DBG_COLOR);
+//ULONG DebugOutput = (DBG_LED);
+
+
+// caller
+// R98DbgPrint((1,"1234","\n\nI'm Here : value is =%d\n",value));
+//
+//
+
+VOID
+R98DebugOutPut(
+ ULONG DebugPrintLevel, // Debug Level
+ PCSZ DebugMessageLed, // For LED strings. shuld be 4Byte.
+ PCSZ DebugMessage, // For DISPLAY or SIO
+ ...
+ )
+
+/*++
+
+Routine Description:
+
+ Debug print routine.
+
+Arguments:
+
+ Debug print level between 0,and 3, with 3 being the most verbose.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ va_list ap;
+ char *p,LedNumber;
+ CHAR buffer[128];
+
+ if (DebugPrintLevel >= R98DebugLevel) {
+ if (DebugOutput & DBG_LED) {
+ // Message is "1-a-f"
+ for(p=(char *)DebugMessageLed,LedNumber=0; LedNumber<4;p++,LedNumber++) // A002
+ HalpDisplaySegment(LedNumber,*p);
+ }
+
+ // sdk/inc/crt/stdarg.h
+ va_start(ap, DebugMessage);
+
+ // stdlib ?? (sdk/inc/crt/stdio.h)
+ (VOID) vsprintf(buffer, DebugMessage, ap);
+
+ //
+ if (DebugOutput & DBG_SERIAL) {
+ DbgPrint(buffer);
+ }
+
+ // Console =Vram Write
+ //
+ if (DebugOutput & DBG_COLOR) {
+ HalDisplayString(buffer);
+ }
+
+ }
+
+ va_end(ap);
+
+}
+#endif
+// End S001
diff --git a/private/ntos/nthals/halr98mp/mips/r98pci.c b/private/ntos/nthals/halr98mp/mips/r98pci.c
new file mode 100644
index 000000000..64703837d
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98pci.c
@@ -0,0 +1,289 @@
+#ident "@(#) NEC r98pci.c 1.8 95/01/11 22:30:24"
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ r98pci.c
+
+Abstract:
+
+ This module implements the pci bus support routine for R98
+
+Author:
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ S001 94.7/20 T.Samezima
+ Chg Del compile err
+
+ S002 '94.10/14 T.Samezima
+ Add Set PCI bus interrupt affinity.
+
+ S003 '94.10/24 T.Samezima
+ Add Error register read and print.
+
+ S004 '94.12/07 T.Samezima
+ Add Error register read and print.
+
+ S005 '94.01/11 T.Samezima
+ Del del werning.
+
+--*/
+
+#include "halp.h"
+#include "stdio.h" // S005
+
+//
+// Enable PCI count
+//
+
+ULONG HalpEnablePCIInterruptCount;
+
+// Start S002
+// Define PCI bus interrupt affinity.
+//
+
+KAFFINITY HalpPCIBusAffinity;
+// End S002
+
+// S001
+BOOLEAN
+HalpPCIDispatch( // S001
+ IN PKINTERRUPT Interrupt
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is entered as the result of PCI err interrupt.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt function address.
+
+Return Value:
+
+
+--*/
+
+{
+ // S003 vvv
+ // S004 vvv
+ ULONG errsBuffer;
+ ULONG pearBuffer;
+ ULONG aearBuffer;
+ UCHAR messageBuffer[256];
+
+ errsBuffer = READ_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS );
+ pearBuffer = READ_REGISTER_ULONG( &( LR_PCI_DEV_REG_CONTROL )->PEAR );
+ aearBuffer = READ_REGISTER_ULONG( &( LR_PCI_DEV_REG_CONTROL )->AEAR );
+
+ if ( errsBuffer & 0x80000000 ) {
+ sprintf( (char *)messageBuffer,
+ "PCI Bus: Master Abort: PEAR=0x%08lX\n",
+ pearBuffer
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if ( errsBuffer & 0x40000000 ) {
+ sprintf( (char *)messageBuffer,
+ "PCI Bus: Target Abort: PEAR=0x%08lX\n",
+ pearBuffer
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if ( errsBuffer & 0x20000000 ) {
+ sprintf( (char *)messageBuffer,
+ "PCI Bus: System error\n"
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if ( errsBuffer & 0x10000000 ) {
+ sprintf( (char *)messageBuffer,
+ "PCI Bus: Parity error\n"
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+
+ if ( errsBuffer & 0x08000000 ) {
+ sprintf( (char *)messageBuffer,
+ "Page fault in NA Bus master transaction\n"
+ " ERRS=0x%08lX, AEAR=0x%08lX\n",
+ errsBuffer,
+ aearBuffer
+ );
+ HalDisplayString( (char *)messageBuffer );
+ KdPrint(( (char *)messageBuffer ));
+ }
+ // S004 ^^^
+
+ KeBugCheckEx(DATA_BUS_ERROR,
+ READ_REGISTER_ULONG( &( LR_CONTROL1 )->ERRS ),
+ READ_REGISTER_ULONG( &( LR_PCI_DEV_REG_CONTROL )->PEAR ),
+ READ_REGISTER_ULONG( &( LR_PCI_DEV_REG_CONTROL )->AEAR ),
+ 0 );
+ // S003 ^^^
+
+ return TRUE;
+}
+
+
+BOOLEAN
+HalpCreatePciStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for PCI operations
+ and connects the intermediate interrupt dispatcher.
+
+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.
+
+--*/
+
+{
+ //
+ // Initialize the interrupt dispatcher for PCI err interrupts.
+ //
+
+ PCR->InterruptRoutine[PCI_ERR_VECTOR] = (PKINTERRUPT_ROUTINE) HalpPCIDispatch;
+
+ // Start S002
+ // Set PCI bus interrupt affinity.
+ //
+
+ HalpPCIBusAffinity = PCR->SetMember;
+ // End S002
+
+ //
+ // Enable PCI err interrupt
+ //
+
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ HalpBuiltinInterruptEnable |= iREN_ENABLE_PCI_ERR_INTERRUPT;
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+
+ return TRUE;
+}
+
+
+VOID
+HalpEnablePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the PCI bus specified PCI bus interrupt.
+
+ memo: This routine enter following condition
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is enabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Count up enable count
+ //
+
+ HalpEnablePCIInterruptCount++;
+
+ //
+ // Check interrupt enable count. if interrupt is not already enable, then
+ // enable PCI interrupt.
+ //
+
+ if(HalpEnablePCIInterruptCount == 1){
+ HalpBuiltinInterruptEnable |= iREN_ENABLE_PCI_INTERRUPT;
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+ }
+
+}
+
+
+VOID
+HalpDisablePciInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function disables the PCI bus specified PCI bus interrupt.
+
+ memo: This routine enter following condition
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+Arguments:
+
+ Vector - Supplies the vector of the PCI interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ //
+ // Count down enable count
+ //
+
+ if( HalpEnablePCIInterruptCount > 0){
+ --HalpEnablePCIInterruptCount;
+ }
+
+ //
+ // Check interrupt enable count. if count equal zero, then disable
+ // PCI interrupt.
+ //
+
+ if(HalpEnablePCIInterruptCount == 0){
+ HalpBuiltinInterruptEnable &= ~iREN_ENABLE_PCI_INTERRUPT;
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable);
+ }
+}
diff --git a/private/ntos/nthals/halr98mp/mips/r98pcibs.c b/private/ntos/nthals/halr98mp/mips/r98pcibs.c
new file mode 100644
index 000000000..bca258f3e
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98pcibs.c
@@ -0,0 +1,3180 @@
+#ident "@(#) NEC r98pcibs.c 1.20 95/06/29 16:09:32"
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ ixpcidat.c
+
+Abstract:
+
+ Get/Set bus data routines for the PCI bus
+
+Author:
+
+ Ken Reneris (kenr) 14-June-1994
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+A001 ataka@oa2.kb.nec.co.jp Mon Oct 24 21:33:30 JST 1994
+ - ³Æ¼ïDbgPrint¤ÎÁÞÆþ
+ - r98DoPciTest = 1, r98DoGetDataPrint = 1
+ - r98PCIIoBase¤ÎÊѹ¹(Á´¤Æ1ecd0000¤ËÀßÄê)
+K001 kugimoto@oa2
+ -defined(DBG) chg IF DBG
+K002 kugimoto@oa2
+ -1:r98DoPciTest = 0, r98DoGetDataPrint = 0
+ -2:ASSERT del
+S001 samezima@oa2
+ - disable DbgPrint
+S002 samezima@oa2
+ - Bug. Change potision of #ifdef.
+A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ - Marge 807-halr98mp-r98pcibus.c to 1050 ixpcibus.c
+ and named r98pcibs.c
+K003 95/06/29 Kugimoto@oa2
+ -Mips Arc have not BIOS. So Set ROM Enable always.
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+extern WCHAR rgzMultiFunctionAdapter[];
+extern WCHAR rgzConfigurationData[];
+extern WCHAR rgzIdentifier[];
+extern WCHAR rgzPCIIdentifier[];
+
+
+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
+ );
+
+
+#if defined (_R98_) // A002
+VOID HalpPCISynchronizeTypeR98 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PVOID State
+ );
+
+VOID HalpPCIReleaseSynchronzationTypeR98 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ );
+
+ULONG HalpPCIReadUlongTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUcharTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIReadUshortTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUlongTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUcharTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+
+ULONG HalpPCIWriteUshortTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PVOID State,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ );
+#endif // _R98_ A002
+
+//
+// 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
+ }
+};
+
+#if defined (_R98_) // A002
+PCI_CONFIG_HANDLER PCIConfigHandlerTypeR98 = {
+ HalpPCISynchronizeTypeR98,
+ HalpPCIReleaseSynchronzationTypeR98,
+ {
+ HalpPCIReadUlongTypeR98, // 0
+ HalpPCIReadUcharTypeR98, // 1
+ HalpPCIReadUshortTypeR98 // 2
+ },
+ {
+ HalpPCIWriteUlongTypeR98, // 0
+ HalpPCIWriteUcharTypeR98, // 1
+ HalpPCIWriteUshortTypeR98 // 2
+ }
+};
+#endif // _R98_ A002
+
+UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
+
+BOOLEAN HalpDoingCrashDump;
+
+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
+ );
+#if defined (_R98_) // A002
+VOID
+HalpTestPciNec (
+ ULONG
+ );
+VOID
+HalpTestPciPrintResult(
+ IN PULONG Buffer,
+ IN ULONG Length
+ );
+VOID
+HalpOtherTestNec (
+ ULONG
+ );
+ULONG r98DbgCfg = 0;
+ULONG r98DoPciTest = 0; // A001 K002-1
+ULONG r98DoOthrTest = 0;
+ULONG r98DoMultiBytes = 0;
+ULONG r98DoGetDataPrint = 0; // A001 K002-1
+#define r98DbgCfgBits { \
+ if (r98DbgCfg) {\
+ DbgPrint("RegNo=%x ", PciCfgR98->u.bits.RegisterNumber); \
+ DbgPrint("FncNo=%x ", PciCfgR98->u.bits.FunctionNumber); \
+ DbgPrint("SltNo=%x ", PciCfgR98->u.bits.SlotNumber); \
+ DbgPrint("All=%x", PciCfgR98->u.AsULONG); \
+ } \
+ }
+#endif // _R98_ A002
+#else
+#define DBGMSG(a)
+#endif
+
+#if defined(_R98_) // A002
+ULONG r98PCIIoBase[] = { // This must be fixed to flexible configration
+ 0x00000000,
+ 0x1ecd0000,
+ 0x1ecd0000,
+ 0x1ecd0000
+ };
+#endif // _R98_ A002
+
+#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;
+
+ PCI_REGISTRY_INFO tPCIRegInfo; // only for debug A002
+
+#if 0 // A002
+ //
+ // 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;
+ }
+ }
+#endif // only for debug A002
+
+
+#if defined (_R98_) // only for debug A002
+// PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
+ PCIRegInfo = &tPCIRegInfo;
+ PCIRegInfo->NoBuses = 1;
+ PCIRegInfo->HardwareMechanism=0xF; // LR4360 PCI Config Type
+#if DBG // S001, S002
+ DbgPrint("PCI System Get Data:\n");
+ DbgPrint("MajorRevision %x\n", PCIRegInfo->MajorRevision );
+ DbgPrint("MinorRevision %x\n", PCIRegInfo->MinorRevision );
+ DbgPrint("NoBuses %x\n", PCIRegInfo->NoBuses );
+ DbgPrint("HwMechanism %x\n", PCIRegInfo->HardwareMechanism );
+#endif // S001, S002
+#endif // only for debug A002
+ //
+ // 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
+
+#if DBG
+ HalpTestPci (0);
+#if defined (_R98_) // A002
+ HalpTestPciNec (r98DoPciTest);
+ HalpOtherTestNec (r98DoOthrTest);
+ DbgPrint("HalpInitializePciBus: return\n");
+#endif // _R98_ A002
+#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
+ //
+
+ BusData->MaxDevice = PCI_MAX_DEVICES;
+ BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq;
+
+ RtlInitializeBitMap (&BusData->DeviceConfigured,
+ BusData->ConfiguredBits, 256);
+
+ switch (HwType) {
+ case 1:
+ //
+ // Initialize access port information for Type1 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType1,
+ sizeof (PCIConfigHandler));
+
+ BusData->Config.Type1.Address = PCI_TYPE1_ADDR_PORT;
+ BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
+ break;
+
+ case 2:
+ //
+ // Initialize access port information for Type2 handlers
+ //
+
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerType2,
+ sizeof (PCIConfigHandler));
+
+ BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
+ BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
+ BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
+
+ //
+ // Early PCI machines didn't decode the last bit of
+ // the device id. Shrink type 2 support max device.
+ //
+ BusData->MaxDevice = 0x10;
+
+ break;
+#if defined (_R98_) // A002
+ case 0xF:
+ RtlCopyMemory (&PCIConfigHandler,
+ &PCIConfigHandlerTypeR98,
+ sizeof (PCIConfigHandler));
+ BusData->MaxDevice = 0x4;
+ break;
+#endif // _R98_ A002
+ 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 DBG //K001 A002
+ if (r98DoGetDataPrint) {
+ DbgPrint("HalpGetPCIData: \n");
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx\n",
+ BusHandler->BusNumber, Slot.u.bits.DeviceNumber,
+ Slot.u.bits.FunctionNumber, 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 ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData->ProgIf, PciData->SubClass, PciData->BaseClass);
+ {ULONG j;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData->u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx\n", j, PciData->u.type0.BaseAddresses[j]);
+ }
+ }}
+ DbgPrint("\n");
+ }
+#endif // A002
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+ PciData->VendorID = PCI_INVALID_VENDORID;
+ Len = 2; // only return invalid id
+
+ } else {
+
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
+ }
+
+ //
+ // Has this PCI device been configured?
+ //
+
+#if DBG
+
+ //
+ // On DBG build, if this PCI device has not yet been configured,
+ // then don't report any current configuration the device may have.
+ //
+
+ bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
+ if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) {
+
+ for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
+ PciData->u.type0.BaseAddresses[i] = 0;
+ }
+
+ PciData->u.type0.ROMBaseAddress = 0;
+ PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
+ }
+#endif
+
+
+ //
+ // Copy whatever data overlaps into the callers buffer
+ //
+
+ if (Len < Offset) {
+ // no data at caller's buffer
+ return 0;
+ }
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory(Buffer, iBuffer + Offset, Len);
+
+ Offset += Len;
+ Buffer += Len;
+ Length -= Len;
+ }
+
+ if (Length) {
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The remaining Buffer comes from the Device Specific
+ // area - put on the kitten gloves and read from it.
+ //
+ // Specific read/writes to the PCI device specific area
+ // are guarenteed:
+ //
+ // Not to read/write any byte outside the area specified
+ // by the caller. (this may cause WORD or BYTE references
+ // to the area in order to read the non-dword aligned
+ // ends of the request)
+ //
+ // To use a WORD access if the requested length is exactly
+ // a WORD long.
+ //
+ // To use a BYTE access if the requested length is exactly
+ // a BYTE long.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+ULONG
+HalpSetPCIData (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+/*++
+
+Routine Description:
+
+ The function returns the Pci bus data for a device.
+
+Arguments:
+
+
+ VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
+
+ Buffer - Supplies the space to store the data.
+
+ Length - Supplies a count in bytes of the maximum amount to return.
+
+Return Value:
+
+ Returns the amount of data stored into the buffer.
+
+--*/
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ PPCIPBUSDATA BusData;
+ ULONG Len, cnt;
+
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+
+
+ if (Offset >= PCI_COMMON_HDR_LENGTH) {
+ //
+ // The user did not request any data from the common
+ // header. Verify the PCI device exists, then continue in
+ // the device specific area.
+ //
+
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
+
+ // no device, or header type unkown
+ return 0;
+ }
+
+
+ //
+ // Set this device as configured
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+#if 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) {
+ return FALSE;
+ }
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ return TRUE;
+ }
+
+ //
+ // Non zero function numbers are only supported if the
+ // device has the PCI_MULTIFUNCTION bit set in it's header
+ //
+
+ i = Slot.u.bits.DeviceNumber;
+
+ //
+ // Read DeviceNumber, Function zero, to determine if the
+ // PCI supports multifunction devices
+ //
+
+ Slot2 = Slot;
+ Slot2.u.bits.FunctionNumber = 0;
+
+ HalpReadPCIConfig (
+ BusHandler,
+ Slot2,
+ &HeaderType,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
+ sizeof (UCHAR)
+ );
+
+ if (!(HeaderType & PCI_MULTIFUNCTION) || HeaderType == 0xFF) {
+ // this device doesn't exists or doesn't support MULTIFUNCTION types
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+VOID
+HalpPCIConfig (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN FncConfigIO *ConfigIO
+ )
+{
+ KIRQL OldIrql;
+ ULONG i;
+ UCHAR State[20];
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
+
+ while (Length) {
+ i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+ i = ConfigIO[i] (BusData, State, Buffer, Offset);
+
+ Offset += i;
+ Buffer += i;
+ Length -= i;
+ }
+
+ PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
+}
+
+VOID HalpPCISynchronizeType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE1_CFG_BITS PciCfg1
+ )
+{
+ //
+ // Initialize PciCfg1
+ //
+
+ PciCfg1->u.AsULONG = 0;
+ PciCfg1->u.bits.BusNumber = BusHandler->BusNumber;
+ PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciCfg1->u.bits.Enable = TRUE;
+
+ //
+ // Synchronize with PCI type1 config space
+ //
+
+ if (!HalpDoingCrashDump) {
+ KeRaiseIrql (HIGH_LEVEL,Irql); // A002
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+ } else {
+ *Irql = HIGH_LEVEL;
+ }
+}
+
+VOID HalpPCIReleaseSynchronzationType1 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ PCI_TYPE1_CFG_BITS PciCfg1;
+ PPCIPBUSDATA BusData;
+
+ //
+ // Disable PCI configuration space
+ //
+
+ PciCfg1.u.AsULONG = 0;
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1.u.AsULONG);
+
+ //
+ // Release spinlock
+ //
+
+ if (!HalpDoingCrashDump) {
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql); // A002
+ }
+}
+
+
+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);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *Buffer = READ_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + 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);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + 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);
+ WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data);
+ 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_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + 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_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + 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 (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
+ WRITE_PORT_ULONG ((PULONG) BusData->Config.Type1.Data, *((PULONG) Buffer));
+ return sizeof (ULONG);
+}
+
+
+VOID HalpPCISynchronizeType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr
+ )
+{
+ PCI_TYPE2_CSE_BITS PciCfg2Cse;
+ PPCIPBUSDATA BusData;
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ //
+ // Initialize Cfg2Addr
+ //
+
+ PciCfg2Addr->u.AsUSHORT = 0;
+ PciCfg2Addr->u.bits.Agent = (USHORT) Slot.u.bits.DeviceNumber;
+ PciCfg2Addr->u.bits.AddressBase = (USHORT) BusData->Config.Type2.Base;
+
+ //
+ // Synchronize with type2 config space - type2 config space
+ // remaps 4K of IO space, so we can not allow other I/Os to occur
+ // while using type2 config space.
+ //
+
+ HalpPCIAcquireType2Lock (&HalpPCIConfigLock, Irql);
+
+ PciCfg2Cse.u.AsUCHAR = 0;
+ PciCfg2Cse.u.bits.Enable = TRUE;
+ PciCfg2Cse.u.bits.FunctionNumber = (UCHAR) Slot.u.bits.FunctionNumber;
+ PciCfg2Cse.u.bits.Key = 0xff;
+
+ //
+ // Select bus & enable type 2 configuration space
+ //
+
+ WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) BusHandler->BusNumber);
+ WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
+}
+
+
+VOID HalpPCIReleaseSynchronzationType2 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ PCI_TYPE2_CSE_BITS PciCfg2Cse;
+ PPCIPBUSDATA BusData;
+
+ //
+ // disable PCI configuration space
+ //
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+
+ PciCfg2Cse.u.AsUCHAR = 0;
+ WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
+ WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) 0);
+
+ //
+ // Restore interrupts, release spinlock
+ //
+
+ HalpPCIReleaseType2Lock (&HalpPCIConfigLock, Irql);
+}
+
+
+ULONG
+HalpPCIReadUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *Buffer = READ_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT);
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT);
+ return sizeof(ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT, *Buffer);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT, *((PUSHORT) Buffer));
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongType2 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
+ WRITE_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT, *((PULONG) Buffer));
+ return sizeof(ULONG);
+}
+
+#if defined (_R98_) // A002
+VOID HalpPCISynchronizeTypeR98 (
+ IN PBUS_HANDLER BusHandler,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PKIRQL Irql,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98
+ )
+{
+ //
+ // Initialize PciCfgR98
+ //
+
+ PciCfgR98->u.AsULONG = PCI_CONFIG_BASE_ADDRESS;
+//K002-2 ASSERT(Slot.u.bits.DeviceNumber >=0 && Slot.u.bits.DeviceNumber < 4); /* only 0-3 */
+ PciCfgR98->u.bits.SlotNumber = (Slot.u.bits.DeviceNumber & 3);
+ PciCfgR98->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+
+ //
+ // Synchronize with PCI type1 config space
+ //
+
+ KeRaiseIrql (PROFILE_LEVEL, Irql);
+ KiAcquireSpinLock (&HalpPCIConfigLock);
+}
+
+VOID HalpPCIReleaseSynchronzationTypeR98 (
+ IN PBUS_HANDLER BusHandler,
+ IN KIRQL Irql
+ )
+{
+ //
+ // Release spinlock
+ //
+
+ KiReleaseSpinLock (&HalpPCIConfigLock);
+ KeLowerIrql (Irql);
+}
+// LR4360 bug work around for debug time B004
+halplrbug0(){
+ ULONG reg1;
+ reg1 = READ_REGISTER_ULONG(0xb8c0a00c);
+ WRITE_REGISTER_ULONG(0xb8c0a00c,(reg1&0xffbfffff));
+ return reg1;
+}
+
+halplrbug1(ULONG reg1){
+ ULONG err,ERR_VALUE,iRRE;
+ ERR_VALUE = READ_REGISTER_ULONG(0xb8c09008);
+ if(ERR_VALUE & 0x80000000){
+ WRITE_REGISTER_ULONG(0xb8c09008,0x80000000);
+ iRRE = READ_REGISTER_ULONG(0xb8c0a008);
+ WRITE_REGISTER_ULONG(0xb8c0a008,(iRRE & 0xffbfffff));
+ err=1;
+ }else{
+ err=0;
+ }
+ WRITE_REGISTER_ULONG(0xb8c0a00c,reg1);
+ return err;
+}
+
+ULONG
+HalpPCIReadUcharTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ ULONG reg1;
+ reg1=halplrbug0();
+
+ i = Offset % sizeof(ULONG);
+ PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+ *Buffer = READ_PORT_UCHAR ((PUCHAR)(PciCfgR98->u.AsULONG + i));
+ if(halplrbug1(reg1)) //B004
+ *Buffer=0xFF;
+#if DBG // B009
+ r98DbgCfgBits("Read Uchar: ",*Buffer);
+#endif
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIReadUshortTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ ULONG reg1;
+ reg1=halplrbug0();
+
+ ASSERT((Offset % sizeof(USHORT)) == 0);
+
+ i = Offset % sizeof(ULONG);
+ PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ *((PUSHORT)Buffer) = READ_PORT_USHORT ((PUSHORT) (PciCfgR98->u.AsULONG + i));
+ if(halplrbug1(reg1)) //B004
+ *((PUSHORT)Buffer)=0xFFFF;
+#if DBG // B009
+ r98DbgCfgBits("Read Ushort: ",*((PUSHORT)Buffer));
+#endif
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIReadUlongTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+
+
+
+ ULONG reg1;
+ reg1=halplrbug0();
+ ASSERT((Offset % sizeof(ULONG)) == 0);
+ PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+#if DBG // B008
+ if (r98DoMultiBytes) {
+ HalpPCIReadUcharTypeR98 (BusData, PciCfgR98, Buffer, Offset);
+ HalpPCIReadUcharTypeR98 (BusData, PciCfgR98, Buffer+1, Offset+1);
+ HalpPCIReadUshortTypeR98 (BusData, PciCfgR98, Buffer+2, Offset+2);
+ } else
+#endif
+ *((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) (PciCfgR98->u.AsULONG));
+ if(halplrbug1(reg1))
+ *((PULONG)Buffer)=0xFFFFFFFF;
+#if DBG
+ r98DbgCfgBits("Read Ulong: ",*((PULONG)Buffer));
+#endif
+ return sizeof (ULONG);
+}
+
+
+ULONG
+HalpPCIWriteUcharTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ ULONG reg1;
+ reg1=halplrbug0();
+
+ i = Offset % sizeof(ULONG);
+ PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_UCHAR(((PUCHAR)(PciCfgR98->u.AsULONG + i)), (*((PUCHAR)Buffer)));
+#if DBG
+ r98DbgCfgBits("Write Uchar: ",*((PUCHAR)Buffer));
+#endif
+ halplrbug1(reg1);
+ return sizeof (UCHAR);
+}
+
+ULONG
+HalpPCIWriteUshortTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG i;
+ ULONG reg1;
+ reg1=halplrbug0();
+
+ ASSERT((Offset % sizeof(USHORT)) == 0);
+
+ i = Offset % sizeof(ULONG);
+ PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+ WRITE_PORT_USHORT(((PULONG)(PciCfgR98->u.AsULONG + i)), (*((PUSHORT)Buffer)));
+#if DBG
+ r98DbgCfgBits("Write Ushort: ",*((PUSHORT)Buffer));
+#endif
+ halplrbug1(reg1);
+ return sizeof (USHORT);
+}
+
+ULONG
+HalpPCIWriteUlongTypeR98 (
+ IN PPCIPBUSDATA BusData,
+ IN PPCI_TYPER98_CFG_BITS PciCfgR98,
+ IN PUCHAR Buffer,
+ IN ULONG Offset
+ )
+{
+ ULONG reg1;
+ reg1=halplrbug0();
+ ASSERT((Offset % sizeof(ULONG)) == 0);
+
+ PciCfgR98->u.bits.RegisterNumber = Offset / sizeof(ULONG);
+
+#if DBG
+ if (r98DoMultiBytes) {
+ HalpPCIWriteUcharTypeR98 (BusData, PciCfgR98, Buffer, Offset);
+ HalpPCIWriteUcharTypeR98 (BusData, PciCfgR98, Buffer+1, Offset+1);
+ HalpPCIWriteUshortTypeR98 (BusData, PciCfgR98, Buffer+2, Offset+2);
+ } else
+#endif
+ WRITE_PORT_ULONG (((PULONG)(PciCfgR98->u.AsULONG)), (*((PULONG)Buffer)));
+#if DBG
+ r98DbgCfgBits("Write Ulong: ",*((PULONG)Buffer));
+#endif
+ halplrbug1(reg1);
+ return sizeof (ULONG);
+}
+#endif // A002
+
+
+
+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 DBG // A002
+ DbgPrint("HalpAssignPCISlotResources: befor fill to ffff\n");
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ BusNumber, Slot, 0, 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 ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData->ProgIf, PciData->SubClass, PciData->BaseClass);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData->u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData->u.type0.BaseAddresses[j]);
+ }
+ }
+ DbgPrint("\n");
+#endif // A002
+
+ 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 0 //K003
+ if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
+ ASSERT (RomIndex+1 == NoBaseAddress);
+ EnableRomBase = FALSE;
+ NoBaseAddress -= 1;
+ }
+#endif
+ //
+ // 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);
+#if DBG // A002
+ DbgPrint("HalpAssignPCISlotResources: befor fill to ffff\n");
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ BusNumber, Slot, 0, 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 ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData->ProgIf, PciData->SubClass, PciData->BaseClass);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData->u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData->u.type0.BaseAddresses[j]);
+ }
+ }
+ DbgPrint("\n");
+#endif // A002
+
+ // 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;
+#if DBG // A002
+ DbgPrint("\nCmResourceTypeInterrupt: CmResourceShared\n");
+ DbgPrint("CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE ");
+ DbgPrint("Min=%x Max=%x\n", Descriptor->u.Interrupt.MinimumVector,
+ Descriptor->u.Interrupt.MaximumVector);
+#endif // A002
+ 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;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this IO range
+ //
+
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MaximumAddress.LowPart = m;
+
+ } else {
+
+ memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
+
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ if (!Is64BitBaseAddress(i) &&
+ (j == RomIndex ||
+ PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
+
+ //
+ // The memory range is/was already enabled at some location, add that
+ // as it's preferred setting.
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ Descriptor->Option = IO_RESOURCE_PREFERRED;
+
+ Descriptor->u.Port.Length = length;
+ Descriptor->u.Port.Alignment = length;
+ Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
+ Descriptor->u.Port.MaximumAddress.LowPart =
+ Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+
+ Descriptor->Flags = Descriptor[-1].Flags;
+ Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+ }
+
+ //
+ // Add this memory range
+ //
+
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Memory.Length = length;
+ Descriptor->u.Memory.Alignment = length;
+ Descriptor->u.Memory.MaximumAddress.LowPart = m;
+
+ if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
+ // limit to 20 bit address
+ Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
+ }
+ }
+
+ 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) {
+#if defined (_R98_) // A002
+#if DBG
+ DbgPrint("Assigned: Port Address %x\n", CmDescriptor->u.Port.Start.LowPart);
+#endif
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart | r98PCIIoBase[Slot];
+#if DBG
+ DbgPrint("Assign: Port Address %x\n", *BaseAddress[j]);
+#endif
+#else
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+#endif // _R98_ // ADD001
+ } else {
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+#if DBG // A002
+ DbgPrint("Assign: memory Address %x\n", *BaseAddress[j]);
+#endif // _R98_ // ADD001
+ }
+ 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)
+ //
+
+ PciData->Command |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+ HalSetBusDataByOffset (
+ PCIConfiguration,
+ BusHandler->BusNumber,
+ PciSlot.u.AsULONG,
+ &PciData->Command,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
+ sizeof (PciData->Command)
+ );
+
+CleanUp:
+ if (!NT_SUCCESS(status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (*pAllocatedResources) {
+ IoAssignResources (
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ //
+ // Restore the device settings as we found them, enable memory
+ // and io decode after setting base addresses
+ //
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ &PciOrigData->Status,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
+ PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+
+ HalpWritePCIConfig (
+ BusHandler,
+ PciSlot,
+ PciOrigData,
+ 0,
+ FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
+ );
+ }
+
+ ExFreePool (WorkingPool);
+ return status;
+}
+
+#if DBG
+VOID
+HalpTestPci (ULONG flag2)
+{
+ PCI_SLOT_NUMBER SlotNumber;
+ PCI_COMMON_CONFIG PciData, OrigData;
+ ULONG i, f, j, k, bus;
+ BOOLEAN flag;
+
+
+ if (!flag2) {
+ return ;
+ }
+
+ DbgBreakPoint ();
+ SlotNumber.u.bits.Reserved = 0;
+
+ //
+ // Read every possible PCI Device/Function and display it's
+ // default info.
+ //
+ // (note this destories it's current settings)
+ //
+
+ flag = TRUE;
+ for (bus = 0; flag; bus++) {
+
+ for (i = 0; i < PCI_MAX_DEVICES; i++) {
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < PCI_MAX_FUNCTION; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+
+ //
+ // Note: This is reading the DeviceSpecific area of
+ // the device's configuration - normally this should
+ // only be done on device for which the caller understands.
+ // I'm doing it here only for debugging.
+ //
+
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+#if 0
+ memcpy (&OrigData, &PciData, sizeof PciData);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
+ }
+
+ PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+#endif
+
+ DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
+ bus, i, f, PciData.VendorID, PciData.DeviceID,
+ PciData.RevisionID);
+
+
+ if (PciData.u.type0.InterruptPin) {
+ DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
+ }
+
+ if (PciData.u.type0.InterruptLine) {
+ DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
+ }
+
+ if (PciData.u.type0.ROMBaseAddress) {
+ DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ PciData.Command, PciData.Status, PciData.ProgIf,
+ PciData.SubClass, PciData.BaseClass);
+
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (PciData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+#if 0
+ if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
+
+ PciData.u.type0.ROMBaseAddress = 0xC00001;
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+
+ DbgPrint ("\n Bogus rom address, edit yields:%08lx",
+ PciData.u.type0.ROMBaseAddress);
+ }
+#endif
+
+ if (k) {
+ DbgPrint ("\n");
+ }
+
+ if (PciData.VendorID == 0x8086) {
+ // dump complete buffer
+ DbgPrint ("Command %x, Status %x, BIST %x\n",
+ PciData.Command, PciData.Status,
+ PciData.BIST
+ );
+
+ DbgPrint ("CacheLineSz %x, LatencyTimer %x",
+ PciData.CacheLineSize, PciData.LatencyTimer
+ );
+
+ for (j=0; j < 192; j++) {
+ if ((j & 0xf) == 0) {
+ DbgPrint ("\n%02x: ", j + 0x40);
+ }
+ DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
+ }
+ DbgPrint ("\n");
+ }
+
+
+#if 0
+ //
+ // now print original data
+ //
+
+ if (OrigData.u.type0.ROMBaseAddress) {
+ DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
+ }
+
+ DbgPrint ("\n");
+ k = 0;
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+ if (OrigData.u.type0.BaseAddresses[j]) {
+ DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
+ k = 1;
+ }
+ }
+
+ //
+ // Restore original settings
+ //
+
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+#endif
+
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+#if defined (_R98_) // A002
+VOID
+HalpTestPciNec (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 < 1; bus++) { /* R98 Support Only 1 */
+
+ for (i = 0; i < 4; i++) { /* R98 Support Only 4 slots(include bridge) */
+ SlotNumber.u.bits.DeviceNumber = i;
+
+ for (f = 0; f < 8; f++) {
+ SlotNumber.u.bits.FunctionNumber = f;
+ DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
+ j = HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, j);
+ if (j == 0) {
+ // out of buses
+ flag = FALSE;
+ break;
+ }
+
+ if (j < PCI_COMMON_HDR_LENGTH) {
+ continue;
+ }
+ DbgPrint("===== SetBusData slot(%d) func(%d)\n", i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ 1
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, 1);
+ DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&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;
+ PciData.u.type0.InterruptLine = 5; // For trial
+ DbgPrint("===== (Change Contents (SetBusData) slot(%d) func(%d)\n", i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ PCI_COMMON_HDR_LENGTH // To avoid alias problem(HDR <--> DevSpecific)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, PCI_COMMON_HDR_LENGTH);
+ DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
+ HalGetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &PciData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData));
+
+ DbgPrint ("--------------->>> Now Print the Slot Information\n");
+ 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 ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
+ 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 ("We got the bridge\n");
+ 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
+ //
+ DbgPrint ("--------------->>> Now Print the Original Slot Information\n");
+ 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
+ //
+ DbgPrint("===== Restore (GetBusData) slot(%d) func(%d)\n", i, f);
+ HalSetBusData (
+ PCIConfiguration,
+ bus,
+ SlotNumber.u.AsULONG,
+ &OrigData,
+ sizeof (PciData)
+ );
+ HalpTestPciPrintResult((PULONG)&OrigData, sizeof (PciData));
+ //
+ // Next
+ //
+
+ if (k) {
+ DbgPrint ("\n\n");
+ }
+ }
+ }
+ }
+ DbgBreakPoint ();
+}
+
+
+VOID
+HalpTestPciPrintResult(
+ IN PULONG Buffer,
+ IN ULONG Length
+)
+{
+ ULONG i, Lines, pchar;
+
+ DbgPrint("----- I/O Data. (%d)byts.\n", Length);
+
+ for (Lines = 0, pchar = 0; Lines < ((Length + 15)/ 16) && pchar < Length; Lines++) {
+ DbgPrint("%08x: ", Lines);
+ for (i = 0; i < 4; pchar += 4, i++) {
+ if (pchar >= Length)
+ break;
+ DbgPrint("%08x ", *Buffer++);
+ }
+ DbgPrint("\n");
+ }
+}
+
+VOID
+HalpOtherTestNec (
+ IN ULONG doOtherTest
+)
+{
+ if (!doOtherTest)
+ return;
+
+
+ DbgPrint("\n\n===== Additional Testing...\n");
+ {
+ CM_EISA_SLOT_INFORMATION EisaSlotInfo;
+ PCM_EISA_SLOT_INFORMATION EisaBuffer;
+ PCM_EISA_FUNCTION_INFORMATION EisaFunctionInfo;
+ ULONG slot, funcs, Length;
+
+ #define MAX_EISA_SLOT 4
+
+ DbgPrint("----- Read Eisa Configration:\n");
+ for (slot = 0; slot < MAX_EISA_SLOT; slot++) {
+ Length = HalGetBusData (EisaConfiguration,0,slot,&EisaSlotInfo,sizeof (EisaSlotInfo));
+ if (Length < sizeof(CM_EISA_SLOT_INFORMATION)) {
+
+ //
+ // The data is messed up since this should never occur
+ //
+
+ break;
+ }
+ Length = sizeof(CM_EISA_SLOT_INFORMATION) +
+ (sizeof(CM_EISA_FUNCTION_INFORMATION) * EisaSlotInfo.NumberFunctions);
+ EisaBuffer = ExAllocatePool(NonPagedPool, Length);
+ HalGetBusData (EisaConfiguration,0,slot,&EisaBuffer,Length);
+ // Print all Eisa Data
+
+ EisaFunctionInfo = (PCM_EISA_FUNCTION_INFORMATION)
+ ((char *)&EisaBuffer + sizeof(CM_EISA_SLOT_INFORMATION));
+
+ DbgPrint("----- HalGetBusData Eisa Slot No=%d\n", slot);
+ DbgPrint("ReturnCode = 0x%x, ReturnFlags = 0x%x, MajorRev = 0x%x, MinorRev = 0x%x, \n",
+ EisaBuffer->ReturnCode, EisaBuffer->ReturnFlags,
+ EisaBuffer->MajorRevision, EisaBuffer->MinorRevision);
+ DbgPrint("CheckSum = 0x%x, NumberFunctions = 0x%x, FunctionInformation = 0x%x, CompressedId = 0x%x\n",
+ EisaBuffer->Checksum,
+ EisaBuffer->NumberFunctions,
+ EisaBuffer->FunctionInformation,
+ EisaBuffer->CompressedId);
+ for (funcs = 0; funcs < EisaBuffer->NumberFunctions; funcs++) {
+ DbgPrint("CompressId = 0x%x, IdSlotFlags1 = 0x%x, IdSlotFlags2 = 0x%x, MinorRevision = 0x%x, MajorRevision = 0x%x\n",
+ EisaFunctionInfo->CompressedId, EisaFunctionInfo->IdSlotFlags1,
+ EisaFunctionInfo->IdSlotFlags2, EisaFunctionInfo->MinorRevision,
+ EisaFunctionInfo->MajorRevision);
+
+ // EisaFunctionInfo->Selections[26];
+ // EisaFunctionInfo->FunctionFlags;
+ // EisaFunctionInfo->TypeString[80];
+ // EISA_MEMORY_CONFIGURATION EisaFunctionInfo->EisaMemory[9];
+ // EISA_IRQ_CONFIGURATION EisaFunctionInfo->EisaIrq[7];
+ // EISA_DMA_CONFIGURATION EisaFunctionInfo->EisaDma[4];
+ // EISA_PORT_CONFIGURATION EisaFunctionInfo->EisaPort[20];
+ // UCHAR EisaFunctionInfo->InitializationData[60];
+ EisaFunctionInfo++;
+ }
+
+ }
+ }
+ DbgBreakPoint ();
+ {
+ #define MEMORY_SPACE 0
+ #define IO_SPACE 1
+ PHYSICAL_ADDRESS cardAddress;
+ ULONG addressSpace = IO_SPACE;
+ PHYSICAL_ADDRESS PhysAddr;
+
+ PhysAddr.LowPart = 0;
+ PhysAddr.HighPart = 0;
+
+
+ DbgPrint("----- \nTranslate Internal Bus Address(I/O): ");
+ HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Eisa Bus Address(I/O): ");
+ addressSpace = IO_SPACE;
+ HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Isa Bus Address(I/O): ");
+ addressSpace = IO_SPACE;
+ HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate PCI Bus Address(I/O): ");
+ addressSpace = IO_SPACE;
+ HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Internal Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Eisa Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate Isa Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+
+ DbgPrint("Translate PCI Bus Address(MEMORY): ");
+ addressSpace = MEMORY_SPACE;
+ HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
+ DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
+ }
+ DbgBreakPoint ();
+
+ {
+ KAFFINITY affinity;
+ KIRQL Irql;
+ ULONG Vec;
+
+ DbgPrint("----- \nGetInterruptVector internal\n");
+ Vec = HalGetInterruptVector(Internal, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ DbgPrint("GetInterruptVector Eisa\n");
+ Vec = HalGetInterruptVector(Eisa, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ DbgPrint("GetInterruptVector Isa\n");
+ Vec = HalGetInterruptVector(Isa, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ DbgPrint("GetInterruptVector PCI\n");
+ Vec = HalGetInterruptVector(PCIBus, 0, 0, 0, &Irql, &affinity);
+ DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
+
+ }
+ DbgBreakPoint ();
+}
+#endif // A002
+
+
+
+#endif
+
diff --git a/private/ntos/nthals/halr98mp/mips/r98pcint.c b/private/ntos/nthals/halr98mp/mips/r98pcint.c
new file mode 100644
index 000000000..d54acb3eb
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98pcint.c
@@ -0,0 +1,384 @@
+#ident "@(#) NEC r98pcint.c 1.13 95/06/29 16:13:28"
+/*++
+
+
+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
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ A001 1995/6/17 ataka@oa2.kb.nec.co.jp
+ - Marge 807-halr98mp-r98pciint.c to 1050 ixpciint.c
+ and named r98pcint.c
+
+ K001 '95/6/29 Kugimoto@oa2
+ - PPCIBUSDATA-->PPCIPBUSDATA
+--*/
+
+#include "halp.h"
+#include "pci.h"
+#include "pcip.h"
+
+ULONG PciIsaIrq;
+ULONG HalpEisaELCR;
+BOOLEAN HalpDoingCrashDump;
+
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
+#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
+#pragma alloc_text(PAGE,HalpGetISAFixedPCIIrq)
+#endif
+
+
+ULONG
+HalpGetPCIIntOnISABus (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity
+ )
+{
+#if defined(_R98_) // A001
+ *Affinity = HalpPCIBusAffinity;
+
+ *Irql = INT1_LEVEL;
+ return(PCI_DEVICE_VECTOR);
+
+ if (BusInterruptLevel < 1) {
+ // bogus bus level
+ return 0;
+ }
+#else
+
+ //
+ // 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 (
+#ifndef MCA
+ Isa, 0,
+#else
+ MicroChannel, 0,
+#endif
+ BusInterruptLevel ^ IRQXOR,
+ 0,
+ Irql,
+ Affinity
+ );
+#endif //_R98_
+}
+
+
+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 the current PC implementations, the bios has already filled in
+ InterruptLine as it's ISA value and there's no portable way to
+ change it.
+
+ On a DBG build we adjust InterruptLine just to ensure driver's
+ don't connect to it without translating it on the PCI bus.
+
+--*/
+{
+ if (!PciData->u.type0.InterruptPin) {
+ return ;
+ }
+
+#if defined(_R98_) // A001
+ PciData->u.type0.InterruptLine = PciData->u.type0.InterruptPin;
+#else
+ //
+ // Set vector as a level vector. (note: this code assumes the
+ // irq is static and does not move).
+ //
+
+ if (PciData->u.type0.InterruptLine >= 1 &&
+ PciData->u.type0.InterruptLine <= 15) {
+
+ //
+ // If this bit was on the in the PIC ELCR register,
+ // then mark it in PciIsaIrq. (for use in hal.dll,
+ // such that we can assume the interrupt controller
+ // has been properly marked as a level interrupt for
+ // this IRQ. Other hals probabily don't care.)
+ //
+
+ PciIsaIrq |= HalpEisaELCR & (1 << PciData->u.type0.InterruptLine);
+ }
+
+ //
+ // On a PC there's no Slot/Pin/Line mapping which needs to
+ // be done.
+ //
+
+ PciData->u.type0.InterruptLine ^= IRQXOR;
+#endif // _R98_
+}
+
+
+
+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.
+
+ On the current PC implementations, this information is
+ fixed by the BIOS. Just make sure the value isn't being
+ editted since PCI doesn't tell us how to dynically
+ connect the interrupt.
+
+--*/
+{
+ if (!PciNewData->u.type0.InterruptPin) {
+ return ;
+ }
+
+#if defined(_R98_) // A001
+ PciNewData->u.type0.InterruptLine = PciOldData->u.type0.InterruptPin;
+#else
+ PciNewData->u.type0.InterruptLine ^= IRQXOR;
+
+#if DBG
+ if (PciNewData->u.type0.InterruptLine != PciOldData->u.type0.InterruptLine ||
+ PciNewData->u.type0.InterruptPin != PciOldData->u.type0.InterruptPin) {
+ DbgPrint ("HalpPCILine2Pin: System does not support changing the PCI device interrupt routing\n");
+ DbgBreakPoint ();
+ }
+#endif
+#endif // _R98_
+}
+
+#if !defined(SUBCLASSPCI)
+
+VOID
+HalpPCIAcquireType2Lock (
+ PKSPIN_LOCK SpinLock,
+ PKIRQL Irql
+ )
+{
+ if (!HalpDoingCrashDump) {
+ KeRaiseIrql (PROFILE_LEVEL, Irql); // A001
+ KiAcquireSpinLock (SpinLock);
+ } else {
+ *Irql = HIGH_LEVEL;
+ }
+}
+
+
+VOID
+HalpPCIReleaseType2Lock (
+ PKSPIN_LOCK SpinLock,
+ KIRQL Irql
+ )
+{
+ if (!HalpDoingCrashDump) {
+ KiReleaseSpinLock (SpinLock);
+ KeLowerIrql (Irql); // A001
+ }
+}
+
+#endif
+
+
+halpPciMemoryLimit=64* 1024*1024; // K001
+
+
+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;
+
+ // Start K000 A001
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ PIO_RESOURCE_REQUIREMENTS_LIST InCompleteList;
+ PIO_RESOURCE_LIST InResourceList;
+ ULONG cnt,alt;
+
+ InCompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) *pResourceList;
+ InResourceList = InCompleteList->List;
+#if DBG
+ DbgPrint("\n HalpPciMemoryLimit= 0x%x\n",halpPciMemoryLimit);
+#endif
+ for (alt=0; alt < InCompleteList->AlternativeLists; alt++) {
+
+ Descriptor = InResourceList->Descriptors;
+
+ for (cnt = InResourceList->Count; cnt; cnt--) {
+ if(
+ Descriptor->Type==CmResourceTypeMemory
+ && halpPciMemoryLimit < (1024*1024*256-1)
+ ){
+ halpPciMemoryLimit=(
+ ( halpPciMemoryLimit
+ +Descriptor->u.Memory.Length
+ +(Descriptor->u.Memory.Alignment-1)
+ ) & ~ (Descriptor->u.Memory.Alignment-1)
+ )-1;
+
+ if(halpPciMemoryLimit >= (1024*1024*256-1)){
+ halpPciMemoryLimit=(1024*1024*256-1);
+ }
+
+
+#if DBG
+ DbgPrint("\n InHalpPciMemoryLimit= 0x%x\n",halpPciMemoryLimit);
+ DbgPrint("\n Length= 0x%x\n",Descriptor->u.Memory.Length);
+ DbgPrint("\n Alignment= 0x%x\n",Descriptor->u.Memory.Alignment);
+#endif
+ }
+ Descriptor++;
+ }
+
+ }
+#if DBG
+ DbgPrint("\n FixHalpPciMemoryLimit= 0x%x\n",halpPciMemoryLimit);
+#endif
+ // End of K001 A002
+
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ BusHandler->BusAddresses->Memory.Limit = halpPciMemoryLimit; //K001 A002
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
+
+ //
+ // 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);
+ return Status;
+}
+
+
+NTSTATUS
+HalpGetISAFixedPCIIrq (
+ IN PBUS_HANDLER BusHandler,
+ IN PBUS_HANDLER RootHandler,
+ IN PCI_SLOT_NUMBER PciSlot,
+ OUT PSUPPORTED_RANGE *Interrupt
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PPCI_COMMON_CONFIG PciData;
+#if defined(_R98_) // A001 K001
+ PPCIPBUSDATA BusData;
+#endif // _R98_
+
+
+ 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));
+ (*Interrupt)->Base = 1; // base = 1, limit = 0
+
+
+#if defined(_R98_) // A001
+ BusData = (PPCIPBUSDATA) BusHandler->BusData;
+ BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
+#else
+ if (!PciData->u.type0.InterruptPin) {
+ return STATUS_SUCCESS;
+ }
+
+ if (PciData->u.type0.InterruptLine == IRQXOR) {
+#if DBG
+ DbgPrint ("HalpGetValidPCIFixedIrq: BIOS did not assign an interrupt vector for the device\n");
+#endif
+ //
+ // We need to let the caller continue, since the caller may
+ // not care that the interrupt vector is connected or not
+ //
+
+ return STATUS_SUCCESS;
+ }
+#endif // _R98_
+
+ (*Interrupt)->Base = PciData->u.type0.InterruptLine;
+ (*Interrupt)->Limit = PciData->u.type0.InterruptLine;
+ return STATUS_SUCCESS;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/r98reg.h b/private/ntos/nthals/halr98mp/mips/r98reg.h
new file mode 100644
index 000000000..d89d560bd
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98reg.h
@@ -0,0 +1,475 @@
+#ident "@(#) NEC r98reg.h 1.8 95/02/20 17:25:49"
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ r98reg.h
+
+Abstract:
+
+ This module is the header file that structure I/O registers for the r98.
+
+Author:
+
+
+Revision History:
+
+--*/
+
+/*
+ ***********************************************************************
+ *
+ * S001 6/10 T.Samezima
+ *
+ * Del Compile err
+ *
+ ***********************************************************************
+ *
+ * S002 6/10 T.Samezima
+ *
+ * Add I/O access macro
+ *
+ ***********************************************************************
+ *
+ * S003 7/5 T.Samezima
+ *
+ * Chg define miss
+ * structure define miss
+ ***********************************************************************
+ *
+ * S004 7/12 T.Samezima
+ *
+ * Chg structure define change
+ *
+ ***********************************************************************
+ *
+ * S005 7/14 T.Samezima
+ *
+ * Chg structure define change
+ *
+ ***********************************************************************
+ *
+ * S006 7/22 T.Samezima
+ *
+ * Add define IOB and SIC register dummy read macro
+ * (correspondence PMC3 bug)
+ *
+ * S007 12/24 T.Samezima
+ * Add define EIFR register define.
+ *
+ * S008 '95.1/7 T.Samezima
+ * Add define EIF0,STS2 register define.
+ *
+ * S009 '95.1/11 T.Samezima
+ * Del miss define
+ *
+ *
+ */
+
+#ifndef _R98REG_
+#define _R98REG_
+
+//
+// Define PMC register structure.
+//
+typedef struct _PMC_REGISTER {
+ ULONG Long;
+ ULONG Fill;
+} PMC_REGISTER, *PPMC_REGISTER;
+
+typedef struct _PMC_LARGE_REGISTER {
+// Start S005
+ ULONG High;
+ ULONG Low;
+// End S005
+} PMC_LARGE_REGISTER, *PPMC_LARGE_REGISTER;
+
+typedef volatile struct _PMC_REGISTERS1 {
+ // offset(H)
+ PMC_LARGE_REGISTER IPR; // 0
+ PMC_LARGE_REGISTER MKR; // 8
+ PMC_LARGE_REGISTER IPRR; // 10
+ PMC_REGISTER IPSR; // 18
+ PMC_REGISTER MKRR; // 20
+ PMC_REGISTER MKSR; // 28
+ PMC_REGISTER NMIR; // 30
+ PMC_REGISTER NMIRST; // 38
+ PMC_REGISTER TMSR1; // 40
+ PMC_REGISTER TMR1; // 48
+ PMC_REGISTER TOVCT1; // 50
+ PMC_REGISTER TMCR1; // 58
+ PMC_REGISTER TMSR2; // 60
+ PMC_REGISTER TMR2; // 68
+ PMC_REGISTER TOVCT2; // 70
+ PMC_REGISTER TMCR2; // 78
+ PMC_REGISTER WDTSR; // 80
+ PMC_REGISTER WDT; // 88
+ PMC_REGISTER WDTCR; // 90
+ PMC_REGISTER Reserved1[13]; // 98-F8
+ PMC_REGISTER IntIR; // 100
+ PMC_REGISTER Reserved2; // 108
+ PMC_REGISTER TCIR; // 110
+ PMC_REGISTER Reserved3[29]; // 118-1F8
+ PMC_REGISTER CTAddr; // 200
+ PMC_REGISTER CTData; // 208
+ PMC_REGISTER CTCTL; // 210
+ PMC_REGISTER EVCNT1H; // 218
+ PMC_REGISTER EVCNT1L; // 220
+ PMC_REGISTER EVCNTCR1; // 228
+ PMC_REGISTER Reserved4[26]; // 230-2F8
+ PMC_REGISTER CNFG; // 300
+ PMC_REGISTER STSR; // 308
+ PMC_REGISTER ERRRST; // 310
+ PMC_REGISTER ERR; // 318
+ PMC_REGISTER AERR; // 320
+ PMC_REGISTER ERRMK; // 328
+ PMC_REGISTER TOSR; // 330
+ PMC_REGISTER EVCNT0H; // 338
+ PMC_REGISTER EVCNT0L; // 340
+ PMC_REGISTER EVCNTCR0; // 348
+} PMC_REGISTERS1, *PPMC_REGISTERS1;
+
+typedef volatile struct _PMC_REGISTERS2 {
+ // offset(H)
+ PMC_REGISTER RRMT0H; // 0
+ PMC_REGISTER RRMT0L; // 8
+ PMC_REGISTER RRMT1H; // 10
+ PMC_REGISTER RRMT1L; // 18
+ PMC_REGISTER RRMT2H; // 20
+ PMC_REGISTER RRMT2L; // 28
+ PMC_REGISTER RRMT3H; // 30
+ PMC_REGISTER RRMT3L; // 38
+ PMC_REGISTER RRMT4H; // 40
+ PMC_REGISTER RRMT4L; // 48
+ PMC_REGISTER RRMT5H; // 50
+ PMC_REGISTER RRMT5L; // 58
+ PMC_REGISTER RRMT6H; // 60
+ PMC_REGISTER RRMT6L; // 68
+ PMC_REGISTER RRMT7H; // 70
+ PMC_REGISTER RRMT7L; // 78
+ PMC_REGISTER Reserved1[2]; // 80-88
+ PMC_REGISTER DISCON; // 90
+ PMC_REGISTER Reserved2[3]; // 98-a8
+ PMC_REGISTER EADRH; // b0
+ PMC_REGISTER EADRL; // b8
+ PMC_REGISTER Reserved3[2]; // c0-c8
+ PMC_REGISTER RTYCNT; // d0
+} PMC_REGISTERS2, *PPMC_REGISTERS2;
+
+//
+// Define pointer to PMC registers.
+//
+#define PMC_GLOBAL_CONTROL1 ((volatile PPMC_REGISTERS1)(KSEG1_BASE | PMC_PHYSICAL_BASE1))
+#define PMC_GLOBAL_CONTROL2 ((volatile PPMC_REGISTERS2)(KSEG1_BASE | PMC_PHYSICAL_BASE2))
+/* Start S002 */
+#define PMC_GLOBAL_CONTROL1_OR(x) ((volatile PPMC_REGISTERS1)(KSEG1_BASE | PMC_PHYSICAL_BASE1 | (x) ))
+#define PMC_GLOBAL_CONTROL2_OR(x) ((volatile PPMC_REGISTERS2)(KSEG1_BASE | PMC_PHYSICAL_BASE2 | (x) ))
+/* End S002 */
+/* Start S001 */
+#define PMC_CONTROL1 ((volatile PPMC_REGISTERS1)((ULONG)PMC_GLOBAL_CONTROL1 | PMC_LOCAL_OFFSET))
+#define PMC_CONTROL2 ((volatile PPMC_REGISTERS2)((ULONG)PMC_GLOBAL_CONTROL2 | PMC_LOCAL_OFFSET))
+/* End S001 */
+/* Start S002 */
+#define PMC_CONTROL1_OR(x) ((volatile PPMC_REGISTERS1)((ULONG)PMC_GLOBAL_CONTROL1 | PMC_LOCAL_OFFSET | (x) ))
+#define PMC_CONTROL2_OR(x) ((volatile PPMC_REGISTERS2)((ULONG)PMC_GLOBAL_CONTROL2 | PMC_LOCAL_OFFSET | (x) ))
+/* End S002 */
+
+/* Start S006 */
+//
+// Define dummy read macro. This macro use to not lead to time out of PMC
+//
+
+#define IOB_DUMMY_READ READ_REGISTER_ULONG(PMC_DUMMY_READ_ADDR)
+#define SIC_DUMMY_READ READ_REGISTER_ULONG(PMC_DUMMY_READ_ADDR)
+/* End S006 */
+
+//
+// Define IOB register structure.
+//
+typedef struct _IOB_REGISTER {
+ ULONG Long;
+ ULONG Fill;
+} IOB_REGISTER, *PIOB_REGISTER;
+
+typedef volatile struct _IOB_REGISTERS {
+ // offset(H)
+ IOB_REGISTER AIMR; // 0
+ IOB_REGISTER AII0; // 8
+ IOB_REGISTER AII1; // 10
+ IOB_REGISTER AII2; // 18
+ IOB_REGISTER AII3; // 20
+ IOB_REGISTER AISR; // 28
+ IOB_REGISTER ITRR; // 30
+ IOB_REGISTER ADC0; // 38
+ IOB_REGISTER ADC1; // 40
+ IOB_REGISTER ADC2; // 48
+ IOB_REGISTER ADC3; // 50
+ IOB_REGISTER AMMD; // 58
+ IOB_REGISTER ANMD; // 60
+ IOB_REGISTER IERR; // 68
+ IOB_REGISTER IEMR; // 70
+ IOB_REGISTER IEER; // 78
+ IOB_REGISTER AMAL; // 80
+ IOB_REGISTER AMAH; // 88
+ IOB_REGISTER ANAL; // 90
+ IOB_REGISTER ANAH; // 98
+ IOB_REGISTER AMRC; // a0
+ IOB_REGISTER ANRC; // a8
+ IOB_REGISTER AMRT; // b0
+ IOB_REGISTER ANMT; // b8
+ IOB_REGISTER ANST; // c0
+ IOB_REGISTER Reserved1[7]; // c8-f8
+ IOB_REGISTER ADG0; // 100
+ IOB_REGISTER ADG1; // 108
+ IOB_REGISTER CNTD; // 110
+ IOB_REGISTER CNTE; // 118
+ IOB_REGISTER CABS; // 120
+ IOB_REGISTER CAWS; // 128
+ IOB_REGISTER CTGL; // 130
+ IOB_REGISTER CTGH; // 138
+ IOB_REGISTER ARMS; // 140
+ IOB_REGISTER ARML; // 148
+ IOB_REGISTER ARMH; // 150
+ IOB_REGISTER Reserved2[21]; // 158-1f8
+ IOB_REGISTER SCFR; // 200
+ IOB_REGISTER MPER; // 208
+ IOB_REGISTER EIMR; // 210
+ IOB_REGISTER EIFR; // 218
+ IOB_REGISTER Reserved3[28]; // 220-2f8
+// DCDW; // 300
+// IOB_REGISTER ATCNF; // 400
+} IOB_REGISTERS, *PIOB_REGISTERS;
+
+// S007 vvv
+//
+// Define EIFR register
+//
+typedef struct _EIFR_REGISTER {
+ ULONG Reserved : 21;
+ ULONG MPDISCN : 1;
+ ULONG IOBERR : 1;
+ ULONG Reserved2 : 1;
+ ULONG EISANMI : 1;
+ ULONG LRERR : 1;
+ ULONG SIC1ERR : 1;
+ ULONG SIC0ERR : 1;
+ ULONG PMC3ERR : 1;
+ ULONG PMC2ERR : 1;
+ ULONG PMC1ERR : 1;
+ ULONG PMC0ERR : 1;
+} EIFR_REGISTER, *PEIFR_REGISTER;
+// S007 ^^^
+
+//
+// Define pointer to IOB registers.
+//
+#define IOB_CONTROL ((volatile PIOB_REGISTERS)(KSEG1_BASE | IOB_PHYSICAL_BASE))
+
+
+//
+// Define SIC register structure.
+//
+typedef struct _SIC_REGISTER {
+ ULONG Long;
+ ULONG Fill;
+} SIC_REGISTER, *PSIC_REGISTER;
+
+typedef volatile struct _SIC_ERR_REGISTERS {
+ // offset(H)
+ SIC_REGISTER EIF0; // 0
+ SIC_REGISTER EIF1; // 8
+ SIC_REGISTER CKE0; // 10
+ SIC_REGISTER CKE1; // 18
+ SIC_REGISTER SECT; // 20
+ SIC_REGISTER Reserved; // 28
+ SIC_REGISTER STS1; // 30
+ SIC_REGISTER STS2; // 38
+ SIC_REGISTER RSRG; // 40
+} SIC_ERR_REGISTERS, *PSIC_ERR_REGISTERS;
+
+typedef volatile struct _SIC_DATA_REGISTERS {
+ // offset(H)
+ SIC_REGISTER DPCM; // 0
+ SIC_REGISTER DSRG; // 8
+ SIC_REGISTER SDLM; // 10
+// SIC_REGISTER Reserved[3]; // 18-28 // S009
+// SIC_REGISTER SDCR; // 30 // S009
+} SIC_DATA_REGISTERS, *PSIC_DATA_REGISTERS;
+
+// S008 vvv
+//
+// Define EIF0 register
+//
+typedef struct _EIF0_REGISTER {
+ ULONG Reserved : 2;
+ ULONG EXTD0MBE : 1;
+ ULONG EXTD0SBE : 1;
+ ULONG Reserved1 : 1;
+ ULONG INTD0PTE : 1;
+ ULONG INTD0MBE : 1;
+ ULONG INTD0SBE : 1;
+ ULONG ICEC : 1;
+ ULONG CPEC : 1;
+ ULONG APEC : 1;
+ ULONG RE1C : 1;
+ ULONG RE0C : 1;
+ ULONG SREC : 1;
+ ULONG RSEC : 1;
+ ULONG DTEJ : 1;
+ ULONG RSEJ : 1;
+ ULONG USYC : 1;
+ ULONG Reserved2 : 4;
+ ULONG IRMC : 1;
+ ULONG IRRC : 1;
+ ULONG Reserved3 : 3;
+ ULONG SBE : 1;
+ ULONG DPCG : 1;
+ ULONG APCG : 1;
+ ULONG MPRG : 1;
+ ULONG SWRG : 1;
+} EIF0_REGISTER, *PEIF0_REGISTER;
+
+//
+// Define STS2 register
+//
+typedef struct _STS2_REGISTER {
+ ULONG COL0_9 : 10;
+ ULONG COL10 : 1;
+ ULONG LOW0_9 : 10;
+ ULONG LOW10 : 1;
+ ULONG Reserved : 2;
+ ULONG RW : 1;
+ ULONG EXTMBE0 : 1;
+ ULONG EXTSBE0 : 1;
+ ULONG MBE0 : 1;
+ ULONG SBE0 : 1;
+ ULONG SIMN : 1;
+ ULONG ARE : 2;
+} STS2_REGISTER, *PSTS2_REGISTER;
+// S008 ^^^
+
+//
+// Define pointer to SIC registers.
+//
+#define SIC_ERR_CONTROL ((volatile PSIC_ERR_REGISTERS)(KSEG1_BASE | SIC_PHYSICAL_BASE | SIC_ERR_OFFSET))
+#define SIC_DATA_CONTROL ((volatile PSIC_DATA_REGISTERS)(KSEG1_BASE | SIC_PHYSICAL_BASE | SIC_DATA_OFFSET))
+/* Start S002 */
+#define SIC_ERR_CONTROL_OR(x) ((volatile PSIC_ERR_REGISTERS)(KSEG1_BASE | SIC_PHYSICAL_BASE | SIC_ERR_OFFSET | (x) ))
+#define SIC_DATA_CONTROL_OR(x) ((volatile PSIC_DATA_REGISTERS)(KSEG1_BASE | SIC_PHYSICAL_BASE | SIC_DATA_OFFSET | (x) ))
+/* End S002 */
+
+//
+// Define LR4360 register structure.
+//
+typedef volatile struct _LR_REGISTERS1 {
+ /* Start S004 */
+ // offset(H)
+ ULONG RSTC; // 0x0
+ ULONG DPRC; // 0x4
+ ULONG Reserved[1024]; // 0x8-0x1004
+ ULONG ERRS; // 0x1008
+ /* End S004 */
+} LR_REGISTERS1, *PLR_REGISTERS1;
+
+typedef volatile struct _LR_REGISTERS2 {
+ // offset(H)
+ ULONG iRPo; // 0
+ ULONG iRED; // 4
+ ULONG iRRE; // 8
+ ULONG iREN; // c
+ ULONG iRSF; // 10
+ ULONG iPoE; // 14
+ ULONG Reserved0[2]; // 18-1c
+ ULONG iFGE; // 20
+ ULONG iFGi; // 24
+ ULONG iRCS0; // 28
+ ULONG iRCS1; // 2c
+} LR_REGISTERS2, *PLR_REGISTERS2;
+
+typedef volatile struct _LR_PCI_DEVICE_REGISTERS {
+ // offset(H)
+ ULONG PTBAR0; // 0
+ ULONG PTBAR1; // 4
+ ULONG PTBAR2; // 8
+ ULONG PTBAR3; // c
+ ULONG PTBAR4; // 10
+ ULONG PTBAR5; // 14
+ ULONG PTBAR6; // 18
+ ULONG PTBAR7; // 1c
+ ULONG PTSZR; // 20
+ ULONG TPASZR; // 24
+ ULONG TFLR; // 28
+ ULONG PABAR; // 2c
+ ULONG AEAR; // 30
+ ULONG PEAR; // 34
+} LR_PCI_DEVICE_REGISTERS, *PLR_PCI_DEVICE_REGISTERS;
+
+//
+// Define Bbus LR4360 DMA channel register structure.
+//
+typedef struct _DMA_CHANNEL { // offset(H)
+ ULONG CnCF; // 0
+ ULONG CnDF; // 4
+ ULONG CnDC; // 8
+ ULONG Reserved1; // c
+ ULONG CnMA; // 10
+ ULONG CnBC; // 14
+ ULONG CnAK; // 18
+ ULONG CnFA; // 1c
+ ULONG CnCA; // 20
+} DMA_CHANNEL, *PDMA_CHANNEL;
+
+//
+// Define Device Channel # DMA Configuration register (CnDF register)
+//
+typedef struct _LR_DMA_CONFIG {
+ ULONG SWAP :1;
+ ULONG ASET :1;
+ ULONG ACKP :1;
+ ULONG REQP :1;
+ ULONG EOPCF :2;
+ ULONG EOPHO :1;
+ ULONG BUOFF :1;
+ ULONG EDEDE :1;
+ ULONG EXEDi :1;
+ ULONG iNEDE :1;
+ ULONG iNEDi :1;
+ ULONG CPUTi :1;
+ ULONG Reserved1 :3;
+ ULONG TMODE :2;
+ ULONG Reserved2 :14;
+} LR_DMA_CONFIG,*PLR_DMA_CONFIG;
+
+//
+// Define Device Channel # DMA Control register (CnDC register)
+//
+typedef struct _LR_DMA_CONTROL {
+ ULONG REQiE :1;
+ ULONG REQii :1;
+ ULONG REQWE :1;
+ ULONG REQiS :1;
+ ULONG MEMWT :1;
+ ULONG MEMWE :1;
+ ULONG Reserved1:2;
+ ULONG EXEDS :1;
+ ULONG iNEDS :1;
+ ULONG CREQS :1;
+ ULONG CERRS :1;
+ ULONG BFiFo :4;
+ ULONG FiFoV :1;
+ ULONG FiFoD :1;
+ ULONG FiFoF :1;
+ ULONG CHACOM :1;
+ ULONG Reserved2 :12;
+} LR_DMA_CONTROL,*PLR_DMA_CONTROL;
+
+//
+// Define pointer to LR4360 registers.
+//
+#define LR_CONTROL1 ((volatile PLR_REGISTERS1)(KSEG1_BASE | LR_PHYSICAL_CMNBASE1))
+#define LR_CONTROL2 ((volatile PLR_REGISTERS2)(KSEG1_BASE | LR_PHYSICAL_CMNBASE2))
+#define LR_PCI_DEV_REG_CONTROL ((volatile PLR_PCI_DEVICE_REGISTERS)(KSEG1_BASE | LR_PHYSICAL_PCI_DEV_REG_BASE))
+
+#endif // _R98REG_
diff --git a/private/ntos/nthals/halr98mp/mips/tga.h b/private/ntos/nthals/halr98mp/mips/tga.h
new file mode 100644
index 000000000..a8db1925a
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/tga.h
@@ -0,0 +1,101 @@
+#ident "@(#) NEC tga.h 1.1 94/11/29 14:09:17"
+/*++
+
+Module Name:
+
+ tga.h
+
+Abstract:
+
+ This module contains the register definitions for the TGA (DEC21030)
+
+Author:
+
+ T.Katoh create-data 1994/11/11
+
+Revision Histort:
+
+--*/
+
+/*
+ * D001 1994.11.29 T.Katoh
+ *
+ * Del: non-used definitions
+ * Chg: TGA_DSP_BUF_OFFSET value
+ * Add: VIDEO_BASE definition
+ */
+
+// TGA Core Space Map offset for 8-bpp Frame Buffers
+
+#define TGA_REG_SPC_OFFSET 0x00100000
+#define TGA_DSP_BUF_OFFSET 0x00200000 // D001
+
+// TGA register offsets, organized by functionality.
+
+#define PLANE_MASK 0x00000028
+#define ONE_SHOT_PIXEL_MASK 0x0000002C
+#define MODE 0x00000030
+#define RASTER_OP 0x00000034
+#define DEEP 0x00000050
+#define BLK_COLOR_R0 0X00000140
+#define BLK_COLOR_R1 0X00000144
+#define H_CONT 0x00000064
+#define V_CONT 0x00000068
+#define VIDEO_BASE 0x0000006c // D001
+#define VIDEO_VALID 0x00000070
+#define RAMDAC_SETUP 0x000000C0
+#define EEPROM_WRITE 0x000001e0
+#define CLOCK 0x000001e8
+#define RAMDAC_DATA 0X000001f0
+#define COMMAND_STATUS 0x000001f8
+
+// Initiate Palette Data
+
+#define VGA_INI_PALETTE_BLACK_R 0x00
+#define VGA_INI_PALETTE_BLACK_G 0x00
+#define VGA_INI_PALETTE_BLACK_B 0x00
+#define VGA_INI_PALETTE_RED_R 0xAA
+#define VGA_INI_PALETTE_RED_G 0x00
+#define VGA_INI_PALETTE_RED_B 0x00
+#define VGA_INI_PALETTE_GREEN_R 0x00
+#define VGA_INI_PALETTE_GREEN_B 0xAA
+#define VGA_INI_PALETTE_GREEN_G 0x00
+#define VGA_INI_PALETTE_YELLOW_R 0xAA
+#define VGA_INI_PALETTE_YELLOW_G 0xAA
+#define VGA_INI_PALETTE_YELLOW_B 0x00
+#define VGA_INI_PALETTE_BLUE_R 0x00
+#define VGA_INI_PALETTE_BLUE_G 0x00
+#define VGA_INI_PALETTE_BLUE_B 0xAA
+#define VGA_INI_PALETTE_MAGENTA_R 0xAA
+#define VGA_INI_PALETTE_MAGENTA_G 0x00
+#define VGA_INI_PALETTE_MAGENTA_B 0xAA
+#define VGA_INI_PALETTE_CYAN_R 0x00
+#define VGA_INI_PALETTE_CYAN_G 0xAA
+#define VGA_INI_PALETTE_CYAN_B 0xAA
+#define VGA_INI_PALETTE_WHITE_R 0xAA
+#define VGA_INI_PALETTE_WHITE_G 0xAA
+#define VGA_INI_PALETTE_WHITE_B 0xAA
+#define VGA_INI_PALETTE_HI_BLACK_R 0x00
+#define VGA_INI_PALETTE_HI_BLACK_G 0x00
+#define VGA_INI_PALETTE_HI_BLACK_B 0x00
+#define VGA_INI_PALETTE_HI_RED_R 0xFF
+#define VGA_INI_PALETTE_HI_RED_G 0x00
+#define VGA_INI_PALETTE_HI_RED_B 0x00
+#define VGA_INI_PALETTE_HI_GREEN_R 0x00
+#define VGA_INI_PALETTE_HI_GREEN_G 0xFF
+#define VGA_INI_PALETTE_HI_GREEN_B 0x00
+#define VGA_INI_PALETTE_HI_YELLOW_R 0xFF
+#define VGA_INI_PALETTE_HI_YELLOW_G 0xFF
+#define VGA_INI_PALETTE_HI_YELLOW_B 0x00
+#define VGA_INI_PALETTE_HI_BLUE_R 0x00
+#define VGA_INI_PALETTE_HI_BLUE_G 0x00
+#define VGA_INI_PALETTE_HI_BLUE_B 0xFF
+#define VGA_INI_PALETTE_HI_MAGENTA_R 0xFF
+#define VGA_INI_PALETTE_HI_MAGENTA_G 0x00
+#define VGA_INI_PALETTE_HI_MAGENTA_B 0xFF
+#define VGA_INI_PALETTE_HI_CYAN_R 0x00
+#define VGA_INI_PALETTE_HI_CYAN_G 0xFF
+#define VGA_INI_PALETTE_HI_CYAN_B 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_R 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_G 0xFF
+#define VGA_INI_PALETTE_HI_WHITE_B 0xFF
diff --git a/private/ntos/nthals/halr98mp/mips/x86bios.c b/private/ntos/nthals/halr98mp/mips/x86bios.c
new file mode 100644
index 000000000..4d65ad4e7
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/x86bios.c
@@ -0,0 +1,2 @@
+#pragma comment(exestr, "@(#) x86bios.c 1.3 95/06/19 11:44:39 nec")
+#include <..\..\halfxs\mips\x86bios.c>
diff --git a/private/ntos/nthals/halr98mp/mips/xxcalstl.c b/private/ntos/nthals/halr98mp/mips/xxcalstl.c
new file mode 100644
index 000000000..1ae682434
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/xxcalstl.c
@@ -0,0 +1,290 @@
+#ident "@(#) NEC xxcalstl.c 1.4 94/10/17 11:57:45"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ xxcalstl.c
+
+Abstract:
+
+
+ This module implements the calibration of the stall execution HAL
+ service, computes the count rate for the profile clock, and connects
+ the clock and profile interrupts for a MIPS R3000 or R4000 system.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.03/16-5/13 T.Samezima
+ *
+ * change HalpClockInterrupt0 vector
+ * HalpProfileInterrupt vector
+ *
+ * add PROFILE interrupt control
+ *
+ * del interrupt clear
+ * '#if defined(R3000)' with content
+ * only '#if defined(R4000)'
+ *
+ ***********************************************************************
+ *
+ * S002 94.03/16-5/13 T.Samezima
+ *
+ * Chg Designate member of structures
+ *
+ * S003 94.08/22 N.Kugimoto
+ * Chg Number 0 Bit Position is MSB (64Bit). So decremenet from 0x3f.
+ */
+
+
+#include "halp.h"
+#include "stdio.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, HalpCalibrateStall)
+#pragma alloc_text(INIT, HalpStallInterrupt)
+
+#endif
+
+//
+// Define global data used to calibrate and stall processor execution.
+//
+
+ULONG HalpProfileCountRate;
+ULONG volatile HalpStallEnd;
+ULONG HalpStallScaleFactor;
+ULONG volatile HalpStallStart;
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function calibrates the stall execution HAL service and connects
+ the clock and profile interrupts to the appropriate NT service routines.
+
+ 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.
+
+--*/
+
+{
+
+ ULONG Index;
+ KIRQL OldIrql;
+
+ //
+ // Use a range of scale factors from 50ns down to 10ns assuming a
+ // five instruction stall loop.
+ //
+
+ for (Index = 50; Index > 0; Index -= 10) {
+
+ //
+ // Disable all interrupts and establish calibration parameters.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Set the scale factor, stall count, starting stall count, and
+ // ending stall count values.
+ //
+
+ PCR->StallScaleFactor = 1000 / (Index * 5);
+ PCR->StallExecutionCount = 0;
+ HalpStallStart = 0;
+ HalpStallEnd = 0;
+
+ //
+ // Enable interrupts and stall execution.
+ //
+
+ KeLowerIrql(OldIrql);
+
+ //
+ // Stall execution for (MAXIMUM_INCREMENT / 10) * 4 us.
+ //
+
+ KeStallExecutionProcessor((MAXIMUM_INCREMENT / 10) * 4);
+
+ //
+ // If both the starting and ending stall counts have been captured,
+ // then break out of loop.
+ //
+
+ if ((HalpStallStart != 0) && (HalpStallEnd != 0)) {
+ break;
+ }
+
+ }
+
+ //
+ // Compute the profile interrupt rate.
+ //
+
+ HalpProfileCountRate =
+ HalpProfileCountRate * ((1000 * 1000 * 10) / MAXIMUM_INCREMENT);
+
+ //
+ // Compute the stall execution scale factor.
+ //
+
+ HalpStallScaleFactor = (HalpStallEnd - HalpStallStart +
+ ((MAXIMUM_INCREMENT / 10) - 1)) / (MAXIMUM_INCREMENT / 10);
+
+ if (HalpStallScaleFactor <= 0) {
+ HalpStallScaleFactor = 1;
+ }
+
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+
+ //
+ // Connect the real clock interrupt routine.
+ //
+
+ /* Start S001 */
+ PCR->InterruptRoutine[CLOCK_VECTOR] = HalpClockInterrupt0;
+ /* End S001 */
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ /* Start S001 */
+ PCR->InterruptRoutine[PROFILE_VECTOR] = HalpProfileInterrupt;
+ WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->MKSR.Long, 0x3f-IPR_PROFILE_BIT_NO ); // S002 S003
+ WRITE_REGISTER_ULONG( &(PMC_CONTROL1)->TMCR2.Long, 0x3 ); // S002
+ /* End S001 */
+
+ return TRUE;
+}
+
+VOID
+KeStallExecutionProcessor (
+ IN ULONG MicroSeconds
+ )
+
+/*++
+
+Routine Description:
+
+ This function stalls execution of the current processor for the specified
+ number of microseconds.
+
+Arguments:
+
+ MicroSeconds - Supplies the number of microseconds that execution is to
+ be stalled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG Index;
+
+ //
+ // Use the stall scale factor to determine the number of iterations
+ // the wait loop must be executed to stall the processor for the
+ // specified number of microseconds.
+ //
+
+ Index = MicroSeconds * PCR->StallScaleFactor;
+ do {
+ PCR->StallExecutionCount += 1;
+ Index -= 1;
+ } while (Index > 0);
+
+ return;
+}
+
+VOID
+HalpStallInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the stall calibration interrupt service
+ routine. It is executed in response to system clock interrupts
+ during the initialization of the HAL layer.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // If this is the very first interrupt, then wait for the second
+ // interrupt before starting the timing interval. Else, if this
+ // the second interrupt, then capture the starting stall count
+ // and clear the count register on R4000 processors. Else, if this
+ // is the third interrupt, then capture the ending stall count and
+ // the ending count register on R4000 processors. Else, if this is
+ // the fourth or subsequent interrupt, then simply dismiss it.
+ //
+
+ if ((HalpStallStart == 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = 1;
+
+ } else if ((HalpStallStart == 0) && (HalpStallEnd != 0)) {
+ HalpStallStart = PCR->StallExecutionCount;
+ HalpStallEnd = 0;
+ HalpWriteCompareRegisterAndClear(0);
+
+ } else if ((HalpStallStart != 0) && (HalpStallEnd == 0)) {
+ HalpStallEnd = PCR->StallExecutionCount;
+ HalpProfileCountRate = HalpWriteCompareRegisterAndClear(0);
+
+ }
+
+ return;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/xxclock.c b/private/ntos/nthals/halr98mp/mips/xxclock.c
new file mode 100644
index 000000000..51559bd63
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/xxclock.c
@@ -0,0 +1,131 @@
+#ident "@(#) NEC xxclock.c 1.4 94/10/23 20:39:13"
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ xxclock.c
+
+Abstract:
+
+
+ This module implements the function necesssary to change the clock
+ interrupt rate.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * M001 94.05/31 T.Samezima
+ *
+ * add check timer increment value
+ * set value use from HalpClockInterrupt1
+ *
+ * change increment unit from 1ms to 1us
+ *
+ * S002 '94.10/14 T.Samezima
+ * chg interval change flag
+ *
+ * S003 '94.10/23 T.Samezima
+ * chg variable size from ULONG to UCHAR
+ *
+ *
+ */
+
+
+#include "halp.h"
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextIntervalCount;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+/* Start M001 */
+UCHAR HalpChangeIntervalFlg[4]={0, 0, 0, 0}; // S003
+ULONG HalpChangeIntervalCount;
+/* End M001 */
+
+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;
+
+ /* Start M001 */
+ //
+ // If the specified time increment value is less that the minimum value
+ // or greater than the maximum value ,then set the time increment value
+ // to the minimum or maximum as appropriate.
+ //
+
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+
+ } else if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+ /* End S001 */
+
+ //
+ // 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);
+ /* Start M001 */
+ NextIntervalCount = DesiredIncrement / 10;
+ NewTimeIncrement = NextIntervalCount * 10;
+ /* End M001 */
+ HalpNextIntervalCount = NextIntervalCount;
+ HalpNewTimeIncrement = NewTimeIncrement;
+ /* Start M001 */
+ HalpChangeIntervalFlg[1] = 0xff; // S002
+ HalpChangeIntervalFlg[2] = 0xff; // S002
+ HalpChangeIntervalFlg[3] = 0xff; // S002
+ HalpChangeIntervalCount = HalpNextIntervalCount;
+ /* End M001 */
+ KeLowerIrql(OldIrql);
+ return NewTimeIncrement;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/xxidle.s b/private/ntos/nthals/halr98mp/mips/xxidle.s
new file mode 100644
index 000000000..e202c795c
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/xxidle.s
@@ -0,0 +1,76 @@
+// "@(#) NEC xxidle.s 1.2 94/10/17 11:59:42"
+// TITLE("Processor Idle")
+//++
+//
+// Copyright (c) 1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxidle.s
+//
+// Abstract:
+//
+// This module implements system platform dependent power management
+// support.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Processor Idle")
+//++
+//
+// 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 IE in PSR clear. This routine
+// must do any power management enabling necessary, set the IE
+// bit in PSR, then either return or wait for an interrupt.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalProcessorIdle)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ or v0,v0,1 << PSR_IE // set interrupt enable.
+ mtc0 v0,psr // enable interrupts
+ .set at
+ .set reorder
+
+//
+// Wait for an interrupt if supported.
+//
+
+ j ra // return
+
+ .end HalProcessorIdle
diff --git a/private/ntos/nthals/halr98mp/mips/xxinithl.c b/private/ntos/nthals/halr98mp/mips/xxinithl.c
new file mode 100644
index 000000000..917e97d75
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/xxinithl.c
@@ -0,0 +1,660 @@
+#ident "@(#) NEC xxinithl.c 1.12 95/06/19 11:45:28"
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ xxinithl.c
+
+Abstract:
+
+
+ This module implements the initialization of the system dependent
+ functions that define the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 system.
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * S001 94.03/09 T.Samezima
+ *
+ * add Spinlock HalpEifInterruptLock
+ *
+ * del only '#if defined(_DUO_)'
+ *
+ * K001 '94.5/30 (Mon) N.Kugimoto
+ * Add allocate contigus phys memory for Internal device
+ * use buffer.
+ *
+ * S002 '94.6/02 T.Samezima
+ *
+ * Add call HalpRegisterNmi
+ *
+ * S003 '94.8/25 T.Samezima
+ *
+ * Chg Set Io address before initialize interrupt
+ *
+ * S004 '94.9/26 T.Samezima
+ *
+ * Add Merge PCI Source Code
+ *
+ * K002 94/10/11 N.Kugimoto
+ * Fix 807 Base
+ * K003 94/10/13 N.Kugimoto
+ * Chg HalpBugCheckBuffer -->HalpEifRegisterBuffer
+ * -1 Chg HalpBusError logic change
+ * K004 94/10/13 N.Kugimoto
+ *
+ * S005 '94.12/08 T.Samezima
+ * Add Disable NMI.
+ *
+ * A002 1995/6/17 ataka@oa2.kb.nec.co.jp
+ * - marge 1050 halx86
+ * S006 1995/7/17 T.Samezima
+ * Del Init header.
+ */
+
+#include "halp.h"
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ );
+
+//
+// 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)
+#pragma alloc_text(INIT, HalStartNextProcessor)
+
+#endif
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+/* Start S001 */
+KSPIN_LOCK HalpEifInterruptLock;
+/* End S001 */
+
+
+// K002 vvvvv
+// Define bug check information buffer and callback record.
+//
+#if !defined(_R98_) //K003
+typedef struct _HALP_BUGCHECK_BUFFER {
+ ULONG FailedAddress;
+ ULONG DiagnosticLow;
+ ULONG DiagnosticHigh;
+} HALP_BUGCHECK_BUFFER, *PHALP_BUGCHECK_BUFFER;
+
+HALP_BUGCHECK_BUFFER HalpBugCheckBuffer;
+#endif
+
+KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord;
+
+UCHAR HalpComponentId[] = "hal.dll";
+// K002^^^^
+
+BOOLEAN
+HalInitSystem (
+ IN ULONG Phase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes the Hardware Architecture Layer (HAL) for a
+ MIPS R3000 or R4000 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;
+ //K002 vvvv
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PHYSICAL_ADDRESS ZeroAddress;
+ ULONG AddressSpace;
+ //K002 ^^^^
+ //
+ // Initialize the HAL components based on the phase of initialization
+ // and the processor number.
+ //
+
+ Prcb = PCR->Prcb;
+ PCR->DataBusError = HalpBusError; //K002
+ PCR->InstructionBusError = HalpBusError; //K002
+ if ((Phase == 0) || (Prcb->Number != 0)) {
+
+ //
+ // Phase 0 initialization.
+ //
+ // N.B. Phase 0 initialization is executed on all processors.
+ //
+ // 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);
+ }
+
+ //
+ // Map the fixed TB entries.
+ //
+
+ HalpMapFixedTbEntries();
+
+ //
+ // If processor 0 is being initialized, then initialize various
+ // variables, spin locks, and the display adapter.
+ //
+
+ if (Prcb->Number == 0) {
+
+
+ /* Start S002 */
+ //
+ // Set NMI interrupt service routine
+ //
+
+#if !defined(DISABLE_NMI) //
+ HalpRegisterNmi();
+#endif
+ /* End S002 */
+
+ //
+ // Set the number of process id's and TB entries.
+ //
+
+ **((PULONG *)(&KeNumberProcessIds)) = 256;
+ **((PULONG *)(&KeNumberTbEntries)) = 48;
+
+ //
+ // Set the interval clock increment value.
+ //
+
+ HalpCurrentTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextTimeIncrement = MAXIMUM_INCREMENT;
+ HalpNextIntervalCount = 0;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+ // A002
+ // Set DMA I/O coherency attributes.
+ //
+ KeSetDmaIoCoherency(DMA_READ_DCACHE_INVALIDATE | DMA_READ_ICACHE_INVALIDATE | DMA_WRITE_DCACHE_SNOOP);
+
+ //
+ // Initialize all spin locks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+ /* Start S001 */
+ KeInitializeSpinLock(&HalpEifInterruptLock);
+ /* End S001 */
+
+ //
+ // Set address of cache error routine.
+ //
+
+ KeSetCacheErrorRoutine(HalpCacheErrorRoutine);
+
+ //
+ // Initialize the display adapter.
+ //
+
+ HalpInitializeDisplay0(LoaderBlock);
+
+ //
+ // Allocate map register memory.
+ //
+
+ HalpAllocateMapRegisters(LoaderBlock);
+
+ // K001 Start
+ // For Internal Device use buffer
+ //
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
+
+ //
+ // Allocate map buffers for the adapter objects
+ //
+
+ HalpMapBufferPhysicalAddress.LowPart =
+ HalpAllocPhysicalMemory (LoaderBlock, MAXIMUM_PHYSICAL_ADDRESS,
+ HalpMapBufferSize >> PAGE_SHIFT, TRUE);
+ HalpMapBufferPhysicalAddress.HighPart = 0;
+
+
+ if (!HalpMapBufferPhysicalAddress.LowPart) {
+
+ //
+ // There was not a satisfactory block. Clear the allocation.
+ //
+
+ HalpMapBufferSize = 0;
+
+ } // End of K001
+ // K002 vvvv
+ // Initialize and register a bug check callback record.
+ //
+
+ KeInitializeCallbackRecord(&HalpCallbackRecord);
+ KeRegisterBugCheckCallback(&HalpCallbackRecord,
+ HalpBugCheckCallback,
+#if defined(_R98_) //K003
+ HalpEifRegisterBuffer,
+#else
+ &HalpBugCheckBuffer,
+#endif
+ 41*4, //K003
+ &HalpComponentId[0]);
+
+ // K002 ^^^^
+
+ }
+
+ // Start S003
+#if defined(_R98_)
+ //
+ // Initialize I/O address
+ //
+
+ HalpMapIoSpace();
+#endif
+ // End S003
+
+ //
+ // Initialize interrupts
+ //
+
+ HalpInitializeInterrupts();
+ return TRUE;
+
+ } else {
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+ //
+ // Complete initialization of the display adapter.
+ //
+
+ HalpRegisterInternalBusHandlers (); // A002
+
+ if (HalpInitializeDisplay1(LoaderBlock) == FALSE) {
+ return FALSE;
+
+ } else {
+
+ //
+ // Map I/O space, calibrate the stall execution scale factor,
+ // and create DMA data structures.
+ //
+
+ // Start S003
+#if !defined(_R98_)
+ HalpMapIoSpace();
+#endif
+ // End S003
+ HalpCalibrateStall();
+ HalpCreateDmaStructures();
+
+ // K002 vvvvv
+ // Map EISA memory space so the x86 bios emulator emulator can
+ // initialze a video adapter in an EISA slot.
+ //
+
+ ZeroAddress.QuadPart = 0;
+ AddressSpace = 0;
+ HalTranslateBusAddress(Isa,
+ 0,
+ ZeroAddress,
+ &AddressSpace,
+ &PhysicalAddress);
+
+ HalpEisaMemoryBase = MmMapIoSpace(PhysicalAddress,
+ PAGE_SIZE * 256,
+ FALSE);
+
+ HalpInitializeX86DisplayAdapter();
+
+ // K002 ^^^^^
+
+ return TRUE;
+ }
+ }
+}
+
+//K002 vvvv
+// no change
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a bug check occurs. Its function is
+ to dump the state of the memory error registers into a bug check
+ buffer.
+
+Arguments:
+
+ Buffer - Supplies a pointer to the bug check buffer.
+
+ Length - Supplies the length of the bug check buffer in bytes.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+#if !defined(_R98_) //K003
+ PHALP_BUGCHECK_BUFFER DumpBuffer;
+
+ //
+ // Capture the failed memory address and diagnostic registers.
+ //
+
+ DumpBuffer = (PHALP_BUGCHECK_BUFFER)Buffer;
+
+#if defined(_DUO_)
+
+ DumpBuffer->DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long;
+
+ DumpBuffer->DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart;
+
+#else
+
+ DumpBuffer->DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long;
+
+ DumpBuffer->DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long;
+
+#endif
+
+ DumpBuffer->FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long;
+#endif //_R98_
+ return;
+}
+
+BOOLEAN
+HalpBusError (
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN PKEXCEPTION_FRAME ExceptionFrame,
+ IN PKTRAP_FRAME TrapFrame,
+ IN PVOID VirtualAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the default bus error handling routine for NT.
+
+ N.B. There is no return from this routine.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ ExceptionFrame - Supplies a pointer to an exception frame.
+
+ TrapFrame - Supplies a pointer to a trap frame.
+
+ VirtualAddress - Supplies the virtual address of the bus error.
+
+ PhysicalAddress - Supplies the physical address of the bus error.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ ULONG DiagnosticHigh;
+ ULONG DiagnosticLow;
+#if !defined(_R98_) //K003-1
+ ULONG FailedAddress;
+
+
+ //
+ // Bug check specifying the exception code, the virtual address, the
+ // failed memory address, and either the ECC diagnostic registers or
+ // the parity diagnostic registers depending on the platform.
+ //
+
+#if defined(_DUO_)
+
+ DiagnosticLow =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress.Long;
+
+ DiagnosticHigh =
+ (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->EccDiagnostic.u.LargeInteger.HighPart;
+
+#else
+
+ DiagnosticLow = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticLow.Long;
+ DiagnosticHigh = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->ParityDiagnosticHigh.Long;
+
+#endif
+
+ FailedAddress = (ULONG)((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->MemoryFailedAddress.Long;
+#else //_R98_
+ ULONG AllError;
+ DiagnosticLow =READ_REGISTER_ULONG(&( PMC_CONTROL2 )->EADRL.Long);
+ DiagnosticHigh =READ_REGISTER_ULONG(&( PMC_CONTROL2 )->EADRH.Long);
+ AllError =READ_REGISTER_ULONG(&( PMC_CONTROL1 )->AERR.Long); //K003
+#endif
+
+ KeBugCheckEx(ExceptionRecord->ExceptionCode & 0xffff,
+ (ULONG)VirtualAddress,
+#if defined(_R98_) //K003
+ AllError,
+#else
+ FailedAddress,
+#endif
+ DiagnosticLow,
+
+ DiagnosticHigh);
+
+ return FALSE;
+}
+
+//K002 ^^^^
+
+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.
+
+--*/
+
+{
+ return;
+}
+
+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 the address of the first restart parameter block is NULL, then
+ // the host system is a uniprocessor system running with old firmware.
+ // Otherwise, the host system may be a multiprocessor system if more
+ // than one restart block is present.
+ //
+ // N.B. The first restart parameter block must be for the boot master
+ // and must represent logical processor 0.
+ //
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if (NextRestartBlock == NULL) {
+ return FALSE;
+ }
+
+ //
+ // 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.
+ //
+
+ Number = 0;
+ do {
+ if ((NextRestartBlock->BootStatus.ProcessorReady != FALSE) &&
+ (NextRestartBlock->BootStatus.ProcessorStart == FALSE)) {
+ RtlZeroMemory(&NextRestartBlock->u.Mips, sizeof(MIPS_RESTART_STATE));
+ NextRestartBlock->u.Mips.IntA0 = ProcessorState->ContextFrame.IntA0;
+ NextRestartBlock->u.Mips.Fir = ProcessorState->ContextFrame.Fir;
+ Prcb = (PKPRCB)(LoaderBlock->Prcb);
+ Prcb->Number = (CCHAR)Number;
+ Prcb->RestartBlock = NextRestartBlock;
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ return TRUE;
+ }
+
+ Number += 1;
+ NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ } while (NextRestartBlock != NULL);
+
+ return FALSE;
+}
+
+VOID
+HalpVerifyPrcbVersion(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function ?
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ return;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/xxinitnt.c b/private/ntos/nthals/halr98mp/mips/xxinitnt.c
new file mode 100644
index 000000000..ad3750771
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/xxinitnt.c
@@ -0,0 +1,556 @@
+#ident "@(#) NEC xxinitnt.c 1.18 95/03/17 11:59:37"
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * L001 94.03/22-5/13 T.Samezima
+ *
+ * add control of Eif interrupt.
+ * make table of change from iRRE bit number to NABus code.
+ * make table of arbitration table and arbitration pointer.
+ * make variable for access of registers.
+ * connect the timer interrupt service routine.
+ * clear unknown interrupt counter
+ *
+ * del only '#if defined(_DUO_)'
+ * '#if defined(_JAZZ_)' with content
+ * HalpCountInterrupt()
+ *
+ * change interrupt control
+ * various vector of interrupt service routine
+ *
+ ***********************************************************************
+ *
+ * S002 94.5/17 T.Samezima
+ *
+ * del Arbitration table
+ *
+ ***********************************************************************
+ *
+ * S003 94.6/10-14 T.Samezima
+ *
+ * del Compile err
+ *
+ ***********************************************************************
+ *
+ * S004 94.7/7 T.Samezima
+ *
+ * Chg Use UNKNOWN_COUNT_BUF_LEN to max
+ * for HalpUnknownInterruptCount
+ *
+ ***********************************************************************
+ *
+ * S005 94.7/7 T.Samezima
+ *
+ * Del move interrupt arbitration pointer to r98dspt.c
+ *
+ ***********************************************************************
+ *
+ * S006 94.7/23 T.Samezima
+ *
+ * Add Enable EIF interrupt on SIC.
+ *
+ ***********************************************************************
+ *
+ * S007 94.8/22 T.Samezima on SNES
+ *
+ * Chg Register buffer size from USHORT to ULONG
+ * Value of set to MKSR register
+ * Condition change
+ *
+ * Add Clear interrupt pending bit on edge level interrupt
+ *
+ * Del Move EISA NMI enable logic to HalpCreateEisaStructure()
+ *
+ ***********************************************************************
+ *
+ * S008 94.9/5 T.Samezima
+ *
+ * Add Institute number of repeat for interrupt clear loop
+ *
+ ***********************************************************************
+ *
+ * S009 94.9/16 T.Samezima
+ *
+ * Chg Only CPU#0 on I/O Initerrupt clear
+ *
+ ***********************************************************************
+ *
+ * S00a 94.10/14 T.Samezima
+ *
+ * Fix Version Up at build807
+ * -Move Int1 interrupt enable to allstart.c
+ *
+ * S00b 94.10/18 T.Samezima
+ * Chg Enable interrupt on MKR register only exist device,
+ *
+ * S00c 94.12/06 T.Samezima
+ * Bug Disable ECC 1bit error interrupt.
+ *
+ * S00d 94.12/06 T.Samezima
+ * Add Disable NMI
+ *
+ * S00e 95.01/10 T.Samezima
+ * Add Enable ECC 1bit error interrupt
+ * Rewrite cycle start on ecc 1bit error
+ *
+ * S00f 95.01/24 T.Samezima
+ * Add Disable rewrite cycle on ecc 1bit error
+ *
+ * S010 95.03/13 T.Samezima
+ * Add Enable HW cache flush.
+ *
+ */
+
+#include "halp.h"
+#include "eisa.h" // S003
+
+
+//
+// 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, HalpInitializeInterrupts)
+
+#endif
+
+//
+// Define global data for builtin device interrupt enables.
+//
+
+ULONG HalpBuiltinInterruptEnable; // S007
+
+//
+// Define the IRQL mask and level mapping table.
+//
+// These tables are transfered to the PCR and determine the priority of
+// interrupts.
+//
+// N.B. The two software interrupt levels MUST be the lowest levels.
+//
+
+UCHAR HalpIrqlMask[] = {4, 5, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 4, 4, 4, 4, 4, 4, 4, 4}; // 1000 - 1111 low 4-bits
+
+UCHAR HalpIrqlTable[] = {0xff, // IRQL 0
+ 0xfe, // IRQL 1
+ 0xfc, // IRQL 2
+ 0xf8, // IRQL 3
+ 0xf0, // IRQL 4
+ 0xe0, // IRQL 5
+ 0xc0, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+/* Start L001 */
+//
+// Define table of change from iRRE bit number to NABus code
+//
+ULONG HalpNaBusCodeTable[] = {0x8000, 0x0010, // iRRE bit0,1
+ 0x0006, 0x0000, // iRRE bit2,3
+ 0x0002, 0x0002, // iRRE bit4,5
+ 0x000a, 0x000a, // iRRE bit6,7
+ 0x0008, 0x000c, // iRRE bit8,9
+ 0x8000, 0x8000, // iRRE bit10,11
+ 0x8000, 0x8000, // iRRE bit12,13
+ 0x8000, 0x8000, // iRRE bit14,15
+ 0x8000, 0x0004, // iRRE bit16,17
+ 0x8000, 0x8000, // iRRE bit18,19
+ 0x8000, 0x8000, // iRRE bit20,21
+ 0x000c, 0x8000, // iRRE bit22,23
+ 0x8000, 0x8000, // iRRE bit24,25
+ 0x8000, 0x8000, // iRRE bit26,27
+ 0x8000, 0x8000, // iRRE bit28,29
+ 0x8000, 0x8000 }; // iRRE bit30,31
+
+//
+// Define table of order of interrupt arbitration
+//
+
+ULONG HalpUnknownInterruptCount[UNKNOWN_COUNT_BUF_LEN]; // S004
+
+/* End L001*/
+
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a Jazz or Duo MIPS system.
+
+ N.B. This function is only called during phase 0 initialization.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+
+ USHORT DataShort;
+ ULONG DataLong;
+ ULONG Index;
+ PKPRCB Prcb;
+ /* Start L001 */
+ ULONG pmcRegisterAddr;
+ ULONG pmcRegisterUpperPart;
+ ULONG pmcRegisterLowerPart;
+ ULONG bitCount;
+ ULONG buffer;
+ ULONG buffer2; // S006
+ UCHAR charBuffer;
+ LONG repeatCounter; // S008
+ /* End L001 */
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ //
+ // Initialize the IRQL translation tables in the PCR. These tables are
+ // used by the interrupt dispatcher to determine the new IRQL and the
+ // mask value that is to be loaded into the PSR. They are also used by
+ // the routines that raise and lower IRQL to load a new mask value into
+ // the PSR.
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask); Index += 1) {
+ PCR->IrqlMask[Index] = HalpIrqlMask[Index];
+ }
+
+ for (Index = 0; Index < sizeof(HalpIrqlTable); Index += 1) {
+ PCR->IrqlTable[Index] = HalpIrqlTable[Index];
+ }
+
+ /* Start L001 */
+ //
+ // All interrupt disables.
+ //
+
+ pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003
+ pmcRegisterUpperPart = MKR_DISABLE_ALL_INTERRUPT_HIGH;
+ pmcRegisterLowerPart = MKR_DISABLE_ALL_INTERRUPT_LOW;
+ HalpWriteLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ //
+ // If processor 0 is being initialized, then set all device
+ // interrupt disables.
+ //
+
+ if (Prcb->Number == 0) {
+ HalpBuiltinInterruptEnable = iREN_DISABLE_ALL_INTERRUPT;
+
+ for (Index = 0; Index < UNKNOWN_COUNT_BUF_LEN; Index += 1) { // S004
+ HalpUnknownInterruptCount[Index] = 0;
+ }
+// } // S009
+ /* End L001 */
+
+ //
+ // Disable individual device interrupts and make sure no device interrupts
+ // are pending.
+ //
+
+ /* Start L001 */
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iREN,
+ HalpBuiltinInterruptEnable );
+
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIMR.Long,
+ EIMR_DISABLE_ALL_EIF );
+
+ repeatCounter = 0; // S008
+
+ while( ((DataLong = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE) & iRRE_MASK) != 0) &&
+ (++repeatCounter < 16) ) { // S008
+ for( bitCount = 0 ; bitCount <= 31 ; bitCount++ ) {
+ if( (DataLong & ( 1 << bitCount )) != 0) {
+ // Start S007
+ if( bitCount < 15 ){
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iRSF,
+ ( 1 << bitCount ) );
+ }
+ // End S007
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AIMR.Long,
+ HalpNaBusCodeTable[bitCount] );
+ }
+ }
+ WRITE_REGISTER_ULONG( &( LR_CONTROL2 )->iRSF,
+ iRSF_CLEAR_INTERRUPT );
+ pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->IPRR ); // S003
+ pmcRegisterUpperPart = 0x0;
+ pmcRegisterLowerPart = 0xffffffff;
+ HalpWriteLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+ }
+ /* End L001 */
+
+ HalpBuiltinInterruptEnable |= 0x10; // S010
+
+ //
+ // If processor 0 is being initialized, then enable device interrupts.
+ //
+
+// if (Prcb->Number == 0) { // S009
+ /* Start L001 */
+ //
+ // Enable INT0-1 interrupt on PMC
+ //
+
+ /* Start S003 */
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII0.Long,
+ AII_INIT_DATA );
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII1.Long,
+ AII_INIT_DATA );
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII2.Long,
+ AII_INIT_DATA );
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->AII3.Long,
+ AII_INIT_DATA );
+ /* End S003 */
+
+ pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003
+ HalpReadLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+ pmcRegisterLowerPart = ( pmcRegisterLowerPart
+ | MKR_INT0_DEVICE_ENABLE_LOW // S00b
+// | MKR_INT1_DEVICE_ENABLE_LOW // S00a, S00b
+ | MKR_INT2_DEVICE_ENABLE_LOW // S00b
+ ); // S003
+ HalpWriteLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+// DataLong = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long);
+// DataLong |= ENABLE_DEVICE_INTERRUPTS;
+// WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InterruptEnable.Long,
+// DataLong);
+ /* End L001 */
+ }
+
+ /* Start L001 */
+ //
+ // Connect the eif interrupt to the eif interrupt routine
+ //
+
+ PCR->InterruptRoutine[EIF_LEVEL] = HalpEifDispatch;
+
+ //
+ // Enable the eif interrupt
+ //
+
+ pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003
+ HalpReadLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+ pmcRegisterUpperPart = ( pmcRegisterUpperPart | MKR_INT5_ENABLE_HIGH );
+ pmcRegisterLowerPart = ( pmcRegisterLowerPart | MKR_INT5_ENABLE_LOW );
+ HalpWriteLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ buffer = READ_REGISTER_ULONG( &( PMC_CONTROL1 )->STSR.Long);
+ buffer = (buffer | STSR_EIF_ENABLE);
+#if defined(DISABLE_NMI) // S00d
+ buffer = (buffer | STSR_NMI_DISABLE);
+#endif
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->STSR.Long, buffer);
+
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->ERRMK.Long, ERRMK_EIF_ENABLE);
+
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->IEMR.Long, IEMR_ENABLE_ALL_EIF);
+
+ WRITE_REGISTER_ULONG( &( IOB_CONTROL )->EIMR.Long, EIMR_ENABLE_ALL_EIF);
+
+ /* Start S006 */
+ buffer = READ_REGISTER_ULONG( &( IOB_CONTROL )->SCFR.Long );
+ IOB_DUMMY_READ;
+
+ if( (buffer & SCFR_SIC_SET0_CONNECT) == 0 ) { // S007
+ buffer2 = READ_REGISTER_ULONG( &(SIC_ERR_CONTROL_OR(SIC_NO0_OFFSET))->CKE0.Long );
+ buffer2 &= CKE0_DISABLE_SBE; // S00c
+ buffer2 |= CKE0_ENABLE_ALL_EIF;
+ WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET0_OFFSET) )->CKE0.Long,
+ buffer2
+ );
+ // S00e vvv
+ buffer2 = READ_REGISTER_ULONG( &(SIC_DATA_CONTROL_OR(SIC_NO0_OFFSET))->DPCM.Long );
+ buffer2 &= DPCM_ENABLE_MASK; // S00c
+ WRITE_REGISTER_ULONG( &( SIC_DATA_CONTROL_OR(SIC_SET0_OFFSET) )->DPCM.Long,
+ buffer2
+ );
+
+#if 0 // S00f
+ WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET0_OFFSET) )->SECT.Long,
+ SECT_REWRITE_ENABLE
+ );
+#endif
+ // S00e ^^^
+
+ WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET0_OFFSET) )->CKE1.Long,
+ CKE1_ENABLE_ALL_EIF
+ );
+ }
+
+ if( (buffer & SCFR_SIC_SET1_CONNECT) == 0 ) { // S007
+ buffer2 = READ_REGISTER_ULONG( &(SIC_ERR_CONTROL_OR(SIC_NO2_OFFSET))->CKE0.Long );
+ buffer2 &= CKE0_DISABLE_SBE; // S00c
+ buffer2 |= CKE0_ENABLE_ALL_EIF;
+ WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET1_OFFSET) )->CKE0.Long,
+ buffer2
+ );
+ // S00e vvv
+ buffer2 = READ_REGISTER_ULONG( &(SIC_DATA_CONTROL_OR(SIC_NO2_OFFSET))->DPCM.Long );
+ buffer2 &= DPCM_ENABLE_MASK; // S00c
+ WRITE_REGISTER_ULONG( &( SIC_DATA_CONTROL_OR(SIC_SET1_OFFSET) )->DPCM.Long,
+ buffer2
+ );
+#if 0 // S00f
+ WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET1_OFFSET) )->SECT.Long,
+ SECT_REWRITE_ENABLE
+ );
+#endif
+ // S00e ^^^
+
+ WRITE_REGISTER_ULONG( &( SIC_ERR_CONTROL_OR(SIC_SET1_OFFSET) )->CKE1.Long,
+ CKE1_ENABLE_ALL_EIF
+ );
+ }
+ /* End S006 */
+
+ // S007
+
+ //
+ // If processor 0 is being initialized, then connect the interval timer
+ // interrupt to the stall interrupt routine so the stall execution count
+ // can be computed during phase 1 initialization. Otherwise, connect the
+ // interval timer interrupt to the appropriate interrupt service routine
+ // and set stall execution count from the computation made on processor
+ // 0.
+ //
+
+ PCR->InterruptRoutine[TIMER_LEVEL] = HalpTimerDispatch; // S003
+
+ if (Prcb->Number == 0) {
+ /* Start L001 */
+ PCR->InterruptRoutine[CLOCK_VECTOR] = HalpStallInterrupt;
+ /* End L001 */
+ } else {
+ /* Start L001 */
+ PCR->InterruptRoutine[CLOCK_VECTOR] = HalpClockInterrupt1;
+ /* End L001 */
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+ }
+
+ //
+ // Initialize the interval timer to interrupt at the specified interval.
+ //
+
+ /* Start L001 */
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR1.Long, CLOCK_INTERVAL);
+
+ //
+ // Initialize the profile timer to interrupt at the default interval.
+ //
+
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMSR2.Long,
+ DEFAULT_PROFILETIMER_COUNT);
+ /* End L001 */
+
+ //
+ // Enable the interval timer interrupt on the current processor.
+ //
+
+ /* Start L001 */
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->MKSR.Long, 0x3f-IPR_CLOCK_BIT_NO); // S007
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR1.Long, 0x3);
+ /* End L001 */
+
+ //
+ // If processor 0 is being initialized, then connect the count/compare
+ // interrupt to the count interrupt routine to handle early count/compare
+ // interrupts during phase 1 initialization. Otherwise, connect the
+ // count\comapre interrupt to the appropriate interrupt service routine.
+ //
+
+ /* Start L001 */
+ if (Prcb->Number != 0) {
+ PCR->InterruptRoutine[PROFILE_VECTOR] = HalpProfileInterrupt;
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->MKSR.Long, 0x3f-IPR_PROFILE_BIT_NO); // S007
+ WRITE_REGISTER_ULONG( &( PMC_CONTROL1 )->TMCR2.Long, 0x3);
+ }
+ /* End L001 */
+
+ //
+ // Connect the interprocessor interrupt service routine and enable
+ // interprocessor interrupts.
+ //
+
+ PCR->InterruptRoutine[IPI_LEVEL] = HalpIpiInterrupt;
+
+ /*Start L001 */
+ pmcRegisterAddr = (ULONG)( &(PMC_CONTROL1)->MKR ); // S003
+ HalpReadLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+ pmcRegisterUpperPart = ( pmcRegisterUpperPart | MKR_INT4_ENABLE_HIGH );
+ pmcRegisterLowerPart = ( pmcRegisterLowerPart | MKR_INT4_ENABLE_LOW );
+ HalpWriteLargeRegister( pmcRegisterAddr,
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+ /*End L001 */
+
+ //
+ // Reserve the local device interrupt vector for exclusive use by the HAL.
+ //
+
+
+ /* Start L001 */
+// PCR->ReservedVectors |= (1 << DEVICE_LEVEL);
+// PCR->ReservedVectors |= (1 << INT1_LEVEL); // S00a
+ PCR->ReservedVectors |= (1 << INT2_LEVEL);
+ /* End L001 */
+
+ return TRUE;
+}
diff --git a/private/ntos/nthals/halr98mp/mips/xxmemory.c b/private/ntos/nthals/halr98mp/mips/xxmemory.c
new file mode 100644
index 000000000..bd7dba343
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/xxmemory.c
@@ -0,0 +1,184 @@
+#pragma comment(exestr, "@(#) xxmemory.c 1.3 94/10/17 13:25:21 nec")
+/*++
+
+Copyright (c) 1991-1994 Microsoft Corporation
+
+Module Name:
+
+ xxmemory.c
+
+Abstract:
+
+ Provides routines to allow the HAL to map physical memory.
+
+Environment:
+
+ Phase 0 initialization only.
+
+Revision History:
+
+--*/
+
+/*
+ * Original source: Build Number 1.612
+ *
+ * Modify for R98(MIPS/R4400)
+ *
+ ***********************************************************************
+ *
+ * K001 '94.5/30 (Mon) N.Kugimoto
+ * FRM HalpAllocPhysicalMemory() From halx86
+ *
+ ***********************************************************************
+ *
+ * S001 '94.6/14 T.Samezima
+ * Chg Compile err del
+ *
+ *
+ */
+
+#include "halp.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpAllocPhysicalMemory)
+#endif
+
+// S001
+MEMORY_ALLOCATION_DESCRIPTOR HalpExtraAllocationDescriptor;
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ )
+/*++
+
+Routine Description:
+
+ Carves out N pages of physical memory from the memory descriptor
+ list in the desired location. This function is to be called only
+ during phase zero initialization. (ie, before the kernel's memory
+ management system is running)
+
+Arguments:
+
+ MaxPhysicalAddress - The max address where the physical memory can be
+ NoPages - Number of pages to allocate
+
+Return Value:
+
+ The physical address or NULL if the memory could not be obtained.
+
+--*/
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ ULONG AlignmentOffset;
+ ULONG MaxPageAddress;
+ ULONG PhysicalAddress;
+
+ MaxPageAddress = MaxPhysicalAddress >> PAGE_SHIFT;
+
+ //
+ // Scan the memory allocation descriptors and allocate map buffers
+ //
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+ Descriptor = CONTAINING_RECORD(NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry);
+
+ AlignmentOffset = bAlignOn64k ?
+ ((Descriptor->BasePage + 0x0f) & ~0x0f) - Descriptor->BasePage :
+ 0;
+
+ //
+ // Search for a block of memory which is contains a memory chuck
+ // that is greater than size pages, and has a physical address less
+ // than MAXIMUM_PHYSICAL_ADDRESS.
+ //
+
+ if ((Descriptor->MemoryType == LoaderFree ||
+ Descriptor->MemoryType == MemoryFirmwareTemporary) &&
+ (Descriptor->BasePage) &&
+ (Descriptor->PageCount >= NoPages + AlignmentOffset) &&
+ (Descriptor->BasePage + NoPages + AlignmentOffset < MaxPageAddress)) {
+
+ PhysicalAddress =
+ (Descriptor->BasePage + AlignmentOffset) << PAGE_SHIFT;
+ break;
+ }
+
+ NextMd = NextMd->Flink;
+ }
+
+ //
+ // Use the extra descriptor to define the memory at the end of the
+ // original block.
+ //
+
+
+ ASSERT(NextMd != &LoaderBlock->MemoryDescriptorListHead);
+
+ if (NextMd == &LoaderBlock->MemoryDescriptorListHead)
+ return (ULONG)NULL;
+
+ //
+ // Adjust the memory descriptors.
+ //
+
+ if (AlignmentOffset == 0) {
+
+ Descriptor->BasePage += NoPages;
+ Descriptor->PageCount -= NoPages;
+
+ if (Descriptor->PageCount == 0) {
+
+ //
+ // The whole block was allocated,
+ // Remove the entry from the list completely.
+ //
+
+ RemoveEntryList(&Descriptor->ListEntry);
+
+ }
+
+ } else {
+
+ if (Descriptor->PageCount - NoPages - AlignmentOffset) {
+
+ //
+ // Currently we only allow one Align64K allocation
+ //
+ ASSERT (HalpExtraAllocationDescriptor.PageCount == 0);
+
+ //
+ // The extra descriptor is needed so intialize it and insert
+ // it in the list.
+ //
+ HalpExtraAllocationDescriptor.PageCount =
+ Descriptor->PageCount - NoPages - AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.BasePage =
+ Descriptor->BasePage + NoPages + AlignmentOffset;
+
+ HalpExtraAllocationDescriptor.MemoryType = MemoryFree;
+ InsertTailList(
+ &Descriptor->ListEntry,
+ &HalpExtraAllocationDescriptor.ListEntry
+ );
+ }
+
+
+ //
+ // Use the current entry as the descriptor for the first block.
+ //
+
+ Descriptor->PageCount = AlignmentOffset;
+ }
+
+ return PhysicalAddress;
+}