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

📄 mdppfs.c

📁 CEPC的引导代码,在BOIS基础上自定义引导WINCE内核,基于VC的工程
💻 C
字号:
/*++
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-2000 Microsoft Corporation.  All rights reserved.

Module Name:

   mdppfs.c

Abstract:

   This file implements the NK kernel ppfs client side interface

Notes:

--*/

#include "windows.h"
#include "wdm.h"
#include "pc.h"

#define PAR_PORT_BASE       0x0378
#define PAR_PORT_DATA       0
#define PAR_PORT_STAT       1
#define PAR_PORT_CTRL       2

#define PAR_STAT_NBUSY      0x80
#define PAR_STAT_NACK       0x40
#define PAR_STAT_PE         0x20
#define PAR_STAT_SLCT       0x10
#define PAR_STAT_NERR       0x08    // This isn't connected

#define PAR_CTRL_READ       0x20
#define PAR_CTRL_IRQE       0x10
#define PAR_CTRL_SLCT_IN    0x08
#define PAR_CTRL_NINIT      0x04
#define PAR_CTRL_AUTOFEED   0x02
#define PAR_CTRL_STROBE     0x01

#define STATUS_IS_DISCONNECTED(a) \
    ((((a) & (PAR_STAT_PE | PAR_STAT_SLCT)) != PAR_STAT_SLCT) || \
     (((a) & (PAR_STAT_NBUSY | PAR_STAT_NACK)) == PAR_STAT_NACK))

//#define STATUS_IS_DISCONNECTED(a) (!((a) & PAR_STAT_SLCT))

#if DEBUG
#define LOG_ENTRY_TYPE_MASK 0xFF00
#define LOG_ENTRY_DATA_MASK 0x00FF

#define LOG_ENTRY_READ      ((USHORT)('R' << 8))
#define LOG_ENTRY_WRITE     ((USHORT)('W' << 8))
#define LOG_ENTRY_CONTROL   ((USHORT)('C' << 8))
#define LOG_ENTRY_STATUS    ((USHORT)('S' << 8))
#define LOG_ENTRY_DATA      ((USHORT)('D' << 8))
#define LOG_ENTRY_EXIT      ((USHORT)('E' << 8))
#define LOG_ENTRY_EVENT     ((USHORT)('V' << 8))

#define LOG_EVENT_SKIP_RECEIVE      ((USHORT)0)
#define LOG_EVENT_BAD_STATUS        ((USHORT)1)
#define LOG_EVENT_BAD_DISCONNECT    ((USHORT)2)

#define NUMBER_LOG_EVENTS   3

TCHAR   *EventDescriptions[NUMBER_LOG_EVENTS] = 
{
    TEXT("# Skipped Receives"),
    TEXT("# Bad Status"),
    TEXT("# Bad Disconnect"),
};

DWORD   dwEventCounters[NUMBER_LOG_EVENTS];

VOID    LogEntry(USHORT usEntry);
VOID    DumpLog(VOID);
VOID    DumpCounters(VOID);

#define LOG_ENTRY(a)    LogEntry(a)
#define DUMP_LOG()      DumpLog()
#else
#define LOG_ENTRY(a)
#define DUMP_LOG()
#endif

extern volatile DWORD *PtrCurMSec;      /* current millisecond counter */

#define IoPortBase  ((PUCHAR)PAR_PORT_BASE)

BOOL    NoPPFS;
BOOL    bLastOpWasWrite;

BOOL    __inline    VerifyDisconnect(VOID)
{
    int     i;
    USHORT  usStatus;

    for (i = 0; i < 3; i++)
    {
        usStatus = READ_PORT_UCHAR(IoPortBase + PAR_PORT_STAT);

        LOG_ENTRY((USHORT)(LOG_ENTRY_STATUS | usStatus));

        if (!STATUS_IS_DISCONNECTED(usStatus))
        {
            LOG_ENTRY(LOG_ENTRY_EVENT | LOG_EVENT_BAD_STATUS);

            return FALSE;
        }
    }
    return TRUE;
    
}

