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

📄 pcibus.c

📁 WINCE5.0操作系统下的PCI总线驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
//
// 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.
//

//
// PCIbus bus driver and enumerator.
//

#include <windows.h>
#include <nkintr.h>
#include <pkfuncs.h>
#include <devload.h>
#include <resmgr.h>
#include <ceddk.h>
#include <stdarg.h>
#include <PCIbus.h>
#include "PCIproto.h"
#include "PCIdbg.h"
#include "PciEnum.h"
#ifndef _PREFAST_
#pragma warning(disable: 4068) // Disable pragma warnings
#endif

#ifdef DEBUG
//
// These defines must match the ZONE_* defines in PCIdbg.h
//
#define DBG_ERROR      1
#define DBG_WARNING    2
#define DBG_FUNCTION   4
#define DBG_INIT       8
#define DBG_ENUM      16
#define DBG_ORDER     32
#define DBG_RSRC     64

DBGPARAM dpCurSettings = {
    TEXT("PCIBUS"), {
    TEXT("Errors"),TEXT("Warnings"),TEXT("Functions"),TEXT("Initialization"),
    TEXT("Enumeration"),TEXT("Load Order"),TEXT("Resource"),TEXT("Undefined"),
    TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),
    TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined"),TEXT("Undefined") },
    DBG_ERROR | DBG_WARNING
};
#endif  // DEBUG

//
// Function prototypes
//
static HANDLE
Enumerate(
    LPCWSTR EnumKey, LPCWSTR lpActiveKey
    );

static BOOL
RegGetFlags(
    PPCI_DEV_INFO pInfo 
    );
    
static DWORD
MinVal(
    DWORD List[],
    DWORD Len
    );
    
static BOOL
PCIEnum(
    LPCWSTR EnumKey, DWORD dwBusNumberBase, DWORD dwBusNumberLength
    );

static BOOL
PCIRegClean(
    LPCWSTR EnumKey
    );

static BOOL
PCIReg(
    PPCI_DEV_INFO pInfo
    );

static DWORD
RegMatchOne(
    PPCI_DEV_INFO pInfo,
    HKEY Key,
    LPCWSTR DevName
    );

static BOOL
RegCopy(
    PPCI_DEV_INFO pInfo
    );

static BOOL
RegCopyKey(
    HKEY TKey,
    HKEY IKey
    );

static BOOL
RegSetVal(
    HKEY Key,
    LPCWSTR ValName,
    DWORD ValType, 
    const PBYTE ValData,
    DWORD ValLen
    );

static BOOL
RegSetList(
    HKEY Key,
    LPCWSTR ValName,
    DWORD Num,
    DWORD List[]
    );
    
static BOOL
RegGetList(
    HKEY Key,
    LPCWSTR ValName,
    PDWORD pNum,
    DWORD List[]
    );

static BOOL 
RegSetConfig(
    PPCI_DEV_INFO pInfo 
    );
    
static BOOL
RequestSysIntr(
    DWORD Irq,
    DWORD *pSysIntr
    );

static PPCI_CFG_INFO
AddConfigInfo(
    HMODULE hDll,
    PFN_CONFIGENTRY ConfigEntryFn
    );

static void
DelConfigInfoList(
    void
    );
    
//
// Global variables
//
PPCI_CFG_INFO g_ConfigInfoList = NULL;
CRITICAL_SECTION    g_CSection;

//
// Process attach/detach API.
//
BOOL WINAPI
DllMain(
     HINSTANCE hinstDll,             /*@parm Instance pointer. */
     DWORD    dwReason,              /*@parm Reason routine is called. */
     LPVOID    lpReserved            /*@parm system parameter. */
     )
{
    if (dwReason == DLL_PROCESS_ATTACH) {
        DEBUGREGISTER(hinstDll);
        DEBUGMSG(ZONE_INIT, (L"PCIBUS!DllMain: process attach\r\n"));
        InitializeCriticalSection( &g_CSection );
        DisableThreadLibraryCalls((HMODULE)hinstDll);
    }

    if (dwReason == DLL_PROCESS_DETACH) {
        DEBUGMSG(ZONE_INIT, (L"PCIBUS!DllMain: process detach\r\n"));
        DeleteCriticalSection( &g_CSection );
    }

    return TRUE;
}


