702 lines
24 KiB
ArmAsm
702 lines
24 KiB
ArmAsm
|
||
/*++
|
||
|
||
Copyright (c) 1993 Digital Equipment Corporation
|
||
|
||
Module Name:
|
||
|
||
apecsio.s
|
||
|
||
|
||
Abstract:
|
||
|
||
This contains assembler code routines for the Alpha AXP Eval Board eb64+.
|
||
|
||
The module contains the functions to turn quasi virtual
|
||
addresses into an Alpha superpage virtual address
|
||
and then read or write based on the request.
|
||
(We are using EV4 64-bit superpage mode.)
|
||
|
||
Author:
|
||
|
||
Joe Notarangelo 25-Oct-1993
|
||
|
||
Environment:
|
||
|
||
Executes in kernel mode.
|
||
|
||
Revision History:
|
||
|
||
Sameer Dekate 28-July-1994
|
||
|
||
Made a common file alphaio.s for machine independent routines.
|
||
|
||
|
||
--*/
|
||
|
||
#include "apecs.h"
|
||
#include "halalpha.h"
|
||
|
||
|
||
|
||
SBTTL( "Write Control Register" )
|
||
//++
|
||
//
|
||
// VOID
|
||
// WRITE_EPIC_REGISTER(
|
||
// IN PVOID RegisterQva,
|
||
// IN ULONG Value
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// Write a control register in the APECS memory or PCI controller
|
||
// (COMANCHE and EPIC respectively).
|
||
//
|
||
// Arguments:
|
||
//
|
||
// RegisterQva(a0) - QVA of control register to be written.
|
||
//
|
||
// Value(a1) - Longword value to be written to the control register.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// None.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(WRITE_EPIC_REGISTER)
|
||
|
||
ALTERNATE_ENTRY(WRITE_COMANCHE_REGISTER)
|
||
|
||
and a0, QVA_SELECTORS, t1 // get qva selector bits
|
||
xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
|
||
bne t1, 2f // if ne, iff failed
|
||
|
||
zap a0, 0xf0, a0 // clear <63:32>
|
||
bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
|
||
sll a0, 5, t0 //
|
||
ldiq t4, -0x4000 //
|
||
sll t4, 28, t4 //
|
||
or t0, t4, t0 // superpage mode
|
||
|
||
.set volatile
|
||
|
||
stl a1, (t0) // write the longword
|
||
ldl t4, (t0) // read the the longword, to force
|
||
// consistency (EPIC chip bug).
|
||
mb // order the write
|
||
.set novolatile
|
||
|
||
ret zero, (ra) // return
|
||
|
||
2: // flag bad QVAs
|
||
BREAK_DEBUG_STOP // take a breakpoint
|
||
ret zero, (ra) // return
|
||
|
||
.end WRITE_EPIC_REGISTER
|
||
|
||
|
||
SBTTL( "Read Control Register" )
|
||
//++
|
||
//
|
||
// ULONG
|
||
// READ_EPIC_REGISTER(
|
||
// IN PVOID RegisterQva
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// Read a control register in the APECS memory or PCI controller
|
||
// (COMANCHE and EPIC respectively).
|
||
//
|
||
// Arguments:
|
||
//
|
||
// RegisterQva(a0) - QVA of control register to be written.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// v0 - Return the value read from the control register.
|
||
//
|
||
//--
|
||
|
||
LEAF_ENTRY(READ_EPIC_REGISTER)
|
||
|
||
ALTERNATE_ENTRY(READ_COMANCHE_REGISTER)
|
||
|
||
and a0, QVA_SELECTORS, t1 // get qva selector bits
|
||
xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
|
||
bne t1, 2f // if ne, iff failed
|
||
|
||
zap a0, 0xf0, a0 // clear <63:32>
|
||
bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
|
||
sll a0, 5, t0 //
|
||
ldiq t4, -0x4000 //
|
||
sll t4, 28, t4 //
|
||
or t0, t4, t0 // superpage mode
|
||
|
||
ldl v0, (t0) // read the register
|
||
|
||
ret zero, (ra) // return
|
||
|
||
2: // flag bad QVAs
|
||
BREAK_DEBUG_STOP // take a breakpoint
|
||
|
||
ret zero, (ra) // return
|
||
|
||
.end READ_EPIC_REGISTER
|
||
|
||
|
||
//
|
||
// Values and structures used to access configuration space.
|
||
//
|
||
|
||
//
|
||
// Define the QVA for the Configuration Cycle Type register within the
|
||
// IOC. Physical Address = 1 A000 01C0
|
||
//
|
||
|
||
#define EPIC_HAXR2_QVA (0xad00000e)
|
||
|
||
//
|
||
// Define the configuration routines stack frame.
|
||
//
|
||
|
||
.struct 0
|
||
CfgRa: .space 8 // return address
|
||
CfgA0: .space 8 // saved ConfigurationAddress
|
||
CfgA1: .space 8 // saved ConfigurationData/CycleType
|
||
CfgA2: .space 8 // saved ConfigurationCycleType
|
||
CfgFrameLength:
|
||
|
||
|
||
//++
|
||
//
|
||
// ULONG
|
||
// READ_CONFIG_UCHAR(
|
||
// ULONG ConfigurationAddress,
|
||
// ULONG ConfigurationCycleType
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// Read an unsigned byte from PCI configuration space.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// ConfigurationAddress(a0) - Supplies the QVA of configuration to be read.
|
||
//
|
||
// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// (v0) Returns the value of configuration space at the specified location.
|
||
//
|
||
// N.B. - This routine follows a protocol for reading from PCI configuration
|
||
// space that allows the HAL or firmware to fixup and continue
|
||
// execution if no device exists at the configuration target address.
|
||
// The protocol requires 2 rules:
|
||
// (1) The configuration space load must use a destination register
|
||
// of v0
|
||
// (2) The instruction immediately following the configuration space
|
||
// load must use v0 as an operand (it must consume the value
|
||
// returned by the load)
|
||
//
|
||
//--
|
||
|
||
NESTED_ENTRY( READ_CONFIG_UCHAR, CfgFrameLength, zero )
|
||
|
||
lda sp, -CfgFrameLength(sp) // allocate stack frame
|
||
stq ra, CfgRa(sp) // save return address
|
||
|
||
PROLOGUE_END // end prologue
|
||
|
||
//
|
||
// Merge the configuration cycle type into the HAXR2 register within
|
||
// the EPIC.
|
||
//
|
||
|
||
stq a0, CfgA0(sp) // save configuration space address
|
||
stq a1, CfgA1(sp) // save configuration cycle type
|
||
|
||
ldil a0, EPIC_HAXR2_QVA // address of HAXR2
|
||
bsr ra, READ_EPIC_REGISTER // read current value
|
||
|
||
ldq a1, CfgA1(sp) // restore configuration cycle type
|
||
bic v0, 0x3, t0 // clear config cycle type field
|
||
bis a1, t0, a1 // merge config cycle type
|
||
ldil a0, EPIC_HAXR2_QVA // address of HAXR2
|
||
bsr ra, WRITE_EPIC_REGISTER // write updated HAXR2
|
||
|
||
//
|
||
// Perform the read from configuration space after restoring the
|
||
// configuration space address.
|
||
//
|
||
|
||
ldq a0, CfgA0(sp) // restore configuration space address
|
||
|
||
and a0, QVA_SELECTORS, t1 // get qva selector bits
|
||
and a0, 0x3, t3 // capture byte lane
|
||
xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
|
||
bne t1, 2f // if ne, iff failed
|
||
|
||
zap a0, 0xf0, a0 // clear <63:32>
|
||
bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
|
||
sll a0, IO_BIT_SHIFT, t0 //
|
||
ldiq t4, -0x4000 //
|
||
sll t4, 28, t4 //
|
||
bis t0, t4, t0 // superpage mode
|
||
|
||
bis t0, IO_BYTE_LEN, t0 // or in the byte enables
|
||
|
||
ldl v0, (t0) // read the longword
|
||
extbl v0, t3, v0 // return byte from requested lane
|
||
// also, consume loaded value to cause
|
||
// a pipeline stall
|
||
2: //
|
||
ldq ra, CfgRa(sp) // restore return address
|
||
lda sp, CfgFrameLength(sp) // deallocate stack frame
|
||
ret zero, (ra) // return
|
||
|
||
.end READ_CONFIG_UCHAR
|
||
|
||
//++
|
||
//
|
||
// VOID
|
||
// WRITE_CONFIG_UCHAR(
|
||
// ULONG ConfigurationAddress,
|
||
// UCHAR ConfigurationData,
|
||
// ULONG ConfigurationCycleType
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// Read an unsigned byte from PCI configuration space.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// ConfigurationAddress(a0) - Supplies the QVA to write.
|
||
//
|
||
// ConfigurationData(a1) - Supplies the data to be written.
|
||
//
|
||
// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// None.
|
||
//
|
||
// N.B. - The configuration address must exist within the address space
|
||
// allocated to an existing PCI device. Otherwise, the access
|
||
// below will initiate an unrecoverable machine check.
|
||
//
|
||
//--
|
||
|
||
NESTED_ENTRY( WRITE_CONFIG_UCHAR, CfgFrameLength, zero )
|
||
|
||
lda sp, -CfgFrameLength(sp) // allocate stack frame
|
||
stq ra, CfgRa(sp) // save return address
|
||
|
||
PROLOGUE_END // end prologue
|
||
|
||
//
|
||
// Merge the configuration cycle type into the HAXR2 register within
|
||
// the EPIC.
|
||
//
|
||
|
||
stq a0, CfgA0(sp) // save configuration space address
|
||
stq a1, CfgA1(sp) // save configuration data
|
||
stq a2, CfgA2(sp) // save configuration cycle type
|
||
|
||
ldil a0, EPIC_HAXR2_QVA // address of HAXR2
|
||
bsr ra, READ_EPIC_REGISTER // read current value
|
||
|
||
ldq a1, CfgA2(sp) // restore configuration cycle type
|
||
bic v0, 0x3, t0 // clear config cycle type field
|
||
bis a1, t0, a1 // merge config cycle type
|
||
ldil a0, EPIC_HAXR2_QVA // address of HAXR2
|
||
bsr ra, WRITE_EPIC_REGISTER // write updated HAXR2
|
||
|
||
//
|
||
// Perform the read from configuration space after restoring the
|
||
// configuration space address and data.
|
||
//
|
||
|
||
ldq a0, CfgA0(sp) // restore configuration space address
|
||
ldq a1, CfgA1(sp) // restore configuration data
|
||
|
||
and a0, QVA_SELECTORS, t1 // get qva selector bits
|
||
and a0, 0x3, t3 // capture byte lane
|
||
xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
|
||
bne t1, 2f // if ne, iff failed
|
||
|
||
zap a0, 0xf0, a0 // clear <63:32>
|
||
bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
|
||
sll a0, IO_BIT_SHIFT, t0 //
|
||
ldiq t4, -0x4000 //
|
||
sll t4, 28, t4 //
|
||
bis t0, t4, t0 // superpage mode
|
||
|
||
bis t0, IO_BYTE_LEN, t0 // or in the byte length indicator
|
||
|
||
insbl a1, t3, t4 // put byte in the appropriate lane
|
||
stl t4, (t0) // write the configuration byte
|
||
mb // synchronize
|
||
|
||
2: //
|
||
ldq ra, CfgRa(sp) // restore return address
|
||
lda sp, CfgFrameLength(sp) // deallocate stack frame
|
||
ret zero, (ra) // return
|
||
|
||
.end WRITE_CONFIG_UCHAR
|
||
|
||
//++
|
||
//
|
||
// ULONG
|
||
// READ_CONFIG_USHORT(
|
||
// ULONG ConfigurationAddress,
|
||
// ULONG ConfigurationCycleType
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// Read a longword from PCI configuration space.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
|
||
//
|
||
// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// (v0) Returns the value of configuration space at the specified location.
|
||
//
|
||
// N.B. - This routine follows a protocol for reading from PCI configuration
|
||
// space that allows the HAL or firmware to fixup and continue
|
||
// execution if no device exists at the configuration target address.
|
||
// The protocol requires 2 rules:
|
||
// (1) The configuration space load must use a destination register
|
||
// of v0
|
||
// (2) The instruction immediately following the configuration space
|
||
// load must use v0 as an operand (it must consume the value
|
||
// returned by the load)
|
||
//--
|
||
|
||
NESTED_ENTRY( READ_CONFIG_USHORT, CfgFrameLength, zero )
|
||
|
||
lda sp, -CfgFrameLength(sp) // allocate stack frame
|
||
stq ra, CfgRa(sp) // save return address
|
||
|
||
PROLOGUE_END // end prologue
|
||
|
||
//
|
||
// Merge the configuration cycle type into the HAXR2 register within
|
||
// the EPIC.
|
||
//
|
||
|
||
stq a0, CfgA0(sp) // save configuration space address
|
||
stq a1, CfgA1(sp) // save configuration cycle type
|
||
|
||
ldil a0, EPIC_HAXR2_QVA // address of HAXR2
|
||
bsr ra, READ_EPIC_REGISTER // read current value
|
||
|
||
ldq a1, CfgA1(sp) // restore configuration cycle type
|
||
bic v0, 0x3, t0 // clear config cycle type field
|
||
bis a1, t0, a1 // merge config cycle type
|
||
ldil a0, EPIC_HAXR2_QVA // address of HAXR2
|
||
bsr ra, WRITE_EPIC_REGISTER // write updated HAXR2
|
||
|
||
//
|
||
// Perform the read from configuration space after restoring the
|
||
// configuration space address.
|
||
//
|
||
|
||
ldq a0, CfgA0(sp) // restore configuration space address
|
||
|
||
and a0, QVA_SELECTORS, t1 // get qva selector bits
|
||
and a0, 0x3, t3 // capture word offset
|
||
xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
|
||
bne t1, 2f // if ne, iff failed
|
||
|
||
zap a0, 0xf0, a0 // clear <63:32>
|
||
bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
|
||
sll a0, IO_BIT_SHIFT, t0 //
|
||
ldiq t4, -0x4000 //
|
||
sll t4, 28, t4 //
|
||
bis t0, t4, t0 // superpage mode
|
||
|
||
bis t0, IO_WORD_LEN, t0 // or in the byte enables
|
||
|
||
ldl v0, (t0) // read the longword
|
||
extwl v0, t3, v0 // return word from requested lanes
|
||
// also, consume loaded value to cause
|
||
// a pipeline stall
|
||
2: //
|
||
ldq ra, CfgRa(sp) // restore return address
|
||
lda sp, CfgFrameLength(sp) // deallocate stack frame
|
||
ret zero, (ra) // return
|
||
|
||
.end READ_CONFIG_USHORT
|
||
|
||
//++
|
||
//
|
||
// VOID
|
||
// WRITE_CONFIG_USHORT(
|
||
// ULONG ConfigurationAddress,
|
||
// USHORT ConfigurationData,
|
||
// ULONG ConfigurationCycleType
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// Read a longword from PCI configuration space.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// ConfigurationAddress(a0) - Supplies the QVA to write.
|
||
//
|
||
// ConfigurationData(a1) - Supplies the data to be written.
|
||
//
|
||
// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// (v0) Returns the value of configuration space at the specified location.
|
||
//
|
||
// N.B. - The configuration address must exist within the address space
|
||
// allocated to an existing PCI device. Otherwise, the access
|
||
// below will initiate an unrecoverable machine check.
|
||
//
|
||
//--
|
||
|
||
NESTED_ENTRY( WRITE_CONFIG_USHORT, CfgFrameLength, zero )
|
||
|
||
lda sp, -CfgFrameLength(sp) // allocate stack frame
|
||
stq ra, CfgRa(sp) // save return address
|
||
|
||
PROLOGUE_END // end prologue
|
||
|
||
//
|
||
// Merge the configuration cycle type into the HAXR2 register within
|
||
// the EPIC.
|
||
//
|
||
|
||
stq a0, CfgA0(sp) // save configuration space address
|
||
stq a1, CfgA1(sp) // save configuration data
|
||
stq a2, CfgA2(sp) // save configuration cycle type
|
||
|
||
ldil a0, EPIC_HAXR2_QVA // address of HAXR2
|
||
bsr ra, READ_EPIC_REGISTER // read current value
|
||
|
||
ldq a1, CfgA2(sp) // restore configuration cycle type
|
||
bic v0, 0x3, t0 // clear config cycle type field
|
||
bis a1, t0, a1 // merge config cycle type
|
||
ldil a0, EPIC_HAXR2_QVA // address of HAXR2
|
||
bsr ra, WRITE_EPIC_REGISTER // write updated HAXR2
|
||
|
||
//
|
||
// Perform the read from configuration space after restoring the
|
||
// configuration space address and data.
|
||
//
|
||
|
||
ldq a0, CfgA0(sp) // restore configuration space address
|
||
ldq a1, CfgA1(sp) // restore configuration data
|
||
|
||
and a0, QVA_SELECTORS, t1 // get qva selector bits
|
||
and a0, 0x3, t3 // capture word offset
|
||
xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
|
||
bne t1, 2f // if ne, iff failed
|
||
|
||
zap a0, 0xf0, a0 // clear <63:32>
|
||
bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
|
||
sll a0, IO_BIT_SHIFT, t0 //
|
||
ldiq t4, -0x4000 //
|
||
sll t4, 28, t4 //
|
||
bis t0, t4, t0 // superpage mode
|
||
|
||
bis t0, IO_WORD_LEN, t0 // or in the byte enables
|
||
|
||
inswl a1, t3, t4 // put data to appropriate lane
|
||
stl t4, (t0) // read the longword
|
||
mb // synchronize
|
||
2: //
|
||
ldq ra, CfgRa(sp) // restore return address
|
||
lda sp, CfgFrameLength(sp) // deallocate stack frame
|
||
ret zero, (ra) // return
|
||
|
||
.end WRITE_CONFIG_USHORT
|
||
|
||
//++
|
||
//
|
||
// ULONG
|
||
// READ_CONFIG_ULONG(
|
||
// ULONG ConfigurationAddress,
|
||
// ULONG ConfigurationCycleType
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// Read a longword from PCI configuration space.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// ConfigurationAddress(a0) - Supplies the QVA of quadword to be read.
|
||
//
|
||
// ConfigurationCycleType(a1) - Supplies the type of the configuration cycle.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// (v0) Returns the value of configuration space at the specified location.
|
||
//
|
||
// N.B. - This routine follows a protocol for reading from PCI configuration
|
||
// space that allows the HAL or firmware to fixup and continue
|
||
// execution if no device exists at the configuration target address.
|
||
// The protocol requires 2 rules:
|
||
// (1) The configuration space load must use a destination register
|
||
// of v0
|
||
// (2) The instruction immediately following the configuration space
|
||
// load must use v0 as an operand (it must consume the value
|
||
// returned by the load)
|
||
//--
|
||
|
||
NESTED_ENTRY( READ_CONFIG_ULONG, CfgFrameLength, zero )
|
||
|
||
lda sp, -CfgFrameLength(sp) // allocate stack frame
|
||
stq ra, CfgRa(sp) // save return address
|
||
|
||
PROLOGUE_END // end prologue
|
||
|
||
//
|
||
// Merge the configuration cycle type into the HAXR2 register within
|
||
// the EPIC.
|
||
//
|
||
|
||
stq a0, CfgA0(sp) // save configuration space address
|
||
stq a1, CfgA1(sp) // save configuration cycle type
|
||
|
||
ldil a0, EPIC_HAXR2_QVA // address of HAXR2
|
||
bsr ra, READ_EPIC_REGISTER // read current value
|
||
|
||
ldq a1, CfgA1(sp) // restore configuration cycle type
|
||
bic v0, 0x3, t0 // clear config cycle type field
|
||
bis a1, t0, a1 // merge config cycle type
|
||
ldil a0, EPIC_HAXR2_QVA // address of HAXR2
|
||
bsr ra, WRITE_EPIC_REGISTER // write updated HAXR2
|
||
|
||
//
|
||
// Perform the read from configuration space after restoring the
|
||
// configuration space address.
|
||
//
|
||
|
||
ldq a0, CfgA0(sp) // restore configuration space address
|
||
|
||
and a0, QVA_SELECTORS, t1 // get qva selector bits
|
||
xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
|
||
bne t1, 2f // if ne, iff failed
|
||
|
||
zap a0, 0xf0, a0 // clear <63:32>
|
||
bic a0, QVA_ENABLE,a0 // clear QVA fields so shift is correct
|
||
sll a0, IO_BIT_SHIFT, t0 //
|
||
ldiq t4, -0x4000 //
|
||
sll t4, 28, t4 //
|
||
or t0, t4, t0 // superpage mode
|
||
|
||
or t0, IO_LONG_LEN, t0 // or in the byte enables
|
||
|
||
ldl v0, (t0) // read the longword
|
||
bis v0, zero, t1 // consume loaded value to cause
|
||
// a pipeline stall
|
||
2: //
|
||
ldq ra, CfgRa(sp) // restore return address
|
||
lda sp, CfgFrameLength(sp) // deallocate stack frame
|
||
ret zero, (ra) // return
|
||
|
||
.end READ_CONFIG_ULONG
|
||
|
||
|
||
//++
|
||
//
|
||
// VOID
|
||
// WRITE_CONFIG_ULONG(
|
||
// ULONG ConfigurationAddress,
|
||
// ULONG ConfigurationData,
|
||
// ULONG ConfigurationCycleType
|
||
// )
|
||
//
|
||
// Routine Description:
|
||
//
|
||
// Read a longword from PCI configuration space.
|
||
//
|
||
// Arguments:
|
||
//
|
||
// ConfigurationAddress(a0) - Supplies the QVA to write.
|
||
//
|
||
// ConfigurationData(a1) - Supplies the data to be written.
|
||
//
|
||
// ConfigurationCycleType(a2) - Supplies the type of the configuration cycle.
|
||
//
|
||
// Return Value:
|
||
//
|
||
// (v0) Returns the value of configuration space at the specified location.
|
||
//
|
||
// N.B. - The configuration address must exist within the address space
|
||
// allocated to an existing PCI device. Otherwise, the access
|
||
// below will initiate an unrecoverable machine check.
|
||
//
|
||
//--
|
||
|
||
NESTED_ENTRY( WRITE_CONFIG_ULONG, CfgFrameLength, zero )
|
||
|
||
lda sp, -CfgFrameLength(sp) // allocate stack frame
|
||
stq ra, CfgRa(sp) // save return address
|
||
|
||
PROLOGUE_END // end prologue
|
||
|
||
//
|
||
// Merge the configuration cycle type into the HAXR2 register within
|
||
// the EPIC.
|
||
//
|
||
|
||
stq a0, CfgA0(sp) // save configuration space address
|
||
stq a1, CfgA1(sp) // save configuration data
|
||
stq a2, CfgA2(sp) // save configuration cycle type
|
||
|
||
ldil a0, EPIC_HAXR2_QVA // address of HAXR2
|
||
bsr ra, READ_EPIC_REGISTER // read current value
|
||
|
||
ldq a1, CfgA2(sp) // restore configuration cycle type
|
||
bic v0, 0x3, t0 // clear config cycle type field
|
||
bis a1, t0, a1 // merge config cycle type
|
||
ldil a0, EPIC_HAXR2_QVA // address of HAXR2
|
||
bsr ra, WRITE_EPIC_REGISTER // write updated HAXR2
|
||
|
||
//
|
||
// Perform the read from configuration space after restoring the
|
||
// configuration space address and data.
|
||
//
|
||
|
||
ldq a0, CfgA0(sp) // restore configuration space address
|
||
ldq a1, CfgA1(sp) // restore configuration data
|
||
|
||
and a0, QVA_SELECTORS, t1 // get qva selector bits
|
||
xor t1, QVA_ENABLE, t1 // ok iff QVA_ENABLE set in selectors
|
||
bne t1, 2f // if ne, iff failed
|
||
|
||
zap a0, 0xf0, a0 // clear <63:32>
|
||
bic a0, QVA_ENABLE, a0 // clear QVA fields so shift is correct
|
||
sll a0, IO_BIT_SHIFT, t0 //
|
||
ldiq t4, -0x4000 //
|
||
sll t4, 28, t4 //
|
||
bis t0, t4, t0 // superpage mode
|
||
|
||
bis t0, IO_LONG_LEN, t0 // or in the byte enables
|
||
|
||
stl a1, (t0) // write the longword
|
||
mb // synchronize
|
||
2: //
|
||
ldq ra, CfgRa(sp) // restore return address
|
||
lda sp, CfgFrameLength(sp) // deallocate stack frame
|
||
ret zero, (ra) // return
|
||
|
||
.end WRITE_CONFIG_ULONG
|