BOOL    WaitForStatus(USHORT usMask, USHORT usValue)
{
    USHORT  usStatus;
    DWORD   msecStart = *PtrCurMSec;
    int     tries = 0;

    do
    {
        if (*PtrCurMSec - msecStart >= 200)
        {
            if (++tries > 5)
            {
                NoPPFS = TRUE;

                printf("\r\nWaitForStatus: time out (1), status = %2.2X\r\n",
                    usStatus);

                LOG_ENTRY(LOG_ENTRY_EXIT | 2);

                DUMP_LOG();

                return FALSE;
            }
            msecStart = *PtrCurMSec;
        }

        usStatus = READ_PORT_UCHAR(IoPortBase + PAR_PORT_STAT);

        LOG_ENTRY((USHORT)(LOG_ENTRY_STATUS | usStatus));

        //
        // Use SELECTIN to identify the existence of ppsh
        //
        if (STATUS_IS_DISCONNECTED(usStatus))
        {
            if (VerifyDisconnect())
            {
                printf("\r\nWaitForStatus: PPSH disconnected\r\n");

                NoPPFS = TRUE;

                LOG_ENTRY(LOG_ENTRY_EXIT | 1);

                DUMP_LOG();

                return FALSE;
            }
            else
            {
              usStatus = READ_PORT_UCHAR(IoPortBase + PAR_PORT_STAT);
              LOG_ENTRY((USHORT)(LOG_ENTRY_STATUS | usStatus));
            }
        }

        if ((usStatus & usMask) == usValue)
        {
            int     i;

            for (i = 0; i < 2; i++)
            {
                usStatus = READ_PORT_UCHAR(IoPortBase + PAR_PORT_STAT);

                LOG_ENTRY((USHORT)(LOG_ENTRY_STATUS | usStatus));

                if ((usStatus & usMask) != usValue)
                {
                    LOG_ENTRY(LOG_ENTRY_EVENT | LOG_EVENT_BAD_STATUS);

                    break;
                }
            }
        }
    }
    while ((usStatus & usMask) != usValue);

    return TRUE;
}

int OEMParallelPortInit(void)
{
    LOG_ENTRY(LOG_ENTRY_CONTROL | PAR_CTRL_AUTOFEED | PAR_CTRL_STROBE);

    WRITE_PORT_UCHAR(
        IoPortBase + PAR_PORT_CTRL, PAR_CTRL_AUTOFEED | PAR_CTRL_STROBE);

    return TRUE;
}

int OEMParallelPortGetByte(void)
{
    BYTE    value;

    if (NoPPFS)
    {
        return -1;
    }

Retry:
    LOG_ENTRY(LOG_ENTRY_READ);

    LOG_ENTRY(LOG_ENTRY_CONTROL | PAR_CTRL_READ | PAR_CTRL_STROBE);

    WRITE_PORT_UCHAR(IoPortBase + PAR_PORT_CTRL, PAR_CTRL_READ | PAR_CTRL_STROBE);

    if (!WaitForStatus(PAR_STAT_NACK, PAR_STAT_NACK))
    {
        return -1;
    }

    value = READ_PORT_UCHAR(IoPortBase + PAR_PORT_DATA);

    LOG_ENTRY((USHORT)(LOG_ENTRY_DATA | value));

    LOG_ENTRY(LOG_ENTRY_CONTROL | PAR_CTRL_AUTOFEED | PAR_CTRL_STROBE);

    WRITE_PORT_UCHAR(IoPortBase + PAR_PORT_CTRL, PAR_CTRL_AUTOFEED | PAR_CTRL_STROBE);

    if (!WaitForStatus(PAR_STAT_NACK, 0))
    {
        return -1;
    }

    LOG_ENTRY(LOG_ENTRY_EXIT | 0);

    if (bLastOpWasWrite && value == 0x1A)
    {
        //
        // The problem is that periodically the first character we
        // receive after a write is the last byte sent of the previous write.
        //
        // For now we will ignore it
        //
        LOG_ENTRY(LOG_ENTRY_EVENT | LOG_EVENT_SKIP_RECEIVE);
        bLastOpWasWrite = FALSE;
        goto Retry;
    }

    bLastOpWasWrite = FALSE;

    return value;
}

