411 lines
8.2 KiB
ArmAsm
411 lines
8.2 KiB
ArmAsm
#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
|
||
|