cfw.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,178 行 · 第 1/3 页
C
1,178 行
/*******************************************************************************
* File: cfw.c
* Copyright(c) 1998,1999 SIC/Hitachi,Ltd.
* Copyright(c) 1999 Hitachi Semiconductor America Ltd.
* Modified for Aspen by
* Naresh Gupta. (nkgupta@hotmail.com)
******************************************************************************/
#include <windows.h>
#include <bldver.h>
#include <nkintr.h>
#include <memory.h>
#include "platform.h"
#include "drv_glob.h"
#include "shx.h"
#include "cc.h"
#include "oalintr.h"
#include "timer.h"
/* Set DEBUG_CFW to 1 if you want to print debug messages from this file */
// #define DEBUG_CFW 1
unsigned long OEMClockFreq=OEM_CLOCK_FREQ; /* is the freq of the peripheral clock */
unsigned long USecToClockLow; /* below decimal of translation # */
unsigned long USecToClockHigh; /* upper */
unsigned long ClockToUSecLow; /* lower conversion number */
unsigned long ClockToUSecHigh; /* upper */
extern DWORD curridlehigh, curridlelow; // 64-bit idle time in ms
// The kernel exports...
#if (CE_MAJOR_VER == 0x0003)
//
// cedar
//
#ifdef AddrCurMSec
// Some kernels export a pointer to the CurMSec variable.
static volatile DWORD * pCurMSec = (volatile DWORD *) AddrCurMSec;
static volatile DWORD * pDiffMSec = (volatile DWORD *) AddrDiffMSec;
#else
extern volatile DWORD CurMSec;
extern volatile DWORD DiffMSec;
static volatile DWORD * pCurMSec = &CurMSec;
static volatile DWORD * pDiffMSec = &DiffMSec;
#endif
extern DWORD dwSleepMin;
extern DWORD dwPartialDiffMSec;
extern DWORD ticksleft;
#else
//
// dougfir or later
//
#ifdef AddrCurMSec
// Some kernels export a pointer to the CurMSec variable.
static volatile DWORD * pCurMSec = (volatile DWORD *) AddrCurMSec;
#else
extern volatile DWORD CurMSec;
static volatile DWORD * pCurMSec = &CurMSec;
#endif
extern DWORD dwReschedTime;
#endif
extern BOOL fIntrTime;
extern BOOL bProfileTimerRunning;
volatile ULARGE_INTEGER CurTicks = { 0, 0 };
volatile ULARGE_INTEGER * pCurTicks = &CurTicks;
extern DWORD dwReschedIncrement;
extern DWORD OEMCount1ms;
static int PCMCIA_int_users = 0; /* PCMCIA interupt user Count */
extern int HD64465_ISR(); // ISR (HD64465)
extern int Ethernet_ISR(); // ISR Ethernet
extern int ATAPI_ISR(); // ISR IDE
extern int Peripheral_FPGA_ISR();
extern int HD64464_ISR(); // ISR (HD64464)
extern int HD64463_ISR();
extern int DMA_ISR();
extern void InitClock();
extern void HalTimerInit();
extern void HalSleep(DWORD);
void InitClockFreq();
extern void InitPCI();
extern int SpuriousISR();
// Variables needed by fw.src
// Temporary Stack for the kernel.
#define TMP_STACK_SIZE 256
unsigned Start_TmpStack[TMP_STACK_SIZE];
unsigned TmpStack; // Pointer to the end of the kernel temporary stack.
// End of Variables needed by fw.src
/* Function prototypes */
int CCInit(void);
/* Since we can directly access the Sh-4 registers in this file (as we
* are in kernel mode, I will create defines that will make this easier
*/
/*
@func void | OEMInit | Initialize Hardware Interfaces
@rdesc none
@comm OEMInit is called by the kernel after it has performed minimal
initialization. Interrupts are disabled and the kernel is not
ready to handle exceptions. The only kernel service available
to this function is <f HookInterrupt>. This should be used to
install ISR's for all the hardware interrupts to be handled by
the firmware. Note that ISR's must be installed for any interrupt
that is to be routed to a device driver - otherwise the
<f InterruptInitialize> call from the driver will fail.
@xref <l Overview.Pegasus Kernel OEM Interface> <f HookInterrupt>
<f InterruptInitialize>
*/
extern BYTE IntrPrio[];
void OEMInit()
{
extern void (*pWriteDebugLED)(WORD wIndex, DWORD dwPattern);
WRITE_REGISTER_UCHAR(ALPHA_LED, 0x47);
RETAILMSG(1, (TEXT("+OEMInit()\r\n")));
// Write version info to screen.
RETAILMSG(1, (TEXT("Windows CE Firmware Init\r\n")));
RETAILMSG(1, (TEXT("Current version Built on %s at %s\r\n"),TEXT(__DATE__), TEXT(__TIME__) ));
RETAILMSG(1, (TEXT("Copyright (c) 1999 Hitachi Semiconductor America, Inc.\r\n")));
//
// We have a function for writing to the LEDs, let kernel get at it.
//
pWriteDebugLED = OEMWriteDebugLED;
#ifdef MODULE_CERTIFY
//
// Set the module signature verification hooks
//
pOEMLoadInit = OEMLoadInit;
pOEMLoadModule = OEMLoadModule;
//
// Init the signature verification public key
//
InitPubKey(g_bSignPublicKeyBlob,sizeof(g_bSignPublicKeyBlob));
#endif
/* initialize the companion chip HD465 */
CCInit();
InitClockFreq();
HalTimerInit();
/*
* The call to InitClock must be done after all the HalSleep invocations, as
* HalSleep use the SH4 Timer 0 to wait the specified number of microseconds
* and InitClock sets up Timer 0 to generate kernel tick interrupts.
*/
InitClock();
#ifdef DEBUG_CFW // Check CPG & BSC
NKDbgPrintfW(L"CPG_FRQCR=%8x\r\n", READ_REGISTER_USHORT(CPG_FRQCR));
NKDbgPrintfW(L"BSC_BCR1=%8x\r\n", READ_REGISTER_ULONG(BSC_BCR1));
NKDbgPrintfW(L"BSC_BCR2=%8x\r\n", READ_REGISTER_USHORT(BSC_BCR2));
NKDbgPrintfW(L"BSC_WCR1=%8x\r\n", READ_REGISTER_ULONG(BSC_WCR1));
NKDbgPrintfW(L"BSC_WCR2=%8x\r\n", READ_REGISTER_ULONG(BSC_WCR2));
NKDbgPrintfW(L"BSC_WCR3=%8x\r\n", READ_REGISTER_ULONG(BSC_WCR3));
lpWriteDebugStringFunc(TEXT("Checked CPG & BSC.\r\n"));
#endif
/* Make sure that all interrupts are setup properly */
DEBUGMSG(1, (TEXT("Initializing Interrupts\r\n")));
/* all interrupts are masked by default on the SH */
// Set priority for DMA interrupt
WRITE_REGISTER_USHORT(INTC_IPRC,
(READ_REGISTER_USHORT(INTC_IPRC) & INTC_IPRC_DMAC_MASK) |
INTC_IPRC_DMAC_INT);
// Make sure STR=0 to avoid accidental restart when TE is cleared
WRITE_REGISTER_ULONG(DMAC_CHCR1,
READ_REGISTER_ULONG(DMAC_CHCR1) & ~DMAC_CHCR_DE_ENABLED & ~DMAC_CHCR_IE_GENERATED & ~DMAC_CHCR_TE_DMATCR_COMP);
WRITE_REGISTER_ULONG(DMAC_CHCR0,
READ_REGISTER_ULONG(DMAC_CHCR0) & ~DMAC_CHCR_DE_ENABLED & ~DMAC_CHCR_IE_GENERATED & ~DMAC_CHCR_TE_DMATCR_COMP);
// clear CMF, just in case (it should be clear already for the same
// reason that TE should have been clear)
WRITE_REGISTER_USHORT(DMAC_DMAOR,
(READ_REGISTER_USHORT(DMAC_DMAOR) & ~DMAC_DMAOR_NMFI & ~DMAC_DMAOR_PR11) |
DMAC_DMAOR_DME );
#ifdef DEBUG_CFW
NKDbgPrintfW(L"INTC_ICR=%8x\r\n", READ_REGISTER_USHORT(INTC_ICR));
NKDbgPrintfW(L"INTC_IPRA=%8x\r\n", READ_REGISTER_USHORT(INTC_IPRA));
NKDbgPrintfW(L"INTC_IPRB=%8x\r\n", READ_REGISTER_USHORT(INTC_IPRB));
NKDbgPrintfW(L"INTC_IPRC=%8x\r\n", READ_REGISTER_USHORT(INTC_IPRC));
lpWriteDebugStringFunc(TEXT("Interrupt Initialization done.\r\n"));
#endif
#if (SH_PLATFORM == PLATFORM_ASPEN)
HookInterrupt(0xC, HD64465_ISR);
IntrPrio[0xC] = 0xf;
HookInterrupt(0xA, ATAPI_ISR);
IntrPrio[0xA] = 0xf;
HookInterrupt(0x2, Ethernet_ISR);
IntrPrio[0x2] = 0xf;
HookInterrupt( (0x660 - 0x200)/0x20 , DMA_ISR); // DMATE1 0x660 : INTEVT code
IntrPrio[(0x660 - 0x200)/0x20]=0xf; // It should be set same as INTC_IPRC_DMAC_INT
#elif (SH_PLATFORM==PLATFORM_BIGSUR)
HookInterrupt((0x340-0x200)/0x20, HD64465_ISR);
IntrPrio[(0x340 - 0x200)/ 0x20 ] = 0xf;
HookInterrupt(0x8, ATAPI_ISR);
IntrPrio[0x8] = 0xf;
HookInterrupt(0x2, Ethernet_ISR);
IntrPrio[0x2] = 0xf;
HookInterrupt( (0x660 - 0x200)/0x20 , DMA_ISR); // DMATE1 0x660 : INTEVT code
IntrPrio[(0x660 - 0x200)/0x20] = 0xf;
if (0) { // Hook all the interrupts to SpuriousISR.
int i;
for(i = 0; i < 16; i++)
HookInterrupt(i, SpuriousISR);
}
#endif
#ifdef DEBUG_CFW
lpWriteDebugStringFunc(TEXT("HookInterrupt Done.\r\n"));
lpWriteDebugStringFunc(TEXT("Firmware Init Done.\r\n"));
#endif
pKDIoControl = OEMKDIoControl;
#if(SH_PLATFORM==PLATFORM_BIGSUR)
WRITE_REGISTER_UCHAR(FPGA_DMA_REG1,FPGA_DMA_REG0_64465CH1);
#endif(SH_PLATFORM==PLATFORM_BIGSUR)
RETAILMSG(1, (TEXT("-OEMInit()\r\n")));
}
/*
@func BOOL | OEMInterruptEnable | Enable a hardware interrupt
@rdesc Returns TRUE if valid interrupt ID or FALSE if invalid ID.
@comm This function is called by the Kernel when a device driver
calls <f InterruptInitialize>. The system is not preemptible when this
function is called.
@xref <l Overview.Pegasus Kernel OEM Interface> <f InterruptInitialize>
*/
BOOL OEMInterruptEnable (
DWORD idInt, // @parm Interrupt ID to be enabled. See
// <l Interrupt ID's.Interrupt ID's> for a list of possble values.
LPVOID pvData, // @parm ptr to data passed in in the <f InterruptInitialize> call
DWORD cbData // @parm Size of data pointed to be <p pvData>
)
{
BOOL bRet = TRUE;
RETAILMSG(1,(TEXT("+OEMInterruptEnable(idInt=%d)\r\n"), idInt));
INTERRUPTS_OFF();
switch (idInt) {
case SYSINTR_BREAK:
break;
case SYSINTR_KEYBOARD:
// DEBUGMSG(1,(TEXT("+OEMInterruptEnable: KEYBD: Write(0x%x, 0x%x)\r\n"), CC_INTC_NIMR, READ_REGISTER_USHORT(CC_INTC_NIMR)&CC_INTC_NIMR_PS2KBM_UNMASK));
WRITE_REGISTER_USHORT(CC_INTC_NIMR, READ_REGISTER_USHORT(CC_INTC_NIMR)&CC_INTC_NIMR_PS2KBM_UNMASK );
break;
case SYSINTR_SERIAL:
WRITE_REGISTER_USHORT( CC_UART_REGBASE + CC_UART_UMCR_OFFSET,
READ_REGISTER_USHORT(CC_UART_REGBASE + CC_UART_UMCR_OFFSET)|0x0008 );
break;
case SYSINTR_AUDIO:
break;
case SYSINTR_PCMCIA_STATE:
if (!PCMCIA_int_users)
{
/* don't need to enable this if it has already been done */
WRITE_REGISTER_USHORT(CC_INTC_REGBASE+CC_INTC_NIMR_OFFSET,
(READ_REGISTER_USHORT(CC_INTC_REGBASE+CC_INTC_NIMR_OFFSET) &
~CC_INTC_NIMR_PCC0M_MASK));
WRITE_REGISTER_USHORT(CC_INTC_REGBASE+CC_INTC_NIMR_OFFSET,
(READ_REGISTER_USHORT(CC_INTC_REGBASE+CC_INTC_NIMR_OFFSET) &
~CC_INTC_NIMR_PCC1M_MASK));
}
PCMCIA_int_users++;
break;
case SYSINTR_PCMCIA_LEVEL:
if (!PCMCIA_int_users)
{
/* don't need to enable this if it has already been done */
WRITE_REGISTER_USHORT(CC_INTC_REGBASE+CC_INTC_NIMR_OFFSET,
(READ_REGISTER_USHORT(CC_INTC_REGBASE+CC_INTC_NIMR_OFFSET) &
~CC_INTC_NIMR_PCC0M_MASK));
WRITE_REGISTER_USHORT(CC_INTC_REGBASE+CC_INTC_NIMR_OFFSET,
(READ_REGISTER_USHORT(CC_INTC_REGBASE+CC_INTC_NIMR_OFFSET) &
~CC_INTC_NIMR_PCC1M_MASK));
}
PCMCIA_int_users++;
break;
case SYSINTR_RTC_ALARM:
break;
case SYSINTR_TIMING:
break;
case SYSINTR_IR:
/* enable the HD64465 IRDA interrupt */
/* all other setup of the 16550 is done in the IST */
WRITE_REGISTER_USHORT( CC_INTC_NIMR,
READ_REGISTER_USHORT(CC_INTC_NIMR)&CC_INTC_NIMR_IRDAM_UNMASK );
break;
case SYSINTR_USB:
WRITE_REGISTER_USHORT( CC_INTC_NIMR,
READ_REGISTER_USHORT(CC_INTC_NIMR)&CC_INTC_NIMR_USBM_UNMASK );
break;
case SYSINTR_MOUSE:
WRITE_REGISTER_USHORT( CC_INTC_NIMR, READ_REGISTER_USHORT(CC_INTC_NIMR)&CC_INTC_NIMR_PS2MSM_UNMASK );
break;
case SYSINTR_PARALLEL:
DEBUGMSG(1, (TEXT("IE: PARALLEL: Previous IMASK = 0x%x\r\n"), READ_REGISTER_USHORT(CC_INTC_NIMR)));
WRITE_REGISTER_USHORT( CC_INTC_NIMR,
READ_REGISTER_USHORT(CC_INTC_NIMR)&CC_INTC_NIMR_PPM_UNMASK );
DEBUGMSG(1, (TEXT("IE: PARALLEL: New IMASK = 0x%x\r\n"), READ_REGISTER_USHORT(CC_INTC_NIMR)));
break;
case SYSINTR_ETHER:
#if (SH_PLATFORM==PLATFORM_ASPEN)
DEBUGMSG(1, (TEXT("IE: Previous IMASK = 0x%x\r\n"), READ_REGISTER_ULONG(FPGA_IMASK)));
WRITE_REGISTER_ULONG(FPGA_IMASK, (READ_REGISTER_ULONG(FPGA_IMASK) | FPGA_IMASK_ILAN) );
DEBUGMSG(1, (TEXT("IE: New IMASK = 0x%x\r\n"), READ_REGISTER_ULONG(FPGA_IMASK)));
#elif (SH_PLATFORM==PLATFORM_BIGSUR)
DEBUGMSG(1, (TEXT("IE 3: Previous IMASK3 = 0x%x\r\n"), READ_REGISTER_UCHAR(INT_IMASK3)));
WRITE_REGISTER_UCHAR(INT_IMASK3, (READ_REGISTER_UCHAR(INT_IMASK3 ) & ~FPGA_IMASK_ENETINT) );
DEBUGMSG(1, (TEXT("IE 3: New IMASK3 = 0x%x\r\n"), READ_REGISTER_UCHAR(INT_IMASK3 )));
#endif (SH_PLATFORM==PLATFORM_ASPEN)
break;
case SYSINTR_IDE:
#if (SH_PLATFORM==PLATFORM_ASPEN)
DEBUGMSG(1, (TEXT("IE: Previous IMASK = 0x%x\r\n"), READ_REGISTER_ULONG(FPGA_IMASK)));
WRITE_REGISTER_ULONG(FPGA_IMASK, (READ_REGISTER_ULONG(FPGA_IMASK) | FPGA_IMASK_IIDE) );
DEBUGMSG(1, (TEXT("IE: New IMASK = 0x%x\r\n"), READ_REGISTER_ULONG(FPGA_IMASK)));
#elif (SH_PLATFORM==PLATFORM_BIGSUR)
DEBUGMSG(1, (TEXT("IE 3: Previous IMASK1 = 0x%x\r\n"), READ_REGISTER_UCHAR(INT_IMASK1)));
WRITE_REGISTER_UCHAR(INT_IMASK1, (READ_REGISTER_UCHAR(INT_IMASK1 ) & ~FPGA_IMASK_IDE_INT) );
DEBUGMSG(1, (TEXT("IE 3: New IMASK1 = 0x%x\r\n"), READ_REGISTER_UCHAR(INT_IMASK1 )));
#endif (SH_PLATFORM==PLATFORM_ASPEN)
break;
default:
bRet = FALSE; /* don't know about this interrupt value */
}
INTERRUPTS_ON();
return bRet;
}
/*
@func BOOL | OEMInterruptDisable | Disable a hardware interrupt
@rdesc none
@comm OEMInterruptDisable is called by the Kernel when a device driver
calls <f InterruptDisable>. The system is not preemtible when this
function is called.
@xref <l Overview.Pegasus Kernel OEM Interface> <f InterruptDisable>
*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?