VOID OEMParallelPortSendByte(BYTE chData)
{
    if (NoPPFS)
        return;

    LOG_ENTRY(LOG_ENTRY_WRITE);

    if (!WaitForStatus(PAR_STAT_NBUSY, 0))
    {
        return;
    }

    LOG_ENTRY((USHORT)(LOG_ENTRY_DATA | chData));

    WRITE_PORT_UCHAR(IoPortBase + PAR_PORT_CTRL, PAR_CTRL_AUTOFEED | PAR_CTRL_STROBE);

    WRITE_PORT_UCHAR(IoPortBase + PAR_PORT_DATA, chData);

    LOG_ENTRY(LOG_ENTRY_CONTROL | PAR_CTRL_AUTOFEED);

    WRITE_PORT_UCHAR(IoPortBase + PAR_PORT_CTRL, PAR_CTRL_AUTOFEED);

    if (!WaitForStatus(PAR_STAT_NBUSY, PAR_STAT_NBUSY))
    {
        return;
    }

    LOG_ENTRY(LOG_ENTRY_CONTROL | PAR_CTRL_AUTOFEED | PAR_CTRL_STROBE);

    WRITE_PORT_UCHAR(IoPortBase + PAR_PORT_CTRL, PAR_CTRL_AUTOFEED | PAR_CTRL_STROBE);

    LOG_ENTRY(LOG_ENTRY_EXIT | 0);

    bLastOpWasWrite = TRUE;
}

#if DEBUG
#define LOG_SIZE        0x1000
#define RW_STACK_SIZE   10

WCHAR   wcHexDigits[16] = 
{
    TEXT('0'), TEXT('1'), TEXT('2'), TEXT('3'),
    TEXT('4'), TEXT('5'), TEXT('6'), TEXT('7'), 
    TEXT('8'), TEXT('9'), TEXT('A'), TEXT('B'),
    TEXT('C'), TEXT('D'), TEXT('E'), TEXT('F')
};

USHORT  usLogBuffer[LOG_SIZE];
int     iLogHead = 0;
int     iLogTail = 0;

VOID
LogEntry(USHORT usEntry)
{
    static  USHORT  usLastEntry;
    USHORT          usEntryType;
    USHORT          usEntryData;

    usEntryData = usEntry & LOG_ENTRY_DATA_MASK;
    usEntryType = usEntry & LOG_ENTRY_TYPE_MASK;

    switch (usEntryType)
    {
    case LOG_ENTRY_STATUS:
        if (usLastEntry == usEntry)
        {
            //
            // Don't log duplicate status
            //
            return;
        }
        break;
        
    case LOG_ENTRY_EVENT:
        if (usEntryData < NUMBER_LOG_EVENTS)
        {
            dwEventCounters[usEntryData]++;
        }
        break;
    }
        
    usLastEntry = usEntry;

    usLogBuffer[iLogTail++] = usEntry;
    iLogTail %= LOG_SIZE;

    if (iLogTail == iLogHead)
    {
        iLogHead++;
        iLogHead %= LOG_SIZE;
    }
}

