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

📄 pcicfg.c

📁 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.
//

//
// Routines to configure and initialize the PCIbus
//
#include <windows.h>
#include <ceddk.h>
#include <devload.h>
#include <PCIbus.h>
#include "PCIcfg.h"
#include "PCIproto.h"
#include "PCIdbg.h"

#pragma warning (disable: 4002)

//
// Resource lists for Memory and I/O
//
PPCI_RSRC g_MemHead, g_IoHead;

//   
// Function prototypes
//
static BOOL
PCICfgBus(
    PPCI_DEV_INFO pBusInfo,
    ULONG Bus,
    PULONG pSubordinateBus,
    PULONG pMemSize,
    PULONG pIoSize
    );

static BOOL
PCICfgDevice(
    PPCI_DEV_INFO pBusInfo,
    ULONG Bus,
    ULONG Device,
    ULONG Function,
    PPCI_COMMON_CONFIG pCfg,
    PULONG pMemSize,
    PULONG pIoSize
    );

static BOOL
PCICfgBridge(
    PPCI_DEV_INFO pBusInfo,
    ULONG Bus,
    ULONG Device,
    ULONG Function,
    PPCI_COMMON_CONFIG pCfg,
    PULONG pSubordinateBus,
    PULONG pMemSize,
    PULONG pIoSize
    );

static BOOL
PCICfgCardBusBridge(
    PPCI_DEV_INFO pBusInfo,
    ULONG Bus,
    ULONG Device,
    ULONG Function,
    PPCI_COMMON_CONFIG pCfg,
    PULONG pSubordinateBus,
    PULONG pMemSize,
    PULONG pIoSize
    );

static BOOL
PCICfgCheckBARs(
    PPCI_DEV_INFO pInfo,
    PULONG pMemSize,
    PULONG pIoSize
    );

static BOOL
PCICfgAllocateIoSpace(
    DWORD Bus,
    DWORD Base,
    DWORD Size
    );

static BOOL
PCICfgAllocateMemSpace(
    DWORD Bus,
    DWORD Base,
    DWORD Size
    );

static BOOL
PCICfgFindMatch(
    PPCI_DEV_INFO pInfo
    );

static BOOL
RequestIrq(
    PDEVICE_LOCATION pDevLoc,
    PDWORD pIrq
    );

//    
// Inline functions
//

//
// Read a DWORD from a device's configuration space
//
__inline static DWORD
PCIConfig_Read(
    ULONG BusNumber,
    ULONG Device,
    ULONG Function,
    ULONG Offset
    )
{
    ULONG RetVal = FALSE;
    PCI_SLOT_NUMBER SlotNumber;

    SlotNumber.u.AsULONG = 0;
    SlotNumber.u.bits.DeviceNumber = Device;
    SlotNumber.u.bits.FunctionNumber = Function;
    
    HalGetBusDataByOffset(PCIConfiguration, BusNumber, SlotNumber.u.AsULONG, &RetVal, Offset, sizeof(RetVal));

    return RetVal;
}


//
// Write a DWORD to a device's configuration space
//
__inline static void
PCIConfig_Write(
    ULONG BusNumber,
    ULONG Device,
    ULONG Function,
    ULONG Offset,
    ULONG Value
    )
{
    PCI_SLOT_NUMBER SlotNumber;

    SlotNumber.u.AsULONG = 0;
    SlotNumber.u.bits.DeviceNumber = Device;
    SlotNumber.u.bits.FunctionNumber = Function;

    HalSetBusDataByOffset(PCIConfiguration, BusNumber, SlotNumber.u.AsULONG, &Value, Offset, sizeof(Value));
}


//
// Top-level PCIbus initialization and configuration routine
//
BOOL
PCICfg(
    PPCI_DEV_INFO pBusInfo
    )
{
    ULONG SubordinateBus = 0;
    ULONG MemSize = 0;
    ULONG IoSize = 0;
    BOOL Status = TRUE;

    DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!PCICfg+(%s, MemBase 0x%X, MemLen 0x%X, IoBase 0x%X, IoLen 0x%X)\r\n",
        pBusInfo->RegPath, pBusInfo->MemBase.Reg[0], pBusInfo->MemLen.Reg[0], pBusInfo->IoBase.Reg[0], pBusInfo->IoLen.Reg[0]));
        
    // Initialize resource lists
    if (!(g_MemHead = PCIRsrc_New(0, 0, 0, 0, pBusInfo->MemBase.Reg[0], pBusInfo->MemLen.Reg[0], TRUE, 0, TRUE, NULL))) {
        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCICfg: Failed local alloc of g_MemHead)\r\n"));
        return FALSE;
    }
    
    if (!(g_IoHead = PCIRsrc_New(0, 0, 0, 0, pBusInfo->IoBase.Reg[0], pBusInfo->IoLen.Reg[0], TRUE, 0, TRUE, NULL))) {
        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCICfg: Failed local alloc of g_IoHead)\r\n"));
        PCIRsrc_DelList(g_MemHead);
        return FALSE;
    }
    
    if (!PCICfgBus(pBusInfo, 0, &SubordinateBus, &MemSize, &IoSize)) {
        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCICfg: Failed PCICfgBus( ) call\r\n"));
        Status = FALSE;
        goto PCICfg_Exit;
    }

#ifdef DEBUG
    DEBUGMSG(ZONE_RSRC, (L"Mem List:\r\n"));
    if (ZONE_RSRC) PCIRsrc_PrintList(g_MemHead);
    DEBUGMSG(ZONE_RSRC, (L"I/O List:\r\n"));
    if (ZONE_RSRC) PCIRsrc_PrintList(g_IoHead);
#endif
    
    if (MemSize > pBusInfo->MemLen.Reg[0]) {
        RETAILMSG(1, (L"PCIBUS!PCICfg: Not enough memory space allocated for PCI Bus, PCIbus driver terminating.\r\n"));
        RETAILMSG(1, (L"PCIBUS!PCICfg: Host Bridge window size: 0x%X, requested: 0x%X\r\n", pBusInfo->MemLen.Reg[0], MemSize));
        RETAILMSG(1, (L"PCIBUS!PCICfg: List of requested memory resources:\r\n"));
        PCIRsrc_PrintList(g_MemHead);
        Status = FALSE;
        goto PCICfg_Exit;
    }
     
    if (IoSize > pBusInfo->IoLen.Reg[0]) {
        RETAILMSG(1, (L"PCIBUS!PCICfg: Not enough I/O space allocated for PCI Bus, PCIbus driver terminating.\r\n"));
        RETAILMSG(1, (L"PCIBUS!PCICfg: Host Bridge window size: 0x%X, requested: 0x%X\r\n", pBusInfo->IoLen.Reg[0], IoSize));
        RETAILMSG(1, (L"PCIBUS!PCICfg: List of requested I/O resources:\r\n"));
        PCIRsrc_PrintList(g_IoHead);
        Status = FALSE;
        goto PCICfg_Exit;
    }
     
    if (!PCICfgAllocateMemSpace(0, pBusInfo->MemBase.Reg[0], pBusInfo->MemLen.Reg[0])) {
        RETAILMSG(1, (L"PCIBUS!PCICfg: Failure allocating PCI memory space, PCIbus driver terminating.\r\n"));
        Status = FALSE;
        goto PCICfg_Exit;
    }
    
    if (!PCICfgAllocateIoSpace(0, pBusInfo->IoBase.Reg[0], pBusInfo->IoLen.Reg[0])) {
        RETAILMSG(1, (L"PCIBUS!PCICfg: Failure allocating PCI I/O space, PCIbus driver terminating.\r\n"));
        Status = FALSE;
        goto PCICfg_Exit;
    }

