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

📄 fwpc.c

📁 威盛 wince5.0 bsp 包 for x86 系统, 支持 VT8601 等北桥
💻 C
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
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.

Module Name:  

Abstract:  

Functions:


Notes: 

--*/

#include <windows.h>
#include <nkintr.h>
#include <oalintr.h>
#include <ceddk.h>
#include "pc.h"
#include "timer.h"
#include <oemwake.h>
#include <oal.h>

#define Naked void __declspec(naked)
extern int (*PProfileInterrupt)(void);

extern volatile LARGE_INTEGER   CurTicks;

extern void KernelInitialize();
UCHAR PICGetCurrentInterrupt();

extern DWORD g_dwOALTimerCount;

//
// Warm reset handling
// 
DWORD dwRebootAddress;
void RebootHandler();


void OEMNMIHandler(void) {
}


// local version of PerfCountSinceTick that is callable from within PeRPISR()
DWORD   _PerfCountSinceTick(void)
{
    WORD wCurCount;

    __asm {
TRY_LATCHING_AGAIN: 
             
        pushfd                  ; Save interrupt state
        cli

        in      al,40h          ; clear latches, in case they are loaded
        in      al,40h          ; 
        mov     al,11000010b    ;latch status and count of counter 0
        out     43h,al
        in      al,40h          ; read status
        shl     eax, 16         ; move into high side of eax
        in      al,40h          ; read counter 0 lsb
        mov     ah,al
        in      al,40h          ; read msb
        xchg    ah, al          ; Get them in the right order
        mov     wCurCount, ax
        shr     eax, 16         ; get the status back into al
        popfd                   ; Restore interrupt state
        
        test    al, 40h         ; did the latch operation fail?
        jne     TRY_LATCHING_AGAIN     ; if so, just do it again
    }
    
    //
    // Note : this is a countdown timer, not count up.
    //

    return g_dwOALTimerCount - wCurCount;
}

// PeRP interrupt service routine.
//
//      This routine decode the various status registers on the PeRP to
// determine the cause of an interrupt and dispatches to the appropriate
// handler for that interrupt.
//
// Registers: v0, AT, a0-a3 available for use.
//
//      Entry   (a0) = 8 (hw interrupt 2)
//              (a1) = ptr to apvIntrData array
//      Exit    (v0) = interrupt dispostion information
//                      (see nkintr.h for values)


BOOL  fIntrTime;
DWORD dwIntrTimeIsr1;
DWORD dwIntrTimeIsr2;
DWORD dwIntrTimeNumInts;
DWORD dwIntrTimeCountdown;
DWORD dwIntrTimeCountdownRef;
DWORD dwIntrTimeSPC;
//Add Two Lines, VIA PowerSaver
 BOOL bChangeFlag;
 void ChangeCPURatio(DWORD ulret);

