cfw_platform.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 657 行 · 第 1/2 页
C
657 行
/* -*-C-*-
*
* $Revision: 1.8 $
* $Author: kwelton $
* $Date: 2000/08/08 21:45:51 $
*
* Module Name: cfw_platform.c
*
* Abstract:
* This file implements the NK kernel interfaces for firmware interrupt
* support on a template ARM board.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
* PARTICULAR PURPOSE.
*
* Copyright (c) 1995, 1996, 1997, 1998 Microsoft Corporation
* Copyright (c) 1999, 2000 ARM Limited
* All Rights Reserved
*/
#include "windows.h"
#include "nkintr.h"
#include "oalintr.h"
#include "drv_glob.h"
#include "platform.h"
#include "arm_ddk.h"
#include <pcilib.h>
#include <memory.h>
#ifdef MODULE_CERTIFY
/*
* OEMLoadInit/OEMLoadModule implementation and the public
* key used for module signature verification
*/
# include "key1024.c"
#endif
#include "win_plat.h"
#include "timer.h"
/*
* @doc EXTERNAL KERNEL HAL
*
* @module cfw_platform.c - ARM Template HW Support
* OEM support Functions for the Windows CE ARM Platform.
*
* @xref
* OEMInit
* OEMInterruptEnable
* OEMInterruptDisable
* OEMInterruptDone
* HAL Overview.Windows CE Kernel OEM Interface
* Interrupt Support Overview.Kernel Interrupt Support
*
* @topic Windows CE Kernel OEM Interface
*
* This defines the HAL layer - OEM and platform dependent pieces of
* code which we expect the OEM to deliver to us. There are three
* pieces of OEM deliverable code - the bootstrap loader & monitor
* (for debugging), the HAL portions which are interfaces between
* the kernel and the firmware, and the driver interface. This
* topic covers just the HAL portion.
*
* The philosophy is to keep the HAL layer as simple as possible.
* The HAL should not be confused with the machine or CPU
* independence. HAL is specific for a particular CPU and
* platform. It includes interfaces for the following devices:
*
* - Real Time Clock
* - Interval Timer (used for the scheduler operation)
* - Interrupt handlers and support
*
* Note that it does not include abstractions for devices like the DMA
* controller etc. since the kernel does not use one. Also note that the
* list could change for different CPU's and platforms - for instance,
* some chips might include a lot of peripheral devices (like the
* interval timer) on the CPU chip itself, removing the need for a
* separate interface for them.
*
* The interfaces for the real time clock and interval timer are still
* being developed. But they should in general be extremely simple and
* straightforward. For details on the interrupt support model in the
* kernel look at <l Interrupt Support Overview.Kernel Interrupt Support>
*/
// unsigned long OEMClockFreq = OEM_CLOCK_FREQ;
//#define DMA_BUFFER_BASE 0xAC000000
//#define INTR_MAXIMUM 15
extern DWORD idleconv; // translation constant in 1 ms units
extern DWORD curridlehigh, curridlelow; // 64-bit idle time in ms
extern DWORD CurMSec;
#ifdef OldCode
extern ROMHDR const *pTOC;
#endif /* def OldCode */
extern int IntrTimeISR(void);
extern void InitClock(void);
extern void HalCpuInit(void);
extern void HalTimerInit(void);
extern void HalSleep(DWORD);
extern DWORD HAL_mSecsLeft(void);
extern DWORD HAL_uSecsLeft(void);
extern void pHALir_EnableIrq(DWORD irq);
extern void pHALir_DisableIrq(DWORD irq);
void OEMInitInterrupts(HARP_BOOT_ARGS *pBootArgs);
int OEMInterruptHandler(unsigned int ra);
void OEMInitInterrupts(HARP_BOOT_ARGS *pBootArgs);
ULONG OEMMapIntLogic2SysIntr(ULONG nLogical);
ULONG OEMMapIntSysIntr2Logic(ULONG nSysIntr);
void OEMInitPCISlotInterrupts(void);
BOOL PCI_InitHierarchy(void);
void InitTransport(void);
void InitDebugEther(void);
extern unsigned int PciMemBase;
extern unsigned int PciCfgBase;
extern unsigned int PciV3Base;
extern unsigned int PciIOBase;
typedef volatile WORD *PVWORD;
typedef volatile DWORD *PVDWORD;
volatile ULARGE_INTEGER CurTicks = { 0, 0 };
volatile ULARGE_INTEGER * pCurTicks = &CurTicks;
HARP_BOOT_ARGS *pBootArgs = &(((PDRIVER_GLOBALS)(DRIVER_GLOBALS_PHYSICAL_MEMORY_START))->eth);
unsigned long OEMClockFreq; // OEM clock frequency is used only in OAL
ULONG Logic2SysIntr[LOGINTR_MAX];
ULONG SysIntr2Logic[SYSINTR_MAX];
#define REG(base, id) (*(PVWORD)((base) + (id)))
#define REG32(base, id) (*(PVDWORD)((base) + (id)))
/**********************************************************************/
void dumpetheraddr(char *qualifier, EDBG_ADDR *addr)
{
unsigned char *aschars = (char *)addr;
DPF("%sAddr = %d.%d.%d.%d:%d at %B:%B:%B:%B:%B:%B\n",
qualifier, aschars[0], aschars[1], aschars[2], aschars[3],
ntohs(addr->wPort), aschars[4], aschars[5], aschars[6],
aschars[7], aschars[8], aschars[9]);
}
/*
* @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 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
* InterruptInitialize() call from the driver will fail.
*
* @xref Overview.Windows CE Kernel OEM Interface
* HookInterrupt
* InterruptInitialize
*/
void OEMInit(void)
{
PciMemBase = VA_PCI_MEM_BASE;
PciCfgBase = VA_PCI_CFG_BASE;
PciIOBase = VA_PCI_IO_BASE;
PciV3Base = VA_PCI_V3_BASE;
#ifdef DEBUG
// Instead of calling OEMWriteDebugString directly, call through exported
// function pointer. This will allow these messages to be seen if debug
// message output is redirected to Ethernet or the parallel port.
// Otherwise, lpWriteDebugStringFunc == OEMWriteDebugString.
lpWriteDebugStringFunc(TEXT("Windows CE Firmware Init\r\n"));
#endif
OEMWriteDebugLED(0, 0);
DEBUGMSG(1, (TEXT("Boot Args @0x%x, signature 0x%08x\r\n"),
pBootArgs, pBootArgs->dwSig));
/*
* Configure the PCI tree
*/
if (!PCI_InitHierarchy())
{
RETAILMSG(1, (TEXT("ERROR: Cannot setup PCI.\r\n")));
return;
}
/*
* Set up translation constant for GetIdleTime() (1 ms units).
*
* Note: Since curridlehigh, curridlelow is counting in ms, and
* GetIdleTime() reports in ms, the conversion ratio is one. If
* curridlehigh, curridlelow were using other units (like ticks),
* then the conversion would be calculated from the clock frequency.
*/
idleconv = 1;
/*
* Initialize timer used for delays in the HAL.
*/
#ifdef DEBUG
lpWriteDebugStringFunc(TEXT("Initialize timer used for delays")
TEXT("in the HAL\r\n"));
#endif
HalTimerInit();
/*
* The call to InitClock must be done after all the HalSleep
* invocations (for compatability with SH3)
*/
lpWriteDebugStringFunc(TEXT("InitClock...\r\n"));
InitClock();
/*
* Initialize driver globals area
*/
lpWriteDebugStringFunc(TEXT("Initialize driver globals area...\r\n"));
memset((PVOID)DRIVER_GLOBALS_ZEROINIT_START, 0,
DRIVER_GLOBALS_ZEROINIT_SIZE);
/*
* Clear any pending interrupts in the cpu ISR register and enable
* any interrupts that the kernel uses. The design for the P2 has
* changed from the PeRP here. The PeRP had different mask
* registers - one for the CPU that had mask bits for sets of
* interrupts (i.e. IO, Parallel Port, PCMCIA), and then a single mask
* register for each specific device type. The P2 only has a single mask
* register, the CPU Mask Register. The CPU ISR on the P2 is defined as
* being read only. The only way to clear any pending interrupts in the
* CPU ISR is to clear them in each device's register.
*/
// Initialize interrupts.
//
OEMInitInterrupts(pBootArgs);
// Only support one core module (0) under CE - interrupts come in on IRQ0.
// ARM doesn't use HookInterrupt - OEMInterruptHandler called by kernel
// instead.
#ifdef DEBUG
// dpCurSettings.ulZoneMask = 0xffffffff;
lpWriteDebugStringFunc(TEXT("Firmware Init Done.\r\n"));
#endif
// Intialize EDBG/KITL.
InitDebugEther();
}
/*
* @func BOOL | OEMInterruptEnable | Enable a hardware interrupt
*
* @parms
* idInt Interrupt ID to be enabled.
* See Interrupt ID's.Interrupt ID's> for a list of
* possble values.
*
* pvData ptr to data passed in in the InterruptInitialize() call
*
* cbData Size of data pointed to by pvData
*
* @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 InterruptInitialize(). The system is not preemptible
* when this function is called.
*
* @xref
* Overview.Windows CE Kernel OEM Interface
* InterruptInitialize
*/
BOOL OEMInterruptEnable(DWORD idInt, LPVOID pvData, DWORD cbData)
{
BOOL bRet = FALSE;
INTERRUPTS_OFF();
if (idInt > SYSINTR_MAX) // Bounds check.
{
bRet = FALSE;
}
#ifdef IMGSHAREETH
else if (idInt == SYSINTR_VMINI) // Vmini interrupt stub.
{
RETAILMSG (1, (TEXT("Accepting VMini interrupt enable request.\r\n")));
bRet = TRUE;
}
#endif // IMGSHAREETH
else if (!SysIntr2Logic[idInt]) // Mapped interrupt?
{
bRet = FALSE;
}
else
{
pHALir_EnableIrq(SysIntr2Logic[idInt]); // Enable interrupt.
bRet = TRUE;
}
INTERRUPTS_ON();
return(bRet);
}
/*
* @func BOOL | OEMInterruptDisable | Disable a hardware interrupt
*
* @rdesc none
*
* @parms
* idInt Interrupt ID to be disabled.
* See Interrupt ID's.Interrupt ID's> for a list of
* possble values.
*
* @comm OEMInterruptDisable is called by the Kernel when a device driver
* calls <f InterruptDisable>. The system is not preemtible when this
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?