summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halsnip/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/halsnip/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/halsnip/mips')
-rw-r--r--private/ntos/nthals/halsnip/mips/allstart.c65
-rw-r--r--private/ntos/nthals/halsnip/mips/cacherr.s645
-rw-r--r--private/ntos/nthals/halsnip/mips/duocache.s780
-rw-r--r--private/ntos/nthals/halsnip/mips/halp.h280
-rw-r--r--private/ntos/nthals/halsnip/mips/i82c54.h34
-rw-r--r--private/ntos/nthals/halsnip/mips/j4flshbf.s53
-rw-r--r--private/ntos/nthals/halsnip/mips/j4flshio.c199
-rw-r--r--private/ntos/nthals/halsnip/mips/j4prof.c316
-rw-r--r--private/ntos/nthals/halsnip/mips/jxbeep.c132
-rw-r--r--private/ntos/nthals/halsnip/mips/jxebsup.c2760
-rw-r--r--private/ntos/nthals/halsnip/mips/jxenvirv.c192
-rw-r--r--private/ntos/nthals/halsnip/mips/jxhwsup.c2250
-rw-r--r--private/ntos/nthals/halsnip/mips/jxmapio.c120
-rw-r--r--private/ntos/nthals/halsnip/mips/jxport.c805
-rw-r--r--private/ntos/nthals/halsnip/mips/jxreturn.c286
-rw-r--r--private/ntos/nthals/halsnip/mips/jxsysint.c335
-rw-r--r--private/ntos/nthals/halsnip/mips/jxtime.c359
-rw-r--r--private/ntos/nthals/halsnip/mips/jxusage.c47
-rw-r--r--private/ntos/nthals/halsnip/mips/mpagent.c745
-rw-r--r--private/ntos/nthals/halsnip/mips/mpagent.h594
-rw-r--r--private/ntos/nthals/halsnip/mips/orcache.s561
-rw-r--r--private/ntos/nthals/halsnip/mips/r4intdsp.c1307
-rw-r--r--private/ntos/nthals/halsnip/mips/snidef.h225
-rw-r--r--private/ntos/nthals/halsnip/mips/snidisp.c1201
-rw-r--r--private/ntos/nthals/halsnip/mips/snihalp.h422
-rw-r--r--private/ntos/nthals/halsnip/mips/snipbus.c2051
-rw-r--r--private/ntos/nthals/halsnip/mips/snipbus.h104
-rw-r--r--private/ntos/nthals/halsnip/mips/snipci.h366
-rw-r--r--private/ntos/nthals/halsnip/mips/sniregs.h139
-rw-r--r--private/ntos/nthals/halsnip/mips/unicache.s1155
-rw-r--r--private/ntos/nthals/halsnip/mips/vgadata.h420
-rw-r--r--private/ntos/nthals/halsnip/mips/x4clock.s457
-rw-r--r--private/ntos/nthals/halsnip/mips/x4misc.s410
-rw-r--r--private/ntos/nthals/halsnip/mips/x4tb.s110
-rw-r--r--private/ntos/nthals/halsnip/mips/x86bios.c191
-rw-r--r--private/ntos/nthals/halsnip/mips/xxcache.c346
-rw-r--r--private/ntos/nthals/halsnip/mips/xxcache.h30
-rw-r--r--private/ntos/nthals/halsnip/mips/xxcalstl.c278
-rw-r--r--private/ntos/nthals/halsnip/mips/xxclock.c277
-rw-r--r--private/ntos/nthals/halsnip/mips/xxerror.c293
-rw-r--r--private/ntos/nthals/halsnip/mips/xxidle.s79
-rw-r--r--private/ntos/nthals/halsnip/mips/xxinithl.c695
-rw-r--r--private/ntos/nthals/halsnip/mips/xxinitnt.c345
-rw-r--r--private/ntos/nthals/halsnip/mips/xxipiint.s56
-rw-r--r--private/ntos/nthals/halsnip/mips/xxmemory.c246
45 files changed, 22761 insertions, 0 deletions
diff --git a/private/ntos/nthals/halsnip/mips/allstart.c b/private/ntos/nthals/halsnip/mips/allstart.c
new file mode 100644
index 000000000..07274b604
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/allstart.c
@@ -0,0 +1,65 @@
+/*++
+
+Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
+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.
+
+--*/
+
+#include "halp.h"
+#include "string.h"
+
+
+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.
+
+ Note: this HAL is for the Siemens Nixdorf Uni-/MultiProcessor Computers
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If platform specific operations are successful, then return TRUE.
+ Otherwise, return FALSE.
+
+--*/
+
+{
+
+
+ if (HalpIsTowerPci){
+
+ // on PCI tower, MAUI_INT is on processor number 1 if more than one processor
+
+ if ((PCR->Number == 1) || (HalpIsMulti == 0 )){
+
+ HalpCreateIntPciMAUIStructures(PCR->Number);
+ HalpInitMAUIMPAgent();
+
+ }
+ }
+
+ return TRUE;
+
+}
diff --git a/private/ntos/nthals/halsnip/mips/cacherr.s b/private/ntos/nthals/halsnip/mips/cacherr.s
new file mode 100644
index 000000000..c0ea29908
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/cacherr.s
@@ -0,0 +1,645 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/cacherr.s,v 1.2 1996/02/23 17:55:12 pierre Exp $")
+// TITLE("Cache Error Handling")
+//++
+//
+// Copyright (c) 1993 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.
+//
+// No correction is done. We only try to get the physical address
+// that causes this exception
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+ .globl HalpCacheErrFirst
+ .globl HalpErrCacheMsg // cache error
+ .globl HalpParityErrMsg // parity error
+ .globl HalpAddrErrMsg // no addr found
+ .globl HalpComputeNum // compute memory sip number
+ .globl HalpKeBugCheck0
+ .globl HalpKeBugCheck1
+ .globl HalpKeBugCheck2
+ .globl HalpKeBugCheck3
+ .globl HalpKeBugCheck4
+ .globl HalpBugCheckNumber
+
+#define CACHE_ERR_ER 0x80000000
+#define CACHE_ERR_EC 0x40000000
+#define CACHE_ERR_ED 0x20000000
+#define CACHE_ERR_ET 0x10000000
+#define CACHE_ERR_ES 0x08000000
+#define CACHE_ERR_EE 0x04000000
+#define CACHE_ERR_EB 0x02000000
+#define CACHE_ERR_EI 0x01000000
+#define CACHE_ERR_SIDX 0x003ffff8
+#define CACHE_ERR_PIDX 0x00000007
+#define PIDX_PD_MASK 0x00001000 // cache size 8k
+
+#define HALP_OPCODE_MASK 0xfc000000
+#define HALP_OPCODE_SHIFT 24 // because we test opcode number on 8 bits
+#define HALP_RT1_REG 0x001f0000
+#define HALP_RT1_SHIFT 16
+#define HALP_RT2_REG 0x03e00000
+#define HALP_RT2_SHIFT 21
+
+#define HALP_SWC1 0xe4 //
+#define HALP_SDC1 0xf4 //
+#define HALP_LWC1 0xc4 //
+#define HALP_LDC1 0xd4 //
+#define HALP_LB 0x80 //
+#define HALP_LH 0x82 //
+#define HALP_LW 0x8c //
+#define HALP_LD 0xdc //
+#define HALP_LBU 0x90 //
+#define HALP_LHU 0x94 //
+#define HALP_SB 0xa0 //
+#define HALP_SH 0xa4 //
+#define HALP_SW 0xac //
+#define HALP_SD 0xfc //
+#define HALP_LWL 0x88 //
+#define HALP_LWR 0x98 //
+#define HALP_LDL 0x68 //
+#define HALP_LDR 0x6c //
+#define HALP_LWU 0x9c //
+#define HALP_SDL 0xb0 //
+#define HALP_SDR 0xb4 //
+#define HALP_LL 0xc0 //
+#define HALP_LLD 0xd0 //
+#define HALP_SC 0xe0 //
+#define HALP_SCD 0xf0 //
+//
+// Define local save area for register state.
+//
+
+ .data
+SavedAt:.space 4 // saved registers
+SavedV0:.space 4 //
+SavedV1:.space 4 //
+SavedA0:.space 4 //
+SavedA1:.space 4 //
+SavedA2:.space 4 //
+SavedA3:.space 4 //
+SavedT0:.space 4 //
+SavedT1:.space 4 //
+SavedT2:.space 4 //
+SavedT3:.space 4 //
+SavedT4:.space 4 //
+SavedT5:.space 4 //
+SavedT6:.space 4 //
+SavedT7:.space 4 //
+SavedS0:.space 4 //
+SavedS1:.space 4 //
+SavedS2:.space 4 //
+SavedS3:.space 4 //
+SavedS4:.space 4 //
+SavedS5:.space 4 //
+SavedS6:.space 4 //
+SavedS7:.space 4 //
+SavedT8:.space 4 //
+SavedT9:.space 4 //
+SavedK0:.space 4 //
+SavedK1:.space 4 //
+SavedGP:.space 4 //
+SavedSP:.space 4 //
+SavedS8:.space 4 //
+SavedRA:.space 4 //
+SavedErrorEpc:.space 4 //
+SavedCacheError:.space 4 //
+
+//++
+//
+// VOID
+// HalpCacheErrorRoutine (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is entered from the cache error vector executing
+// in KSEG1 and with finished with a fatal system error :
+//
+// Msg Hal : CACHE ERROR - PARITY ERROR - ADDR IN ERROR NOT FOUND
+// KeBugCheckEx :
+// a0 = 0x80 Hardware malfunction
+// a1 = 18 (parity pb) or 19 (cache error)
+// a2 = physical address in error (or 0x00)
+// a3 = sim number
+// a4 = cacheerror register contents
+//
+//
+// N.B. No state has been saved when this routine is entered.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+ .struct 0
+
+ .struct 0
+CiArgs0:.space 4 // saved arguments
+CiArgs1:.space 4 // saved arguments
+CiArgs2:.space 4 // saved arguments
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpCacheErrorRoutine, CiFrameLength, zero)
+
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+//
+// Save volatile registers needed to fix cache error.
+//
+
+ .set noreorder
+
+//
+// Protection to avoid to execute twice in multipro
+// (modif of psr doesn't seem very effective)
+//
+
+ la k0,HalpCacheErrFirst
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k1,k0,k1 //
+ lw k0,0(k1)
+ nop
+ beq k0,zero,1f
+ nop
+
+// cache error during cache error routine
+ lw ra,CiRa(sp) // save return address
+ addu sp,sp,CiFrameLength // allocate stack frame
+ eret // hope we don't need k0 and k1...
+ nop
+
+1: add k0,k0,0x01
+ sw k0,0(k1)
+
+//
+// Save all the registers
+//
+
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ .set noat
+ sw AT,0(k0) // save registers AT - a3
+ .set at
+ sw v0,4(k0) //
+ sw v1,8(k0) //
+ sw a0,12(k0) //
+ sw a1,16(k0) //
+ sw a2,20(k0) //
+ sw a3,24(k0) //
+ sw t0,28(k0) //
+ sw t1,32(k0) //
+ sw t2,36(k0) //
+ sw t3,40(k0) //
+ sw t4,44(k0) //
+ sw t5,48(k0) //
+ sw t6,52(k0) //
+ sw t7,56(k0) //
+ sw s0,60(k0) //
+ sw s1,64(k0) //
+ sw s2,68(k0) //
+ sw s3,72(k0) //
+ sw s4,76(k0) //
+ sw s5,80(k0) //
+ sw s6,84(k0) //
+ sw s7,88(k0) //
+ sw t8,92(k0) //
+ sw t9,96(k0) //
+ sw s8,100(k0) //
+ sw k0,104(k0) //
+ sw k1,108(k0) //
+ sw gp,112(k0) //
+ sw sp,116(k0) //
+ sw s8,120(k0) //
+ sw ra,124(k0) //
+
+ mfc0 a1,cacheerr // get cache error state
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ mfc0 a0,errorepc // get error address
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ la k0,SavedErrorEpc // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ sw a0,0(k0) // save errorepc register
+ sw a1,4(k0) // save cache error register
+//
+// Disable ECC and parity detection (HalpCacheFirstErr will help...)
+//
+
+ mfc0 k0,psr // get current processor state
+ nop
+ nop
+ nop
+ nop
+ nop
+ or k0,k0,0x00010000 // disable ECC and Parity detection
+ and k0,k0,0xfffffffe // disable interrupt
+ mtc0 k0,psr
+ and k0,k0,0xffff00e0
+ mtc0 k0,psr
+
+
+// Analysis of cacheerror register
+
+ la k0,SavedCacheError // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ lw t0,0(k0) // restore cache error register in t0
+
+ and t1,t0,CACHE_ERR_EE // parity error
+ bne t1,zero,ParityError
+ nop
+
+//
+// Cache error message
+//
+
+ la a0,HalpErrCacheMsg
+ and a0,a0,0x1fffffff
+ or a0,a0,0xa0000000
+ la t0,HalDisplayString
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 //
+ nop
+
+ la k0,SavedCacheError // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ lw t0,0(k0) // restore cache error register in t0
+
+ and t1,t0,CACHE_ERR_SIDX // grab low bits of PAddr
+ lw t2,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ subu t2,t2,1
+ not t2
+ and t1,t2 // t1=PAddre(21..scache_block_size); SCache index
+// lw t2,KiPcr + PcSecondLevelDcacheSize(zero) // get 2nd size
+// subu t2,t2,1
+// and t1,t2 // t1=PAddre(21..scache_block_size); SCache index
+
+ and t5,t0,CACHE_ERR_PIDX
+ sll t5,t5,0xc // align PIDX (bits 15:13)
+ and t2,t1,~(PIDX_PD_MASK) // suppress PIDX bits for VAddr
+ or t2,t5 // t2=VAddr(15..scache_block_size);PCache base index
+
+ or t1,0x80000000 // SCache index with K0SEG address
+ or t2,0x80000000 // PCache base index with K0SEG address
+
+ and t5,t0,CACHE_ERR_EC // Cache level of the error (0=primary, 1=secondary)
+ bne zero,t5,3f // if EC=0, Primary Cache Parity Error
+ nop
+
+1: // primary cache
+
+ // int error
+ and t5,t0,CACHE_ERR_ER // data or instruction flag
+ bne zero,t5,2f // if ER=1 Data error
+ nop
+
+ move a2,t2
+ // primary cache - inst
+ cache INDEX_LOAD_TAG_I,0(t2)
+
+ nop
+ mfc0 a3,taglo
+ b 5f
+ nop
+
+2: // primary cache - data
+ move a2,t2
+ cache INDEX_LOAD_TAG_D,0(t2)
+
+ nop
+ mfc0 a3,taglo
+ b 5f
+ nop
+
+3: // secondary cache - inst/data
+ move a2,t1
+ cache INDEX_LOAD_TAG_SD,0(t1)
+
+ nop
+ mfc0 a3,taglo
+5:
+
+// maybe a3 will be the erroneous physical address...
+
+ li a0,0x80 // harware error
+ la k0,SavedErrorEpc // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ li a1,19 // restore error epc register
+ lw a2,4(k0) // restore cache error register
+ la t1,HalpKeBugCheck0
+ sw a0,0(t1)
+ la t1,HalpKeBugCheck1
+ sw a1,0(t1)
+ la t1,HalpKeBugCheck2
+ sw a2,0(t1)
+ la t1,HalpKeBugCheck3
+ sw a3,0(t1)
+ la t1,HalpKeBugCheck4
+ sw zero,0(t1)
+ la t1,HalpBugCheckNumber
+ sw a1,0(t1)
+ la t0,KeBugCheckEx
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 //
+ sw zero,0x10(sp)
+ lw ra,CiRa(sp) // save return address
+ addu sp,sp,CiFrameLength // allocate stack frame
+ eret
+ nop
+
+ParityError:
+
+//
+// cacheerr contents are not usable if parity error.
+// Then we must disassemble the errorepc code, get the used register
+// and get the contents of this register which must cause the error.
+//
+
+//
+// Parity Error Msg
+//
+
+ la a0,HalpParityErrMsg
+ and a0,a0,0x1fffffff
+ or a0,a0,0xa0000000
+ la t0,HalDisplayString
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 //
+ nop
+
+//
+// disasm
+//
+ la k0,SavedErrorEpc // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ lw a0,0(k0)
+ li a2,0x00 // init for one loop
+ move t0,a0
+
+10: lw a0,0(a0) // instruction
+ move a1,a0 // instruction saved in a1
+ li a3,HALP_OPCODE_MASK
+ and a0,a0,a3
+ srl a0,a0,HALP_OPCODE_SHIFT
+ li a2,0x00
+ beq a0,HALP_SWC1,8f
+ nop
+ beq a0,HALP_SDC1,8f
+ nop
+ beq a0,HALP_LWC1,8f
+ nop
+ beq a0,HALP_LDC1,8f
+ nop
+ beq a0,HALP_LB,8f
+ nop
+ beq a0,HALP_LH,8f
+ nop
+ beq a0,HALP_LW,8f
+ nop
+ beq a0,HALP_LD,8f
+ nop
+ beq a0,HALP_LBU,8f
+ nop
+ beq a0,HALP_LHU,8f
+ nop
+ beq a0,HALP_SB,8f
+ nop
+ beq a0,HALP_SH,8f
+ nop
+ beq a0,HALP_SW,8f
+ nop
+ beq a0,HALP_SD,8f
+ nop
+ beq a0,HALP_LWL,8f
+ nop
+ beq a0,HALP_LWR,8f
+ nop
+ beq a0,HALP_LDL,8f
+ nop
+ beq a0,HALP_LDR,8f
+ nop
+ beq a0,HALP_LWU,8f
+ nop
+ beq a0,HALP_SDL,8f
+ nop
+ beq a0,HALP_SDR,8f
+ nop
+ beq a0,HALP_LWU,8f
+ nop
+ beq a0,HALP_SDL,8f
+ nop
+ beq a0,HALP_SDR,8f
+ nop
+ beq a0,HALP_LL,8f
+ nop
+ beq a0,HALP_SC,8f
+ nop
+ beq a0,HALP_SCD,8f
+ nop
+ move a0,t0
+ addu a0,a0,4
+ beq a2,zero,10b // try the next instruction (case of branch...)
+ addu a2,a2,1
+
+ beq zero,zero,NotFoundAddr
+
+8: // a1 = inst en erreur
+
+ move a2,a1
+
+ li a3,HALP_RT2_REG
+ and a2,a2,a3
+ srl a3,a2,HALP_RT2_SHIFT
+
+ subu a3,1 // reg at has 1 as number
+ sll a3,a3,0x2 // *4
+
+ la k0,SavedAt // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ addu k0,k0,a3
+ lw a3,0(k0) // contents of the register
+//
+// Try To find the physical address
+// a3 = virtual address
+//
+
+ move a0,a3
+ srl a0,a0,30 // two upper bits
+ li a2,0x2 // binary 10
+ beq a0,a2,FoundAddr // KSEG0 or KSEG1 addr
+ nop
+// mapped address => try to find it in the TLB
+ move a0,a3
+ mfc0 t1,entryhi // get current PID and VPN2
+ srl t2,a0,ENTRYHI_VPN2 // isolate VPN2 of virtual address
+ sll t2,t2,ENTRYHI_VPN2 //
+ and t1,t1,PID_MASK << ENTRYHI_PID // isolate current PID
+ or t2,t2,t1 // merge PID with VPN2 of virtual address
+ mtc0 t2,entryhi // set VPN2 and PID for probe
+ nop // 3 cycle hazzard
+ nop //
+ nop //
+ tlbp // probe for entry in TB
+ nop // 2 cycle hazzard
+ nop //
+ mfc0 t3,index // read result of probe
+ nop
+ bltz t3,NotFoundAddr // if ltz, entry is not in TB
+ sll a0,a0,0x1f - (ENTRYHI_VPN2 - 1) // shift VPN<12> into sign
+ tlbr // read entry from TB
+ nop // 3 cycle hazzard
+ nop //
+ nop //
+ bltz a0,11f // if ltz, check second PTE
+ mfc0 t2,entrylo1 // get second PTE for probe
+ mfc0 t2,entrylo0 // get first PTE for probe
+11: mtc0 t1,entryhi // restore current PID
+ mtc0 zero,pagemask // restore page mask register
+// t2 = entrylo
+ srl t2,t2,ENTRYLO_PFN
+ sll t2,t2,PAGE_SHIFT
+ li a2,PAGE_SIZE
+ subu a2,a2,1
+ and a3,a3,a2
+ or a3,a3,t2
+
+FoundAddr:
+// a3 = Physical addr
+ li a2,0x1fffffff
+ and a3,a3,a2 // 3 upper bits deleted
+ la k0,SavedErrorEpc // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ lw a1,0(k0) // load error epc register
+ lw a2,4(k0) // load cache error register
+
+ // compute sip num
+ sw a3,CiArgs0(sp)
+ sw a1,CiArgs1(sp)
+ sw a2,CiArgs2(sp)
+ move a0,a3
+ la t0,HalpComputeNum
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 // compute sip num
+ nop
+ lw a3,CiArgs2(sp)
+ sw a3,0x10(sp)
+ li a1,18
+ lw a2,CiArgs0(sp)
+ShowMsg:
+ li a0,0x80
+
+ la t1,HalpKeBugCheck0
+ sw a0,0(t1)
+ la t1,HalpKeBugCheck1
+ sw a1,0(t1)
+ la t1,HalpKeBugCheck2
+ sw a2,0(t1)
+ la t1,HalpKeBugCheck3
+ sw v0,0(t1)
+ la t1,HalpKeBugCheck4
+ sw a3,0(t1)
+ la t1,HalpBugCheckNumber
+ sw a1,0(t1)
+ la t0,KeBugCheckEx
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 //
+ move a3,v0 // sip num
+
+ lw ra,CiRa(sp) // save return address
+ addu sp,sp,CiFrameLength // allocate stack frame
+ eret //
+
+NotFoundAddr:
+
+ la a0,HalpAddrErrMsg
+ and a0,a0,0x1fffffff
+ or a0,a0,0xa0000000
+ la t0,HalDisplayString
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 //
+ nop
+
+ move a3,a1
+ li a0,0x80
+ la k0,SavedErrorEpc // get address of register save area
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or k0,k0,k1 //
+ li a1,18
+ li a2,0x00
+ lw a3,4(k0)
+ sw a3,0x10(sp)
+ la t1,HalpKeBugCheck0
+ sw a0,0(t1)
+ la t1,HalpKeBugCheck1
+ sw a1,0(t1)
+ la t1,HalpKeBugCheck2
+ sw a2,0(t1)
+ la t1,HalpKeBugCheck3
+ sw v0,0(t1)
+ la t1,HalpKeBugCheck4
+ sw a3,0(t1)
+ la t1,HalpBugCheckNumber
+ sw a1,0(t1)
+ la t0,KeBugCheckEx
+ li k1,KSEG1_BASE // convert address of KSEG1 address
+ or t0,t0,k1 //
+ jal t0 //
+ li a3,0xff
+
+ lw ra,CiRa(sp) // save return address
+ addu sp,sp,CiFrameLength // allocate stack frame
+ eret //
+
+ .set reorder
+
+ .end HalpCacheErrorRoutine
diff --git a/private/ntos/nthals/halsnip/mips/duocache.s b/private/ntos/nthals/halsnip/mips/duocache.s
new file mode 100644
index 000000000..8d743a0b5
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/duocache.s
@@ -0,0 +1,780 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/duocache.s,v 1.4 1996/02/23 17:55:12 pierre Exp $")
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// duocache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// MIPS R4000 MultiProcerssor Machines. It is very special to SNI machines,
+// which use a special MP Agent Asic.
+//`
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+#include "SNIdef.h"
+
+// NON COHERENT algorithm : to use the replace facility of the MP_Agent
+
+#define CONFIG_NONCOH(reg) \
+ .set noreorder; \
+ .set noat; \
+ mfc0 reg,config; \
+ nop; \
+ nop; \
+ and AT,reg,~(7); \
+ or AT,AT,0x3; \
+ mtc0 AT,config; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ .set at; \
+ .set reorder
+
+// restauration of CONFIG register
+
+#define CONFIG_RESTORE(reg) \
+ .set noreorder; \
+ mtc0 reg,config; \
+ nop; \
+ nop; \
+ nop; \
+ nop; \
+ .set reorder
+
+// beql : if the cond branch is not taken, the inst in the delay-slot is nullified
+
+#define LOAD_RPL_ADDR(reg,reg1) \
+ lw reg,HalpMpaCacheReplace; \
+2:
+
+
+
+//
+// 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("Processor Identification")
+//++
+//
+// VOID
+// HalpProcIdentify()
+//
+// Routine Description:
+//
+// This function reads the implementation number in the prid register.
+//
+// Arguments:
+//
+// None
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpProcIdentify)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,prid
+ nop
+ srl v0,PRID_IMP
+ and v0,0xff
+ j ra
+ nop
+
+ .end HalpProcIdentify
+
+ SBTTL("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalpFlushDcachePageMulti (
+// 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(HalpFlushDcachePageMulti)
+
+#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
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// Flush the primary and secondary data caches.
+//
+
+//
+// HIT_WRITEBACK_INVALIDATE cache instruction does not update the SC
+// TagRam copy in the MP Agent. So we do cache replace.
+//
+
+ .set noreorder
+ .set noat
+40: and a0,a0,PAGE_SIZE -1 // PageOffset
+ sll t7,a1,PAGE_SHIFT // physical address
+ lw t4,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ or t0,t7,a0 // physical address + offset
+ 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,60f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ LOAD_RPL_ADDR(a3,a2) // get base flush address
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get cache size
+ add t0,t0,-1 // mask of the cache size
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+ .set noreorder
+ .set noat
+
+50: and t7,t8,t0 // offset
+ addu t7,t7,a3 // physical address + offset
+ lw zero,0(t7) // load Cache -> Write back old Data
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address (+Linesize)
+
+ CONFIG_RESTORE(t2)
+
+60: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpFlushDcachePageMulti
+
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalpPurgeIcachePageMulti (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of 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(HalpPurgeIcachePageMulti)
+
+#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 t4,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill 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,60f // if eq, no blocks to purge
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// Purge the primary and secondary instruction caches.
+//
+ .set noreorder
+ .set noat
+
+40: move t7,t8
+
+//
+// HIT_WRITEBACK_INVALIDATE cache instruction does not work. So we do cache replace.
+// We use a MP agent facility to do that : a 4Mb area is stolen to the upper EISA space
+// and this address is notified to the MP agent. When the cache replace is done, no
+// access to the memory is done : the MP agent returns zero as value for these addresses.
+// Be careful : to use this mechanism, CONFIG register must be programmed in NON COHERENT
+// mode, so we must be protected from interrupts.
+//
+
+ li t8,PAGE_SIZE
+ add t8,t8,-1 // page mask
+ and t8,t7,t8 // offset in the page
+ sll t7,a1,PAGE_SHIFT // physical address
+ or t8,t7,t8 // physical address + offset
+
+//
+// note: we have a Unified SLC, so SecondLevelIcacheSize is set to 0
+//
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get cache size
+
+ addu t9,t8,a2 // compute ending physical address
+ subu t9,t9,t4 // compute ending loop address
+
+ add t0,t0,-1 // mask of the cache size
+ and t8,t8,t0 // first cache line to invalidate
+ and t9,t9,t0 // last cache line to invalidate
+
+ LOAD_RPL_ADDR(a2,a3)
+
+ or t8,a2,t8 // starting address
+ or t9,a2,t9 // ending address
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+ .set noreorder
+ .set noat
+
+50: lw zero,0(t8) // invalidate sc
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+
+ CONFIG_RESTORE(t2)
+
+60: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalPurgeIcachePage
+
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalpSweepDcacheMulti (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheMulti)
+
+#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 at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t3) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// sweep secondary cache in the MP Agent
+//
+
+//
+// HIT_WRITEBACK_INVALIDATE cache instruction does not update the SC
+// TagRam copy in the MP Agent. So we do cache replace.
+//
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+
+ LOAD_RPL_ADDR(a0,t5) // starting address
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+
+ .set noreorder
+ .set noat
+
+25:
+ lw zero,0(a0)
+ bne a0,a1,25b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+ CONFIG_RESTORE(t2)
+
+ ENABLE_INTERRUPTS(t3) // enable interrupts
+
+ .set at
+ .set reorder
+
+ j ra // return
+
+
+ .end HalpSweepDcacheMulti
+
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalpSweepIcacheMulti (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheMulti)
+
+#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
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+
+ DISABLE_INTERRUPTS(t3) // disable interrupts
+ .set noreorder
+ .set noat
+
+//
+// sweep secondary cache
+// SNI machines have only an Unified SL cache
+// NOTE: PcSecondLevelIcacheSize and PcSecondLevelICacheFillSize is set to 0
+// on SNI machines
+//
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ LOAD_RPL_ADDR(a0,a3) // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+ .set noreorder
+ .set noat
+
+10: lw zero,0(a0)
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+ CONFIG_RESTORE(t2)
+ .set noreorder
+ .set noat
+
+
+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.
+//
+
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ ENABLE_INTERRUPTS(t3) // enable interrupts
+
+ .set at
+ .set reorder
+ j ra // return
+
+ .end HalSweepIcache
+
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalpZeroPageMulti (
+// 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(HalpZeroPageMulti, 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 a1,ZpA1(sp) // save old 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
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+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) //
+
+ .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 HalpZeroPageMulti
+
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalpMultiPciEccCorrector (
+// IN PVOID PhysicalAddr,
+// IN PVOID PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function corrects an ECC.
+//
+//
+// Arguments:
+//
+// a0 : virtual
+// a1 : pfn
+// a2 : length
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ LEAF_ENTRY(HalpMultiPciEccCorrector)
+
+//
+// to avoid Virtual Coherency Exception (unrecoverable with NT)
+// flush of the primary cache. So the physical address won't
+// be twice in the primary cache.
+//
+ DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+//
+// first, we make a virtual address to get the corrected address in the cache
+// secondly, we flush it by cache replace mechanism
+//
+
+ and a0,a0,COLOR_MASK // isolate color and offset bits
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ 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
+
+15: 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
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+//
+// load data and flush it to correct the ECC
+//
+
+ LOAD_RPL_ADDR(a3,a2) // get base flush address
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get cache size
+ add t0,t0,-1 // mask of the cache size
+ .set noreorder
+ .set noat
+
+50: lw t7,0(t8)
+ sw t7,0(t8)
+
+ and t7,t8,t0 // offset
+ addu t7,t7,a3 // physical address + offset
+ CONFIG_NONCOH(t2) // NON COHERENT algorithm
+ lw zero,0(t7) // load Cache -> Write back old Data
+ CONFIG_RESTORE(t2)
+
+ lw t7,0(t8) // t8 fffe0400 et entree tlb ->417 =>ok
+
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address (+Linesize)
+
+60:
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+
+ .end HalpMultiPciEccCorrector
diff --git a/private/ntos/nthals/halsnip/mips/halp.h b/private/ntos/nthals/halsnip/mips/halp.h
new file mode 100644
index 000000000..d6edc0499
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/halp.h
@@ -0,0 +1,280 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/halp.h,v 1.4 1996/02/23 17:55:12 pierre Exp $")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ halp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ interfaces.
+
+
+--*/
+
+#ifndef _HALP_
+#define _HALP_
+
+#if defined(NT_UP)
+
+#undef NT_UP
+
+#endif
+
+#include "nthal.h"
+#include "hal.h"
+#include "SNIhalp.h"
+#include "xm86.h"
+#include "x86new.h"
+
+
+extern ULONG HalpKeBugCheck0;
+extern ULONG HalpKeBugCheck1;
+extern ULONG HalpKeBugCheck2;
+extern ULONG HalpKeBugCheck3;
+extern ULONG HalpKeBugCheck4;
+
+#define HalpKeBugCheckEx(p0,p1,p2,p3,p4) \
+ {\
+ HalpKeBugCheck0 = p0;\
+ HalpKeBugCheck1 = p1;\
+ HalpKeBugCheck2 = p2;\
+ HalpKeBugCheck3 = p3;\
+ HalpKeBugCheck4 = p4;\
+ KeBugCheckEx(p0,p1,p2,p3,p4); \
+ }\
+
+
+typedef struct _HALP_BUGCHECK_BUFFER {
+ ULONG Par0;
+ ULONG Par1;
+ ULONG Par2;
+ ULONG Par3;
+ ULONG Par4;
+ ULONG MainBoard;
+ UCHAR TEXT[50];
+} HALP_BUGCHECK_BUFFER, *PHALP_BUGCHECK_BUFFER;
+
+//
+// Define function prototypes.
+//
+
+ULONG
+HalpAllocateTbEntry (
+ VOID
+ );
+
+VOID
+HalpFreeTbEntry (
+ VOID
+ );
+
+VOID
+HalpCacheErrorRoutine (
+ VOID
+ );
+
+BOOLEAN
+HalpCalibrateStall (
+ VOID
+ );
+
+VOID
+HalpClockInterrupt(
+ VOID
+ );
+
+
+VOID
+HalpClockInterruptPciTower(
+ VOID
+ );
+
+VOID
+HalpClockInterrupt1(
+ VOID
+ );
+
+BOOLEAN
+HalpInitializeDisplay0(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeDisplay1(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ );
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ );
+
+VOID
+HalpProfileInterrupt (
+ VOID
+ );
+
+ULONG
+HalpReadCountRegister (
+ VOID
+ );
+
+ULONG
+HalpWriteCompareRegisterAndClear (
+ IN ULONG Value
+ );
+
+
+VOID
+HalpStallInterrupt (
+ VOID
+ );
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ );
+
+VOID
+HalpSendIpi(
+ IN ULONG pcpumask,
+ IN ULONG msg_data
+ );
+
+VOID
+HalpRequestIpi(
+ IN ULONG pcpumask,
+ IN ULONG msg_data
+ );
+
+VOID
+HalpProcessIpi (
+ IN struct _KTRAP_FRAME *TrapFrame
+ );
+
+VOID
+HalpInitMPAgent (
+ IN ULONG Number
+ );
+
+ULONG
+HalpGetMyAgent(
+ VOID
+ );
+
+BOOLEAN
+HalpCheckSpuriousInt(
+ ULONG mask
+ );
+
+VOID
+HalpBootCpuRestart(
+ VOID
+ );
+
+ULONG
+HalpGetPCIData (
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+ULONG
+HalpSetPCIData (
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ ) ;
+
+
+NTSTATUS
+HalpAssignPCISlotResources (
+ IN ULONG BusNumber,
+ 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
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN ULONG BusNumber,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+VOID
+HalpInit2MPAgent(
+ VOID
+ );
+
+VOID
+HalpInitMAUIMPAgent(
+ VOID
+ );
+
+BOOLEAN
+HalpCreateIntPciMAUIStructures(
+ CCHAR Number
+ );
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+ULONG
+HalpFindEccAddr(
+ ULONG Addr, // from ECC Error Asic Register
+ PVOID ErrStatusRegister, // register which indicates parity and Ecc error
+ PVOID ErrStatusBits // bits which indicates errors in the previous register
+ );
+
+USHORT
+HalpComputeNum(
+ UCHAR *PhysAddr
+ );
+
+//
+// Define external references.
+//
+
+extern HALP_BUGCHECK_BUFFER HalpBugCheckBuffer;
+
+extern KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord;
+
+extern UCHAR HalpComponentId[];
+
+extern ULONG HalpBugCheckNumber;
+
+extern PUCHAR HalpBugCheckMessage[];
+extern ULONG HalpColumn;
+extern ULONG HalpRow;
+extern KINTERRUPT HalpInt3Interrupt; // Interrupt Object for IT3 tower multipro
+extern ULONG HalpCurrentTimeIncrement;
+extern ULONG HalpNextTimeIncrement;
+extern ULONG HalpNewTimeIncrement;
+extern KSPIN_LOCK HalpBeepLock;
+extern KSPIN_LOCK HalpDisplayAdapterLock;
+extern KSPIN_LOCK HalpSystemInterruptLock;
+extern KSPIN_LOCK HalpInterruptLock;
+extern KSPIN_LOCK HalpMemoryBufferLock;
+extern ULONG HalpProfileCountRate;
+extern ULONG HalpStallScaleFactor;
+extern PULONG HalpPciConfigAddr;
+extern PULONG HalpPciConfigData;
+extern UCHAR HalpIntAMax;
+extern UCHAR HalpIntBMax;
+extern UCHAR HalpIntCMax;
+extern UCHAR HalpIntDMax;
+#endif // _HALP_
diff --git a/private/ntos/nthals/halsnip/mips/i82c54.h b/private/ntos/nthals/halsnip/mips/i82c54.h
new file mode 100644
index 000000000..3eb213052
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/i82c54.h
@@ -0,0 +1,34 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/i82c54.h,v 1.1 1995/07/20 15:55:16 flo Exp $")
+/*++
+
+Copyright (c) 1993-1994 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ i82C54.h
+
+Abstract:
+
+ This header file defines the private Address structure for
+ the Intel 82C54 Timer chip found on the SNI Minitower and RM400-10.
+
+
+--*/
+
+#ifndef _I82C54_
+#define _I82C54_
+//
+// the SNI Clock (i82C54) Structure
+//
+
+typedef struct _LOCAL_8254 {
+ UCHAR counter0; /* counter 0 port */
+ char fill_1[3];
+ UCHAR counter1; /* counter 1 port */
+ char fill_2[3];
+ UCHAR counter2; /* counter 2 port */
+ char fill_3[3];
+ UCHAR control; /* control word */
+} LOCAL_8254, *PLOCAL_8254;
+
+#endif
diff --git a/private/ntos/nthals/halsnip/mips/j4flshbf.s b/private/ntos/nthals/halsnip/mips/j4flshbf.s
new file mode 100644
index 000000000..a4ce6e784
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/j4flshbf.s
@@ -0,0 +1,53 @@
+#if defined(R4000)
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/j4flshbf.s,v 1.1 1995/07/20 15:56:14 flo Exp $")
+
+// TITLE("Miscellaneous Kernel Functions")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// j4flshbf.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.
+//
+//--
+
+#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/halsnip/mips/j4flshio.c b/private/ntos/nthals/halsnip/mips/j4flshio.c
new file mode 100644
index 000000000..7a785169a
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/j4flshio.c
@@ -0,0 +1,199 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/j4flshio.c,v 1.3 1996/03/04 13:14:32 pierre Exp $")
+
+
+/*++
+
+Copyright (c) 1991-1993 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 SNI MIPS R4x00 machine.
+
+
+--*/
+
+#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;
+ PULONG PageFrame;
+ ULONG Source;
+
+ //
+ // The SNI MIPS R4x00 machines use 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
+ // 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 read or a page read
+ // operation, then flush the data cache.
+ //
+ if (DmaOperation != FALSE) {
+ HalFlushDcachePage((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/halsnip/mips/j4prof.c b/private/ntos/nthals/halsnip/mips/j4prof.c
new file mode 100644
index 000000000..7b360f1cc
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/j4prof.c
@@ -0,0 +1,316 @@
+/*++
+
+Copyright (c) 1991 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.
+
+Author:
+
+ David N. Cutler (davec) 21-Feb-1991
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+// #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];
+ULONG HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+
+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.
+ //
+
+ KeRaiseIrql(PROFILE_LEVEL, &OldIrql);
+ 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->QuadPart = HalpProfileCountRate;
+ }
+
+ //
+ // Return the value of the performance counter.
+ //
+
+ PerformanceCounter.QuadPart += CurrentCount;
+ return PerformanceCounter;
+}
+
+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.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ PKPRCB Prcb;
+
+ //
+ // Raise IRQL to HIGH_LEVEL, decrement the number of processors, and
+ // wait until the number is zero.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ if (InterlockedDecrement(Number) != 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_PROFILE_COUNT);
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].QuadPart = 0;
+
+ //
+ // 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.
+ //
+
+ if (Interval < MINIMUM_PROFILE_INTERVAL) {
+ Interval = MINIMUM_PROFILE_INTERVAL;
+
+ } else if (Interval > MAXIMUM_PROFILE_INTERVAL) {
+ Interval = MAXIMUM_PROFILE_INTERVAL;
+ }
+
+ //
+ // First compute the profile count value and then back calculate the
+ // actual profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate, Interval);
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+ TempValue.QuadPart = Int32x32To64(TempValue.LowPart, ONE_SECOND);
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, HalpProfileCountRate, NULL);
+ HalpProfileInterval = TempValue.LowPart;
+ return HalpProfileInterval;
+}
+
+VOID
+HalStartProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+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:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+ LARGE_INTEGER TempValue;
+
+ //
+ // Compute the profile count from the current profile interval.
+ //
+
+ TempValue.QuadPart = Int32x32To64(HalpProfileCountRate,
+ HalpProfileInterval);
+
+ TempValue.QuadPart += ROUND_VALUE;
+ TempValue = RtlExtendedLargeIntegerDivide(TempValue, ONE_SECOND, NULL);
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(TempValue.LowPart);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].QuadPart += PreviousCount;
+ return;
+}
+
+VOID
+HalStopProfileInterrupt (
+ KPROFILE_SOURCE Source
+ )
+
+/*++
+
+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:
+
+ Source - Supplies the profile source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PKPRCB Prcb;
+ ULONG PreviousCount;
+
+ //
+ // Write the compare register and clear the count register.
+ //
+
+ PreviousCount = HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+
+ //
+ // Update the performance counter by adding in the previous count value.
+ //
+
+ Prcb = KeGetCurrentPrcb();
+ HalpPerformanceCounter[Prcb->Number].QuadPart += PreviousCount;
+ return;
+}
diff --git a/private/ntos/nthals/halsnip/mips/jxbeep.c b/private/ntos/nthals/halsnip/mips/jxbeep.c
new file mode 100644
index 000000000..a2a99459b
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxbeep.c
@@ -0,0 +1,132 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxbeep.c,v 1.1 1995/07/20 15:56:54 flo Exp $")
+
+/*++
+
+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 = HalpOnboardControlBase;
+ 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/halsnip/mips/jxebsup.c b/private/ntos/nthals/halsnip/mips/jxebsup.c
new file mode 100644
index 000000000..acae485bc
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxebsup.c
@@ -0,0 +1,2760 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxebsup.c,v 1.6 1996/03/04 13:15:15 pierre Exp $")
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ jxebsup.c
+
+Abstract:
+
+ The module provides the ISA/EISA bus support for SNI systems.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+//
+// Declare the interrupt structure and spinlock for the intermediate EISA
+// interrupt dispachter.
+//
+
+KINTERRUPT HalpEisaInterrupt;
+KINTERRUPT HalpOnboardInterrupt;
+
+//
+// Define save area for EISA adapter objects.
+//
+
+PADAPTER_OBJECT HalpEisaAdapter[8];
+PADAPTER_OBJECT HalpOnboardAdapter[8];
+PADAPTER_OBJECT HalpInternalAdapters[2];
+
+//
+// Define save area for EISA interrupt mask registers and level\edge control
+// registers.
+//
+
+UCHAR HalpEisaInterrupt1Mask;
+UCHAR HalpEisaInterrupt2Mask;
+UCHAR HalpEisaInterrupt1Level;
+UCHAR HalpEisaInterrupt2Level;
+
+UCHAR HalpOnboardInterrupt1Mask;
+UCHAR HalpOnboardInterrupt2Mask;
+UCHAR HalpOnboardInterrupt1Level;
+UCHAR HalpOnboardInterrupt2Level;
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ );
+
+
+NTSTATUS
+HalAllocateAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PWAIT_CONTEXT_BLOCK Wcb,
+ IN ULONG NumberOfMapRegisters,
+ IN PDRIVER_CONTROL ExecutionRoutine
+ )
+/*++
+
+Routine Description:
+
+ This routine allocates the adapter channel specified by the adapter object.
+ This is accomplished by placing the device object of the driver that wants
+ to allocate the adapter on the adapter's queue. If the queue is already
+ "busy", then the adapter has already been allocated, so the device object
+ is simply placed onto the queue and waits until the adapter becomes free.
+
+ Once the adapter becomes free (or if it already is), then the driver's
+ execution routine is invoked.
+
+ Also, a number of map registers may be allocated to the driver by specifying
+ a non-zero value for NumberOfMapRegisters. Then the map register must be
+ allocated from the master adapter. Once there are a sufficient number of
+ map registers available, then the execution routine is called and the
+ base address of the allocated map registers in the adapter is also passed
+ to the driver's execution routine.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+
+ Wcb - Supplies a wait context block for saving the allocation parameters.
+ The DeviceObject, CurrentIrp and DeviceContext should be initalized.
+
+ NumberOfMapRegisters - The number of map registers that are to be allocated
+ from the channel, if any.
+
+ ExecutionRoutine - The address of the driver's execution routine that is
+ invoked once the adapter channel (and possibly map registers) have been
+ allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS unless too many map registers are requested.
+
+Notes:
+
+ Note that this routine MUST be invoked at DISPATCH_LEVEL or above.
+
+--*/
+{
+
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Initialize the device object's wait context block in case this device
+ // must wait before being able to allocate the adapter.
+ //
+
+ Wcb->DeviceRoutine = ExecutionRoutine;
+ Wcb->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ //
+ // Allocate the adapter object for this particular device. If the
+ // adapter cannot be allocated because it has already been allocated
+ // to another device, then return to the caller now; otherwise,
+ // continue.
+ //
+
+ if (!KeInsertDeviceQueue( &AdapterObject->ChannelWaitQueue,
+ &Wcb->WaitQueueEntry )) {
+
+ //
+ // Save the parameters in case there are not enough map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = Wcb;
+
+ //
+ // The adapter was not busy so it has been allocated. Now check
+ // to see whether this driver wishes to allocate any map registers.
+ // Ensure that this adapter has enough total map registers
+ // to satisfy the request.
+ //
+
+ //
+ // For PCI devices we don't have to deal with
+ // map registers
+ //
+
+ if (NumberOfMapRegisters != 0 && AdapterObject->NeedsMapRegisters && AdapterObject->InterfaceType != PCIBus) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ }
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+
+ AdapterObject->CurrentWcb = Wcb;
+ Action = ExecutionRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then release the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ IoFreeAdapterChannel( AdapterObject );
+
+ } else if (Action == DeallocateObjectKeepRegisters) {
+
+ //
+ // Set the NumberOfMapRegisters = 0 in the adapter object.
+ // This will keep IoFreeAdapterChannel from freeing the
+ // registers. After this it is the driver's responsiblity to
+ // keep track of the number of map registers.
+ //
+
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+
+ }
+ }
+ }
+
+
+ return(STATUS_SUCCESS);
+
+}
+
+PADAPTER_OBJECT
+HalGetAdapter(
+ IN PDEVICE_DESCRIPTION DeviceDescriptor,
+ OUT PULONG NumberOfMapRegisters
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns the appropriate adapter object for the device defined
+ in the device description structure. This code works for Isa and Eisa
+ systems.
+
+Arguments:
+
+ DeviceDescriptor - Supplies a description of the device.
+
+ 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, tmpAdapterObject;
+ PVOID adapterBaseVa;
+ ULONG channelNumber;
+ ULONG controllerNumber;
+ DMA_EXTENDED_MODE extendedMode;
+ UCHAR adapterMode;
+ ULONG numberOfMapRegisters;
+ BOOLEAN useChannel;
+ ULONG maximumLength;
+ UCHAR DataByte;
+ PEISA_CONTROL controlBase;
+
+ if (MasterAdapterObject == NULL)
+ MasterAdapterObject = HalpAllocateAdapter(
+ 10,
+ (PVOID) -1,
+ NULL
+ );
+
+ if ((DeviceDescriptor->InterfaceType == Internal) || (DeviceDescriptor->InterfaceType == PCIBus)) {
+
+ if (DeviceDescriptor->Master) {
+
+ // The SNI machines support only Master Devices on the
+ // internal Bus; most of this stuff is the same as for EISA
+
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if ((DeviceDescriptor->ScatterGather) || (DeviceDescriptor->InterfaceType == PCIBus)) {
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ }
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ NULL,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+ return(NULL);
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The specified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 5;
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters ) {
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ // calculated Count for allocation was 0 ...
+ // ScatterGather Device on internal Bus
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+ }
+
+ adapterObject->InterfaceType = DeviceDescriptor->InterfaceType;
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+ adapterObject->MasterDevice = TRUE;
+ return (adapterObject);
+
+ } // end of Master Device
+
+ } // end of Internal Interface
+
+//+++++++++++++++EISA/ISA/MCA etc ...++++++++++++++++++++++++++++++++++++
+
+ //
+ // Determine if the the channel number is important. Master cards on
+ // Eisa and Mca do not use a channel number.
+ //
+
+ if (DeviceDescriptor->InterfaceType != Isa &&
+ DeviceDescriptor->Master) {
+
+ useChannel = FALSE;
+ } else {
+
+ useChannel = TRUE;
+ }
+
+ //
+ // determine the controlBase, depending on Interface Type
+ //
+
+ //
+ // Isa and Eisa Requests have to go to the Eisa Controller on the
+ // Eisa Extension, onboard components (Floppy) have to have the InterfaceType
+ // Internal in the Device Description !!!
+ //
+ if(DeviceDescriptor->InterfaceType == PCIBus) {
+ DbgBreakPoint();
+ }
+
+ //
+ // we direct all to the
+ // PC core (also if UseChannel = TRUE and InterfaceType == Internal )
+ //
+
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+ //
+ // Support for ISA local bus machines:
+ // If the driver is a Master but really does not want a channel since it
+ // is using the local bus DMA, just don't use an ISA channel.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Isa &&
+ DeviceDescriptor->DmaChannel > 7) {
+
+ useChannel = FALSE;
+ }
+
+ //
+ // Determine if Eisa DMA is supported.
+ //
+
+ if (DeviceDescriptor->InterfaceType == Eisa) {
+
+ WRITE_REGISTER_UCHAR(&(controlBase)->DmaPageHighPort.Channel2, 0x55);
+ DataByte = READ_REGISTER_UCHAR(&(controlBase)->DmaPageHighPort.Channel2);
+
+ if (DataByte == 0x55) {
+ HalpEisaDma = TRUE;
+ }
+
+ }
+
+ //
+ // Limit the maximum length to 2 GB this is done so that the BYTES_TO_PAGES
+ // macro works correctly.
+ //
+
+ maximumLength = DeviceDescriptor->MaximumLength & 0x7fffffff;
+
+ //
+ // Channel 4 cannot be used since it is used for chaining. Return null if
+ // it is requested.
+ //
+
+ if (DeviceDescriptor->DmaChannel == 4 && useChannel) {
+ return(NULL);
+ }
+
+ //
+ // Determine the number of map registers for this device.
+ //
+
+ if (DeviceDescriptor->ScatterGather && (LessThan16Mb ||
+ DeviceDescriptor->InterfaceType == Eisa)) {
+
+ //
+ // Since the device support scatter/Gather then map registers are not
+ // required.
+ //
+
+ numberOfMapRegisters = 0;
+
+ } else {
+
+ //
+ // Determine the number of map registers required based on the maximum
+ // transfer length, up to a maximum number.
+ //
+
+ numberOfMapRegisters = BYTES_TO_PAGES(maximumLength)
+ + 1;
+ numberOfMapRegisters = numberOfMapRegisters > MAXIMUM_ISA_MAP_REGISTER ?
+ MAXIMUM_ISA_MAP_REGISTER : numberOfMapRegisters;
+
+ //
+ // Make sure there where enough registers allocated initalize to support
+ // this size relaibly. This implies there must be to chunks equal to
+ // the allocatd size. This is only a problem on Isa systems where the
+ // map buffers cannot cross 64KB boundtires.
+ //
+
+ if (!HalpEisaDma &&
+ numberOfMapRegisters > HalpMapBufferSize / (PAGE_SIZE * 2)) {
+
+ numberOfMapRegisters = (HalpMapBufferSize / (PAGE_SIZE * 2));
+ }
+ //
+ // If the device is not a master and does scatter/Gather,
+ // then it only needs one map register
+ //
+
+ if (DeviceDescriptor->ScatterGather && !DeviceDescriptor->Master) {
+
+ numberOfMapRegisters = 1;
+ }
+ }
+
+ //
+ // Set the channel number number.
+ //
+
+ channelNumber = DeviceDescriptor->DmaChannel & 0x03;
+
+ //
+ // Set the adapter base address to the Base address register and controller
+ // number.
+ //
+
+ if (!(DeviceDescriptor->DmaChannel & 0x04)) {
+
+ controllerNumber = 1;
+ adapterBaseVa = (PVOID) &(controlBase)->Dma1BasePort;
+
+ } else {
+
+ controllerNumber = 2;
+ adapterBaseVa = &(controlBase)->Dma2BasePort;
+
+ }
+
+ //
+ // Determine if a new adapter object is necessary. If so then allocate it.
+ //
+
+ tmpAdapterObject = HalpOnboardAdapter[DeviceDescriptor->DmaChannel];
+
+
+ if (useChannel && tmpAdapterObject != NULL) {
+
+ adapterObject = tmpAdapterObject;
+
+ if (adapterObject->NeedsMapRegisters) {
+
+ if (numberOfMapRegisters > adapterObject->MapRegistersPerChannel) {
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+ }
+ }
+ } else {
+
+ //
+ // Allocate an adapter object.
+ //
+
+ adapterObject = (PADAPTER_OBJECT) HalpAllocateAdapter(
+ numberOfMapRegisters,
+ adapterBaseVa,
+ NULL
+ );
+
+ if (adapterObject == NULL) {
+
+ return(NULL);
+
+ }
+
+ if (useChannel) {
+
+ HalpOnboardAdapter[DeviceDescriptor->DmaChannel] = adapterObject;
+
+ }
+
+ //
+ // Set the maximum number of map registers for this channel bus on
+ // the number requested and the type of device.
+ //
+
+ if (numberOfMapRegisters) {
+
+ //
+ // The specified number of registers are actually allowed to be
+ // allocated.
+ //
+
+ adapterObject->MapRegistersPerChannel = numberOfMapRegisters;
+
+ //
+ // Increase the commitment for the map registers.
+ //
+
+ if (DeviceDescriptor->Master) {
+
+ //
+ // Master I/O devices use several sets of map registers double
+ // their commitment.
+ //
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters * 5;
+
+ } else {
+
+ MasterAdapterObject->CommittedMapRegisters +=
+ numberOfMapRegisters;
+
+ }
+
+ //
+ // If the committed map registers is signicantly greater than the
+ // number allocated then grow the map buffer.
+ //
+
+ if (MasterAdapterObject->CommittedMapRegisters >
+ MasterAdapterObject->NumberOfMapRegisters) {
+
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ }
+
+ adapterObject->NeedsMapRegisters = TRUE;
+
+ } else {
+
+ //
+ // No real map registers were allocated. If this is a master
+ // device, then the device can have as may registers as it wants.
+ //
+
+ adapterObject->NeedsMapRegisters = FALSE;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(
+ maximumLength
+ )
+ + 1;
+
+ } else {
+
+ //
+ // The device only gets one register. It must call
+ // IoMapTransfer repeatedly to do a large transfer.
+ //
+
+ adapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+ }
+
+ adapterObject->InterfaceType = DeviceDescriptor->InterfaceType;
+ adapterObject->ScatterGather = DeviceDescriptor->ScatterGather;
+ *NumberOfMapRegisters = adapterObject->MapRegistersPerChannel;
+
+ if (DeviceDescriptor->Master) {
+
+ adapterObject->MasterDevice = TRUE;
+
+ } else {
+
+ adapterObject->MasterDevice = FALSE;
+
+ }
+
+ //
+ // If the channel number is not used then we are finished. The rest of
+ // the work deals with channels.
+ //
+
+ if (!useChannel) {
+ return(adapterObject);
+ }
+
+ //
+ // Setup the pointers to all the random registers.
+ //
+
+ adapterObject->ChannelNumber = (UCHAR) channelNumber;
+
+ if (controllerNumber == 1) {
+
+ switch ((UCHAR)channelNumber) {
+
+ case 0:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel0;
+ break;
+
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel1;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel2;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel3;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 1;
+
+ //
+ // Save the extended mode register address.
+ //
+
+ adapterBaseVa =
+ &(controlBase)->Dma1ExtendedModePort;
+
+ } else {
+
+ switch (channelNumber) {
+ case 1:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel5;
+ break;
+
+ case 2:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel6;
+ break;
+
+ case 3:
+ adapterObject->PagePort = (PUCHAR) &((PDMA_PAGE) 0)->Channel7;
+ break;
+ }
+
+ //
+ // Set the adapter number.
+ //
+
+ adapterObject->AdapterNumber = 2;
+
+ //
+ // Save the extended mode register address.
+ //
+ adapterBaseVa =
+ &(controlBase)->Dma2ExtendedModePort;
+
+ }
+
+
+ adapterObject->Width16Bits = FALSE;
+
+ if (HalpEisaDma) {
+
+ //
+ // Initialzie the extended mode port.
+ //
+
+ *((PUCHAR) &extendedMode) = 0;
+ extendedMode.ChannelNumber = (UCHAR)channelNumber;
+
+ switch (DeviceDescriptor->DmaSpeed) {
+ case Compatible:
+ extendedMode.TimingMode = COMPATIBLITY_TIMING;
+ break;
+
+ case TypeA:
+ extendedMode.TimingMode = TYPE_A_TIMING;
+ break;
+
+ case TypeB:
+ extendedMode.TimingMode = TYPE_B_TIMING;
+ break;
+
+ case TypeC:
+ extendedMode.TimingMode = BURST_TIMING;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+ extendedMode.TransferSize = BY_BYTE_8_BITS;
+ break;
+
+ case Width16Bits:
+ extendedMode.TransferSize = BY_BYTE_16_BITS;
+
+ //
+ // Note Width16bits should not be set here because there is no need
+ // to shift the address and the transfer count.
+ //
+
+ break;
+
+ case Width32Bits:
+ extendedMode.TransferSize = BY_BYTE_32_BITS;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+
+ WRITE_REGISTER_UCHAR( adapterBaseVa, *((PUCHAR) &extendedMode));
+
+ } else if (!DeviceDescriptor->Master) {
+
+ switch (DeviceDescriptor->DmaWidth) {
+ case Width8Bits:
+
+ //
+ // The channel must use controller 1.
+ //
+
+ if (controllerNumber != 1) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ break;
+
+ case Width16Bits:
+
+ //
+ // The channel must use controller 2.
+ //
+
+ if (controllerNumber != 2) {
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+ }
+
+ adapterObject->Width16Bits = TRUE;
+ break;
+
+ default:
+ ObDereferenceObject( adapterObject );
+ return(NULL);
+
+ }
+ }
+
+ //
+ // 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);
+}
+
+PHYSICAL_ADDRESS
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to set up the map registers in the DMA controller
+ to allow a transfer to or from a device.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel that has been allocated.
+
+ Mdl - Pointer to the MDL that describes the pages of memory that are
+ being read or written.
+
+ MapRegisterBase - The address of the base map register that has been
+ allocated to the device driver for use in mapping the transfer.
+
+ CurrentVa - Current virtual address in the buffer described by the MDL
+ that the transfer is being done to or from.
+
+ Length - Supplies the length of the transfer. This determines the
+ number of map registers that need to be written to map the transfer.
+ Returns the length of the transfer which was actually mapped.
+
+ WriteToDevice - Boolean value that indicates whether this is a write
+ to the device from memory (TRUE), or vice versa.
+
+Return Value:
+
+ Returns the logical address that should be used bus master controllers.
+
+--*/
+
+{
+ BOOLEAN useBuffer;
+ ULONG transferLength;
+ ULONG logicalAddress;
+ PHYSICAL_ADDRESS returnAddress;
+ ULONG index;
+ PULONG pageFrame;
+ PUCHAR bytePointer;
+ UCHAR adapterMode;
+ UCHAR dataByte;
+ PTRANSLATION_ENTRY translationEntry;
+ ULONG pageOffset;
+ KIRQL Irql;
+ ULONG partialLength;
+ ULONG temp;
+ PEISA_CONTROL controlBase;
+
+ // for minitower or Eisa Interface Type (default case)
+
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+ pageOffset = BYTE_OFFSET(CurrentVa);
+
+ //
+ // Calculate how much of the transfer is contiguous.
+ //
+
+ transferLength = PAGE_SIZE - pageOffset;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+ logicalAddress = (*pageFrame << PAGE_SHIFT) + pageOffset;
+
+ //
+ // If the buffer is contigous and does not cross a 64 K bountry then
+ // just extend the buffer. The 64 K bountry restriction does not apply
+ // to Eisa systems.
+ //
+
+ while( transferLength < *Length ){
+
+ if (*pageFrame + 1 != *(pageFrame + 1)) {
+ break;
+ }
+
+ transferLength += PAGE_SIZE;
+ pageFrame++;
+
+ }
+
+ //
+ // Limit the transferLength to the requested Length.
+ //
+
+ transferLength = transferLength > *Length ? *Length : transferLength;
+
+ //
+ // Determine if the data transfer needs to use the map buffer.
+ //
+
+ if (MapRegisterBase != NULL) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER
+ && transferLength < *Length) {
+
+ logicalAddress = translationEntry->PhysicalAddress + pageOffset;
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+ transferLength = *Length;
+ useBuffer = TRUE;
+
+ } else {
+
+ //
+ // If there are map registers, then update the index to indicate
+ // how many have been used.
+ //
+
+ useBuffer = FALSE;
+ index = translationEntry->Index;
+ translationEntry->Index += ADDRESS_AND_SIZE_TO_SPAN_PAGES(
+ CurrentVa,
+ transferLength
+ );
+ }
+
+ //
+ // It must require memory to be at less than 16 MB. If the
+ // logical address is greater than 16MB then map registers must be used
+ //
+
+ if (logicalAddress+transferLength >= MAXIMUM_PHYSICAL_ADDRESS) {
+
+ logicalAddress = (translationEntry + index)->PhysicalAddress +
+ pageOffset;
+ useBuffer = TRUE;
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ translationEntry->Index = COPY_BUFFER;
+ index = 0;
+
+ }
+
+ }
+
+ //
+ // Copy the data if necessary.
+ //
+
+ if (useBuffer && WriteToDevice) {
+
+ temp = transferLength;
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= *Length ) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = *Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry + index,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ transferLength = temp;
+
+ }
+ }
+
+ //
+ // Return the length.
+ //
+
+ *Length = transferLength;
+
+ //
+ // We only support 32 bits, but the return is 64. Just
+ // zero extend
+ //
+
+ returnAddress.LowPart = logicalAddress;
+ returnAddress.HighPart = 0;
+
+ //
+ // If no adapter was specificed then there is no more work to do so
+ // return.
+ //
+
+ if (AdapterObject == NULL || AdapterObject->MasterDevice) {
+
+ return(returnAddress);
+ }
+
+ //
+ // Determine the mode based on the transfer direction.
+ //
+
+ adapterMode = AdapterObject->AdapterMode;
+ ((PDMA_EISA_MODE) &adapterMode)->TransferType = (UCHAR) (WriteToDevice ?
+ WRITE_TRANSFER : READ_TRANSFER);
+
+ bytePointer = (PUCHAR) &logicalAddress;
+
+ if (AdapterObject->Width16Bits) {
+
+ //
+ // If this is a 16 bit transfer then adjust the length and the address
+ // for the 16 bit DMA mode.
+ //
+
+ transferLength >>= 1;
+
+ //
+ // In 16 bit DMA mode the low 16 bits are shifted right one and the
+ // page register value is unchanged. So save the page register value
+ // and shift the logical address then restore the page value.
+ //
+
+ dataByte = bytePointer[2];
+ logicalAddress >>= 1;
+ bytePointer[2] = dataByte;
+
+ }
+
+
+ //
+ // grab the spinlock for the system DMA controller
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &(controlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[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) &(controlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ WRITE_REGISTER_UCHAR( &dmaControl->Mode, adapterMode );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[0]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseAddress,
+ bytePointer[1]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ ((PUCHAR) &(controlBase)->DmaPageLowPort) +
+ (ULONG)AdapterObject->PagePort,
+ bytePointer[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) &(controlBase)->DmaPageHighPort) +
+ (ULONG)AdapterObject->PagePort,
+ 0
+ );
+
+ //
+ // Notify DMA chip of the length to transfer.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) & 0xff)
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount,
+ (UCHAR) ((transferLength - 1) >> 8)
+ );
+
+
+ //
+ // Set the DMA chip to read or write mode; and unmask it.
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &dmaControl->SingleMask,
+ (UCHAR) (DMA_CLEARMASK | AdapterObject->ChannelNumber)
+ );
+
+ }
+ KeReleaseSpinLock (&AdapterObject->MasterAdapter->SpinLock, Irql);
+
+ return(returnAddress);
+}
+
+BOOLEAN
+IoFlushAdapterBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine flushes the DMA adapter object buffers. For the Jazz system
+ its clears the enable flag which aborts the dma.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object representing the DMA
+ controller channel.
+
+ Mdl - A pointer to a Memory Descriptor List (MDL) that maps the locked-down
+ buffer to/from which the I/O occured.
+
+ MapRegisterBase - A pointer to the base of the map registers in the adapter
+ or DMA controller.
+
+ CurrentVa - The current virtual address in the buffer described the the Mdl
+ where the I/O operation occurred.
+
+ Length - Supplies the length of the transfer.
+
+ WriteToDevice - Supplies a BOOLEAN value that indicates the direction of
+ the data transfer was to the device.
+
+Return Value:
+
+ TRUE - No errors are detected so the transfer must succeed.
+
+--*/
+
+{
+ PTRANSLATION_ENTRY translationEntry;
+ PULONG pageFrame;
+ ULONG transferLength;
+ ULONG partialLength;
+ BOOLEAN masterDevice;
+
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ masterDevice = AdapterObject == NULL || AdapterObject->MasterDevice ?
+ TRUE : FALSE;
+
+ //
+ // If this is a slave device, then stop the DMA controller.
+ //
+
+ if (!masterDevice) {
+
+ //
+ // Mask the DMA request line so that DMA requests cannot occur.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_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)
+ );
+
+ }
+
+ }
+
+ if (MapRegisterBase == NULL) {
+ return(TRUE);
+ }
+
+ //
+ // Determine if the data needs to be copied to the orginal buffer.
+ // This only occurs if the data tranfer is from the device, the
+ // MapReisterBase is not NULL and the transfer spans a page.
+ //
+
+ if (!WriteToDevice) {
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // If this is not a master device, then just transfer the buffer.
+ //
+
+ if ((ULONG) MapRegisterBase & NO_SCATTER_GATHER) {
+
+ if (translationEntry->Index == COPY_BUFFER) {
+
+ if (!masterDevice) {
+
+ //
+ // Copy only the bytes that have actually been transfered.
+ //
+
+ Length -= HalReadDmaCounter(AdapterObject);
+
+ }
+
+ //
+ // The adapter does not support scatter/gather copy the buffer.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+ }
+
+ } else {
+
+ //
+ // Cycle through the pages of the transfer to determine if there
+ // are any which need to be copied back.
+ //
+
+ transferLength = PAGE_SIZE - BYTE_OFFSET(CurrentVa);
+ partialLength = transferLength;
+ pageFrame = (PULONG)(Mdl+1);
+ pageFrame += ((ULONG) CurrentVa - (ULONG) Mdl->StartVa) >> PAGE_SHIFT;
+
+ while( transferLength <= Length ){
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+
+ (PCCHAR) CurrentVa += partialLength;
+ partialLength = PAGE_SIZE;
+
+ //
+ // Note that transferLength indicates the amount which will be
+ // transfered after the next loop; thus, it is updated with the
+ // new partial length.
+ //
+
+ transferLength += partialLength;
+ pageFrame++;
+ translationEntry++;
+ }
+
+ //
+ // Process the any remaining residue.
+ //
+
+ partialLength = Length - transferLength + partialLength;
+
+ if (partialLength) {
+
+ if (*pageFrame >= BYTES_TO_PAGES(MAXIMUM_PHYSICAL_ADDRESS)) {
+
+ HalpCopyBufferMap(
+ Mdl,
+ translationEntry,
+ CurrentVa,
+ partialLength,
+ WriteToDevice
+ );
+
+ }
+ }
+
+ }
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ translationEntry = (PTRANSLATION_ENTRY) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ //
+ // Clear index in map register.
+ //
+
+ translationEntry->Index = 0;
+
+ return TRUE;
+}
+
+ULONG
+HalReadDmaCounter(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+/*++
+
+Routine Description:
+
+ This function reads the DMA counter and returns the number of bytes left
+ to be transfered.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object to be read.
+
+Return Value:
+
+ Returns the number of bytes still be be transfered.
+
+--*/
+
+{
+ ULONG count;
+ ULONG high;
+ KIRQL Irql;
+
+ //
+ // Grab the spinlock for the system DMA controller.
+ //
+
+ KeAcquireSpinLock( &AdapterObject->MasterAdapter->SpinLock, &Irql );
+
+ //
+ // Determine the controller number based on the Adapter number.
+ //
+
+ if (AdapterObject->AdapterNumber == 1) {
+
+ //
+ // This request is for DMA controller 1
+ //
+
+ PDMA1_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+ } else {
+
+ //
+ // This request is for DMA controller 2
+ //
+
+ PDMA2_CONTROL dmaControl;
+
+ dmaControl = AdapterObject->AdapterBaseVa;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Initialize count to a value which will not match.
+ //
+
+ count = 0xFFFF00;
+
+ //
+ // Loop until the same high byte is read twice.
+ //
+
+ do {
+
+ high = count;
+
+ WRITE_REGISTER_UCHAR( &dmaControl->ClearBytePointer, 0 );
+
+ //
+ // Read the current DMA count.
+ //
+
+ count = READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ );
+
+ count |= READ_REGISTER_UCHAR(
+ &dmaControl->DmaAddressCount[AdapterObject->ChannelNumber]
+ .DmaBaseCount
+ ) << 8;
+
+ } while ((count & 0xFFFF00) != (high & 0xFFFF00));
+
+
+ }
+
+ //
+ // Release the spinlock for the system DMA controller.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->MasterAdapter->SpinLock, Irql );
+
+ //
+ // The DMA counter has a bias of one and can only be 16 bit long.
+ //
+
+ count = (count + 1) & 0xFFFF;
+
+ //
+ // If this is a 16 bit dma the multiply the count by 2.
+ //
+
+ if (AdapterObject->Width16Bits) {
+
+ count *= 2;
+
+ }
+
+ return(count);
+}
+
+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 ESIA 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
+ );
+ }
+
+}
+
+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
+ );
+
+ }
+
+}
+
+VOID
+HalpEnableOnboardInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ )
+
+/*++
+
+Routine Description:
+
+ This function enables the ISA bus (onboard) specified ISA bus interrupt and sets
+ the level/edge register to the requested value.
+
+Arguments:
+
+ Vector - Supplies the vector of the ISA(onboard) interrupt that is enabled.
+
+ InterruptMode - Supplies the mode of the interrupt; LevelSensitive or
+ Latched.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Calculate the ISA interrupt vector.
+ //
+
+ Vector -= ONBOARD_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpOnboardInterrupt2Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt2ControlPort1,
+ HalpOnboardInterrupt2Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpOnboardInterrupt2Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpOnboardInterrupt2Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt2EdgeLevel,
+ HalpOnboardInterrupt2Level
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpOnboardInterrupt1Mask &= (UCHAR) ~(1 << Vector);
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt1ControlPort1,
+ HalpOnboardInterrupt1Mask
+ );
+
+ //
+ // Set the level/edge control register.
+ //
+
+ if (InterruptMode == LevelSensitive) {
+
+ HalpOnboardInterrupt1Level |= (UCHAR) (1 << Vector);
+
+ } else {
+
+ HalpOnboardInterrupt1Level &= (UCHAR) ~(1 << Vector);
+
+ }
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt1EdgeLevel,
+ HalpOnboardInterrupt1Level
+ );
+ }
+
+}
+
+VOID
+HalpDisableOnboardInterrupt(
+ IN ULONG Vector
+ )
+
+/*++
+
+Routine Description:
+
+ This function Disables the ISA(Onboard) bus interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the ISA interrupt that is Disabled.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+
+ //
+ // Calculate the Onboard interrupt vector.
+ //
+
+ Vector -= ONBOARD_VECTORS;
+
+ //
+ // Determine if this vector is for interrupt controller 1 or 2.
+ //
+
+ if (Vector & 0x08) {
+
+ //
+ // The interrupt is in controller 2.
+ //
+
+ Vector &= 0x7;
+
+ HalpOnboardInterrupt2Mask |= (UCHAR) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt2ControlPort1,
+ HalpOnboardInterrupt2Mask
+ );
+
+ } else {
+
+ //
+ // The interrupt is in controller 1.
+ //
+
+ Vector &= 0x7;
+
+ HalpOnboardInterrupt1Mask |= (ULONG) 1 << Vector;
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->Interrupt1ControlPort1,
+ HalpOnboardInterrupt1Mask
+ );
+
+ }
+
+}
+
+BOOLEAN
+HalpCreateEisaStructures (
+ IN INTERFACE_TYPE InterfaceType
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for Isa (Desktop onboard) or
+ EISA operations
+ and connects the intermediate interrupt dispatcher. It also initializes the
+ 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;
+ PEISA_CONTROL controlBase;
+
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+ //
+ // Raise the IRQL while the interrupt controller is initialized.
+ //
+
+ KeRaiseIrql(EISA_DEVICE_LEVEL, &oldIrql);
+
+ //
+ // Initialize the Isa/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(
+ &(controlBase)->Interrupt1ControlPort0,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ DataByte
+ );
+
+ //
+ // The second intitialization control word sets the interrupt vector to
+ // 0-15.
+ //
+
+ DataByte = 0x00;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = 0x08;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // The third initialization control word set the controls for slave mode.
+ // The master ICW3 uses bit position and the slave ICW3 uses a numeric.
+ //
+
+ DataByte = 1 << SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ DataByte = SLAVE_IRQL_LEVEL;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->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(
+ &(controlBase)->Interrupt1ControlPort1,
+ DataByte
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort1,
+ DataByte
+ );
+
+ //
+ // this is for the onboard components
+ // Disable all of the interrupts except the slave.
+ //
+
+ HalpOnboardInterrupt1Mask = (UCHAR) ~(1 << SLAVE_IRQL_LEVEL);
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort1,
+ HalpOnboardInterrupt1Mask
+ );
+
+ HalpOnboardInterrupt2Mask = 0xFF;
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort1,
+ HalpOnboardInterrupt2Mask
+ );
+
+ //
+ // Initialize the edge/level register masks to 0 which is the default
+ // edge sensitive value.
+ //
+
+ HalpOnboardInterrupt1Level = 0;
+ HalpOnboardInterrupt2Level = 0;
+
+ //
+ // Restore IRQL level.
+ //
+
+ KeLowerIrql(oldIrql);
+
+ //
+ // 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(
+ &(controlBase)->Dma1BasePort.AllMask,
+ 0x0F
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Dma2BasePort.AllMask,
+ 0x0E
+ );
+
+ return(TRUE);
+}
+
+BOOLEAN
+HalpPciEisaDispatch(
+ 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 connected to an interrupt object that describes
+ the EISA device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the EISA
+ controller.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector;
+ USHORT PCRInOffset, Offset;
+ BOOLEAN returnValue;
+ PEISA_CONTROL controlBase;
+
+ //
+ // this is the default case
+ // the interrupts occur on the onboard PC core
+ //
+
+ PCRInOffset = ONBOARD_VECTORS;
+ Offset = ONBOARD_VECTORS;
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+ //
+ // Send a POLL Command to Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+ if (interruptVector & 0x80) {
+
+ //
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector &= 0x07;
+
+ //
+ // See if this is an interrupt on IRQ2 which is cascaded to the
+ // other interrupt controller
+ //
+
+ if (interruptVector!=0x02) {
+
+ //
+ // This interrupt is on the first interrupt controller
+ //
+
+ PCRInOffset += (USHORT)interruptVector;
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset]
+ );
+
+ //
+ // Clear the interrupt from Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return returnValue;
+
+ } else {
+
+ //
+ // This interrupt is on the second interrupt controller
+ //
+
+ //
+ // Send a POLL Command to Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+ if (interruptVector & 0x80) {
+
+ //
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector &= 0x07;
+
+ PCRInOffset += (USHORT)(interruptVector + 8);
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset]
+ );
+
+ //
+ // Clear the interrupt from Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ //
+ // Clear the interrupt from Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ NONSPECIFIC_END_OF_INTERRUPT
+ );
+
+ return returnValue;
+
+ }
+ }
+ }
+}
+
+BOOLEAN
+HalpPciEisaSBDispatch(
+ 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 connected to an interrupt object that describes
+ the EISA device interrupts. Its function is to call the second
+ level interrupt dispatch routine and acknowledge the interrupt at the EISA
+ controller.
+
+!!!!!!!!! This routine is only use with the chip 82375 SB (for the moment only PCI Tower)
+ * Bug : This version doesn't report an interrupt request coming from the slave interrupt controller
+ * Workaround :
+ - to detect interrupts from slave controller :
+ * master controller : read ISR to detect pending interrupt IRQ2
+ * if no valid interrupt on master controller --> interrupt from slave controller
+ - slave controller : Loop until there is no more interrupt valid
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the EISA interrupt acknowledge
+ register.
+
+Return Value:
+
+ Returns the value returned from the second level routine.
+
+--*/
+
+{
+ UCHAR interruptVector = 0;
+ UCHAR PollSlave;
+ USHORT PCRInOffset;
+ BOOLEAN returnValue;
+ PEISA_CONTROL controlBase;
+ UCHAR isr;
+
+
+
+ PCRInOffset = ONBOARD_VECTORS;
+ controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+
+
+
+ //
+ // Send a POLL Command to Interrupt Controller 1
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ interruptVector = READ_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+ if (interruptVector & 0x80) {
+
+
+
+ // read ISR
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ 0xb
+ );
+
+ isr = READ_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0);
+
+
+ if (isr == 0x4) interruptVector = 2;
+
+
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector &= 0x07;
+
+ //
+ // See if this is an interrupt on IRQ2 which is cascaded to the
+ // other interrupt controller
+ //
+
+ if (interruptVector!=0x02) {
+
+ //
+ // This interrupt is on the first interrupt controller
+ //
+
+ PCRInOffset += (USHORT)interruptVector;
+
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ (SPECIFIC_END_OF_INTERRUPT | interruptVector)
+ );
+ return returnValue;
+
+ }
+
+ }
+
+
+
+ do {
+
+ //
+ // Send a POLL Command to Interrupt Controller 2
+ //
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ 0x0c
+ );
+
+ //
+ // Read the interrupt vector
+ //
+
+ PollSlave = READ_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0);
+
+ //
+ // See if there is really an interrupt present
+ //
+
+
+
+ if (PollSlave & 0x80) {
+
+ //
+ // Strip off the all the bits except for the interrupt vector
+ //
+
+ interruptVector = PollSlave & 0x07;
+
+
+ PCRInOffset = (USHORT)(interruptVector + 8) + ONBOARD_VECTORS;
+
+
+
+
+ //
+ // Dispatch to the secondary interrupt service routine.
+ //
+
+ returnValue = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[PCRInOffset])(
+ PCR->InterruptRoutine[PCRInOffset]
+ );
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt2ControlPort0,
+ (SPECIFIC_END_OF_INTERRUPT | interruptVector)
+ );
+
+
+ }
+
+
+
+ } while ( PollSlave & 0x80);
+
+ WRITE_REGISTER_UCHAR(
+ &(controlBase)->Interrupt1ControlPort0,
+ (SPECIFIC_END_OF_INTERRUPT | 0x2)
+ );
+ return returnValue;
+}
+
+/*++
+
+Routine Description:
+
+ Get the revision ID of the 82374 PCI_EISA Bridge
+
+Arguments:
+
+
+Return Value:
+
+ Returns the revision of the 82374 PCI_EISA Bridge
+
+--*/
+
+
+UCHAR HalpRevIdESC(VOID)
+{
+UCHAR save_value,Rev_ID;
+
+// save value
+WRITE_REGISTER_UCHAR(PCI_ESC_ADDR,PCI_ESC_ID_82374);
+save_value = READ_REGISTER_UCHAR(PCI_ESC_DATA);
+
+//free to read
+WRITE_REGISTER_UCHAR(PCI_ESC_ADDR,PCI_ESC_ID_82374);
+WRITE_REGISTER_UCHAR(PCI_ESC_DATA,0xf);
+
+//get current version
+WRITE_REGISTER_UCHAR(PCI_ESC_ADDR,PCI_REV_ID_82374);
+Rev_ID =READ_REGISTER_UCHAR(PCI_ESC_DATA);
+
+//restore old value
+WRITE_REGISTER_UCHAR(PCI_ESC_ADDR,PCI_ESC_ID_82374);
+WRITE_REGISTER_UCHAR(PCI_ESC_DATA,save_value);
+
+return (Rev_ID );
+}
diff --git a/private/ntos/nthals/halsnip/mips/jxenvirv.c b/private/ntos/nthals/halsnip/mips/jxenvirv.c
new file mode 100644
index 000000000..6584e3a56
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxenvirv.c
@@ -0,0 +1,192 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxenvirv.c,v 1.2 1995/11/02 11:04:33 flo Exp $")
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+Copyright (c) 1993 Siemens Nixdorf Informationssyteme AG
+
+Module Name:
+
+ jxenvirv.c
+
+Abstract:
+
+ This module implements the HAL get and set environment variable routines
+ for a MIPS system.
+
+Environment:
+
+ Kernel mode
+
+NOTES:
+ --- Preliminary using ARC function calls ---
+
+--*/
+
+
+#include "halp.h"
+#include "arccodes.h"
+#include "arc.h"
+
+ // preliminary calls to the ARC functions (function vector call)
+
+ /* NOTE:
+ This is strongly discouraged by the ARC specifications.
+ Only "reset"/return calls to the prom are recommended.
+ All other system access to the NVRAM should be handled
+ by operating systems functions directly. For that the
+ operating system has to know the algorithms for handling
+ those data structures (e.g. the checksum calculations).
+ Though is a drawback in terms of HW/FW-independance NT
+ seems to avoid side effects of ARC function code that way,
+ e.g. via register/stack manipulations.
+ */
+
+//
+// The following addresses are defined by ARC and handed over to the osloader.
+// For now we assume that the osloader will leave this memory part unchanged
+// for the operating system (NT), which itself also doesn't overwrite that
+// data structure.
+// We don't (yet) know yet know whether the firmware copies or maps/banks
+// runnable code into the physical memory (or if it just sets up a vector
+// into the prom). We also do not know whether the NVRAM variables are copied
+// into physical memory or mapped/banked by the (ARC) firmware.
+//
+
+//
+// Therefore we preliminary use the ARC entry vectors from ARC.H
+//
+
+
+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.
+
+NOTE:
+ This implementation returns the error code ENOMEM if the output buffer
+ is too small.
+
+--*/
+
+{
+
+ PUCHAR Environment_var;
+ ULONG Index;
+ ARC_STATUS Status;
+
+ //
+ // retrieve the variable
+ //
+
+ Environment_var = (PUCHAR)ArcGetEnvironmentVariable(Variable);
+
+ if (Environment_var == (PUCHAR)NULL) {
+
+ Status = ENOENT;
+
+ } else {
+
+ //
+ // Copy the specified value to the output buffer.
+ //
+
+ for (Index = 0; Index < Length; Index += 1) {
+ *Buffer = READ_REGISTER_UCHAR(Environment_var);
+ if (*Buffer == 0) {
+ break;
+ }
+
+ Buffer += 1;
+ Environment_var += 1;
+ }
+
+ //
+ // If the length terminated the loop, then return not enough memory.
+ // Otherwise, return success.
+ //
+
+ if (Index == Length) {
+ Status = ENOMEM;
+
+ } else {
+ Status = ESUCCESS;
+ }
+ }
+
+ 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.
+
+NOTES:
+ This preliminary implementation always returns ESUCCESS even in case of
+ error.
+
+--*/
+
+{
+
+ ARC_STATUS Status;
+
+ Status = ArcSetEnvironmentVariable(Variable, Value);
+
+ switch (Status) {
+
+ case ESUCCESS:
+ break;
+
+ case ENOSPC:
+ break; // until further we assume NT can handle that
+
+ case ENOMEM:
+ default:
+ Status = ENOMEM;
+ break;
+ }
+ return Status;
+}
+
diff --git a/private/ntos/nthals/halsnip/mips/jxhwsup.c b/private/ntos/nthals/halsnip/mips/jxhwsup.c
new file mode 100644
index 000000000..07bd0f121
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxhwsup.c
@@ -0,0 +1,2250 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxhwsup.c,v 1.7 1996/03/12 14:56:20 pierre Exp $")
+/*++
+
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ jxhwsup.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.
+
+
+Environment:
+
+ Kernel mode
+
++++*/
+
+
+#include "halp.h"
+#include "eisa.h"
+
+extern VOID NtClose();
+
+typedef struct {
+ PVOID MmContiguousAddr;
+ PVOID MmMapIoSpaceAddr;
+ PVOID Next;
+} HALP_MEMORY;
+
+HALP_MEMORY HalpMemoryBuffer ={0,0,0}, * HalpMemoryBufferPt;
+
+ULONG
+HalpReadEisaData (
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+//
+// Some devices require a phyicially contiguous data buffers for DMA transfers.
+// Map registers are used give the appearance that all data buffers are
+// contiguous. 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 which requires
+// map registers.
+//
+
+PADAPTER_OBJECT MasterAdapterObject;
+
+
+//
+// Map buffer parameters. These are initialized in HalInitSystem
+//
+
+
+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.
+ This routine is used when the machine is less than 16Mb memory.
+
+Arguments:
+
+ AdapterObject - Supplies the adapter object for which the buffers are to be
+ allocated.
+
+ Amount - Indicates the size of the map buffers which should be allocated.
+
+Return Value:
+
+ TRUE is returned if the memory could be allocated.
+
+ FALSE is returned if the memory could not be allocated.
+
+--*/
+{
+ ULONG MapBufferPhysicalAddress;
+ PVOID MapBufferVirtualAddress;
+ PTRANSLATION_ENTRY TranslationEntry;
+ LONG NumberOfPages;
+ LONG i;
+ KIRQL Irql;
+ PHYSICAL_ADDRESS physicalAddress;
+ PULONG Page;
+ PMDL mdl;
+
+ KeAcquireSpinLock( &AdapterObject->SpinLock, &Irql );
+
+ NumberOfPages = BYTES_TO_PAGES(Amount);
+
+ //
+ // Make sure there is room for the additional 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 allocation amount so it will fit.
+ //
+
+ NumberOfPages += i;
+ }
+
+ if (NumberOfPages <= 0) {
+ //
+ // No more memory can be allocated.
+ //
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+
+ 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 allocating a new one.
+ //
+
+ MapBufferPhysicalAddress = HalpMapBufferPhysicalAddress.LowPart;
+
+ //
+ // Map the buffer for access.
+ //
+
+ MapBufferVirtualAddress = MmMapIoSpace(
+ HalpMapBufferPhysicalAddress,
+ HalpMapBufferSize,
+ FALSE // Cache disable. Importent for DMA if we
+ // have more than 16Mb memory in our SNI
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ //
+ // The buffer could not be mapped.
+ //
+
+ HalpMapBufferSize = 0;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+
+
+ return(FALSE);
+ }
+
+ } else {
+
+ //
+ // Allocate the map buffers.
+ // (We use MmAllocateContiguousMemory because we need a specific physical limit to the address)
+ //
+ physicalAddress.LowPart = MAXIMUM_PHYSICAL_ADDRESS - 1;
+ physicalAddress.HighPart = 0;
+ MapBufferVirtualAddress = MmAllocateContiguousMemory(
+ NumberOfPages * PAGE_SIZE,
+ physicalAddress
+ );
+
+ if (MapBufferVirtualAddress == NULL) {
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+
+ return(FALSE);
+ }
+
+ //
+ // Get the physical address of the map base.
+ //
+
+ MapBufferPhysicalAddress = MmGetPhysicalAddress(
+ MapBufferVirtualAddress
+ ).LowPart;
+
+ //
+ // flush the new allocated memory area
+ // because we are going to use it uncached.
+ //
+
+ mdl = MmCreateMdl(NULL,MapBufferVirtualAddress,NumberOfPages * PAGE_SIZE);
+ Page = (PULONG) (mdl + 1);
+ for (i=0;i < NumberOfPages; ++i) {
+ *Page = (MapBufferPhysicalAddress >> PAGE_SHIFT)+i;
+ ++Page;
+ }
+ KeFlushIoBuffers(mdl,TRUE,TRUE);
+
+ //
+ // Map registers need to be uncached.
+ //
+
+ physicalAddress.LowPart = MapBufferPhysicalAddress;
+ physicalAddress.HighPart = 0;
+ MapBufferVirtualAddress = MmMapIoSpace(
+ physicalAddress,
+ NumberOfPages * PAGE_SIZE,
+ FALSE
+ );
+
+ }
+
+ //
+ // Initialize the map registers where memory has been allocated.
+ //
+
+ TranslationEntry = ((PTRANSLATION_ENTRY) AdapterObject->MapRegisterBase) +
+ AdapterObject->NumberOfMapRegisters;
+
+ //
+ // Make sure the previous entry is physically contiguous with the next
+ // entry
+ //
+
+ 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 boundary.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+
+ for (i = 0; i < NumberOfPages; i++) {
+
+#if 0
+ //
+ // Make sure the previous entry is physically contiguous with the next
+ // entry and that a 64K physical boundary is not crossed unless this
+ // is an Eisa system.
+ //
+
+ if (TranslationEntry != AdapterObject->MapRegisterBase &&
+ (((TranslationEntry - 1)->PhysicalAddress + PAGE_SIZE) !=
+ MapBufferPhysicalAddress || (!HalpEisaDma &&
+ ((TranslationEntry - 1)->PhysicalAddress & ~0x0ffff) !=
+ (MapBufferPhysicalAddress & ~0x0ffff)))) {
+
+ //
+ // An entry needs to be skipped in the table. This entry will
+ // remain marked as allocated so that no allocation of map
+ // registers will cross this boundary.
+ //
+
+ TranslationEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+#endif
+ //
+ // Clear the bits where the memory has been allocated.
+ //
+
+ RtlClearBits(
+ AdapterObject->MapRegisters,
+ TranslationEntry - (PTRANSLATION_ENTRY)
+ AdapterObject->MapRegisterBase,
+ 1
+ );
+ TranslationEntry->VirtualAddress = MapBufferVirtualAddress;
+ TranslationEntry->PhysicalAddress = MapBufferPhysicalAddress;
+ TranslationEntry++;
+ (PCCHAR) MapBufferVirtualAddress += PAGE_SIZE;
+ MapBufferPhysicalAddress += PAGE_SIZE;
+
+ }
+
+ //
+ // Remember the number of pages that where allocated.
+ //
+
+ AdapterObject->NumberOfMapRegisters += NumberOfPages;
+
+ KeReleaseSpinLock( &AdapterObject->SpinLock, Irql );
+
+
+ return(TRUE);
+}
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID ChannelNumber
+ )
+
+/*++
+
+Routine Description:
+
+ This routine allocates and initializes an adapter object to represent an
+ adapter or a DMA controller on the system. If no map registers are required
+ then a standalone adapter object is allocated with no master adapter.
+
+ If map registers are required, then a master adapter object is used to
+ allocate the map registers. For Isa systems these registers are really
+ physically contiguous memory pages.
+
+Arguments:
+
+ MapRegistersPerChannel - Specifies the number of map registers that each
+ channel provides for I/O memory mapping.
+
+ AdapterBaseVa - Address of the the DMA controller.
+
+ ChannelNumber - Unused.
+
+Return Value:
+
+ The function value is a pointer to the allocate adapter object.
+
+--*/
+
+{
+
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG Size;
+ ULONG BitmapSize;
+ HANDLE Handle;
+ NTSTATUS Status;
+
+ UNREFERENCED_PARAMETER(ChannelNumber);
+
+
+ //
+ // Initalize the master adapter if necessary.
+ //
+ if (MasterAdapterObject == NULL && AdapterBaseVa != (PVOID) -1 &&
+ MapRegistersPerChannel) {
+
+ MasterAdapterObject = HalpAllocateAdapter(
+ MapRegistersPerChannel,
+ (PVOID) -1,
+ NULL
+ );
+
+ //
+ // If we could not allocate the master adapter then give up.
+ //
+ if (MasterAdapterObject == NULL) {
+
+ return(NULL);
+ }
+ }
+
+ //
+ // Begin by initializing the object attributes structure to be used when
+ // creating the adapter object.
+ //
+
+ InitializeObjectAttributes( &ObjectAttributes,
+ NULL,
+ OBJ_PERMANENT,
+ (HANDLE) NULL,
+ (PSECURITY_DESCRIPTOR) NULL
+ );
+
+ //
+ // Determine the size of the adapter object. If this is the master object
+ // then allocate space for the register bit map; otherwise, just allocate
+ // an adapter object.
+ //
+ if (AdapterBaseVa == (PVOID) -1) {
+
+ //
+ // Allocate a bit map large enough MAXIMUM_MAP_BUFFER_SIZE / PAGE_SIZE
+ // of map register buffers.
+ //
+
+ BitmapSize = (((sizeof( RTL_BITMAP ) +
+ (( ((MAXIMUM_MAP_BUFFER_SIZE*9)/8) / PAGE_SIZE ) + 7 >> 3)) + 3) & ~3);
+ Size = sizeof( ADAPTER_OBJECT ) + BitmapSize;
+
+
+ } else {
+
+ Size = sizeof( ADAPTER_OBJECT );
+
+ }
+
+ //
+ // Now create the adapter object.
+ //
+
+ Status = ObCreateObject( KernelMode,
+ *IoAdapterObjectType,
+ &ObjectAttributes,
+ KernelMode,
+ (PVOID) NULL,
+ Size,
+ 0,
+ 0,
+ (PVOID *)&AdapterObject );
+
+ //
+ // Reference the object.
+ //
+
+ if (NT_SUCCESS(Status)) {
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ *IoAdapterObjectType,
+ KernelMode
+ );
+
+ }
+
+ //
+ // If the adapter object was successfully created, then attempt to insert
+ // it into the the object table.
+ //
+
+ if (NT_SUCCESS( Status )) {
+
+ Status = ObInsertObject( AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ (PVOID *) NULL,
+ &Handle );
+
+ if (NT_SUCCESS( Status )) {
+
+ NtClose( Handle );
+
+ //
+ // Initialize the adapter object itself.
+ //
+
+ AdapterObject->Type = IO_TYPE_ADAPTER;
+ AdapterObject->Size = (USHORT) Size;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+
+ if (MapRegistersPerChannel) {
+
+ AdapterObject->MasterAdapter = MasterAdapterObject;
+
+ } else {
+
+ AdapterObject->MasterAdapter = NULL;
+
+ }
+
+ //
+ // Initialize the channel wait queue for this
+ // adapter.
+ //
+
+ KeInitializeDeviceQueue( &AdapterObject->ChannelWaitQueue );
+
+ //
+ // If this is the MasterAdatper then initialize the register bit map,
+ // AdapterQueue and the spin lock.
+ //
+
+ if ( AdapterBaseVa == (PVOID) -1 ) {
+
+ KeInitializeSpinLock( &AdapterObject->SpinLock );
+
+ InitializeListHead( &AdapterObject->AdapterQueue );
+
+ AdapterObject->MapRegisters = (PVOID) ( AdapterObject + 1);
+
+ RtlInitializeBitMap( AdapterObject->MapRegisters,
+ (PULONG) (((PCHAR) (AdapterObject->MapRegisters)) + sizeof( RTL_BITMAP )),
+ ((9 * MAXIMUM_MAP_BUFFER_SIZE) / 8) / PAGE_SIZE
+ );
+ //
+ // Set all the bits in the memory to indicate that memory
+ // has not been allocated for the map buffers
+ //
+
+ RtlSetAllBits( AdapterObject->MapRegisters );
+ AdapterObject->NumberOfMapRegisters = 0;
+ AdapterObject->CommittedMapRegisters = 0;
+
+ //
+ // ALlocate the memory map registers.
+ //
+
+ AdapterObject->MapRegisterBase = ExAllocatePool(
+ NonPagedPool,
+ (((9 * MAXIMUM_MAP_BUFFER_SIZE) / 8) / PAGE_SIZE ) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (AdapterObject->MapRegisterBase == NULL) {
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+
+
+ return(NULL);
+
+ }
+
+ //
+ // Zero the map registers.
+ //
+
+ RtlZeroMemory(
+ AdapterObject->MapRegisterBase,
+ (((9 * MAXIMUM_MAP_BUFFER_SIZE) / 8) / PAGE_SIZE ) *
+ sizeof(TRANSLATION_ENTRY)
+ );
+
+ if (!HalpGrowMapBuffers(AdapterObject, INITIAL_MAP_BUFFER_SMALL_SIZE))
+ {
+
+ //
+ // If no map registers could be allocated then free the
+ // object.
+ //
+
+ ObDereferenceObject( AdapterObject );
+ AdapterObject = NULL;
+
+
+ return(NULL);
+
+ }
+ }
+
+ } else {
+
+ //
+ // An error was incurred for some reason. Set the return value
+ // to NULL.
+ //
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+ }
+ } else {
+
+ AdapterObject = (PADAPTER_OBJECT) NULL;
+
+ }
+
+
+
+ return AdapterObject;
+
+}
+
+VOID
+HalpCopyBufferMap(
+ IN PMDL Mdl,
+ IN PTRANSLATION_ENTRY TranslationEntry,
+ IN PVOID CurrentVa,
+ IN ULONG Length,
+ IN BOOLEAN WriteToDevice
+ )
+
+/*++
+
+Routine Description:
+
+ This routine copies the specific 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, (PCCHAR)bufferAddress, Length);
+
+ } else {
+
+ RtlMoveMemory( (PCCHAR)bufferAddress, mapAddress, Length);
+
+
+ }
+
+}
+
+PTRANSLATION_ENTRY
+HalpAcquireMapBuffers(
+ ULONG NumberOfMapRegisters,
+ PADAPTER_OBJECT MasterAdapter)
+{
+ KIRQL Irql;
+ ULONG MapRegisterNumber;
+ PTRANSLATION_ENTRY MapRegisterBase;
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber > MasterAdapter->NumberOfMapRegisters) {
+ HalpGrowMapBuffers(
+ MasterAdapterObject,
+ INCREMENT_MAP_BUFFER_SIZE
+ );
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ NumberOfMapRegisters,
+ 0
+ );
+ if (MapRegisterNumber > MasterAdapter->NumberOfMapRegisters)
+ MapRegisterNumber = (ULONG)-1;
+ }
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+// InsertTailList( &MasterAdapter->AdapterQueue,
+// &AdapterObject->AdapterQueue
+// );
+// Busy = 1;
+
+ MapRegisterBase = NULL;
+
+ } else {
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ return(MapRegisterBase);
+}
+
+
+
+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;
+ ULONG numberOfMapRegisters;
+ PTRANSLATION_ENTRY MapRegisterTranslation;
+ PHYSICAL_ADDRESS physicalAddress;
+ KIRQL Irql;
+
+ numberOfMapRegisters = BYTES_TO_PAGES(Length);
+
+ //
+ // Allocate the actual buffer.
+ //
+
+ if (AdapterObject->InterfaceType != PCIBus) {
+
+ // address < 16Mb (isa compatibility) - cut to 64k
+ MapRegisterTranslation = HalpAcquireMapBuffers(numberOfMapRegisters,MasterAdapterObject);
+ if (MapRegisterTranslation == NULL) return(NULL);
+ virtualAddress = MapRegisterTranslation->VirtualAddress;
+ LogicalAddress->LowPart = MapRegisterTranslation->PhysicalAddress;
+ LogicalAddress->HighPart = 0;
+
+ } else {
+
+ // no limitation : address contiguous because we cannot use map registers
+ // for scatter-gather in this function
+ physicalAddress.LowPart = 0x7FFFFFFF;
+ physicalAddress.HighPart = 0;
+
+ virtualAddress = MmAllocateContiguousMemory(
+ Length,
+ physicalAddress
+ );
+
+ if (virtualAddress == NULL) {
+ return(NULL);
+ }
+
+ *LogicalAddress = MmGetPhysicalAddress(virtualAddress);
+
+ if (CacheEnabled == FALSE) {
+ PULONG Page;
+ ULONG i;
+ PMDL mdl;
+
+ //
+ // flush the new allocated memory area
+ // because we are going to use it uncached.
+ //
+
+ mdl = MmCreateMdl(NULL,virtualAddress,Length);
+ Page = (PULONG) (mdl + 1);
+ for (i=0;i < numberOfMapRegisters; ++i) {
+ *Page = (((LogicalAddress->LowPart)) >> PAGE_SHIFT)+i;
+ ++Page;
+ }
+ KeFlushIoBuffers(mdl,TRUE,TRUE);
+
+ // save the allocated address to be able to free it later.
+
+ KeAcquireSpinLock(&HalpMemoryBufferLock,&Irql);
+ HalpMemoryBufferPt = &HalpMemoryBuffer;
+ while (HalpMemoryBufferPt->Next) HalpMemoryBufferPt = HalpMemoryBufferPt->Next;
+ HalpMemoryBufferPt->Next = ExAllocatePool(PagedPool,sizeof(HALP_MEMORY));
+ HalpMemoryBufferPt = HalpMemoryBufferPt->Next;
+ HalpMemoryBufferPt->Next = NULL;
+ HalpMemoryBufferPt->MmContiguousAddr = virtualAddress;
+
+ // second mapping to get uncached addresses...
+ virtualAddress = MmMapIoSpace(
+ *LogicalAddress,
+ Length,
+ FALSE
+ );
+
+ HalpMemoryBufferPt->MmMapIoSpaceAddr = virtualAddress;
+ KeReleaseSpinLock(&HalpMemoryBufferLock,Irql);
+ }
+ }
+// KeStallExecutionProcessor(50000);
+ return(virtualAddress);
+}
+
+BOOLEAN
+HalFlushCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress
+ )
+/*++
+
+Routine Description:
+
+ This function is called to flush any hardware adapter buffers when the
+ driver needs to read data written by an I/O master device to a common
+ buffer.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+Return Value:
+
+ Returns TRUE if no errors were detected; otherwise, FALSE is return.
+
+--*/
+
+{
+
+ return(TRUE);
+
+}
+
+VOID
+HalFreeCommonBuffer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG Length,
+ IN PHYSICAL_ADDRESS LogicalAddress,
+ IN PVOID VirtualAddress,
+ IN BOOLEAN CacheEnabled
+ )
+/*++
+
+Routine Description:
+
+ This function frees a common buffer and all of the resouces it uses.
+
+Arguments:
+
+ AdapterObject - Supplies a pointer to the adapter object used by this
+ device.
+
+ Length - Supplies the length of the common buffer. This should be the same
+ value used for the allocation of the buffer.
+
+ LogicalAddress - Supplies the logical address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ VirtualAddress - Supplies the virtual address of the common buffer. This
+ must be the same value return by HalAllocateCommonBuffer.
+
+ CacheEnable - Indicates whether the memeory is cached or not.
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PTRANSLATION_ENTRY mapRegisterBase,resultat;
+ ULONG numberOfMapRegisters;
+// ULONG mapRegisterNumber;
+ ULONG i;
+ HALP_MEMORY * HalpMemoryPrevious;
+ KIRQL Irql;
+
+ //
+ // Free the memory for the common buffer.
+ //
+
+ if (AdapterObject->InterfaceType == PCIBus) {
+
+ if (CacheEnabled == FALSE) {
+
+ KeAcquireSpinLock(&HalpMemoryBufferLock ,&Irql);
+ HalpMemoryPrevious = HalpMemoryBufferPt = &HalpMemoryBuffer;
+ while (HalpMemoryBufferPt) {
+ if (HalpMemoryBufferPt->MmMapIoSpaceAddr == VirtualAddress) {
+ MmUnmapIoSpace(VirtualAddress, Length);
+ MmFreeContiguousMemory(HalpMemoryBufferPt->MmContiguousAddr);
+ HalpMemoryPrevious->Next = HalpMemoryBufferPt->Next;
+ ExFreePool(HalpMemoryBufferPt);
+ KeReleaseSpinLock(&HalpMemoryBufferLock,Irql);
+ return;
+ }
+ HalpMemoryPrevious = HalpMemoryBufferPt;
+ HalpMemoryBufferPt = HalpMemoryBufferPt->Next;
+ }
+ KeReleaseSpinLock(&HalpMemoryBufferLock,Irql);
+
+ } else MmFreeContiguousMemory(VirtualAddress);
+
+ return;
+
+ }
+
+
+ //
+ // Calculate the number of map registers, the map register number and
+ // the map register base.
+ //
+
+ numberOfMapRegisters = ADDRESS_AND_SIZE_TO_SPAN_PAGES(VirtualAddress, Length);
+ // mapRegisterNumber = LogicalAddress.LowPart >> PAGE_SHIFT;
+ mapRegisterBase = (PTRANSLATION_ENTRY) MasterAdapterObject->MapRegisterBase;
+ resultat = NULL;
+
+ for (i = 0; i < MasterAdapterObject->NumberOfMapRegisters; i++) {
+
+ if (mapRegisterBase->VirtualAddress == VirtualAddress) {
+ resultat = mapRegisterBase;
+ break;
+ }
+
+ mapRegisterBase++;
+
+ }
+
+
+ //
+ // Free the map registers.
+ //
+
+ IoFreeMapRegisters(
+ AdapterObject,
+ (PVOID) resultat,
+ numberOfMapRegisters
+ );
+
+ return;
+}
+
+PVOID
+HalAllocateCrashDumpRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine is called during the crash dump disk driver's initialization
+ to allocate a number map registers permanently.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter control object to allocate to the
+ driver.
+ NumberOfMapRegisters - Number of map registers requested and update to show
+ number actually allocated.
+
+Return Value:
+
+ Returns STATUS_SUCESS if map registers allocated.
+
+--*/
+
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG MapRegisterNumber;
+
+ //
+ // Begin by obtaining a pointer to the master adapter associated with this
+ // request.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Check to see whether this driver needs to allocate any map registers.
+ //
+
+ if (AdapterObject->NeedsMapRegisters) {
+
+ //
+ // Ensure that this adapter has enough total map registers to satisfy
+ // the request.
+ //
+
+ if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ return NULL;
+ }
+
+ //
+ // Attempt to allocate the required number of map registers w/o
+ // affecting those registers that were allocated when the system
+ // crashed.
+ //
+
+ MapRegisterNumber = (ULONG)-1;
+
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ *NumberOfMapRegisters,
+ 0
+ );
+
+ if (MapRegisterNumber == (ULONG)-1) {
+
+ //
+ // Not enough free map registers were found, so they were busy
+ // being used by the system when it crashed. Force the appropriate
+ // number to be "allocated" at the base by simply overjamming the
+ // bits and return the base map register as the start.
+ //
+
+ RtlSetBits(
+ MasterAdapter->MapRegisters,
+ 0,
+ *NumberOfMapRegisters
+ );
+ MapRegisterNumber = 0;
+
+ }
+
+ //
+ // Calculate the map register base from the allocated map
+ // register and base of the master adapter object.
+ //
+
+ AdapterObject->MapRegisterBase = ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ return AdapterObject->MapRegisterBase;
+}
+
+VOID
+IoFreeAdapterChannel(
+ IN PADAPTER_OBJECT AdapterObject
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is invoked to deallocate the specified adapter object.
+ Any map registers that were allocated are also automatically deallocated.
+ No checks are made to ensure that the adapter is really allocated to
+ a device object. However, if it is not, then kernel will bugcheck.
+
+ If another device is waiting in the queue to allocate the adapter object
+ it will be pulled from the queue and its execution routine will be
+ invoked.
+
+Arguments:
+
+ AdapterObject - Pointer to the adapter object to be deallocated.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PKDEVICE_QUEUE_ENTRY Packet;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN Busy = FALSE;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+ LONG MapRegisterNumber;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ //
+ // Pull requests of the adapter's device wait queue as long as the
+ // adapter is free and there are sufficient map registers available.
+ //
+
+ while( TRUE ) {
+
+ //
+ // Begin by checking to see whether there are any map registers that
+ // need to be deallocated. If so, then deallocate them now.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+ IoFreeMapRegisters( AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters
+ );
+ }
+
+ //
+ // Simply remove the next entry from the adapter's device wait queue.
+ // If one was successfully removed, allocate any map registers that it
+ // requires and invoke its execution routine.
+ //
+
+ Packet = KeRemoveDeviceQueue( &AdapterObject->ChannelWaitQueue );
+ if (Packet == NULL) {
+
+ //
+ // There are no more requests break out of the loop.
+ //
+
+ break;
+ }
+
+ Wcb = CONTAINING_RECORD( Packet,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry );
+
+ AdapterObject->CurrentWcb = Wcb;
+ AdapterObject->NumberOfMapRegisters = Wcb->NumberOfMapRegisters;
+
+ //
+ // Check to see whether this driver wishes to allocate any map
+ // registers. If so, then queue the device object to the master
+ // adapter queue to wait for them to become available. If the driver
+ // wants map registers, ensure that this adapter has enough total
+ // map registers to satisfy the request.
+ //
+
+ if (Wcb->NumberOfMapRegisters != 0 &&
+ AdapterObject->MasterAdapter != NULL) {
+
+ //
+ // Lock the map register bit map and the adapter queue in the
+ // master adapter object. The channel structure offset is used as
+ // a hint for the register search.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ MapRegisterNumber = -1;
+
+ if (IsListEmpty( &MasterAdapter->AdapterQueue)) {
+ MapRegisterNumber = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ Wcb->NumberOfMapRegisters,
+ 0);
+ }
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Queue this request
+ // on the master adapter where is will wait until some registers
+ // are deallocated.
+ //
+
+ InsertTailList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+ Busy = 1;
+
+ } else {
+
+ AdapterObject->MapRegisterBase = (PVOID)((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG)AdapterObject->MapRegisterBase |NO_SCATTER_GATHER);
+
+ }
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ } else {
+
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ }
+
+ //
+ // If there were either enough map registers available or no map
+ // registers needed to be allocated, invoke the driver's execution
+ // routine now.
+ //
+
+ if (!Busy) {
+ AdapterObject->CurrentWcb = Wcb;
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the execution routine would like to have the adapter
+ // deallocated, then release the adapter object.
+ //
+
+ if (Action == KeepObject) {
+
+ //
+ // This request wants to keep the channel a while so break
+ // out of the loop.
+ //
+
+ break;
+
+ }
+
+ //
+ // If the driver wants to keep the map registers then set the
+ // number allocated to 0. This keeps the deallocation routine
+ // from deallocating them.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ } else {
+
+ //
+ // This request did not get the requested number of map registers so
+ // out of the loop.
+ //
+
+ break;
+ }
+ }
+
+}
+
+VOID
+IoFreeMapRegisters(
+ PADAPTER_OBJECT AdapterObject,
+ PVOID MapRegisterBase,
+ ULONG NumberOfMapRegisters
+ )
+/*++
+
+Routine Description:
+
+ This routine deallocates the map registers for the adapter. If there are
+ any queued adapter waiting for an attempt is made to allocate the next
+ entry.
+
+Arguments:
+
+ AdapterObject - The adapter object to where the map register should be
+ returned.
+
+ MapRegisterBase - The map register base of the registers to be deallocated.
+
+ NumberOfMapRegisters - The number of registers to be deallocated.
+
+Return Value:
+
+ None
+
+--+*/
+{
+ PADAPTER_OBJECT MasterAdapter;
+ LONG MapRegisterNumber;
+ PWAIT_CONTEXT_BLOCK Wcb;
+ PLIST_ENTRY Packet;
+ IO_ALLOCATION_ACTION Action;
+ KIRQL Irql;
+
+
+ //
+ // Begin by getting the address of the master adapter.
+ //
+
+ if (AdapterObject->MasterAdapter != NULL && MapRegisterBase != NULL) {
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ } else {
+
+ //
+ // There are no map registers to return.
+ //
+
+ return;
+ }
+
+ //
+ // Strip no scatter/gather flag.
+ //
+
+ MapRegisterBase = (PVOID) ((ULONG) MapRegisterBase & ~NO_SCATTER_GATHER);
+
+ MapRegisterNumber = (PTRANSLATION_ENTRY) MapRegisterBase -
+ (PTRANSLATION_ENTRY) MasterAdapter->MapRegisterBase;
+
+ //
+ // Acquire the master adapter spinlock which locks the adapter queue and the
+ // bit map for the map registers.
+ //
+
+ KeAcquireSpinLock(&MasterAdapter->SpinLock, &Irql);
+
+ //
+ // Return the registers to the bit map.
+ //
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ NumberOfMapRegisters
+ );
+
+ //
+ // Process any requests waiting for map registers in the adapter queue.
+ // Requests are processed until a request cannot be satisfied or until
+ // there are no more requests in the queue.
+ //
+
+ while(TRUE) {
+
+ if ( IsListEmpty(&MasterAdapter->AdapterQueue) ){
+ break;
+ }
+
+ Packet = RemoveHeadList( &MasterAdapter->AdapterQueue );
+ AdapterObject = CONTAINING_RECORD( Packet,
+ ADAPTER_OBJECT,
+ AdapterQueue
+ );
+ Wcb = AdapterObject->CurrentWcb;
+
+ //
+ // Attempt to allocate map registers for this request. Use the previous
+ // register base as a hint.
+ //
+
+ MapRegisterNumber = RtlFindClearBitsAndSet( MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters
+ );
+
+ if (MapRegisterNumber == -1) {
+
+ //
+ // There were not enough free map registers. Put this request back on
+ // the adapter queue where is came from.
+ //
+
+ InsertHeadList( &MasterAdapter->AdapterQueue,
+ &AdapterObject->AdapterQueue
+ );
+
+ break;
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+ AdapterObject->MapRegisterBase = (PVOID) ((PTRANSLATION_ENTRY)
+ MasterAdapter->MapRegisterBase + MapRegisterNumber);
+
+ //
+ // Set the no scatter/gather flag if scatter/gather not
+ // supported.
+ //
+
+ if (!AdapterObject->ScatterGather) {
+
+ AdapterObject->MapRegisterBase = (PVOID)
+ ((ULONG) AdapterObject->MapRegisterBase | NO_SCATTER_GATHER);
+
+ }
+ //
+ // Invoke the driver's execution routine now.
+ //
+
+ Action = Wcb->DeviceRoutine( Wcb->DeviceObject,
+ Wcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ Wcb->DeviceContext );
+
+ //
+ // If the driver wishes to keep the map registers then set the number
+ // allocated to zero and set the action to deallocate object.
+ //
+
+ if (Action == DeallocateObjectKeepRegisters) {
+ AdapterObject->NumberOfMapRegisters = 0;
+ Action = DeallocateObject;
+ }
+
+ //
+ // If the driver would like to have the adapter deallocated,
+ // then deallocate any map registers allocated and then release
+ // the adapter object.
+ //
+
+ if (Action == DeallocateObject) {
+
+ //
+ // The map registers registers are deallocated here rather than in
+ // IoFreeAdapterChannel. This limits the number of times
+ // this routine can be called recursively possibly overflowing
+ // the stack. The worst case occurs if there is a pending
+ // request for the adapter that uses map registers and whos
+ // excution routine decallocates the adapter. In that case if
+ // there are no requests in the master adapter queue, then
+ // IoFreeMapRegisters will get called again.
+ //
+
+ if (AdapterObject->NumberOfMapRegisters != 0) {
+
+ //
+ // Deallocate the map registers and clear the count so that
+ // IoFreeAdapterChannel will not deallocate them again.
+ //
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ RtlClearBits( MasterAdapter->MapRegisters,
+ MapRegisterNumber,
+ AdapterObject->NumberOfMapRegisters
+ );
+
+ AdapterObject->NumberOfMapRegisters = 0;
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+ }
+
+ IoFreeAdapterChannel( AdapterObject );
+ }
+
+ KeAcquireSpinLock( &MasterAdapter->SpinLock, &Irql );
+
+ }
+
+ KeReleaseSpinLock( &MasterAdapter->SpinLock, Irql );
+
+
+}
+
+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
+
+--*/
+
+{
+
+ //
+ // SNI only has one I/O bus which is an EISA, so the bus number is unused.
+ //
+
+ UNREFERENCED_PARAMETER( BusNumber );
+
+
+ TranslatedAddress->HighPart = 0;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ //
+ // There is no difference between IoSpace and MemorySpace in the internal Interface.
+ // Mips Processors have only memory mapped I/O
+ //
+
+ *AddressSpace = 0;
+
+ //
+ // Return the passed parameters.
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+
+ return(TRUE);
+ }
+
+ if (InterfaceType == PCIBus) {
+
+ //
+ // Return the passed parameters.
+ //
+
+ if (*AddressSpace == 1) {
+
+ //
+ // PCI IO Space
+ //
+
+ TranslatedAddress->LowPart = BusAddress.LowPart | PCI_IO_PHYSICAL_BASE;
+
+ } else {
+
+ TranslatedAddress->LowPart = BusAddress.LowPart | PCI_MEMORY_BELOW1M_PHYSICAL_BASE;
+
+ }
+
+ *AddressSpace = 0;
+
+ return (TRUE);
+ }
+
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ DebugPrint(("HAL: HalTranslateBusAddress: WRONG INTERFACE (%d) ", InterfaceType));
+
+ //
+ // Not on this system -- return nothing.
+ //
+
+ *AddressSpace = 0;
+ TranslatedAddress->LowPart = 0;
+ return(FALSE);
+ }
+
+ //
+ // 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.
+ // we always direct Isa and Eisa Adresses to the extension board
+ //
+
+ *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.
+ // we always direct Isa and Eisa Adresses to the extension board
+ //
+
+ *AddressSpace = 0;
+
+ TranslatedAddress->LowPart = BusAddress.LowPart |
+ EISA_MEMORY_PHYSICAL_BASE;
+
+ if (TranslatedAddress->LowPart < BusAddress.LowPart) {
+
+ //
+ // A carry occurred.
+ //
+
+ TranslatedAddress->HighPart = 1;
+ }
+
+ return(TRUE);
+
+ }
+
+ DebugPrint(("HAL: HalTranslateBusAddress: Beeing in the very bad tree\n"));
+
+ TranslatedAddress->LowPart = BusAddress.LowPart;
+ TranslatedAddress->HighPart = 0;
+ return(FALSE);
+}
+
+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 PCIConfiguration:
+ DataLength = HalpGetPCIData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+
+ 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;
+
+
+ switch (BusDataType) {
+
+ case PCIConfiguration:
+ DataLength = HalpSetPCIData(BusNumber, SlotNumber, Buffer, Offset, Length);
+ break;
+
+ default:
+ break;
+
+ }
+
+ 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
+
+--*/
+{
+ switch (BusType) {
+
+ case PCIBus:
+
+ return HalpAssignPCISlotResources (BusNumber,
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ SlotNumber,
+ AllocatedResources);
+ break;
+
+ default:
+ return STATUS_NOT_SUPPORTED;
+ break;
+
+ }
+}
+
+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
+
+--*/
+{
+ if ((*pResourceList)->InterfaceType == PCIBus)
+ return HalpAdjustPCIResourceList ((*pResourceList)->BusNumber, pResourceList);
+
+ //
+ // 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;
+}
+
+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;
+}
+
diff --git a/private/ntos/nthals/halsnip/mips/jxmapio.c b/private/ntos/nthals/halsnip/mips/jxmapio.c
new file mode 100644
index 000000000..b9d54e3ca
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxmapio.c
@@ -0,0 +1,120 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxmapio.c,v 1.2 1995/11/02 11:04:33 flo Exp $")
+
+/*++
+
+Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 - 1994 Microsoft Corporation
+
+Module Name:
+
+ jxmapio.c
+
+Abstract:
+
+ This module implements the mapping of HAL I/O space for a SNI
+ or R4x00 system.
+ For use of EISA I/O Space during phase 0 we go via KSEG1_BASE
+
+Environment:
+
+ Kernel mode
+
+
+--*/
+
+#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) (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE);
+
+//
+// be careful : HalpOnboardControlBase value is used before the init in xxinithl.c
+//
+
+PVOID HalpOnboardControlBase=(PVOID) (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE);
+
+PVOID HalpEisaMemoryBase =(PVOID) (EISA_MEMORY_PHYSICAL_BASE | KSEG1_BASE);
+
+BOOLEAN
+HalpMapIoSpace (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine maps the HAL I/O space for a MIPS R4x00 SNI
+ system (Phase 1, so the mapping goes via MmMapIoSpace()).
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the initialization is successfully completed, than a value of TRUE
+ is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+ PHYSICAL_ADDRESS physicalAddress;
+
+ //
+ // Map EISA control space. Map all 16 slots. This is done so the NMI
+ // code can probe the cards.
+ // (64KB I/O Space)
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = EISA_CONTROL_PHYSICAL_BASE;
+ HalpEisaControlBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 16,
+ FALSE);
+
+ HalpOnboardControlBase = HalpEisaControlBase;
+
+ //
+ // Map EISA memory space so the x86 bios emulator emulator can
+ // initialze a video adapter in an EISA/Isa slot.
+ // (first 1MB only to have access to Card Bioses)
+ // We do not have to call HalTranslateBusAddress on our SNI machines,
+ // because we always use EISA_MEMORY_PHYSICAL_BASE for Extension Cards
+ // on all machines
+ //
+
+ physicalAddress.HighPart = 0;
+ physicalAddress.LowPart = EISA_MEMORY_PHYSICAL_BASE;
+ HalpEisaMemoryBase = MmMapIoSpace(physicalAddress,
+ PAGE_SIZE * 256,
+ FALSE);
+ //
+ // If either mapped address is NULL, then return FALSE as the function
+ // value. Otherwise, return TRUE.
+ //
+
+ if ((HalpEisaControlBase == NULL) ||
+ (HalpOnboardControlBase == NULL) ||
+ (HalpEisaMemoryBase == NULL)) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
diff --git a/private/ntos/nthals/halsnip/mips/jxport.c b/private/ntos/nthals/halsnip/mips/jxport.c
new file mode 100644
index 000000000..d56b8c559
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxport.c
@@ -0,0 +1,805 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxport.c,v 1.1 1995/07/20 15:58:02 flo Exp $")
+
+/*++
+
+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 R4000 system and the host
+ system.
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "jazzserp.h"
+
+// set the correct divisor for the SNI serial ports / quartz clock
+#if defined(SNI)
+ #undef BAUD_RATE_9600
+ #undef BAUD_RATE_19200
+ #define BAUD_RATE_9600 12
+ #define BAUD_RATE_19200 6
+#endif // SNI
+
+
+#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(USE_COM2)
+
+// Assume COM2 for the kernel debugger.
+
+#define SP_READ ((PSP_READ_REGISTERS) ((ULONG)HalpOnboardControlBase + SERIAL1_RELATIVE_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)((ULONG)HalpOnboardControlBase + SERIAL1_RELATIVE_BASE))
+
+
+#else
+
+// Assume COM1 for the kernel debugger.
+
+#define SP_READ ((PSP_READ_REGISTERS) ((ULONG)HalpOnboardControlBase + SERIAL0_RELATIVE_BASE))
+#define SP_WRITE ((PSP_WRITE_REGISTERS)((ULONG)HalpOnboardControlBase + SERIAL0_RELATIVE_BASE))
+
+#endif
+//
+// Define forward referenced prototypes.
+//
+
+SP_LINE_STATUS
+KdReadLsr (
+ IN BOOLEAN WaitReason
+ );
+
+//
+// Define baud rate divisor to be used on the debugger port.
+//
+
+SHORT HalpBaudRateDivisor = BAUD_RATE_19200;
+
+
+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;
+ 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;
+ }
+
+//
+// BUGBUG the FW configuration sets the serial 0 Port config relativ to
+// the EISA/ISA Base Address, so the serial driver doesn't get the right
+// information when debugging is enabled ....
+//
+
+#if defined(USE_COM2)
+ KdComPortInUse=(PUCHAR)(SERIAL1_PHYSICAL_BASE);
+#else
+ KdComPortInUse=(PUCHAR)(SERIAL0_PHYSICAL_BASE);
+#endif
+
+
+ //
+ // 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);
+
+ 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.
+
+--*/
+
+{
+
+ 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.
+
+--*/
+
+{
+ 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/halsnip/mips/jxreturn.c b/private/ntos/nthals/halsnip/mips/jxreturn.c
new file mode 100644
index 000000000..f5f7c4711
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxreturn.c
@@ -0,0 +1,286 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxreturn.c,v 1.6 1996/03/12 16:28:26 pierre Exp $")
+
+/*++
+
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxreturn.c
+
+Abstract:
+
+ This module implements the HAL return to firmware function.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "SNIregs.h"
+#include "mpagent.h"
+
+VOID
+HalpBootCpuRestart(
+ VOID
+ );
+VOID
+HalpClearVGADisplay(
+ VOID
+ );
+
+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.
+
+Arguments:
+
+ Routine - Supplies a value indicating which firmware routine to invoke.
+
+Return Value:
+
+ Does not return.
+
+--*/
+
+{
+ KIRQL OldIrql;
+ UCHAR DataByte;
+
+ //
+ // Disable Interrupts.
+ //
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Case on the type of return.
+ //
+
+ switch (Routine) {
+ case HalHaltRoutine:
+
+ //
+ // Hang looping.
+ //
+
+ // power off asked by DCU/IDC (power - fan or ... failure)
+ if (((ULONG)(((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine) != (ULONG)-1) &&
+ (((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipHalInfo == 1))
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine(
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipContext
+ );
+ for (;;) {}
+
+ case HalPowerDownRoutine:
+
+ // power off always done by DCU
+
+ if ((ULONG)(((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine) != (ULONG)-1)
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine(
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipContext
+ );
+ //
+ // PowerOff is done by the SNI machines by writing the Power_Off bit to the machine control register ...
+ //
+ if (HalpIsTowerPci){
+ WRITE_REGISTER_ULONG((PULONG) PCI_TOWER_DCU_CONTROL, DC_POWEROFF);
+ }else{
+ WRITE_REGISTER_UCHAR((PUCHAR) PCI_MCR_ADDR, PCI_MCR_POWEROFF);
+ }
+
+ for (;;) {} // hang looping
+
+
+ case HalRestartRoutine:
+ case HalRebootRoutine:
+ case HalInteractiveModeRoutine:
+
+ // power off asked by DCU/IDC (power - fan or ... failure)
+ if (((ULONG)(((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine) != (ULONG)-1) &&
+ (((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipHalInfo == 1))
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine(
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipContext
+ );
+
+ if (HalpIsMulti) {
+ ULONG Mask,i;
+
+ for (i=0;i<HalpIsMulti;i++)
+ if (((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[PCR->Number])
+ Mask |= 1<<i;
+
+
+ Mask = Mask & ~(PCR->SetMember);
+#if DBGG
+ DbgPrint("Send message RESTART to maskcpu = %x \n",Mask);
+#endif
+
+ HalpRequestIpi(Mask,MPA_RESTART_MESSAGE);
+ //
+ // if this is not the Boot CPU, we call a special Firmware entry to stop it
+ //
+
+ //
+ // remove this processor from the list of active processors
+ //
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[PCR->Number]=0;
+
+ if (PCR->Number ) {
+
+#if DBGG
+ DbgPrint(" Reinit slave %x \n", ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->reinit_slave);
+#endif
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->reinit_slave();
+
+ } else HalpBootCpuRestart();
+ }
+
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalDisplayString("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
+ HalDisplayString(" ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
+ HalDisplayString(" º º\n");
+ HalDisplayString(" º Restart in Progress º\n");
+ HalDisplayString(" º º\n");
+ HalDisplayString(" ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\n");
+
+ DataByte = READ_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ KeStallExecutionProcessor(10000);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ ArcReboot();
+
+ for (;;) ;
+
+ default:
+ DbgPrint("HalReturnToFirmware invalid argument\n");
+ KeLowerIrql(OldIrql);
+ DbgBreakPoint();
+ }
+}
+
+VOID
+HalpBootCpuRestart(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function returns control to the firmware Arcreboot routine.
+ it waits until all other cpu's have beet shut down.
+ this code is executed only on the boot cpu
+
+Arguments:
+
+ None
+
+Return Value:
+
+ Does not return.
+
+--*/
+{
+ UCHAR DataByte;
+ ULONG cpt;
+
+
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalDisplayString("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
+ HalDisplayString(" ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
+ HalDisplayString(" º º\n");
+ HalDisplayString(" º Restart in Progress º\n");
+ HalDisplayString(" º º\n");
+ HalDisplayString(" ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\n");
+
+ cpt = 0;
+ while(*(PULONG)(& (((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[0]) )) {
+ KeStallExecutionProcessor(500000);
+ ++cpt;if (cpt == 20) break;
+ }
+ //
+ // if there are still ssome processors active, we do a reset of the entire machine
+ //
+ if (*(PULONG)(& (((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[0]) )) {
+
+#if DBG
+ DbgPrint(" Some processors did not answer . Reset machine started. \n");
+#endif
+ if (HalpIsTowerPci) {
+ WRITE_REGISTER_ULONG((PULONG) PCI_TOWER_DCU_CONTROL, DC_SWRESET);
+ }else {
+
+ WRITE_REGISTER_UCHAR((PUCHAR) PCI_MCR_ADDR, PCI_MCR_SOFTRESET);
+ }
+ } else {
+
+#if DBG
+ DbgPrint("Reboot started \n");
+#endif
+
+ }
+
+ DataByte = READ_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 1;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+ KeStallExecutionProcessor(10000);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->BusReset = 0;
+
+ WRITE_REGISTER_UCHAR(
+ &((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,
+ DataByte
+ );
+
+
+ ArcReboot();
+
+ for (;;) ;
+}
+
+
+
+
+
diff --git a/private/ntos/nthals/halsnip/mips/jxsysint.c b/private/ntos/nthals/halsnip/mips/jxsysint.c
new file mode 100644
index 000000000..1e32051c2
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxsysint.c
@@ -0,0 +1,335 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxsysint.c,v 1.3 1996/03/04 13:19:54 pierre Exp $")
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ jxsysint.c
+
+Abstract:
+
+ This module implements the HAL enable/disable system interrupt, and
+ request interprocessor interrupt routines for a MIPS R3000 or R4000
+ SNI system.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalDisableSystemInterrupt (
+ IN ULONG Vector,
+ IN KIRQL Irql
+ )
+
+/*++
+
+Routine Description:
+
+ This routine disables the specified system interrupt.
+
+Arguments:
+
+ Vector - Supplies the vector of the system interrupt that is disabled.
+
+ Irql - Supplies the IRQL of the interrupting source.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+
+
+ //
+ // Raise IRQL to the highest level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+
+ //
+ // If the vector number is within the range of the onboard interrupts, then
+ // disable the onboard interrrupt.
+ // This may be an Isa (Desktop) or Isa/Eisa (Minitower) Interrupt
+ //
+
+ if (Vector >= ONBOARD_VECTORS &&
+ Vector <= MAXIMUM_ONBOARD_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpDisableOnboardInterrupt(Vector);
+ }
+
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // disable the EISA interrrupt on the Eisa Backplane (Eisa Extension).
+ //
+
+ else if (Vector >= EISA_VECTORS &&
+ Vector <= MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+
+ HalpDisableEisaInterrupt(Vector);
+ }
+
+ //
+ // 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.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpSystemInterruptLock);
+
+ //
+ // If the vector number is within the range of the onboard interrupts, then
+ // enable the onboard interrrupt and set the Level/Edge register to latched,
+ // because the onboard Opti 499 (Desktop)is a real Isa Controler and cannot share interrupts.
+ // even the i82350 Chipset on the Minitower cannot share interrupts (why ?)
+ //
+
+ if (Vector >= ONBOARD_VECTORS &&
+ Vector <= MAXIMUM_ONBOARD_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+
+ HalpEnableOnboardInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // If the vector number is within the range of the EISA interrupts, then
+ // enable the EISA interrrupt in the Eisa Backplane (Eisa Extension) and set the Level/Edge register.
+ //
+
+ else if (Vector >= EISA_VECTORS &&
+ Vector <= MAXIMUM_EISA_VECTOR &&
+ Irql == EISA_DEVICE_LEVEL) {
+ HalpEnableEisaInterrupt( Vector, InterruptMode);
+ }
+
+ //
+ // Lower IRQL to the previous level.
+ //
+
+ KiReleaseSpinLock(&HalpSystemInterruptLock);
+ KeLowerIrql(OldIrql);
+
+
+ return TRUE;
+}
+
+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.
+
+--*/
+
+{
+
+
+ *Affinity = 1;
+
+ //
+ // If this is for the internal bus then just return the passed parameter.
+ //
+
+ if (InterfaceType == Internal) {
+
+ if (BusInterruptVector >= ONBOARD_VECTORS &&
+ BusInterruptVector <= MAXIMUM_ONBOARD_VECTOR ) {
+
+ //
+ // this is one of the onboard components of the PC core
+ // (floppy, serial, parallel, mouse etc.)
+ // they should be configured in the Firmware tree with an Offset of
+ // ONBOARD_VECTORS (e.g. 0x10 to make them different to the real onboard components
+ // like scsi or ethernet) and with an Irql of EISA_DEVICE_LEVEL (actually 4)
+ // we need Firmware release 1.04 or later ...
+ //
+
+ //
+ // Bus interrupt vector 2 of Onboard PC core interrupts is actually mapped to
+ // vector 9 in the Isa/Eisa hardware.
+ //
+
+ if (BusInterruptVector == ONBOARD_VECTORS + 2) {
+ BusInterruptVector = ONBOARD_VECTORS + 9;
+ }
+
+ //
+ // The IRQL level is always equal to the EISA level.
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ return(BusInterruptVector);
+ }
+
+ //
+ // this is another special case of the DCU Interrupt for PCI Tower
+ // we have an agreement with the DCU developer
+ // we meet each other on InterruptVector 15, so we limit the Irql to Device Level
+ //
+
+ if ( BusInterruptVector == DCU_VECTOR ) {
+
+ if (HalpIsTowerPci) {
+ *Irql = (KIRQL) INT6_LEVEL;
+ // if more than one proc , DCU Interrupt is connected to proc 1
+ if (HalpIsMulti !=0) *Affinity = 2;
+ return(BusInterruptVector);
+ } else {
+ *Irql = EISA_DEVICE_LEVEL;
+ return(BusInterruptVector);
+ }
+
+ }
+
+
+ //
+ // these are the "real" Onboard components (scsi and Ethernet)
+ // Return the passed parameters.
+ //
+
+ *Irql = (KIRQL) BusInterruptLevel;
+
+ return(BusInterruptVector);
+ }
+
+ if (InterfaceType == PCIBus) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *Irql = (KIRQL) SCSIEISA_LEVEL;
+
+
+ return(BusInterruptVector);
+ }
+
+ if (InterfaceType != Isa && InterfaceType != Eisa) {
+
+ //
+ // Not on this system return nothing.
+ //
+
+ *Affinity = 0;
+ *Irql = 0;
+ return(0);
+ }
+
+ //
+ // Isa/Eisa Interrupts which are not configured in the Firmware
+ // (boards should be located in the Expansion Slots ...)
+ // The IRQL level is always equal to the EISA level.
+ // WARNING: some driver call HalGetInterruptVector
+ // with the BusInterruptLevel == BusInterruptVector
+ // but some call it with different values.
+ // In this part of the source tree we match the Jazz reference
+ // sources (see Internal handling; which is different)
+ //
+
+ *Irql = EISA_DEVICE_LEVEL;
+
+ //
+ // Bus interrupt 2 is actually mapped to bus interrupt 9 in the Isa/Eisa
+ // hardware.
+ //
+
+ if (BusInterruptLevel == 2) {
+ BusInterruptLevel = 9;
+ }
+
+ //
+ // all Isa/Eisa Interrupts should be handled by the onboard PC core
+ //
+
+ return(BusInterruptLevel + ONBOARD_VECTORS);
+
+}
diff --git a/private/ntos/nthals/halsnip/mips/jxtime.c b/private/ntos/nthals/halsnip/mips/jxtime.c
new file mode 100644
index 000000000..a13ed8ec1
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxtime.c
@@ -0,0 +1,359 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxtime.c,v 1.2 1995/11/02 11:04:33 flo Exp $")
+
+/*++
+
+Copyright (c) 1993 SNI
+
+Module Name:
+
+ SNItime.c
+
+Abstract:
+
+ This module implements the HAL set/query realtime clock routines for
+ a MIPS R4000 SNI system.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+
+
+#define NVINDEX_STATE 0x6
+#define NVSTATE_TODVALID 0x1
+
+
+
+#define bcd_to_dec(x) ( ((((x) >> 4 ) & 0xf ) * 10 ) + ((x) & 0xf) )
+#define dec_to_bcd(x) ( (((x) / 10) << 4) | ((x) % 10) )
+
+
+#define RTC_NVRAM_SIZE 0x7ff // NVRAM size on this chip
+
+// definitions for rtc 146818
+
+#define RTC_SECS 0
+#define RTC_SECA 1
+#define RTC_MINS 2
+#define RTC_MINA 3
+#define RTC_HOURS 4
+#define RTC_HOURA 5
+#define RTC_DAYW 6
+#define RTC_DAYM 7
+#define RTC_MONTH 8
+#define RTC_YEAR 9
+#define RTC_REGA 10
+#define RTC_REGB 11
+#define RTC_REGC 12
+#define RTC_REGD 13
+#define RTC_MEM1 14
+#define RTC_MEM2 128
+
+/*
+ * Register B bit definitions
+ */
+#define RTCB_SET 0x80 /* inhibit date update */
+#define RTCB_PIE 0x40 /* enable periodic interrupt */
+#define RTCB_AIE 0x20 /* enable alarm interrupt */
+#define RTCB_UIE 0x10 /* enable update-ended interrupt */
+#define RTCB_SQWE 0x08 /* square wave enable */
+#define RTCB_DMBINARY 0x04 /* binary data (0 => bcd data) */
+#define RTCB_24HR 0x02 /* 24 hour mode (0 => 12 hour) */
+#define RTCB_DSE 0x01 /* daylight savings mode enable */
+
+/* Time of Day Clock */
+
+struct todc {
+ short htenths;
+ short hsecs;
+ short hmins;
+ short hhours;
+ short hdays;
+ short hweekday;
+ short hmonth;
+ short hyear;
+};
+
+/* masks to get valid information */
+
+#define MASK_CENT_SECS 0xFF
+#define MASK_SECS 0x7F
+#define MASK_MINS 0x7F
+#define MASK_HOURS 0x3F
+#define MASK_DAY_W 0x07
+#define MASK_DAY_M 0x3F
+#define MASK_MONTH 0x1F
+#define MASK_YEAR 0xFF
+
+//
+// the reference year (we have only two digits for the year on the chip)
+//
+
+#define YRREF 1900
+
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ );
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ );
+
+VOID
+HalpWrite146818(struct todc *todp, PUCHAR index, PUCHAR data);
+
+VOID
+HalpRead146818(struct todc *todp, PUCHAR index, PUCHAR data);
+
+VOID
+HalpPciReadTodc(struct todc *todp);
+
+VOID
+HalpPciWriteTodc(struct todc *todp);
+
+UCHAR
+HalpReadRegister146818(PUCHAR index, PUCHAR data, int reg);
+
+VOID HalpWriteRegister146818(PUCHAR index, PUCHAR data, int reg, UCHAR val);
+
+
+
+/* Calendar clock : For PCI Minitower and Desktop systems, the RTC is part of
+ * --------------- the SUPER_IO pc87323.
+ * It is software compatible with rtc146818.
+ */
+
+BOOLEAN
+HalQueryRealTimeClock (
+ OUT PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine queries the realtime clock.
+
+ N.B. this comment stand in jxtime.c:
+ 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.
+
+--*/
+
+{
+
+ register CSHORT month, dayweek, daymonth, year, hours, mins, secs, msecs;
+ struct todc ltodc;
+ KIRQL oldIrql;
+
+
+ KeRaiseIrql(HIGH_LEVEL, &oldIrql);
+
+ HalpPciReadTodc(&ltodc);
+
+ KeLowerIrql(oldIrql);
+
+ msecs = 0;
+ secs = ltodc.hsecs;
+ mins = ltodc.hmins;
+ hours = ltodc.hhours;
+ daymonth = ltodc.hdays;
+ dayweek = ltodc.hweekday;
+ month = ltodc.hmonth;
+ year = ltodc.hyear;
+
+
+ if (TimeFields)
+ {
+ TimeFields->Year = year+YRREF;
+ TimeFields->Month = month;
+ TimeFields->Day = daymonth;
+ TimeFields->Weekday = dayweek;
+ TimeFields->Hour = hours;
+ TimeFields->Minute = mins;
+ TimeFields->Second = secs;
+ TimeFields->Milliseconds = msecs;
+ }
+
+ return TRUE;
+
+}
+
+BOOLEAN
+HalSetRealTimeClock (
+ IN PTIME_FIELDS TimeFields
+ )
+
+/*++
+
+Routine Description:
+
+ This routine sets the realtime clock.
+
+ N.B. this comment stand in jxtime.c:
+ This routine is required to provide anq 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.
+
+--*/
+
+{
+
+ struct todc ltodc;
+
+ KIRQL oldIrql;
+ UCHAR year, month, daymonth, dayweek, hours, mins, secs, msecs;
+
+ //
+ // 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.
+ //
+
+ // this part has to be written
+ // if (...) return FALSE;
+ year = (UCHAR) ( (TimeFields->Year - YRREF) % 100 );
+ month = (UCHAR) TimeFields->Month;
+ daymonth = (UCHAR) TimeFields->Day;
+ dayweek = (UCHAR) TimeFields->Weekday;
+ hours = (UCHAR) TimeFields->Hour;
+ mins = (UCHAR) TimeFields->Minute;
+ secs = (UCHAR) TimeFields->Second;
+ msecs = (UCHAR) TimeFields->Milliseconds;
+
+
+ ltodc.htenths = 0;
+ ltodc.hsecs = secs;
+ ltodc.hmins = mins;
+ ltodc.hhours = hours;
+ ltodc.hdays = daymonth;
+ ltodc.hweekday = dayweek;
+ ltodc.hmonth = month;
+ ltodc.hyear = year;
+
+ KeRaiseIrql(HIGH_LEVEL, &oldIrql);
+
+ HalpPciWriteTodc(&ltodc);
+
+ KeLowerIrql(oldIrql);
+
+
+
+ return TRUE;
+
+}
+/* HAL_RTODC() */
+VOID
+HalpPciReadTodc(struct todc *todp)
+{
+ PUCHAR rtc_index = (PUCHAR) RTC_ADDR_PCIMT;
+ PUCHAR rtc_data = (PUCHAR) RTC_DATA_PCIMT;
+ HalpRead146818(todp,rtc_index,rtc_data);
+}
+
+/* HAL_WTODC() */
+VOID
+HalpPciWriteTodc(struct todc *todp)
+{
+
+ PUCHAR rtc_index = (PUCHAR) RTC_ADDR_PCIMT;
+ PUCHAR rtc_data = (PUCHAR)RTC_DATA_PCIMT;
+ HalpWrite146818(todp, rtc_index, rtc_data);
+}
+
+
+VOID
+HalpWrite146818(struct todc *todp, PUCHAR index, PUCHAR data)
+{
+ UCHAR temp;
+ /*
+ * Write information to rtc146818 chip
+ */
+ HalpWriteRegister146818(index,data,RTC_REGB,temp=(HalpReadRegister146818(index,data,RTC_REGB)|RTCB_SET));
+ HalpWriteRegister146818(index,data,RTC_SECS,dec_to_bcd(todp->hsecs)&MASK_SECS);
+ HalpWriteRegister146818(index,data,RTC_MINS,dec_to_bcd(todp->hmins)&MASK_MINS);
+ HalpWriteRegister146818(index,data,RTC_HOURS,dec_to_bcd(todp->hhours)&MASK_HOURS);
+ HalpWriteRegister146818(index,data,RTC_DAYM,dec_to_bcd(todp->hdays)&MASK_DAY_M);
+ HalpWriteRegister146818(index,data,RTC_DAYW,dec_to_bcd(todp->hweekday)&MASK_DAY_W);
+ HalpWriteRegister146818(index,data,RTC_MONTH,dec_to_bcd(todp->hmonth)&MASK_MONTH);
+
+ HalpWriteRegister146818(index,data,RTC_YEAR,dec_to_bcd(todp->hyear)&MASK_YEAR);
+
+
+
+ HalpWriteRegister146818(index,data,RTC_REGB, temp &= ~RTCB_SET);
+}
+
+VOID
+HalpRead146818(struct todc *todp, PUCHAR index, PUCHAR data)
+{
+ UCHAR temp;
+
+ HalpWriteRegister146818(index,data,RTC_REGB,temp=(HalpReadRegister146818(index,data,RTC_REGB)|RTCB_SET));
+
+ todp->htenths = 0;
+ todp->hsecs=bcd_to_dec(HalpReadRegister146818(index,data,RTC_SECS)&MASK_SECS);
+ todp->hmins=bcd_to_dec(HalpReadRegister146818(index,data,RTC_MINS)&MASK_MINS);
+ todp->hhours=bcd_to_dec(HalpReadRegister146818(index,data,RTC_HOURS)&MASK_HOURS);
+ todp->hdays=bcd_to_dec(HalpReadRegister146818(index,data,RTC_DAYM)&MASK_DAY_M);
+ todp->hweekday=bcd_to_dec(HalpReadRegister146818(index,data,RTC_DAYW)&MASK_DAY_W);
+ todp->hmonth=bcd_to_dec(HalpReadRegister146818(index,data,RTC_MONTH)&MASK_MONTH);
+ todp->hyear=bcd_to_dec(HalpReadRegister146818(index,data,RTC_YEAR)&MASK_YEAR);
+
+ HalpWriteRegister146818(index,data,RTC_REGB, temp &= ~RTCB_SET);
+}
+
+
+
+UCHAR
+HalpReadRegister146818(PUCHAR index, PUCHAR data, int reg)
+{
+ WRITE_REGISTER_UCHAR(index,reg);
+ // *index = reg;
+ // wbflush();
+ // return(*data)
+ return(READ_REGISTER_UCHAR(data));
+}
+
+VOID HalpWriteRegister146818(PUCHAR index, PUCHAR data, int reg, UCHAR val)
+{
+ WRITE_REGISTER_UCHAR(index,reg);
+// *index = reg;
+// wbflush();
+ WRITE_REGISTER_UCHAR(data, val);
+// *data = val;
+// wbflush();
+}
+
diff --git a/private/ntos/nthals/halsnip/mips/jxusage.c b/private/ntos/nthals/halsnip/mips/jxusage.c
new file mode 100644
index 000000000..b39cab418
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/jxusage.c
@@ -0,0 +1,47 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/jxusage.c,v 1.1 1995/07/20 15:58:57 flo Exp $")
+
+/*++
+
+Copyright (c) 1990-1994 Microsoft Corporation
+
+Module Name:
+
+ jxusage.c
+
+Abstract:
+
+ The module reports the io resources in use by the JAZZ hal.
+
+
+--*/
+
+#include "halp.h"
+
+
+VOID
+HalReportResourceUsage(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+--*/
+{
+ //
+ // BUGBUG: hal resouce usage reporting needs to be added here
+ //
+
+ // IoReportHalResourceUsage (
+ // HalName,
+ // RawResourceList,
+ // TranslatedResourceList,
+ // ListSize
+ // );
+
+ return;
+}
diff --git a/private/ntos/nthals/halsnip/mips/mpagent.c b/private/ntos/nthals/halsnip/mips/mpagent.c
new file mode 100644
index 000000000..7420911ff
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/mpagent.c
@@ -0,0 +1,745 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/mpagent.c,v 1.7 1996/02/23 17:55:12 pierre Exp $")
+
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ mpagent.c
+
+Abstract:
+
+ This module implements the routines dealing with the SNI MP Agent on
+ SNI system.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "MPagent.h"
+
+extern VOID
+KeUpdateRunTime(
+ IN struct _KTRAP_FRAME *TrapFrame
+ );
+
+
+VOID
+HalpInitMPAgent(
+ IN ULONG Number
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the MutiProcessor_Agent chipset:
+ - reset an eventual MP_Agent fatal error,
+ - enable message passing (send/receive),
+ - fix routage for internal IT -> external IT,
+ - enable the internal interrupts,
+ - fix the mask for wanted external interrupts,
+ - disable Low Process Priority mode for
+ external interrupts,
+ - enable cache replace operator and update the
+ 'cache_rpl_buffer' global variable with a KSEG0
+ 4 Mb reserved address.
+
+Arguments:
+
+ Number : Logical number of the processor to be initialised
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ ULONG reg;
+
+
+
+ //
+ // set up the snooper register
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->snooper)); /* read the current value */
+ reg |= (MPA_ENRCVMESS | /* enable message receiving */
+ MPA_RSTSNPERR | /* reset an eventual old MP_Agent fatal error */
+ MPA_ENLINK | /* enable read and link command */
+ MPA_ENCOHREQ | /* enable coherency on the MP bus for this agent */
+ 0); /* keep other fields */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), reg);
+
+ // RM300 with mono-processors boards with mp-agent can be configured with 1Mb cache,
+ // but the MP-agent tag RAM can be configured with 4Mb or 2MB. So we disable the MPbus error.
+ // (With monoprocessor machine the MP-agent tag ram is not useful at all ...)
+
+ if ((HalpIsMulti) || (HalpIsTowerPci))
+ reg &= ~(MPA_RSTSNPERR); /* enable new interrupt for MP_Agent fatal error */
+
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), reg);
+
+
+ //
+ // cpu1reg register
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->cpuda1reg)); /* read the current value */
+ reg &= ~(MPA_ENDIRECT | /* disable LPP mechanism */
+ MPA_ENTESTIT | /* disable interrupt test mode (interrupts from MPBus) */
+ MPA_SELITI_MASK | /* reset old internal interrupt routage */
+ 0); /* keep other fields */
+
+ reg |= MPA_SELITI_SR_IP7; /* send internal interrupts on external interrupt SR_IP7*/
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpuda1reg), reg);
+
+ //
+ // cpureg register
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+ reg &= ~(MPA_ENINT_MASK | /* reset old values for interrupts */
+ MPA_INTCONF_MASK| /* force falling edge for all interrupts */
+ MPA_ENSHARED | /* don't put optimal mode for KERNEL */
+ 0);
+ reg |= (MPA_ENSENDMSG | /* enable sending message */
+ MPA_ENINT_MPBERR | /* enable internal interrupt for MP_Agent fatal error */
+ MPA_ENINT_ITMSG1 | /* enable internal interrupt for message1 register */
+ MPA_ENINT_ITMSG2 | /* enable internal interrupt for message2 register */
+ MPA_ENINT_ITMSG3 | /* enable internal interrupt for message3 register */
+ MPA_INTMSK | /* mask sent during external request stage */
+ 0); /* keep other fields */
+
+ //
+ // external Interrupts routing in the MP Agent
+ //
+
+ // pci tower -> force raising edges for all interrupts
+
+ if (HalpIsTowerPci) reg |= MPA_INTCONF_MASK;
+
+ // pci multi-processor machines => interrupts are centralized.
+
+ if (Number == 0) reg |= MPA_ENINT_SR_IP3; // device interrupts are only processed by bootcpu.
+ // Timer processor 1 : IP5 for RM300 - IP6 for RM400
+
+ if (Number == 1)
+ if (!HalpIsTowerPci) reg |= MPA_ENINT_SR_IP5;
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), reg);
+
+ //
+ // clear pending interrupts by reading of the message registers
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->datamsg1));
+ reg = READ_REGISTER_ULONG(&(mpagent->datamsg2));
+ reg = READ_REGISTER_ULONG(&(mpagent->datamsg3));
+
+ // Modif PS 20 June -> Don't use the operator with ASIC PCI -> BUGBUG
+
+ if (HalpMpaCacheReplace == MPAGENT_RESERVED | KSEG0_BASE) {
+ reg = ((MPAGENT_RESERVED & // put the reserved physical address (4Mb long)
+ MPA_OP_ADDR_MASK) |
+ MPA_OP_ENABLE); // enable the operator
+ } else {
+ reg = 0;
+ }
+
+ WRITE_REGISTER_ULONG(&(mpagent->mem_operator), reg); // for all procs (done for proc 0 in xxcache)
+
+}
+
+
+VOID
+HalpInitMAUIMPAgent(
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the MutiProcessor_Agent chipset:
+ - enable MAUI interrupt on the current processor
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+
+ ULONG reg;
+
+ //
+ // cpureg register
+ //
+
+ reg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+
+ reg |= MPA_ENINT_SR_IP6;
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), reg);
+}
+
+
+VOID
+HalRequestIpi(
+ IN ULONG CpuMask
+ )
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ That is done by using the message passing facility of the MPagent.
+
+ 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.
+
+--*/
+{
+ULONG physmask, cpt;
+PRESTART_BLOCK NextRestartBlock;
+
+ // CpuMask is a logical mask. We must use a mask with the physical
+ // numbers of cpus to communicate with the MP_Agent.
+
+ physmask = 0;cpt = 0;
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ while (NextRestartBlock != NULL) {
+
+ if (CpuMask & ( 1 << cpt)) {
+ physmask = (1 << (NextRestartBlock->ProcessorId));
+ HalpSendIpi(physmask,MPA_KERNEL_MESSAGE);
+ }
+ ++cpt ; NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ }
+
+}
+
+ VOID
+HalpRequestIpi(
+ IN ULONG CpuMask,
+ IN ULONG msg_data
+ )
+/*++
+
+Routine Description:
+
+ This routine requests an interprocessor interrupt on a set of processors.
+ That is done by using the message passing facility of the MPagent.
+
+ 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.
+
+--*/
+{
+ULONG physmask, cpt;
+PRESTART_BLOCK NextRestartBlock;
+
+ // CpuMask is a logical mask. We must use a mask with the physical
+ // numbers of cpus to communicate with the MP_Agent.
+
+ physmask = 0;cpt = 0;
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ while (NextRestartBlock != NULL) {
+
+ if (CpuMask & ( 1 << cpt)) {
+ physmask = (1 << (NextRestartBlock->ProcessorId));
+ HalpSendIpi(physmask,msg_data);
+ }
+ ++cpt ; NextRestartBlock = NextRestartBlock->NextRestartBlock;
+ }
+
+}
+
+
+VOID
+HalpSendIpi(
+ IN ULONG pcpumask,
+ IN ULONG msg_data
+ )
+/*++
+
+Routine Description:
+
+ This routine sends an interprocessor interrupt on a set of processors.
+ That is done by using the message passing facility of the MPagent.
+
+ N.B. This routine must ensure that the interrupt is posted at the target
+ processor(s) before returning.
+
+Arguments:
+
+ pcpumask - Supplies the set of processors that are sent an interprocessor
+ interrupt. It contains physical numbers.
+
+ msg_data _ Supplies the kind of message to be send : kernel demand or HAL internal demand.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+KIRQL OldIrql;
+LONG msg_retries, watchdog;
+ULONG msg_address, msg_status, itpend;
+
+
+ if (!pcpumask || !HalpIsMulti) {
+
+ return;
+
+ }
+
+ //
+ // Raise IRQL to ??? level.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+
+ //
+ // form the Message Address register (Message register 1 / 2, CPUMask)
+ // The SNI MP Agent supports up to 4 CPU's
+ //
+
+ if (msg_data ==MPA_TIMER_MESSAGE )
+ msg_address = (pcpumask & MPA_CPUTARGET_MASK) | MPA_REGTARGET_MSG2;
+ else
+ msg_address = (pcpumask & MPA_CPUTARGET_MASK) | MPA_REGTARGET_MSG1;
+
+ msg_data = ((msg_data << 24) | (pcpumask & MPA_CPUTARGET_MASK));
+
+ msg_retries = MPA_MSG_RETRY;
+
+ /*
+ * Go on, just do it.
+ * If at first you don't succeed, then try, try and try again...
+ */
+
+ do {
+
+ watchdog = 10;
+
+ WRITE_REGISTER_ULONG(&(mpagent->msgaddress), msg_address);
+ WRITE_REGISTER_ULONG(&(mpagent->msgdata), msg_data);
+
+ /*
+ * so, what happened? poll either until we know or the watchdog counter runs out
+ */
+ do {
+
+ KeStallExecutionProcessor(5);
+
+ //
+ // read the message status register
+ //
+ msg_status = READ_REGISTER_ULONG(&(mpagent->msgstatus));
+
+ } while (((msg_status & MPA_VALSTAT) == 0) && watchdog--);
+
+
+// KeLowerIrql(OldIrql);
+
+
+ if ((msg_status & MPA_VALSTAT) != MPA_VALSTAT) {
+
+
+ KeStallExecutionProcessor(100);
+// KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ continue;
+
+ } else {
+
+ //
+ // okay, we have a Valid status bit
+ // so test of busy
+
+ if ((msg_status & MPA_ERRMSG) == 0) {
+
+ //
+ // all is fine
+ //
+ KeLowerIrql(OldIrql);
+ return;
+
+ } else {
+
+ // we have to verify that it is not a MPA_RETRY error.
+
+ itpend = READ_REGISTER_ULONG(&(mpagent->itpend)); /* first read the interrupt pending MP_Agent register */
+
+ if (itpend & MPA_INTN_MPBERR) {
+
+ ULONG snooper, cpureg, tmp ;
+
+ cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+ cpureg &= ~(MPA_ENINT_MPBERR /* disable interrupt for MP_Agent fatal error */
+ ); /* keep other fields */
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // write the new value in the MP_Agent register /
+ snooper = READ_REGISTER_ULONG(&(mpagent->snooper)); // read the current snooper register value/
+
+ tmp = READ_REGISTER_ULONG(&(mpagent->snpadreg)); /* read the current value */
+ snooper |= MPA_RSTSNPERR; /* reset this MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
+
+ if ((snooper & MPA_MSEQERR == MPA_RETRYERR) || (snooper & MPA_MSEQERR ==0)) {
+ snooper &= ~(MPA_RSTSNPERR); /* stop reseting this MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
+ cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+ cpureg |= (MPA_ENINT_MPBERR); /* enable interrupt for MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // write the new value in the MP_Agent register /
+
+ }
+ }
+
+// msg_retries = MPA_MSG_RETRY;
+ KeStallExecutionProcessor(100);
+// KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ if (itpend & MPA_INTN_MPBERR) {
+ continue;
+ } else {
+ KeLowerIrql(OldIrql);
+ return;
+ }
+ }
+
+ }
+
+
+// KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KeStallExecutionProcessor(10);
+
+ } while (--msg_retries); /* message aborted, try again */
+
+ KeLowerIrql(OldIrql);
+ return;
+
+}
+
+
+VOID
+HalpProcessIpi(
+ IN struct _KTRAP_FRAME *TrapFrame
+ )
+/*++
+
+ Routine Description:
+
+ This routine is entered as the result of an IP5 interrupt. This function
+ will looks at the MPagent to see if an IPI has just occurred.
+
+ Arguments:
+
+ None.
+
+ Return Value:
+
+
+--*/
+{
+ ULONG itpend, msg_data;
+
+ itpend = READ_REGISTER_ULONG(&(mpagent->itpend)); /* first read the interrupt pending MP_Agent register */
+
+ if (itpend & (MPA_INTN_ITMSG1 | MPA_INTN_ITMSG2)) {
+
+ //
+ // reading the message register clears the interrupt from the MP Agent
+ //
+
+ if (itpend & MPA_INTN_ITMSG1) {
+ msg_data = (READ_REGISTER_ULONG(&(mpagent->datamsg1)) >> 24);
+ if (msg_data == MPA_KERNEL_MESSAGE) {
+ KeIpiInterrupt(TrapFrame);
+ } else {
+ // remove this processor from the list of active processors
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[PCR->Number]=0;
+ if (PCR->Number) {
+
+ // call a firmware funtion to stop slave cpu's which will break the caches
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->reinit_slave();
+
+ } else {
+
+ HalpBootCpuRestart();
+ }
+ }
+ }
+
+ if (itpend & MPA_INTN_ITMSG2) {
+ msg_data = (READ_REGISTER_ULONG(&(mpagent->datamsg2)) >> 24);
+ KeUpdateRunTime(TrapFrame);
+ }
+
+ HalpCheckSpuriousInt(0);
+
+ return ;
+ }
+
+ if ((itpend & MPA_INTN_INT_MASK) == 0) {
+
+ ULONG snooper = READ_REGISTER_ULONG(&(mpagent->snooper));
+
+ //
+ // None of the MP Agent internal Interrupts was pending --> just return
+ //
+
+ HalpCheckSpuriousInt(0);
+
+
+ return ;
+ }
+
+ if (itpend & MPA_INTN_MPBERR) {
+
+ //
+ // Fatal Error
+ //
+
+ ULONG snooper, cpureg, tmp ;
+
+ cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+ cpureg &= ~(MPA_ENINT_MPBERR /* disable interrupt for MP_Agent fatal error */
+ ); /* keep other fields */
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // write the new value in the MP_Agent register /
+ snooper = READ_REGISTER_ULONG(&(mpagent->snooper)); // read the current snooper register value/
+
+ tmp = READ_REGISTER_ULONG(&(mpagent->snpadreg)); /* read the current value */
+ snooper |= MPA_RSTSNPERR; /* reset this MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
+
+ if ((snooper & MPA_MSEQERR == MPA_RETRYERR) || (snooper & MPA_MSEQERR ==0)) {
+ snooper &= ~(MPA_RSTSNPERR); /* stop reseting this MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
+ cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
+ cpureg |= (MPA_ENINT_MPBERR); /* enable interrupt for MP_Agent fatal error */
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // write the new value in the MP_Agent register /
+
+ } else {
+#if DBG
+ DebugPrint(("MP_Agent fatal error : adresse=0x%x snooper=0x%x\n",tmp,snooper));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 0;
+ HalDisplayString(HalpBugCheckMessage[0]); // "MP_Agent fatal error\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,snooper,tmp,0);
+#endif
+
+ }
+
+ HalpCheckSpuriousInt(0);
+
+ return ;
+ }
+
+ if (itpend & MPA_INTN_ITMSG3) {
+
+
+ //
+ // reading the message register clears the interrupt from the MP Agent
+ //
+
+ msg_data = (READ_REGISTER_ULONG(&(mpagent->datamsg3)) >> 24);
+ HalpCheckSpuriousInt(0);
+
+ return ;
+ }
+}
+
+ULONG
+HalpGetMyAgent(
+ VOID
+ )
+{
+ ULONG reg;
+ reg = READ_REGISTER_ULONG(&(mpagent->snooper)); /* read the current value */
+ return( (reg & MPA_ADAGT_MASK) >> MPA_ADAGT_SHIFT);
+}
+
+
+
+/*
+ * ======================================================================
+ *
+ * NAME: mpa_check_spurious_intr
+ *
+ * PURPOSE: Fix a bug in the MP_Agent which sometimes make a bad
+ * update of the cause register.
+ *
+ * PARAMETERS: none
+ *
+ * RETURNS: = 0 no possible spurious interrupt
+ * 1 possible spurious interrupt
+ *
+ * ======================================================================
+ */
+BOOLEAN HalpCheckSpuriousInt(ULONG mask)
+{
+
+ULONG itpend, causeit, pending;
+ULONG cpureg, tempreg, reg;
+
+ if ( HalpProcessorId != MPAGENT) {
+ return 0;
+ }
+
+
+
+ itpend = READ_REGISTER_ULONG(&(mpagent->itpend)); /* read the interrupt pending MP_Agent register */
+
+ causeit = (itpend & MPA_OINTN_MASKGEN) >> MPA_OINTN_SHIFT;
+ pending = (itpend & MPA_INTN_MASKGEN );
+
+ if (causeit != pending) {
+
+ /*
+ * Need a second filter for pending interrupt which don't take care
+ * of real enabled interrupt mask of cpureg.
+ */
+ cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read interrupt enable mask for this cpu */
+
+ if (PCR->Prcb->Number == 0) {
+ if (HalpIsTowerPci && HalpIsMulti == 0)
+ pending &= (
+ ((cpureg & (MPA_ENINT_SR_IP3 | MPA_ENINT_SR_IP6 |
+ MPA_ENINT_SR_IP7 )) >> MPA_ENINT_MASKSHIFT)
+ |
+ ((cpureg & (MPA_ENINT_ITMSG1 |
+ MPA_ENINT_ITMSG2 |
+ MPA_ENINT_ITMSG3 |
+ MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
+ );
+ else
+ pending &= (
+ ((cpureg & (MPA_ENINT_SR_IP3 |
+ MPA_ENINT_SR_IP7 )) >> MPA_ENINT_MASKSHIFT)
+ |
+ ((cpureg & (MPA_ENINT_ITMSG1 |
+ MPA_ENINT_ITMSG2 |
+ MPA_ENINT_ITMSG3 |
+ MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
+ );
+ } else if (PCR->Prcb->Number == 1){
+ if (HalpIsTowerPci){
+ pending &= (
+ ((cpureg & (MPA_ENINT_SR_IP6 |
+ MPA_ENINT_SR_IP7 )) >> MPA_ENINT_MASKSHIFT)
+ |
+ ((cpureg & (MPA_ENINT_ITMSG1 |
+ MPA_ENINT_ITMSG2 |
+ MPA_ENINT_ITMSG3 |
+ MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
+ );
+ }else{
+ pending &= (
+ ((cpureg & (MPA_ENINT_SR_IP5 |
+ MPA_ENINT_SR_IP7 )) >> MPA_ENINT_MASKSHIFT)
+ |
+ ((cpureg & (MPA_ENINT_ITMSG1 |
+ MPA_ENINT_ITMSG2 |
+ MPA_ENINT_ITMSG3 |
+ MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
+ );
+ }
+ } else {
+ pending &= (
+ ((cpureg & MPA_ENINT_SR_IP7 ) >> MPA_ENINT_MASKSHIFT)
+
+ |
+ ((cpureg & (MPA_ENINT_ITMSG1 |
+ MPA_ENINT_ITMSG2 |
+ MPA_ENINT_ITMSG3 |
+ MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
+ );
+
+ }
+
+ if (causeit != pending) {
+
+ /*
+ * There is sometimes an MP_Agent interrupt with values different in
+ * MPA_INTN_... = 0 and MPA_OINTN_....
+ * That means : The cause register has been updated with a wrong value!
+ * We need to force a new update of the cause register to avoid looping
+ * on this interrupt until a new external interrupt happens.
+ */
+ if (cpureg & MPA_INTCONF_SR_IP8) {
+ tempreg = (cpureg & (~MPA_INTCONF_SR_IP8)) | MPA_ENINT_SR_IP8;
+ } else {
+ tempreg = (cpureg | MPA_INTCONF_SR_IP8 | MPA_ENINT_SR_IP8);
+ }
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), tempreg); // write the new value in the MP_Agent register /
+
+
+ WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // Restore initial value
+
+
+ if (mask <= 1) {
+
+
+
+ return 0;
+ }
+
+ reg = HalpGetCauseRegister();
+ if ( reg & mask ) {
+
+
+ return 0;
+ } else {
+
+
+ return 1;
+ }
+ }
+ }
+
+
+
+ return 0; /* No possible spurious ! */
+
+}
+
+
diff --git a/private/ntos/nthals/halsnip/mips/mpagent.h b/private/ntos/nthals/halsnip/mips/mpagent.h
new file mode 100644
index 000000000..650cb4d81
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/mpagent.h
@@ -0,0 +1,594 @@
+//
+// Defines for Access to the MP Agent
+// this file can be used on assembly language files and C Files
+//
+
+#ifndef _MPAGENT_H_
+#define _MPAGENT_H_
+
+
+#define MPA_BASE_ADDRESS 0xbffff000 /* Base to address the MP_Agent */
+#define MPA_BOOT_MESSAGE 6 /* to start the other processors */
+#define MPA_KERNEL_MESSAGE 10 /* kernel requested IPI */
+#define MPA_TIMER_MESSAGE 11 /* timer interrupt */
+#define MPA_RESTART_MESSAGE 12 /* restart requested */
+
+//
+// define relative offsets of the MP Agent registers
+// (little endian mode)
+//
+
+#define MPA_cpureg 0x000 // (0x00 * 8) configuration cpu register
+#define MPA_cpuda1reg 0x008 // (0x01 * 8) general register
+#define MPA_msgdata 0x010 // (0x02 * 8) data for message passing
+#define MPA_msgstatus 0x018 // (0x03 * 8) message status
+#define MPA_snooper 0x020 // (0x04 * 8) snooper configuration register
+#define MPA_tagreg 0x028 // (0x05 * 8) tag ram R/W index register
+#define MPA_snpadreg 0x030 // (0x06 * 8) adress of first MBus fatal error
+#define MPA_itpend 0x038 // (0x07 * 8) Interrupt register
+#define MPA_datamsg1 0x040 // (0x08 * 8) data message register 1
+#define MPA_datamsg2 0x048 // (0x09 * 8) data message register 2
+#define MPA_datamsg3 0x050 // (0x0a * 8) data message register 3
+#define MPA_lppreg0 0x058 // (0x0b * 8) LPP register cpu 0
+#define MPA_lppreg1 0x060 // (0x0c * 8) LPP register cpu 1
+#define MPA_lppreg2 0x068 // (0x0d * 8) LPP register cpu 2
+#define MPA_lppreg3 0x070 // (0x0e * 8) LPP register cpu 3
+#define MPA_tagram 0x078 // (0x0f * 8) tag ram R/W register
+#define MPA_crefcpt 0x080 // (0x10 * 8) cpu general read counter register
+#define MPA_ctarcpt 0x088 // (0x11 * 8) cpu programmable access counter
+#define MPA_srefcpt 0x090 // (0x12 * 8) snooper general read counter reg.
+#define MPA_starcpt 0x098 // (0x13 * 8) snooper programmable accesscounter
+#define MPA_linkreg 0x0a0 // (0x14 * 8) link register
+#define MPA_software1 0x0a8 // (0x15 * 8) software register1
+#define MPA_msgaddress 0x0b0 // (0x16 * 8) address message register
+#define MPA_mem_operator 0x0b8 // (0x17 * 8) operator internal burst register
+#define MPA_software2 0x0c0 // (0x18 * 8) software register2
+
+
+/* +---------------------------+ */
+/* ! cpureg register (0x00) ! */
+/* +---------------------------+ */
+/*
+
+ The CPUREG Register (LOW-PART) , which has the following bits:
+
+ 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
+ +---------------|---------------|---------------|---------------+
+ | ED| ED| ED| | MI| MI| MI| EI| EI| EI| EI| EI| EI| R | 1 | 0 | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |__________ enable shared 1-> TagCopy for S
+ |_____________ enable message sending
+ |_________________ reserved
+ |_____________________ enable external Interrupts
+ |________________________ enable external Interrupts
+ |____________________________ enable external Interrupts
+ |________________________________ enable external Interrupts
+ |____________________________________ enable external Interrupts
+
+ |__________________________________________ enable external Interrupts
+ |______________________________________________ enable Message Reg. Int.
+ |__________________________________________________ enable Message Reg. Int.
+ |______________________________________________________ enable Message Reg. Int.
+ |__________________________________________________________
+ |______________________________________________________________ Edge Config for Interrupts
+ |__________________________________________________________________ Edge Config for Interrupts
+ |______________________________________________________________________ Edge Config for Interrupts
+
+
+ The CPUREG Register (HIGH-PART), which has the following bits:
+
+
+
+ 31 30 29 28 27 26 25 24| 23 22 21 20 19 18 17 16
+ +---------------|---------------|---------------|---------------+
+ | 1 | 1 | 1 | 1 | 1 | MA| MA| MA| MA| MA| MA| MA| ED| ED| ED| ED| 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ Edge Config for Interrupts
+ |_____________ Edge Config for Interrupts
+ |________________ Edge Config for Interrupts
+ |____________________ Edge Config for Interrupts
+ |________________________ Interrupt Mask on external Request
+ |____________________________ Interrupt Mask on external Request
+ |________________________________ Interrupt Mask on external Request
+ |____________________________________ Interrupt Mask on external Request
+
+ |__________________________________________ Interrupt Mask on external Request
+ |______________________________________________ Interrupt Mask on external Request
+ |__________________________________________________ Interrupt Mask on external Request
+ |______________________________________________________ maximal Retry Count on MP-Bus
+ |__________________________________________________________ maximal Retry Count on MP-Bus
+ |______________________________________________________________ maximal Retry Count on MP-Bus
+ |__________________________________________________________________ maximal Retry Count on MP-Bus
+ |______________________________________________________________________ maximal Retry Count on MP-Bus
+
+*/
+
+#define MPA_ENSHARED 0x00000001 /* (0) If the MP_Agent has not the data in
+ * exclusif state, the MP_Agent forces
+ * the data to shared state for all
+ * coherent access.
+ *
+ * (1) If no other MP_agent has the data
+ * in exclusif state, the requester
+ * can put the data in share or exclusif
+ * state.
+ */
+
+#define MPA_ENSENDMSG 0x00000002 /* (1) 0 -> disable message passing
+ * 1 -> enable message passing
+ */
+
+#define MPA_ENINT_MASK 0x00001ffc /* (12:2) enable interrupt mask */
+#define MPA_ENINT_MASKSHIFT 3 /* shift for enable interrupt mask */
+#define MPA_ENINT_SR_IP3 0x00000008 /* (3) enable external interrupt SR_IP3 */
+#define MPA_ENINT_SR_IP4 0x00000010 /* (4) enable external interrupt SR_IP4 */
+#define MPA_ENINT_SR_IP5 0x00000020 /* (5) enable external interrupt SR_IP5 */
+#define MPA_ENINT_SR_IP6 0x00000040 /* (6) enable external interrupt SR_IP6 */
+#define MPA_ENINT_SR_IP7 0x00000080 /* (7) enable external interrupt SR_IP7 */
+#define MPA_ENINT_SR_IP8 0x00000100 /* (8) enable external interrupt SR_IP8 */
+#define MPA_ENINT_ITMSG1 0x00000200 /* (9) enable interrupt message1 register */
+#define MPA_ENINT_ITMSG2 0x00000400 /* (10) enable interrupt message2 register */
+#define MPA_ENINT_ITMSG3 0x00000800 /* (11) enable interrupt message3 register */
+#define MPA_ENINT_MPBERR 0x00001000 /* (12) enable interrupt MP_Agent fatal error */
+
+#define MPA_INTCONF_MASK 0x000fe000 /* (19:13) select interrupt level
+ * 0 -> falling
+ * 1 -> raising */
+#define MPA_INTCONF_SR_IP3 0x00002000 /* (13) select raising mode for SR_IP3 */
+#define MPA_INTCONF_SR_IP4 0x00004000 /* (14) select raising mode for SR_IP4 */
+#define MPA_INTCONF_SR_IP5 0x00008000 /* (15) select raising mode for SR_IP5 */
+#define MPA_INTCONF_SR_IP6 0x00010000 /* (16) select raising mode for SR_IP6 */
+#define MPA_INTCONF_SR_IP7 0x00020000 /* (17) select raising mode for SR_IP7 */
+#define MPA_INTCONF_SR_IP8 0x00040000 /* (18) select raising mode for SR_IP8 */
+#define MPA_INTCONF_SR_NMI 0x00080000 /* (19) select raising mode for SR_NMI */
+
+#define MPA_INTMSK 0x07f00000 /* (26:20) mask sent during external request stage */
+
+#define MPA_MAXRTY_MASK 0xf8000000 /* (31:27) mask for maximum number of retry on
+ * INV / UPD / MESS / RD_COH */
+
+/* +---------------------------+ */
+/* ! cpuda1reg register (0x01) ! */
+/* +---------------------------+ */
+/*
+ The CPU1REG Register (LOW-PART) , which has the following bits:
+
+ 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
+ +---------------|---------------|---------------|---------------+
+ | SS| SS| TI| 1 | DP| DP| R | R | R | R | R | R | R | R | R | R | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ reserved
+ |_____________ reserved
+ |________________ reserved
+ |____________________ reserved
+ |________________________ reserved
+ |____________________________ reserved
+ |________________________________ reserved
+ |____________________________________ reserved
+ |__________________________________________ reserved
+ |______________________________________________ reserved
+ |__________________________________________________ CPU Data Pattern
+ |______________________________________________________ CPU Data Pattern
+ |__________________________________________________________ Int. Update Policy 0 - direct
+ |______________________________________________________________ Test Interrupts
+ |__________________________________________________________________ Cpu Port Statistics
+ |______________________________________________________________________ Cpu Port Statistics
+
+
+ The CPU1REG Register (HIGH-PART), which has the following bits:
+
+ 31 30 29 28 27 26 25 24| 23 22 21 20 19 18 17 16
+ +---------------|---------------|---------------|---------------+
+ | R | R | R | R | R | R | R | R | R | R | R | IS| IS| IS| 1 | SS| 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ Cpu Port Statistics
+ |_____________ Enable Read Anticipate mode
+ |________________ Select Interrupt for Internal Ints
+ |____________________ Select Interrupt for Internal Ints
+ |________________________ Select Interrupt for Internal Ints
+ |____________________________ reserved
+ |________________________________ reserved
+ |____________________________________ reserved
+
+ |__________________________________________ reserved
+ |______________________________________________ reserved
+ |__________________________________________________ reserved
+ |______________________________________________________ reserved
+ |__________________________________________________________ reserved
+ |______________________________________________________________ reserved
+ |__________________________________________________________________ reserved
+ |______________________________________________________________________ reserved
+
+*/
+
+#define MPA_CPURDPAT_MASK 0x00000c00 /* (11:10) number of wait-state between 2 double
+ * cpu reads. */
+#define MPA_CPURDPAT_DD 0x00000000 /* 0 : dd */
+#define MPA_CPURDPAT_DDX 0x00000400 /* 1 : dd. */
+#define MPA_CPURDPAT_DDXX 0x00000800 /* 2 : dd.. */
+#define MPA_CPURDPAT_DXDX 0x00000c00 /* 3 : d.d. */
+
+#define MPA_ENDIRECT 0x00001000 /* (12) 0 send interrupt to all MP_Agent
+ * 1 use LPP mechanism to dispatch interrupt
+ */
+
+#define MPA_ENTESTIT 0x00002000 /* (13) 0 disable test mode (interrupts from MPBus)
+ * 1 enable test mode (interrupts from INTCONF(6:0))
+ */
+
+#define MPA_CPUSELSTAT_MASK 0x0001c000 /* (16:14) select programmable mode for cpu
+ * access
+ */
+
+#define MPA_ENRDANT 0x00020000 /* (17) 0 disable overlapping memory/MP_Agent
+ *
+ * 1 enable overlapping memory/MP_Agent
+ * The Tag copy checking is done concurently
+ * with memory access. The memory must support
+ * the 'read abort' command (not supported
+ * by current Asic chipset rev.0).
+ */
+
+#define MPA_SELITI_MASK 0x001c0000 /* (20:18) define routage for internal interrupts */
+#define MPA_SELITI_SR_IP3 0x00000000 /* Internal interrupts go on SR_IP3 */
+#define MPA_SELITI_SR_IP4 0x00040000 /* Internal interrupts go on SR_IP4 */
+#define MPA_SELITI_SR_IP5 0x00080000 /* Internal interrupts go on SR_IP5 */
+#define MPA_SELITI_SR_IP6 0x000c0000 /* Internal interrupts go on SR_IP6 */
+#define MPA_SELITI_SR_IP7 0x00100000 /* Internal interrupts go on SR_IP7 */
+#define MPA_SELITI_SR_IP8 0x00140000 /* Internal interrupts go on SR_IP8 */
+
+/* +---------------------------+ */
+/* ! msgstatus register (0x03) ! */
+/* +---------------------------+ */
+
+/* message passing status register */
+
+#define MPA_VALSTAT 0x00000001 /* (0) 0 -> status is invalid
+ * 1 -> status is valid */
+//
+// if (MPA_VALSTAT != 0)
+//
+
+#define MPA_SENDMSG 0x00000002 /* (1) 1 -> message not acknowledged by MPBus */
+#define MPA_ERRMSG 0x00000004 /* (2) 0 -> message has been acknowledged
+ * 1 -> at least one MP_Agent has refused */
+#define MPA_BUSY 0x00000008
+#define MPA_ADERR_MASK 0x000000f0 /* (7:4) list of refusing processor(s) */
+#define MPA_ADERR_SHIFT 0x4
+
+
+/* +---------------------------+ */
+/* ! snooper register (0x04) ! */
+/* +---------------------------+ */
+
+/*
+ The SNOOPER Register (LOW-PART), which has the following bits:
+
+ 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
+ +---------------|---------------|---------------|---------------+
+ | 1 | R | R | R | R | - | - | - | 1 | 1 | 1 | - | - | R | R | 1 | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ enable Message receive
+ |_____________ reserved
+ |________________ reserved
+ |____________________ LineSize
+ |________________________ LineSize
+ |____________________________ Three/ Two Party
+ |________________________________ enable Read+Link
+ |____________________________________ enable Coherency
+
+ |__________________________________________ MP Statistics
+ |______________________________________________ MP Statistics
+ |__________________________________________________ MP Statistics
+ |______________________________________________________ reserved
+ |__________________________________________________________ reserved
+ |______________________________________________________________ reserved
+ |__________________________________________________________________ reserved
+ |______________________________________________________________________ FATAL INTERRUPT inactive
+
+
+ The SNOOPER Register (HIGH-PART), which has the following bits:
+
+ 31 30 29 28 27 26 25 24| 23 22 21 20 19 18 17 16
+ +---------------|---------------|---------------|---------------+
+ | 1 | 1 | 1 | 1 | 1 | R | R | R | R | R | M | M | M | C | C | C | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ Cderrtag TagSeq direct error code
+ |_____________ Cderrtag
+ |________________ Cderrtag
+ |____________________ Mderrtag SnpTagSeq memo Error code
+ |________________________ Mderrtag
+ |____________________________ Mderrtag
+ |________________________________ reserved
+ |____________________________________ reserved
+
+ |__________________________________________ reserved
+ |______________________________________________ reserved
+ |__________________________________________________ reserved
+ |______________________________________________________ Agent Address
+ |__________________________________________________________ Agent Address
+ |______________________________________________________________ seq. cpu error
+ |__________________________________________________________________ tag seq. error
+ |______________________________________________________________________ ext. seq. error
+
+*/
+
+#define MPA_ENRCVMESS 0x00000001 /* (0) 0 -> disable message receiving
+ * 1 -> enable message receiving */
+
+#define MPA_LSIZE_MASK 0x00000018 /* (4:3) secondary linesize mask */
+#define MPA_LSIZE16 0x00000000 /* secondary linesize = 16 bytes */
+#define MPA_LSIZE32 0x00000008 /* secondary linesize = 32 bytes */
+#define MPA_LSIZE64 0x00000010 /* secondary linesize = 64 bytes */
+#define MPA_LSIZE128 0x00000018 /* secondary linesize = 128 bytes */
+
+/* NOTE: MP_Agent doesn't support linesize greater than 64 bytes !! */
+
+#define MPA_DISTPARTY 0x00000020 /* (5) 0 -> enable three-party mode
+ * MP_Agent requester/MP_Agent target
+ * + memory (for update)
+ *
+ * 1 -> disable three-party mode
+ * MP_Agent requester/MP_Agent target
+ */
+
+#define MPA_ENLINK 0x00000040 /* (6) 0 -> The cpu read and link command is
+ * disabled.
+ * 1 -> The cpu read and link command is
+ * enabled.
+ */
+
+#define MPA_ENCOHREQ 0x00000080 /* (7) 0 -> disable sending external request
+ * for coherency to cpu by his MP_Agent
+ * 1 -> enable sending external request
+ * for coherency to cpu by his MP_Agent
+ */
+
+#define MPA_SNPSELSTAT_MASK 0x00000700 /* (10:8) select programmable mode for snooper
+ * access
+ */
+
+#define MPA_RSTSNPERR 0x00008000 /* (15) 1 -> reset all MP bus fatal error
+ *
+ * 0 -> enable new fatal error on MP bus
+ * sent by interrupt.
+ */
+
+#define MPA_CDERRTAG 0x00070000 /* (18:16) (Read only) error code */
+
+#define MPA_MCDERRTAG 0x00380000 /* (21:19) (Read only) error code */
+
+#define MPA_MCDERREXT 0x00c00000 /* (23:22) (Read only) error code */
+
+#define MPA_ADAGT_MASK 0x18000000 /* (28:27) (Read only) MP_Agent address mask */
+#define MPA_ADAGT_SHIFT 27 /* shift address agent value */
+
+#define MPA_MSEQERR 0xe0000000 /* (31:29) (Read only) error code */
+#define MPA_RETRYERR 0x20000000 /* (31:29) (Read only) error code */
+
+
+/* +---------------------------+ */
+/* ! itpend register (0x07) ! */
+/*+---------------------------+ */
+
+/*
+ The Interrupt Pending Register (LOW-PART) , which has the following bits:
+
+ 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
+ +---------------|---------------|---------------|---------------+
+ | UE| UE| UE| UE| R | F | M | M | M | R | E | E | E | E | E | E | 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ pending external Interrupts
+ |_____________ pending external Interrupts
+ |________________ pending external Interrupts
+ |____________________ pending external Interrupts
+ |________________________ pending external Interrupts
+ |____________________________ pending external Interrupts
+ |________________________________ reserved
+ |____________________________________ Message Register 1
+
+ |__________________________________________ Message Register 2
+ |______________________________________________ Message Register 3
+ |__________________________________________________ FATAL MP Agent Error
+ |______________________________________________________ reserved
+ |__________________________________________________________ last updated external State
+ |______________________________________________________________ last updated external State
+ |__________________________________________________________________ last updated external State
+ |______________________________________________________________________ last updated external State
+
+ The Interrupt Pending Register (HIGH-PART), which has the following bits:
+
+ 31 30 29 28 27 26 25 24| 23 22 21 20 19 18 17 16
+ +---------------|---------------|---------------|---------------+
+ | R | R | R | R | R | R | R | R | R | UF| UM| UM| UM| R | UE| UE| 0 Low Activ; 1 High activ;
+ +---------------|---------------+---------------|---------------+
+
+
+
+ |_________ last updated external State
+ |_____________ last updated external State
+ |________________ reserved
+ |____________________ last updated Message State
+ |________________________ last updated Message State
+ |____________________________ last updated Message State
+ |________________________________ last updated FATAL E State
+ |____________________________________ reserved
+
+ |__________________________________________ reserved
+ |______________________________________________ reserved
+ |__________________________________________________ reserved
+ |______________________________________________________ reserved
+ |__________________________________________________________ reserved
+ |______________________________________________________________ reserved
+ |__________________________________________________________________ reserved
+ |______________________________________________________________________ reserved
+
+*/
+
+/* external interrupts */
+#define MPA_INTN_MASKGEN 0x000007ff /* (10:0) pending general interrupt mask */
+#define MPA_INTN_EXT_MASK 0x0000003f /* (5:0) pending external interrupt mask */
+#define MPA_INTN_SR_IP3 0x00000001 /* (0) pending external interrupt SR_IP3 */
+#define MPA_INTN_SR_IP4 0x00000002 /* (1) pending external interrupt SR_IP4 */
+#define MPA_INTN_SR_IP5 0x00000004 /* (2) pending external interrupt SR_IP5 */
+#define MPA_INTN_SR_IP6 0x00000008 /* (3) pending external interrupt SR_IP6 */
+#define MPA_INTN_SR_IP7 0x00000010 /* (4) pending external interrupt SR_IP7 */
+#define MPA_INTN_SR_IP8 0x00000020 /* (5) pending external interrupt SR_IP8 */
+
+/* internal interrupts */
+#define MPA_INTN_ITNMI 0x00000040 /* (6) unused */
+#define MPA_INTN_ITMSG1 0x00000080 /* (7) pending interrupt message1 register */
+#define MPA_INTN_ITMSG2 0x00000100 /* (8) pending interrupt message2 register */
+#define MPA_INTN_ITMSG3 0x00000200 /* (9) pending interrupt message3 register */
+#define MPA_INTN_MPBERR 0x00000400 /* (10) pending interrupt MP_Agent fatal error */
+/* pending internal interrupts mask */
+#define MPA_INTN_INT_MASK (MPA_INTN_ITNMI | \
+ MPA_INTN_ITMSG1 | \
+ MPA_INTN_ITMSG2 | \
+ MPA_INTN_ITMSG3 | \
+ MPA_INTN_MPBERR)
+
+/* old interrupts written in the processor cause register */
+
+/* external interrupts */
+#define MPA_OINTN_MASKGEN 0x007ff000 /* (22:12) old general interrupt mask */
+#define MPA_OINTN_SHIFT 12 /* shift to compare to pending interrupt */
+#define MPA_OINTN_MASK 0x0003f000 /* (17:12) old external interrupt mask */
+#define MPA_OINTN_SR_IP3 0x00001000 /* (12) old external interrupt SR_IP3 */
+#define MPA_OINTN_SR_IP4 0x00002000 /* (13) old external interrupt SR_IP4 */
+#define MPA_OINTN_SR_IP5 0x00004000 /* (14) old external interrupt SR_IP5 */
+#define MPA_OINTN_SR_IP6 0x00008000 /* (15) old external interrupt SR_IP6 */
+#define MPA_OINTN_SR_IP7 0x00010000 /* (16) old external interrupt SR_IP7 */
+#define MPA_OINTN_SR_IP8 0x00020000 /* (17) old external interrupt SR_IP8 */
+
+/* internal interrupts */
+#define MPA_OINTN_ITNMI 0x00040000 /* (18) unused */
+#define MPA_OINTN_ITMSG1 0x00080000 /* (19) old interrupt message1 register */
+#define MPA_OINTN_ITMSG2 0x00100000 /* (20) old interrupt message2 register */
+#define MPA_OINTN_ITMSG3 0x00200000 /* (21) old interrupt message3 register */
+#define MPA_OINTN_MPBERR 0x00400000 /* (22) old interrupt MP_Agent fatal error */
+
+
+/* +---------------------------+ */
+/* ! msgaddress register(0x16) ! */
+/* +---------------------------+ */
+
+/* Message address for message passing */
+
+#define MPA_CPUTARGET_MASK 0x0000000f /* (3:0) target cpu mask */
+#define MPA_CPUTARGET_ALL 0x0000000f /* cpu target : all */
+#define MPA_CPUTARGET_CPU0 0x00000001 /* cpu target : 0 */
+#define MPA_CPUTARGET_CPU1 0x00000002 /* cpu target : 1 */
+#define MPA_CPUTARGET_CPU2 0x00000004 /* cpu target : 2 */
+#define MPA_CPUTARGET_CPU3 0x00000008 /* cpu target : 3 */
+
+#define MPA_REGTARGET_MASK 0x000001f0 /* (8:4) target register */
+#define MPA_REGTARGET_MSG1 0x00000080 /* msg1reg target register */
+#define MPA_REGTARGET_MSG2 0x00000090 /* msg2reg target register */
+#define MPA_REGTARGET_MSG3 0x000000a0 /* msg3reg target register */
+
+#define MPA_ENMSGLPP 0x00000200 /* (9) 0 disable LPP mode for message passing */
+
+/* +---------------------------+ */
+/* ! mem_operator reg. (0x17) ! */
+/* +---------------------------+ */
+
+/* For fake read on a 4Mb segment. Used for cache replace functions */
+
+#define MPA_OP_ENABLE 0x00000001 /* (0) 0 disable operator (address invalid)
+ * 1 enable operator (address valid)
+ */
+
+#define MPA_OP_ADDR_MASK 0xffc00000 /* (31:22) base physical address of a 4Mb kseg0
+ * reserved segment (4Mb == 0x00400000).
+ */
+
+
+#define MPA_TAGREG_ADDR_MASK 0x003ffff0
+#define MPA_TR_STATE_MASK 0x00000003
+#define MPA_TR_NOCOHERENT 0x00000000
+/*
+ * Number of retries before sending a fatal error
+ */
+#define MPA_MSG_RETRY 10
+
+typedef struct _mp_agent{
+
+ /* Register Register
+ * name number offset description
+ * ---------- ---- ------ --------------------------------- */
+ ULONG cpureg; /* 0x00 0x000 configuration cpu register */
+ ULONG invalid_0;
+ ULONG cpuda1reg; /* 0x01 0x008 general register */
+ ULONG invalid_1;
+ ULONG msgdata; /* 0x02 0x010 data for message passing */
+ ULONG invalid_2;
+ ULONG msgstatus; /* 0x03 0x018 message status */
+ ULONG invalid_3;
+ ULONG snooper; /* 0x04 0x020 snooper configuration register */
+ ULONG invalid_4;
+ ULONG tagreg; /* 0x05 0x028 tag ram R/W index register */
+ ULONG invalid_5;
+ ULONG snpadreg; /* 0x06 0x030 adress of first MBus fatal error */
+ ULONG invalid_6;
+ ULONG itpend; /* 0x07 0x038 Interrupt register */
+ ULONG invalid_7;
+ ULONG datamsg1; /* 0x08 0x040 data message register 1 */
+ ULONG invalid_8;
+ ULONG datamsg2; /* 0x09 0x048 data message register 2 */
+ ULONG invalid_9;
+ ULONG datamsg3; /* 0x0a 0x050 data message register 3 */
+ ULONG invalid_a;
+ ULONG lppreg0; /* 0x0b 0x058 LPP register cpu 0 */
+ ULONG invalid_b;
+ ULONG lppreg1; /* 0x0c 0x060 LPP register cpu 1 */
+ ULONG invalid_c;
+ ULONG lppreg2; /* 0x0d 0x068 LPP register cpu 2 */
+ ULONG invalid_d;
+ ULONG lppreg3; /* 0x0e 0x070 LPP register cpu 3 */
+ ULONG invalid_e;
+ ULONG tagram; /* 0x0f 0x078 tag ram R/W register */
+ ULONG invalid_f;
+ ULONG crefcpt; /* 0x10 0x080 cpu general read counter register */
+ ULONG invalid_10;
+ ULONG ctarcpt; /* 0x11 0x088 cpu programmable access counter */
+ ULONG invalid_11;
+ ULONG srefcpt; /* 0x12 0x090 snooper general read counter reg. */
+ ULONG invalid_12;
+ ULONG starcpt; /* 0x13 0x098 snooper programmable accesscounter*/
+ ULONG invalid_13;
+ ULONG linkreg; /* 0x14 0x0a0 link register */
+ ULONG invalid_14;
+ ULONG software1; /* 0x15 0x0a8 software register1 */
+ ULONG invalid_15;
+ ULONG msgaddress; /* 0x16 0x0b0 address message register */
+ ULONG invalid_16;
+ ULONG mem_operator; /* 0x17 0x0b8 operator internal burst register */
+ ULONG invalid_17;
+ ULONG software2; /* 0x18 0x0c0 software register2 */
+}MP_AGENT, *PMP_AGENT;
+
+#define mpagent ((volatile PMP_AGENT) MPA_BASE_ADDRESS) // mpagent address
+
+#endif
diff --git a/private/ntos/nthals/halsnip/mips/orcache.s b/private/ntos/nthals/halsnip/mips/orcache.s
new file mode 100644
index 000000000..bf3024fe7
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/orcache.s
@@ -0,0 +1,561 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/orcache.s,v 1.3 1996/02/23 17:55:12 pierre Exp $")
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// orcache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// R4600 orion Machines.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+#include "SNIdef.h"
+
+#define ORION_REPLACE 0x17c00000
+
+//
+// some bitmap defines to display cache activities via the LED's
+// in the SNI RM machines
+//
+
+#define SWEEP_DCACHE 0xc0 // 1100 0000
+#define FLUSH_DCACHE_PAGE 0x80 // 1000 0000
+#define PURGE_DCACHE_PAGE 0x40 // 0100 0000
+#define ZERO_PAGE 0x0c // 0000 1100
+
+#define SWEEP_ICACHE 0x30 // 0011 0000
+#define PURGE_ICACHE_PAGE 0x10 // 0001 0000
+
+//
+// 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("Flush Data Cache Page")
+//++
+//
+// VOID
+// HalpFlushDcachePageOrion (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function flushes (cache replace) up to a page of data
+// from the secondary data cache. (primary cache is already processed)
+//
+// 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(HalpFlushDcachePageOrion)
+
+#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
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// Flush the secondary data caches => cache replace.
+//
+
+ .set noreorder
+ .set noat
+40: and a0,a0,PAGE_SIZE -1 // PageOffset
+ sll t7,a1,PAGE_SHIFT // physical address
+ lw t4,KiPcr + PcSecondLevelDcacheFillSize(zero) // get 2nd fill size
+ or t0,t7,a0 // physical address + offset
+ 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,60f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ li a3,ORION_REPLACE // get base flush address
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get cache size
+ add t0,t0,-1 // mask of the cache size
+
+ .set noreorder
+ .set noat
+
+50: and t7,t8,t0 // offset
+ addu t7,t7,a3 // physical address + offset
+ lw zero,0(t7) // load Cache -> Write back old Data
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address (+Linesize)
+
+60: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpFlushDcachePageOrion
+
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalpPurgeIcachePageOrion (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of 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(HalpPurgeIcachePageOrion)
+
+#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
+
+
+15: DISABLE_INTERRUPTS(t5) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// Flush the secondary data caches => cache replace.
+//
+
+ .set noreorder
+ .set noat
+40: and a0,a0,PAGE_SIZE -1 // PageOffset
+ sll t7,a1,PAGE_SHIFT // physical address
+ lw t4,KiPcr + PcSecondLevelIcacheFillSize(zero) // get 2nd fill size
+ beq t4,zero,60f
+ or t0,t7,a0 // physical address + offset
+ 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,60f // if eq, no blocks to flush
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+ li a3,ORION_REPLACE // get base flush address
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get cache size
+ add t0,t0,-1 // mask of the cache size
+
+50: and t7,t8,t0 // offset
+ addu t7,t7,a3 // physical address + offset
+ lw zero,0(t7) // load Cache -> Write back old Data
+ bne t8,t9,50b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address (+Linesize)
+
+60: ENABLE_INTERRUPTS(t5) // enable interrupts
+
+ j ra // return
+
+ .end HalpPurgeIcachePageOrion
+
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalpSweepDcacheOrion (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheOrion)
+
+#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 at
+ .set reorder
+
+ DISABLE_INTERRUPTS(t3) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// Sweep the primary data cache.
+//
+
+ 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
+
+//
+// the size is configured on SNI machines as 16KB
+// we invalidate in both sets - so divide the configured size by 2
+//
+
+ srl t0,t0,1
+
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+10:
+ cache INDEX_WRITEBACK_INVALIDATE_D,0(a0) // writeback/invalidate on index
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0)
+
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+//
+// sweep secondary cache
+//
+
+ lw t0,KiPcr + PcSecondLevelDcacheSize(zero) // get data cache size
+ lw t1,KiPcr + PcSecondLevelDcacheFillSize(zero) // get block size
+
+ li a0,ORION_REPLACE // starting address
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+25:
+ lw zero,0(a0)
+ bne a0,a1,25b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+ ENABLE_INTERRUPTS(t3) // enable interrupts
+
+ .set at
+ .set reorder
+
+ j ra // return
+
+
+ .end HalpSweepDcacheMulti
+
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalpSweepIcacheOrion (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheOrion)
+
+#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
+//
+// Sweep the secondary instruction cache.
+//
+
+ .set noreorder
+ .set noat
+
+ DISABLE_INTERRUPTS(t3) // disable interrupts
+
+ .set noreorder
+ .set noat
+
+//
+// sweep secondary cache
+//
+
+ lw t0,KiPcr + PcSecondLevelIcacheSize(zero) // get instruction cache size
+ lw t1,KiPcr + PcSecondLevelIcacheFillSize(zero) // get fill size
+ beq zero,t0,20f // if eq, no second level cache
+ li a0,ORION_REPLACE // set starting index value
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+10: lw zero,0(a0)
+ bne a0,a1,10b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+
+//
+// Sweep the primary instruction cache.
+//
+
+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
+
+//
+// the size is configured on SNI machines as 16KB
+// we invalidate in both sets - so divide the configured size by 2
+//
+
+ srl t0,t0,1
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+ cache INDEX_INVALIDATE_I,8192(a0)
+
+ bne a0,a1,30b // if ne, more to invalidate
+ addu a0,a0,t1 // compute address of next block
+ .set at
+ .set reorder
+
+20: ENABLE_INTERRUPTS(t3) // enable interrupts
+
+ .set at
+ .set reorder
+ j ra // return
+
+ .end HalpSweepIcacheOrion
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalpZeroPageOrion (
+// 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(HalpZeroPageOrion, 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 a1,ZpA1(sp) // save old 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
+ and t8,t4,0x10 // test if 16-byte cache block
+
+//
+// Zero page in primary and secondary data caches.
+//
+
+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) //
+
+ .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 HalpZeroPageOrion
+
+
diff --git a/private/ntos/nthals/halsnip/mips/r4intdsp.c b/private/ntos/nthals/halsnip/mips/r4intdsp.c
new file mode 100644
index 000000000..08f79fb39
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/r4intdsp.c
@@ -0,0 +1,1307 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/r4intdsp.c,v 1.9 1996/02/23 17:55:12 pierre Exp $")
+
+/*++
+
+Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ r4intdsp.c
+
+Abstract:
+
+ This module contains the HalpXxx routines which are important to
+ handle the Interrupts on the SNI machines.
+
+Environment:
+
+ Kernel mode
+
+--*/
+
+#include "halp.h"
+#include "SNIregs.h"
+#include "mpagent.h"
+#include "eisa.h"
+#include "pci.h"
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+typedef BOOLEAN (*PINT0_DISPATCH)(
+ PKINTERRUPT Interupt,
+ PVOID ServiceContext
+ );
+
+extern VOID HalpSendIpi(IN ULONG pcpumask, IN ULONG msg_data);
+
+KINTERRUPT HalpInt0Interrupt; // Interrupt Object for SC machines (centralised interrupt)
+KINTERRUPT HalpInt3Interrupt; // Interrupt Object for IT3 tower multipro
+
+ULONG HalpTargetRetryCnt=0; // Counter for pci error ( initiator receives target retry)
+ULONG HalpSingleEccCounter = 0; // Single Ecc Error Counter (for RM200/RM300)
+
+extern VOID
+HalpReadPCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+extern VOID
+HalpWritePCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+extern BOOLEAN
+HalpPciEisaDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ ) ;
+
+extern BOOLEAN
+HalpPciEisaSBDispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ ) ;
+
+extern BOOLEAN HalpESC_SB;
+
+BOOLEAN
+HalpCreateIntPciStructures (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary for Int0-handling
+ and connects the intermediate interrupt dispatcher.
+ Also the structures necessary for PCI tower Int3 (MAUI interrupt)
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ PVOID InterruptSourceRegister;
+ PINT0_DISPATCH (DispatchRoutine);
+ PKSPIN_LOCK pSpinLock;
+
+ switch (HalpMainBoard) {
+ case M8150 : InterruptSourceRegister = (PVOID)PCI_TOWER_INTERRUPT_SOURCE_REGISTER;
+ DispatchRoutine = HalpPciTowerInt0Dispatch;
+ pSpinLock = (PKSPIN_LOCK)NULL;
+ break;
+
+ default: InterruptSourceRegister = (PVOID)PCI_INTERRUPT_SOURCE_REGISTER;
+ DispatchRoutine = HalpPciInt0Dispatch;
+ pSpinLock = &HalpInterruptLock;
+ }
+
+ KeInitializeInterrupt( &HalpInt0Interrupt,
+ DispatchRoutine,
+ InterruptSourceRegister,
+ (PKSPIN_LOCK)pSpinLock,
+ INT0_LEVEL,
+ INT0_LEVEL, //INT0_LEVEL,
+ INT0_LEVEL, //Synchr. Level
+ LevelSensitive,
+ FALSE, // only one Intobject ispossible for int0
+ 0, // processor number
+ FALSE // floating point registers
+ // and pipe line are not
+ // saved before calling
+ // the service routine
+ );
+
+
+ if (!KeConnectInterrupt( &HalpInt0Interrupt )) {
+
+ //
+ // this is the central Interrupt for the SNI SecondLevel Cache Machines
+ //
+
+ HalDisplayString("Failed to connect Int0!\n");
+ return(FALSE);
+ }
+
+
+
+ return (TRUE);
+}
+
+
+
+BOOLEAN
+HalpCreateIntPciMAUIStructures (
+ CCHAR Number
+ )
+
+/*++
+
+Routine Description:
+
+ This routine initializes the structures necessary
+ for PCI tower Int3 (MAUI interrupt)
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ If the second level interrupt dispatcher are connected, then a value of
+ TRUE is returned. Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+PVOID InterruptSourceRegister;
+
+ InterruptSourceRegister = (PVOID)PCI_TOWER_INTERRUPT_SOURCE_REGISTER;
+
+ KeInitializeInterrupt( &HalpInt3Interrupt,
+ HalpPciTowerInt3Dispatch,
+ InterruptSourceRegister,
+ (PKSPIN_LOCK)&HalpInterruptLock,
+ INT6_LEVEL,
+ INT6_LEVEL, //INT6_LEVEL,
+ INT6_LEVEL, //Synchr. Level
+ LevelSensitive,
+ FALSE, // only one Intobject ispossible for int0
+ Number, // processor number
+ FALSE // floating point registers
+ // and pipe line are not
+ // saved before calling
+ // the service routine
+ );
+
+
+ if (!KeConnectInterrupt( &HalpInt3Interrupt )) {
+
+ //
+ // this is the central Interrupt for the SNI SecondLevel Cache Machines
+ //
+
+ HalDisplayString("Failed to connect Int3!\n");
+ return(FALSE);
+ }
+ }
+
+
+
+BOOLEAN
+HalpPciInt0Dispatch (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+Routine Description:
+
+ This routine handles the central INT0 Interrupt on an SNI PCI Desktop or Minitower
+ To decide which interrupt, read the Interrupt Source Register
+
+ We have to manage priorities by software.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Interrupt
+ Source register.
+
+
+Return Value:
+
+ A BOOLEAN value, TRUE if the interrupt is OK,
+ otherwise FALSE for unknown interrupts
+
+--*/
+
+{
+ UCHAR IntSource;
+ UCHAR MaStatus;
+ ULONG Itpend;
+
+ BOOLEAN SCSIresult, NETresult, result;
+
+ if (HalpCheckSpuriousInt(0x400)) return(FALSE);
+
+
+ IntSource = READ_REGISTER_UCHAR(ServiceContext);
+
+ IntSource ^= PCI_INTERRUPT_MASK; // XOR the low active bits with 1 gives 1
+ // and XOR the high active with 0 gives 1
+
+ if ( IntSource & PCI_EISA_MASK) { // EISA Interrupt
+
+ if (HalpESC_SB)
+ result = HalpPciEisaSBDispatch( NULL, // InterruptObject (unused)
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+ else
+ result = HalpPciEisaDispatch( NULL, // InterruptObject (unused)
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+
+ HalpCheckSpuriousInt(0x00);
+ return(result);
+ }
+
+ //
+ // look for SCSI Interrupts
+ //
+
+ if ( IntSource & PCI_SCSI_MASK){
+ SCSIresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI_VECTOR])(
+ PCR->InterruptRoutine[SCSI_VECTOR]
+ );
+#if DBG
+ if(!SCSIresult) DebugPrint(("Got an invalid SCSI interrupt !\n"));
+#endif
+ HalpCheckSpuriousInt(0x00);
+ return(SCSIresult);
+
+ }
+
+ //
+ // PCI interrupts
+ //
+
+ if ( IntSource & PCI_INTA_MASK){
+ int i;
+ for (i=INTA_VECTOR;i<HalpIntAMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ if ( IntSource & PCI_INTB_MASK){
+ int i;
+ for (i=INTB_VECTOR;i<HalpIntBMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ if ( IntSource & PCI_INTC_MASK){
+ int i;
+ for (i=INTC_VECTOR;i<HalpIntCMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ if ( IntSource & PCI_INTD_MASK){
+ int i;
+ for (i=INTD_VECTOR;i<HalpIntDMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ //
+ // look for an Ethernet Interrupt
+ //
+
+ if ( IntSource & PCI_NET_MASK){
+ NETresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[NET_LEVEL])(
+ PCR->InterruptRoutine[NET_LEVEL]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(NETresult);
+ }
+
+ //
+ // Other interrupts => look in MSR register
+ //
+
+ if ( IntSource & PCI_INT2_MASK) {
+
+ MaStatus = READ_REGISTER_UCHAR(PCI_MSR_ADDR);
+ if (HalpMainBoard == DesktopPCI) {
+ MaStatus ^= PCI_MSR_MASK_D;
+ } else {
+ MaStatus ^= PCI_MSR_MASK_MT;
+ }
+
+ //
+ // look for an ASIC interrupt
+ //
+
+ if ( MaStatus & PCI_MSR_ASIC_MASK){
+
+ Itpend = READ_REGISTER_ULONG(PCI_ITPEND_REGISTER);
+
+ if ( Itpend & (PCI_ASIC_ECCERROR | PCI_ASIC_TRPERROR)) {
+
+ ULONG ErrAddr, AsicErrAddr, Syndrome, ErrStatus, irqsel;
+
+ AsicErrAddr = ErrAddr = READ_REGISTER_ULONG(PCI_ERRADDR_REGISTER);
+ Syndrome = READ_REGISTER_ULONG(PCI_SYNDROME_REGISTER);
+ Syndrome &= 0xff; // only 8 lower bits are significant
+ ErrStatus = READ_REGISTER_ULONG(PCI_ERRSTATUS_REGISTER);
+
+ if (ErrStatus & PCI_MEMSTAT_PARERR) {
+ // Parity error (PCI_ASIC <-> CPU)
+ irqsel = READ_REGISTER_ULONG(PCI_IRQSEL_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER ,
+ (irqsel & 0x70000)); // PARERR it not routed
+ ErrAddr = HalpFindEccAddr(AsicErrAddr,(PVOID)PCI_ERRSTATUS_REGISTER,(PVOID)PCI_MEMSTAT_PARERR);
+
+ if (ErrAddr == -1) ErrAddr = AsicErrAddr;
+
+#if DBG
+ DebugPrint(("pci_memory_error : errstatus=0x%x Add error=0x%x syndrome=0x%x \n",
+ ErrStatus,ErrAddr,Syndrome));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 1;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PARITY ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ErrAddr,HalpComputeNum((UCHAR *)ErrAddr),Syndrome);
+#endif
+ }
+
+ if (ErrStatus & PCI_MEMSTAT_ECCERR) {
+ // ECC error (PCI_ASIC <-> Memory access)
+ AsicErrAddr &= 0xfffffff8;
+ irqsel = READ_REGISTER_ULONG(PCI_IRQSEL_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER ,
+ (irqsel & 0xe000)); // ECC it not routed
+ ErrAddr = HalpFindEccAddr(AsicErrAddr,(PVOID)PCI_ERRSTATUS_REGISTER,(PVOID)PCI_MEMSTAT_ECCERR);
+
+ if (ErrAddr == -1) ErrAddr = AsicErrAddr;
+
+ if (ErrStatus & PCI_MEMSTAT_ECCSINGLE) {
+// HalSweepDcacheRange(0x80000000,2*(PCR->FirstLevelDcacheSize)); // to avoid data_coherency_exception
+// HalSweepIcacheRange(0x80000000,2*(PCR->FirstLevelIcacheSize)); // to avoid data_coherency_exception
+ if (HalpProcessorId == MPAGENT)
+ HalpMultiPciEccCorrector(ErrAddr,ErrAddr >> PAGE_SHIFT,4);
+ else
+ HalpPciEccCorrector(ErrAddr,ErrAddr >> PAGE_SHIFT,4);
+// HalSweepDcacheRange(0x80000000,2*(PCR->FirstLevelDcacheSize)); // to avoid data_coherency_exception
+// HalSweepIcacheRange(0x80000000,2*(PCR->FirstLevelIcacheSize)); // to avoid data_coherency_exception
+
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER, irqsel); // restore routage ECC
+
+ if (ErrAddr == READ_REGISTER_ULONG(PCI_ERRADDR_REGISTER)) {
+ Syndrome = READ_REGISTER_ULONG(PCI_SYNDROME_REGISTER);
+ ErrStatus = READ_REGISTER_ULONG(PCI_ERRSTATUS_REGISTER);
+ KeStallExecutionProcessor(100);
+ }
+
+ // We use SNI_PRIVATE_VECTOR to transmit parameters to the RM300 equivalent DCU' driver
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved=0;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis=FLAG_ECC_ERROR;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EccErrorSimmNum=HalpComputeNum((UCHAR *)ErrAddr);
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EccErrorAddress=ErrAddr;
+
+ // Call the 'RM300 equivalent DCU' driver to log the ECC error in event viewer
+
+ result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+ ++HalpSingleEccCounter;
+ if (HalpSingleEccCounter > 0xffff) {
+#if DBG
+ HalpSingleEccCounter = 0;
+ DebugPrint(("Memory Read Error Counter Overflow\n"));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 2;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "ECC SINGLE ERROR COUNTER OVERFLOW\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ErrAddr,HalpComputeNum((UCHAR *)ErrAddr),Syndrome);
+#endif
+ }
+
+ } else {
+
+#if DBG
+ // UNIX => PANIC
+ DebugPrint(("pci_ecc_error : errstatus=0x%x Add error=0x%x syndrome=0x%x \n",
+ ErrStatus,ErrAddr,Syndrome));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 3;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "UNCORRECTABLE ECC ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ErrAddr,HalpComputeNum((UCHAR *)ErrAddr),Syndrome);
+#endif
+ }
+
+ }
+
+ }
+
+ if ( Itpend & PCI_ASIC_IOTIMEOUT ) {
+
+ ULONG ioadtimeout2, iomemconf;
+
+ ioadtimeout2 = READ_REGISTER_ULONG(PCI_IOADTIMEOUT2_REGISTER);
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT)));
+ // reenable timeout
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf );
+#if DBG
+ DebugPrint(("pci_timeout_error : adresse=0x%x \n",ioadtimeout2));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 4;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PCI TIMEOUT ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ioadtimeout2,0,0);
+#endif
+ }
+ }
+
+ //
+ // Pb NMI because of cirrus chip which generates a parity which is understood by the ASIC
+ // like an error and transmit as an NMI EISA.
+ //
+
+ if (MaStatus & PCI_MSR_NMI) {
+
+ UCHAR DataByte;
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus);
+
+ if (((PNMI_STATUS) &DataByte)->ParityNmi == 1) {
+
+ DebugPrint(("Parity error from system memory\n"));
+
+ // reset NMI interrupt
+ ((PNMI_STATUS) &DataByte)->DisableEisaParity = 1;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus,DataByte);
+
+ ((PNMI_STATUS) &DataByte)->DisableEisaParity = 0;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus,DataByte);
+ }
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl);
+
+ if (((PNMI_EXTENDED_CONTROL) &DataByte)->PendingBusMasterTimeout == 1) {
+
+ DebugPrint(("EISA Bus Master timeout\n"));
+
+ // reset NMI interrupt
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->EnableBusMasterTimeout = 0;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,DataByte);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->EnableBusMasterTimeout = 1;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,DataByte);
+
+ }
+
+ }
+
+ //
+ // look for an PushButton Interrupt and simply dismiss it
+ //
+
+ if ( MaStatus & PCI_MSR_PB_MASK){
+ DebugPrint(("Interrupt - PushButton\n"));
+ WRITE_REGISTER_ULONG( PCI_CSRSTBP_ADDR ,0x0); // reset debug intr
+#if DBG
+ DbgBreakPoint();
+#endif
+ KeStallExecutionProcessor(500000); // sleep 0.5 sec
+ }
+
+ //
+ // look for an OverTemperature Interrupt and simply dismiss it
+ //
+
+ if ( MaStatus & PCI_MSR_TEMP_MASK){
+
+ DebugPrint(("Interrupt - Temperature\n"));
+
+ // we use SNI_PRIVATE_VECTOR->DCU_reserved to transmit the interrupt sources to
+ // the 'RM300 equivalent DCU' driver
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= MaStatus;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //no ECC error
+ result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+
+ // if DCU driver not installed, Reset interrupt + auto-rearm
+
+ READ_REGISTER_ULONG( PCI_CLR_TMP_ADDR);
+
+ }
+
+ //
+ // look for an power off
+ //
+
+ if ( MaStatus & PCI_MSR_POFF_MASK){
+
+ // we use SNI_PRIVATE_VECTOR->DCU_reserved to transmit the interrupt sources to
+ // the 'RM300 equivalent DCU' driver
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= MaStatus;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //No ECC error
+ result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+
+ // if DCU driver not installed, Reset interrupt + auto-rearm
+
+ WRITE_REGISTER_ULONG( PCI_CLRPOFF_ADDR,0);
+ }
+
+ //
+ // look for an power management
+ //
+
+ if ( MaStatus & PCI_MSR_PMGNT_MASK){
+
+ // we use SNI_PRIVATE_VECTOR->DCU_reserved to transmit the interrupt sources to
+ // the 'RM300 equivalent DCU' driver
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= MaStatus;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //No ECC error
+ result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+
+ // if DCU driver not installed, Reset interrupt + auto-rearm
+
+ WRITE_REGISTER_ULONG( PCI_PWDN_ADDR,0); // power down
+ }
+ }
+
+ HalpCheckSpuriousInt(0x00);
+ return (TRUE); // perhaps one of the interrupts was pending :-)
+}
+
+
+BOOLEAN
+HalpPciTowerInt0Dispatch (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+Routine Description:
+
+ This routine handles the central INT0 Interrupt on an SNI PCI tower
+ To decide which interrupt, read the Interrupt Source Register
+
+ We have to manage priorities by software.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Interrupt
+ Source register.
+
+
+Return Value:
+
+ A BOOLEAN value, TRUE if the interrupt is OK,
+ otherwise FALSE for unknown interrupts
+
+--*/
+
+{
+ ULONG IntSource;
+ BOOLEAN SCSIresult, result;
+
+ if (HalpCheckSpuriousInt(0x400)) return(FALSE);
+
+ IntSource = READ_REGISTER_ULONG(ServiceContext);
+
+
+
+ if ( IntSource & PCI_TOWER_EISA_MASK) { // EISA Interrupt
+ if (HalpESC_SB)
+ result = HalpPciEisaSBDispatch( NULL, // InterruptObject (unused)
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+ else
+ result = HalpPciEisaDispatch( NULL, // InterruptObject (unused)
+ (PVOID)EISA_CONTROL_PHYSICAL_BASE // ServiceContext
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(result);
+ }
+
+ //
+ // look for SCSI Interrupts
+ //
+
+ if ( IntSource & PCI_TOWER_SCSI1_MASK){
+
+
+
+ SCSIresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI1_VECTOR])(
+ PCR->InterruptRoutine[SCSI1_VECTOR]
+ );
+#if DBG
+ if(!SCSIresult) DebugPrint(("Got an invalid SCSI 1 interrupt !\n"));
+#endif
+ HalpCheckSpuriousInt(0x00);
+ return(SCSIresult);
+
+ }
+ if ( IntSource & PCI_TOWER_SCSI2_MASK){
+ SCSIresult = ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[SCSI2_VECTOR])(
+ PCR->InterruptRoutine[SCSI2_VECTOR]
+ );
+#if DBG
+ if(!SCSIresult) DebugPrint(("Got an invalid SCSI 2 interrupt !\n"));
+#endif
+ HalpCheckSpuriousInt(0x00);
+ return(SCSIresult);
+
+ }
+ //
+ // PCI interrupts
+ //
+
+ if ( IntSource & PCI_TOWER_INTA_MASK){
+ int i;
+ for (i=INTA_VECTOR;i<HalpIntAMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ if ( IntSource & PCI_TOWER_INTB_MASK){
+ int i;
+ for (i=INTB_VECTOR;i<HalpIntBMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ if ( IntSource & PCI_TOWER_INTC_MASK){
+ int i;
+ for (i=INTC_VECTOR;i<HalpIntCMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+ if ( IntSource & PCI_TOWER_INTD_MASK){
+ int i;
+ for (i=INTD_VECTOR;i<HalpIntDMax;++i)
+ ((PSECONDARY_DISPATCH) PCR->InterruptRoutine[i])(
+ PCR->InterruptRoutine[i]
+ );
+ HalpCheckSpuriousInt(0x00);
+ return(TRUE);
+ }
+
+
+
+
+
+ HalpCheckSpuriousInt(0x00);
+ return (TRUE); // perhaps one of the interrupts was pending :-)
+}
+
+
+
+BOOLEAN
+HalpPciTowerInt3Dispatch (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ )
+/*++
+Routine Description:
+
+ This routine handles the MAUI-INT4 Interrupt on an SNI PCI tower :
+ - DCU interrupt (extra_timer,...)
+ - MPBus error
+ - Memory error
+ - PCI error
+
+ To decide which interrupt, read the Interrupt Source Register
+
+ We have to manage priorities by software.
+
+Arguments:
+
+ Interrupt - Supplies a pointer to the interrupt object.
+
+ ServiceContext - Supplies a pointer to the Interrupt
+ Source register.
+
+
+Return Value:
+
+ A BOOLEAN value, TRUE if the interrupt is OK,
+ otherwise FALSE for unknown interrupts
+
+--*/
+
+{
+ ULONG IntSource;
+ ULONG mem_addr,status;
+ ULONG status0,status1;
+ BOOLEAN result;
+
+
+ if (HalpCheckSpuriousInt(0x2000)) return(FALSE);
+
+
+ IntSource = READ_REGISTER_ULONG(ServiceContext);
+
+
+ //
+ // look if a DCU_INDICATE interrupt occured
+ //
+ //
+
+ if (IntSource & PCI_TOWER_D_INDICATE_MASK){
+
+
+ status = READ_REGISTER_ULONG(PCI_TOWER_INDICATE);
+
+ //
+ // look if extra timer interrupt
+ //
+
+ if (status & PCI_TOWER_DI_EXTRA_TIMER){
+
+ HalpClockInterruptPciTower();
+ return(TRUE);
+ }
+
+ DebugPrint(("DCU_INDICATE interrupt\n"));
+ //
+ // look for an PushButton Interrupt and simply dismiss it
+ //
+
+
+ if ( status & PCI_TOWER_DI_PB_MASK){
+
+ DebugPrint(("Interrupt - PushButton\n"));
+
+#if DBG
+ DbgBreakPoint();
+#endif
+ KeStallExecutionProcessor(500000); // sleep 0.5 sec
+
+ return(TRUE);
+ }
+
+
+ //The reading of DCU_INDICATE register clears the interrupt sources
+ // --> we use SNI_PRIVATE_VECTOR->DCU_reserved to transmit the interrupt sources to
+ // the DCU driver
+ result = TRUE;
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= status;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //No ECC error
+ result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+
+ // if DCU driver not installed, reset EISA_NMI interrupt if necessary
+
+ if (status & PCI_TOWER_DI_EISA_NMI)
+ {
+ UCHAR DataByte;
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus);
+
+
+ if (((PNMI_STATUS) &DataByte)->ParityNmi == 1)
+ {
+ DebugPrint(("Parity error from system memory\n"));
+
+ //reset NMI interrupt //
+
+ ((PNMI_STATUS) &DataByte)->DisableEisaParity = 1;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus,DataByte);
+
+ ((PNMI_STATUS) &DataByte)->DisableEisaParity = 0;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->NmiStatus,DataByte);
+ }
+
+
+ DataByte = READ_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl);
+
+ if (((PNMI_EXTENDED_CONTROL) &DataByte)->PendingBusMasterTimeout == 1)
+ {
+ DebugPrint(("EISA Bus Master timeout\n"));
+
+ //reset NMI interrupt //
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->EnableBusMasterTimeout = 0;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,DataByte);
+
+ ((PNMI_EXTENDED_CONTROL) &DataByte)->EnableBusMasterTimeout = 1;
+ WRITE_REGISTER_UCHAR(&((PEISA_CONTROL) HalpOnboardControlBase)->ExtendedNmiResetControl,DataByte);
+ }
+ }
+
+ return (result);
+ }
+
+ //
+ // look if a DCU_ERROR interrupt occured
+ //
+ //
+
+ if (IntSource & PCI_TOWER_D_ERROR_MASK){
+
+ status = 0;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved= 0;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis = 0; //No ECC error
+ result =(((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+ // read DCU_ERROR register to clear interrupt source if DCU driver not installed
+ READ_REGISTER_ULONG(PCI_TOWER_DCU_ERROR);
+ return (result);
+ }
+
+
+
+ //
+ // look if MP_BUS error
+ //
+
+
+ if (IntSource & PCI_TOWER_MP_BUS_MASK){
+
+
+ status = READ_REGISTER_ULONG(PCI_TOWER_MP_BUS_ERROR_STATUS);
+ mem_addr = READ_REGISTER_ULONG(PCI_TOWER_MP_BUS_ERROR_ADDR);
+
+ // Clear MP_Bus interrupt
+
+ WRITE_REGISTER_ULONG (ServiceContext,IntSource);
+
+
+ if (IntSource & PCI_TOWER_C_PARITY_MASK){
+
+#if DBG
+ DebugPrint(("MP_Bus Parity Error : MPBusErrorStatus = 0x%x MPBusErrorAddress = 0x%x \n",
+ status,mem_addr));
+ //DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 5;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MP_BUS PARITY ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
+#endif
+ }
+
+ if (IntSource & PCI_TOWER_C_REGSIZE){
+#if DBG
+ DebugPrint(("MP_Bus Register Size Error : MPBusErrorStatus = 0x%x \n",
+ status));
+ DbgBreakPoint();
+
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 6;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MP_BUS REGISTER SIZE ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,0,0);
+#endif
+ }
+ }
+
+ //
+ // look if Memory error
+ //
+ if (IntSource & PCI_TOWER_M_ECC_MASK){
+
+
+ mem_addr = READ_REGISTER_ULONG(PCI_TOWER_MEM_ERROR_ADDR)& MEM_ADDR_MASK;
+
+ // correct ECC error
+ HalpMultiPciEccCorrector(mem_addr ,mem_addr >> PAGE_SHIFT,4);
+
+ IntSource = READ_REGISTER_ULONG(PCI_TOWER_GEN_INTERRUPT);
+ if (IntSource & PCI_TOWER_M_ECC_MASK){
+
+ mem_addr = READ_REGISTER_ULONG(PCI_TOWER_MEM_ERROR_ADDR)& MEM_ADDR_MASK;
+ KeStallExecutionProcessor(100);
+ }
+ // We use SNI_PRIVATE_VECTOR to transmit parameters to DCU driver
+
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved=0;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->DCU_reserved_bis=FLAG_ECC_ERROR;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EccErrorSimmNum=HalpComputeNum((UCHAR *)mem_addr);
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EccErrorAddress= mem_addr ;
+
+ // Call the 'DCU' driver to log the ECC error in event viewer
+
+ result = (((PSECONDARY_DISPATCH) PCR->InterruptRoutine[DCU_VECTOR])(
+ PCR->InterruptRoutine[DCU_VECTOR]
+ ));
+
+
+ }
+
+ if (IntSource & PCI_TOWER_M_ADDR_MASK){
+
+ mem_addr = READ_REGISTER_ULONG(PCI_TOWER_MEM_ERROR_ADDR);
+#if DBG
+ DebugPrint(("Memory Address Error : MemErrorAddr = 0x%x \n",mem_addr));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 7;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MEMORY ADDRESS ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,mem_addr,0,0);
+#endif
+ }
+
+ if (IntSource & PCI_TOWER_M_SLT_MASK){
+
+ ULONG MemControl2,MemConf;
+
+ MemControl2 = READ_REGISTER_ULONG(PCI_TOWER_MEM_CONTROL_2);
+ MemConf = READ_REGISTER_ULONG(PCI_TOWER_MEM_CONFIG);
+#if DBG
+ DebugPrint(("Memory slot Error : MemControl2 = 0x%x, MemConf = 0x%x \n",MemControl2,MemConf));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 8;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MEMORY SLOT ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,MemControl2,MemConf,0);
+#endif
+ }
+
+ if (IntSource & PCI_TOWER_M_CFG_MASK){
+
+ ULONG MemControl2,MemConf;
+
+ MemControl2 = READ_REGISTER_ULONG(PCI_TOWER_MEM_CONTROL_2);
+ MemConf = READ_REGISTER_ULONG(PCI_TOWER_MEM_CONFIG);
+#if DBG
+ DebugPrint(("Memory Config Error : MemControl2 = 0x%x, MemConf = 0x%x \n",MemControl2,MemConf));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 9;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MEMORY CONFIG ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,MemControl2,MemConf,0);
+#endif
+ }
+
+
+ if (IntSource & PCI_TOWER_M_RC_MASK){
+
+ // reset error counter
+ WRITE_REGISTER_ULONG (PCI_TOWER_MEM_CONTROL_1, (READ_REGISTER_ULONG(PCI_TOWER_MEM_CONTROL_1) & ERROR_COUNTER_MASK) | ERROR_COUNTER_INITVALUE);
+
+#if DBG
+ DebugPrint(("Memory Read Error Counter Overflow\n"));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 2;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "ECC SINGLE ERROR COUNTER OVERFLOW\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,0,0,0);
+#endif
+ }
+
+
+
+ //
+ // look if PCI interrupt
+ //
+ if (IntSource & PCI_TOWER_P_ERROR_MASK){
+ ULONG PciDataInt,PciData;
+
+ DebugPrint(("PCI interrupt \n"));
+
+
+ PciDataInt = PCI_TOWER_INTERRUPT_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+
+ status = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+
+ // First Initiator interrupt
+
+ if (status & PI_INITF){
+
+ PciData = PCI_TOWER_INITIATOR_ADDR_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ mem_addr = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ // Reset interrupt with write-1-to-clear bit Initiator_Interrupts
+ status0 = PI_INITF;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
+
+ if (status & PI_REC_TARGET_RETRY)
+ HalpTargetRetryCnt++;
+ else {
+
+#if DBG
+ DebugPrint(("PCI Iniatiator interrupt error : Addr = 0x%x , PCI_interrupt register = 0x%x\n",
+ mem_addr,status));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 10;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PCI INITIATOR INTERRUPT ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
+#endif
+ }
+ }
+
+ // First Target interrupt
+
+ if (status & PI_TARGF){
+ PciData = PCI_TOWER_TARGET_ADDR_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ mem_addr = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ // Reset interrupt with write-1-to-clear bit Target_Interrupts
+ status0 = PI_TARGF;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
+
+
+#if DBG
+ DebugPrint(("PCI Target interrupt error : Addr = 0x%x , PCI_interrupt register = 0x%x\n",
+ mem_addr,status));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 11;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PCI TARGET INTERRUPT ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
+#endif
+
+ }
+
+ // First parity error
+
+ if (status & PI_PARF){
+
+ // Reset interrupt with write-1-to-clear bit Parity_Interrupts
+ status0 = PI_PARF;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
+
+ PciData = PCI_TOWER_PAR_0_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ status0 = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ PciData = PCI_TOWER_PAR_1_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ status1 = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+#if DBG
+ DebugPrint(("PCI Parity interrupt error : Parity_0 register = 0x%x , Parity_1 register = 0x%x\n",
+ status0,status1));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 12;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PCI PARITY INTERRUPT ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status0,status1,0);
+#endif
+
+ }
+
+
+ // Multiple Initiator interrupts
+
+ if (status & PI_INITM){
+
+ PciData = PCI_TOWER_TARGET_ADDR_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ mem_addr = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+ // Reset interrupt with write-1-to-clear bit Multiple Initiator_Interrupts
+ status0 = PI_INITM;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
+
+
+
+ if (!(status & PI_REC_TARGET_RETRY)) {
+#if DBG
+ DebugPrint(("Multiple PCI Iniatiator interrupt : Addr = 0x%x , PCI_interrupt register = 0x%x\n",
+ mem_addr,status));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 13;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MULTIPLE PCI INITIATOR ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
+#endif
+ }
+ }
+
+ // Multiple Target interrupts
+
+ if (status & PI_TARGM){
+
+ PciData = PCI_TOWER_TARGET_ADDR_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ mem_addr = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ // Reset interrupt with write-1-to-clear bit Multiple Target_interrupts
+ status0 = PI_TARGM;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
+
+
+
+#if DBG
+ DebugPrint(("Multiple PCI Target interrupt : Addr = 0x%x , PCI_interrupt register = 0x%x\n",
+ mem_addr,status));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 14;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MULTIPLE PCI TARGET ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status,mem_addr,0);
+#endif
+
+ }
+
+ // Multiple Parity interrupts
+
+ if (status & PI_PARM){
+
+ // Reset interrupt with write-1-to-clear bit Multiple Parity_Interrupts
+ status0 = PI_PARM;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status0));
+
+ PciData = PCI_TOWER_PAR_0_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ status0 = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ PciData = PCI_TOWER_PAR_1_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ status1 = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+
+#if DBG
+ DebugPrint(("Multiple PCI Parity interrupt : Parity_0 register = 0x%x , Parity_1 register = 0x%x\n",
+ status0,status1));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 15;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "MULTIPLE PCI PARITY ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,status0,status1,0);
+#endif
+
+ }
+ //reenable PCI interrupt
+ status &= MASK_INT;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciDataInt));
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &status));
+
+ }
+ HalpCheckSpuriousInt(0x00);
+ return (TRUE); // perhaps one of the interrupts was pending :-)
+}
+
+
+
+
diff --git a/private/ntos/nthals/halsnip/mips/snidef.h b/private/ntos/nthals/halsnip/mips/snidef.h
new file mode 100644
index 000000000..8f803cb46
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/snidef.h
@@ -0,0 +1,225 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/snidef.h,v 1.5 1995/11/30 11:12:21 sylvie Exp $")
+/*+++
+
+Copyright (c) 1993-1994 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ SNIdef.h
+
+Abstract:
+
+ This module is the header file that describes hardware addresses
+ common for all SNI systems.
+
+
+
+---*/
+
+#ifndef _SNIDEF_
+#define _SNIDEF_
+
+
+#if DBG
+#define DebugPrint(arg) DbgPrint arg
+#else
+#define DebugPrint(arg) ;
+#endif
+
+#include "snipci.h"
+
+#define VESA_BUS_PHYSICAL_BASE 0x1d000000
+#define VESA_BUS (VESA_BUS_PHYSICAL_BASE | KSEG1_BASE)
+#define VESA_IO_PHYSICAL_BASE 0x1e000000
+#define VESA_IO (VESA_IO_PHYSICAL_BASE | KSEG1_BASE)
+#define PROM_PHYSICAL_BASE 0x1fc00000 // physical base of boot PROM
+#define EISA_MEMORY_PHYSICAL_BASE 0x10000000 // physical base of EISA memory
+#define EISA_CONTROL_PHYSICAL_BASE 0x14000000 // physical base of EISA I/O Space
+#define EISA_MEMORY_BASE (EISA_MEMORY_PHYSICAL_BASE | KSEG1_BASE)
+#define EISA_IO (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE)
+
+// Cache replace addresse for multi-processor machines
+#define MPAGENT_RESERVED 0x17c00000 // MP-Agent operator (VL machines and tower PCI)
+#define RM300_RESERVED 0x00c00000 // cache replace (memory) for RM300 PCI
+
+#define NET_PHYSICAL_BASE 0x18000000 // physical base of ethernet control
+#define SCSI_PHYSICAL_BASE 0x19000000 // physical base of SCSI control 1
+
+#define FLOPPY_CHANNEL 0x2 // Floppy DMA channel
+#define FLOPPY_RELATIVE_BASE 0x3f0 // base of floppy control
+#define PARALLEL_RELATIVE_BASE 0x3bc // base of parallel port
+#define SERIAL0_RELATIVE_BASE 0x3f8 // base of serial port 0
+#define SERIAL1_RELATIVE_BASE 0x2f8 // base of serial port 1
+
+#define FLOPPY_PHYSICAL_BASE 0x140003f0 // base of floppy control
+#define PARALLEL_PHYSICAL_BASE 0x140003bc // base of parallel port
+#define SERIAL0_PHYSICAL_BASE 0x140003f8 // base of serial port 0
+#define SERIAL1_PHYSICAL_BASE 0x140002f8 // base of serial port 1
+
+//
+// the UCONF, MachineStatus, LED and MachineConfig Registers in the ASIC
+// (identical on all SNI machines)
+//
+
+#define UCONF_PHYSICAL_ADDR 0x1fff0000 // interruptions, interface protocol
+#define UCONF_ADDR 0xbfff0000 // interruptions, | KSEG1_BASE
+#define IOMEMCONF_PHYSICAL_ADDR 0x1fff0010 // I/O and Memory Config (for disable Timeout int)
+#define IOMEMCONF_ADDR 0xbfff0010 // I/O and memconf | KSEG1_BASE
+
+//
+// some debugging information registers in the ASIC
+// common on all SNI machines
+//
+
+#define DMACCES_PHYSICAL_ADDR 0x1fff0028 // Counter: # of DMA accesses
+#define DMACCES 0xbfff0028 // Counter: # of DMA accesses | KSEG1_BASE
+#define DMAHIT_PHYSICAL_ADDR 0x1fff0030 // Counter: # of DMA hits
+#define DMAHIT 0xbfff0030 // Counter: # of DMA hits | KSEG1_BASE
+#define IOMMU_PHYSICAL_ADDR 0x1fff0018 // Select IO space addressing
+#define IOMMU 0xbfff0018 // Select IO space addressing | KSEG1_BASE
+#define IOADTIMEOUT1_PHYSICAL_ADDR 0x1fff0020 // Current IO context for the first CPU timeout
+#define IOADTIMEOUT1 0xbfff0020 // first CPU timeout | KSEG1_BASE
+#define IOADTIMEOUT2_PHYSICAL_ADDR 0x1fff0008 // Current IO context on all CPU timeouts
+#define IOADTIMEOUT2 0xbfff0008 // all CPU timeouts | KSEG1_BASE
+
+//
+// Define system time increment value.
+//
+
+#define TIME_INCREMENT (10 * 1000 * 10) // Time increment in 100ns units
+#define MAXIMUM_INCREMENT (10 * 1000 * 10)
+#define MINIMUM_INCREMENT (1 * 1000 * 10)
+
+#define EXTRA_TIMER_CLOCK_IN 7159090 // 7.15909 Mhz (hard value)
+// #define EXTRA_TIMER_CLOCK_IN 7900000 // adjustement to get fq = 10ms
+
+#define PRE_COUNT 3 //
+
+//
+// Define basic Interrupt Levels which correspond to Cause register bits.
+//
+
+#define INT0_LEVEL 3
+#define INT3_LEVEL 3
+#define SCSIEISA_LEVEL 4 // SCSI/EISA device int. vector
+#define EISA_DEVICE_LEVEL 4 // EISA bus interrupt level ???
+#define DUART_VECTOR 5 // DUART SC 2681 int. vector
+
+#define INT6_LEVEL 6
+#define EXTRA_CLOCK_LEVEL 5 // extra timer on RM300
+
+#define PROFILE_LEVEL 8 // Profiling level via Count/compare Interrupt
+
+#define CLOCK_LEVEL (ONBOARD_VECTORS + 0) // Timer channel 0 in the PC core
+
+//
+// all others are vectors in the interrupt dispatch table.
+//
+
+#define SCSI_VECTOR 9 // SCSI device interrupt vector
+#define SCSI1_VECTOR 9 // SCSI 1 device interrupt vector
+#define SCSI2_VECTOR 10 // SCSI 2 device interrupt vector
+#define NET_DEFAULT_VECTOR 7 // ethernet device internal vector on R4x00 PC !!!
+ // configured in the Firmware Tree !!!!!
+#define NET_LEVEL 10 // ethernet device int. vector
+
+#define OUR_IPI_LEVEL 7 // multipro machine
+#define NETMULTI_LEVEL 5 // multipro machine : ethernet device int. vector
+
+#define EIP_VECTOR 15 // EIP Interrupt routine
+#define DCU_VECTOR 15 // DCU Interrupt routine
+
+#define CLOCK2_LEVEL CLOCK_LEVEL // System Clock Level
+
+#define ONBOARD_VECTORS 16
+#define MAXIMUM_ONBOARD_VECTOR (15 + ONBOARD_VECTORS) // maximum Onboard (PC core) vector
+
+//
+// Define EISA device interrupt vectors.
+// they only occur when an Eisa Extension is installed in the Desktop model
+//
+
+#define EISA_VECTORS 32
+#define MAXIMUM_EISA_VECTOR (15 + EISA_VECTORS) // maximum EISA vector
+
+//
+// relative interrupt vectors
+// only the interrupt vectors relative to the Isa/EISA bus are defined
+//
+
+#define KEYBOARD_VECTOR 1 // Keyboard device interrupt vector
+#define SERIAL1_VECTOR 3 // Serial device 1 interrupt vector
+#define SERIAL0_VECTOR 4 // Serial device 0 interrupt vector
+#define FLOPPY_VECTOR 6 // Floppy device interrupt vector
+#define PARALLEL_VECTOR 7 // Parallel device interrupt vector
+#define MOUSE_VECTOR 12 // PS/2 Mouse device interrupt vector
+
+
+// PCI interrupts
+
+#define INTA_VECTOR 50 // PCI INTA first interrupt number
+#define INTB_VECTOR 100 // PCI INTB first interrupt number
+#define INTC_VECTOR 150 // PCI INTC first interrupt number
+#define INTD_VECTOR 200 // PCI INTD first interrupt number
+
+#define MACHINE_TYPE_ISA 0
+#define MACHINE_TYPE_EISA 1
+
+
+//
+// The MAXIMUM_MAP_BUFFER_SIZE defines the maximum map buffers which the system
+// will allocate for devices which require phyically contigous buffers.
+//
+
+#define MAXIMUM_MAP_BUFFER_SIZE 0xc0000 // 768KB for today
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_SMALL_SIZE 0x10000
+
+//
+// Define the initial buffer allocation size for a map buffers for systems with
+// no memory which has a physical address greater than MAXIMUM_PHYSICAL_ADDRESS.
+//
+
+#define INITIAL_MAP_BUFFER_LARGE_SIZE 0xc0000 // 256KB as start
+
+//
+// Define the incremental buffer allocation for a map buffers.
+//
+
+#define INCREMENT_MAP_BUFFER_SIZE 0x10000
+
+//
+// Define the maximum number of map registers that can be requested at one time
+// if actual map registers are required for the transfer.
+//
+
+#define MAXIMUM_ISA_MAP_REGISTER 512
+
+//
+// Define the maximum physical address which can be handled by an Isa card.
+// (16MB)
+//
+
+#define MAXIMUM_PHYSICAL_ADDRESS 0x01000000
+
+//
+// Define the maximum physical address of Main memory on SNI machines
+// (256 MB)
+//
+
+#define MAXIMUM_MEMORY_PHYSICAL_ADDRESS 0x10000000
+
+
+#define COPY_BUFFER 0xFFFFFFFF
+
+#define NO_SCATTER_GATHER 0x00000001
+
+
+
+#endif /* _SNIDEF_ */
diff --git a/private/ntos/nthals/halsnip/mips/snidisp.c b/private/ntos/nthals/halsnip/mips/snidisp.c
new file mode 100644
index 000000000..0e31d4fc0
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/snidisp.c
@@ -0,0 +1,1201 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/snidisp.c,v 1.5 1996/03/04 13:24:39 pierre Exp $")
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991-93 Microsoft Corporation
+
+Module Name:
+
+ SNIdisp.c
+
+Abstract:
+
+ This module implements the HAL display initialization and output routines
+ for the different SNI machines.
+
+ At the moment we know about the following boards:
+ WEITEK P9100 PCIBUS (not in the HAL at the moment...)
+ MATROX STORM PCIBUS ( 80x50 Alpha Mode)
+ Cirrus 5434 PCI cards ( 80x50 Alpha Mode)
+ Standard (unknown) VGA on PCI( 80x50 Alpha Mode)
+
+ If we can not identify the board, we don't initialise the display and we call
+ the vendor printf to display strings.
+
+ At the boot phase all I/O is done via the unmapped uncached Segment (KSEG1) of the
+ R4000 (HalpEisaControlBase); later with the mapped value of HalpEisaControlBase
+ Memory is always accessed via unmapped/uncached (KSEG1) area
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+ Removed HalpInitializeDisplay1, because we do no longer use the P9000 in graphic mode ...
+
+
+NOTE:
+
+
+ We did use our own ...MoveMemory() instead of RtlMoveMemory(),
+ as there is a Hardware bug in our machine and RtlMoveMemory uses
+ the floating point registers for fast 64 bit move and on our bus
+ only 32 bit can be found ... :-)
+
+--*/
+
+#include "halp.h"
+#include "string.h"
+#include "vgadata.h"
+
+#define MEGA_MOVE_MEMORY(D,S,L) MegaMoveMemory(D,S,L) // orig. RtlMoveMemory()
+
+//
+// supported VGA text modi
+//
+
+typedef enum _TEXT_MODE {
+ TEXT_80x50,
+ TEXT_132x50
+} TEXT_MODE;
+
+
+//
+// Define forward referenced procedure prototypes.
+//
+
+extern VOID
+HalpReadPCIConfig (
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VOID HalpDisplaySmallCharacter (IN UCHAR Character);
+VOID HalpOutputSmallCharacter (IN PUCHAR Font);
+VOID HalpInitializeVGADisplay(TEXT_MODE TextMode);
+VOID HalpClearVGADisplay (VOID);
+VOID HalpDisplayVGAString (PUCHAR String);
+VOID HalpPutVGACharacter (UCHAR Character);
+VOID HalpNextVGALine (VOID);
+VOID HalpScrollVGADisplay (VOID);
+VOID DownLoadVGAFont (VOID);
+VOID HalpResetS3Chip (VOID);
+VOID HalpResetCirrusChip (VOID);
+VOID HalpResetP9000 (VOID);
+VOID HalpResetMatroxStorm (VOID);
+VOID HalpVGASetup (VOID);
+VOID HalpDoNoSetup (VOID);
+
+
+typedef
+VOID
+(*PHALP_CONTROLLER_SETUP) (
+ VOID
+ );
+
+
+//
+// Supported board definitions.
+//
+
+typedef enum _VIDEO_BOARD {
+ S3_GENERIC, // Standard S3 based Card (miro crystal 8s)
+ S3_GENERIC_VLB, // Standard S3 based Card (Local Bus)
+ CIRRUS_GENERIC, // Generic Cirrus VGA (Cirrus CL54xx)
+ CIRRUS_GENERIC_VLB, // Generic Cirrus VGA (Cirrus CL54xx) (Local Bus)
+ CIRRUS_ONBOARD, // The Desktop onboard VGA (Cirrus CL5434)
+ VGA_GENERIC, // generic (unknown) VGA
+ VGA_GENERIC_VLB, // generic (unknown) VGA on the Vesa Local BUS
+ MATROX_STORM,
+ VIDEO_BOARD_UNKNOWN // unknown Display Adapter
+} VIDEO_BOARD;
+
+//
+// some supported VGA chips
+//
+
+typedef enum _VIDEO_CHIP {
+ S3,
+ CIRRUS,
+ VGA, // generic (unknown) VGA
+ VGA_P9000,
+ VGA_STORM,
+ VIDEO_CHIP_UNKNOWN
+} VIDEO_CHIP;
+
+typedef struct _VIDEO_BOARD_INFO {
+ PUCHAR FirmwareString;
+ PHALP_CONTROLLER_SETUP ControllerSetup;
+ VIDEO_BOARD VideoBoard;
+ VIDEO_CHIP VideoChip;
+} VIDEO_BOARD_INFO, *PVIDEO_BOARD_INFO;
+
+
+VIDEO_BOARD_INFO KnownVideoBoards[] = {
+ {"VGA ON PCIBUS", HalpVGASetup , VGA_GENERIC, VGA },
+ {"CIRRUS 5434 PCIBUS", HalpVGASetup , CIRRUS_GENERIC, CIRRUS},
+ {"MATROX STORM PCIBUS", HalpVGASetup , MATROX_STORM , VGA_STORM }
+};
+
+LONG numVideoBoards = sizeof (KnownVideoBoards) / sizeof(VIDEO_BOARD_INFO);
+
+//
+// Define static data.
+//
+
+VIDEO_BOARD HalpVideoBoard = VIDEO_BOARD_UNKNOWN;
+VIDEO_CHIP HalpVideoChip = VIDEO_CHIP_UNKNOWN;
+PHALP_CONTROLLER_SETUP HalpDisplayControllerSetup = HalpDoNoSetup;
+
+ULONG HalpColumn;
+ULONG HalpRow;
+ULONG HalpDisplayText;
+ULONG HalpDisplayWidth;
+
+ULONG HalpScrollLength;
+ULONG HalpScrollLine;
+ULONG HalpBytesPerRow;
+PVOID HalpVGAControlBase=( PVOID)( EISA_IO); // Base Address for VGA register access
+PUSHORT VideoBuffer = ( PUSHORT)( EISA_MEMORY_BASE + 0xb8000);
+PUCHAR FontBuffer = ( PUCHAR )( EISA_MEMORY_BASE + 0xa0000);
+BOOLEAN HalpFirstBoot = TRUE;
+
+ULONG HalpMgaStormBase = 0;
+ULONG Halpval40;
+ULONG HalpMatroxBus,HalpMatroxSlot;
+//
+// Declare externally defined data.
+//
+
+
+BOOLEAN HalpDisplayOwnedByHal;
+PHAL_RESET_DISPLAY_PARAMETERS HalpReturnToVga;
+
+//
+// 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
+
+
+
+VOID MegaMoveMemory(
+ OUT PVOID Destination,
+ IN PVOID Source,
+ IN ULONG Length
+ )
+/*++
+
+ Our private function written to substitute the RtlMoveMemory()
+ function (64 bit problem).
+
+--*/
+{
+ULONG lo_index_ul;
+PULONG Dst, Src;
+
+ Dst = (PULONG)Destination;
+ Src = (PULONG)Source;
+ for (lo_index_ul=0; lo_index_ul < Length/sizeof(ULONG); lo_index_ul++)
+ *Dst++ = *Src++;
+}
+
+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 ConfigurationEntry;
+ PVIDEO_BOARD_INFO VideoBoard;
+ LONG Index;
+ ULONG MatchKey;
+
+ //
+ // Find the configuration entry for the first display controller.
+ //
+
+ MatchKey = 0;
+ ConfigurationEntry = KeFindConfigurationEntry(LoaderBlock->ConfigurationRoot,
+ ControllerClass,
+ DisplayController,
+ &MatchKey);
+
+ if (ConfigurationEntry == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Determine which video controller is present in the system.
+ // N.B. Be carefull with debug prints during Phase 0, it
+ // will kill the initial break point request from the debugger ...
+ //
+
+
+ for( Index=0, VideoBoard = KnownVideoBoards; Index < numVideoBoards; Index++, VideoBoard++) {
+
+ if (!strcmp( ConfigurationEntry->ComponentEntry.Identifier,
+ VideoBoard->FirmwareString
+ )) {
+ HalpVideoBoard = VideoBoard->VideoBoard;
+ HalpVideoChip = VideoBoard->VideoChip;
+ HalpDisplayControllerSetup = VideoBoard->ControllerSetup;
+ break;
+ }
+ }
+
+ if (Index >= numVideoBoards) {
+ HalpVideoBoard = VIDEO_BOARD_UNKNOWN;
+ HalpVideoChip = VIDEO_CHIP_UNKNOWN;
+ HalpDisplayControllerSetup = HalpVGASetup;
+
+ //
+ // let's see, if the bios emulator can initialize the card ....
+ //
+
+ HalpDisplayWidth = 80;
+ HalpDisplayText = 25;
+ return TRUE;
+ }
+
+ //
+ // Initialize the display controller.
+ //
+
+ HalpDisplayControllerSetup();
+
+ HalpFirstBoot = FALSE;
+
+ return TRUE;
+}
+
+BOOLEAN
+HalpInitializeDisplay1 (
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+
+/*++
+
+Routine Description:
+
+ This routine normally allocates pool for the OEM font file, but
+ in this version we use only VGA facilities of the Grapgic boards
+ so we simply return TRUE
+
+Arguments:
+
+ LoaderBlock - Supplies a pointer to the loader parameter block.
+
+Return Value:
+
+ TRUE
+
+--*/
+
+{
+
+ return TRUE;
+}
+
+VOID
+HalAcquireDisplayOwnership (
+ IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters
+ )
+
+/*++
+
+Routine Description:
+
+ This routine switches ownership of the display away from the HAL to
+ the system display driver. It is called when the system has reached
+ a point during bootstrap where it is self supporting and can output
+ its own messages. Once ownership has passed to the system display
+ driver any attempts to output messages using HalDisplayString must
+ result in ownership of the display reverting to the HAL and the
+ display hardware reinitialized for use by the HAL.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ //
+ // Set HAL ownership of the display to false.
+ //
+
+ HalpDisplayOwnedByHal = FALSE;
+ HalpReturnToVga = ResetDisplayParameters;
+ return;
+}
+
+VOID
+HalpDoNoSetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine does nothing...
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ HalpDisplayOwnedByHal = TRUE;
+ return;
+}
+
+VOID
+HalpVGASetup(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes a VGA based Graphic card
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ UCHAR byte;
+
+ HalpVGAControlBase = (PVOID)HalpEisaControlBase;
+ VideoBuffer = ( PUSHORT)( EISA_MEMORY_BASE + 0xb8000);
+ FontBuffer = ( PUCHAR )( EISA_MEMORY_BASE + 0xa0000);
+
+ //
+ // if "only" VGA is detected look for an S3 or cirrus chip (VGA ON ATBUS)
+ // if the firmware detects an S3 chip, look if this is an 805i (interleave)
+ //
+
+
+ if ((HalpVideoChip == VGA) || (HalpVideoChip == S3)){
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x1206); // look for Cirrus chips
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA); // read it back
+ if (byte != 0x12) { // no cirrus
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x4838); // unlock the S3 regs
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa539); // Unlock the SC regs
+ WRITE_REGISTER_UCHAR(VGA_CRT_IDX, 0x30); // look for s3 chip id
+ byte = READ_REGISTER_UCHAR(VGA_CRT_DATA) ; // look only for major id
+ switch (byte & 0xf0){
+ case 0xa0: // 801/805 chipset
+ if (byte == 0xa8) { // the new 805i (interleave)
+// DebugPrint(("HAL: Found the new 805i Chip resetting to 805 mode\n"));
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0053);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0067);
+ }
+ case 0x80:
+ case 0x90:
+// DebugPrint(("HAL: Found S3 Chip set - Chip id 0x%x\n",byte));
+ HalpVideoChip = S3;
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0038); // lock s3 regs
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0039); // lock more s3 regs
+ break;
+ default: DebugPrint(("HAL: This seems to be no S3 Chip\n"));
+ }
+ } else { // this may be an cirrus
+ WRITE_REGISTER_UCHAR(VGA_CRT_IDX, 0x27); // cirrus id reg
+ byte = READ_REGISTER_UCHAR(VGA_CRT_DATA);
+ if ((byte & 0xe0) == 0x80) { // look for 100xxxxx
+// DebugPrint(("HAL: Found Cirrus Chip set - Chip id 0x%x\n",byte));
+ HalpVideoChip = CIRRUS;
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0006); // lock Cirrus extensions
+ }
+ }
+ }
+
+
+ switch (HalpVideoChip) {
+
+ case S3: HalpResetS3Chip();
+ break;
+
+ case CIRRUS: HalpResetCirrusChip();
+ break;
+
+ case VGA_STORM:
+ HalpResetMatroxStorm();
+ break;
+
+ default: ;
+ }
+
+ HalpInitializeVGADisplay(TEXT_80x50);
+
+ //
+ // Initialize the current display column, row, and ownership values.
+ //
+
+ HalpColumn = 0;
+ HalpRow = 0;
+ HalpDisplayOwnedByHal = TRUE;
+ 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
+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;
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ if(HalpIsMulti) KiAcquireSpinLock(&HalpDisplayAdapterLock);
+
+ //
+ // 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) {
+
+ if (((HalpVideoBoard == VIDEO_BOARD_UNKNOWN) || (HalpVideoBoard == VGA_GENERIC)) && (HalpReturnToVga != NULL)) {
+ (HalpReturnToVga)(80,25);
+ }
+ HalpDisplayControllerSetup();
+
+ }
+
+ // display the string
+
+// if( HalpVideoChip == VIDEO_CHIP_UNKNOWN) {
+// ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->printf(String);
+// } else {
+ HalpDisplayVGAString(String);
+// }
+
+ if(HalpIsMulti) KiReleaseSpinLock(&HalpDisplayAdapterLock);
+
+ KeLowerIrql(OldIrql);
+
+ return;
+}
+
+
+VOID
+HalpDisplayVGAString (
+ PUCHAR String
+ )
+{
+ while (*String) {
+ switch (*String) {
+ case '\n':
+ HalpNextVGALine();
+ break;
+ case '\r':
+ HalpColumn = 0;
+ break;
+ default:
+ HalpPutVGACharacter(*String);
+ if (++HalpColumn == HalpDisplayWidth) {
+ HalpNextVGALine();
+ }
+ }
+ ++String;
+ }
+
+ return;
+}
+
+
+VOID
+HalpNextVGALine(
+ VOID
+ )
+{
+ if (HalpRow==HalpDisplayText-1) {
+ HalpScrollVGADisplay();
+ } else {
+ ++HalpRow;
+ }
+ HalpColumn = 0;
+}
+
+VOID
+HalpScrollVGADisplay(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ Scrolls the text on the display up one line.
+
+Arguments:
+
+ None
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PUSHORT NewStart;
+ ULONG i;
+
+
+ NewStart = VideoBuffer+HalpDisplayWidth;
+ MegaMoveMemory((PVOID)VideoBuffer, (PVOID)NewStart, (HalpDisplayText-1)*HalpDisplayWidth*sizeof(USHORT));
+
+ for (i=(HalpDisplayText-1)*HalpDisplayWidth; i<HalpDisplayText*HalpDisplayWidth; i++) {
+ VideoBuffer[i] = (REVERSE_ATTRIBUTE << 8) | ' ';
+ }
+}
+
+VOID
+HalpPutVGACharacter(
+ UCHAR Character
+ )
+{
+ PUSHORT cp = (PUSHORT)VideoBuffer;
+ int x = HalpColumn;
+ int y = HalpRow;
+
+ cp[y*HalpDisplayWidth + x] = (USHORT)((REVERSE_ATTRIBUTE << 8) | (Character ));
+}
+
+
+VOID
+HalpClearVGADisplay(
+ VOID
+ )
+{
+ ULONG i;
+ PUSHORT cp = (PUSHORT)VideoBuffer;
+ USHORT Attribute = (REVERSE_ATTRIBUTE << 8) | ' ';
+
+ for(i=0; i < HalpDisplayText*HalpDisplayWidth; i++) {
+ VideoBuffer[i] = Attribute;
+ }
+
+ HalpColumn=0;
+ HalpColumn=0;
+}
+
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ HARDWARE specific Part of Display routines
+
+ this part of this file deals with special Hardware parts of some
+ graphic adapters (RamDac, Clock Generator, VGA Chipsets etc.
+
+-------------------------------------------------------------------*/
+
+VOID
+DownLoadVGAFont(
+ VOID
+ )
+/*+++
+
+ The Space occupied for 1 caracter in the charackter generator memory of an VGA
+ is 0x20 bytes, The font itself uses only 8 bytes, so we skip over the difference
+
+---*/
+{
+
+ PUCHAR dst = (PUCHAR)FontBuffer;
+ PUCHAR src = (PUCHAR)font_8x8;
+ long i, count = 256;
+
+ INIT_VGA_FONT();
+
+ while(count--){
+ for (i=0; i<8; i++)
+ *dst++ = *src++;
+ dst += 0x18;
+ }
+ EXIT_VGA_FONT() ;
+}
+
+VOID
+HalpInitializeVGADisplay(
+ TEXT_MODE TextMode
+ )
+{
+
+static UCHAR _80x50_crt_regs [MAX_CRT] = { // 80x50 text mode
+ 0x5f, 0x4f, 0x50, 0x82, 0x55, // cr0 - cr4
+ 0x81, 0xBF, 0x1f, 0x0, 0x47, // cr9 - 7 lines per char
+ 0x20, 0x00, 0x00, 0x00, 0x00, // cra - cursor off
+ 0x00, 0x9c, 0x8e, 0x8f, 0x28,
+ 0x1f, 0x96, 0xb9, 0xa3, 0xff
+ };
+
+static UCHAR _132x50_crt_regs [MAX_CRT] = { // 132x50 text mode
+ 0xa0, 0x83, 0x84, 0x83, 0x8a, // cr0 - cr4
+ 0x9e, 0xBF, 0x1f, 0x0, 0x47, // cr9 - 7 lines per char
+ 0x20, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x9c, 0x85, 0x8f, 0x42,
+ 0x1f, 0x95, 0xa5, 0xa3, 0xff
+ };
+
+static UCHAR default_graph_regs[GRAPH_MAX] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x0e, 0x00, 0xff
+ };
+
+static UCHAR default_pal_regs[MAX_PALETTE] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x14, 0x7, 0x38, 0x39,
+ 0x3A, 0x3B, 0x3C, 0x3d, 0x3e,
+ 0x3f, 0x08, 0x00, 0x0f, 0x00,
+ 0x00
+ };
+
+ int i;
+ UCHAR byte;
+
+ //
+ // Matrox modification : (cf I/O space mapping p 3.9 of MGA STORM specification)
+ // PCI convention states that i/o space should only be accessed in bytes)
+ //
+
+ //
+ // VGA_MISC : 25.xxx MHZ frequency -> 640 horizontal pixels (val = 63)
+ // VGA_MISC : 28.xxx MHZ frequency -> 720 horizontal pixels (val = 67)
+ //
+
+ if (HalpVideoChip == VGA_STORM) WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x67) ; // else little frame
+
+ // reset ATC FlipFlop
+ byte = READ_REGISTER_UCHAR(VGA_ATC_FF);
+ WRITE_REGISTER_UCHAR(VGA_ATC_DATA, 0); // Disable palette
+
+ // stop the sequencer
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0100);
+
+ if (HalpVideoChip != VGA_STORM) {
+ if (TextMode == TEXT_132x50) {
+ // external clock (40MHz)
+ WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0xAF);
+ } else {
+ // COLOR registers , enable RAM, 25 MHz 400 Lines,
+ WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x63) ;
+ }
+ }
+
+ // Select the timing sequencer values
+ // 8 dot/char
+
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0101);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0302);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0003);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0204);
+
+ // start the sequencer
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0300);
+
+ // Unprotect CRT regs and program them
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX , 0x0011);
+
+ for(i=0; i<MAX_CRT; i++) {
+ WRITE_REGISTER_UCHAR(VGA_CRT_IDX, i);
+ if (TextMode == TEXT_132x50){
+ WRITE_REGISTER_UCHAR(VGA_CRT_DATA, _132x50_crt_regs[i]);
+ } else {
+ WRITE_REGISTER_UCHAR(VGA_CRT_DATA, _80x50_crt_regs[i]);
+ }
+ }
+
+ DownLoadVGAFont();
+
+ HalpDisplayWidth = (TextMode == TEXT_132x50) ? 132 : 80;
+ HalpDisplayText = 50;
+
+ HalpClearVGADisplay();
+
+ i = READ_REGISTER_UCHAR(VGA_ATC_FF); // Reset attr FF
+
+ if (!HalpFirstBoot) {
+
+ //
+ // if this is not the First Boot
+ // i.e. an Bugcheck; we have to setup
+ // the Attribute and colors of the VGA PART
+ //
+
+ for(i=0; i<GRAPH_MAX; i++) {
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX , i);
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, default_graph_regs[i]);
+ }
+
+ for(i=0; i<MAX_PALETTE; i++) { // PALETTE (ATC)
+ WRITE_REGISTER_UCHAR(VGA_ATC_IDX , i);
+ WRITE_REGISTER_UCHAR(VGA_ATC_DATA, default_pal_regs[i]);
+ }
+
+
+ }
+
+ WRITE_REGISTER_UCHAR(VGA_DAC_MASK , 0xff);
+
+ //
+ // set the 16 base colors for text mode in the DAC
+ //
+
+ WRITE_REGISTER_UCHAR(VGA_DAC_WRITE_INDEX, 0x00);
+ for(i=0; i<48; i++) {
+ WRITE_REGISTER_UCHAR(VGA_DAC_DATA, base_colors[i]);
+ }
+
+ WRITE_REGISTER_UCHAR(VGA_ATC_IDX, 0x20);
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen on
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA);
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte & 0xdf)); // in the sequencer
+}
+
+VOID
+HalpMgaWaitLock(
+ UCHAR clock,
+ UCHAR p
+ )
+{
+UCHAR tmpByte;
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PLL_ADDR);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0xea);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,clock);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,(p & 0x7f));
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PLL_ADDR);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0xea);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,clock);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,p );
+ KeStallExecutionProcessor(10);
+
+ tmpByte = 0;
+ while (!(tmpByte & 0x40)) {
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,clock);
+ tmpByte = READ_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA);
+ KeStallExecutionProcessor(10);
+ }
+
+}
+
+
+VOID
+HalpResetMatroxStorm(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine initializes the VGA part of an Matrox storm card
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ USHORT buffer[8];
+ UCHAR tmpByte;
+
+ if (!HalpMgaStormBase) {
+ for(HalpMatroxBus=0;HalpMatroxBus<32;++HalpMatroxBus) {
+
+ for(HalpMatroxSlot=0;HalpMatroxSlot<32;++HalpMatroxSlot) {
+
+ HalpReadPCIConfig(HalpMatroxBus,HalpMatroxSlot,&buffer,0,14);
+
+ if ((buffer[0] == 0x102b) && (buffer[1] == 0x0519) && (buffer[5] == 0x0300)) {
+ HalpReadPCIConfig(HalpMatroxBus,HalpMatroxSlot,&HalpMgaStormBase,0x10,4);
+ break;
+
+ }
+ }
+ if (HalpMgaStormBase) break;
+ }
+ }
+ if ( HalpMgaStormBase == (ULONG)0) return;
+
+ // tranlated address
+ HalpMgaStormBase |= 0xa0000000;
+
+ /*** wait for the drawing engine to be idle ***/
+ tmpByte = 0;
+ while (tmpByte & 0x01) tmpByte = READ_REGISTER_UCHAR(HalpMgaStormBase + STORM_OFFSET + STORM_STATUS + 2);
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_OFFSET + STORM_MISC_W, 0x67);
+
+ if (HalpFirstBoot) {
+ HalpReadPCIConfig(HalpMatroxBus,HalpMatroxSlot,&Halpval40,STORM_PCI_OPTION,4);
+ } else {
+ // interleave bit is reset - gclk not divided - VGA io locations decoded
+ HalpSetPCIData(HalpMatroxBus,HalpMatroxSlot,(PUCHAR)(&Halpval40),STORM_PCI_OPTION,4);
+ }
+
+ if (!HalpFirstBoot) {
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_OFFSET +STORM_MISC_W, 0x2f);
+
+ /*** first : reset (especially for cursor...) ***/
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PLL_RESET);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0);
+
+ /*** like fw -> pgm clocks (50Mhz) ***/
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_OFFSET +STORM_MISC_W, 0x2f); // to pgm PLL
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PLL_ADDR);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PIX_CLK_DATA);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0xfd);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PIX_CLK_DATA);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0x3a);
+ HalpMgaWaitLock(STORM_TVP3026_PIX_CLK_DATA,0xb2);
+
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_MCLK_CTL);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0x0);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_MCLK_CTL);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0x8);
+
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_PLL_ADDR);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_MEM_CLK_DATA);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0xfd);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_MEM_CLK_DATA);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0x3a);
+ HalpMgaWaitLock(STORM_TVP3026_MEM_CLK_DATA,0xb2);
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_MCLK_CTL);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0x10);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_INDEX,STORM_TVP3026_MCLK_CTL);
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_RAMDAC_OFFSET + STORM_TVP3026_DATA,0x18);
+
+ WRITE_REGISTER_UCHAR (HalpMgaStormBase + STORM_OFFSET + STORM_MISC_W, 0x67); // VGA clock 25.xxxMhz
+
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_IDX , VGA_CRTCEXT0);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_DATA, 0);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_IDX , VGA_CRTCEXT1);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_DATA, 0);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_IDX , VGA_CRTCEXT2);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_DATA, 0);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_IDX , VGA_CRTCEXT3);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_DATA, 0);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_IDX , VGA_CRTCEXT4);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_DATA, 0);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_IDX , VGA_CRTCEXT5);
+ WRITE_REGISTER_UCHAR(VGA_CRTCEXT_DATA, 0);
+ }
+
+}
+
+
+VOID
+HalpResetS3Chip(
+ VOID
+ )
+/*+++
+
+ This function resets/loads default values to the S3 Chip
+ extended registers
+
+ this code is borrowed/derived from the s3 miniport driver
+
+---*/
+{
+ UCHAR byte;
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x4838); // unlock the S3 regs
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa539); // Unlock the SC regs
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen off
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA);
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte | 0x20)); // stop the sequencer
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0140); // Enable the enhanced 8514 registers
+ WRITE_REGISTER_USHORT(S3_ADVFUNC_CNTL, 0x02); // reset to normal VGA operation
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0032); // Backward Compat 3
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0035); // CRTC Lock
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x00); // async reset
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x01); //
+
+ WRITE_REGISTER_UCHAR(VGA_FEAT_CNTRL, 0x00); // normal sync
+ WRITE_REGISTER_UCHAR(VGA_MISC_READ, 0x00); //
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x8531);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x2033); // Backward Compat 2
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0034); // Backward Compat 3
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x853a); // S3 Misc 1
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x5a3b); // Data Transfer Exec Pos
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x103c); // Interlace Retrace start
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x00); // start the sequencer
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x03); //
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa640); // VLB: 3Wait
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x1841);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0050);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0051);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff52);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0053);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x3854);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0055);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0056);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0057);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x8058); // ISA Latch ? (bit 3)
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x005c);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x005d);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x005e);
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0760);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x8061);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xa162);
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0043); // Extended Mode
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0045); // HW graphics Cursor Mode
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0046); // HW graphics Cursor Orig x
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff47); // HW graphics Cursor Orig x
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xfc48); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff49); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4a); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4b); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4c); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4d); // HW graphics Cursor Orig y
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xff4e); // Dsp Start x pixel pos
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0xdf4f); // Dsp Start y pixel pos
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0042); // select default clock
+
+ WRITE_REGISTER_UCHAR(VGA_MISC_WRITE, 0x63); // Clock select
+/*
+// this should be done in the InitializeVGA code ...
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen on
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA);
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte & 0xdf)); // in the sequencer
+*/
+
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0038); // lock s3 regs
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x0039); // lock more s3 regs
+
+}
+
+VOID
+HalpResetCirrusChip(
+ VOID
+ )
+/*+++
+
+ This function resets/loads default values to the Cirrus Chip
+ extended registers for use with extended text mode (80x50)
+
+ Register values found in the cirrus manual, appendix D5
+
+---*/
+{
+ UCHAR byte;
+
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x01); // Screen off
+ byte = READ_REGISTER_UCHAR(VGA_SEQ_DATA);
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, (byte | 0x20)); // stop the sequencer
+
+ // extended sequencer and crtc regs for cirrus
+
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x1206); // unlock the extended registers
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0007);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x4008);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x5709);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x180a);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x660b);
+
+ // new modifs
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x3b1b);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x000f);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0016);
+ WRITE_REGISTER_USHORT(VGA_CRT_IDX, 0x001b);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0007);
+ WRITE_REGISTER_USHORT(VGA_GRAPH_IDX, 0x0009);
+ WRITE_REGISTER_USHORT(VGA_GRAPH_IDX, 0x000a);
+ WRITE_REGISTER_USHORT(VGA_GRAPH_IDX, 0x000b);
+ // end new modifs
+
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0010);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0011);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0012);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0013);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0018);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x0119);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x001a);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x3b1b);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x2f1c);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x301d);
+ WRITE_REGISTER_USHORT(VGA_SEQ_IDX, 0x331e);
+
+}
diff --git a/private/ntos/nthals/halsnip/mips/snihalp.h b/private/ntos/nthals/halsnip/mips/snihalp.h
new file mode 100644
index 000000000..9bfc31e99
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/snihalp.h
@@ -0,0 +1,422 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/snihalp.h,v 1.5 1996/03/12 14:56:20 pierre Exp $")
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ SNIhalp.h, original file jxhalp.h
+
+Abstract:
+
+ This header file defines the private Hardware Architecture Layer (HAL)
+ SNI specific interfaces, defines and structures.
+
+
+--*/
+
+#ifndef _SNIHALP_
+#define _SNIHALP_
+#include "SNIdef.h"
+
+//
+// Determine if an virtual address is really a physical address.
+//
+
+#define HALP_IS_PHYSICAL_ADDRESS(Va) \
+ ((((ULONG)Va >= KSEG0_BASE) && ((ULONG)Va < KSEG2_BASE)) ? TRUE : FALSE)
+
+#define IS_KSEG0_ADDRESS(Va) \
+ ((((ULONG)Va >= KSEG0_BASE) && ((ULONG)Va < KSEG1_BASE)) ? TRUE : FALSE)
+
+#define IS_KSEG1_ADDRESS(Va) \
+ ((((ULONG)Va >= KSEG1_BASE) && ((ULONG)Va < KSEG2_BASE)) ? TRUE : FALSE)
+
+#define KSEG0_TO_KSEG1(Va) { \
+ Va &= ~KSEG0_BASE; \
+ Va |= KSEG1_BASE; \
+ }
+
+//
+// Define global data used to locate the EISA control space and the realtime
+// clock registers.
+//
+
+extern PVOID HalpEisaControlBase;
+extern PVOID HalpOnboardControlBase;
+extern PVOID HalpEisaMemoryBase;
+extern PVOID HalpRealTimeClockBase;
+extern PVOID HalpEisaMemoryBase;
+
+extern UCHAR HalpIsMulti;
+extern BOOLEAN HalpIsTowerPci;
+extern ULONG HalpMpaCacheReplace; // address to be used for cache replace operation.
+extern ULONG HalpTwoWayBit; // size of one set for associative cache R5000-R4600-R4700
+
+//
+// possibly processor types for SNI machines ...
+//
+
+typedef enum _HalpProcessorType {
+ ORIONSC, // Orion + Writeback secondary cache
+ MPAGENT, // R4000 + MpAgent
+ R4x00, // R4000 SC
+ UNKNOWN // not yet identified (initial value)
+} HalpProcessorType;
+
+//
+// Kind of processor of SNI machines
+//
+
+extern HalpProcessorType HalpProcessorId;
+
+#define HalpR4600 32
+#define HalpR4700 33
+//
+// possibly moterboard types for SNI machines ...
+//
+
+typedef enum _MotherBoardType {
+// M8022 = 2, // RM400-10 mother board
+// M8022D = 3, // RM400-10 mother board (new PCB)
+// M8032 = 4, // RM400 Tower
+// M8042 = 5, // RM400 Minitower
+ M8150 = 6, // RM400 PCI Tower
+// M8036 = 7, // RM200 Desktop
+ MinitowerPCI= 8, // minitower PCI
+ DesktopPCI = 9 // Desktop PCI
+} MotherBoardType;
+
+//
+// Kind of Mainboard of SNI machines
+//
+
+extern MotherBoardType HalpMainBoard;
+
+//
+// Define map register translation entry structure.
+//
+
+typedef struct _TRANSLATION_ENTRY {
+ PVOID VirtualAddress;
+ ULONG PhysicalAddress;
+ ULONG Index;
+} TRANSLATION_ENTRY, *PTRANSLATION_ENTRY;
+
+//
+// Define adapter object structure.
+//
+
+typedef struct _ADAPTER_OBJECT {
+ CSHORT Type;
+ CSHORT Size;
+ struct _ADAPTER_OBJECT *MasterAdapter;
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PVOID MapRegisterBase;
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+ struct _WAIT_CONTEXT_BLOCK *CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ UCHAR AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+ INTERFACE_TYPE InterfaceType;
+} ADAPTER_OBJECT;
+
+extern PADAPTER_OBJECT MasterAdapterObject;
+
+extern POBJECT_TYPE *IoAdapterObjectType;
+
+extern BOOLEAN LessThan16Mb;
+extern BOOLEAN HalpEisaDma;
+
+//
+// Map buffer parameters. These are initialized in HalInitSystem
+//
+
+extern PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+extern ULONG HalpMapBufferSize;
+
+//
+// Firmware interface
+//
+
+typedef struct {
+ CHAR (*getchar)();
+ PCHAR (*gets)();
+ VOID (*printf)();
+ PCHAR (*parsefile)();
+ VOID (*reinit_slave)();
+ ULONG DCU_reserved;
+ UCHAR ActiveProcessor[4];
+ USHORT DCU_reserved_bis;
+ USHORT EccErrorSimmNum;
+ ULONG EccErrorAddress;
+ struct mpmsg_s *MsgPassArea;
+ struct bank *MemConfArea;
+ ULONG NbMemBanks;
+ ULONG scram_ctlr; // fw reserved (ram disk)
+ ULONG (*EipRoutine)();
+ ULONG EipContext;
+ UCHAR EipHalInfo;
+ UCHAR pad[3];
+ ULONG reserved[5];
+ } SNI_PRIVATE_VECTOR;
+
+
+// definitions for DCU_reserved_bis
+
+#define FLAG_ECC_ERROR 1
+
+
+ struct mpmsg_s {
+ ULONG *mpmsg_wlckp; /* pointer to the writer lock */
+ ULONG *mpmsg_bp; /* beginning pointer message[0] */
+ ULONG *mpmsg_ep; /* endding pointer message[MPMSG_NMAXMSG] */
+ ULONG *mpmsg_rp; /* current read pointer in message[] */
+ ULONG *mpmsg_wp; /* current write pointer in message[] */
+};
+
+
+struct bank {
+ ULONG total_size;
+ UCHAR *first_addr;
+ ULONG first_piece_size;
+ UCHAR *second_addr;
+ ULONG second_piece_size;
+};
+
+
+
+//
+// Define function prototypes.
+//
+
+
+ULONG
+HalpGetStatusRegister(
+ VOID
+ );
+
+ULONG
+HalpSetStatusRegister(
+ ULONG Value
+ );
+
+ULONG
+HalpGetCauseRegister(
+ VOID
+ );
+
+ULONG
+HalpSetCauseRegister(
+ ULONG value
+ );
+
+ULONG
+HalpGetConfigRegister(
+ VOID
+ );
+
+ULONG
+HalpSetConfigRegister(
+ ULONG value
+ );
+
+BOOLEAN
+HalpMapIoSpace(
+ VOID
+ );
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateIntStructures(
+ VOID
+ );
+
+BOOLEAN
+HalpCreateIntMultiStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateIntPciStructures (
+ VOID
+ );
+
+BOOLEAN
+HalpCreateEisaStructures(
+ IN INTERFACE_TYPE Interface
+ );
+
+
+VOID
+HalpDisableEisaInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpDisableInterrupts(
+ VOID
+ );
+
+VOID
+HalpEnableEisaInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+VOID
+HalpDisableOnboardInterrupt(
+ IN ULONG Vector
+ );
+
+VOID
+HalpEnableOnboardInterrupt(
+ IN ULONG Vector,
+ IN KINTERRUPT_MODE InterruptMode
+ );
+
+BOOLEAN
+HalpGrowMapBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Amount
+ );
+
+PADAPTER_OBJECT
+HalpAllocateAdapter(
+ IN ULONG MapRegistersPerChannel,
+ IN PVOID AdapterBaseVa,
+ IN PVOID MapRegisterBase
+ );
+
+ULONG
+HalpAllocPhysicalMemory(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN ULONG MaxPhysicalAddress,
+ IN ULONG NoPages,
+ IN BOOLEAN bAlignOn64k
+ );
+
+BOOLEAN
+HalpPciInt0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpPciTowerInt0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+BOOLEAN
+HalpPciTowerInt3Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+
+BOOLEAN
+HalpRM200Int0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400Int0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400TowerInt0Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpInt1Dispatch(
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400Int3Process (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400Int4Process (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+BOOLEAN
+HalpRM400Int5Process (
+ IN PKINTERRUPT Interrupt,
+ IN PVOID ServiceContext
+ );
+
+VOID
+HalpSystemInit(
+ VOID
+ );
+
+VOID
+HalpDisplayCopyRight(
+ VOID
+ );
+
+VOID
+HalpClearVGADisplay(
+ VOID
+ );
+
+VOID
+HalpIpiInterrupt(
+ VOID
+ );
+
+VOID
+HalpInitMPAgent(
+ ULONG Number
+ );
+
+ULONG
+HalpProcIdentify(
+ VOID
+ );
+
+BOOLEAN
+HalpPciEccCorrector(
+ ULONG Addr,
+ ULONG Pfn,
+ ULONG Length
+ );
+
+BOOLEAN
+HalpMultiPciEccCorrector(
+ ULONG Addr,
+ ULONG Pfn,
+ ULONG Length
+ );
+
+#endif // _SNIHALP_
diff --git a/private/ntos/nthals/halsnip/mips/snipbus.c b/private/ntos/nthals/halsnip/mips/snipbus.c
new file mode 100644
index 000000000..0fb0d1063
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/snipbus.c
@@ -0,0 +1,2051 @@
+/*++
+
+
+Copyright (c) 1989 Microsoft Corporation
+Copyright (c) 1994 Digital Equipment Corporation
+
+Module Name:
+
+ pcisup.c
+
+Abstract:
+
+ Platform-independent PCI bus routines
+
+Author:
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+#include "halp.h"
+#include "snipci.h"
+#include "snipbus.h"
+#include "pci.h"
+#include "eisa.h"
+
+UCHAR HalpInterruptLine[10][32];
+
+//
+// Define PCI slot validity
+//
+typedef enum _VALID_SLOT {
+ InvalidBus = 0,
+ InvalidSlot,
+ ValidSlot
+} VALID_SLOT;
+
+//
+// Local prototypes for routines supporting HalpGet/SetPCIData
+//
+
+VOID
+HalpReadPCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VOID
+HalpWritePCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ );
+
+VALID_SLOT
+HalpValidPCISlot (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+BOOLEAN
+HalpPCIConfigPartialRead(
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN PUCHAR Buffer
+ );
+
+VOID
+HalpPCIConfigPartialWrite(
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN PUCHAR Buffer
+ );
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+ );
+
+VOID
+HalpIntLineUpdate(
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ PPCI_COMMON_CONFIG PciData
+ );
+
+BOOLEAN HalpTowerTestConf(
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+);
+
+//
+// Pragmas to assign functions to different kinds of pages.
+//
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(INIT,HalpInitializePCIBus)
+#endif // ALLOC_PRAGMA
+
+
+//
+// Globals
+//
+
+KSPIN_LOCK HalpPCIConfigLock;
+extern BOOLEAN HalPCIRegistryInitialized;
+ULONG PCIMaxBuses;
+ULONG PCIMaxLocalDevice;
+ULONG PCIMaxDevice;
+ULONG PCIMaxBusZeroDevice;
+PULONG HalpPciConfigAddr;
+PULONG HalpPciConfigData;
+UCHAR HalpIntAMax;
+UCHAR HalpIntBMax;
+UCHAR HalpIntCMax;
+UCHAR HalpIntDMax;
+
+//
+// Registry stuff
+//
+
+PCWSTR rgzMultiFunctionAdapter = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
+PCWSTR rgzConfigurationData = L"Configuration Data";
+PCWSTR rgzIdentifier = L"Identifier";
+PCWSTR rgzPCIIdentifier = L"PCI";
+
+
+
+/*++
+
+Routine Description:
+
+ This function looks at the registry to find if the current machine
+ has a PCI bus or not.
+
+ The Arc firmware is responsible for building configuration information
+ about the number of PCI buses on the system and nature (local vs. secondary
+ - across a PCI-PCI bridge) of the each bus. This state is held in
+ PCIRegInfo.
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+
+
+VOID
+HalpRecurseLoaderBlock(
+ IN PCONFIGURATION_COMPONENT_DATA CurrentEntry
+ )
+/*++
+
+Routine Description:
+
+ This routine parses the loader parameter block looking for the PCI
+ node. Once found, used to determine if PCI parity checking should be
+ enabled or disabled. Set the default to not disable checking.
+
+Arguments:
+
+ CurrentEntry - Supplies a pointer to a loader configuration
+ tree or subtree.
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+ PCONFIGURATION_COMPONENT Component;
+ PPCI_REGISTRY_INFO PCIRegInfo = NULL;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR HalpDesc;
+
+ if (CurrentEntry) {
+ Component = &CurrentEntry->ComponentEntry;
+
+ if (Component->Class == AdapterClass &&
+ Component->Type == MultiFunctionAdapter) {
+
+ if (strcmp(Component->Identifier, "PCI") == 0) {
+#if DBG
+ HalDisplayString("PCI Machine detected\n");
+#endif
+ HalpDesc = ((PCM_PARTIAL_RESOURCE_LIST)(CurrentEntry->ConfigurationData))->PartialDescriptors;
+ if (HalpDesc->Type == CmResourceTypeDeviceSpecific) {
+ PCIRegInfo = (PPCI_REGISTRY_INFO) (HalpDesc+1);
+ PCIMaxBuses = PCIRegInfo->NoBuses;
+ HalPCIRegistryInitialized = TRUE;
+ }
+ return;
+ }
+ }
+
+ //
+ // Process all the Siblings of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Sibling);
+
+ //
+ // Process all the Childeren of current entry
+ //
+
+ HalpRecurseLoaderBlock(CurrentEntry->Child);
+
+ }
+}
+
+VOID
+HalpParseLoaderBlock(
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock
+ )
+{
+
+ if (LoaderBlock == NULL) {
+ return;
+ }
+ HalpRecurseLoaderBlock( (PCONFIGURATION_COMPONENT_DATA)
+ LoaderBlock->ConfigurationRoot);
+}
+
+
+/*++
+
+Routine Description:
+
+ The function intializes global PCI bus state from execpt those from the registry.
+
+ The maximum virtual slot number on the local (type 0 config cycle)
+ PCI bus is registered here, based on the machine dependent define
+ PCI_MAX_LOCAL_DEVICE. This state is carried in PCIMaxLocalDevice.
+
+ The maximum number of virtual slots on a secondary bus is fixed by the
+ PCI Specification and is represented by PCI_MAX_DEVICES. This
+ state is held in PCIMaxDevice.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+
+--*/
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ )
+
+{
+ ULONG irqsel, iomemconf;
+
+ PCIMaxLocalDevice = PCI_MAX_DEVICES - 1;
+ PCIMaxDevice = PCI_MAX_DEVICES - 1;
+
+ if (HalpIsTowerPci) {
+ PCIMaxBusZeroDevice = PCI_MAX_DEVICES - 1;
+ } else {
+ PCIMaxBusZeroDevice = 7;
+ }
+
+ KeInitializeSpinLock (&HalpPCIConfigLock);
+
+ //
+ // Specific sni init to distinguish between desktop/minitower and tower ASIC
+ //
+
+ if (HalpIsTowerPci) HalpPciConfigAddr = (PULONG) (PCI_TOWER_CONF_ADDR_REGISTER);
+ else HalpPciConfigAddr = (PULONG) (PCI_CONF_ADDR_REGISTER);
+ HalpPciConfigData = (PULONG)(PCI_IO_BASE | 0xcfc);
+
+ HalpIntAMax = INTA_VECTOR ;
+ HalpIntBMax = INTB_VECTOR ;
+ HalpIntCMax = INTC_VECTOR ;
+ HalpIntDMax = INTD_VECTOR ;
+
+ // enable PCI timeout interrupts
+
+ if (!HalpIsTowerPci) {
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT))); // clear it
+ // reenable timeout + enable ECC detector-corrector
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf | PCI_IOMEMCONF_ENCHKECC);
+ irqsel = READ_REGISTER_ULONG(PCI_IRQSEL_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER ,
+ ((irqsel | PCI_IRQSEL_MASK ) & PCI_IRQSEL_INT));
+ } else {
+ // init ECC single counter to autorize 0xffff single ECC errors before system crash
+ WRITE_REGISTER_ULONG (PCI_TOWER_MEM_CONTROL_1, (READ_REGISTER_ULONG(PCI_TOWER_MEM_CONTROL_1) & ERROR_COUNTER_MASK) | ERROR_COUNTER_INITVALUE);
+ }
+
+}
+
+
+
+/*++
+
+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.
+
+
+--*/
+
+ULONG
+HalpGetPCIData (
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+{
+ PPCI_COMMON_CONFIG PciData;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ ULONG Len;
+ PCI_SLOT_NUMBER PciSlot;
+ ULONG j;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+ 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 (BusNumber, PciSlot, PciData, 0, sizeof(ULONG));
+
+ //
+ // Check for non-existent bus
+ //
+
+ if (PciData->VendorID == 0x00) {
+ return 0; // Requested bus does not exist. Return no data.
+ }
+
+ //
+ // Check for invalid slot
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID) {
+ if ((Offset == 0) && (Length >=2)) *(PUSHORT)Buffer = PCI_INVALID_VENDORID;
+ return 2;
+ }
+
+
+ } 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
+ //
+
+ //
+ // Read this PCI devices slot data
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusNumber, PciSlot, PciData, 0, Len);
+
+ //
+ // Check for non-existent bus
+ //
+
+ if (PciData->VendorID == 0x00) {
+ return 0; // Requested bus does not exist. Return no data.
+ }
+
+ //
+ // Check for invalid slot
+ //
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ if ((Offset == 0) && (Length >=2)) *(PUSHORT)Buffer = PCI_INVALID_VENDORID;
+ return 2; // only return invalid id
+ }
+
+ //
+ // Update interrupt line
+ //
+
+ HalpIntLineUpdate(BusNumber, Slot, PciData);
+
+ //
+ // Pb concerning especially SCSI : skip IO address when = 3bf0000
+ //
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
+
+ if ( (((ULONG)(PciData->u.type0.BaseAddresses[j]) & ~0x3) | 0x01) == 0x3bf0001 )
+ PciData->u.type0.BaseAddresses[j] = 0;
+ }
+
+ //
+ // 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 (BusNumber, PciSlot, Buffer, Offset, Length);
+ Len += Length;
+
+ }
+
+ }
+
+ return Len;
+}
+
+
+/*++
+
+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.
+
+--*/
+
+ULONG
+HalpSetPCIData (
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+
+{
+ PPCI_COMMON_CONFIG PciData, PciData2;
+ UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
+ ULONG Len;
+ PCI_SLOT_NUMBER PciSlot;
+
+ if (Length > sizeof (PCI_COMMON_CONFIG)) {
+ Length = sizeof (PCI_COMMON_CONFIG);
+ }
+
+
+ Len = 0;
+ PciData = (PPCI_COMMON_CONFIG) iBuffer;
+ PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+
+ 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 (BusNumber, PciSlot, PciData, 0, sizeof(ULONG));
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID || PciData->VendorID == 0x00) {
+ return 0;
+ }
+
+ } else {
+
+ //
+ // Caller requested to set at least some data within the
+ // common header.
+ //
+
+ Len = PCI_COMMON_HDR_LENGTH;
+ HalpReadPCIConfig (BusNumber, PciSlot, PciData, 0, Len);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID ||
+ PciData->VendorID == 0x00 ||
+ PCI_CONFIG_TYPE (PciData) != 0) {
+ //
+ // no device, or header type unkown
+ //
+ return 0;
+ }
+
+ //
+ // Copy COMMON_HDR values to buffer2, then overlay callers changes.
+ //
+
+ RtlMoveMemory (iBuffer2, iBuffer, Len);
+
+ Len -= Offset;
+ if (Len > Length) {
+ Len = Length;
+ }
+
+ RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
+
+ // in case interrupt line or pin was editted
+ //HalpPCILineToPin (BusNumber, PciSlot, PciData2, PciData);
+
+
+ //
+ // Set new PCI configuration
+ //
+
+ HalpWritePCIConfig (BusNumber, PciSlot, 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 (BusNumber, PciSlot, Buffer, Offset, Length);
+ Len += Length;
+ }
+ }
+
+ return Len;
+}
+
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+VOID
+HalpReadPCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ KIRQL OldIrql;
+ PCI_CONFIG_ADDR PciConfigAddrData;
+ PUCHAR BufferOrg;
+ ULONG LengthOrg;
+ ULONG PartialLength;
+ ULONG irqsel, iomemconf;
+ BOOLEAN result;
+ //
+ // Read the slot, if it's valid.
+ // Otherwise, return an Invalid VendorId for a invalid slot on an existing bus
+ // or a null (zero) buffer if we have a non-existant bus.
+ //
+
+ BufferOrg = Buffer;LengthOrg = Length;
+
+ switch (HalpValidPCISlot (BusNumber, Slot)) {
+
+ case ValidSlot:
+
+ //
+ // Acquire Spin Lock
+ //
+
+ KeAcquireSpinLock (&HalpPCIConfigLock, &OldIrql);
+
+ // disable PCI timeout to avoid timeout interrupt when drivers attempt to access invalid slot
+
+ if (!HalpIsTowerPci) {
+ irqsel = READ_REGISTER_ULONG(PCI_IRQSEL_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER ,
+ (irqsel & ~PCI_IRQSEL_TIMEOUTMASK));
+ }
+
+ //
+ // Program PciConfigAddr register
+ //
+
+ PciConfigAddrData.Type = (BusNumber ? PciConfigType1 : PciConfigType0);
+ PciConfigAddrData.BusNumber = BusNumber;
+ PciConfigAddrData.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciConfigAddrData.FunctionNumber = 0;
+// PciConfigAddrData.DeviceNumber = (BusNumber ? Slot.u.bits.DeviceNumber : 0);
+// PciConfigAddrData.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciConfigAddrData.Reserved = 0;
+ PciConfigAddrData.Enable = 1;
+
+ //
+ // Issue PCI Configuration Cycles
+ //
+
+ if (Offset % 4) {
+
+ PartialLength = (Length > (4 - (Offset % 4))) ? (4 - (Offset % 4)) : Length;
+
+ PciConfigAddrData.RegisterNumber = (Offset - (Offset % 4)) >> 2; // ULONG frontier
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ if (HalpIsTowerPci &&( PciConfigAddrData.BusNumber !=0 || PciConfigAddrData.DeviceNumber !=0))
+ WRITE_REGISTER_ULONG(PCI_TOWER_MP_BUS_PCI_LOCK,MP_BUS_PCI_LOCK_REQ);
+
+ result = HalpPCIConfigPartialRead((4 - (Offset % 4)),PartialLength, Buffer);
+
+ if (HalpIsTowerPci &&( PciConfigAddrData.BusNumber !=0 || PciConfigAddrData.DeviceNumber !=0))
+ WRITE_REGISTER_ULONG(PCI_TOWER_MP_BUS_PCI_LOCK,0);
+
+ if (!result){
+
+ RtlFillMemory (BufferOrg, LengthOrg, (UCHAR) -1);
+
+ if (!HalpIsTowerPci) {
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT))); // clear it
+ // reenable timeout
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf );
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER , irqsel );
+ }
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+ return;
+ }
+ Offset += PartialLength;
+ Length -= PartialLength;
+ Buffer += PartialLength;
+
+ }
+
+ while (Length >= 4) {
+
+ PciConfigAddrData.RegisterNumber = Offset >> 2; // ULONG frontier
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ if (HalpIsTowerPci &&( PciConfigAddrData.BusNumber !=0 || PciConfigAddrData.DeviceNumber !=0))
+ WRITE_REGISTER_ULONG(PCI_TOWER_MP_BUS_PCI_LOCK,MP_BUS_PCI_LOCK_REQ);
+
+ * (PULONG) Buffer = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ if (HalpIsTowerPci && (PciConfigAddrData.BusNumber !=0 || PciConfigAddrData.DeviceNumber !=0))
+ WRITE_REGISTER_ULONG(PCI_TOWER_MP_BUS_PCI_LOCK,0);
+
+ if (* (PULONG) Buffer == 0XFFFFFFFF) {
+ RtlFillMemory (BufferOrg, LengthOrg, (UCHAR) -1);
+
+ if (!HalpIsTowerPci) {
+ // reenable timeout
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT))); // clear it
+ // reenable timeout
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf );
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER , irqsel );
+ }
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+ return;
+ }
+
+ Offset += 4;
+ Buffer += 4;
+ Length -= 4;
+
+ }
+
+ if ( Length > 0) {
+
+ PciConfigAddrData.RegisterNumber = Offset >> 2;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ if (HalpIsTowerPci &&( PciConfigAddrData.BusNumber !=0 || PciConfigAddrData.DeviceNumber !=0))
+ WRITE_REGISTER_ULONG(PCI_TOWER_MP_BUS_PCI_LOCK,MP_BUS_PCI_LOCK_REQ);
+
+ result = HalpPCIConfigPartialRead(0,Length,Buffer);
+
+ if (HalpIsTowerPci &&( PciConfigAddrData.BusNumber !=0 || PciConfigAddrData.DeviceNumber !=0))
+ WRITE_REGISTER_ULONG(PCI_TOWER_MP_BUS_PCI_LOCK,0);
+
+ if (!result) {
+
+ RtlFillMemory (BufferOrg, LengthOrg, (UCHAR) -1);
+
+ if (!HalpIsTowerPci) {
+ // reenable timeout
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT))); // clear it
+ // reenable timeout
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf );
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER , irqsel );
+ }
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+ return;
+ }
+
+ Offset += Length;
+ Length -= Length;
+ Buffer += Length;
+
+ }
+
+ //
+ // Release Spin Lock
+ //
+
+ // reenable timeout
+
+ if (!HalpIsTowerPci) {
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT))); // clear it
+ // reenable timeout
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf );
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER , irqsel );
+ }
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+ break;
+
+ case InvalidSlot:
+
+ //
+ // Invalid SlotID return no data (Invalid Slot ID = 0xFFFF)
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) -1);
+ break ;
+
+ case InvalidBus:
+
+ //
+ // Invalid Bus, return return no data
+ //
+
+ RtlFillMemory (Buffer, Length, (UCHAR) 0);
+ break ;
+
+ }
+
+
+ return;
+
+}
+
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+VOID
+HalpWritePCIConfig (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot,
+ IN PUCHAR Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+ )
+{
+ KIRQL OldIrql;
+ PCI_CONFIG_ADDR PciConfigAddrData;
+ ULONG PartialLength;
+ ULONG irqsel, iomemconf;
+
+ if (HalpValidPCISlot (BusNumber, Slot) != ValidSlot) {
+
+ //
+ // Invalid SlotID do nothing
+ //
+
+ return ;
+ }
+
+
+ //
+ // Acquire Spin Lock
+ //
+
+ KeAcquireSpinLock (&HalpPCIConfigLock, &OldIrql);
+
+ // disable PCI timeout to avoid timeout interrupt when drivers attempt to access invalid slot
+
+ if (!HalpIsTowerPci) {
+ irqsel = READ_REGISTER_ULONG(PCI_IRQSEL_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER ,
+ (irqsel & ~PCI_IRQSEL_TIMEOUTMASK));
+ }
+
+
+ //
+ // Program PciConfigAddr register
+ //
+
+ PciConfigAddrData.Type = (BusNumber ? PciConfigType1 : PciConfigType0);
+ PciConfigAddrData.BusNumber = BusNumber;
+ PciConfigAddrData.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciConfigAddrData.FunctionNumber = 0;
+// PciConfigAddrData.DeviceNumber = (BusNumber ? Slot.u.bits.DeviceNumber : 0);
+// PciConfigAddrData.FunctionNumber = Slot.u.bits.FunctionNumber;
+ PciConfigAddrData.Reserved = 0;
+ PciConfigAddrData.Enable = 1;
+
+ //
+ // Issue PCI Configuration Cycles
+ //
+
+ if (Offset % 4) {
+
+ PartialLength = (Length > (4 - (Offset % 4))) ? (4 - (Offset % 4)) : Length;
+
+ PciConfigAddrData.RegisterNumber = (Offset - (Offset % 4)) >> 2; // ULONG frontier
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ HalpPCIConfigPartialWrite((4 - (Offset % 4)),PartialLength, Buffer);
+
+ Offset += PartialLength;
+ Length -= PartialLength;
+ Buffer += PartialLength;
+
+ }
+
+ while (Length >= 4) {
+
+ PciConfigAddrData.RegisterNumber = Offset >> 2; // ULONG frontier
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG)Buffer));
+
+ Offset += 4;
+ Buffer += 4;
+ Length -= 4;
+
+ }
+
+ if ( Length > 0) {
+
+ PciConfigAddrData.RegisterNumber = Offset >> 2;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ HalpPCIConfigPartialWrite(0,Length,Buffer);
+
+ Offset += Length;
+ Length -= Length;
+ Buffer += Length;
+
+ }
+
+ //
+ // Release Spin Lock
+ //
+
+ // reenable timeout
+
+ if (!HalpIsTowerPci) {
+ iomemconf = READ_REGISTER_ULONG(PCI_IOMEMCONF_REGISTER);
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER ,
+ (iomemconf & (~PCI_IOMEMCONF_ENIOTMOUT))); // clear it
+ // reenable timeout
+ WRITE_REGISTER_ULONG( PCI_IOMEMCONF_REGISTER , iomemconf );
+ WRITE_REGISTER_ULONG( PCI_IRQSEL_REGISTER , irqsel );
+ }
+
+ KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
+
+
+}
+
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+VALID_SLOT
+HalpValidPCISlot (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+ )
+{
+ PCI_SLOT_NUMBER Slot2;
+ UCHAR HeaderType;
+ ULONG i;
+ PCI_CONFIGURATION_TYPES PciConfigType;
+
+
+ //
+ // Get the config cycle type for the proposed bus.
+ // (PciConfigTypeInvalid indicates a non-existent bus.)
+ //
+
+ PciConfigType = HalpPCIConfigCycleType(BusNumber, Slot);
+
+ //
+ // The number of devices allowed on a local PCI bus may be different
+ // than that across a PCI-PCI bridge.
+ //
+
+ switch(PciConfigType) {
+
+ case PciConfigType0:
+
+ if ((BusNumber == 0) && (Slot.u.bits.DeviceNumber > PCIMaxBusZeroDevice)) {
+
+ return InvalidSlot;
+ }
+ if (Slot.u.bits.DeviceNumber > PCIMaxLocalDevice) {
+
+ return InvalidSlot;
+ }
+ break;
+
+ case PciConfigType1:
+
+ if ((BusNumber == 0) && (Slot.u.bits.DeviceNumber > PCIMaxBusZeroDevice)) {
+
+ return InvalidSlot;
+ }
+ if (Slot.u.bits.DeviceNumber > PCIMaxDevice) {
+
+ return InvalidSlot;
+ }
+ break;
+
+ case PciConfigTypeInvalid:
+
+ return InvalidBus;
+
+ break;
+
+ }
+
+ //
+ // Check function number
+ //
+
+ if (Slot.u.bits.FunctionNumber == 0) {
+ if (HalpTowerTestConf(BusNumber, Slot)) return ValidSlot;else return InvalidSlot;
+ }
+
+ //
+ // 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;
+
+ if ( ! HalpTowerTestConf(BusNumber, Slot2)) return InvalidSlot;
+
+ HalpReadPCIConfig (BusNumber,
+ 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 InvalidSlot;
+
+ }
+
+ return ValidSlot;
+}
+
+
+/*++
+
+Routine Description:
+
+ Partial write in the PCI config space ( less than one ULONG)
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+VOID
+HalpPCIConfigPartialWrite(
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN PUCHAR Buffer
+ )
+{
+ switch(Offset) {
+
+ case 0:
+
+ if (Length > 1) {
+ WRITE_REGISTER_USHORT ((PULONG) HalpPciConfigData, *(PUSHORT)Buffer);
+ Buffer +=2;Offset +=2;
+ }
+ if (Length !=2) {
+ WRITE_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + Offset), *Buffer);
+ ++Buffer;
+ }
+ break;
+
+ case 1:
+
+ WRITE_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 1), *Buffer);
+ ++Buffer;
+ if (Length == 2)
+ WRITE_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 2), *Buffer);
+ if (Length == 3)
+ WRITE_REGISTER_USHORT ((PULONG) (((PUCHAR)HalpPciConfigData) + 2), *(PUSHORT)Buffer);
+
+ break;
+
+ case 2:
+
+ if (Length < 2) {
+ WRITE_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 2), *Buffer);
+ } else {
+ WRITE_REGISTER_USHORT ((PULONG) (((PUCHAR)HalpPciConfigData) + 2), *(PUSHORT)Buffer);
+ }
+ break;
+
+ case 3:
+
+ WRITE_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 1), *Buffer);
+ break;
+ }
+
+}
+
+
+
+
+
+/*++
+
+Routine Description:
+
+ Partial read in the PCI config space ( less than one ULONG)
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+BOOLEAN
+HalpPCIConfigPartialRead(
+ IN ULONG Offset,
+ IN ULONG Length,
+ IN PUCHAR Buffer
+ )
+{
+ switch(Offset) {
+
+ case 0:
+
+ if (Length > 1) {
+ * (PUSHORT) Buffer = READ_REGISTER_USHORT ((PULONG) HalpPciConfigData);
+ if (* (PUSHORT) Buffer == 0XFFFF) return FALSE;
+ Buffer +=2; Offset+=2;
+ }
+ if (Length !=2) {
+ * Buffer = READ_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + Offset));
+ if (* Buffer == 0XFF) return FALSE;
+ }
+ break;
+
+ case 1:
+
+ * Buffer = READ_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 1));
+ if (* Buffer == 0XFF) return FALSE;
+ ++Buffer;
+ if (Length == 2) {
+ * Buffer = READ_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 2));
+ if (* Buffer == 0XFF) return FALSE;
+ } else {
+ if (Length == 3) {
+ * (PUSHORT) Buffer = READ_REGISTER_USHORT ((PULONG) (((PUCHAR)HalpPciConfigData) + 2));
+ if (* (PUSHORT) Buffer == 0XFFFF) return FALSE;
+ }
+ }
+ break;
+
+ case 2:
+
+ if (Length < 2) {
+ * Buffer = READ_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 2));
+ if (* Buffer == 0XFF) return FALSE;
+ } else {
+ * (PUSHORT) Buffer = READ_REGISTER_USHORT ((PULONG) (((PUCHAR)HalpPciConfigData) + 2));
+ if (* (PUSHORT) Buffer == 0XFFFF) return FALSE;
+ }
+ break;
+
+ case 3:
+
+ * Buffer = READ_REGISTER_UCHAR ((PULONG) (((PUCHAR)HalpPciConfigData) + 1)); ++Buffer;
+ if (* Buffer == 0XFF) return FALSE;
+ break;
+ }
+
+ return TRUE ;
+}
+
+
+
+/*++
+
+Routine Description:
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+PCI_CONFIGURATION_TYPES
+HalpPCIConfigCycleType (
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+ )
+
+{
+
+ //
+ // Determine if Type0, Type1, or Invalid
+ //
+
+ if (BusNumber < 0 || BusNumber > (PCIMaxBuses - 1)) {
+ return PciConfigTypeInvalid;
+ } else if (BusNumber) {
+ return PciConfigType1;
+ } else {
+ return PciConfigType0;
+ }
+
+}
+
+/*++
+
+Routine Description:
+
+
+ Update interrupt line : the read value in the PCI config space is form 0 to 6.
+ Each device needs a unique system interrupt number. This number is given by
+ this routine. The array HalpInterruptLine keeps the given system value.
+
+
+
+Arguments:
+
+
+
+
+Return Value:
+
+
+--*/
+
+VOID
+HalpIntLineUpdate(
+ IN ULONG BusNumber,
+ IN ULONG Slot,
+ PPCI_COMMON_CONFIG PciData
+ )
+
+{
+
+ if (HalpInterruptLine[BusNumber][Slot] == 0) {
+
+ switch (PciData->u.type0.InterruptLine) {
+ case 1:
+ if (HalpIntAMax > INTA_VECTOR + 50) {
+ DebugPrint(("More than 50 PCI Devices connected to INTA\n"));
+#if DBG
+ DbgBreakPoint();
+#endif
+ }
+
+ HalpInterruptLine[BusNumber][Slot] = HalpIntAMax;
+ ++ HalpIntAMax;
+ break;
+ case 2:
+ if (HalpIntBMax > INTB_VECTOR + 50) {
+ DebugPrint(("More than 50 PCI Devices connected to INTB\n"));
+#if DBG
+ DbgBreakPoint();
+#endif
+ }
+ HalpInterruptLine[BusNumber][Slot] = HalpIntBMax;
+ ++ HalpIntBMax;
+ break;
+ case 3:
+ if (HalpIntCMax > INTC_VECTOR + 50) {
+ DebugPrint(("More than 50 PCI Devices connected to INTC\n"));
+#if DBG
+ DbgBreakPoint();
+#endif
+ }
+ HalpInterruptLine[BusNumber][Slot] = HalpIntCMax;
+ ++ HalpIntCMax;
+ break;
+ case 4:
+ if (HalpIntDMax > INTD_VECTOR + 50) {
+ DebugPrint(("More than 50 PCI Devices connected to INTD\n"));
+#if DBG
+ DbgBreakPoint();
+#endif
+ }
+ HalpInterruptLine[BusNumber][Slot] = HalpIntDMax;
+ ++ HalpIntDMax;
+ break;
+ case 5:
+ HalpInterruptLine[BusNumber][Slot] = SCSI_VECTOR;
+ break;
+ case 6:
+ HalpInterruptLine[BusNumber][Slot] = NET_LEVEL;
+ break;
+ }
+
+ }
+
+ PciData->u.type0.InterruptLine = HalpInterruptLine[BusNumber][Slot];
+
+}
+
+BOOLEAN HalpTowerTestConf(
+ IN ULONG BusNumber,
+ IN PCI_SLOT_NUMBER Slot
+)
+
+/*++
+
+Routine Description
+
+ Only for tower.
+ An access to an empty slot will do an exception if we don't care.
+
+Arguments
+
+ None
+
+Return value
+
+ True : slot ok
+ False : slot not ok
+
+++*/
+
+{
+ULONG PciData,Buffer,SaveReg;
+PCI_CONFIG_ADDR PciConfigAddrData;
+
+ if (!HalpIsTowerPci) return TRUE;
+
+
+ PciData = PCI_TOWER_INTERRUPT_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ // Save PCI interrupt register
+ SaveReg = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ // reset MAUI PCI error, set flag for exception routine
+ PciData = PI_RESET ;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+
+ // write to vendor-id (ro) to see if exception appears.
+ PciConfigAddrData.Type = (BusNumber ? PciConfigType1 : PciConfigType0);
+ PciConfigAddrData.BusNumber = BusNumber;
+ PciConfigAddrData.DeviceNumber = Slot.u.bits.DeviceNumber;
+ PciConfigAddrData.FunctionNumber = 0;
+ PciConfigAddrData.Reserved = 0;
+ PciConfigAddrData.Enable = 1;
+ PciConfigAddrData.RegisterNumber = 0; // ULONG frontier
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciConfigAddrData));
+
+ PciData = 0xffffffff;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+
+ // read MAUI PCI error
+ PciData = PCI_TOWER_INTERRUPT_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+ Buffer = READ_REGISTER_ULONG ((PULONG) HalpPciConfigData);
+
+ if ( Buffer & PI_CPU_PCI_TIMO) {
+ // reset MAUI PCI error, set flag for exception routine
+ PciData = PCI_TOWER_INTERRUPT_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ PciData = PI_RESET ;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+
+ // restore PCI interrupt
+ PciData = SaveReg;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+
+ return FALSE;
+ } else {
+ // restore PCI interrupt
+ PciData = SaveReg;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+ return TRUE;
+ }
+}
+
+
+
+/*++
+
+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
+HalpAssignPCISlotResources (
+ IN ULONG BusNumber,
+ 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
+ )
+
+{
+
+ NTSTATUS status;
+ PUCHAR WorkingPool;
+ PPCI_COMMON_CONFIG PciData;
+ PCI_SLOT_NUMBER PciSlot;
+ PCM_RESOURCE_LIST CmRes;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ ULONG i, j, length, memtype, BaseAd, BaseAd2, Offset;
+ ULONG BaseAddresses[10];
+ ULONG cnt, len;
+ BOOLEAN conflict;
+
+ *pAllocatedResources = NULL;
+ PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (CM_RESOURCE_LIST) +
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) +
+ PCI_COMMON_HDR_LENGTH * 2;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+
+ if (!WorkingPool) {
+
+ return STATUS_NO_MEMORY;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CmRes = (PCM_RESOURCE_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH );
+
+ //
+ // Read the PCI device's configuration
+ //
+
+ HalpReadPCIConfig (BusNumber, PciSlot, (PUCHAR) PciData, 0, PCI_COMMON_HDR_LENGTH);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID || PciData->VendorID == 0x00) {
+
+ ExFreePool (WorkingPool);
+ return STATUS_NO_SUCH_DEVICE;
+
+ }
+
+ //
+ // Update interrupt line
+ //
+
+ HalpIntLineUpdate(BusNumber, Slot, PciData);
+
+ //
+ // Build an CM_RESOURCE_LIST for the PCI device to report resources
+ // to IoReportResourceUsage.
+ //
+ // This code does *not* use IoAssignResources, as the PCI
+ // address space resources have been previously assigned by the ARC firmware
+ //
+
+ CmRes->Count = 1;
+ CmRes->List[0].InterfaceType = PCIBus;
+ CmRes->List[0].BusNumber = BusNumber;
+
+ CmRes->List[0].PartialResourceList.Count = 0;
+
+ //
+ // Set current CM_RESOURCE_LIST version and revision
+ //
+
+ CmRes->List[0].PartialResourceList.Version = 0;
+ CmRes->List[0].PartialResourceList.Revision = 0;
+
+ CmDescriptor = CmRes->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+
+ CmDescriptor->Type = CmResourceTypeInterrupt;
+ CmDescriptor->ShareDisposition = CmResourceShareShared;
+ CmDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+ CmDescriptor->u.Interrupt.Level = PciData->u.type0.InterruptLine;
+ CmDescriptor->u.Interrupt.Vector = PciData->u.type0.InterruptLine;
+
+ CmRes->List[0].PartialResourceList.Count++;
+ CmDescriptor++;
+
+ }
+
+ //
+ // Add a memory/port resource for each PCI resource
+ //
+
+ Offset = FIELD_OFFSET(PCI_COMMON_CONFIG,u.type0.BaseAddresses[0]);
+
+ for (j=0; j < PCI_TYPE0_ADDRESSES; j++,Offset += sizeof(LONG)) {
+
+//
+// Pb concerning especially SCSI : skip IO address when = 3bf0000
+//
+
+ if ( (((ULONG)(PciData->u.type0.BaseAddresses[j]) & ~0x3) | 0x01) != 0x3bf0001 ) {
+
+ BaseAddresses[j] = 0xFFFFFFFF;
+
+ HalpWritePCIConfig (BusNumber, PciSlot,(PUCHAR)(&(BaseAddresses[j])), Offset, sizeof(LONG));
+ HalpReadPCIConfig (BusNumber, PciSlot, (PUCHAR)(&(BaseAddresses[j])), Offset, sizeof(LONG));
+
+
+ BaseAd = BaseAddresses[j];
+
+ if (BaseAd) {
+
+ //
+ // calculate the length necessary -
+ // memory : the four less significant bits are only indicators
+ // IO : the two less significant bits are indicators
+ //
+
+ length = 1 << ( BaseAd & PCI_ADDRESS_IO_SPACE ? 2 : 4); // mask the indicator bits
+
+ while ( !( BaseAd & length ) && length ) {
+ length <<= 1;
+ }
+
+ // now length => less significant bit set to 1.
+
+ // scan for the most significant bit set to 1
+
+ if (BaseAd & PCI_ADDRESS_IO_SPACE) {
+
+ memtype = 0;
+ BaseAd2 = (ULONG)(PciData->u.type0.BaseAddresses[j]) & ~0x3;
+// BaseAd2 |= PCI_IO_BASE;
+
+ CmDescriptor->Type = CmResourceTypePort;
+ CmDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ CmDescriptor->Flags = CM_RESOURCE_PORT_IO;
+
+ CmDescriptor->u.Port.Length = length;
+ CmDescriptor->u.Port.Start.LowPart = BaseAd2;
+
+ } else {
+
+ memtype = BaseAd & PCI_ADDRESS_MEMORY_TYPE_MASK;
+ BaseAd2 = (ULONG)(PciData->u.type0.BaseAddresses[j]) & ~0xf;
+
+ CmDescriptor->Type = CmResourceTypeMemory;
+ CmDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+ CmDescriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+
+ CmDescriptor->u.Memory.Length = length;
+ CmDescriptor->u.Memory.Start.LowPart = BaseAd2;
+ }
+
+ CmRes->List[0].PartialResourceList.Count++;
+ CmDescriptor++;
+
+ HalpWritePCIConfig (BusNumber, PciSlot, (PUCHAR)(&(PciData->u.type0.BaseAddresses[j])), Offset, sizeof(ULONG));
+
+ }
+ } else {
+
+ DebugPrint(("HalAssignResources : skip 0x3bf0001\n"));
+ }
+ }
+
+
+ //
+ // Setup the resource list.
+ // Count only the acquired resources.
+ //
+
+ *pAllocatedResources = CmRes;
+ cnt = CmRes->List[0].PartialResourceList.Count;
+ len = sizeof (CM_RESOURCE_LIST) +
+ cnt * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
+
+#if DBG
+ DbgPrint("HalAssignSlotResources: Acq. Resourses = %d (len %x list %x\n)",
+ cnt, len, *pAllocatedResources);
+#endif
+
+ //
+ // Report the IO resource assignments
+ //
+
+ if (!DeviceObject) {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ *pAllocatedResources, // DriverList
+ len, // DriverListSize
+ DeviceObject, // DeviceObject
+ NULL, // DeviceList
+ 0, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ } else {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ NULL, // DriverList
+ 0, // DriverListSize
+ DeviceObject,
+ *pAllocatedResources, // DeviceList
+ len, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ }
+
+ if (NT_SUCCESS(status) && conflict) {
+
+ //
+ // IopReportResourceUsage saw a conflict?
+ //
+
+#if DBG
+ DbgPrint("HalAssignSlotResources: IoAssignResources detected a conflict: %x\n",
+ status);
+#endif
+ status = STATUS_CONFLICTING_ADDRESSES;
+
+ if (!DeviceObject) {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ (PCM_RESOURCE_LIST) &i, // DriverList
+ sizeof (i), // DriverListSize
+ DeviceObject,
+ NULL, // DeviceList
+ 0, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ } else {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ NULL, // DriverList
+ 0, // DriverListSize
+ DeviceObject,
+ (PCM_RESOURCE_LIST) &i, // DeviceList
+ sizeof (i), // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ }
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+ if (!NT_SUCCESS(status)) {
+#if DBG
+ DbgPrint("HalAssignSlotResources: IoAssignResources failed: %x\n", status);
+#endif
+ if (!DeviceObject) {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ (PCM_RESOURCE_LIST) &i, // DriverList
+ sizeof (i), // DriverListSize
+ DeviceObject,
+ NULL, // DeviceList
+ 0, // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ } else {
+ status = IoReportResourceUsage (
+ DriverClassName,
+ DriverObject, // DriverObject
+ NULL, // DriverList
+ 0, // DriverListSize
+ DeviceObject,
+ (PCM_RESOURCE_LIST) &i, // DeviceList
+ sizeof (i), // DeviceListSize
+ FALSE, // override conflict
+ &conflict // conflicted detected
+ );
+ }
+
+ ExFreePool (*pAllocatedResources);
+ *pAllocatedResources = NULL;
+ }
+
+// ExFreePool (WorkingPool);
+
+ return status;
+
+}
+
+
+/*++
+
+Routine Description:
+
+Arguments:
+
+Return Value:
+
+
+--*/
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN ULONG BusNumber,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ )
+{
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PCI_SLOT_NUMBER PciSlot;
+ PPCI_COMMON_CONFIG PciData;
+ LARGE_INTEGER liIo, liMem;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_LIST ResourceList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG alt, cnt;
+
+ return STATUS_SUCCESS;
+
+ liIo = RtlConvertUlongToLargeInteger (PCI_MAX_IO_ADDRESS);
+ liMem = RtlConvertUlongToLargeInteger (PCI_MAX_MEMORY_ADDRESS);
+
+ //
+ // First, shrink to limits
+ //
+
+ HalpAdjustResourceListUpperLimits (pResourceList,
+ liIo, // IO Maximum Address
+ liMem, // Memory Maximum Address
+ PCI_MAX_INTERRUPT_VECTOR, // irq
+ 0xffff); // dma
+
+ //
+ // Fix any requested IRQs for this device to be the
+ // support value for this device.
+ //
+
+ PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber),
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ HalGetBusData ( PCIConfiguration,
+ BusNumber,
+ PciSlot.u.AsULONG,
+ PciData,
+ PCI_COMMON_HDR_LENGTH);
+
+ if (PciData->VendorID == PCI_INVALID_VENDORID || PCI_CONFIG_TYPE (PciData) != 0) {
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+
+ CompleteList = *pResourceList;
+ ResourceList = CompleteList->List;
+
+ for (alt=0; alt < CompleteList->AlternativeLists; alt++) {
+
+ Descriptor = ResourceList->Descriptors;
+ for (cnt = ResourceList->Count; cnt; cnt--) {
+
+ switch (Descriptor->Type) {
+
+ case CmResourceTypeInterrupt:
+
+ //
+ // Interrupt lines on a PCI device can not move.
+ // Make sure the request fits within the PCI device's
+ // requirements.
+ //
+
+ if (Descriptor->u.Interrupt.MinimumVector > PciData->u.type0.InterruptLine ||
+ Descriptor->u.Interrupt.MaximumVector < PciData->u.type0.InterruptLine) {
+
+ //
+ // descriptor doesn't fit requirements
+ //
+
+ return STATUS_UNSUCCESSFUL;
+
+ }
+
+ //
+ // Fix the interrupt at the HAL programed routing
+ //
+
+ Descriptor->u.Interrupt.MinimumVector = PciData->u.type0.InterruptLine;
+ Descriptor->u.Interrupt.MaximumVector = PciData->u.type0.InterruptLine;
+ break;
+
+ case CmResourceTypePort:
+ break;
+
+ case CmResourceTypeMemory:
+
+ //
+ // Check for prefetchable memory
+ //
+
+ if ( Descriptor->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE)
+ {
+ // Set upper limit to max dense space address
+
+ Descriptor->u.Memory.MinimumAddress.HighPart = 0;
+ Descriptor->u.Memory.MinimumAddress.LowPart =
+ PCI_MIN_DENSE_MEMORY_ADDRESS;
+
+ Descriptor->u.Memory.MaximumAddress.HighPart = 0;
+ Descriptor->u.Memory.MaximumAddress.LowPart =
+ PCI_MAX_DENSE_MEMORY_ADDRESS;
+ }
+
+ break;
+
+ default:
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ //
+ // Next descriptor
+ //
+
+ Descriptor++;
+
+ }
+
+ //
+ // Next Resource List
+ //
+
+ ResourceList = (PIO_RESOURCE_LIST) Descriptor;
+
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+/*++
+
+Routine Description:
+
+
+--*/
+
+VOID
+HalpAdjustResourceListUpperLimits (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN LARGE_INTEGER MaximumPortAddress,
+ IN LARGE_INTEGER MaximumMemoryAddress,
+ IN ULONG MaximumInterruptVector,
+ IN ULONG MaximumDmaChannel
+ )
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_LIST ResourceList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG alt, cnt;
+
+
+ //
+ // Walk each ResourceList and shrink any values to system limits
+ //
+
+ CompleteList = *pResourceList;
+ ResourceList = CompleteList->List;
+
+ for (alt=0; alt < CompleteList->AlternativeLists; alt++) {
+
+ Descriptor = ResourceList->Descriptors;
+ for (cnt = ResourceList->Count; cnt; cnt--) {
+
+
+ //
+ // Make sure descriptor limits fall within the
+ // CompleteList->InterfaceType & CompleteList->BusNumber.
+ //
+ //
+
+ switch (Descriptor->Type) {
+
+ case CmResourceTypePort:
+
+ if (Descriptor->u.Port.MaximumAddress.QuadPart >
+ MaximumPortAddress.QuadPart) {
+
+ Descriptor->u.Port.MaximumAddress = MaximumPortAddress;
+ }
+ break;
+
+ case CmResourceTypeInterrupt:
+
+ if (Descriptor->u.Interrupt.MaximumVector > MaximumInterruptVector ) {
+
+ Descriptor->u.Interrupt.MaximumVector = MaximumInterruptVector;
+ }
+ break;
+
+ case CmResourceTypeMemory:
+
+ if (Descriptor->u.Memory.MaximumAddress.QuadPart >
+ MaximumMemoryAddress.QuadPart) {
+
+ Descriptor->u.Memory.MaximumAddress = MaximumMemoryAddress;
+ }
+ break;
+
+ case CmResourceTypeDma:
+ if (Descriptor->u.Dma.MaximumChannel > MaximumDmaChannel ) {
+
+ Descriptor->u.Dma.MaximumChannel = MaximumDmaChannel;
+ }
+ break;
+
+ }
+
+ //
+ // Next descriptor
+ //
+
+ Descriptor++;
+
+ }
+
+ //
+ // Next Resource List
+ //
+
+ ResourceList = (PIO_RESOURCE_LIST) Descriptor;
+
+ }
+
+}
+
+
diff --git a/private/ntos/nthals/halsnip/mips/snipbus.h b/private/ntos/nthals/halsnip/mips/snipbus.h
new file mode 100644
index 000000000..f1ba64346
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/snipbus.h
@@ -0,0 +1,104 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/snipbus.h,v 1.2 1995/11/02 11:04:33 flo Exp $")
+/*+++
+
+Copyright (c) 1993-1994 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ PCIdef.h
+
+Abstract:
+
+ Hal specific PCI bus structures */
+
+
+#define PCI_MAX_LOCAL_DEVICE 32
+#define PCI_MAX_BUS_NUMBER 250
+#define PCI_MAX_IO_ADDRESS 0x1FFFFFFF
+#define PCI_MAX_MEMORY_ADDRESS 0x1FFFFFFF
+#define PCI_MAX_SPARSE_MEMORY_ADDRESS PCI_MAX_MEMORY_ADDRESS
+#define PCI_MIN_DENSE_MEMORY_ADDRESS PCI_MEMORY_PHYSICAL_BASE
+#define PCI_MAX_DENSE_MEMORY_ADDRESS PCI_MAX_MEMORY_ADDRESS
+#define PCI_MAX_INTERRUPT_VECTOR 0x100
+
+#define PCI_CONFIG_TYPE(PciData) ((PciData)->HeaderType & ~PCI_MULTIFUNCTION)
+
+//
+// Define PciConfigAddr register structure
+//
+typedef struct _PCI_CONFIG_ADDR {
+ ULONG Type : 2;
+ ULONG RegisterNumber : 6;
+ ULONG FunctionNumber : 3;
+ ULONG DeviceNumber : 5;
+ ULONG BusNumber : 8;
+ ULONG Reserved : 7;
+ ULONG Enable : 1;
+} PCI_CONFIG_ADDR, *PPCI_CONFIG_ADDR;
+
+//
+// Define PCI configuration cycle types.
+//
+typedef enum _PCI_CONFIGURATION_TYPES {
+ PciConfigTypeInvalid = -1,
+ PciConfigType0 = 0,
+ PciConfigType1 = 1
+} PCI_CONFIGURATION_TYPES, *PPCI_CONFIGURATION_TYPES;
+
+//
+// Define PCI cycle/command types.
+//
+
+typedef enum _PCI_COMMAND_TYPES{
+ PciCommandInterruptAcknowledge = 0x0,
+ PciCommandSpecialCycle = 0x1,
+ PciCommandIoRead = 0x2,
+ PciCommandIoWrite = 0x3,
+ PciCommandMemoryRead = 0x6,
+ PciCommandMemoryWrite = 0x7,
+ PciCommandConfigurationRead = 0xa,
+ PciCommandConfigurationWrite = 0xb,
+ PciCommandMemoryReadMultiple = 0xc,
+ PciCommandDualAddressCycle = 0xd,
+ PciCommandMemoryReadLine = 0xe,
+ PciCommandMemoryWriteAndInvalidate = 0xf,
+ MaximumPciCommand
+} PCI_COMMAND_TYPES, *PPCI_COMMAND_TYPES;
+
+
+//
+// PCI platform-specific functions
+//
+
+VOID
+HalpInitializePCIBus (
+ VOID
+ );
+
+VOID
+HalpAdjustResourceListUpperLimits (
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
+ IN LARGE_INTEGER MaximumPortAddress,
+ IN LARGE_INTEGER MaximumMemoryAddress,
+ IN ULONG MaximumInterruptVector,
+ IN ULONG MaximumDmaChannel
+ );
+
+NTSTATUS
+HalpAdjustPCIResourceList (
+ IN ULONG BusNumber,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+NTSTATUS
+HalpAdjustEisaResourceList (
+ IN ULONG BusNumber,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
+NTSTATUS
+HalpAdjustIsaResourceList (
+ IN ULONG BusNumber,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
+ );
+
diff --git a/private/ntos/nthals/halsnip/mips/snipci.h b/private/ntos/nthals/halsnip/mips/snipci.h
new file mode 100644
index 000000000..0a4651ebe
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/snipci.h
@@ -0,0 +1,366 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/snipci.h,v 1.6 1996/02/23 17:55:12 pierre Exp $")
+/*+++
+
+Copyright (c) 1993-1994 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ PCIdef.h
+
+Abstract:
+
+ This file describes hardware addresses
+ for SNI PCI machines.
+
+
+
+---*/
+
+#ifndef _PCIDEF_
+#define _PCIDEF_
+
+
+// ---------------------
+// desktop and minitower -
+// ---------------------
+
+
+//
+// define various masks for the interrupt sources register
+//
+
+/*
+ The interrupt Source Register on a PCI minitower or desktop has the following bits:
+
+ 7 6 5 4 3 2 1 0
+ +-------------------------------+
+ | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 Low Activ; 1 High activ; x not connected
+ +-------------------------------+
+ |________ INT2 Interrupt (Push button, high temp, pci asic)
+ |____________ PCI_INTD
+ |________________ PCI_INTC
+ |____________________ PCI_INTB
+ |________________________ PCI_INTA
+ |____________________________ EISA_INT
+ |________________________________ SCSI_INT
+ |____________________________________ ETHERNET_INT
+
+
+ The second source for Interrupt Information is the MachineStatusRegister, which has the following bits:
+
+ 7 6 5 4 3 2 1 0
+ +-------------------------------+
+ | x | 0 | 0 | 1 | x | 0 | 0 | 0 | 0 Low Activ; 1 High activ; x not connected
+ +-------------------------------+
+ |________ Power Off Request (only RM200)
+ |____________ ASIC int
+ |________________ PushButton
+ |________________________ NMI
+ |____________________________ Power Management ie system wakeup (only rm200)
+ |________________________________ High Temperature
+*/
+
+#define PCI_INTERRUPT_MASK 0xdf
+#define PCI_INT2_MASK 0x01 // push-button, high temp, asic...
+#define PCI_INTD_MASK 0x02
+#define PCI_INTC_MASK 0x04
+#define PCI_INTB_MASK 0x08
+#define PCI_INTA_MASK 0x10
+#define PCI_EISA_MASK 0x20
+#define PCI_SCSI_MASK 0x40
+#define PCI_NET_MASK 0x80
+
+#define PCI_MSR_MASK_D 0x67
+#define PCI_MSR_MASK_MT 0x46
+#define PCI_MSR_POFF_MASK 0x01
+#define PCI_MSR_ASIC_MASK 0x02
+#define PCI_MSR_PB_MASK 0x04
+#define PCI_MSR_NMI 0x10 // NMI from the EISA controller
+#define PCI_MSR_TEMP_MASK 0x40 // OverTemperature Interrupt in the MSR (RM400MT only) (high active)
+#define PCI_MSR_PMGNT_MASK 0x20 // power management (system wake-up)
+
+#define PCI_NVMEM_PHYSICAL_BASE 0x1ff00000 // physical base of nonvolatile RAM and RTC
+
+//
+// SNI ASIC registers
+//
+
+#define PCI_UCONF_REGISTER 0xbfff0000
+#define PCI_IOADTIMEOUT2_REGISTER 0xbfff0008
+#define PCI_IOMEMCONF_REGISTER 0xbfff0010
+#define PCI_IOMMU_REGISTER 0xbfff0018
+#define PCI_IOADTIMEOUT1_REGISTER 0xbfff0020
+#define PCI_DMAACCESS_REGISTER 0xbfff0028
+#define PCI_DMAHIT_REGISTER 0xbfff0030
+#define PCI_ERRSTATUS_REGISTER 0xbfff0038
+#define PCI_MEMSTAT_ECCERR (1<<0)
+#define PCI_MEMSTAT_ECCSINGLE (1<<3)
+#define PCI_MEMSTAT_PARERR (1<<4)
+#define PCI_ERRADDR_REGISTER 0xbfff0040
+#define PCI_SYNDROME_REGISTER 0xbfff0048
+#define PCI_ITPEND_REGISTER 0xbfff0050
+#define PCI_ASIC_ECCERROR (1<<8)
+#define PCI_ASIC_TRPERROR (1<<9)
+#define PCI_ASIC_IOTIMEOUT (1<<7)
+#define PCI_IRQSEL_REGISTER 0xbfff0058
+#define PCI_TESTMEM_REGISTER 0xbfff0060
+#define PCI_ECCREG_REGISTER 0xbfff0068
+#define PCI_CONF_ADDR_REGISTER 0xbfff0070 // (EISA_IO + 0xcf8)
+#define PCI_ASIC_ID_REGISTER 0xbfff0078 // Read
+#define PCI_SOFT_RESET_REGISTER 0xbfff0078 //Write
+#define PCI_PIA_OE_REGISTER 0xbfff0080
+#define PCI_PIA_DATAOUT_REGISTER 0xbfff0088
+#define PCI_PIA_DATAIN_REGISTER 0xbfff0090
+#define PCI_CACHECONF_REGISTER 0xbfff0098
+#define PCI_INVSPACE_REGISTER 0xbfff00A0
+#define PCI_PCICONF_REGISTER 0xbfff0100
+
+//
+// System dependant registers
+//
+
+#define PCI_MSR_PHYSICAL_ADDR 0x1fd00000 // machine status register
+#define PCI_MSR_ADDR 0xbfd00000 // machine status register | KSEG1
+#define PCI_CSWITCH_PHYSICAL_ADDR 0x1fd10000 // DIP switch register
+#define PCI_CSWITCH_ADDR 0xbfd10000 // DIP switch register | KSEG1
+#define PCI_INTERRUPT_SOURCE_PHYSICAL_BASE 0x1fd20000 // physical base of interrupt source register
+#define PCI_INTERRUPT_SOURCE_REGISTER 0xbfd20000 // physical base | KSEG1_BASE
+#define PCI_CLR_TMP_PHYSICAL_ADDR 0x1fd40000 // Clear Temperature Register
+#define PCI_CLR_TMP_ADDR 0xbfd40000 // Clear Temperature Register | KSEG1
+#define PCI_MCR_PHYSICAL_ADDR 0x1fd80000 // MachineConfigRegister
+#define PCI_MCR_ADDR 0xbfd80000 // MachineConfigRegister | KSEG1
+#define PCI_LED_PHYSICAL_ADDR 0x1fda0000 // LED Register physical
+#define PCI_LED_ADDR 0xbfda0000 // LED Register | KSEG1_BASE
+#define PCI_ISA_MAP_PHYSICAL_BASE 0x1fdb0000 // physical base of ISA map register (for BusMaster Devices)
+#define PCI_ISA_MAP 0xbfdb0000 // physical base | KSEG1_BASE
+#define PCI_CSRSTBP_PHYSICAL_ADDR 0x1fdc0000 // reset dbg button int
+#define PCI_CSRSTBP_ADDR 0xbfdc0000 // reset dbg button int
+#define PCI_CLRPOFF_PHYSICAL_ADDR 0x1fdd0000 // RM200 only
+#define PCI_CLRPOFF_ADDR 0xbfdd0000 // RM200 only
+#define PCI_PWDN_PHYSICAL_ADDR 0x1fdf0000 // RM200 only
+#define PCI_PWDN_ADDR 0xbfdf0000 // RM200 only
+#define PCI_MCR_SOFTRESET 0xdf // bit 6 set to zero
+#define PCI_MCR_POWEROFF 0xfd // bit 2 set to zero
+
+//
+// RealTimeClock Chip
+//
+
+#define PCI_REAL_TIME_CLOCK_ADDRESS 0x14000070 // physical base of RTC
+#define PCI_REAL_TIME_CLOCK 0xb4000070 // physical base of RTC | KSEG1_BASE
+
+#define RTC_ADDR_PCIMT PCI_REAL_TIME_CLOCK
+#define RTC_DATA_PCIMT PCI_REAL_TIME_CLOCK + 1
+
+//
+// Standard PCI addresses
+//
+
+#define PCI_IO_PHYSICAL_BASE 0x14000000
+#define PCI_IO_BASE 0xb4000000
+#define PCI_MEMORY_PHYSICAL_BASE 0x18000000 // memory area (cpu 0x18... chip 0x18...)
+#define PCI_MEMORY_BELOW1M_PHYSICAL_BASE 0x10000000 // for memory below 1Mb (cpu 0x10... chip 0x00...)
+#define PCI_MEMORY_BASE 0xb8000000
+
+#define PCI_CONF_DATA_REGISTER (PCI_IO_BASE + 0xcfc)
+
+#define PCI_IOMEMCONF_ENIOTMOUT (1 <<21 )
+#define PCI_IOMEMCONF_FORCE_ECC (1 <<29 )
+#define PCI_IOMEMCONF_ENCHKECC (1 <<30 )
+
+#define PCI_ECCTEST_REGISTER (1 <<30 )
+
+// def for PCI_MSR_REGISTER
+
+#define PCI_MSR_REV_ASIC (1 <<3 )
+
+// def for PCI_IRQSEL_REGISTER
+
+#define PCI_IRQSEL_MASK 0x380 // enable IOTIMEOUT ECCERROR TRPERROR
+#define PCI_IRQSEL_TIMEOUTMASK 0x80 // enable IOTIMEOUT
+#define PCI_IRQSEL_INT 0x803ff // Int line = 0 for IOTIMOUT, ECCERROR and TRPERROR
+
+//
+// RM300 extra timer (on board)
+//
+
+#define PCI_EXTRA_TIMER_PHYSICAL_ADDR 0x1fde0000 // Timer for system clock
+#define PCI_EXTRA_TIMER_ADDR 0xbfde0000 // Timer for system clock | KSEG1_BASE
+#define PCI_EXTRA_TIMER_ACK_ADDR 0xbfd90000 // reset extra Timer Interrupt | KSEG1_BASE
+
+//
+// Definitions for 82374 Bridge PCI_EISA
+//
+
+#define PCI_ESC_ADDR 0xb4000022
+#define PCI_ESC_DATA 0xb4000023
+#define PCI_ESC_ID_82374 0x2
+#define PCI_REV_ID_82374 0x8
+
+#define REV_ID_82374_SB 0x3
+
+
+// -------------------------
+// definitions for PCI Tower -
+// -------------------------
+
+
+
+#define PCI_TOWER_CONF_ADDR_REGISTER (PCI_IO_BASE + 0xcf8)
+#define PCI_TOWER_LED_ADDR PCI_TOWER_CPU_STATUS
+#define PCI_TOWER_LED_MASK 0xFFFCFFFC
+
+//
+// MAUI MP_BUS Configuration/Status
+//
+
+#define PCI_TOWER_MP_BUS_CONFIG 0xbfff0000
+
+#define PCI_TOWER_GEN_INTERRUPT 0xbfff0008
+#define PCI_TOWER_INTERRUPT_SOURCE_REGISTER PCI_TOWER_GEN_INTERRUPT
+
+// define various mask for interrupt
+
+
+#define PCI_TOWER_EISA_MASK 0x00400000
+#define PCI_TOWER_SCSI1_MASK 0x00100000
+#define PCI_TOWER_SCSI2_MASK 0x00200000
+#define PCI_TOWER_INTA_MASK 0x00010000
+#define PCI_TOWER_INTB_MASK 0x00020000
+#define PCI_TOWER_INTC_MASK 0x00040000
+#define PCI_TOWER_INTD_MASK 0x00080000
+#define PCI_TOWER_MP_BUS_MASK 0x00000003
+#define PCI_TOWER_C_PARITY_MASK 0x00000001
+#define PCI_TOWER_C_REGSIZE 0x00000002
+#define PCI_TOWER_M_ECC_MASK 0x00000004
+#define PCI_TOWER_M_ADDR_MASK 0x00000008
+#define PCI_TOWER_M_SLT_MASK 0x00000010
+#define PCI_TOWER_M_CFG_MASK 0x00000020
+#define PCI_TOWER_M_RC_MASK 0x00000040
+#define PCI_TOWER_D_INDICATE_MASK 0x00000080
+#define PCI_TOWER_D_ERROR_MASK 0x00000100
+#define PCI_TOWER_P_ERROR_MASK 0x00000200
+
+#define PCI_TOWER_MP_BUS_ERROR_STATUS 0xbfff0010
+#define PCI_TOWER_MP_BUS_ERROR_ADDR 0xbfff0018
+#define PCI_TOWER_MP_BUS_PCI_LOCK 0xbfff0020
+#define MP_BUS_PCI_LOCK_REQ 0x2
+#define MP_BUS_PCI_LOCK_ACK 0x1
+
+//
+// MAUI Memory Configuration registers
+//
+
+#define PCI_TOWER_MEM_SLOT_0 0xbfff1000
+#define PCI_TOWER_MEM_SLOT_1 0xbfff1008
+#define PCI_TOWER_MEM_SLOT_2 0xbfff1010
+#define PCI_TOWER_MEM_SLOT_3 0xbfff1018
+#define PCI_TOWER_MEM_SLOT_4 0xbfff1020
+#define PCI_TOWER_MEM_SLOT_5 0xbfff1028
+#define PCI_TOWER_MEM_SLOT_6 0xbfff1030
+#define PCI_TOWER_MEM_SLOT_7 0xbfff1038
+
+#define PCI_TOWER_MEM_CONTROL_0 0xbfff1040
+
+#define ERROR_COUNTER_MASK 0xff000000
+#define ERROR_COUNTER_INITVALUE 0xff0000 // to get overflow with ffff errors
+#define PCI_TOWER_MEM_CONTROL_1 0xbfff1048
+#define PCI_TOWER_MEM_CONTROL_2 0xbfff1050
+
+#define PCI_TOWER_MEM_CONFIG 0xbfff1058
+#define PCI_TOWER_MEM_ERROR_DATA_H 0xbfff1060
+#define PCI_TOWER_MEM_ERROR_DATA_L 0xbfff1068
+#define PCI_TOWER_MEM_ERROR_ECC 0xbfff1070
+#define PCI_TOWER_MEM_ERROR_ADDR 0xbfff1078
+#define MEM_ADDR_MASK 0xffffffe0
+
+// PCI configuration register
+#define PCI_TOWER_COMMAND_OFFSET 0x04
+#define PCI_TOWER_PM_LOCKSPACE 0x64
+#define PCI_TOWER_INTERRUPT_OFFSET 0x68
+#define PCI_TOWER_INITIATOR_ADDR_OFFSET 0x6c
+#define PCI_TOWER_TARGET_ADDR_OFFSET 0x70
+#define PCI_TOWER_PAR_0_OFFSET 0x74
+#define PCI_TOWER_PAR_1_OFFSET 0x78
+
+// definitions for command register
+
+#define EN_SERR 0x100
+
+// definitions for PCI_interrupt register
+
+#define PI_RESET 0xff000000 // reset interrupt in PCI_Interrupt
+
+#define PI_INITF 0x80000000 // mask for first Initiator interrupt in PCI_Interrupt
+#define PI_INITM 0x40000000 // mask for multi Initiator interrupt in PCI_Interrupt
+#define PI_TARGF 0x20000000 // mask for first Target interrupt in PCI_Interrupt
+#define PI_TARGM 0x10000000 // mask for multi Target interrupt in PCI_Interrupt
+#define PI_PARF 0x08000000 // mask for first Parity interrupt in PCI_Interrupt
+#define PI_PARM 0x04000000 // mask for multi Parity interrupt in PCI_Interrupt
+
+
+// Cause for initiator interrupts
+#define PI_READ_PCI 0x00200000 // from PCI
+#define PI_CPU_PCI_TIMO 0x00100000 // CPU to PCI timeout
+#define PI_CPU_PCI_ADDR 0x00080000 // address error
+#define PI_CPU_PCI_PAR 0x00020000 // initiator receives target abort
+#define PI_REC_TARGET_RETRY 0x00010000 // initiator receives target retry
+#define PI_REC_TARGET_DISCON 0x00008000 // initiator receives target disconnect
+// Cause for target interrupts
+#define PI_TARGET_MEM 0x00000080 // read error from memory
+#define PI_TARGET_RETRY 0x00000040 // target acts retry
+#define PI_TARGET_ADDR_PAR 0X00000020 // PCI_to_MEM addr parity
+#define PI_TARGET_DATA_PAR 0x00000010 // PCI_to_MEM data patity
+// enable interrupts
+#define EN_INIT_INT 0x00800000 // enable initiator interrupt
+#define EN_INIT_INTR 0x00400000 // enable initiator receives target disconnect
+#define EN_TARG_INTR 0x00000001 // enable target interrupt
+#define MASK_INT 0x00c00001
+//
+// DCU interface registers
+//
+
+#define PCI_TOWER_CONTROL 0xbfff2000
+
+#define PCI_TOWER_INDICATE 0xbfff2008
+
+// sources for DCU interrupt
+
+#define PCI_TOWER_DI_PB_MASK 0x00000100
+#define PCI_TOWER_DI_EISA_NMI 0x00000080
+#define PCI_TOWER_DI_AC_FAIL 0x00000004
+#define PCI_TOWER_DI_FAN_FAIL 0x00000008
+#define PCI_TOWER_DI_THERMO1_FAIL 0x00000010
+#define PCI_TOWER_DI_THERMO2_FAIL 0x00000020
+#define PCI_TOWER_DI_THERMO3_FAIL 0x00000040
+#define PCI_TOWER_DI_NT_FAN_FAIL 0x00000200
+#define PCI_TOWER_DI_SCSI1_TERM_FAIL 0x00000400
+#define PCI_TOWER_DI_SCSI2_INT_TERM_FAIL 0x00000800
+#define PCI_TOWER_DI_SCSI2_EXT_TERM_FAIL 0x00001000
+#define PCI_TOWER_DI_AUI_FAIL 0x00002000
+#define PCI_TOWER_DI_EXTRA_TIMER 0x00040000
+
+#define PCI_TOWER_DCU_CONTROL 0xbfff2000
+#define PCI_TOWER_DCU_STATUS 0xbfff2010
+#define PCI_TOWER_CPU_STATUS 0xbfff2018
+#define PCI_TOWER_DCU_ERROR 0xbfff2020
+
+// definitions for DCU error
+
+#define DE_CPU_ID 0x00006000
+#define DE_WRN 0x00001000
+#define DE_ADDR 0x00000fe0
+#define DE_ERR_ADDR 0x1fff2000
+
+// definitions for additional timer
+
+#define PCI_TOWER_TIMER_CMD_REG 0xbff03ffb
+#define PCI_TOWER_TIMER_COUNT_REG 0xbff03ffc
+#define PCI_TOWER_TIMER_VALUE_REG 0xbff03ffd
+
+// definitions for DCU Control
+
+#define DC_SWRESET 0x04000000
+#define DC_POWEROFF 0x02000000
+
+#endif // _PCIDEF_
diff --git a/private/ntos/nthals/halsnip/mips/sniregs.h b/private/ntos/nthals/halsnip/mips/sniregs.h
new file mode 100644
index 000000000..6f50d42f0
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/sniregs.h
@@ -0,0 +1,139 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/sniregs.h,v 1.1 1995/07/20 16:03:21 flo Exp $")
+/*++
+
+Copyright (c) 1993 SNI
+
+Module Name:
+
+ SNIregs.h
+
+Abstract:
+
+ This module is the header file that describes hardware structures
+ for the system board registers
+ The System addresses are found in SNIdef.h
+
+--*/
+
+#ifndef _SNIREGS_
+#define _SNIREGS_
+
+
+/*******************************************************************
+** Description of the R4x000 ASIC Chipset registers for SNI Machines
+**
+** 32 bits access only
+*******************************************************************/
+
+//
+// UCONF register
+//
+
+#define UCONF_ENSCMODE (1<<0) /* Secondary mode valid for R4000 */
+#define UCONF_ENEXTINT (1<<1) /* External interruption request */
+#define UCONF_NMI (1<<5) /* Interrupt level for NMI */
+#define UCONF_NMI_MSK (1<<6) /* Interrupt mask for NMI */
+#define UCONF_MDINT (1<<7) /* Select test mode for interruptions */
+#define UCONF_INT0_MSK (1<<8) /* Interrupt mask for INT0 ( eisa ) */
+#define UCONF_INT1_MSK (1<<9) /* Interrupt mask for INT1 ( scci 1, 2 ) */
+#define UCONF_INT2_MSK (1<<10) /* Interrupt mask for INT2 ( duart 2681 ) */
+#define UCONF_INT3_MSK (1<<11) /* Interrupt mask for INT3 ( timer 8254 ) */
+#define UCONF_INT4_MSK (1<<12) /* Interrupt mask for INT4 ( lance ) */
+#define UCONF_INT5_MSK (1<<13) /* Interrupt mask for INT5 ( dbg button ) */
+#define UCONF_INT0 (1<<14) /* Interrupt level for INT0 ( eisa ) */
+#define UCONF_INT1 (1<<15) /* Interrupt level for INT1 ( scci 1, 2 ) */
+#define UCONF_INT2 (1<<16) /* Interrupt level for INT2 ( duart 2681 ) */
+#define UCONF_INT3 (1<<17) /* Interrupt level for INT3 ( timer 8254 ) */
+#define UCONF_INT4 (1<<18) /* Interrupt level for INT4 ( lance ) */
+#define UCONF_INT5 (1<<19) /* Interrupt level for INT5 ( dbg button ) */
+#define UCONF_ENCPUHIT (1<<20) /* Enable address comparators */
+#define UCONF_ENCKDATA (1<<25) /* Enable check bits on data read */
+#define UCONF_SYSCMD0 (1<<26)
+#define UCONF_SYSCMD1 (1<<27)
+#define UCONF_SYSCMD2 (1<<28)
+#define UCONF_SYSCMD3 (1<<29)
+
+#define UCONF_INT UCONF_INT4|UCONF_INT0
+
+//
+// IOADTIMEOUT2 & IOADTIMEOUT1
+//
+
+#define IO_HOLD (1<<0) /* The R4K_CS request the IO bus */
+#define IO_HLDA (1<<1) /* The IO arbitrer acknowledge */
+#define IO_HWR (1<<3) /* Set to 1 for a write IO cycle */
+#define IO_HADR_MASK 0x3FFFFFF8 /* IO address (29:3) in progress */
+
+//
+// IOMEMCONF
+//
+
+
+#define IOMEM_RAFPER 8 /* Select Refresh Period */
+#define IOMEM_SELRC (1<<4) /* Select fast Ttc time on memory */
+#define IOMEM_SELRAF (1<<5) /* Select fast refresh precharge */
+#define IOMEM_SELSIDE (1<<6) /* Select dual side SIPS */
+#define IOMEM_SELDD (1<<7) /* Select DD pattern for memory */
+#define IOMEM_SEL16MB (1<<8) /* Select 16 Mb technology SIPS */
+#define IOMEM_SELDHOLD (1<<9) /* Select long hold time on data write */
+#define IOMEM_DISHLDA (1<<15) /* Mask arbitrer acknowledge */
+#define IOMEM_ENRDCMP (1<<16) /* Enable anticipation on IO read */
+#define IOMEM_ENWRCMP (1<<20) /* Enable bufferisation on IO write */
+#define IOMEM_ENIOTMOUT (1<<21) /* Enable output timeout */
+#define IOMEM_SELIODD (1<<22) /* Enable fast mode for IO burst DD */
+#define IOMEM_MDTIMEOUT (1<<23) /* Select short timeout */
+
+#define BANK_16 0
+#define BANK_32 IOMEM_SELSIDE
+#define BANK_64 IOMEM_SEL16MB
+#define BANK_128 IOMEM_SEL16MB | IOMEM_SELSIDE
+
+#define IOMEM_INIT IOMEM_RAFPER /* Initial register load */
+
+//
+// IOMMU
+//
+
+#define IOMMU_SWAP 0x7fff /* all segments swapped */
+#define IOMMU_BITS 0x0000 /* all segments 32 bits */
+
+
+//
+// DMACCESS & DMAHIT
+//
+
+#define DMA_COUNT_MASK 0x0000FFFF /* Count mask (15:0) */
+
+
+//
+// MACHINE STATUS REGISTER (MSR)
+//
+
+/* SNI machine status register information */
+
+#define MSR_VSYNC (1<<0) /* active high - video synchronization */
+#define MSR_TEMP (1<<1) /* active high - excessive temperature */
+#define MSR_LINEGOOD (1<<2) /* active low - power good */
+#define MSR_TIMER1 (1<<3) /* active low - int timer 1 */
+#define MSR_TIMER0 (1<<4) /* active low - int timer 0 */
+#define MSR_DBG_BUT (1<<5) /* active low - debug button int */
+#define MSR_TIMEOUT (1<<6) /* active low - timeout int */
+#define MSR_BAT_EN (1<<7) /* active high - batteries connected */
+
+//
+// MACHINE CONFIGURATION REGISTER (MCR)
+//
+
+/* SNI machine configuration register */
+
+#define MCR_TEMPBATACK (1<<0) /* active high - Disable / clear TEMP an Temp info */
+#define MCR_POWER_OFF (1<<1) /* active high - Stop power */
+#define MCR_STOP_BAT (1<<2) /* active high - Stop batteries */
+#define MCR_PODD (1<<3) /* active high - Select ODD parity R4K_CS */
+#define MCR_INRESET (1<<5) /* active high - Reset board */
+#define MCR_ENBREAK (1<<7) /* active high - Enable Break Duart B machine reset */
+
+
+#define LINEGOOD_L MSR_LINEGOOD /* high : powerfail */
+
+#endif // _SNIREGS_
diff --git a/private/ntos/nthals/halsnip/mips/unicache.s b/private/ntos/nthals/halsnip/mips/unicache.s
new file mode 100644
index 000000000..7be37c8ee
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/unicache.s
@@ -0,0 +1,1155 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/unicache.s,v 1.2 1995/11/02 11:04:33 flo Exp $")
+// TITLE("Cache Flush")
+//++
+//
+// Copyright (c) 1991-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// unicache.s
+//
+// Abstract:
+//
+// This module implements the code necessary for cache operations on
+// MIPS R4000 Uni Processor machine.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+
+//
+// Note: On the SNI machines all single processor machines are configured in the Firmware
+// tree with the size of the Primary cache matching the physical size.
+// So, even Orion CPU are configured with 16KB not 2 sets of 8Kb.
+// In this case wqe can use the Routines special for Orion CPU also for
+// R4400 CPU.
+//
+
+#if!defined(ORION)
+#define ORION
+#endif
+
+//
+// some bitmap defines to display cache activities via the LED's
+// in the SNI RM machines
+//
+
+#define SWEEP_DCACHE 0xc0 // 1100 0000
+#define FLUSH_DCACHE_PAGE 0x80 // 1000 0000
+#define PURGE_DCACHE_PAGE 0x40 // 0100 0000
+
+#define SWEEP_ICACHE 0x30 // 0011 0000
+#define PURGE_ICACHE_PAGE 0x10 // 0001 0000
+
+//
+// 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
+// HalpFlushDcachePageUni (
+// 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(HalpFlushDcachePageUni)
+
+#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 HalpFlushDcachePageUni
+
+ SBTTL("Purge Data Cache Page")
+//++
+//
+// VOID
+// HalpPurgeDcachePageUni (
+// 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(HalpPurgeDcachePageUni)
+
+#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 HalpPurgeDcachePageUni
+
+ SBTTL("Purge Instruction Cache Page")
+//++
+//
+// VOID
+// HalpPurgeIcachePageUni (
+// IN PVOID Color,
+// IN ULONG PageFrame,
+// IN ULONG Length
+// )
+//
+// Routine Description:
+//
+// This function purges (hit/invalidate) up to a page of 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(HalpPurgeIcachePageUni)
+
+#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 HalpPurgeIcachePageUni
+
+ SBTTL("Sweep Data Cache")
+//++
+//
+// VOID
+// HalpSweepDcacheUni (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/writeback/invalidate) the entire data cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepDcacheUni)
+
+#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
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5)
+#endif
+
+ 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
+
+#if defined(ORION)
+
+//
+// the size is configured on SNI machines as 16KB
+// we invalidate in both sets - so divide the configured size by 2
+//
+
+ srl t0,t0,1
+#endif
+ 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(ORION)
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0)
+#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:
+#if defined(ORION)
+ ENABLE_INTERRUPTS(t5)
+#endif
+
+ j ra // return
+
+ .end HalpSweepDcacheUni
+
+ 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
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5);
+#endif
+
+ 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(ORION)
+ cache INDEX_WRITEBACK_INVALIDATE_D,8192(a0) // do other set on Orion
+#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(ORION)
+ ENABLE_INTERRUPTS(t5);
+#endif
+ j ra // return
+
+ .end HalSweepDcacheRange
+
+ SBTTL("Sweep Instruction Cache")
+//++
+//
+// VOID
+// HalpSweepIcacheUni (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sweeps (index/invalidate) the entire instruction cache.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpSweepIcacheUni)
+
+#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
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5);
+#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
+
+#if defined(ORION)
+
+//
+// the size is configured on SNI machines as 16KB
+// we invalidate in both sets - so divide the configured size by 2
+//
+
+ srl t0,t0,1
+#endif
+ addu a1,a0,t0 // compute ending cache address
+ subu a1,a1,t1 // compute ending block address
+
+//
+// Sweep the primary instruction cache.
+//
+
+
+ .set noreorder
+ .set noat
+30: cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(ORION)
+ cache INDEX_INVALIDATE_I,8192(a0)
+#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(ORION)
+ ENABLE_INTERRUPTS(t5);
+#endif
+
+ j ra // return
+
+ .end HalpSweepIcacheUni
+
+ 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
+
+#if defined(ORION)
+ DISABLE_INTERRUPTS(t5);
+#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.
+//
+
+
+ .set noreorder
+ .set noat
+10:
+
+ cache INDEX_INVALIDATE_I,0(a0) // invalidate cache line
+
+#if defined(ORION)
+ cache INDEX_INVALIDATE_I,8192(a0) // do set B first on Orion
+#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(ORION)
+ ENABLE_INTERRUPTS(t5);
+#endif
+
+ j ra // return
+
+ .end HalSweepIcacheRange
+
+
+ SBTTL("Zero Page")
+//++
+//
+// VOID
+// HalpZeroPageUni (
+// 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(HalpZeroPageUni, 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 a1,ZpA1(sp) // save old 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
+//
+// 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,ZpA1(sp) // get old color bits
+ lw a1,ZpA2(sp) // get page frame number
+ li a2,PAGE_SIZE // set length of purge
+ jal HalPurgeDcachePage // purge data cache page
+
+//
+// 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.
+//
+
+
+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
+
+
+ .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
+
+
+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
+
+ .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 HalpZeroPageUni
+
+
+
+
+ LEAF_ENTRY(HalpPciEccCorrector)
+// a0 : offset
+// a1 : pfn
+// a2 : length
+
+ .set noreorder
+ .set noat
+ and a0,a0,PAGE_SIZE -1 // PageOffset
+ lw v0,KiPcr + PcAlignedCachePolicy(zero) // get cache policy
+ 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
+
+ ENABLE_INTERRUPTS(t5) // enable interrupts
+ .set noreorder
+ .set noat
+
+ 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
+ and t8,t0,t6 // compute starting virtual address
+ addu t9,t8,a2 // compute ending virtual address
+ subu t9,t9,t4 // compute ending loop address
+
+// beq zero,v0,40f // if eq, no second level cache
+
+//
+// Flush the secondary data cache.
+//
+
+20: lw t7,0(t8)
+ sw t7,0(t8)
+ cache HIT_WRITEBACK_INVALIDATE_SD,0(t8) // invalidate cache block
+
+ nop
+ nop
+
+ bne t8,t9,20b // if ne, more blocks to invalidate
+ addu t8,t8,t4 // compute next block address
+40:
+
+ j ra // return
+
+ .end HalpPciEccCorrector
+
+
diff --git a/private/ntos/nthals/halsnip/mips/vgadata.h b/private/ntos/nthals/halsnip/mips/vgadata.h
new file mode 100644
index 000000000..a996b85a7
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/vgadata.h
@@ -0,0 +1,420 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/vgadata.h,v 1.3 1995/11/02 11:04:33 flo Exp $")
+
+#define MAX_CRT 0x19
+#define GRAPH_MAX 0x9
+#define MAX_PALETTE 0x15
+
+// VGA constants
+
+#define REVERSE_ATTRIBUTE 0x17 // white on blue
+
+#define INIT_VGA_FONT() \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x02); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x04); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x04); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x06); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x05); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x08); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x06); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x01);
+
+#define EXIT_VGA_FONT() \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x02); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x03); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_IDX, 0x04); \
+ WRITE_REGISTER_UCHAR(VGA_SEQ_DATA, 0x02); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x04); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x00); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x05); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x10); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_IDX, 0x06); \
+ WRITE_REGISTER_UCHAR(VGA_GRAPH_DATA, 0x0e);
+
+
+//
+// Adresses for the Bt485 RamDac on the Orchid VLB and Diamond Viper board
+//
+
+#define Bt485_MASK ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c6))
+#define Bt485_ADDRRD ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c7))
+#define Bt485_ADDR ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c8))
+#define Bt485_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c9))
+#define Bt485_CR0 ((PVOID) ((ULONG)HalpVGAControlBase + 0x43c6))
+#define Bt485_ADDRCURRD ((PVOID) ((ULONG)HalpVGAControlBase + 0x43c7))
+#define Bt485_ADDRCUR ((PVOID) ((ULONG)HalpVGAControlBase + 0x43c8))
+#define Bt485_DATACUR ((PVOID) ((ULONG)HalpVGAControlBase + 0x43c9))
+#define Bt485_STATUS ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c6))
+#define Bt485_CR3 ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c6)) /* if enabled */
+#define Bt485_CURSORRAM ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c7))
+#define Bt485_CR1 ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c8))
+#define Bt485_CR2 ((PVOID) ((ULONG)HalpVGAControlBase + 0x83c9))
+#define Bt485_CURSOR_YL ((PVOID) ((ULONG)HalpVGAControlBase + 0xc3c6))
+#define Bt485_CURSOR_YH ((PVOID) ((ULONG)HalpVGAControlBase + 0xc3c7))
+#define Bt485_CURSOR_XL ((PVOID) ((ULONG)HalpVGAControlBase + 0xc3c8))
+#define Bt485_CURSOR_XH ((PVOID) ((ULONG)HalpVGAControlBase + 0xc3c9))
+
+// Some VGA Registers
+
+#define VGA_MISC_READ ((PVOID) ((ULONG)HalpVGAControlBase + 0x03cc))
+#define VGA_MISC_WRITE ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c2))
+#define VGA_SEQ_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c4))
+#define VGA_SEQ_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c5))
+#define VGA_CRT_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03d4))
+#define VGA_CRT_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03d5))
+#define VGA_ATC_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c0))
+#define VGA_ATC_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c0))
+#define VGA_GRAPH_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03ce))
+#define VGA_GRAPH_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03cf))
+#define VGA_ATC_FF ((PVOID) ((ULONG)HalpVGAControlBase + 0x03da))
+#define VGA_DAC_MASK ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c6))
+#define VGA_DAC_STATUS ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c7))
+#define VGA_DAC_WRITE_INDEX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c8))
+#define VGA_DAC_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c9))
+#define VGA_FEAT_CNTRL ((PVOID) ((ULONG)HalpVGAControlBase + 0x03ca))
+#define S3_ADVFUNC_CNTL ((PVOID) ((ULONG)HalpVGAControlBase + 0x4ae8))
+
+// the same registers as offset for use in SetHwMode()
+
+#define MISC_READ 0x03cc
+#define MISC_WRITE 0x03c2
+#define SEQ_IDX 0x03c4
+#define SEQ_DATA 0x03c5
+#define CRT_IDX 0x03d4
+#define CRT_DATA 0x03d5
+#define ATC_IDX 0x03c0
+#define ATC_DATA 0x03c0
+#define GRAPH_IDX 0x03ce
+#define GRAPH_DATA 0x03cf
+#define ATC_FF 0x03da
+#define DAC_MASK 0x03c6
+#define DAC_STATUS 0x03c7
+#define DAC_WRITE_INDEX 0x03c8
+#define DAC_DATA 0x03c9
+#define FEAT_CNTRL 0x03ca
+
+// S3 Advanced Function control register
+
+#define ADVFUNC_CNTL 0x4ae8
+
+#define MAGIC_REG1 0x46e8
+#define MAGIC_REG2 0x0102
+#define CIRRUS_MAGIC1 0x03c3
+#define CIRRUS_MAGIC2 0x0094
+
+//
+// "magic" registers to enable the Video System on VGA
+// for non Intel Systems
+//
+#define VGA_MAGIC_REG1 ((PVOID) ((ULONG)HalpVGAControlBase + 0x46e8))
+#define VGA_MAGIC_REG2 ((PVOID) ((ULONG)HalpVGAControlBase + 0x0102))
+#define CIRRUS_MAGIC_REG1 ((PVOID) ((ULONG)HalpVGAControlBase + 0x03c3))
+#define CIRRUS_MAGIC_REG2 ((PVOID) ((ULONG)HalpVGAControlBase + 0x0094))
+
+
+UCHAR base_colors[] = {
+ 0, 0, 0, // color 0 (black)
+ 0, 0, 42, // color 1 (drk. blue)
+ 0, 42, 0, // color 2 (olive)
+ 0, 42, 42, // color 3 ()
+42, 0, 0, // color 4 (brown)
+42, 0, 42, // color 5 (turquise)
+42, 21, 0, // color 6 (tundra )
+63, 63, 63, // color 7 (lt. grey(42,42,42 but we set it to white)
+21, 21, 21, // color 8 (drk. grey)
+21, 21, 63, // color 9 (blue)
+21, 63, 21, // color 10 (green)
+21, 63, 63, // color 11 (lt. blue)
+63, 0, 0, // color 12 (red)
+63, 0, 63, // color 13 (cyan)
+63, 63, 0, // color 14 (yellow)
+63, 63, 63 // color 15 (white)
+};
+
+//
+// this is an VGA 8x8 font (Codepage 437)
+//
+
+UCHAR font_8x8[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //0x00
+0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, //0x01
+0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, //0x02
+0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, //0x03
+0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00,
+0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c,
+0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c,
+0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00,
+0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff,
+0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
+0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff,
+0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
+0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18,
+0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0,
+0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0,
+0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99,
+0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00,
+0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
+0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18,
+0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
+0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00,
+0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78,
+0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00,
+0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff,
+0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00,
+0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
+0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00,
+0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
+0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00,
+0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00,
+0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00,
+0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00,
+0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
+0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00,
+0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00,
+0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00,
+0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
+0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
+0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
+0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
+0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00,
+0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00,
+0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00,
+0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00,
+0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00,
+0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00,
+0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00,
+0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00,
+0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00,
+0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
+0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00,
+0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
+0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
+0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00,
+0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, // =
+0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, // >
+0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, // ?
+0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, // @
+0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, // A
+0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, // B
+0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, // C
+0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, // D
+0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, // E
+0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00,
+0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00,
+0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00,
+0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00,
+0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00,
+0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00,
+0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
+0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00,
+0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00,
+0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
+0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00,
+0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00,
+0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00,
+0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00,
+0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
+0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00,
+0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00,
+0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00,
+0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00,
+0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
+0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00,
+0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
+0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
+0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00,
+0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
+0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00,
+0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
+0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00,
+0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78,
+0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
+0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
+0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00,
+0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
+0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
+0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0,
+0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
+0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00,
+0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00,
+0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00,
+0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
+0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
+0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00,
+0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00,
+0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
+0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00,
+0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00,
+0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
+0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00,
+0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
+0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78, // 8 bit codes 0x80
+0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, // 0x81 ü
+0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, // 0x82 é
+0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00, // 0x83 â
+0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, // 0x84 ä
+0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, // 0x85 à
+0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00, // 0x86°a
+0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38, // 0x87,c
+0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00, // 0x88 ê
+0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, // 0x89 ..e
+0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, // 0x8a è
+0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, // 0x8b ..i
+0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, // 0x8c î
+0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, // 0x8d ì
+0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, // 0x8e Ä
+0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00, // 0x8f °A
+0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00, // 0x90
+0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00, // 0x91
+0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00, // 0x92
+0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, // 0x93 ô
+0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, // 0x94 ö
+0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00, // 0x95 ò
+0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, // 0x96 û
+0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00, // 0x97 ù
+0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, // 0x98 ..y
+0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00, // 0x99 Ö
+0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, // 0x9a ü
+0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18, // 0x9b
+0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00, // 0x9c
+0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30, // 0x9d
+0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7, // 0x9e
+0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, // 0x9f
+0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
+0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
+0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
+0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
+0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00,
+0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00,
+0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00,
+0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
+0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00,
+0x38, 0x74, 0xaa, 0xba, 0xaa, 0x64, 0x38, 0x00, // (R)
+0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00,
+0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f,
+0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03,
+0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00,
+0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00,
+0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00,
+0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
+0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
+0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee,
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18,
+0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
+0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36,
+0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36,
+0x3c, 0x42, 0x99, 0xa1, 0xa1, 0x99, 0x42, 0x3c, // (c)
+0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36,
+0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00,
+0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00,
+0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
+0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36,
+0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36,
+0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
+0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36,
+0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
+0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00,
+0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00,
+0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36,
+0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36,
+0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18,
+0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
+0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
+0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00,
+0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0,
+0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
+0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00,
+0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00,
+0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00,
+0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0,
+0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00,
+0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc,
+0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00,
+0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00,
+0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00,
+0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00,
+0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0,
+0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00,
+0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
+0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00,
+0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00,
+0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00,
+0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00,
+0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18,
+0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70,
+0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00,
+0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00,
+0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c,
+0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
+0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+#define STORM_OFFSET 0x1c00
+#define STORM_MISC_W 0x3c2
+#define STORM_PCI_OPTION 0x40
+
+#define STORM_RAMDAC_OFFSET 0x3c00
+#define STORM_TVP3026_INDEX 0x00
+#define STORM_TVP3026_DATA 0x0a
+
+#define STORM_TVP3026_PIX_CLK_DATA 0x2d
+#define STORM_TVP3026_MEM_CLK_DATA 0x2e
+#define STORM_TVP3026_MCLK_CTL 0x39
+
+#define STORM_TVP3026_PLL_ADDR 0x2c
+#define STORM_TVP3026_PLL_RESET 0xff
+
+#define VGA_CRTCEXT_IDX ((PVOID) ((ULONG)HalpVGAControlBase + 0x03de))
+#define VGA_CRTCEXT_DATA ((PVOID) ((ULONG)HalpVGAControlBase + 0x03df))
+#define VGA_CRTCEXT0 0x00
+#define VGA_CRTCEXT1 0x01
+#define VGA_CRTCEXT2 0x02
+#define VGA_CRTCEXT3 0x03
+#define VGA_CRTCEXT4 0x04
+#define VGA_CRTCEXT5 0x05
+
+#define STORM_STATUS 0x214
diff --git a/private/ntos/nthals/halsnip/mips/x4clock.s b/private/ntos/nthals/halsnip/mips/x4clock.s
new file mode 100644
index 000000000..82df85dee
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/x4clock.s
@@ -0,0 +1,457 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/x4clock.s,v 1.6 1996/03/12 14:56:20 pierre Exp $")
+
+// TITLE("Interval and Profile Clock Interrupts")
+//++
+//
+// Copyright (c) 1991 Microsoft Corporation
+//
+// Module Name:
+//
+// x4clock.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interval and profile clock interrupts on a MIPS R4000 system.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//
+//--
+
+#include "halmips.h"
+#include "SNIdef.h"
+
+#define MPA_TIMER_MESSAGE 11 /* timer interrupt */
+
+
+ SBTTL("System Clock Interrupt")
+//++
+//
+// 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:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+
+ .struct 0
+CiArgs: .space 4 * 4 // saved arguments
+ .space 3 * 4 // fill
+CiRa: .space 4 // saved return address
+CiFrameLength: //
+
+ NESTED_ENTRY(HalpClockInterrupt, CiFrameLength, zero)
+
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ move a0,s8 // set address of trap frame
+ lw a1,HalpCurrentTimeIncrement
+ lw t0,__imp_KeUpdateSystemTime // update system time
+ jal t0 //
+
+//
+// we use this only when we have the machine up and running ...
+// LED's can show us something, what we do not see in the debugger
+//
+
+ la t0,HalpLedRegister // get current Value of LED Register
+ lw a0,0(t0)
+ addu a0,a0,1 // increment
+ sw a0,0(t0) // store and
+
+ lw t0,HalpIsTowerPci
+ beq t0,zero,2f
+ jal HalpPciTowerDisplayLed
+ b 3f
+
+2:
+ la t0, HalpLedAddress // get address of the variable
+ lw t0,0(t0) // get value
+ sb a0,0(t0) // display LSByte (set the LED)
+
+//
+// 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 new time increment is nonzero, then the new time
+// increment is moved to the next time increment and the timer is reprogramed
+//
+
+3: lw t0,KdDebuggerEnabled // get address of debugger enable
+ lw t1,HalpNewTimeIncrement // get new time increment
+ lw t2,HalpNextTimeIncrement // get the next increment value
+ lbu t0,0(t0) // get debugger enable flag
+ lw ra,CiRa(sp) // restore return address
+ or t4,t1,t0 // new interval count or debugger?
+ sw t2,HalpCurrentTimeIncrement // pipeline current increment value
+ bne zero,t4,10f // 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.
+//
+
+10: sw zero,HalpNewTimeIncrement // clear new time increment
+ beq zero,t1,15f // if eq, not interval count change
+ sw t1,HalpNextTimeIncrement // set next time increment value
+ move a0,t1 // prepare to call HalpProgramIntervalTimer
+ jal HalpProgramIntervalTimer // program timer chip ...
+15: 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
+ break BREAKIN_BREAKPOINT // break into the debugger
+
+40: lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra // return
+
+ .end HalpClockInterrupt
+
+
+ SBTTL("System Clock Interrupt - Processor N")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the extra interval timer in the slave processors. Its function is
+// to transfer control to the standard system routine to update the
+// execution time of the current thread and process.
+//
+// Note: We plan to use the extra timer for our MultiProcessor (SNI)Machine
+// MAYBE, if we have arbitrated interrupts, we have to acknowledge
+// this interrupt here and send an message to the other processors
+// (Quadro machine)
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ NESTED_ENTRY(HalpClockInterrupt1, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+ li a0,0x1000
+ jal HalpCheckSpuriousInt
+ beq v0,0,10f
+ lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra
+
+10:
+ li t0, PCI_EXTRA_TIMER_ACK_ADDR // get address of acknowledge register
+ sb zero,0(t0) // acknowledge timer interrupt
+
+ move a0,s8 // set address of trap frame
+ lw t1,__imp_KeUpdateRunTime // update system runtime
+ lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j t1 //
+ .end HalpClockInterrupt1
+
+ SBTTL("System Clock Interrupt - Processor N")
+//++
+//
+// Routine Description:
+//
+// This routine is entered as the result of an interrupt generated by
+// the extra interval timer in the slave processors. Its function is
+// to transfer control to the standard system routine to update the
+// execution time of the current thread and process.
+//
+// We use the extra timer for our MultiProcessor (SNI)Machine
+// we have to acknowledge
+// this interrupt here and send an message to the other processors
+// (Quadro machine)
+//
+// Arguments:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ NESTED_ENTRY(HalpClockInterruptPciTower, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+
+
+ //
+ // Send a "TIMER" ipi
+ //
+ lw a0,HalpIsMulti // test if more than 2 procs
+ li a1,2
+ slt a2,a1,a0
+ beq a2,0,10f // if no more than 2 proc , no need to send Ipi
+
+ li a0,0xc // send IPI to proc 2 and 3
+ li a1,MPA_TIMER_MESSAGE
+ jal HalpRequestIpi
+
+10: move a0,s8 // set address of trap frame
+ lw t1,__imp_KeUpdateRunTime // update system runtime
+ lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j t1 //
+ .end HalpClockInterruptPciTower
+
+
+ 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:
+//
+// s8 - Supplies a pointer to a trap frame.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ NESTED_ENTRY(HalpProfileInterrupt, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+// li a0,0x8000
+// jal HalpCheckSpuriousInt
+// beq v0,zero,10f
+// lw ra,CiRa(sp) // restore return address
+// addu sp,sp,CiFrameLength // deallocate stack frame
+// j ra
+
+10: .set noreorder
+ .set noat
+ mfc0 t1,count // get current count value
+ mfc0 t0,compare // get current comparison value
+ addu t1,t1,8 // factor in lost cycles
+ subu t1,t1,t0 // compute initial count value
+ mtc0 t0,compare // dismiss interrupt
+ mtc0 t1,count // set new count register value
+ .set at
+ .set reorder
+
+
+
+//
+// we prefer the MultiPro version, which also works on UniPro machines
+//
+
+ 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 //
+
+ 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
+ li a0,0x00
+ move a0,s8 // set address of trap frame
+ lw t4,__imp_KeProfileInterrupt // process profile interrupt
+ jal t4 //
+
+
+
+ jal HalpCheckSpuriousInt
+ lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra
+ .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
+
+ NESTED_ENTRY(HalpPciTowerDisplayLed, CiFrameLength, zero)
+
+ subu sp,sp,CiFrameLength // allocate stack frame
+ sw ra,CiRa(sp) // save return address
+
+ PROLOGUE_END
+
+
+ //
+ // code for PCI tower
+ //
+ li t5,8,
+ divu a0,t5
+ mfhi t4
+ li t5,1
+ .word 0x018d2004 # sllv a0,t5,t4
+
+
+// t4 -> temp-reg.
+// t5 -> low-reg. 32 bits
+// t6 -> high-reg. 32 bits
+
+ and t5,a0,0x01 # bit0 shift to bit0(LED0)
+
+ and t4,a0,0x02 # bit1 shift to bit16(LED1)
+ sll t4,t4,16-1
+ or t5,t5,t4
+
+ and t4,a0,0x04 # bit2 shift to bit32(LED2) -> bit0/high_reg.
+ srl t6,t4,2-0
+
+ and t4,a0,0x08 # bit3 shift to bit48(LED3) -> bit16/high_reg.
+ sll t4,t4,16-3
+ or t6,t6,t4
+
+ and t4,a0,0x10 # bit4 shift to bit1(LED4)
+ srl t4,t4,4-1
+ or t5,t5,t4
+
+ and t4,a0,0x20 # bit5 shift to bit17(LED5)
+ sll t4,t4,17-5
+ or t5,t5,t4
+
+ and t4,a0,0x40 # bit6 shift to bit33(LED6) -> bit1/high_reg.
+ srl t4,t4,6-1
+ or t6,t6,t4
+
+ and t4,a0,0x80 # bit7 shift to bit49(LED7) -> bit17/high_reg.
+ sll t4,t4,17-7
+ or t6,t6,t4
+
+ lw a1,HalpLedAddress
+ lw t4,0(a1)
+ and t4,t4,PCI_TOWER_LED_MASK # led mask
+ or t4,t4,t5 # t5 -> low 32 bits
+ sw t4,0(a1)
+ jal KeFlushWriteBuffer
+
+ lw a1,HalpLedAddress
+ lw t4,4(a1)
+ and t4,t4,PCI_TOWER_LED_MASK # led mask
+ or t4,t4,t6 # t6 -> high 32 bits
+ sw t4,4(a1)
+ jal KeFlushWriteBuffer
+ lw ra,CiRa(sp) // restore return address
+ addu sp,sp,CiFrameLength // deallocate stack frame
+ j ra
+
+ .end HalpPciTowerDisplayLed
+//
+// end code for PCI 1tower
+//
diff --git a/private/ntos/nthals/halsnip/mips/x4misc.s b/private/ntos/nthals/halsnip/mips/x4misc.s
new file mode 100644
index 000000000..c4c49fffd
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/x4misc.s
@@ -0,0 +1,410 @@
+#if defined(R4000)
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/x4misc.s,v 1.4 1996/02/23 17:55:12 pierre Exp $")
+
+// TITLE("Misc R4000 Functions")
+//++
+//
+// Copyright (c) 1994 Siemens Nixdorf Informationssysteme AG
+//
+// Module Name:
+//
+// x4misc.s
+//
+// Abstract:
+//
+// This module implements some R4000 basic register access routines
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+#include "SNIdef.h"
+#define STATUS_DE 0x10000 // Disable Cache error ands ECC Errors bit
+#define STATUS_IE 0x00001 // Interrupt Enable/Disable Bit
+#define STATUS_KX 0x80
+
+#define UNCACHED 0x2
+#define CACHABLE_NONCOHERENT 0x3
+#define CACHABLE_COHERENT_EXCLUSIVE 0x4
+#define CACHABLE_COHERENT_EXCLUSIVE_ON_WRITE 0x5
+#define CACHABLE_COHERENT_UPDATE_ON_WRITE 0x6
+
+ SBTTL("Get R4000 Status Register")
+//++
+//
+// ULONG
+// HalpGetStatusRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function returns the current value of the status register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The value of the Status register.
+//
+//--
+
+ LEAF_ENTRY(HalpGetStatusRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpGetStatusRegister
+
+ SBTTL("Set R4000 Status Register")
+//++
+//
+// ULONG
+// HalpSetStatusRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sets the status register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The previous value of the Status register.
+//
+//--
+
+ LEAF_ENTRY(HalpSetStatusRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,psr // get current (old)PSR
+ nop // fill
+ nop
+ nop
+ nop
+ mtc0 a0,psr
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpSetStatusRegister
+
+ SBTTL("Get R4000 Cause Register")
+//++
+//
+// ULONG
+// HalpGetCauseRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function returns the current value of the cause register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The value of the cause register.
+//
+//--
+
+ LEAF_ENTRY(HalpGetCauseRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,cause // get current cause
+ nop // fill
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpGetCauseRegister
+
+ SBTTL("Set R4000 Cause Register")
+//++
+//
+// ULONG
+// HalpSetCauseRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sets the Cause register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The previous value of the Cause register.
+//
+//--
+
+ LEAF_ENTRY(HalpSetCauseRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,cause // get current (old)Cause
+ nop // fill
+ nop
+ nop
+ nop
+ mtc0 a0,cause
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpSetCauseRegister
+
+ SBTTL("Get R4000 Config Register")
+//++
+//
+// ULONG
+// HalpGetConfigRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function returns the current value of the Config register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The value of the Config register.
+//
+//--
+
+ LEAF_ENTRY(HalpGetConfigRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,config // get current Config
+ nop // fill
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpGetConfigRegister
+
+ SBTTL("Set R4000 Config Register")
+//++
+//
+// ULONG
+// HalpSetConfigRegister(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function sets the R4000 Config register
+//
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The previous value of the Config register.
+//
+//--
+
+ LEAF_ENTRY(HalpSetConfigRegister)
+
+ .set noreorder
+ .set noat
+ mfc0 v0,config // get current (old)Config
+ nop // fill
+ nop
+ nop
+ nop
+ mtc0 a0,config
+ nop
+ nop
+ nop
+ nop
+ .set at
+ .set reorder
+
+ j ra // return
+
+ .end HalpSetConfigRegister
+#endif
+
+
+//++
+//
+// ULONG
+// HalpDisableInterrupts(
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function is called to disable interrupts after a PCI error interrupt,
+// The machine is then stopped by a KeBugCheckEx().
+// This is indispensable for MATROX boards....
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpDisableInterrupts)
+
+//
+// Perform power management enabling.
+//
+
+ .set noreorder
+ mfc0 v0,psr // get current PSR
+ nop // fill
+ and v0, v0, ~(STATUS_IE) // disable Interrupts
+ mtc0 v0,psr // enable interrupts
+
+ .set reorder
+10: j ra
+ .end HalpDisableInterrupts
+
+
+//++
+//
+// ULONG
+// HalpFindEccAddr(
+// ULONG Addr, // from ECC Error Asic Register
+// PVOID ErrStatusRegister, // register which indicates parity and Ecc error
+// PVOID ErrStatusBits // bits which indicates errors in the previous register
+// )
+//
+// Routine Description:
+//
+// This function is called to find the real physical address where the error occurs,
+// The Ecc Error Asic register contains the block address where the error address is.
+// To get ride of memory above 0x10000000, we use 64bits addressing capabilities of
+// the processor.
+// To detect the faulty address, we read all the block of data, word by word...
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFindEccAddr)
+
+
+ .set noreorder
+// adjust addr to a cache line
+ lw t4,KiPcr + PcFirstLevelDcacheFillSize(zero) // get 1st fill size
+ subu t3,t4,1
+ nor t3,t3,zero
+ and a0,a0,t3
+
+// generate 64 bits addr
+ mfc0 t1,psr // get current PSR saved in t1
+ nop // fill
+ and v0, t1, ~(STATUS_IE) // disable Interrupts
+// or v0, v0, PSR_KX // 64 bits adressing in kernel
+ mtc0 v0,psr // enable interrupts
+ nop
+ nop
+ nop
+
+ li t0,0x90000000
+ .word 0x0008403c // dsll32 t0,t0,zero
+ or a0,a0,t0 // beginning KSEG1 addr in 64bits
+ daddu t0,a0,t4 // ending KSEG1 addr in 64bits
+
+ or v0, v0, STATUS_KX // 64 bits adressing in kernel
+ mtc0 v0,psr
+ nop
+ nop
+ nop
+
+// reading loop
+1: lw t8,0(a0)
+ nop
+ sync
+
+ lw t8,0(a1) // PCI Error Status
+ nop
+ sync
+
+ and t9,t8,a2 // test memory/ecc error bits
+ nop
+ beq t9,zero,2f
+ nop
+// addr found
+ move v0,a0
+ j 10f
+ nop
+2: // addr not found => continue loop
+ daddiu a0,4 // word by word
+ bltu a0,t0,1b
+ nop
+ li v0,-1 // end of the loop - no addr found!
+
+10:
+ mtc0 t1,psr // enable interrupts + back to 32bits addressing
+ nop
+ nop
+ nop
+ .set reorder
+ j ra
+ .end HalpFindEccAddr
+
diff --git a/private/ntos/nthals/halsnip/mips/x4tb.s b/private/ntos/nthals/halsnip/mips/x4tb.s
new file mode 100644
index 000000000..4120525f4
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/x4tb.s
@@ -0,0 +1,110 @@
+#if defined(R4000)
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/x4tb.s,v 1.1 1995/07/20 16:04:27 flo Exp $")
+
+// TITLE("AllocateFree TB Entry")
+//++
+//
+// Copyright (c) 1992-1993 Microsoft Corporation
+//
+// Module Name:
+//
+// x4tb.s
+//
+// Abstract:
+//
+// This module implements allocates and frees fixed TB entries using the
+// wired register.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+//--
+
+#include "halmips.h"
+
+ SBTTL("Allocate Tb Entry")
+//++
+//
+// ULONG
+// HalpAllocateTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function allocates the TB entry specified by the wired register
+// and increments the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// The index of the allocated TB entry.
+//
+//--
+
+ LEAF_ENTRY(HalpAllocateTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ addu v1,v0,1 // allocate TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpAllocateTbEntry
+
+ SBTTL("Free Tb Entry")
+//++
+//
+// VOID
+// HalpFreeTbEntry (
+// VOID
+// )
+//
+// Routine Description:
+//
+// This function frees the TB entry specified by the wired register
+// and decrements the wired register.
+//
+// Arguments:
+//
+// None.
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ LEAF_ENTRY(HalpFreeTbEntry)
+
+ DISABLE_INTERRUPTS(t0) // disable interrupts
+
+ .set noreorder
+ .set noat
+ mfc0 v0,wired // get contents of wired register
+ nop // fill
+ subu v1,v0,1 // free TB entry
+ mtc0 v1,wired //
+ .set at
+ .set reorder
+
+ ENABLE_INTERRUPTS(t0) // enable interrupts
+
+ j ra // return
+
+ .end HalpFreeTbEntry
+
+#endif
diff --git a/private/ntos/nthals/halsnip/mips/x86bios.c b/private/ntos/nthals/halsnip/mips/x86bios.c
new file mode 100644
index 000000000..17cd688aa
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/x86bios.c
@@ -0,0 +1,191 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ x86bios.c
+
+Abstract:
+
+
+ This module implements the platform specific interface between a device
+ driver and the execution of x86 ROM bios code for the device.
+
+--*/
+
+#include "halp.h"
+
+//
+// Define global data.
+// per default, we enable int10's but we do nort use them on our well known
+// SNI graphic cards
+// if we have an unknown card, we try to initialize it via the emulator and the card
+// bios. if this fails, we disable int10 calls
+//
+
+ULONG HalpX86BiosInitialized = FALSE;
+ULONG HalpEnableInt10Calls = TRUE;
+
+BOOLEAN
+HalCallBios (
+ IN ULONG BiosCommand,
+ IN OUT PULONG Eax,
+ IN OUT PULONG Ebx,
+ IN OUT PULONG Ecx,
+ IN OUT PULONG Edx,
+ IN OUT PULONG Esi,
+ IN OUT PULONG Edi,
+ IN OUT PULONG Ebp
+ )
+
+/*++
+
+Routine Description:
+
+ This function provides the platform specific interface between a device
+ driver and the execution of the x86 ROM bios code for the specified ROM
+ bios command.
+
+Arguments:
+
+ BiosCommand - Supplies the ROM bios command to be emulated.
+
+ Eax to Ebp - Supplies the x86 emulation context.
+
+Return Value:
+
+ A value of TRUE is returned if the specified function is executed.
+ Otherwise, a value of FALSE is returned.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // If the X86 BIOS Emulator has not been initialized, then return FALSE.
+ //
+
+ if (HalpX86BiosInitialized == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // If the Video Adapter initialization failed and an Int10 command is
+ // specified, then return FALSE.
+ //
+
+ if (BiosCommand == 0x10){
+
+ if(HalpEnableInt10Calls == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // if Int10 commands are still enabled, Initialize the Card
+ // if it fails, disable Int10's
+ // this should make sense ...
+ //
+
+ if (x86BiosInitializeAdapter(0xc0000, NULL, NULL, NULL) != XM_SUCCESS) {
+ HalpEnableInt10Calls = FALSE;
+ return FALSE;
+ }
+ }
+
+ //
+ // Copy the x86 bios context and emulate the specified command.
+ //
+
+ Context.Eax = *Eax;
+ Context.Ebx = *Ebx;
+ Context.Ecx = *Ecx;
+ Context.Edx = *Edx;
+ Context.Esi = *Esi;
+ Context.Edi = *Edi;
+ Context.Ebp = *Ebp;
+ if (x86BiosExecuteInterrupt((UCHAR)BiosCommand, &Context, NULL, NULL) != XM_SUCCESS) {
+ return FALSE;
+ }
+
+ //
+ // Copy the x86 bios context and return TRUE.
+ //
+
+ *Eax = Context.Eax;
+ *Ebx = Context.Ebx;
+ *Ecx = Context.Ecx;
+ *Edx = Context.Edx;
+ *Esi = Context.Esi;
+ *Edi = Context.Edi;
+ *Ebp = Context.Ebp;
+ return TRUE;
+}
+
+VOID
+HalpResetX86DisplayAdapter(
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function resets a display adapter using the x86 bios emulator.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ XM86_CONTEXT Context;
+
+ //
+ // Initialize the x86 bios context and make the INT 10 call to initialize
+ // the display adapter to 80x50 16 color text mode.
+ // this is done by two int10 calls like on an standard PC
+ // hopefully this works ...
+ // the sample code sets only 80x25 mode, but we want more !!!
+ //
+
+ Context.Eax = 0x0003; // Function 0, Mode 3
+ Context.Ebx = 0;
+ Context.Ecx = 0;
+ Context.Edx = 0;
+ Context.Esi = 0;
+ Context.Edi = 0;
+ Context.Ebp = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+ //
+ // Now change it to 80x50 8x8Font Mode
+ //
+
+ Context.Eax = 0x1112; // use 8x8 font (causes 50 line mode)
+ Context.Ebx = 0;
+
+ HalCallBios(0x10,
+ &Context.Eax,
+ &Context.Ebx,
+ &Context.Ecx,
+ &Context.Edx,
+ &Context.Esi,
+ &Context.Edi,
+ &Context.Ebp);
+}
diff --git a/private/ntos/nthals/halsnip/mips/xxcache.c b/private/ntos/nthals/halsnip/mips/xxcache.c
new file mode 100644
index 000000000..69d72396f
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxcache.c
@@ -0,0 +1,346 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxcache.c,v 1.4 1996/03/04 13:27:00 pierre Exp $")
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+
+Module Name:
+
+ xxcache.c
+
+Abstract:
+
+
+ This module implements the functions necessesary to call the correct Cache routines
+ depending on Uni- or MultiProcessor machine typ.
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "halp.h"
+#include "mpagent.h"
+#include "xxcache.h"
+
+HalpProcessorType HalpProcessorId = UNKNOWN;
+
+
+
+// Desktop : processor may be R4600 or R4700 both of them with or without SC
+// Minitower : processors may be R4700 with or without SC or R4400 + MPAgent (1 or 2)
+
+VOID
+HalpProcessorConfig()
+{
+ULONG Proc, reg;
+
+ Proc = HalpProcIdentify();
+ HalpMainBoard = (MotherBoardType) READ_REGISTER_UCHAR(0xbff0002a);
+ if (HalpMainBoard == M8150) HalpIsTowerPci = TRUE;
+
+ switch (Proc) {
+
+ case HalpR4600:
+ case HalpR4700:
+ if (PCR->SecondLevelDcacheFillSize) HalpProcessorId = ORIONSC; // ASIC driven SC
+ else HalpProcessorId = R4x00;
+ break;
+
+ default:
+ // RM200 and RM300 use the same bit but use the opposite value to determine the new ASIC revision...
+ // ASIC rev 1.0 => cache replace memory (special area reserved by the firmware).
+ // ASIC rev >= 1.1 => cache replace with the ASIC register value.
+ if (HalpMainBoard == DesktopPCI) {
+ UCHAR tmp;
+ tmp = READ_REGISTER_UCHAR(PCI_MSR_ADDR);
+ if (tmp & PCI_MSR_REV_ASIC) HalpMpaCacheReplace = RM300_RESERVED | KSEG0_BASE; // rev 1.0
+ else HalpMpaCacheReplace = MPAGENT_RESERVED | KSEG0_BASE; // rev 1.1
+ } else {
+ if (HalpMainBoard == MinitowerPCI) {
+ UCHAR tmp;
+ tmp = READ_REGISTER_UCHAR(PCI_MSR_ADDR);
+ if (tmp & PCI_MSR_REV_ASIC) HalpMpaCacheReplace = MPAGENT_RESERVED | KSEG0_BASE; // rev 1.1
+ else HalpMpaCacheReplace = RM300_RESERVED | KSEG0_BASE; // rev 1.0
+ } else HalpMpaCacheReplace = MPAGENT_RESERVED | KSEG0_BASE; // RM400 all ASIC
+ }
+
+ HalpProcessorId = MPAGENT; // R4x00 always with MPAgent on the PCI range.
+
+ if (HalpMpaCacheReplace == MPAGENT_RESERVED | KSEG0_BASE) {
+ reg = ((MPAGENT_RESERVED & // put the reserved physical address (4Mb long)
+ MPA_OP_ADDR_MASK) |
+ MPA_OP_ENABLE); // enable the operator
+ } else {
+ reg = 0;
+ }
+
+ WRITE_REGISTER_ULONG(&(mpagent->mem_operator), reg); // for all procs (done for proc 0 in xxcache)
+
+ }
+
+ return;
+}
+
+VOID
+HalFlushDcachePage(
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpFlushDcachePageMulti(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case ORIONSC:
+
+ HalSweepDcacheRange(
+ Color,
+ Length
+ );
+ HalpFlushDcachePageOrion(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case R4x00:
+
+ HalpFlushDcachePageUni(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalFlushDcachePage(Color, PageFrame, Length);
+
+ }
+
+}
+
+VOID
+HalPurgeDcachePage (
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpFlushDcachePageMulti(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case ORIONSC:
+
+ HalSweepDcacheRange(
+ Color,
+ Length
+ );
+ HalpFlushDcachePageOrion(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case R4x00:
+
+ HalpPurgeDcachePageUni(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalPurgeDcachePage(Color, PageFrame, Length);
+
+ }
+
+}
+
+VOID
+HalPurgeIcachePage(
+ IN PVOID Color,
+ IN ULONG PageFrame,
+ IN ULONG Length
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpPurgeIcachePageMulti(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case ORIONSC:
+
+ HalSweepIcacheRange(
+ Color,
+ Length
+ );
+ HalpPurgeIcachePageOrion(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case R4x00:
+
+ HalpPurgeIcachePageUni(
+ Color,
+ PageFrame,
+ Length
+ );
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalPurgeIcachePage(Color, PageFrame, Length);
+
+ }
+
+}
+
+VOID
+HalSweepDcache(
+ VOID
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpSweepDcacheMulti();
+ break;
+
+ case ORIONSC:
+
+ HalpSweepDcacheOrion();
+ break;
+
+ case R4x00:
+
+ HalpSweepDcacheUni();
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalSweepDcache();
+
+ }
+
+}
+
+VOID
+HalSweepIcache (
+ VOID
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpSweepIcacheMulti();
+ break;
+
+ case ORIONSC:
+
+ HalpSweepIcacheOrion();
+ break;
+
+ case R4x00:
+
+ HalpSweepIcacheUni();
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalSweepIcache();
+
+ }
+
+}
+
+VOID
+HalZeroPage (
+ IN PVOID NewColor,
+ IN PVOID OldColor,
+ IN ULONG PageFrame
+ )
+{
+
+ switch (HalpProcessorId) {
+
+ case MPAGENT:
+
+ HalpZeroPageMulti(
+ NewColor,
+ OldColor,
+ PageFrame
+ );
+ break;
+
+ case ORIONSC:
+
+ HalpZeroPageOrion(
+ NewColor,
+ OldColor,
+ PageFrame
+ );
+ break;
+
+ case R4x00:
+
+ HalpZeroPageUni(
+ NewColor,
+ OldColor,
+ PageFrame
+ );
+ break;
+
+ case UNKNOWN:
+
+ HalpProcessorConfig();
+ HalZeroPage(NewColor, OldColor, PageFrame);
+
+ }
+
+}
+
diff --git a/private/ntos/nthals/halsnip/mips/xxcache.h b/private/ntos/nthals/halsnip/mips/xxcache.h
new file mode 100644
index 000000000..6bc20b155
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxcache.h
@@ -0,0 +1,30 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxcache.h,v 1.2 1996/03/04 13:27:16 pierre Exp $")
+
+//
+// Prototypes for private cache functions
+// they match the ones defined for the HAL ...
+//
+
+VOID HalpZeroPageOrion(IN PVOID NewColor, IN PVOID OldColor, IN ULONG PageFrame);
+VOID HalpZeroPageMulti(IN PVOID NewColor, IN PVOID OldColor, IN ULONG PageFrame);
+VOID HalpZeroPageUni(IN PVOID NewColor, IN PVOID OldColor, IN ULONG PageFrame);
+
+VOID HalpSweepIcacheOrion(VOID);
+VOID HalpSweepIcacheMulti(VOID);
+VOID HalpSweepIcacheUni(VOID);
+
+VOID HalpSweepDcacheOrion(VOID);
+VOID HalpSweepDcacheMulti(VOID);
+VOID HalpSweepDcacheUni(VOID);
+
+VOID HalpPurgeIcachePageOrion(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+VOID HalpPurgeIcachePageMulti(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+VOID HalpPurgeIcachePageUni(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+
+VOID HalpPurgeDcachePageUni(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+
+VOID HalpFlushDcachePageOrion(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+VOID HalpFlushDcachePageMulti(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+VOID HalpFlushDcachePageUni(IN PVOID Color, IN ULONG PageFrame, IN ULONG Length);
+
+
diff --git a/private/ntos/nthals/halsnip/mips/xxcalstl.c b/private/ntos/nthals/halsnip/mips/xxcalstl.c
new file mode 100644
index 000000000..1eb6e4c17
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxcalstl.c
@@ -0,0 +1,278 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxcalstl.c,v 1.4 1996/03/04 13:27:51 pierre Exp $")
+/*++
+
+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.
+
+--*/
+
+#include "halp.h"
+#include "stdio.h"
+
+#if DBG
+UCHAR HalpBuffer[128];
+#endif
+//
+// 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.
+
+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 = 200; 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 = 4000 / (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;
+ }
+
+ }
+
+ if (Index == 0) {
+ HalDisplayString("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
+ HalDisplayString("ºWARNING: Cannot compute stall factor º\n");
+ HalDisplayString("ºWARNING: Using default value (250 Mhz) º\n");
+ HalDisplayString("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\n");
+ HalpStallScaleFactor = 0x20;
+ HalpProfileCountRate = 125*1000000;
+ }
+ else {
+ //
+ // 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;
+
+ //
+ // Set the time increment value and connect the real clock interrupt
+ // routine.
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = (PKINTERRUPT_ROUTINE) HalpClockInterrupt;
+
+ //
+ // Write the compare register and clear the count register, and
+ // connect the profile interrupt if profiling is done via count/compare interrupt.
+ //
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ PCR->InterruptRoutine[PROFILE_LEVEL] = (PKINTERRUPT_ROUTINE) HalpProfileInterrupt;
+
+#if DBG
+ sprintf(HalpBuffer,"HalpCalibrateStall : CPU frequency is %d MHz, StallFactor is %d\n", (HalpProfileCountRate/1000000)*2, HalpStallScaleFactor);
+ HalDisplayString(HalpBuffer);
+#endif
+
+ 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/halsnip/mips/xxclock.c b/private/ntos/nthals/halsnip/mips/xxclock.c
new file mode 100644
index 000000000..c9da66a5c
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxclock.c
@@ -0,0 +1,277 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxclock.c,v 1.3 1995/11/02 11:04:33 flo Exp $")
+
+/*++
+
+Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1985-94 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:
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "i82C54.h"
+
+
+//
+// Define global data used to communicate new clock rates to the clock
+// interrupt service routine.
+//
+
+ULONG HalpCurrentTimeIncrement;
+ULONG HalpNextTimeIncrement;
+ULONG HalpNewTimeIncrement;
+
+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;
+ KIRQL OldIrql;
+
+ if (DesiredIncrement < MINIMUM_INCREMENT) {
+ DesiredIncrement = MINIMUM_INCREMENT;
+ }
+ if (DesiredIncrement > MAXIMUM_INCREMENT) {
+ DesiredIncrement = MAXIMUM_INCREMENT;
+ }
+
+ //
+ // 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);
+ NewTimeIncrement = DesiredIncrement / MINIMUM_INCREMENT;
+ NewTimeIncrement = NewTimeIncrement * MINIMUM_INCREMENT;
+ HalpNewTimeIncrement = NewTimeIncrement ;
+ KeLowerIrql(OldIrql);
+ return NewTimeIncrement;
+}
+
+VOID
+HalpProgramIntervalTimer (
+ IN ULONG Interval
+ )
+/*++
+
+Routine Description:
+
+ This function is called to program the System clock according to the frequency
+ required by the specified time increment value.
+
+ N.B. this information was found in the jenson (ALPHA) HAL
+ also valid for MIPS computer ???
+
+ There are four different rates that are used under NT
+ (see page 9-8 of KN121 System Module Programmer's Reference)
+
+ .976562 ms
+ 1.953125 ms
+ 3.90625 ms
+ 7.8125 ms
+
+
+Arguments:
+
+ Interval - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ none.
+
+--*/
+{
+ PEISA_CONTROL controlBase = (PEISA_CONTROL)HalpOnboardControlBase;
+ ULONG Count;
+ TIMER_CONTROL timerControl;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Start the system clock to interrupt at the desired interval.
+ //
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_0;
+
+ //
+ // use timer in the onboard PC core
+ //
+
+ Count = TIMER_CLOCK_IN / ( 10000000 / Interval );
+
+ WRITE_REGISTER_UCHAR(&controlBase->CommandMode1, *((PUCHAR) &timerControl));
+
+ //
+ // Set the system clock timer to the correct frequency.
+ //
+
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)Count);
+ WRITE_REGISTER_UCHAR(&controlBase->Timer1, (UCHAR)(Count >> 8));
+
+ KeLowerIrql(OldIrql);
+}
+
+
+VOID
+HalpProgramExtraTimer (
+ IN ULONG Interval
+ )
+/*++
+
+Routine Description:
+
+ This function is called to program the second clock generator in a multiprocessor System
+ according to the frequency required by the specified Interval value (in 100ns units).
+
+
+Arguments:
+
+ Interval - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ none.
+
+--*/
+{
+
+ volatile PLOCAL_8254 pt = (PLOCAL_8254) PCI_EXTRA_TIMER_ADDR;
+ ULONG Count;
+ TIMER_CONTROL timerControl;
+ KIRQL OldIrql;
+
+ //
+ // Raise IRQL to the highest level, set the new clock interrupt
+ // parameters, lower IRQl, and return the new time increment value.
+ //
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ //
+ // Start the system clock to interrupt at the desired interval.
+ //
+ //
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_SQUARE_WAVE;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_0;
+
+ Count = EXTRA_TIMER_CLOCK_IN / (PRE_COUNT * 10000000 / Interval );
+
+ WRITE_REGISTER_UCHAR( &pt->control, *((PUCHAR) &timerControl));
+ WRITE_REGISTER_UCHAR(&(pt->counter0), (UCHAR)Count);
+ WRITE_REGISTER_UCHAR(&(pt->counter0), (UCHAR)(Count >> 8));
+
+ timerControl.BcdMode = 0;
+ timerControl.Mode = TM_RATE_GENERATOR;
+ timerControl.SelectByte = SB_LSB_THEN_MSB;
+ timerControl.SelectCounter = SELECT_COUNTER_2;
+
+ // the output of counter 2 is hardwired as input to counter 0/1
+ // so we use it as a pre-counter
+
+ WRITE_REGISTER_UCHAR( &pt->control, *((PUCHAR) &timerControl));
+ WRITE_REGISTER_UCHAR(&(pt->counter2), (UCHAR)PRE_COUNT);
+ WRITE_REGISTER_UCHAR(&(pt->counter2), (UCHAR)(PRE_COUNT >>8));
+
+ KeLowerIrql(OldIrql);
+
+}
+
+
+VOID
+HalpProgramExtraTimerPciT (
+ IN ULONG Interval
+ )
+/*++
+
+Routine Description:
+
+ This function is called to program the second clock generator in PCI tower
+ according to the frequency required by the specified Interval value (in 100ns units).
+
+
+Arguments:
+
+ Interval - Supplies desired number of 100ns units between clock
+ interrupts.
+
+Return Value:
+
+ none.
+
+--*/
+{
+
+ KIRQL OldIrql;
+
+ //Stop the timer
+ WRITE_REGISTER_UCHAR(PCI_TOWER_TIMER_CMD_REG,0);
+
+ //Reset Timer-Count Register
+ WRITE_REGISTER_UCHAR(PCI_TOWER_TIMER_COUNT_REG,0);
+
+ //Set Timer-Value Register in ms
+ WRITE_REGISTER_UCHAR(PCI_TOWER_TIMER_VALUE_REG,(UCHAR)(Interval/10000));
+
+ //Start Timer
+ WRITE_REGISTER_UCHAR(PCI_TOWER_TIMER_CMD_REG,1);
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ KeLowerIrql(OldIrql);
+
+}
diff --git a/private/ntos/nthals/halsnip/mips/xxerror.c b/private/ntos/nthals/halsnip/mips/xxerror.c
new file mode 100644
index 000000000..f55c9dd81
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxerror.c
@@ -0,0 +1,293 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxerror.c,v 1.3 1996/05/15 08:13:24 pierre Exp $")
+/*--
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxerror.c
+
+Abstract:
+
+
+ This module implements the management of errors (KeBugCheckEx, HalpBusError)
+
+Environment:
+
+ Kernel mode only.
+
+
+--*/
+
+#include "halp.h"
+#include "string.h"
+
+//
+// Messages for CacheError routine
+//
+
+UCHAR HalpErrCacheMsg[] = "\nCACHE ERROR\n";
+UCHAR HalpParityErrMsg[] = "\nPARITY ERROR\n";
+UCHAR HalpAddrErrMsg[] = "Address in error not found\n";
+ULONG HalpCacheErrFirst = 0;
+
+ULONG HalpKeBugCheck0;
+ULONG HalpKeBugCheck1;
+ULONG HalpKeBugCheck2;
+ULONG HalpKeBugCheck3;
+ULONG HalpKeBugCheck4;
+
+VOID
+HalpBugCheckCallback (
+ IN PVOID Buffer,
+ IN ULONG Length
+ );
+
+//
+// Define bug check information buffer and callback record.
+//
+
+HALP_BUGCHECK_BUFFER HalpBugCheckBuffer;
+
+KBUGCHECK_CALLBACK_RECORD HalpCallbackRecord;
+
+UCHAR HalpComponentId[] = "hal.dll";
+
+//
+// Define BugCheck Number and BugCheck Additional Message
+//
+
+ULONG HalpBugCheckNumber = (ULONG)(-1);
+
+PUCHAR HalpBugCheckMessage[] = {
+"MP_Agent fatal error\n", // #0
+"ASIC PCI TRANSFER ERROR\n", // #1
+"ECC SINGLE ERROR COUNTER OVERFLOW\n", // #2
+"UNCORRECTABLE ECC ERROR\n", // #3
+"PCI TIMEOUT ERROR\n", // #4
+"MP_BUS PARITY ERROR\n", // #5
+"MP_BUS REGISTER SIZE ERROR\n", // #6
+"MEMORY ADDRESS ERROR\n", // #7
+"MEMORY SLOT ERROR\n", // #8
+"MEMORY CONFIG ERROR\n", // #9
+"PCI INITIATOR INTERRUPT ERROR\n", // #10
+"PCI TARGET INTERRUPT ERROR\n", // #11
+"PCI PARITY INTERRUPT ERROR\n", // #12
+"MULTIPLE PCI INITIATOR ERROR\n", // #13
+"MULTIPLE PCI TARGET ERROR\n", // #14
+"MULTIPLE PCI PARITY ERROR\n", // #15
+"DATA_BUS_ERROR\n", // #16
+"INSTRUCTION_BUS_ERROR\n", // #17
+"PARITY ERROR\n", // #18
+"CACHE ERROR\n" // #19
+};
+
+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.
+
+--*/
+
+{
+
+ PHALP_BUGCHECK_BUFFER DumpBuffer;
+ PUCHAR p,q;
+
+ if (HalpBugCheckNumber == -1) return; // that is not a HAL bugcheck ...
+
+ //
+ // Capture the failed memory address and diagnostic registers.
+ //
+
+ DumpBuffer = (PHALP_BUGCHECK_BUFFER)Buffer;
+
+ DumpBuffer->Par0 = HalpKeBugCheck0;
+ DumpBuffer->Par1 = HalpKeBugCheck1;
+ DumpBuffer->Par2 = HalpKeBugCheck2;
+ DumpBuffer->Par3 = HalpKeBugCheck3;
+ DumpBuffer->Par4 = HalpKeBugCheck4;
+ DumpBuffer->MainBoard = HalpMainBoard;
+ p = DumpBuffer->TEXT;q = HalpBugCheckMessage[HalpBugCheckNumber];
+ while (*q) *p++ = *q++;
+ 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.
+
+--*/
+
+{
+
+ KIRQL OldIrql;
+ UCHAR IntSource;
+ UCHAR MaStatus;
+ ULONG Itpend;
+
+
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+ KiAcquireSpinLock(&HalpInterruptLock);
+
+
+
+ if (HalpIsTowerPci){
+ // stop the extra-timer
+
+ WRITE_REGISTER_UCHAR(PCI_TOWER_TIMER_CMD_REG,0);
+
+
+ HalpPciTowerInt3Dispatch(&HalpInt3Interrupt,(PVOID)PCI_TOWER_INTERRUPT_SOURCE_REGISTER);
+ }else{
+
+ IntSource = READ_REGISTER_UCHAR(PCI_INTERRUPT_SOURCE_REGISTER);
+
+ IntSource ^= PCI_INTERRUPT_MASK; // XOR the low active bits with 1 gives 1
+ // and XOR the high active with 0 gives 1
+ if ( IntSource & PCI_INT2_MASK) {
+
+ MaStatus = READ_REGISTER_UCHAR(PCI_MSR_ADDR);
+ if (HalpMainBoard == DesktopPCI) {
+ MaStatus ^= PCI_MSR_MASK_D;
+ } else {
+ MaStatus ^= PCI_MSR_MASK_MT;
+ }//(HalpMainBoard == DesktopPCI)
+
+ //
+ // look for an ASIC interrupt
+ //
+
+ if ( MaStatus & PCI_MSR_ASIC_MASK){
+
+ Itpend = READ_REGISTER_ULONG(PCI_ITPEND_REGISTER);
+
+ if ( Itpend & (PCI_ASIC_ECCERROR | PCI_ASIC_TRPERROR)) {
+
+ ULONG AsicErrAddr, ErrAddr, Syndrome, ErrStatus;
+
+ ErrAddr = READ_REGISTER_ULONG(PCI_ERRADDR_REGISTER);
+ Syndrome = READ_REGISTER_ULONG(PCI_SYNDROME_REGISTER);
+ ErrStatus = READ_REGISTER_ULONG(PCI_ERRSTATUS_REGISTER);
+
+ if (ErrStatus & PCI_MEMSTAT_PARERR) {
+ // Parity error (PCI_ASIC <-> CPU)
+#if DBG
+ DebugPrint(("pci_memory_error : errstatus=0x%x Add error=0x%x syndrome=0x%x \n",
+ ErrStatus,ErrAddr,Syndrome));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 1;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "PARITY ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ErrAddr,HalpComputeNum((UCHAR *)ErrAddr),Syndrome);
+#endif
+ }//if (ErrStatus & PCI_MEMSTAT_PARERR)
+
+
+
+ if (ErrStatus & PCI_MEMSTAT_ECCERR) {
+
+ AsicErrAddr &= 0xfffffff8;
+ ErrAddr = HalpFindEccAddr(AsicErrAddr,(PVOID)PCI_ERRSTATUS_REGISTER,(PVOID)PCI_MEMSTAT_ECCERR);
+ if (ErrAddr == -1) ErrAddr = AsicErrAddr;
+
+#if DBG
+ // UNIX => PANIC
+ DebugPrint(("pci_ecc_error : errstatus=0x%x Add error=0x%x syndrome=0x%x \n",
+ ErrStatus,ErrAddr,Syndrome));
+ DbgBreakPoint();
+#else
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ HalpBugCheckNumber = 3;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "UNCORRECTABLE ECC ERROR\n"
+ HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,ErrAddr,HalpComputeNum((UCHAR *)ErrAddr),Syndrome);
+#endif
+ } //if (ErrStatus & PCI_MEMSTAT_ECCERR)
+ } //if ( Itpend & (PCI_ASIC_ECCERROR | PCI_ASIC_TRPERROR))
+
+
+ }//if ( MaStatus & PCI_MSR_ASIC_MASK)
+
+ }//if ( IntSource & PCI_INT2_MASK)
+ }//if (HalpIsTowerPci)
+
+ // arrive here if no interruption found
+ HalpDisableInterrupts(); // for the MATROX boards...
+ HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
+ HalDisplayString("\n");
+ HalpClearVGADisplay();
+ if (( ExceptionRecord->ExceptionCode & DATA_BUS_ERROR ) == DATA_BUS_ERROR) {
+ HalpBugCheckNumber = 16;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "DATA_BUS_ERROR\n"
+ } else {
+ HalpBugCheckNumber = 17;
+ HalDisplayString(HalpBugCheckMessage[HalpBugCheckNumber]); // "INSTRUCTION_BUS_ERROR\n"
+ }
+
+ HalpKeBugCheckEx(ExceptionRecord->ExceptionCode ,
+ HalpBugCheckNumber,
+ (ULONG)VirtualAddress,
+ (ULONG)PhysicalAddress.LowPart,
+ 0);
+
+ KiReleaseSpinLock(&HalpInterruptLock);
+ KeLowerIrql(OldIrql);
+
+return FALSE;
+}
diff --git a/private/ntos/nthals/halsnip/mips/xxidle.s b/private/ntos/nthals/halsnip/mips/xxidle.s
new file mode 100644
index 000000000..97c9a8d6d
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxidle.s
@@ -0,0 +1,79 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxidle.s,v 1.3 1995/11/02 11:04:33 flo Exp $")
+// 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.
+//
+ li a0,0x01
+ j HalpCheckSpuriousInt // return
+
+10: j ra
+ .end HalProcessorIdle
+
diff --git a/private/ntos/nthals/halsnip/mips/xxinithl.c b/private/ntos/nthals/halsnip/mips/xxinithl.c
new file mode 100644
index 000000000..61e462bb0
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxinithl.c
@@ -0,0 +1,695 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxinithl.c,v 1.13 1996/05/15 08:14:04 pierre Exp $")
+/*--
+
+Copyright (c) 1991 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.
+
+Environment:
+
+ Kernel mode only.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+#include "string.h"
+#include "mpagent.h"
+#include "snipbus.h"
+
+ULONG HalpLedRegister;
+PUCHAR HalpLedAddress = (PUCHAR)PCI_LED_ADDR;;
+ULONG HalpMapBufferSize;
+PHYSICAL_ADDRESS HalpMapBufferPhysicalAddress;
+BOOLEAN LessThan16Mb;
+BOOLEAN HalpEisaDma;
+MotherBoardType HalpMainBoard;
+
+// MultiProcessor machine has a MpAgent per processor
+// Values of HalpIsMulti are :
+// 0 : 1 processor
+// 2 : 2 processors
+// n : n processors
+
+UCHAR HalpIsMulti = 0;
+
+BOOLEAN HalpCountCompareInterrupt = FALSE;
+BOOLEAN HalpIsTowerPci = FALSE;
+ULONG HalpMpaCacheReplace = RM300_RESERVED | KSEG0_BASE; // address to be used for cache replace operation.
+ULONG HalpTwoWayBit; // size of one set for associative cache R5000-R4600-R4700
+
+//
+// Define global spin locks used to synchronize various HAL operations.
+//
+
+KSPIN_LOCK HalpBeepLock;
+KSPIN_LOCK HalpDisplayAdapterLock;
+KSPIN_LOCK HalpSystemInterruptLock;
+KSPIN_LOCK HalpInterruptLock;
+KSPIN_LOCK HalpMemoryBufferLock;
+
+extern VOID HalpParseLoaderBlock(IN PLOADER_PARAMETER_BLOCK LoaderBlock) ;
+BOOLEAN HalPCIRegistryInitialized = FALSE;
+BOOLEAN HalpESC_SB;
+
+extern UCHAR
+HalpRevIdESC(
+ VOID
+ );
+
+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)
+#pragma alloc_text(INIT, HalpDisplayCopyRight)
+
+#endif
+
+
+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.
+
+--*/
+
+{
+ PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+ PLIST_ENTRY NextMd;
+ PKPRCB Prcb;
+ ULONG BuildType = 0;
+ PRESTART_BLOCK NextRestartBlock;
+ ULONG PciData;
+
+ Prcb = PCR->Prcb;
+
+ PCR->DataBusError = HalpBusError;
+ PCR->InstructionBusError = HalpBusError;
+
+ 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);
+ }
+
+ //
+ // Processor 0 specific
+ //
+
+ if(Prcb->Number == 0) {
+
+ *(PULONG)(& (((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[0]) )=0;
+
+ //
+ // 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;
+ HalpNewTimeIncrement = 0;
+ KeSetTimeIncrement(MAXIMUM_INCREMENT, MINIMUM_INCREMENT);
+
+
+ //
+ // Initialize all spin locks.
+ //
+
+ KeInitializeSpinLock(&HalpBeepLock);
+ KeInitializeSpinLock(&HalpDisplayAdapterLock);
+ KeInitializeSpinLock(&HalpSystemInterruptLock);
+ KeInitializeSpinLock(&HalpInterruptLock);
+ KeInitializeSpinLock(&HalpMemoryBufferLock);
+
+ //
+ // Set address of cache error routine.
+ //
+
+ KeSetCacheErrorRoutine(HalpCacheErrorRoutine);
+
+ //
+ // try to identify the Kind of Mainboard => already done in HalpProcessorIdentify
+ //
+
+// HalpMainBoard = (MotherBoardType) READ_REGISTER_UCHAR(0xbff0002a);
+
+ if (HalpRevIdESC() == REV_ID_82374_SB ) HalpESC_SB = TRUE;
+ else HalpESC_SB = FALSE;
+
+ if (HalpMainBoard == M8150) HalpIsTowerPci = TRUE;
+
+ if (HalpIsTowerPci)
+ HalpLedAddress = (PUCHAR)PCI_TOWER_LED_ADDR;
+ else
+ HalpLedAddress = (PUCHAR)PCI_LED_ADDR;
+
+ HalpLedRegister = 0;
+
+ //
+ // for Isa/Eisa access during phase 0 we use KSEG1 addresses
+ //
+
+ HalpOnboardControlBase = (PVOID) (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE);
+
+ HalpEisaControlBase = (PVOID) (EISA_CONTROL_PHYSICAL_BASE | KSEG1_BASE);
+
+ HalpParseLoaderBlock(LoaderBlock) ;
+
+ HalpInitializePCIBus();
+
+ //
+ // Initialize the display adapter.
+ //
+
+ HalpInitializeDisplay0(LoaderBlock);
+
+#if DBG
+ if (!HalPCIRegistryInitialized) HalDisplayString("Non PCI Machine detected\n");;
+#endif
+
+ if (!HalPCIRegistryInitialized) HalDisplayString("Non PCI Machine detected - This HAL is not the right one\n");;
+
+ (ULONG)(((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipRoutine) = (ULONG)-1;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipContext = 0;
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->EipHalInfo = 0;
+
+ //
+ // Determine if there is physical memory above 16 MB.
+ //
+
+ LessThan16Mb = TRUE;
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead) {
+
+ Descriptor = CONTAINING_RECORD( NextMd,
+ MEMORY_ALLOCATION_DESCRIPTOR,
+ ListEntry );
+
+ if (Descriptor->BasePage + Descriptor->PageCount > 0x1000) {
+ LessThan16Mb = FALSE;
+ }
+
+ NextMd = Descriptor->ListEntry.Flink;
+ }
+
+ //
+ // Determine the size need for map buffers. If this system has
+ // memory with a physical address of greater than
+ // MAXIMUM_PHYSICAL_ADDRESS, then allocate a large chunk; otherwise,
+ // allocate a small chunk.
+ //
+
+ if (LessThan16Mb) {
+
+ //
+ // Allocate a small set of map buffers. They are only needed for
+ // slave DMA devices.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_SMALL_SIZE;
+
+ } else {
+
+ //
+ // Allocate a larger set of map buffers. These are used for
+ // slave DMA controllers and Isa cards.
+ //
+
+ HalpMapBufferSize = INITIAL_MAP_BUFFER_LARGE_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;
+ }
+
+ //
+ // Is this machine a multi-processor one ?
+ //
+ // 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.
+
+
+ NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
+ if ((NextRestartBlock != NULL) && (NextRestartBlock->NextRestartBlock != NULL)) {
+
+#if DBG
+ HalDisplayString("Multiprocessor machine detected by RestartBlock\n");
+#endif
+
+ //
+ // There is more than one processor
+ // be sure, the boot (this one) is set to running and started
+ //
+
+ if (!HalpIsMulti) HalpIsMulti = TRUE;
+
+ NextRestartBlock->BootStatus.ProcessorStart = 1;
+ NextRestartBlock->BootStatus.ProcessorReady = 1;
+
+ } else {
+#if DBG
+ HalDisplayString("UniProcessor machine detected\n");
+#endif
+ HalpIsMulti = FALSE;
+ }
+
+ // Initialize the MP Agent
+
+ if (HalpProcessorId == MPAGENT) {
+ HalpInitMPAgent(0);
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[PCR->Number] = 0x01;
+ PCR->InterruptRoutine[OUR_IPI_LEVEL] = HalpIpiInterrupt;
+ }
+
+ //
+ // For the moment, we say all Eisa/ Isa(Onboard) Interrupts should go to processor 0
+ //
+
+ HalpCreateEisaStructures(Isa); // Initialize Onboard Interrupts and Controller
+
+ //
+ // Initialize SNI specific interrupts
+ // (only once needed)
+ //
+
+ HalpCreateIntPciStructures();
+
+ //
+ // Initialize and register a bug check callback record.
+ //
+
+ KeInitializeCallbackRecord(&HalpCallbackRecord);
+ KeRegisterBugCheckCallback(&HalpCallbackRecord,
+ HalpBugCheckCallback,
+ &HalpBugCheckBuffer,
+ sizeof(HALP_BUGCHECK_BUFFER),
+ &HalpComponentId[0]);
+
+ } else {
+
+#if DBG
+// sprintf(HalpBuffer,"HalInitSystem: running on %d\n", HalpGetMyAgent());
+// HalDisplayString(HalpBuffer);
+#endif
+ //
+ // Place something special only to Slave Processors here ...
+ //
+
+ HalpInitMPAgent(Prcb->Number); // enables IPI, init cache replace address
+ PCR->InterruptRoutine[OUR_IPI_LEVEL] = HalpIpiInterrupt;
+
+
+ }
+
+ //
+ // PCR tables and System Timer Initialisation
+ //
+
+ HalpInitializeInterrupts();
+
+ if (HalpIsTowerPci){
+
+ // enable PCI interrupt
+
+ PciData = PCI_TOWER_INTERRUPT_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ PciData = EN_TARG_INTR | EN_INIT_INT ;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+
+ // enable PCI parity interrupt
+
+ PciData = PCI_TOWER_COMMAND_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ PciData = EN_SERR ;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData,READ_REGISTER_ULONG((PULONG) HalpPciConfigData) | *((PULONG) &PciData));
+
+
+ PciData = PCI_TOWER_PAR_0_OFFSET | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ PciData = 0x1f0 ;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+
+ // LOCKSPACE for workaround ethernet
+ PciData = PCI_TOWER_PM_LOCKSPACE | 0x80000000;
+ WRITE_REGISTER_ULONG(HalpPciConfigAddr, *((PULONG) &PciData));
+
+ PciData = 0x80000000 ;
+ WRITE_REGISTER_ULONG ((PULONG) HalpPciConfigData, *((PULONG) &PciData));
+ }
+
+ return (TRUE);
+
+ } else {
+
+ extern BOOLEAN HalpX86BiosInitialized;
+
+ //
+ // Phase 1 initialization.
+ //
+ // N.B. Phase 1 initialization is only executed on processor 0.
+
+ //
+ // Complete initialization of the display adapter.
+ //
+
+ if (HalpInitializeDisplay1(LoaderBlock) == FALSE) {
+ return FALSE;
+ }
+
+ //
+ // Mapping of the EISA Control Space via MmMapIoSpace()
+ //
+
+ HalpMapIoSpace();
+
+ HalpCalibrateStall();
+
+ //
+ // Initialisation of the x86 Bios Emulator ...
+ //
+
+ x86BiosInitializeBios(HalpEisaControlBase, HalpEisaMemoryBase);
+ HalpX86BiosInitialized = TRUE;
+
+ //
+ // Be sure, that the NET_LEVEL is not in the reserved vector .
+ // (NET_DEFAULT_VECTOR == IPI_LEVEL = 7) => only used for
+ // machine != RM200 (mainboard 8036) and processor without
+ // secondary cache
+ //
+
+ PCR->ReservedVectors &= ~(1 << NET_DEFAULT_VECTOR);
+
+ HalpDisplayCopyRight();
+
+ return TRUE;
+ }
+}
+
+
+VOID
+HalInitializeProcessor (
+ IN ULONG Number
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called early in the initialization of the kernel
+ to perform platform dependent initialization for each processor
+ before the HAL Is fully functional.
+
+ N.B. When this routine is called, the PCR is present but is not
+ fully initialized.
+
+Arguments:
+
+ Number - Supplies the number of the processor to initialize.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+//
+// The boot processor is already initialized
+//
+
+#if DBG
+// sprintf(HalpBuffer,"HalInitializeProcessor %d\n",Number);
+// HalDisplayString(HalpBuffer);
+#endif
+
+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(!HalpIsMulti) {
+ return FALSE;
+ }
+
+
+#if DBG
+// sprintf(HalpBuffer,"HalStartNextProcessor running on %d\n", HalpGetMyAgent());
+// HalDisplayString(HalpBuffer);
+#endif
+
+ //
+ // 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;
+//
+// start it by sending him a special IPI message (SNI special to avoid traffic on
+// the MP bus during boot)
+//
+ ((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[Number] = 0x01;
+ HalpSendIpi(1 << (NextRestartBlock->ProcessorId), MPA_BOOT_MESSAGE );
+
+ HalpIsMulti++; //the number of processors is incremented
+
+ 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;
+}
+
+VOID
+HalpDisplayCopyRight(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This function displays the CopyRight Information in the correct SNI Style
+
+Arguments:
+
+ None.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+
+//
+// Define Identification Strings.
+//
+ HalDisplayString("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
+#if defined(SNI_INTERNAL)
+ HalDisplayString("ºMicrosoft(R) Windows NT(TM) 3.51 Hardware Abstraction Layer º\n");
+ HalDisplayString("ºfor Siemens Nixdorf RM200/RM300/RM400 Release 3.0 A0008 º\n");
+#else
+ HalDisplayString("ºMicrosoft(R) Windows NT(TM) 4.00 Hardware Abstraction Layer º\n");
+ HalDisplayString("ºfor Siemens Nixdorf RM200/RM300/RM400 Release 3.0 B0008 º\n");
+#endif
+ HalDisplayString("ºCopyright(c) Siemens Nixdorf Informationssysteme AG 1996 º\n");
+ HalDisplayString("ºCopyright(c) Microsoft Corporation 1985-1996 º\n");
+ HalDisplayString("ºAll Rights Reserved º\n");
+ HalDisplayString("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\n");
+
+ //
+ // this does not seem to work correct on NT 3.51 builds (872) at least
+ // on our MultiPro machine
+ //
+ if(!HalpCountCompareInterrupt) {
+
+ HalDisplayString("ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\n");
+ HalDisplayString("ºWARNING: CountCompare Interrupt is not enabled º\n");
+ HalDisplayString("ºWARNING: please contact your local Siemens Nixdorf º\n");
+ HalDisplayString("ºWARNING: Service Center. º\n");
+ HalDisplayString("ºWARNING: º\n");
+ HalDisplayString("ºWARNING: Your System will come up - but some º\n");
+ HalDisplayString("ºWARNING: performance measurement issues º\n");
+ HalDisplayString("ºWARNING: WILL NOT FUNCTION PROPERLY º\n");
+ HalDisplayString("ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ\n");
+
+ }
+
+}
+
diff --git a/private/ntos/nthals/halsnip/mips/xxinitnt.c b/private/ntos/nthals/halsnip/mips/xxinitnt.c
new file mode 100644
index 000000000..eeb252c3a
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxinitnt.c
@@ -0,0 +1,345 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxinitnt.c,v 1.5 1996/03/04 13:29:07 pierre Exp $")
+/*++
+
+Copyright (c) 1993 - 1994 Siemens Nixdorf Informationssysteme AG
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxinitnt.c
+
+Abstract:
+
+
+ This module implements the interrupt initialization for a MIPS R3000
+ or R4000 system.
+
+Environment:
+
+ Kernel mode only.
+
+
+--*/
+
+#include "halp.h"
+#include "eisa.h"
+extern BOOLEAN HalpCountCompareInterrupt;
+
+//
+// Define forward referenced prototypes.
+//
+
+VOID
+HalpAckExtraClockInterrupt(
+ VOID
+ );
+
+VOID
+HalpCountInterrupt (
+ VOID
+ );
+
+VOID
+HalpProgramIntervalTimer (
+ IN ULONG Interval
+ );
+
+VOID
+HalpProgramExtraTimer (
+ IN ULONG Interval
+ );
+
+
+VOID
+HalpProgramExtraTimerPciT (
+ IN ULONG Interval
+ );
+
+
+//
+// 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)
+#pragma alloc_text(INIT, HalpCountInterrupt)
+
+#endif
+
+
+//
+// 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.
+/*+++
+
+
+ The interrupts bits in the cause Register have the following Hardware Interrupts:
+
+ 7 6 5 4 3 2 1 0
+ +-------------------------------+
+ | x | x | x | x | x | x | x | x |
+ +-------------------------------+
+ | | | | | | | |
+ | | | | | | | +-------- APC LEVEL (Software)
+ | | | | | | +------------ Dispatch LEVEL (Software)
+ | | | | | +---------------- central Int0 (proc 0)
+ | | | | +-------------------- None
+ | | | +------------------------ None
+ | | +---------------------------- TIMER (Proc 1 for RM300MP only)
+ | +-------------------------------- DCU (Proc 1 for RM400MP only - proc 0 for RM400UP only)
+ +------------------------------------ CountCompare (Profiling)
+
+---*/
+
+//
+// On an PCI Desktop or minitower single-processor (ORION), the processor has only 1 central
+// interrupt pin, so all should be directed to this interrupt, except the (internal)
+// CountCompare interrupt
+//
+
+UCHAR
+HalpIrqlMask_PCIs[] = {3, 3, 3, 3, 3, 3, 3, 3, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits (CountCompare only!)
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 3, 3, 3, 3, 3, 3, 3, 3}; // 1000 - 1111 low 4-bits
+
+UCHAR
+HalpIrqlTable_PCIs[] = {0x87, // IRQL 0
+ 0x86, // IRQL 1
+ 0x84, // IRQL 2
+ 0x80, // Int0Dispatch Level
+ // allow only Irql 8 (profiling & HIGH_LEVEL) ?!
+ 0x80, // IRQL 4
+ 0x80, // IRQL 5
+ 0x80, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+
+//
+// On a PCI Tower, all the external interrupts are centralised
+// on one central pin except DCU on IP6 (because of the extra-timer).
+// The internal MP-Agent interrupt is directed on the seventh pin.
+//
+
+UCHAR
+HalpIrqlMask_PCIm_ExT[] = {3, 3, 6, 6, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits (CountCompare only!)
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 3, 3, 3, 3, 3, 3, 3, 3}; // 1000 - 1111 low 4-bits
+UCHAR
+HalpIrqlTable_PCIm_ExT[] = {0xe7, // IRQL 0
+ 0xe6, // IRQL 1
+ 0xe4, // IRQL 2
+ 0xe0, // Int0Dispatch Level
+ 0xe0, // IRQL 4
+ 0xe0, // IRQL 5
+ 0xc0, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+
+//
+// On a PCI multi-processor minitower (or mono-processor with MPagent),
+// all the external interrupts are centralised
+// on one central pin except extra-timer on IP6 (not used if mono).
+// The internal MP-Agent interrupt is directed on the seventh pin.
+//
+
+UCHAR
+HalpIrqlMask_PCIm[] = {3, 5, 3, 5, 7, 7, 7, 7, // 0000 - 0111 high 4-bits
+ 8, 8, 8, 8, 8, 8, 8, 8, // 1000 - 1111 high 4-bits (CountCompare only!)
+ 0, 1, 2, 2, 3, 3, 3, 3, // 0000 - 0111 low 4-bits
+ 3, 3, 3, 3, 3, 3, 3, 3}; // 1000 - 1111 low 4-bits
+UCHAR
+HalpIrqlTable_PCIm[] = {0xd7, // IRQL 0
+ 0xd6, // IRQL 1
+ 0xd4, // IRQL 2
+ 0xd0, // Int0Dispatch Level
+ 0xd0, // IRQL 4
+ 0xc0, // IRQL 5
+ 0xc0, // IRQL 6
+ 0x80, // IRQL 7
+ 0x00}; // IRQL 8
+
+
+
+VOID
+HalpCountInterrupt (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function serves as the R4000 count/compare interrupt service
+ routine early in the system initialization. Its only function is
+ to field and acknowledge count/compare interrupts during the system
+ boot process.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ extern ULONG HalpProfileInterval;
+
+ //
+ // Acknowledge the R4000 count/compare interrupt.
+ //
+ HalpProfileInterval = DEFAULT_PROFILE_INTERVAL;
+ HalpCountCompareInterrupt = TRUE;
+
+ HalpWriteCompareRegisterAndClear(DEFAULT_PROFILE_COUNT);
+ return;
+}
+
+BOOLEAN
+HalpInitializeInterrupts (
+ VOID
+ )
+
+/*++
+
+Routine Description:
+
+ This function initializes interrupts for a MIPS R3000 or R4000 system.
+
+Arguments:
+
+ None.
+
+Return Value:
+
+ A value of TRUE is returned if the initialization is successfully
+ completed. Otherwise a value of FALSE is returned.
+
+--*/
+
+{
+ ULONG Index;
+ PKPRCB Prcb;
+
+
+ //
+ // Get the address of the processor control block for the current
+ // processor.
+ //
+
+ Prcb = PCR->Prcb;
+
+ if (Prcb->Number == 0) {
+
+ //
+ // 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.
+ //
+
+ if (HalpProcessorId != MPAGENT) {
+
+ //
+ // this is a PCI desktop or a single-processor PCI minitower
+ //
+
+ for (Index = 0; Index < sizeof(HalpIrqlMask_PCIs); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_PCIs[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_PCIs); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_PCIs[Index];
+
+ } else {
+
+ //
+ // this is a PCI minitower or PCI tower
+ //
+
+ if (HalpIsTowerPci){
+ for (Index = 0; Index < sizeof(HalpIrqlMask_PCIm_ExT); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_PCIm_ExT[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_PCIm_ExT); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_PCIm_ExT[Index];
+ }else{
+ for (Index = 0; Index < sizeof(HalpIrqlMask_PCIm); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_PCIm[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_PCIm); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_PCIm[Index];
+ }
+
+ }
+
+ //
+ // the main system clock is always in the onboard PC core
+ //
+
+ PCR->InterruptRoutine[CLOCK2_LEVEL] = (PKINTERRUPT_ROUTINE)HalpStallInterrupt;
+
+ //
+ // force a CountCompare interrupt
+ //
+
+ HalpWriteCompareRegisterAndClear(100);
+
+ //
+ // 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\compare interrupt to the appropriate interrupt service routine.
+ //
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpCountInterrupt;
+
+ HalpProgramIntervalTimer (MAXIMUM_INCREMENT);
+ HalpEnableOnboardInterrupt(CLOCK2_LEVEL,Latched); // Enable Timer1,Counter0 interrupt
+
+ } else {
+
+ //
+ // MultiProcessorEnvironment Processor N
+ //
+
+ if (HalpIsTowerPci){
+ for (Index = 0; Index < sizeof(HalpIrqlMask_PCIm_ExT); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_PCIm_ExT[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_PCIm_ExT); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_PCIm_ExT[Index];
+ }else{
+ for (Index = 0; Index < sizeof(HalpIrqlMask_PCIm); Index += 1)
+ PCR->IrqlMask[Index] = HalpIrqlMask_PCIm[Index];
+ for (Index = 0; Index < sizeof(HalpIrqlTable_PCIm); Index += 1)
+ PCR->IrqlTable[Index] = HalpIrqlTable_PCIm[Index];
+ }
+
+ if (Prcb->Number==1){
+ if (HalpIsTowerPci){
+ HalpProgramExtraTimerPciT(MAXIMUM_INCREMENT);
+ }else{
+ HalpProgramExtraTimer (MAXIMUM_INCREMENT);
+ PCR->InterruptRoutine[EXTRA_CLOCK_LEVEL] = HalpClockInterrupt1;
+ }
+ }
+
+ PCR->InterruptRoutine[PROFILE_LEVEL] = HalpProfileInterrupt;
+ PCR->StallScaleFactor = HalpStallScaleFactor;
+
+ }
+
+ return TRUE;
+}
+
diff --git a/private/ntos/nthals/halsnip/mips/xxipiint.s b/private/ntos/nthals/halsnip/mips/xxipiint.s
new file mode 100644
index 000000000..20c0302ac
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxipiint.s
@@ -0,0 +1,56 @@
+// TITLE("Interprocessor Interrupts")
+//++
+//
+// Copyright (c) 1993-1994 Microsoft Corporation
+//
+// Module Name:
+//
+// xxipiint.s
+//
+// Abstract:
+//
+// This module implements the code necessary to field and process the
+// interprocessor interrupts on a MIPS R4000 Duo system.
+//
+// Environment:
+//
+// Kernel mode only.
+//
+// Revision History:
+//
+//--
+
+#include "halmips.h"
+
+
+
+ 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.
+//
+//--
+
+ LEAF_ENTRY(HalpIpiInterrupt)
+
+//
+// Inter processor interrupt processing
+//
+
+ move a0,s8
+ j HalpProcessIpi // acknowledgement Ipi
+
+ .end HalpIpiInterrupt
+
diff --git a/private/ntos/nthals/halsnip/mips/xxmemory.c b/private/ntos/nthals/halsnip/mips/xxmemory.c
new file mode 100644
index 000000000..2d9806212
--- /dev/null
+++ b/private/ntos/nthals/halsnip/mips/xxmemory.c
@@ -0,0 +1,246 @@
+//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/xxmemory.c,v 1.2 1996/02/23 17:55:12 pierre Exp $")
+
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ xxmemory.c
+
+Abstract:
+
+ Provides routines to allow the HAL to map physical memory.
+
+Environment:
+
+ Phase 0 initialization only.
+
+Changes:
+
+ All stuff comes from the x86 HAL Sources (xxmemory.c)
+
+--*/
+#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, HalpAllocPhysicalMemory)
+#endif
+
+
+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 pyhsical 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 contains a memory chunk
+ // 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 = (AlignmentOffset + 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 (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;
+}
+
+
+#define MEMBASE 0x20000000
+
+USHORT HalpComputeNum (phys_addr)
+UCHAR *phys_addr;
+{
+ USHORT board_or_simm_num;
+ ULONG i;
+ struct bank *pbank =((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->MemConfArea;
+ ULONG nb_banks =((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))-> NbMemBanks;
+ UCHAR *conf_addr;
+
+
+
+ if (pbank == 0) return((USHORT)(-1)); // firmware revision < 4.5 --> function non implemented
+
+
+ // Rebase phys_addr at 0x20000000
+ (ULONG)phys_addr |= MEMBASE;
+
+ for (i = 0; i < nb_banks; i++, pbank++) {
+
+ // Rebase conf_addr at 0x20000000
+ conf_addr =(UCHAR *)( (ULONG)pbank->first_addr | MEMBASE);
+
+ if ((phys_addr >= conf_addr) && (phys_addr < (conf_addr + pbank->first_piece_size))){
+
+ break;
+ }
+
+ if (pbank->second_piece_size != 0) {
+
+ // Rebase conf_addr at 0x20000000
+ conf_addr =(UCHAR *)((ULONG) pbank->second_addr | MEMBASE);
+
+ if ((phys_addr >= conf_addr) && (phys_addr < (conf_addr + pbank->second_piece_size))) {
+
+ break;
+ }
+ }
+ }
+
+ if (i == nb_banks) {
+
+ // Unable to find the board or SIMM
+ board_or_simm_num = (USHORT)(-1);
+ }
+
+ else {
+ // On RM400 we have one board per bank from 1 to nb_banks
+ if (HalpIsTowerPci) {
+ board_or_simm_num = (USHORT)(i + 1);
+ }
+ // On RM200/RM300 we have two SIMM's per bank from 0 to 2*nb_banks - 1
+ else {
+ board_or_simm_num = (USHORT)( (2*i) + (((ULONG)phys_addr >> 3) & 0x01));
+ }
+ }
+
+ return (board_or_simm_num);
+}
+
+
+
+
+