ULONG PeRPISR(void) {
    ULONG ulRet = SYSINTR_NOP;
    UCHAR ucCurrentInterrupt;
   
    if (fIntrTime) {
        //
        // We're doing interrupt timing. Get Time to ISR.
        //
#ifdef EXTERNAL_VERIFY
        _outp((USHORT)0x80, 0xE1);
#endif
        dwIntrTimeIsr1 = _PerfCountSinceTick();
        dwIntrTimeNumInts++;
    }
    
    ucCurrentInterrupt = PICGetCurrentInterrupt();

    if (ucCurrentInterrupt == INTR_TIMER0) {
        
        if (PProfileInterrupt) {
            ulRet= PProfileInterrupt();
        }

        if (!PProfileInterrupt || ulRet == SYSINTR_RESCHED) {
            
#ifdef SYSTIMERLED
            static BYTE bTick;
            _outp((USHORT)0x80, bTick++);
#endif
            
            CurMSec += g_dwBSPMsPerIntr;

            CurTicks.QuadPart += g_dwOALTimerCount;

            if (fIntrTime) {
                //
                // We're doing interrupt timing. Every nth tick is a SYSINTR_TIMING.
                //
                dwIntrTimeCountdown--;

                if (dwIntrTimeCountdown == 0) {
                    dwIntrTimeCountdown = dwIntrTimeCountdownRef;
                    dwIntrTimeNumInts = 0;
#ifdef EXTERNAL_VERIFY
                    _outp((USHORT)0x80, 0xE2);
#endif
                    dwIntrTimeIsr2 = _PerfCountSinceTick();
                    ulRet = SYSINTR_TIMING;
                } else {
                    if ((int) (CurMSec - dwReschedTime) >= 0)
                        ulRet = SYSINTR_RESCHED;
                }
            } else {
                if ((int) (CurMSec - dwReschedTime) >= 0)
                    ulRet = SYSINTR_RESCHED;
            }
        }
        
        //
        // Check if a reboot was requested.
        //
        if (dwRebootAddress) {
            RebootHandler();
        }
    
    } else if (ucCurrentInterrupt == INTR_RTC) {
        UCHAR cStatusC;
        // Check to see if this was an alarm interrupt
        cStatusC = CMOS_Read( RTC_STATUS_C);
        if((cStatusC & (RTC_SRC_IRQ|RTC_SRC_US)) == (RTC_SRC_IRQ|RTC_SRC_US))
            ulRet = SYSINTR_RTC_ALARM;
    } else if (ucCurrentInterrupt <= INTR_MAXIMUM) {  
        // We have a physical interrupt ID, but want to return a SYSINTR_ID

        // Call interrupt chain to see if any installed ISRs handle this interrupt
        ulRet = NKCallIntChain(ucCurrentInterrupt);

        // IRQ not claimed by installed ISR; translate into SYSINTR
        if (ulRet == SYSINTR_CHAIN) {
            ulRet = OALIntrTranslateIrq (ucCurrentInterrupt);
        }

        if (ulRet == SYSINTR_NOP || ulRet == SYSINTR_UNDEFINED || !NKIsSysIntrValid(ulRet)) {
            // If SYSINTR_NOP, IRQ claimed by installed ISR, but no further action required
            // If SYSINTR_UNDEFINED, ignore
            // If SysIntr was never initialized, ignore
            ulRet = SYSINTR_NOP;
        } else {
            // Valid SYSINTR, mask off interrupt source
            PICEnableInterrupt(ucCurrentInterrupt, FALSE);
        }
    }
    OEMIndicateIntSource(ulRet);
    if (ucCurrentInterrupt > 7 || ucCurrentInterrupt == -2) {
        __asm {
            mov al, 020h    ; Nonspecific EOI
            out 0A0h, al
        }
    }
    __asm {
        mov al, 020h        ; Nonspecific EOI
        out 020h, al
    }
    // Add three Lines, VIA PowerSaver
    if ((bChangeFlag)) {
        ChangeCPURatio(ulRet);
        bChangeFlag = FALSE;
    }
    return ulRet;
}

void x86InitPICs(void) {
    int     i;
    __asm {
        ;
        ; First do PIC 1
        ;
        mov     al, 011h        ; Init command 1, cascade & 4th init byte
        out     020h, al
        jmp     short $+2

        mov     al, 040h        ; Init command 2, vector interrupts to 64
        out     021h, al
        jmp     short $+2

        mov     al, 004h        ; Init command 3, slave on IRQ 2
        out     021h, al
        jmp     short $+2

        mov     al, 001h        ; Init command 4, normal EOI
        out     021h, al
        jmp     short $+2

        mov     al, 00Bh        ; Select In Service Register for reads
        out     020h, al

        mov     al, 0FFh        ; Start with all interrupts disabled
        out     021h, al

        ;
        ; Now do PIC 2
        ;
        mov     al, 011h        ; Init command 1, cascade & 4th init byte
        out     0A0h, al
        jmp     short $+2

        mov     al, 048h        ; Init command 2, vector interrupts to 40
        out     0A1h, al
        jmp     short $+2

        mov     al, 002h        ; Init command 3, slave on IRQ 2
        out     0A1h, al
        jmp     short $+2

        mov     al, 001h        ; Init command 4, normal EOI
        out     0A1h, al

        mov     al, 00Bh        ; Select In Service Register for reads
        out     0A0h, al

        mov     al, 0FFh        ; Start with all interrupts disabled
        out     0A1h, al


        ; Clear any interrupts that might be pending (after a warm reboot).
        ;
        mov al, 020h		; PIC1
        out 020h, al

        mov al, 020h		; PIC2
        out 0A0h, al
    }
    /* Setup the PeRP interrupt handler and enable the PeRP interrupt in the BasePSR */
    for (i = 64; i < 80; i++)
        HookInterrupt(i, (void *)PeRPISR);
    //
    // Enable interrupts from cascaded PIC
    //
    PICEnableInterrupt(INTR_PIC2, TRUE);
}

