Files
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

407 lines
12 KiB
ArmAsm

# @(#)70 1.4 src/bos/kernel/ml/POWER/dma_pwr.s, sysios, bos411, 9428A410j 7/27/93 20:53:31
#*****************************************************************************
#
# COMPONENT_NAME: (SYSIOS)
#
# FUNCTIONS: d_kmove iocc_rw iocc_str master_flush
#
# ORIGINS: 27, 83
#
# IBM CONFIDENTIAL -- (IBM Confidential Restricted when
# combined with the aggregated modules for this product)
# SOURCE MATERIALS
# (C) COPYRIGHT International Business Machines Corp. 1990,1993
# All Rights Reserved
#
# US Government Users Restricted Rights - Use, duplication or
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
#
#
# LEVEL 1, 5 Years Bull Confidential Information
#
#****************************************************************************
.file "dma_pwr.s"
.machine "pwr"
.using low, r0
include(macros.m4)
ifdef(`_POWER_RS',`
#------------------------------------------------------------------------------
#
# NAME: iocc_rw
#
# FUNCTION: word access to the IOCC. Sets up an exception handler, and will
# retry the load/store if an exception occurs.
#
# CALL: int iocc_rw(direction, address, data)
# ulong direction; /* 0 - read 1 - write */
# ulong *address; /* IOCC address */
# ulong data; /* for write contains data to write */
#
# EXECUTION ENVORONMENT:
# called only by the DMA services
#
# RETURNS:
# for read returns value loaded
# for write returns 0
#
#------------------------------------------------------------------------------
S_PROLOG(iocc_rw)
LTOC(r7, iocc_excpt, data) # get address of exception handler
cmpi cr1, r3, 0 # check the read/write flag
GET_CSA(cr0, r8, r6) # get pointer to current mst
lil r8, PIO_RETRY_COUNT # initialize retry counter
iocc_retry:
st r7, excbranch(r6) # set up exception handler
beq cr1, iocc_read # branch if direction == 0
st r5, 0(r4) # careful, this could except
lil r3, 0
st r3, excbranch(r6) # clear exception handler
br # return success
iocc_read:
l r3, 0(r4) # carefull, this could except
lil r4, 0
st r4, excbranch(r6) # clear exception handler
br # return success
iocc_excpt:
cmpi cr0, r3, EXCEPT_IO # check exception code
bne cr0, iocc_trap # if its not an IO exception then trap
ai. r8, r8, -1 # decrement retry count
bge cr0, iocc_retry # if retry_count >= 0 then retry it
iocc_trap:
TRAP
#-----------------------------------------------------------------------------
#
# NAME: d_kmove_rs1
#
# FUNCTION: This service provides consistent access to memory
# when a device and its driver both have access to system
# memory.
#
# CALL: int d_kmove(baddr, daddr, count, channel_id, bid, flags)
# char *baddr; /* buffer address */
# char *daddr; /* bus address */
# int count; /* number of bytes to move */
# int channel_id; /* channel to use */
# int bid;
# int flags; /* control flags */
#
#
# EXECUTION ENVIRONMENT:
# This service can be called on either the process or
# interrupt level
#
# baddr must be in kernel address space
#
# It only page faults on the stack when under a process
#
# NOTES:
# This is a specialized interface for the d_move service.
#
# RETURN VALUE:
# 0 = successful
# -1 = not successful
# EINVAL = Operation not supported
#
#-----------------------------------------------------------------------------
.set ICF_BUF_MSK, 0x30 # mask for type of iocc buffering
.set ICF_UNBUFF, 0x10 # un-bufferd iocc
.set DMA_READ, 0x80
.set CSR15_HI, 0xb04f # effective address for csr15.
.set CSR15_LO, 0x0060 # Using segment 12
.set BUID_MASK, 0x0ff00000 # mask bid to buid value
.set IO_SEG_HI, 0x800c # srval used to access csr15
.set IO_SEG_LO, 0x00e0
S_PROLOG(d_kmove_rs1)
# Save some registers for use as local variables.
# Register usage:
# r31 - saved msr value
# r30 - seg reg 12 save value
# r29 - seg reg 11 save value
# r28 - old interrupt priority
# r27 - csr save value
LTOC(r9, iocc_config, data) # get shadow copy of iocc config reg
l r9, 0(r9)
stm r27, -5*4(r1)
rlinm r9, r9, 0, ICF_BUF_MSK # mask out bufferd bits
cmpi cr0, r9, ICF_UNBUFF # check for unbuffed iocc
mfmsr r31 # save the old msr value
# in cr0 for later use.
rlinm r0, r31, 0, ~MSR_EE # calculate the INTMAX msr value
GET_CSA(cr1, r10, r12) # get pointer to our state save area
beq cr0, bad_move # branch if RSC (unbuffered iocc)
mfsr r30, sr12 # save sr12
lbz r28, mstintpri(r12) # save old interrupt priority
mtmsr r0 # disable the machine
cmpi cr5, r28, INTBASE # check if we are at intbase
mfsr r29, sr11 # save sr11
rlinm. r8, r8, 0, DMA_READ # check if read or write. Save result
lil r9, INTMAX # new interrupt priority
bne cr5, fixed_stack # branch if oldpri != INTBASE. All
# ready has a fixed stack
# set stack fix, and touch the stack. If this faults resume will carefully
# touch the stack before we run again
st r1, mststackfix(r12)
l r0, -STACKTOUCH(r1)
l r0, 0(r1)
l r0, STACKTOUCH(r1)
fixed_stack:
stb r9, mstintpri(r12) # set new interrupt priority
rlinm r9, r7, 0, BUID_MASK # mask the given buid
oriu r9, r9, IO_SEG_HI # set io seg address check and
# increment
oril r10, r9, IO_SEG_LO # set IOCC select, 24-bit mode and
# bypass mode
mtsr sr11, r10 # load seg for access to to csr15
liu r8, CSR15_HI # upper 16 bits of csr15 address
l r27, CSR15_LO(r8) # save old value of CSR15
sli r11, r6, 16 # new csr val
# CSR(0, channel, MASTER_NO_AUTHORITY)
st r11, CSR15_LO(r8) # set the CSR15 value
mtsr sr12, r9 # load bus segment, address check,
# address increment, bypass bit off
oriu r4, r4, 0xc000 # calculate the effective address for
# bus
beq cr0, dma_write # branch if DMA_READ was not set in
# flags
mr r0, r3
mr r3, r4
mr r4, r0
dma_write:
LTOC(r7, kdexcpt, data) # get address of exception handler
sri. r6, r5, 5 # r6 = count / 32
rlinm r0, r5, 0, 0x1f # r0 = count % 32
st r7, excbranch(r12) # set up exception handler
mtxer r0 # setup xer for copy of remainder
beq small # branch if count < 32
mtctr r6 # count of 32 byte chunks to move
loop:
lsi r5, r3, 32 # move memory
ai r3, r3, 32
stsi r5, r4, 32
ai r4, r4, 32
bdn loop
small:
lsx r5, 0, r3 # move the remainder
stsx r5, 0, r4
GET_CSA(cr0, r11, r12) # get current mst pointer
lil r3, 0 # get return code
st r3, excbranch(r12) # clear the exception handler
cleanup:
liu r11, CSR15_HI # get high part of csr15 address
st r27, CSR15_LO(r11) # retore CSR15 value
mtsr sr12, r30
mtsr sr11, r29
stb r28, mstintpri(r12)
bne cr5, still_fixed # branch if we were called on a fixed
# stack
cal r4, NULL(0) # clear mststackfix to return to
st r4, mststackfix(r12) # non - fixed stack
still_fixed:
mtmsr r31 # enable interrupts
exit:
lm r27, -5*4(r1) # restore non-volatile registers
br # return
kdexcpt:
l r4, syscfg_impl(0) # get implementation
andil. r4, r4, POWER_RS2 # check if its an RS2
LTOC(r4, i_data, data) # Load addr of interrupt mask table
bne kdrs2 # branch if on RS2
mfsr r9, sr15 # Save segment reg 15
cau r8, 0, BUID0 # Set segment register 15
mtsr sr15, r8 # to allow I/O access
rlinm r5, r28, 3, 0x7F8 # Mult by 8 to get mask index
a r5, r5, r4 # get address of map
lsi r6, r5, 8 # load masks
cau r5, 0, 0xF000 # address of EIMs
stsi r6, r5, 8 # write EIMs
mtsr sr15, r9 # Restore segment reg 15
b kdfin
kdrs2:
lbzx r5, r28, r4 # get new CIL level
rlinm r5, r5, 8, 0xFF00 # generate ILCR command
mtspr ILCR, r5 # update CIL value
muli r3, r3, 1 # wait for update
muli r3, r3, 1
kdfin:
GET_CSA(cr0, r11, r12) # set up mst pointer
cal r3, -1(0) # set return code
b cleanup # cleanup and exit
bad_move:
lil r3, EINVAL # set return code
b exit # return to caller
FCNDES(d_kmove_rs1)
#-----------------------------------------------------------------------------
#
# NAME: master_flush
#
# FUNCTION: write buffer flush command to iocc. disables inline to INTMAX.
# and wraps exception handler around buffer flush.
#
# CALL: int master_flush(csr15addr, csr15val, tcwaddr, iocc_config_addr,
# errstate)
# ulong *csr15addr; /* effective address of CSR 15 */
# ulong car15val; /* value for CSR 15 while executing flush */
# ulong *tcwaddr; /* address to write flush command to */
# ulong *iocc_config_addr; /* must do a load from this addres */
# struc { /* info. for caller to clean up after error */
# int intpri;
# ulong csr15save;
# } *errstate;
#
# EXECUTION ENVIRONMENT:
# See MASTER_FLUSH macro in dma_hw.h
#
# RETURNS:
# 0 - on success
# EXCPT_IO - error occurred during flush. It is up to the caller to
# clean up. Channel status register 15 should be set to
# errstate->csr15save, then i_enable should be called to
# reset interrupt priority to errstate->intpri
#
#------------------------------------------------------------------------------
# register usage:
# r12 - mst
# r11 - msr save
# r10 - old intpri
# r8 - old csr15 value
S_PROLOG(master_flush)
GET_CSA(cr0, r11, r12) # get mst pointer
lbz r10, mstintpri(r12) # get old interrupt priority
mfmsr r11 # get old msr
cmpi cr1, r10, INTBASE # check if we are at INTBASE
rlinm r0, r11, 0, ~MSR_EE # generate disabled MSR
mtmsr r0
LTOC(r9, mf_excpt, data) # get address of exception handler
bne cr1, mf_fixed_stack # branch if we are already on a fixed
# stack
st r1, mststackfix(r12) # fix the stack
l r0, STACKTOUCH(r1) # touch the stack to be sure it
l r0, 0(r1) # is there
l r0, -STACKTOUCH(r1)
mf_fixed_stack:
# It is important that the software interrupt priority is not set
# until the stack is touched. This way the EIMs will not change
# if the stack touch page faults.
lil r0, INTMAX # Now set software interrupt priority
stb r0, mstintpri(r12)
l r8, 0(r3) # get old csr15 value
lil r0, 0
st r4, 0(r3) # set new csr15 value
st r9, excbranch(r12) # set up exception handler
st r0, 0(r5) # do flush -- this could except
st r8, 0(r3) # restore csr15
l r8, 0(r6) # for IOCC bug see LOAD_IOCC_CONFIG
st r0, excbranch(r12) # clear exception handler
bne cr1, mf_unfix_stack # branch if we entered on a fixed stack
st r0, mststackfix(r12) # clear stack fix
mf_unfix_stack:
lil r3, 0 # set return code
stb r10, mstintpri(r12) # restore software priority
mtmsr r11 # restore hardware priority
br
mf_excpt:
cmpi cr0, r3, EXCEPT_IO # Check for IO exception
bne cr0, mf_trap # if not except_io then trap
st r10, 0(r7) # save interrupt priority
st r8, 4(r7) # save old csr15
br # return to C
mf_trap:
TRAP
#------------------------------------------------------------------------------
#
# NAME: disable_chan
#
# FUNCTION: issue the disable command
#
# CALL: void disable_chan(disable_addr, io_addr)
# volatile ulong *disable_addr; /* address of disable command */
# volatile ulong *io_addr; /* address of any load io address */
#
# NOTES:
# A load to any IO address is issued before the store-disable command.
# If the disable command is surrounded by word aligned fixed point
# stores an RSC bug will show up
#
# RETURNS: None
#
#------------------------------------------------------------------------------
S_PROLOG(disable_chan)
l r5, 0(r4) # do dummy io load
st r5, 0(r3) # issue store command
br
_DF(_DF_NOFRAME)
.toc
TOCE(i_data, data)
TOCE(iocc_config, data)
TOCL(kdexcpt, data)
TOCL(iocc_excpt, data)
TOCL(mf_excpt, data)
',)
include(param.m4)
include(mstsave.m4)
include(low_dsect.m4)
include(i_machine.m4)
include(machine.m4)
include(scrs.m4)
include(except.m4)
include(errno.m4)
include(systemcfg.m4)