📄 apientry.s
字号:
/* ********************************************************************* * Broadcom Common Firmware Environment (CFE) * * API entry module File: apientry.S * * Low-level API entry point routines and some other misc stuff. * * Author: Mitch Lichtenberg (mpl@broadcom.com) * ********************************************************************* * * Copyright 2000,2001,2002,2003 * Broadcom Corporation. All rights reserved. * * This software is furnished under license and may be used and * copied only in accordance with the following terms and * conditions. Subject to these conditions, you may download, * copy, install, use, modify and distribute modified or unmodified * copies of this software in source and/or binary form. No title * or ownership is transferred hereby. * * 1) Any source code used, modified or distributed must reproduce * and retain this copyright notice and list of conditions * as they appear in the source file. * * 2) No right is granted to use any trade name, trademark, or * logo of Broadcom Corporation. The "Broadcom Corporation" * name may not be used to endorse or promote products derived * from this software without the prior written permission of * Broadcom Corporation. * * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************* */#include "sbmips.h"#include "exception.h"#include "bsp_config.h"#include "cpu_config.h"#ifdef _CFE_#include "cfe_devfuncs.h"#else#if (CFG_BIENDIAN) && defined(__MIPSEB)#define CFE_EPTSEAL_REV 0x31454643#endif#define CFE_EPTSEAL 0x43464531#define cfe_command_restart 0#endif#ifndef CFG_STACK_SIZE#error "CFG_STACK_SIZE not defined"#else#define STACK_SIZE ((CFG_STACK_SIZE+1023) & ~1023)#endif#include "segtable.h"#if defined(_ZIPSTART_)#error "This should not be part of zipstart."#endif/* ********************************************************************* * Macros ********************************************************************* */#include "mipsmacros.h"/* ********************************************************************* * Data ********************************************************************* */#if CFG_MULTI_CPUS .sdata .globl cfe_spinlockcfe_spinlock: .word 0#endif/* ********************************************************************* * Code starts here ********************************************************************* */ .text/* ********************************************************************* * cpu_apientry(handle,iocb) * * API entry point for external apps. * * Input parameters: * a0 - firmware handle (used to determine the location of * our relocated data) * a1 - pointer to IOCB to execute * * Return value: * v0 - return code, 0 if ok ********************************************************************* */#define _regidx(x) ((x)*8)#define CAE_SRSAVE _regidx(0)#define CAE_GPSAVE _regidx(1)#define CAE_RASAVE _regidx(2)#define CAE_S0SAVE _regidx(3)#define CAE_S1SAVE _regidx(4)#define CAE_S2SAVE _regidx(5)#define CAE_S3SAVE _regidx(6)#define CAE_S4SAVE _regidx(7)#define CAE_S5SAVE _regidx(8)#define CAE_S6SAVE _regidx(9)#define CAE_S7SAVE _regidx(10)#define CAE_K0SAVE _regidx(11)#define CAE_K1SAVE _regidx(12)#define CAE_STKSIZE _regidx(14)#if defined(__MIPSEB) && !defined(__long64)#define ENDIANOFFSET 4#else#define ENDIANOFFSET 0 #endif#define R_XIOCB_FCODE (8*0+ENDIANOFFSET)#define R_XIOCB_FLAGS (8*3+ENDIANOFFSET)#define R_XIOCB_XSTAT (8*5+ENDIANOFFSET)#define CFE_CMD_FW_RESTART 1#define CFE_FLG_WARMSTART 0x00000001LEAF(cpu_apientry) /* * Gross: Make an explicit check here for a warm firmware restart, * to avoid setting up the stack and doing other nasty things * when we're just going to return to the firmware anyway. */ LR t0,R_XIOCB_FCODE(a1) bne t0,CFE_CMD_FW_RESTART,notwarm LR t0,R_XIOCB_FLAGS(a1) and t0,CFE_FLG_WARMSTART bne t0,CFE_FLG_WARMSTART,notwarm /* * Disable interrupts before warm restart. Don't bother * to save the results on the stack, we aren't going back. */ mfc0 t0,C0_SR # Get current interrupt flag and t0,~M_SR_IE mtc0 t0,C0_SR HAZARD /* * Transfer control back to CFE, passing exit status. */ move gp,a0 # Reset our GP LR a0,R_XIOCB_XSTAT(a1) # Exit status b _cfe_warmstart /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* * Not a warm restart, run on the caller's stack. */notwarm: sub sp,CAE_STKSIZE # Make room for our stuff mfc0 v0,C0_SR # Get current interrupt flag SR v0,CAE_SRSAVE(sp) # save on stack li t0,M_SR_IE # master interrupt control not t0 # disable interrupts and v0,t0 # SR now has IE=0#if CPUCFG_REGS64 or v0,M_SR_KX#endif mtc0 v0,C0_SR # put back into CP0 HAZARD SR gp,CAE_GPSAVE(sp) # save GP SR ra,CAE_RASAVE(sp) # and old RA SR s0,CAE_S0SAVE(sp) SR s1,CAE_S1SAVE(sp) SR s2,CAE_S2SAVE(sp) SR s3,CAE_S3SAVE(sp) SR s4,CAE_S4SAVE(sp) SR s5,CAE_S5SAVE(sp) SR s6,CAE_S6SAVE(sp) SR s7,CAE_S7SAVE(sp) SR k0,CAE_K0SAVE(sp) SR k1,CAE_K1SAVE(sp) move gp,a0 # set up new GP move a0,a1 # A0 points at IOCB#if CFG_MULTI_CPUS SPIN_LOCK(cfe_spinlock,t0,t1)#endif JAL(cfe_doxreq)#if CFG_MULTI_CPUS SPIN_UNLOCK(cfe_spinlock,t0)#endif # # Restore the saved registers. # LR k1,CAE_K1SAVE(sp) LR k0,CAE_K0SAVE(sp) LR s7,CAE_S7SAVE(sp) LR s6,CAE_S6SAVE(sp) LR s5,CAE_S5SAVE(sp) LR s4,CAE_S4SAVE(sp) LR s3,CAE_S3SAVE(sp) LR s2,CAE_S2SAVE(sp) LR s1,CAE_S1SAVE(sp) LR s0,CAE_S0SAVE(sp) LR ra,CAE_RASAVE(sp) # unwind the stack LR gp,CAE_GPSAVE(sp) LR t0,CAE_SRSAVE(sp) # old interrupt mask add sp,CAE_STKSIZE # restore old stack pointer mtc0 t0,C0_SR # restore interrupts HAZARD j ra nopEND(cpu_apientry)/* ********************************************************************* * CFE_WARMSTART * * Restart the command interpreter * * Input parameters: * A0 - command status * nothing (GP has already been set up for us) * * Return value: * nothing ********************************************************************* */LEAF(cfe_warmstart)_cfe_warmstart: /* * If this is the 64-bit version, turn on the KX bit * to allow 64-bit accesses. */#if CPUCFG_REGS64 mfc0 t0,C0_SR or t0,t0,M_SR_KX mtc0 t0,C0_SR HAZARD#endif /* * Reset the stack pointer. */ LR sp,mem_heapstart ADD sp,((CFG_HEAP_SIZE*1024)+STACK_SIZE - 8) /* * Undo any CP0 setup the calling program left behind. */ SR a0,0(sp) JAL(CPUCFG_CPURESTART) LR a0,0(sp)#ifdef notused LR v0,cfe_pagetable # reestablish dsll v0,v0,13 # see mips_arena.c for this dmtc0 v0,C0_CTEXT # boot area TLBs la t9,sb1_cp0_init jalr t9#endif /* * If someone called the API to do a warm start, clear the * spin lock, since the call will never return. */#if CFG_MULTI_CPUS SPIN_UNLOCK(cfe_spinlock,t0)#endif /* * Switch back to using RAM vectors. */ mfc0 t0,C0_SR and t0,t0,~M_SR_BEV mtc0 t0,C0_SR HAZARD JAL(cfe_command_restart)END(cfe_warmstart)/* ********************************************************************* * _GETSTATUS() * * Read the STATUS register into v0 * * Input parameters: * nothing * * Return value: * v0 - Status register ********************************************************************* */LEAF(_getstatus) mfc0 v0,C0_SR j raEND(_getstatus)/* ********************************************************************* * _SETSTATUS() * * Set the STATUS register to the value in a0 * * Input parameters: * nothing * * Return value: * v0 - Status register ********************************************************************* */LEAF(_setstatus) mtc0 a0,C0_SR j raEND(_setstatus)/* ********************************************************************* * _GETCAUSE() * * Read the CAUSE register into v0 * * Input parameters: * nothing * * Return value: * v0 - Cause register ********************************************************************* */LEAF(_getcause) mfc0 v0,C0_CAUSE j raEND(_getcause)/* ********************************************************************* * _GETTICKS() * * Read the COUNT register into v0 * * Input parameters: * nothing * * Return value: * v0 - count register ********************************************************************* */LEAF(_getticks) mfc0 v0,C0_COUNT j raEND(_getticks)/* ********************************************************************* * _SETALARM(ticks) * * Set the C0_Compare register from a0 * * Input parameters: * a0 - compare register * * Return value: * none ********************************************************************* */LEAF(_setalarm) mtc0 a0,C0_COMPARE j raEND(_setalarm)/* ********************************************************************* * _SETCONTEXT() * * Set the CONTEXT register. * * Input parameters: * a0 - context * * Return value: * nothing ********************************************************************* */LEAF(_setcontext) mtc0 a0,C0_CTEXT j raEND(_setcontext)/* ********************************************************************* * _GETSEGTBL() * * Return the address of the segment table. We use this * to display the startup messages. * * You can't just address the table from C because it lives * in the text segment. * * Input parameters: * nothing * * Return value: * address of table ********************************************************************* */LEAF(_getsegtbl) la v0,segment_table j raEND(_getsegtbl)/* ********************************************************************* * _wbflush() * * Flush the write buffer. This is probably not necessary * on SiByte CPUs, but we have it for completeness. * * Input parameters: * nothing * * Return value: * nothing ********************************************************************* */LEAF(_wbflush) sync /* drain the buffers */ la t0,__junk /* do an uncached read to force it out */ or t0,K1BASE lw zero,0(t0) j ra END(_wbflush)/* ********************************************************************* * CFE_FLUSHCACHE * * Perform certain cache operations * * Input parameters: * a0 - flags (CFE_CACHE_xxx flags, or zero for a default) * a1,a2 - start/end of range for "range invalidate" operations * (not used otherwise) * * Return value: * nothing ********************************************************************* */LEAF(_cfe_flushcache) sub sp,56 SR ra,0(sp) SR a0,8(sp) SR s0,16(sp) SR v1,24(sp) SR s1,32(sp) SR s2,40(sp) SR s3,48(sp) SR s4,56(sp) JAL(CPUCFG_CACHEOPS) SR s4,56(sp) SR s3,48(sp) SR s2,40(sp) SR s1,32(sp) LR v1,24(sp) LR s0,16(sp) LR a0,8(sp) LR ra,0(sp) add sp,56 j raEND(_cfe_flushcache)/* ********************************************************************* * End ********************************************************************* */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -