pci.c

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

C
394
字号
// -----------------------------------------------------------------------------
//
//      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.
//  
// -----------------------------------------------------------------------------
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <pc_ddk.h>

int             __cdecl _inp  (unsigned short);
unsigned short  __cdecl _inpw (unsigned short);
unsigned long   __cdecl _inpd (unsigned short);

int             __cdecl _outp (unsigned short, int);
unsigned short  __cdecl _outpw(unsigned short, unsigned short);
unsigned long   __cdecl _outpd(unsigned short, unsigned long);


#define MAX_SUPPORTED_PCI_BUS   8

#define PCI_TYPE1_ADDRESS       0x0CF8
#define PCI_TYPE1_DATA          0x0CFC

#define PCI_TYPE2_FORWARD       0x0CFA
#define PCI_TYPE2_CSE           0x0CF8

// -------------------------------------
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;

typedef struct  _TYPE2_PCI_CSE {
    union {
        struct {
            UCHAR   SCE:1;
            UCHAR   Function:3;
            UCHAR   Key:4;
        } bits;
        UCHAR   AsUCHAR;
    } u;
} TYPE2_PCI_CSE, *PTYPE2_PCI_CSE;

typedef struct  _TYPE2_PCI_ADDRESS {
    union {
        struct {
            USHORT  Reserved:2;
            USHORT  Register:6;
            USHORT  Device:4;
            USHORT  PCIConfigSpace:4;   // Must be 0xC
        } bits;
        USHORT  AsUSHORT;
    } u;
} TYPE2_PCI_ADDRESS, *PTYPE2_PCI_ADDRESS;


// -------------------------------------
UCHAR   ucPCIConfigMechanism;

UCHAR   ucPCIMaxBus;                            // Highest Bus #+1, Inited to 0 on load
UCHAR   ucPCIMaxDeviceNumber = PCI_MAX_DEVICES;
UCHAR   ucPCIMaxDevice[MAX_SUPPORTED_PCI_BUS];  // For Each Bus, Highest Device Number + 1

CRITICAL_SECTION    csPCIConfig;

BOOL    bPCIInitialized;


// -------------------------------------
ULONG
PCIReadBusData(
              IN ULONG BusNumber,
              IN ULONG DeviceNumber,
              IN ULONG FunctionNumber,
              IN PVOID Buffer,
              IN ULONG Offset,
              IN ULONG Length
              );



// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
PCIInitBusInfo()
{
    PCI_COMMON_CONFIG   pciCommonConfig;
    int                 bus, device;
    DWORD               dwResult;

    if ( bPCIInitialized ) {
        return;
    }

    bPCIInitialized = TRUE;

    InitializeCriticalSection(&csPCIConfig);

    if ( ucPCIConfigMechanism == 0 ) {
        PBYTE   pArgs;

        pArgs = *(PBYTE *)0x801FFFFC;

        if ( pArgs != 0 ) {
            (ULONG)pArgs |= 0x80000000;

            ucPCIConfigMechanism = pArgs[3] & 0x03;
            ucPCIMaxBus = pArgs[3] >> 2;
        }

        if ( ucPCIConfigMechanism == 2 ) {
            ucPCIMaxDeviceNumber = 16;
        }
    }

    if ( ucPCIConfigMechanism == 0 ) {
        RETAILMSG(1, (TEXT("No PCI bus\r\n")));

        ucPCIConfigMechanism = (UCHAR)~0;

        return;
    }

    //
    // Enumerate the PCI busses 
    //

    ucPCIMaxBus = 1;

    for ( bus = 0; bus < ucPCIMaxBus; bus++ ) {
        for ( device = 0; device < ucPCIMaxDeviceNumber; device++ ) {
            dwResult = PCIReadBusData(
                                     bus, device, 0, &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) ) {
                            RETAILMSG(1, (TEXT("Error: Too many PCI busses\r\n")));

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

    if ( ucPCIMaxBus == 1 && ucPCIMaxDevice[0] == 0 ) {
        ucPCIMaxBus = (UCHAR)~0;
    }
}



// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
ULONG
PCIReadBusData(
              IN ULONG BusNumber,
              IN ULONG DeviceNumber,
              IN ULONG FunctionNumber,
              IN PVOID Buffer,
              IN ULONG Offset,
              IN ULONG Length
              )
{
    PULONG              pBuffer;
    int                 registerOffset, endOffset;

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

    if ( ucPCIConfigMechanism == 1 ) {
        TYPE1_PCI_ADDRESS   type1Address;

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

        for ( ; registerOffset < endOffset; registerOffset++ ) {
            type1Address.u.bits.Register = registerOffset;
            _outpd((USHORT)PCI_TYPE1_ADDRESS, type1Address.u.AsULONG);
            *pBuffer++ = _inpd((USHORT)PCI_TYPE1_DATA);
        }
    } else if ( ucPCIConfigMechanism == 2 ) {
        TYPE2_PCI_CSE       type2CSE;
        TYPE2_PCI_ADDRESS   type2Address;

        type2CSE.u.bits.Key = type2CSE.u.bits.SCE = 0xFF;
        type2CSE.u.bits.Function = (UCHAR)FunctionNumber;

        type2Address.u.AsUSHORT = 0;
        type2Address.u.bits.PCIConfigSpace = 0xC;
        type2Address.u.bits.Device = (USHORT)DeviceNumber;

        _outp((USHORT)PCI_TYPE2_FORWARD, (UCHAR)BusNumber);

        INTERRUPTS_OFF();

        _outp((USHORT)PCI_TYPE2_CSE, type2CSE.u.AsUCHAR);

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

            *pBuffer++ = _inpd((USHORT)type2Address.u.AsUSHORT);
        }

        _outp((USHORT)PCI_TYPE2_CSE, 0);
        _outp((USHORT)PCI_TYPE2_FORWARD, 0);

        INTERRUPTS_ON();
    } else {
        if ( ucPCIConfigMechanism == (UCHAR)~0 ) {
            // No PCI bus
            RETAILMSG(1, (TEXT("HalpReadBusData: No PCI bus\r\n")));
        } else {
            RETAILMSG(1, (TEXT("HalpReadBusData: Unknown config mechanism = 0x%2.2X\r\n"),
                          ucPCIConfigMechanism));
        }

        Length = 0;
    }

    return (Length);
}



// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
ULONG
PCIGetBusDataByOffset(
                     IN ULONG BusNumber,
                     IN ULONG SlotNumber,
                     IN PVOID Buffer,
                     IN ULONG Offset,
                     IN ULONG Length
                     )
{
    PCI_SLOT_NUMBER     slotNumber;

    if ( bPCIInitialized == FALSE )
        PCIInitBusInfo();

    if ( ucPCIMaxBus == (UCHAR)~0U || BusNumber >= ucPCIMaxBus ) {
        RETAILMSG(1, (TEXT("Invalid bus number passed (%d >= %d)\r\n"),
                      BusNumber, ucPCIMaxBus));

        return (0);
    }

    slotNumber.u.AsULONG = SlotNumber;

    if ( slotNumber.u.bits.DeviceNumber >= ucPCIMaxDeviceNumber ) {
        return (0);
    }

    EnterCriticalSection(&csPCIConfig);

    Length = PCIReadBusData(
                           BusNumber, slotNumber.u.bits.DeviceNumber,
                           slotNumber.u.bits.FunctionNumber, Buffer, Offset, Length);

    LeaveCriticalSection(&csPCIConfig);

    return (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;

    if ( bPCIInitialized == FALSE )
        PCIInitBusInfo();

    if ( ucPCIMaxBus == (UCHAR)~0U || BusNumber >= ucPCIMaxBus ) {
        RETAILMSG(1, (TEXT("Invalid bus number passed (%d >= %d)\r\n"),
                      BusNumber, ucPCIMaxBus));

        return (0);
    }

    slotNumber.u.AsULONG = SlotNumber;

    if ( slotNumber.u.bits.DeviceNumber >= ucPCIMaxDeviceNumber ) {
        return (0);
    }

    EnterCriticalSection(&csPCIConfig);

    if ( ucPCIConfigMechanism == 1 ) {
        TYPE1_PCI_ADDRESS   type1Address;

        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 + 3) / sizeof(ULONG);
        pBuffer = Buffer;

        for ( ; registerOffset < endOffset; registerOffset++ ) {
            type1Address.u.bits.Register = registerOffset;
            _outpd((USHORT)PCI_TYPE1_ADDRESS, type1Address.u.AsULONG);
            _outpd((USHORT)PCI_TYPE1_DATA, *pBuffer++);
        }
    } else if ( ucPCIConfigMechanism == 2 ) {
        TYPE2_PCI_CSE       type2CSE;
        TYPE2_PCI_ADDRESS   type2Address;

        type2CSE.u.bits.Key = type2CSE.u.bits.SCE = 0xFF;
        type2CSE.u.bits.Function = (UCHAR)slotNumber.u.bits.FunctionNumber;

        type2Address.u.AsUSHORT = 0;
        type2Address.u.bits.PCIConfigSpace = 0xC;
        type2Address.u.bits.Device = (USHORT)slotNumber.u.bits.DeviceNumber;

        _outp((USHORT)PCI_TYPE2_FORWARD, (UCHAR)BusNumber);

        registerOffset = Offset >> 2;
        endOffset = (registerOffset + Length + 3) >> 2;
        pBuffer = Buffer;

        INTERRUPTS_OFF();

        _outp((USHORT)PCI_TYPE2_CSE, type2CSE.u.AsUCHAR);

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

            _outpd((USHORT)type2Address.u.AsUSHORT, *pBuffer++);
        }

        _outp((USHORT)PCI_TYPE2_CSE, 0);
        _outp((USHORT)PCI_TYPE2_FORWARD, 0);

        INTERRUPTS_ON();
    } else if ( ucPCIConfigMechanism == (UCHAR)~0 ) {
        // No PCI bus
        RETAILMSG(1, (TEXT("HalGetBusDataByOffset: No PCI bus\r\n")));
        return (0);
    } else {
        RETAILMSG(1, (TEXT("HalGetBusDataByOffset: Unknown config mechanism = 0x%2.2X\r\n"), ucPCIConfigMechanism));
        return (0);
    }

    LeaveCriticalSection(&csPCIConfig);

    return (Length);
}

⌨️ 快捷键说明

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