PCICfg_Exit:
    UnloadConfigEntrys();           // Unload any configuration DLLs that were loaded
    PCIRsrc_DelList(g_MemHead);
    PCIRsrc_DelList(g_IoHead);

    DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!PCICfg-\r\n"));
    
    return Status;
}


//
// Initialize and configure PCIbus
//
static BOOL
PCICfgBus(
    PPCI_DEV_INFO pBusInfo,
    ULONG Bus,
    PULONG pSubordinateBus,
    PULONG pMemSize,
    PULONG pIoSize
    )
{
    DWORD Device;
    DWORD Function;
    DWORD Length;

    PCI_SLOT_NUMBER SlotNumber;
    PCI_COMMON_CONFIG Cfg;

    BOOL RetVal = TRUE;

    DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!PCICfgBus+(Bus %d)\r\n", Bus));

    SlotNumber.u.AsULONG = 0;
    
    // Loop through all device numbers
    for (Device = 0; Device < PCI_MAX_DEVICES; Device++) {
        SlotNumber.u.bits.DeviceNumber = Device;
        
        // Loop through all functions  
        for (Function = 0; Function < PCI_MAX_FUNCTION; Function++) {
            Cfg.VendorID = PCI_INVALID_VENDORID;
            Cfg.DeviceID = PCI_INVALID_DEVICEID;
            Cfg.HeaderType = PCI_DEVICE_TYPE;
            
            SlotNumber.u.bits.FunctionNumber = Function;

            // Read device's configuration header (except for device-specific information) 
            Length = HalGetBusData(PCIConfiguration, Bus, SlotNumber.u.AsULONG, &Cfg, sizeof(Cfg) - sizeof(Cfg.DeviceSpecific));

            if (Length != (sizeof(Cfg) - sizeof(Cfg.DeviceSpecific)) ||
                (Cfg.DeviceID == PCI_INVALID_DEVICEID) || (Cfg.VendorID == PCI_INVALID_VENDORID) || (Cfg.VendorID == 0)) {
                // No function found
                if (Function != 0) {
                    // If a multi-function device, continue to next function
                    continue;
                } else {
                    // If not a multi-function device, continue to next device
                    break;
                }
            }

            switch (Cfg.HeaderType & ~PCI_MULTIFUNCTION) {
            case PCI_DEVICE_TYPE:  // Device   
                if (!PCICfgDevice(pBusInfo, Bus, Device, Function, &Cfg, pMemSize, pIoSize)) {
                    RetVal = FALSE;
                    goto PCICfgBus_Exit;
                }

                break;

            case PCI_BRIDGE_TYPE:  // PCI-PCI bridge
                if (!PCICfgBridge(pBusInfo, Bus, Device, Function, &Cfg, pSubordinateBus, pMemSize, pIoSize)) {
                    RetVal = FALSE;
                    goto PCICfgBus_Exit;
                }

                break;

            case PCI_CARDBUS_TYPE:  // PCI-Cardbus bridge
                if (!PCICfgCardBusBridge(pBusInfo, Bus, Device, Function, &Cfg,pSubordinateBus, pMemSize, pIoSize)) {
                    RetVal = FALSE;
                    goto PCICfgBus_Exit;
                }

                break;

            default:
                DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCICfgBus: Invalid HeaderType, 0x%X, found for Device %d/%d/%d\r\n",
                    Cfg.HeaderType, Bus, Device, Function));
            }

            if (Function == 0 && !(Cfg.HeaderType & PCI_MULTIFUNCTION)) {
                // Not a multifunction device, continue on to next device
                break;
            }
        }
    }

PCICfgBus_Exit:
    DEBUGMSG(ZONE_INIT, (L"PCIBUS!PCICfgBus-(Bus %d, SubBus %d, MemSize 0x%X, IoSize 0x%X)\r\n", Bus, *pSubordinateBus, *pMemSize, *pIoSize));
    

⌨️ 快捷键说明

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