488 lines
11 KiB
ArmAsm
488 lines
11 KiB
ArmAsm
//++
|
||
//
|
||
// Copyright (c) 1994 FirePower Systems INC.
|
||
//
|
||
// Copyright (c) 1994 MOTOROLA, INC. All Rights Reserved. This file
|
||
// contains copyrighted material. Use of this file is restricted
|
||
// by the provisions of a Motorola Software License Agreement.
|
||
//
|
||
// Module Name:
|
||
//
|
||
// pxsystem.s
|
||
//
|
||
// Abstract:
|
||
//
|
||
// This module implements the routines to handle system functions:
|
||
// Provides system specific info.
|
||
// Currently provides processor version type
|
||
//
|
||
// Author:
|
||
// breeze@firepower.com
|
||
//
|
||
// Environment:
|
||
//
|
||
// Kernel mode only.
|
||
//
|
||
// Revision History:
|
||
//
|
||
//--
|
||
|
||
/*
|
||
* Copyright (c) 1995 FirePower Systems, Inc.
|
||
* DO NOT DISTRIBUTE without permission
|
||
*
|
||
* $RCSfile: phsystem.s $
|
||
* $Revision: 1.7 $
|
||
* $Date: 1996/01/11 07:08:26 $
|
||
* $Locker: $
|
||
*/
|
||
|
||
#include "kxppc.h"
|
||
|
||
//++
|
||
//
|
||
// Routine Description:
|
||
//
|
||
//
|
||
// Arguments:
|
||
// HalProcessorRev, in r3
|
||
//
|
||
//
|
||
// Return Value:
|
||
// Processor Version register value
|
||
//
|
||
//
|
||
//--
|
||
|
||
|
||
LEAF_ENTRY(HalpGetProcessorRev)
|
||
mfpvr r.3 // get processor version
|
||
LEAF_EXIT(HalpGetProcessorRev)
|
||
|
||
|
||
/******************************************************************************
|
||
Synopsis:
|
||
ULONG HalpGetUpperIBAT(ULONG BatNumber) [ged]
|
||
|
||
Purpose:
|
||
Supplies the 32-bit upper instruction BAT value for a given <BatNumber>.
|
||
|
||
Returns:
|
||
Returns the 32-bit upper BAT value.
|
||
******************************************************************************/
|
||
|
||
.set BatNumber, r.3
|
||
|
||
LEAF_ENTRY(HalpGetUpperIBAT)
|
||
|
||
cmpli 0,0,BatNumber,0
|
||
bne NotUI0
|
||
mfibatu BatNumber,0
|
||
b ExitUI
|
||
NotUI0:
|
||
cmpli 0,0,BatNumber,1
|
||
bne NotUI1
|
||
mfibatu BatNumber,1
|
||
b ExitUI
|
||
NotUI1:
|
||
cmpli 0,0,BatNumber,2
|
||
bne NotUI2
|
||
mfibatu BatNumber,2
|
||
b ExitUI
|
||
NotUI2:
|
||
mfibatu BatNumber,3 // OK, it's three by default
|
||
|
||
ExitUI:
|
||
|
||
LEAF_EXIT(HalpGetUpperIBAT)
|
||
|
||
/******************************************************************************
|
||
Synopsis:
|
||
ULONG HalpGetLowerIBAT(ULONG BatNumber) [ged]
|
||
|
||
Purpose:
|
||
Supplies the 32-bit lower instruction BAT value for a given <BatNumber>.
|
||
|
||
Returns:
|
||
Returns the 32-bit lower BAT value.
|
||
******************************************************************************/
|
||
|
||
LEAF_ENTRY(HalpGetLowerIBAT)
|
||
|
||
cmpli 0,0,BatNumber,0
|
||
bne NotLI0
|
||
mfibatl BatNumber,0
|
||
b ExitLI
|
||
NotLI0:
|
||
cmpli 0,0,BatNumber,1
|
||
bne NotLI1
|
||
mfibatl BatNumber,1
|
||
b ExitLI
|
||
NotLI1:
|
||
cmpli 0,0,BatNumber,2
|
||
bne NotLI2
|
||
mfibatl BatNumber,2
|
||
b ExitLI
|
||
NotLI2:
|
||
mfibatl BatNumber,3 // OK, it's three by default
|
||
|
||
ExitLI:
|
||
|
||
LEAF_EXIT(HalpGetLowerIBAT)
|
||
|
||
/******************************************************************************
|
||
Synopsis:
|
||
ULONG HalpGetUpperDBAT(ULONG BatNumber) [ged]
|
||
|
||
Purpose:
|
||
Supplies the 32-bit upper data BAT value for a given <BatNumber>.
|
||
|
||
Returns:
|
||
Returns the 32-bit upper BAT value.
|
||
******************************************************************************/
|
||
|
||
LEAF_ENTRY(HalpGetUpperDBAT)
|
||
|
||
cmpli 0,0,BatNumber,0
|
||
bne NotUD0
|
||
mfdbatu BatNumber,0
|
||
b ExitUD
|
||
NotUD0:
|
||
cmpli 0,0,BatNumber,1
|
||
bne NotUD1
|
||
mfdbatu BatNumber,1
|
||
b ExitUD
|
||
NotUD1:
|
||
cmpli 0,0,BatNumber,2
|
||
bne NotUD2
|
||
mfdbatu BatNumber,2
|
||
b ExitUD
|
||
NotUD2:
|
||
mfdbatu BatNumber,3 // OK, it's three by default
|
||
|
||
ExitUD:
|
||
|
||
LEAF_EXIT(HalpGetUpperDBAT)
|
||
|
||
/******************************************************************************
|
||
Synopsis:
|
||
ULONG HalpGetLowerDBAT(ULONG BatNumber) [ged]
|
||
|
||
Purpose:
|
||
Supplies the 32-bit lower data BAT value for a given <BatNumber>.
|
||
|
||
Returns:
|
||
Returns the 32-bit lower BAT value.
|
||
******************************************************************************/
|
||
|
||
LEAF_ENTRY(HalpGetLowerDBAT)
|
||
|
||
cmpli 0,0,BatNumber,0
|
||
bne NotLD0
|
||
mfdbatl BatNumber,0
|
||
b ExitLD
|
||
NotLD0:
|
||
cmpli 0,0,BatNumber,1
|
||
bne NotLD1
|
||
mfdbatl BatNumber,1
|
||
b ExitLD
|
||
NotLD1:
|
||
cmpli 0,0,BatNumber,2
|
||
bne NotLD2
|
||
mfdbatl BatNumber,2
|
||
b ExitLD
|
||
NotLD2:
|
||
mfdbatl BatNumber,3 // OK, it's three by default
|
||
|
||
ExitLD:
|
||
|
||
LEAF_EXIT(HalpGetLowerDBAT)
|
||
|
||
/******************************************************************************
|
||
Synopsis:
|
||
ULONG HalpSetUpperDBAT(ULONG BatNumber) [rdl]
|
||
|
||
Purpose:
|
||
Stores the 32-bit upper data BAT value for a given <BatNumber>.
|
||
|
||
Returns:
|
||
N/A
|
||
******************************************************************************/
|
||
|
||
.set BatValueToSet, r.4
|
||
|
||
LEAF_ENTRY(HalpSetUpperDBAT)
|
||
|
||
cmpli 0,0,BatNumber,0
|
||
bne NotSetUD0
|
||
mtdbatu 0,BatValueToSet
|
||
b ExitSetUD
|
||
NotSetUD0:
|
||
cmpli 0,0,BatNumber,1
|
||
bne NotSetUD1
|
||
mtdbatu 1,BatValueToSet
|
||
b ExitSetUD
|
||
NotSetUD1:
|
||
cmpli 0,0,BatNumber,2
|
||
bne NotSetUD2
|
||
mtdbatu 2,BatValueToSet
|
||
b ExitSetUD
|
||
NotSetUD2:
|
||
mtdbatu 3,BatValueToSet // OK, it's three by default
|
||
|
||
ExitSetUD:
|
||
|
||
LEAF_EXIT(HalpSetUpperDBAT)
|
||
|
||
/******************************************************************************
|
||
Synopsis:
|
||
ULONG HalpSetLowerDBAT(ULONG BatNumber) [rdl]
|
||
|
||
Purpose:
|
||
Stores the 32-bit lower data BAT value for a given <BatNumber>.
|
||
|
||
Returns:
|
||
N/A
|
||
******************************************************************************/
|
||
|
||
LEAF_ENTRY(HalpSetLowerDBAT)
|
||
|
||
cmpli 0,0,BatNumber,0
|
||
bne NotSetLD0
|
||
mtdbatl 0,BatValueToSet
|
||
b ExitSetLD
|
||
NotSetLD0:
|
||
cmpli 0,0,BatNumber,1
|
||
bne NotSetLD1
|
||
mtdbatl 1,BatValueToSet
|
||
b ExitSetLD
|
||
NotSetLD1:
|
||
cmpli 0,0,BatNumber,2
|
||
bne NotSetLD2
|
||
mtdbatl 2,BatValueToSet
|
||
b ExitSetLD
|
||
NotSetLD2:
|
||
mtdbatl 3,BatValueToSet // OK, it's three by default
|
||
|
||
ExitSetLD:
|
||
|
||
LEAF_EXIT(HalpSetLowerDBAT)
|
||
|
||
/******************************************************************************
|
||
Synopsis:
|
||
VOID HalpSetLowerDBAT3(ULONG BatValue) [ged]
|
||
|
||
Purpose:
|
||
Writes the 32-bit lower data BAT value <BatValue> to DBAT3.
|
||
|
||
Returns:
|
||
Nothing
|
||
******************************************************************************/
|
||
|
||
.set BatValue, r.3
|
||
|
||
LEAF_ENTRY(HalpSetLowerDBAT3)
|
||
|
||
mtdbatl 3,BatValue
|
||
|
||
LEAF_EXIT(HalpSetLowerDBAT3)
|
||
|
||
/******************************************************************************
|
||
Synopsis:
|
||
VOID HalpSetLowerDBAT1(ULONG BatValue) [ged]
|
||
|
||
Purpose:
|
||
Writes the 32-bit lower data BAT value <BatValue> to DBAT1.
|
||
|
||
Returns:
|
||
Nothing
|
||
******************************************************************************/
|
||
|
||
LEAF_ENTRY(HalpSetLowerDBAT1)
|
||
|
||
mtdbatl 1,BatValue
|
||
|
||
LEAF_EXIT(HalpSetLowerDBAT1)
|
||
|
||
/******************************************************************************
|
||
Synopsis:
|
||
VOID HalpSetUpperDBAT1(ULONG BatValue) [ged]
|
||
|
||
Purpose:
|
||
Writes the 32-bit upper data BAT value <BatValue> to DBAT1.
|
||
|
||
Returns:
|
||
Nothing
|
||
******************************************************************************/
|
||
|
||
LEAF_ENTRY(HalpSetUpperDBAT1)
|
||
|
||
mtdbatu 1,BatValue
|
||
|
||
LEAF_EXIT(HalpSetUpperDBAT1)
|
||
|
||
/******************************************************************************
|
||
|
||
Synopsis:
|
||
VOID HalpDisableDCache()
|
||
******************************************************************************/
|
||
|
||
LEAF_ENTRY(HalpDisableDCache)
|
||
|
||
.set HID0, 1008
|
||
|
||
mtspr HID0, r3
|
||
|
||
LEAF_EXIT(HalpDisableDCache)
|
||
|
||
|
||
//++
|
||
//
|
||
// void
|
||
// KiSetDbat
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// Writes a set of values to DBAT n
|
||
//
|
||
// No validation of parameters is done. Protection is set for kernel
|
||
// mode access only.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// r.3 Number of DBAT
|
||
// r.4 Physical address
|
||
// r.5 Virtual Address
|
||
// r.6 Length (in bytes)
|
||
// r.7 Coherence Requirements (WIM)
|
||
//
|
||
// Return Value:
|
||
//
|
||
// None.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY (KiSetDbat)
|
||
|
||
mfpvr r.9 // different format for
|
||
// 601 vs other 6xx processors
|
||
cmpwi cr.5, r.3, 1
|
||
cmpwi cr.6, r.3, 2
|
||
cmpwi cr.7, r.3, 3
|
||
|
||
rlwinm. r.10, r.9, 0, 0xfffe0000// Check for 601
|
||
|
||
// calculate mask (ie BSM) If we knew the number passed in was
|
||
// always a power of two we could just subtract 1 and shift right
|
||
// 17 bits. But to be sure we will use a slightly more complex
|
||
// algorithm than will always generate a correct mask.
|
||
//
|
||
// the mask is given by
|
||
//
|
||
// ( 1 << ( 32 - 17 - cntlzw(Length - 1) ) ) - 1
|
||
// == ( 1 << ( 15 - cntlzw(Length - 1) ) ) - 1
|
||
|
||
addi r.6, r.6, -1
|
||
oris r.6, r.6, 1 // ensure min length 128KB
|
||
ori r.6, r.6, 0xffff
|
||
cntlzw r.6, r.6
|
||
subfic r.6, r.6, 15
|
||
li r.10, 1
|
||
slw r.6, r.10, r.6
|
||
addi r.6, r.6, -1
|
||
|
||
beq cr.0, KiSetDbat601
|
||
|
||
// processor is not a 601.
|
||
|
||
rlwinm r.7, r.7, 3, 0x38 // position WIM (G = 0)
|
||
rlwinm r.6, r.6, 2, 0x1ffc // restrict BAT maximum (non 601)
|
||
// after left shifting by 2.
|
||
ori r.6, r.6, 0x2 // Valid (bit) in supervisor state only
|
||
ori r.7, r.7, 2 // PP = 0x2
|
||
or r.5, r.5, r.6 // = Virt addr | BL | Vs | Vp
|
||
or r.4, r.4, r.7 // = Phys addr | WIMG | 0 | PP
|
||
|
||
beq cr.5, KiSetDbat1
|
||
beq cr.6, KiSetDbat2
|
||
beq cr.7, KiSetDbat3
|
||
|
||
KiSetDbat0:
|
||
mtdbatl 0, r.4
|
||
mtdbatu 0, r.5
|
||
ALTERNATE_EXIT(KiSetDbat)
|
||
|
||
KiSetDbat1:
|
||
mtdbatl 1, r.4
|
||
mtdbatu 1, r.5
|
||
ALTERNATE_EXIT(KiSetDbat)
|
||
|
||
KiSetDbat2:
|
||
mtdbatl 2, r.4
|
||
mtdbatu 2, r.5
|
||
ALTERNATE_EXIT(KiSetDbat)
|
||
|
||
KiSetDbat3:
|
||
mtdbatl 3, r.4
|
||
mtdbatu 3, r.5
|
||
ALTERNATE_EXIT(KiSetDbat)
|
||
|
||
// 601 has different format BAT registers and actually only has
|
||
// one set unlike other PowerPC processors which have seperate
|
||
// Instruction and Data BATs. The 601 BAT registers are set
|
||
// with the mtibat[u|l] instructions.
|
||
|
||
KiSetDbat601:
|
||
|
||
rlwinm r.7, r.7, 3, 0x70 // position WIMG (601 has no G bit)
|
||
rlwinm r.6, r.6, 0, 0x3f // restrict BAT maximum (601 = 8MB)
|
||
ori r.6, r.6, 0x40 // Valid bit
|
||
ori r.7, r.7, 4 // Ks = 0 | Ku = 1 | PP = 0b00
|
||
or r.4, r.4, r.6 // = Phys addr | Valid | BL
|
||
or r.5, r.5, r.7 // = Virt addr | WIM | Ks | Ku | PP
|
||
|
||
beq cr.5, KiSet601Bat1
|
||
beq cr.6, KiSet601Bat2
|
||
beq cr.7, KiSet601Bat3
|
||
|
||
KiSet601Bat0:
|
||
mtibatl 0, r.4
|
||
mtibatu 0, r.5
|
||
ALTERNATE_EXIT(KiSet601Bat)
|
||
|
||
KiSet601Bat1:
|
||
mtibatl 1, r.4
|
||
mtibatu 1, r.5
|
||
ALTERNATE_EXIT(KiSet601Bat)
|
||
|
||
KiSet601Bat2:
|
||
mtibatl 2, r.4
|
||
mtibatu 2, r.5
|
||
ALTERNATE_EXIT(KiSet601Bat)
|
||
|
||
KiSet601Bat3:
|
||
mtibatl 3, r.4
|
||
mtibatu 3, r.5
|
||
|
||
LEAF_EXIT(KiSetDbat)
|
||
|
||
/******************************************************************************
|
||
Synopsis:
|
||
ULONG HalpGetHighVector(ULONG IntValue)
|
||
|
||
Purpose:
|
||
Find the highest bit turned on and return the bit order
|
||
|
||
Returns:
|
||
Number of leading zeroes
|
||
******************************************************************************/
|
||
|
||
.set IntValue, r.3
|
||
|
||
LEAF_ENTRY(HalpGetHighVector)
|
||
|
||
cntlzw IntValue, IntValue
|
||
subfic IntValue, IntValue, 0x1f
|
||
|
||
LEAF_EXIT(HalpGetHighVector)
|