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 + -
显示快捷键?