⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mdsh3.c

📁 windows ce 3.00 嵌入式操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved. */

#include "kernel.h"
#include "shx.h"

extern void UnusedHandler(void);
extern void OEMInitDebugSerial(void);
extern void InitClock(void);
extern void FlushTLB(void);
extern void LoadKPage(void);
extern void DumpFrame(PTHREAD pth, PCONTEXT pctx, DWORD dwExc, DWORD info);
extern void APICallReturn(void);

#ifdef SH4
void SaveFloatContext(PTHREAD);
void RestoreFloatContext(PTHREAD);
DWORD GetAndClearFloatCode(void);
DWORD GetAndClearFloatCode(void);
DWORD GetCauseFloatCode(void);
extern BOOL HandleHWFloatException(EXCEPTION_RECORD *ExceptionRecord,
                                   PCONTEXT pctx);
extern unsigned int get_fpscr();
extern void set_fpscr(unsigned int);
extern void clr_fpscr(unsigned int);
#endif

#ifdef SH3
// frequency control register value
extern unsigned short SH3FQCR_Fast;
extern unsigned int SH3DSP;
void SaveSH3DSPContext(PTHREAD);
void RestoreSH3DSPContext(PTHREAD);
#endif

// OEM definable extra bits for the Cache Control Register
unsigned long OEMExtraCCR;

extern char InterlockedAPIs[], InterlockedEnd[];

void SH3Init(int cpuType) {
    int ix;
#ifdef SH3
    /* initialize frequency control register */
    if (SH3FQCR_Fast)
        *(volatile ushort *)0xffffff80 = SH3FQCR_Fast;
#endif

    /* Disable the cpu cache & flush it. */
    CCR = 0;
    CCR = CACHE_FLUSH;

    /* Zero out kernel data page. */
    memset(&KData, 0, sizeof(KData));
    KData.handleBase = 0x80000000;
    KData.pAPIReturn = (ulong)APICallReturn;

    /* Initialize SectionTable in KPage */
    for (ix = 1 ; ix <= SECTION_MASK ; ++ix)
        SectionTable[ix] = NULL_SECTION;

    /* Copy kernel data to RAM & zero out BSS */
    KernelRelocate(pTOC);

    OEMInitDebugSerial();			// initialize serial port
    OEMWriteDebugString(TEXT("\r\nWindows CE Kernel for Hitachi SH Built on ") TEXT(__DATE__)
			TEXT(" at ") TEXT(__TIME__) TEXT("\r\n"));
#if defined(SH4)
    OEMWriteDebugString(TEXT("SH-4 Kernel\r\n"));
#else
    NKDbgPrintfW(L"SH-3 Kernel. FQCR=%x\r\n", *(volatile ushort *)0xffffff80);
#endif

    /* Initialize address translation hardware. */
    MMUTEA = 0;			/* clear transation address */
    MMUTTB = (DWORD)SectionTable; /* set translation table base address */
    MMUPTEH = 0;		/* clear ASID */
    MMUCR = TLB_FLUSH | TLB_ENABLE;
    LoadKPage();

    /* Copy interlocked api code into the kpage */
    DEBUGCHK(sizeof(KData) <= FIRST_INTERLOCK);
    DEBUGCHK((InterlockedEnd-InterlockedAPIs)+FIRST_INTERLOCK == 0x400);
    memcpy((char *)&KData+FIRST_INTERLOCK, InterlockedAPIs, InterlockedEnd-InterlockedAPIs);

    // Enable the CPU cache. Can't do this before KernelRelocate because OEMExtraCCR
    // may not be properly initialized before that point.
    CCR = CACHE_ENABLE | OEMExtraCCR;
    NKDbgPrintfW(L"CCR=%4.4x\r\n", CCR);

    OEMInit();			// initialize firmware
    KernelFindMemory();
#ifdef DEBUG
    OEMWriteDebugString(TEXT("SH3Init done.\r\n"));
#endif
}

BOOL HookInterrupt(int hwInterruptNumber, FARPROC pfnHandler) {
    if (hwInterruptNumber > 112)
        return FALSE;
    InterruptTable[hwInterruptNumber] = (DWORD)pfnHandler;
    return TRUE;
}

BOOL UnhookInterrupt(int hwInterruptNumber, FARPROC pfnHandler) {
    if (hwInterruptNumber > 112 ||
        InterruptTable[hwInterruptNumber] != (DWORD)pfnHandler)
        return FALSE;
    InterruptTable[hwInterruptNumber] = (DWORD)UnusedHandler;
    return TRUE;
}

#ifdef SH4
void FlushCache(void) {
    FlushDCache();
    FlushICache();
}