//
// PCIbus driver entry point.
//
HANDLE
Init(
    LPCWSTR ActiveKey
    )
{
    HKEY Key;
    DWORD Status;
    WCHAR EnumKey[DEVKEY_LEN];
    DWORD KeyLen;
    HANDLE hReturn = NULL;

    // Signal Entry Allow.
    EnterCriticalSection( &g_CSection ) ;
    //
    // Open the Active key and find the client key.
    //
    Status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, ActiveKey, 0, 0, &Key);
    if (Status != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!Init RegOpenKeyEx(%s) returned %d.\r\n", ActiveKey, Status));
        LeaveCriticalSection( &g_CSection );
        return (HANDLE)0;
    }

    KeyLen = sizeof(EnumKey);
    Status = RegQueryValueEx(Key, DEVLOAD_DEVKEY_VALNAME, NULL, NULL, (PUCHAR)EnumKey, &KeyLen);
    if (Status != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!Init RegQueryValueEx(%s\\%s) returned %d.\r\n", ActiveKey, DEVLOAD_DEVKEY_VALNAME, Status));
        RegCloseKey(Key);
        LeaveCriticalSection( &g_CSection );
        return (HANDLE)0;
    }

    RegCloseKey(Key);
    
    hReturn = Enumerate(EnumKey,ActiveKey);
    LeaveCriticalSection( &g_CSection );
    
    return hReturn;
}


//
//  De-init entry point.
//
void
Deinit(
    HANDLE hInitKey
    )
{
    if (hInitKey)
        DeletePciBus(hInitKey);
}


//
// Enumerate PCIbus.
//
static HANDLE
Enumerate(
    LPCWSTR EnumKey,LPCWSTR lpActiveKey
    )
{
    WCHAR RegPath[DEVKEY_LEN];
    PCI_DEV_INFO_EX Info;
    size_t MaxKeyLen = DEVKEY_LEN - (wcslen(L"\\") + wcslen(PCIBUS_INSTANCE_KEYNAME) + 1);

    // If EnumKey too long, return with error
    if (wcslen(EnumKey) > MaxKeyLen) {
        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!Enumerate: ERROR: EnumKey '%s' exceeds the allowed %d characters\r\n", EnumKey, MaxKeyLen));
        return NULL;
    }

    PCIInitInfo(EnumKey, 0, 0, 0, NULL, &Info.pciDevice);

    if (!RegGetInfo(&Info.pciDevice)) {
        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!Enumerate: RegGetInfo failed\r\n"));
        return NULL;
    }
    if (!RegGetExtraDeviceInfo(&Info)) {
        Info.PrefetchMemBase.Num = 0;
        Info.PrefetchMemLen.Num = 0;
        Info.dwBusNumberBase = 0;
        Info.dwBusNumberLength = PCI_MAX_BUS;
    }
    
    if (Info.pciDevice.Configure) {
        // Configure bus
        if (!PCICfg(&Info)) {
            DEBUGMSG(ZONE_ERROR, (L"PCIBUS!Enumerate: PCICfg failed\r\n"));
            return NULL;
        }
    }

    // Clean out devices from under PCI\Instance sub-key that have no physical device available.  This is
    // to prevent device drivers from being loaded for devices that have been removed while suspended and while
    // retaining the registry settings.
    wcscpy(RegPath, EnumKey);
    wcscat(RegPath, L"\\");
    wcscat(RegPath, PCIBUS_INSTANCE_KEYNAME);

    PCIRegClean(RegPath);
    
    // Enumerate bus
    if (!PCIEnum(EnumKey,Info.dwBusNumberBase, Info.dwBusNumberLength)) {
        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!Enumerate: PCIEnum failed\r\n"));
        return NULL;
    }

    // Start DLL under PCI\Instance key to load drivers (usually RegEnum.dll)
    return CreatePciBus(lpActiveKey,RegPath);
}