VOID PICEnableInterrupt(UCHAR ucInterrupt, BOOL bEnabled) {
    __asm {
        pushfd                      ; Save interrupt state
        cli
        mov     dx, 021h            ; Assume its on PIC 1
        mov     cl, ucInterrupt
        mov     ch, 8
        cmp     cl, ch
        jl      lbl10
        mov     dx, 0A1h            ; Its actually on PIC 2
        sub     cl, ch
lbl10:
        mov     ch, 1               ; Convert interrupt number to bitmask
        shl     ch, cl

        in      al, dx              ; Get currently enabled interrupts

        test    bEnabled, 0FFh      ; Disable?
        jz      lbl20               ; Yes
        not     ch
        and     al, ch              ; Unmask interrupt
        jmp     short lbl30
lbl20:
        or      al, ch              ; Mask interrupt

lbl30:
        out     dx, al

        popfd                       ; Restore interrupt state
    }
}

UCHAR PICGetCurrentInterrupt() {
    UCHAR   ucActiveInterrupts;
    UCHAR   ucCurrentInterrupt;
    __asm {
        in  al, 020h    ; Get current interrupt
        mov ucActiveInterrupts, al
    }
    for (ucCurrentInterrupt = 0; ucCurrentInterrupt < 8; ucCurrentInterrupt++)
        if (ucActiveInterrupts & (1 << ucCurrentInterrupt)) 
            break;
    if (ucCurrentInterrupt == 8)
        return (UCHAR)-1;           // No interrupts pending on 1st PIC
    if (ucCurrentInterrupt == INTR_PIC2) {
        __asm {
            in  al, 0A0h    ; Get current interrupt
            mov ucActiveInterrupts, al
        }
        for (ucCurrentInterrupt = 0; ucCurrentInterrupt < 8; ucCurrentInterrupt++) 
            if (ucActiveInterrupts & (1 << ucCurrentInterrupt))
                break;
        if (ucCurrentInterrupt == 8)
            return (UCHAR)-2;       // No interrupts pending on 2nd PIC
        ucCurrentInterrupt += 8;
    }
    return ucCurrentInterrupt;
}


BOOL OALIntrEnableIrqs(UINT32 count, const UINT32 *pIrqs)
{
    UINT32 i;

    for (i = 0; i < count; i++) {
        PICEnableInterrupt ((UCHAR)pIrqs[i], TRUE);
    }        
    return TRUE;
}

VOID OALIntrDisableIrqs(UINT32 count, const UINT32 *pIrqs)
{
    UINT32 i;

    for (i = 0; i < count; i++) {
        PICEnableInterrupt((UCHAR)pIrqs[i], FALSE);
    }        
}

VOID OALIntrDoneIrqs(UINT32 count, const UINT32 *pIrqs)
{
    UINT32 i;

    for (i = 0; i < count; i++) {
        PICEnableInterrupt((UCHAR)pIrqs[i], TRUE);
    }        
}


⌨️ 快捷键说明

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