void SwitchFPUOwner(PCONTEXT pctx) {
    KCALLPROFON(61);
    if (g_CurFPUOwner != pCurThread) {
        if (g_CurFPUOwner)
            SaveFloatContext(g_CurFPUOwner);
        g_CurFPUOwner = pCurThread;
        RestoreFloatContext(pCurThread);
    }
    KCALLPROFOFF(61);
    pctx->Psr &= ~0x8000;
}

void FPUFlushContext(void) {
    if (g_CurFPUOwner) {
        SaveFloatContext(g_CurFPUOwner);
        g_CurFPUOwner->ctx.Psr |= 0x8000;
        g_CurFPUOwner = 0;
    }
}

DWORD dwStoreQueueBase;
BOOL DoSetRAMMode(BOOL bEnable, LPVOID *lplpvAddress, LPDWORD lpLength);

BOOL SC_SetRAMMode(BOOL bEnable, LPVOID *lplpvAddress, LPDWORD lpLength) {
    if (pCurProc->bTrustLevel != KERN_TRUST_FULL) {
        ERRORMSG(1,(L"SC_SetRAMMode failed due to insufficient trust\r\n"));
        KSetLastError(pCurThread, ERROR_ACCESS_DENIED);
    	return 0;
    }
    return DoSetRAMMode(bEnable, lplpvAddress, lpLength);
}

LPVOID SC_SetStoreQueueBase(DWORD dwPhysPage) {
    if (pCurProc->bTrustLevel != KERN_TRUST_FULL) {
        ERRORMSG(1,(L"SC_SetStoreQueueBase failed due to insufficient trust\r\n"));
        KSetLastError(pCurThread, ERROR_ACCESS_DENIED);
    	return 0;
    }
    if (dwPhysPage & (1024*1024-1)) {
        KSetLastError(pCurThread,ERROR_INVALID_PARAMETER);
        return 0;
    }
    if (dwPhysPage & 0xe0000000) {
        KSetLastError(pCurThread,ERROR_INVALID_PARAMETER);
        return 0;
    }
    dwStoreQueueBase = dwPhysPage | PG_VALID_MASK | PG_1M_MASK | PG_PROT_WRITE | PG_DIRTY_MASK | 1;
    FlushTLB();
    return (LPVOID)0xE0000000;
}

#else   // !SH4

void SwitchDSPOwner(PCONTEXT pctx) {
    KCALLPROFON(68);
    if (g_CurDSPOwner != pCurThread) {
        if (g_CurDSPOwner)
            SaveSH3DSPContext(g_CurDSPOwner);
        g_CurDSPOwner = pCurThread;
        RestoreSH3DSPContext(pCurThread);
    }
    pctx->Psr |= 0x1000;            // enable the DSP
    KCALLPROFOFF(68);
}

#endif

void FlushTLB(void) {
    MMUCR = TLB_FLUSH | TLB_ENABLE;
#if defined(SH4) || (PAGE_SIZE == 1024)
    FlushCache();
#endif
}

typedef struct ExcInfo {
    DWORD   linkage;
    ULONG	oldFir;
    UINT    oldMode;
    UCHAR	exc;
    UCHAR	lowSp;
    UCHAR	pad[2];
    ULONG	info;
} EXCINFO, *PEXCINFO;

ERRFALSE(sizeof(EXCINFO) <= sizeof(CALLSTACK));
ERRFALSE(offsetof(EXCINFO,linkage) == offsetof(CALLSTACK,pcstkNext));
ERRFALSE(offsetof(EXCINFO,oldFir) == offsetof(CALLSTACK,retAddr));
ERRFALSE(offsetof(EXCINFO,oldMode) == offsetof(CALLSTACK,pprcLast));
ERRFALSE(64 >= sizeof(CALLSTACK));

