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

📄 pciinit.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++
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

Module Name: pciinit.c

Abstract: Boot loader PCI initialization functions.

Functions:

    PCIConfig_Read
    PCIConfig_Write
    PCIConfig_WriteW
    PciInit
    PciInitBus
    PciInitDevice
    PciInitBridge
    PciInitCheckBARs
    PciInitAllocateIoSpace
    PciInitAllocateMemSpace
    PciInitListDevices
    PciInitSearchForDevice
    PCIInitListDevicesSummary

Notes:

--*/

#include <windows.h>
#include <ceddk.h>
#include "pciinit.h"
#include "pci.h"
#include "bldr.h"

#pragma warning (disable: 4002)

// Preprocessor definitions.
//
#define MAX_SPACE 120
#define MAX_DEVICE 32


#define DPF EdbgOutputDebugString
#define VDPF 

// Global variables.
//
ULONG nSpaceDesc = 0;
SPACE_DESC SpaceDesc[MAX_SPACE];
ULONG nDev = 0;
ULONG SortOrder = 0;
PCI_DEVICE pDev[MAX_DEVICE];


DWORD 
PCIConfig_Read(
    ULONG bus,
    ULONG device,
    ULONG function,
    ULONG offset
    ) 
{
    PCI_SLOT_NUMBER     slotNumber;
    int                 length;
    DWORD               dwRet = 0;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("+PciConfigRead (%d:%d:%d 0x%x)..."), bus, device, function, offset));
    
    slotNumber.u.bits.DeviceNumber = device;
    slotNumber.u.bits.FunctionNumber = function;

    length = PCIGetBusDataByOffset(bus, slotNumber.u.AsULONG,
                                   &dwRet, offset, sizeof(dwRet));

    DEBUGMSG(ZONE_INFO, (TEXT("0x%x read\r\n"), dwRet));

    return(dwRet);
}


BOOL
PCIConfig_Write(
    ULONG bus,
    ULONG device,
    ULONG function,
    ULONG offset,
    ULONG dwValue
    ) 
{
    PCI_SLOT_NUMBER     slotNumber;
    int                 length;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("+PciConfigWrite (%d:%d:%d 0x%x)..."), bus, device, function, offset));
    
    slotNumber.u.bits.DeviceNumber = device;
    slotNumber.u.bits.FunctionNumber = function;

    length = PCISetBusDataByOffset(bus, slotNumber.u.AsULONG,
                                   &dwValue, offset, sizeof(dwValue));

    DEBUGMSG(ZONE_INFO, (TEXT("0x%x written\r\n"), dwValue));
    return(FALSE);
}


BOOL
PCIConfig_WriteW(
    ULONG bus,
    ULONG device,
    ULONG function,
    ULONG offset,
    ULONG wValue
    ) 
{
    PCI_SLOT_NUMBER     slotNumber;
    int                 length;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("+PciConfigWrite (%d:%d:%d 0x%x)..."), bus, device, function, offset));
    
    slotNumber.u.bits.DeviceNumber = device;
    slotNumber.u.bits.FunctionNumber = function;

    length = PCISetBusDataByOffset(bus, slotNumber.u.AsULONG,
                                   &wValue, offset, sizeof(wValue));

    DEBUGMSG(ZONE_INFO, (TEXT("0x%x written\r\n"), wValue));
    return(FALSE);
}


BOOL PciInit(void)
{
    ULONG SubordinateBus = 0;
    ULONG MemSize = 0;
    ULONG IoSize = 0;
    BOOL Status = TRUE;

    SortOrder = 0;
    nSpaceDesc = 0;
    nDev = 0;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("+PciInit\r\n")));
    
    if (!PciInitBus(0,&SubordinateBus,&MemSize,&IoSize)) {
        RETAILMSG(1, (TEXT("ERROR: Too many PCI devices initializing PCI Bus\r\n")));
        return(FALSE);
    }

    if (MemSize > (g_nPCI_BUS0_MEM_LIMIT - g_nPCI_BUS0_MEM_BASE)) {
        RETAILMSG(1, (TEXT("ERROR: Not enough memory space allocated for PCI Bus\r\n")));
        Status = FALSE;
    }

    if (IoSize > (g_nPCI_BUS0_IO_LIMIT - g_nPCI_BUS0_IO_BASE)) {
        RETAILMSG(1, (TEXT("ERROR: Not enough I/O space allocated for PCI Bus\r\n")));
        Status = FALSE;
    }

    //InitSerial2();
    
    if (!PciInitAllocateMemSpace(g_nPCI_BUS0_MEM_LIMIT, g_nPCI_BUS0_MEM_BASE, 0)) {
        Status = FALSE;
        RETAILMSG(1, (TEXT("ERROR: Failure allocating PCI memory space\r\n")));
    }
    if (!PciInitAllocateIoSpace(g_nPCI_BUS0_IO_LIMIT, g_nPCI_BUS0_IO_BASE, 0)) {
        Status = FALSE;
        RETAILMSG(1, (TEXT("ERROR: Failure allocation PCI IO space\r\n")));
    }

    return(Status);
}


BOOL
PciInitBus(
    ULONG Bus,
    PULONG pSubordinateBus,
    PULONG pMemSize,
    PULONG pIoSize
    )
{
    ULONG Device;
    ULONG VendorID;
    ULONG HeaderType;
    ULONG Function;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("InitBus %d\r\n"), Bus));

    //
    // Loop through all device numbers (slots)
    //

    for (Device = 0; Device < 32; Device++) {

        DEBUGMSG(ZONE_FUNCTION, (TEXT("InitBus (device %d)\r\n"), Device));
        //
        // Loop through all functions
        //

        for (Function = 0; Function < 8; Function++) {

            DEBUGMSG(ZONE_FUNCTION, (TEXT("InitBus (device %d, func %d)\r\n"), Device, Function));
            //
            // Check Device Present
            //

            PCIConfig_Write(Bus,Device,Function,PCI_CONFIG_BASE0,0xFFFFFFFF);
            VendorID = PCIConfig_Read(Bus,Device,Function,PCI_CONFIG_ID);
            if (((VendorID & 0xFFFF0000) != 0xFFFF0000) &&
                ((VendorID & 0x0000FFFF) != 0x0000FFFF) &&
                ((VendorID & 0x0000FFFF) != 0x00000000)) {

                pDev[nDev].Bus = Bus;
                pDev[nDev].Device = Device;
                pDev[nDev].Function = Function;
                pDev[nDev].VendorID = VendorID;
                nDev++;
                if (nDev == MAX_DEVICE) {
                    return(FALSE);
                }

                //
                // Check header type
                //

                HeaderType = PCIConfig_Read(Bus,Device,Function,PCI_CONFIG_HEAD);
                if (((PPCI_BHLC)(&HeaderType))->HeadType.HeadType == 0x00) {

                    //
                    // regular device
                    //

                    if (!PciInitDevice(Bus,Device,Function,pMemSize,pIoSize)) {
                        return(FALSE);
                    }

                } else {

                    //
                    // Bridge device
                    //

                    if (!PciInitBridge(Bus,
                                       Device,
                                       Function,
                                       pSubordinateBus,
                                       pMemSize,
                                       pIoSize)) {
                        return(FALSE);
                    }

                }

                //
                // check if multifunction device
                //

// TODO - National CS5330 SouthBridge doesn't report itself as a multifuntion.
// This check should be made platform-dependent.
                if (((VendorID & 0xFF00FFFF) != 0x01001078) && ((PPCI_BHLC)(&HeaderType))->HeadType.MultiFunctionDevice == 0) {
                    break;
                }
            } else {
                break;
            }
        }
    }
    DEBUGMSG(ZONE_FUNCTION, (TEXT("--InitBus %d\r\n"), Bus));
    return(TRUE);
}


BOOL
PciInitDevice(
    ULONG Bus,
    ULONG Device,
    ULONG Function,
    PULONG pMemSize,
    PULONG pIoSize
    )
{
    ULONG Reg;
    DWORD dwVendorDevice;

    dwVendorDevice = PCIConfig_Read(Bus,Device,Function,0);

    DEBUGMSG(ZONE_FUNCTION, (TEXT("InitDevice %d %d %d %X\r\n"), Bus, Device, Function, dwVendorDevice));

    //
    // read the base address registers to determine space to allocate
    //

    if (!PciInitCheckBARs(Bus,Device,Function,6,pMemSize,pIoSize)) {
        return(FALSE);
    }

    //
    // disable expansion ROM
    // Enable device
    //

    PCIConfig_Write(Bus,Device,Function,PCI_CONFIG_ROM,0);
    PCIConfig_Write(Bus,Device,Function,PCI_CONFIG_COMMAND_STATUS,0x7);
    Reg = PCIConfig_Read(Bus,Device,Function,PCI_CONFIG_INTERRUPT);
    ((PPCI_INT)(&Reg))->InterruptLine = 0xFF;
    PCIConfig_Write(Bus,Device,Function,PCI_CONFIG_INTERRUPT,Reg);

    return(TRUE);
}