VOID
DumpLog(VOID)
{
    // R 00 W 4F
    TCHAR   szPrintLine[100];
    int     iLogCurrent;
    PTCHAR  pCurrentColumn;
    int     nDataItems;
    USHORT  usCurrentOp, usLastOp;
    int     iReadWriteStack[RW_STACK_SIZE];
    int     i;

    pCurrentColumn = szPrintLine;
    nDataItems = 0;

    usLastOp = 0;

    for (i = 0; i < RW_STACK_SIZE; i++)
    {
        iReadWriteStack[i] = iLogTail;
    }

    for (iLogCurrent = iLogHead; iLogCurrent != iLogTail;
        iLogCurrent++, iLogCurrent %= LOG_SIZE)
    {
        usCurrentOp = usLogBuffer[iLogCurrent] & LOG_ENTRY_TYPE_MASK;
        switch (usCurrentOp)
        {
        case LOG_ENTRY_READ:
        case LOG_ENTRY_WRITE:
            if (usLastOp != usCurrentOp)
            {
                if (pCurrentColumn != szPrintLine)
                {
                    memcpy(pCurrentColumn, TEXT("\r\n"), sizeof(TEXT("\r\n")));
                    OutputDebugString(szPrintLine);
                    pCurrentColumn = szPrintLine;
                }

                *pCurrentColumn++ = (TCHAR)(usLogBuffer[iLogCurrent] >> 8);
                *pCurrentColumn++ = TEXT(' ');
                usLastOp = usCurrentOp;
                nDataItems = 0;
            }

            for (i = 0; i < (RW_STACK_SIZE - 1); i++)
            {
                iReadWriteStack[i] = iReadWriteStack[i + 1];
            }

            iReadWriteStack[RW_STACK_SIZE - 1] = iLogCurrent;
            break;

        case LOG_ENTRY_EVENT:
        case LOG_ENTRY_DATA:
            if (nDataItems == 25)
            {
                memcpy(pCurrentColumn, TEXT("\r\n"), sizeof(TEXT("\r\n")));
                OutputDebugString(szPrintLine);
                pCurrentColumn = szPrintLine;
                *pCurrentColumn++ = TEXT(' ');
                *pCurrentColumn++ = TEXT(' ');
                nDataItems = 0;
            }
            *pCurrentColumn++ = wcHexDigits[(usLogBuffer[iLogCurrent] >> 4) & 0x0F];
            *pCurrentColumn++ = wcHexDigits[usLogBuffer[iLogCurrent] & 0x0F];
            *pCurrentColumn++ = usCurrentOp == LOG_ENTRY_DATA ? TEXT(' ') : TEXT('!');
            nDataItems++;
            break;
        }
    }

    if (pCurrentColumn != szPrintLine)
    {
        memcpy(pCurrentColumn, TEXT("\r\n"), sizeof(TEXT("\r\n")));
        OutputDebugString(szPrintLine);
        pCurrentColumn = szPrintLine;
    }

    nDataItems = 0;

    for (i = 0; i < RW_STACK_SIZE; i++)
    {
        if (iReadWriteStack[i] != iLogTail)
        {
            break;
        }
    }

    iLogCurrent = (i < RW_STACK_SIZE) ? iReadWriteStack[i] : iLogTail;

    for ( ; iLogCurrent != iLogTail; iLogCurrent++, iLogCurrent %= LOG_SIZE)
    {
        if (nDataItems == 16)
        {
            memcpy(pCurrentColumn, TEXT("\r\n"), sizeof(TEXT("\r\n")));
            OutputDebugString(szPrintLine);
            pCurrentColumn = szPrintLine;
            nDataItems = 0;
        }

        *pCurrentColumn++ = (TCHAR)(usLogBuffer[iLogCurrent] >> 8);

        *pCurrentColumn++ = TEXT(' ');

        *pCurrentColumn++ = wcHexDigits[(usLogBuffer[iLogCurrent] >> 4) & 0x0F];

        *pCurrentColumn++ = wcHexDigits[usLogBuffer[iLogCurrent] & 0x0F];

        *pCurrentColumn++ = TEXT(' ');

        nDataItems++;
    }

    if (pCurrentColumn != szPrintLine)
    {
        memcpy(pCurrentColumn, TEXT("\r\n"), sizeof(TEXT("\r\n")));
        OutputDebugString(szPrintLine);
        pCurrentColumn = szPrintLine;
    }

    DumpCounters();
}

VOID
DumpCounters(VOID)
{
    int     i;
    
    for (i = 0; i < NUMBER_LOG_EVENTS; i++)
    {
        if (dwEventCounters[i] != 0)
        {
            NKDbgPrintfW(
                TEXT("%s = %d\r\n"), EventDescriptions[i], dwEventCounters[i]);
        }
    }
}
#endif

⌨️ 快捷键说明

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