pci.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 351 行

C
351
字号
/*++
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, 1996, 1997  Microsoft Corporation

Module Name:

   pci.c

Abstract:

   This file implements the platform specific WDM routines for accessing PCI
   configuration.

Notes:

--*/

#define WINCEMACRO 1

#include <windows.h>
#include <nkintr.h>

#undef DeviceIoControl
#include <oalio.h>
#include <wdmhal.h>
#include <altoona.h>
#include <hal.h>


#define MAX_SUPPORTED_PCI_BUS   8


typedef struct  _TYPE1_PCI_ADDRESS
{
    union {
        struct {
            ULONG   Reserved:2;
            ULONG   Register:6;
            ULONG   Function:3;
            ULONG   Device:5;
            ULONG   Bus:8;
            ULONG   Reserved2:7;
            ULONG   ConfigurationAccess:1;
        } bits;
        ULONG   AsULONG;
    } u;
} TYPE1_PCI_ADDRESS, *PTYPE1_PCI_ADDRESS;


// Initialized to 0 on load
UCHAR   ucPCIMaxBus;                            // Highest Bus number + 1
UCHAR   ucPCIMaxDevice[MAX_SUPPORTED_PCI_BUS];  // For Each Bus, Highest Device Number + 1


//CRITICAL_SECTION    csPCIConfig;



ULONG
PCIReadBusData(
    IN TYPE1_PCI_ADDRESS Type1Address,
    IN PVOID Buffer,
    IN ULONG Offset,
    IN ULONG Length
    );


VOID
PCIInitBusInfo()
{
    PCI_COMMON_CONFIG   pciCommonConfig;
    TYPE1_PCI_ADDRESS   type1Address;
    int                 bus, device;
    DWORD               dwResult;

//    InitializeCriticalSection(&csPCIConfig);

    //
    // Enumerate the PCI busses 
    //

    ucPCIMaxBus = 1;

    for (bus = 0; bus < ucPCIMaxBus; bus++)
    {
        for (device = 0; device < PCI_MAX_DEVICES; device++)
        {
            type1Address.u.AsULONG = 0;
            type1Address.u.bits.ConfigurationAccess = 1;
            type1Address.u.bits.Bus = bus;
            type1Address.u.bits.Device = device;
            type1Address.u.bits.Function = 0;

            dwResult = PCIReadBusData(
                type1Address, &pciCommonConfig, 0,
                offsetof(PCI_COMMON_CONFIG, u.type1.IOBase));

            if (pciCommonConfig.VendorID != 0xFFFF)
            {
                if (ucPCIMaxDevice[bus] <= device)
                {
                    ucPCIMaxDevice[bus] = device + 1;
                }

                if (bus == 0 && (pciCommonConfig.HeaderType & 0x7F) == 1)
                {
                    // Its a bridge

                    if (ucPCIMaxBus <= pciCommonConfig.u.type1.SubordinateBusNumber)
                    {
                        ucPCIMaxBus = pciCommonConfig.u.type1.SubordinateBusNumber + 1;
                        if (ucPCIMaxBus > (MAX_SUPPORTED_PCI_BUS + 1))
                        {
                            OEMWriteDebugString(
                                TEXT("Error: Too many PCI busses\r\n"));

                            ucPCIMaxBus = MAX_SUPPORTED_PCI_BUS + 1;
                        }
                    }
                }
            }
        }
    }

    if (ucPCIMaxBus == 1 && ucPCIMaxDevice[0] == 0)
    {
        OEMWriteDebugString(TEXT("No PCI device detected\r\n"));
        ucPCIMaxBus = (UCHAR)~0;
    }

}


ULONG
PCIReadBusData(
    IN TYPE1_PCI_ADDRESS Type1Address,
    IN PVOID Buffer,
    IN ULONG Offset,
    IN ULONG Length
    )
{
    PULONG     pBuffer;
    int        registerOffset, endOffset;
    ULONG      InitSaveLo;
    ULONG      InitSaveHi;

    ULONG      Slot = Type1Address.u.bits.Device + 11;

    registerOffset = Offset / sizeof(ULONG);
    endOffset = registerOffset + (Length + (sizeof(ULONG) - 1)) / sizeof(ULONG);
    pBuffer = Buffer;

    //
    // Can't access Vrc5074's config registers via PCI bus
    //
    if (Type1Address.u.bits.Bus == 0)
        if (Slot == IDSEL_VRC5074 ) {
            *pBuffer = 0xffff;
            return sizeof(SHORT);
        }
    else if ( Slot > 31) {
        *pBuffer = 0xffff;
        return sizeof(SHORT);
    }
    
    for ( ; registerOffset < endOffset; registerOffset++)
    {
        Type1Address.u.bits.Register = registerOffset;

        INTERRUPTS_OFF();

        InitSaveLo = pVRC5074->PCIINIT1.Low;
        InitSaveHi = pVRC5074->PCIINIT1.Hi;

        pVRC5074->PCIINIT1.Hi = 0;
        pVRC5074->PCIINIT1.Lo = PCIINIT_TYPE_CONFIG |
                                PCIINIT_ACCESS_32   |
                                ((Type1Address.u.bits.Bus == 0)
                                ? PCIINIT_CONFIGTYPE0 : PCIINIT_CONFIGTYPE1);

        if (Type1Address.u.bits.Bus == 0) {

            //
            // If slot number is greater than the config space size,
            // then the PCIADD field of the PCIINIT register must be used
            //

            if ((1 << Slot) >= PCI_CONFIG_SIZE) {

                pVRC5074->PCIINIT1.Lo |= (1 << Slot);
                if (registerOffset == 0)
                     *(PULONG)( PHYS_ADDR_PCI_CFG_BASE |
                                KSEG1_BASE
                              ) = 0;

                *pBuffer++ = *(PULONG)( PHYS_ADDR_PCI_CFG_BASE |
                                        KSEG1_BASE |
                                        (Type1Address.u.bits.Function << 8) |
                                        (registerOffset<<2)
                                      );



            } else {

                if (registerOffset == 0)
                     *(PULONG)( PHYS_ADDR_PCI_CFG_BASE |
                                KSEG1_BASE |
                                (1 << Slot)
                              ) = 0;

                *pBuffer++ = *(PULONG)( PHYS_ADDR_PCI_CFG_BASE |
                                        KSEG1_BASE |
                                        (1 << Slot) |
                                        (Type1Address.u.bits.Function << 8) |
                                        (registerOffset<<2)
                                      );
            }

        }
        else {

            if (registerOffset == 0)
                *(PULONG)( PHYS_ADDR_PCI_CFG_BASE |
                           KSEG1_BASE |
                           (Type1Address.u.AsULONG & 0x00ffffff)
                         ) = 0;

            *pBuffer++ = *(PULONG)( PHYS_ADDR_PCI_CFG_BASE |
                                    KSEG1_BASE |
                                    (Type1Address.u.AsULONG & 0x00ffffff)
                                  );

        }

        pVRC5074->PCIINIT1.Lo = InitSaveLo;
        pVRC5074->PCIINIT1.Hi = InitSaveHi;

        INTERRUPTS_ON();

        if (registerOffset == 0)
        {
            PUSHORT     pVendorID = (PUSHORT)(pBuffer - 1);

            if ((*pVendorID & 0xFF) == 0xFF || *pVendorID == 0)
            {
                *pVendorID = 0xFFFF;
            }

            if (*pVendorID == 0xFFFF)
            {
                Length = 2;
                break;
            }
        }
    }

    return Length;
}



ULONG
PCIGetBusDataByOffset(
    IN ULONG BusNumber,
    IN ULONG SlotNumber,
    IN PVOID Buffer,
    IN ULONG Offset,
    IN ULONG Length
    )
{
    TYPE1_PCI_ADDRESS   type1Address;

    type1Address.u.AsULONG = 0;
    type1Address.u.bits.ConfigurationAccess = 1;
    type1Address.u.bits.Bus = BusNumber;
    type1Address.u.bits.Device = ((PCI_SLOT_NUMBER *)&SlotNumber)->u.bits.DeviceNumber;
    type1Address.u.bits.Function = ((PCI_SLOT_NUMBER *)&SlotNumber)->u.bits.FunctionNumber;

    return PCIReadBusData(type1Address, Buffer, Offset, Length);
}



ULONG
PCISetBusDataByOffset(
    IN ULONG BusNumber,
    IN ULONG SlotNumber,
    IN PVOID Buffer,
    IN ULONG Offset,
    IN ULONG Length
    )
{
    PCI_SLOT_NUMBER     slotNumber;
    PULONG              pBuffer;
    int                 registerOffset, endOffset;
    TYPE1_PCI_ADDRESS   type1Address;
    ULONG               InitSaveLo;
    ULONG               InitSaveHi;

    slotNumber.u.AsULONG = SlotNumber;

    type1Address.u.AsULONG = 0;
    type1Address.u.bits.ConfigurationAccess = 1;
    type1Address.u.bits.Bus = BusNumber;
    type1Address.u.bits.Device = slotNumber.u.bits.DeviceNumber;
    type1Address.u.bits.Function = slotNumber.u.bits.FunctionNumber;

    registerOffset = Offset / sizeof(ULONG);
    endOffset = registerOffset + (Length + (sizeof(ULONG) - 1)) / sizeof(ULONG);
    pBuffer = Buffer;

    for ( ; registerOffset < endOffset; registerOffset++) {
        type1Address.u.bits.Register = registerOffset;

        INTERRUPTS_OFF();

        InitSaveLo = pVRC5074->PCIINIT1.Low;
        InitSaveHi = pVRC5074->PCIINIT1.Hi;

        pVRC5074->PCIINIT1.Hi = 0;
        pVRC5074->PCIINIT1.Lo = PCIINIT_TYPE_CONFIG | PCIINIT_ACCESS_32 | ((type1Address.u.bits.Bus == 0) ? PCIINIT_CONFIGTYPE0 : PCIINIT_CONFIGTYPE1);

        if (type1Address.u.bits.Bus == 0) {
            //
            // If slot number is greater than the config space size,
            // then the PCIADD field of the PCIINIT register must be used
            //
            if ((1 << (type1Address.u.bits.Device+11)) >= PCI_CONFIG_SIZE) {
                pVRC5074->PCIINIT1.Lo |= 1 << (type1Address.u.bits.Device+11);
                *(PULONG)(PHYS_ADDR_PCI_CFG_BASE | (type1Address.u.bits.Function << 8) | KSEG1_BASE | (registerOffset<<2)) = *pBuffer++;
            } else {
                *(PULONG)(PHYS_ADDR_PCI_CFG_BASE | KSEG1_BASE | (type1Address.u.bits.Function << 8) | (1 << (type1Address.u.bits.Device+11)) | (registerOffset<<2)) = *pBuffer++;
            }
        } else {
            *(PULONG)( PHYS_ADDR_PCI_CFG_BASE | KSEG1_BASE | (type1Address.u.AsULONG & 0x00ffffff)) = *pBuffer++;
        }

        pVRC5074->PCIINIT1.Lo = InitSaveLo;
        pVRC5074->PCIINIT1.Hi = InitSaveHi;

        INTERRUPTS_ON();

    }

    return Length;
}

⌨️ 快捷键说明

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