BOOL HandleException(PTHREAD pth, DWORD dwExc, DWORD info) {
    PEXCINFO pexi;
    DWORD stackaddr;
    KCALLPROFON(0);
#if 0
    NKDbgPrintfW(L"Exception %03x Thread=%8.8lx(%8.8lx) PC=%8.8lx TEA=%8.8lx AKY=%8.8lx\r\n",
                 dwExc, pCurThread, pth, pth->ctx.Fir, info, CurAKey);
#endif
    // avoid crossing page boundary in structure
    pexi = (struct ExcInfo *)((pth->ctx.R15 & ~63) - sizeof(CALLSTACK));
    if (!((DWORD)pexi & 0x80000000) && DemandCommit((DWORD)pexi)) {
        stackaddr = (DWORD)pexi & ~(PAGE_SIZE-1);
        if ((stackaddr >= pth->dwStackBound) || (stackaddr < pth->dwStackBase) ||
            ((pth->dwStackBound = stackaddr) >= (pth->dwStackBase + MIN_STACK_RESERVE)) ||
            TEST_STACKFAULT(pth)) {
            KCALLPROFOFF(0);
            return 1; // restart instruction
        }
        SET_STACKFAULT(pth);
        dwExc = 0x1fe0;
        info = (DWORD)pexi;
    }
    // Setup to capture the exception context in kernel mode but
    // running in thread context to allow preemption and stack growth.
    if (pth->ctx.Fir != (ulong)CaptureContext+4) {
        pexi->exc = (UCHAR)(dwExc >> 5);
        pexi->lowSp = (UCHAR)(pth->ctx.R15 & 63);
        pexi->oldFir = pth->ctx.Fir;
        pexi->oldMode = GetThreadMode(pth);
        pexi->info = info;
        pexi->linkage = (DWORD)pCurThread->pcstkTop | 1;
        pCurThread->pcstkTop = (PCALLSTACK)pexi;
        pth->ctx.R15 = (DWORD)pexi;
        pth->ctx.Psr |= 0x40000000;	// Kernel mode
        pth->ctx.Fir = (ulong)CaptureContext;
        KCALLPROFOFF(0);
        return TRUE;			// continue execution
    }
    DumpFrame(pth, (PCONTEXT)&pth->ctx, dwExc, info);
    RETAILMSG(1, (TEXT("Halting thread %8.8lx\r\n"), pCurThread));
    SurrenderCritSecs();
    DEBUGCHK(!((pCurThread->wInfo >> DEBUG_LOOPCNT_SHIFT) & 1));
    SET_RUNSTATE(pCurThread,RUNSTATE_BLOCKED);
    RunList.pth = 0;
    SetReschedule();
    KCALLPROFOFF(0);
    return 0;
}

typedef struct _EXCARGS {
    DWORD dwExceptionCode;		/* exception code	*/
    DWORD dwExceptionFlags;		/* continuable exception flag	*/
    DWORD cArguments;			/* number of arguments in array	*/
    DWORD *lpArguments;			/* address of array of arguments	*/
} EXCARGS, *PEXCARGS;

void ExceptionDispatch(PCONTEXT pctx) {
    EXCEPTION_RECORD er;
    int exc;
    ULONG info;
    BOOL bHandled;
    PEXCARGS pea;
    PTHREAD pth; 
    PEXCINFO pexi;

    pth = pCurThread;
    pexi = (PEXCINFO)pth->pcstkTop;
    DEBUGMSG(ZONE_SEH, (TEXT("ExceptionDispatch: pexi=%8.8lx Fir=%8.8lx RA=%8.8lx exc=%x\r\n"),
			pexi, pexi->oldFir, pctx->PR, pexi->exc << 5));

    // Update CONTEXT with infomation saved in the EXCINFO structure
    pctx->Fir = pexi->oldFir;
    if (pexi->oldMode != KERNEL_MODE)
        pctx->Psr &= ~0x40000000;
    pctx->R15 = (ULONG)pctx + sizeof(CONTEXT);
    memset(&er, 0, sizeof(er));
    er.ExceptionAddress = (PVOID)pctx->Fir;

    // Check for RaiseException call versus a CPU detected exception.
    // RaiseException just becomes a call to CaptureContext as a KPSL.
    // HandleExcepion sets the LSB of the callstack linkage but ObjectCall
    // does not.
    if (!(pexi->linkage & 1)) {
                pea = (PEXCARGS)pctx->R15;
        exc = -1;
        pctx->Fir -= 2;     // to avoid boundary problems at the end of a try block.
        DEBUGMSG(ZONE_SEH, (TEXT("Raising exception %x flags=%x args=%d pexi=%8.8lx\r\n"),
                            pea->dwExceptionCode, pea->dwExceptionFlags, pea->cArguments, pexi));
        er.ExceptionCode = pea->dwExceptionCode;
        er.ExceptionFlags = pea->dwExceptionFlags;
        if (pea->lpArguments && pea->cArguments) {
            if (pea->cArguments > EXCEPTION_MAXIMUM_PARAMETERS) {
                er.ExceptionCode = STATUS_INVALID_PARAMETER;
                er.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
            } else {
                memcpy(er.ExceptionInformation, pea->lpArguments,
                       pea->cArguments*sizeof(DWORD));
                er.NumberParameters = pea->cArguments;
            }
        }
    } else {
        // CPU detected exception. Extract some additional information about

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -