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