411 lines
8.2 KiB
ArmAsm
Raw Normal View History

2001-01-01 00:00:00 +01:00
#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