BOOL
PciInitBridge(
    ULONG Bus,
    ULONG Device,
    ULONG Function,
    PULONG pSubordinateBus,
    PULONG pMemSize,
    PULONG pIoSize
    )
{
    ULONG BusReg;
    ULONG SecondaryMemSize;
    ULONG SecondaryIoSize;
    ULONG i;
    ULONG Reg;
    DWORD dwVal;

    dwVal = PCIConfig_Read(Bus,Device,Function,0);

    DEBUGMSG(ZONE_FUNCTION, (TEXT("InitBridge %d %d %d %X\r\n"), Bus, Device, Function, dwVal));
    //
    // read the base address registers to determine space to allocate
    //

    if (!PciInitCheckBARs(Bus,Device,Function,2,pMemSize,pIoSize)) {
        RETAILMSG(1, (TEXT("ERROR PciInitCheckBARs failed.\r\n")));
        return(FALSE);
    }

    //
    // Enable bridge
    // disable expansion ROM
    // zero all the base and limit registers - these will get written later
    // zero the IRQ register
    //
    DEBUGMSG(ZONE_INFO, (TEXT("IB (enable bridge)\r\n")));

    PCIConfig_Write(Bus,Device,Function,PCI_CONFIG_COMMAND_STATUS,0x7);
    PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_ROM,0x0);
    PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_PREFETCHABLE,0x0);
    PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_BASE_UPPER32,0x0);
    PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_LIMIT_UPPER32,0x0);
    PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_MEMORY,0);
    PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_IO_UPPER16,0);
    Reg = PCIConfig_Read(Bus,Device,Function,PCIBRIDGE_IO);
    ((PBRIDGE_IO)(&Reg))->IoLimit.Address = 0;
    ((PBRIDGE_IO)(&Reg))->IoBase.Address = 0;
    PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_IO,Reg);
    Reg = PCIConfig_Read(Bus,Device,Function,PCI_CONFIG_INTERRUPT);
    ((PPCI_INT)(&Reg))->InterruptLine = 0xFF;
    PCIConfig_Write(Bus,Device,Function,PCI_CONFIG_INTERRUPT,Reg);

    
    //
    // Set the bus numbers
    // Need to set the subordinate bus as max for now, then write
    // actual number after found all downstream busses
    //

    (*pSubordinateBus)++;
    BusReg = PCIConfig_Read(Bus,Device,Function,PCIBRIDGE_BUS_NUMBER);
    ((PBRIDGE_BUS)(&BusReg))->PrimaryBusNumber = (BYTE)Bus;
    ((PBRIDGE_BUS)(&BusReg))->SecondaryBusNumber = (BYTE)(*pSubordinateBus);
    ((PBRIDGE_BUS)(&BusReg))->SubordinateBusNumber = 0xFF;
    PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_BUS_NUMBER,BusReg);

    DEBUGMSG(ZONE_INFO, (TEXT("InitBridge %d %d %d %d %X\r\n"), Bus, Device,
                       Function, *pSubordinateBus,
                       PCIConfig_Read(Bus,Device,Function,0)));
    //
    // Call initbus routine recursively
    //
    SecondaryMemSize = 0;
    SecondaryIoSize = 0;
    if (!PciInitBus(*pSubordinateBus,
                    pSubordinateBus,
                    &SecondaryMemSize,
                    &SecondaryIoSize)) {
        RETAILMSG(1, (TEXT("ERROR: PciInitBus failed.\r\n")));
        return(FALSE);
    }
     
    //
    // fill in the proper value for subordinate bus
    //

    ((PBRIDGE_BUS)(&BusReg))->SubordinateBusNumber = (BYTE)(*pSubordinateBus);
    PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_BUS_NUMBER,BusReg);

    //
    // Add bridge to list to come back later and fill in limit registers
    // Round up space required by secondary bus to 1MB boundary and then
    // align to proper boundary after that
    //

    SecondaryMemSize = (SecondaryMemSize + 0x000FFFFF) & 0xFFF00000;
    if (((SecondaryMemSize - 1) & (SecondaryMemSize)) != 0) {
        for (i = 31; i > 1; i--) {
            if (SecondaryMemSize & (1 << i)) {
                SecondaryMemSize = (1 << (i+1));
                break;
            }
        }
    }

    SecondaryIoSize = (SecondaryIoSize + 0x00000FFF) & 0xFFFFF000;
    if (((SecondaryIoSize - 1) & (SecondaryIoSize)) != 0) {
        for (i = 31; i > 1; i--) {
            if (SecondaryIoSize & (1 << i)) {
                SecondaryIoSize = (1 << (i+1));
                break;
            }
        }
    }

    DEBUGMSG(ZONE_INFO, (TEXT("Bridgespace %X %X %X\r\n"),
                       SecondaryMemSize, SecondaryIoSize,BusReg));

    SpaceDesc[nSpaceDesc].Bus = Bus;
    SpaceDesc[nSpaceDesc].Device = Device;
    SpaceDesc[nSpaceDesc].Function = Function;
    SpaceDesc[nSpaceDesc].MemSize = SecondaryMemSize;
    SpaceDesc[nSpaceDesc].IoSize = SecondaryIoSize;
    SpaceDesc[nSpaceDesc].Bridge = 1;
    SpaceDesc[nSpaceDesc].SecondaryBus =
        ((PBRIDGE_BUS)(&BusReg))->SecondaryBusNumber;
    nSpaceDesc++;
    if (nSpaceDesc == MAX_SPACE) {
        RETAILMSG(1, (TEXT("ERROR: MAX_SPACE.\r\n")));

⌨️ 快捷键说明

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