//
// Get registry information.
//
BOOL
RegGetInfo(
    PPCI_DEV_INFO pInfo
    )
{
    HKEY Key;
    DWORD Status;
    DWORD ValLen;
    DWORD ValType;
    DWORD Val;
    BOOL ConfigDllExists = TRUE;
    BOOL DllExists = TRUE;

    //
    // Open key to be enumerated
    //
    Status = RegOpenKeyEx(
                HKEY_LOCAL_MACHINE,
                pInfo->RegPath,
                0,
                0,
                &Key);
                
    if (Status != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ENUM|ZONE_ERROR,
            (TEXT("PCIBUS!RegGetInfo RegOpenKeyEx(%s) returned %d.\r\n"),
            pInfo->RegPath, Status));
        return FALSE;
    }

    //
    // Read NoConfig value
    //
    ValLen = sizeof(Val);
    Status = RegQueryValueEx(Key, PCIBUS_NOCONFIG_VALNAME, NULL, &ValType, (PUCHAR)&Val, &ValLen);            
    if ((Status == ERROR_SUCCESS) && (Val != 0)) {
        // If NoConfig exists and non-zero, don't configure bus
        pInfo->Configure = FALSE;
        RegCloseKey(Key);
        return TRUE;
    } else {
        pInfo->Configure = TRUE;
    }

    //
    // Read MemBase and MemLen values.
    //
    pInfo->MemBase.Num = PCI_TYPE0_ADDRESSES;
    if (!RegGetList(Key, PCIBUS_MEMBASE_VALNAME, &pInfo->MemBase.Num, pInfo->MemBase.Reg) && (pInfo->MemBase.Num == PCI_TYPE0_ADDRESSES)) {
        DEBUGMSG(ZONE_WARNING, (L"PCIBUS!RegGetInfo: Registry value '%s\\%s' has more than %d items in multi_sz list.  Ignoring the additional items.\r\n",
            pInfo->RegPath, PCIBUS_MEMBASE_VALNAME, PCI_TYPE0_ADDRESSES));
    }

    pInfo->MemLen.Num = PCI_TYPE0_ADDRESSES;
    if (!RegGetList(Key, PCIBUS_MEMLEN_VALNAME, &pInfo->MemLen.Num, pInfo->MemLen.Reg) && (pInfo->MemLen.Num == PCI_TYPE0_ADDRESSES)) {
        DEBUGMSG(ZONE_WARNING, (L"PCIBUS!RegGetInfo: Registry value '%s\\%s' has more than %d items in multi_sz list.  Ignoring the additional items.\r\n",
            pInfo->RegPath, PCIBUS_MEMLEN_VALNAME, PCI_TYPE0_ADDRESSES));
    }

    //
    // Read IoBase and IoLen values
    //
    pInfo->IoBase.Num = PCI_TYPE0_ADDRESSES;
    if (!RegGetList(Key, PCIBUS_IOBASE_VALNAME, &pInfo->IoBase.Num, pInfo->IoBase.Reg) && (pInfo->IoBase.Num == PCI_TYPE0_ADDRESSES)) {
        DEBUGMSG(ZONE_WARNING, (L"PCIBUS!RegGetInfo: Registry value '%s\\%s' has more than %d items in multi_sz list.  Ignoring the additional items\r\n",
            pInfo->RegPath, PCIBUS_IOBASE_VALNAME, PCI_TYPE0_ADDRESSES));
    }

    pInfo->IoLen.Num = PCI_TYPE0_ADDRESSES;
    if (!RegGetList(Key, PCIBUS_IOLEN_VALNAME, &pInfo->IoLen.Num, pInfo->IoLen.Reg) && (pInfo->IoLen.Num == PCI_TYPE0_ADDRESSES)) {
        DEBUGMSG(ZONE_WARNING, (L"PCIBUS!RegGetInfo: Registry value '%s\\%s' has more than %d items in multi_sz list.  Ignoring the additional items\r\n",
            pInfo->RegPath, PCIBUS_IOLEN_VALNAME, PCI_TYPE0_ADDRESSES));
    }

    //
    // Read ConfigEntry value (if it exists)
    //
    ValLen = sizeof(pInfo->ConfigEntryName);
    Status = RegQueryValueEx(Key, PCIBUS_CONFIGENTRY_VALNAME, NULL, &ValType, (PUCHAR)pInfo->ConfigEntryName, &ValLen);            
    if ((Status == ERROR_SUCCESS) && (ValType == PCIBUS_CONFIGENTRY_VALTYPE)) {
        // ConfigEntry value exists
        pInfo->ConfigEntry = TRUE;
    } else {
        pInfo->ConfigEntry = FALSE;
        wcscpy(pInfo->ConfigEntryName, L"");
        ConfigDllExists = FALSE;
    }
    
    if (pInfo->ConfigEntry) {
        //
        // Read ConfigDllName value (if it exists)
        //
        ValLen = sizeof(pInfo->ConfigDllName);
        Status = RegQueryValueEx(Key, PCIBUS_CONFIGDLL_VALNAME, NULL, &ValType, (PUCHAR)pInfo->ConfigDllName, &ValLen);            
        if ((Status != ERROR_SUCCESS) || (ValType != PCIBUS_CONFIGDLL_VALTYPE)) {

⌨️ 快捷键说明

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