📄 intc.c
字号:
1. Make the FIQStatus using FIQRawStatus & Enable.
2. Set the nFiq signal
*/
static void FIQUpdate(IntCtrlState *intcs)
{
/* Make the FIQStatus using FIQRawStatus & FIQEnable */
intcs->myIntc.FIQStatus = intcs->myIntc.FIQRawStatus & intcs->myIntc.FIQEnable;
/* Set the nFiq signal */
if ( intcs->myIntc.FIQStatus )
{
/* There is at least ONE active interrupt ( although probably only one)
* - so trigger FIQ
*/
ARMulif_SetSignal(&intcs->coredesc, RDIPropID_ARMSignal_FIQ,
Signal_On);
}
else
{
/* There are no active interrupt sources - clear FIQ source */
ARMulif_SetSignal(&intcs->coredesc, RDIPropID_ARMSignal_FIQ,
Signal_Off);
}
}
/*
************************************************************************
* Memory veneer functions *
* Pass on the call to the real function, then check for the watchpoint.*
************************************************************************
*/
/*
Function Name: INTCRegisterAccess
Parameters:
IntcState *intcs - IntcState pointer - in this case the
MemAccess handle is the IntcState - but needs to
be cast to IntcState type.
ARMword addr - the 32 bit address to access
ARMword *word - pointer to the data word ARMulator want us to
fill in/read from depending on acc.
ARMul_acc acc - the access information ( read/write, seq etc. )
Return: int 0 = Waiting
1 = success
-1 = Abort
-2 = Address not decoded ** This is new for switch/peripherals
Description: Finished the address decoding that the switch started.
Resolves an address to a particular register - or rejects the
access if the decode fails or is to a reserved address.
For writes to registers FIQ/IRQUpdate is called, this ensures
that the interrupt registers and signals reflect any changes
immediately.
Notes: It may not be obvious why this code isn't in MemAccess.
This code is kept in a separate function to ease future
maintenance should the Memory interface be changed in the future.
*/
static int INTCRegisterAccess(IntCtrlState *intcs, ARMword addr, ARMword *word,
unsigned /*ARMul_acc*/ acc)
{
unsigned long maskedAddress = addr & 0x000001ff;
#ifdef VERBOSE_ACCESS
printf("INTCRegisterAccess, addr:%08lx range=(%08lx,%08lx) type:%04x "
"@data:%08lx \n",
(unsigned long)addr,
(unsigned long)intcs->range.lo,
(unsigned long)intcs->range.hi,
acc, *(ARMword*)word);
#endif
if (ACCESS_SIZE(acc) != ACCESS_WORD)
return PERIP_DABORT; /* Words are all we know about */
if ( ACCESS_IS_READ(acc) )
{
/* Read from registers */
switch ( maskedAddress)
{
case 0x00:
*word = intcs->myIntc.IRQStatus;
break;
case 0x04:
*word = intcs->myIntc.IRQRawStatus;
break;
case 0x08:
*word = intcs->myIntc.IRQEnable;
break;
case 0x100:
*word = intcs->myIntc.FIQStatus;
break;
case 0x104:
*word = intcs->myIntc.FIQRawStatus;
break;
case 0x108:
*word = intcs->myIntc.FIQEnable;
break;
case 0x0c:
case 0x10:
case 0x10c:
if (intcs->warn && ACCESS_IS_REAL(acc)) {
Hostif_ConsolePrint(intcs->hostif,
"Warning - attempted read from "
"Reserved INTC register address %08x\n",addr);
}
/* We accept the read - but always return 0 */
*word = 0;
break;
default:
return PERIP_NODECODE; /* Failed to decode address */
}
}
else
{
/* Write to registers */
switch ( maskedAddress)
{
case 0x0:
case 0x04:
case 0x100:
case 0x104:
if (intcs->warn && ACCESS_IS_REAL(acc)) {
Hostif_ConsolePrint(intcs->hostif,
"Warning - attempted write to "
"Reserved INTC register address %08x\n",addr);
}
/* We accept the write - but throw away the data */
break;
case 0x08:
intcs->myIntc.IRQEnable |= *word; /* IRQEnableSet - add set bits
to IRQEnable */
IRQUpdate(intcs);
break;
case 0x0c:
{
intcs->myIntc.IRQEnable &= ~(*word); /* IRQEnableClear - clear
the set bits in IRQEnable reg */
IRQUpdate(intcs);
break;
}
case 0x10:
/* IRQSoft - or programmed IRQ interrupt */
/* Only bit 1 has any effect. */
intcs->myIntc.IRQRawStatus &= ~2;
intcs->myIntc.IRQRawStatus |= *word & 2;
IRQUpdate(intcs);
break;
case 0x108:
intcs->myIntc.FIQEnable |= *word; /* FIQEnableSet - add set bits
to FIQEnable */
FIQUpdate(intcs);
break;
case 0x10c:
intcs->myIntc.FIQEnable &= ~(*word); /* FIQEnableClear - clear
the set bits in FIQEnable reg */
FIQUpdate(intcs);
break;
default:
return PERIP_NODECODE; /* Failed to decode address */
}
}
return PERIP_OK;
}
/* Bus state machine
*/
static int BusState(IntCtrlState *is, ARMword addr, ARMword *word,
unsigned /*ARMul_acc*/ acc)
{
#ifdef VERBOSE_ACCESS
printf("IntCtrl_Access/BusState addr:%08lx range=(%08lx,%08lx) type:%04x "
"@data:%08lx \n",
(unsigned long)addr,
(unsigned long)is->range.lo,
(unsigned long)is->range.hi,
acc, *(ARMword*)word);
#endif
if (!ACCESS_IS_REAL(acc)) {
return INTCRegisterAccess(is, addr, word, acc);
}
if ( is->accessState == 0 )
{
/* Idle on access */
if ( is->waitStates == 0)
{
/* No waits - do access now */
return INTCRegisterAccess(is,addr,word,acc);
}
else
{
/* First access -but with waits - so decrement and return 0*/
is->waits = is->waitStates;
is->accessState=1;
return PERIP_BUSY; /* tell core to wait */
}
}
else /* ( is->accessState == 1) */
{
/* Waiting state */
if ( is->waits == 0)
{
/* No waits - do access now */
is->accessState = 0; /* restore access state */
/* Post wait - doing access */
return INTCRegisterAccess(is,addr,word,acc);
}
else
{
/* Subsequent access -but with waits - so decrement and return 0*/
is->waits--;
/* Subsequent wait */
return PERIP_BUSY; /* tell core to wait */
}
}
/* accessState : 0=Idle, 1= Waiting */
}
/* Memory interface functions */
static int IntCtrl_Access(void *handle,
struct ARMul_AccessRequest *req)
{
IntCtrlState *is=(IntCtrlState *)handle;
/* We have idenfitied an intc memory access */
return BusState(is,req->req_address[0],req->req_data,
req->req_access_type);
}
/* Reset handler */
static void InitialiseState(IntCtrlState *intcs)
{
intcs->myIntc.IRQStatus=0;
intcs->myIntc.IRQRawStatus=0;
intcs->myIntc.IRQEnable=0; /*all interrupts disabled */
intcs->myIntc.IRQEnableClear=0;
intcs->myIntc.IRQSoft=0;
intcs->myIntc.FIQStatus=0;
intcs->myIntc.FIQRawStatus=0;
intcs->myIntc.FIQEnable=0;
intcs->myIntc.FIQEnableClear=0;
intcs->myIntc.nIRQ=1;
intcs->myIntc.nFIQ=1;
}
/*--- <SORDI STUFF> ---*/
#define SORDI_DLL_DESCRIPTION_STRING "Interrupt Controller "\
"(a Reference Peripheral)"
#define SORDI_RDI_PROCVEC IntCtrl_AgentRDI
#include "perip_sordi.h"
#include "perip_rdi_agent.h"
IMPLEMENT_AGENT_PROCS_NOEXE_NOMODULE(IntCtrl)
IMPLEMENT_AGENT_PROCVEC_NOEXE(IntCtrl)
/*--- </> ---*/
/* EOF intc.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -