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

📄 route.c

📁 威盛 wince5.0 bsp 包 for x86 系统, 支持 VT8601 等北桥
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// 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.
//
// -----------------------------------------------------------------------------
//
//      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.
//  
// -----------------------------------------------------------------------------
#include <windows.h>
#include <oal_intr.h>
#include <nkintr.h>
#include <x86boot.h>
#include <PCIReg.h>
#include "pci.h"

PCI_REG_INFO g_KitlPCIInfo;

// Inline functions
__inline static DWORD
PCIConfig_Read(
    ULONG BusNumber,
    ULONG Device,
    ULONG Function,
    ULONG Offset
    )
{
    ULONG RetVal = FALSE;
    
    PCIReadBusData(BusNumber, Device, Function, &RetVal, Offset, sizeof(RetVal));

    return RetVal;
}


__inline static void
PCIConfig_Write(
    ULONG BusNumber,
    ULONG Device,
    ULONG Function,
    ULONG Offset,
    ULONG Value
    )
{
    PCIWriteBusData(BusNumber, Device, Function, &Value, Offset, sizeof(Value));
}


BOOL
PCIReadBARs(
    PPCI_REG_INFO pInfo
    )
{   
    DWORD NumberOfRegs;
    DWORD Offset;
    DWORD i;
    DWORD BaseAddress;
    DWORD Size;
    DWORD Reg;
    DWORD IoIndex = 0;
    DWORD MemIndex = 0;

    // Determine number of BARs to examine from header type
    switch (pInfo->Cfg.HeaderType & ~PCI_MULTIFUNCTION) {
    case PCI_DEVICE_TYPE:
        NumberOfRegs = PCI_TYPE0_ADDRESSES;
        break;

    case PCI_BRIDGE_TYPE:
        NumberOfRegs = PCI_TYPE1_ADDRESSES;
        break;

    case PCI_CARDBUS_TYPE:
        NumberOfRegs = PCI_TYPE2_ADDRESSES;
        break;

    default:
        return FALSE;
    }
        
    for (i = 0, Offset = 0x10; i < NumberOfRegs; i++, Offset += 4) {
        // Get base address register value
        Reg = pInfo->Cfg.u.type0.BaseAddresses[i];

        // Get size info
        PCIConfig_Write(pInfo->Bus, pInfo->Device, pInfo->Function, Offset, 0xFFFFFFFF);
        BaseAddress = PCIConfig_Read(pInfo->Bus, pInfo->Device, pInfo->Function, Offset);
        PCIConfig_Write(pInfo->Bus, pInfo->Device, pInfo->Function, Offset, Reg);

        // Re-adjust BaseAddress if upper 16-bits are 0 (this happens on some devices that don't follow
        // the PCI spec, like the Intel UHCI controllers)
        if (((BaseAddress & 0xFFFFFFFC) != 0) && ((BaseAddress & 0xFFFF0000) == 0)) {
            BaseAddress |= 0xFFFF0000;
        }
        
        if (Reg & 1) {
            // IO space
            Size = ~(BaseAddress & 0xFFFFFFFC);

            if ((BaseAddress != 0) && (BaseAddress != 0xFFFFFFFF) && (((Size + 1) & Size) == 0)) {
                // BAR has valid format (consecutive high 1's and consecutive low 0's)
                pInfo->IoLen.Reg[IoIndex] = Size + 1;
                pInfo->IoLen.Num++;
                pInfo->IoBase.Reg[IoIndex++] = Reg & 0xFFFFFFFC;
                pInfo->IoBase.Num++;
            } else {
                // BAR invalid => skip to next one
                continue;
            }
        } else {
            // Memory space
            // TODO: don't properly handle the MEM20 case
            Size = ~(BaseAddress & 0xFFFFFFF0);
            
            if ((BaseAddress != 0) && (BaseAddress != 0xFFFFFFFF) && (((Size + 1) & Size) == 0)) {
                // BAR has valid format (consecutive high 1's and consecutive low 0's)
                pInfo->MemLen.Reg[MemIndex] = Size + 1;
                pInfo->MemLen.Num++;
                pInfo->MemBase.Reg[MemIndex++] = Reg & 0xFFFFFFF0;
                pInfo->MemBase.Num++;
            } else {
                // BAR invalid => skip to next one
                continue;
            }
        }

        //
        // check for 64 bit device - BAR is twice as big
        //
        if ((pInfo->Cfg.u.type0.BaseAddresses[i] & 0x7) == 0x4) {
            // 64 bit device - BAR is twice as wide - zero out high part
            Offset += 4;
            i++;
        }
    }

    return TRUE;
}
//----------------------------------------------------------------------------------
// PCI BIOS (Routing Table Support)
#define BIOS_START  0xe0000
#define BIOS_LENGTH 0x20000
#pragma pack(1)
typedef struct {
    BYTE PCIBusNumber;
    BYTE PCIDeviceNumber;// In upper 5bits
    
    BYTE INTA_LinkValue;
    unsigned short INTA_IrqBitMap;
    
    BYTE INTB_LinkValue;
    unsigned short INTB_IrqBitMap;
    
    BYTE INTC_LinkValue;
    unsigned short INTC_IrqBitMap;
    
    BYTE INTD_LinkValue;
    unsigned short INTD_IrqBitMap;

    BYTE SlotNumber;
    BYTE Reserved;
} RoutingOptionTable;

typedef struct {
    DWORD   Signature;
    WORD    Version;
    WORD    Table_Size;
    BYTE    Bus;
    BYTE    DeviceFunc;
    WORD    ExclusiveIrqs;
    DWORD   CompatibleRouter;
    DWORD   MiniportData;
    BYTE    Reseved[11];
    BYTE    Checksum;
} PCI_ROUTING_TABLE;


typedef struct 
{
    ULONG   magic;
    ULONG   phys_bsd_entry;
    UCHAR   vers,prg_lens,crc;
} BIOS32;

typedef struct {
    DWORD RegEax;
    DWORD RegEbx;
    DWORD RegEcx;
    DWORD RegEdx;
    DWORD RegEsi;
    DWORD RegEdi;
} Reg32;
#define MAX_DEVICE 0x20
typedef struct {
    unsigned short BufferSize;
    BYTE * pDataBuffer;
    DWORD DS;
    RoutingOptionTable routingOptionTable[MAX_DEVICE];
} IRQRountingOptionsBuffer;

#pragma pack() 

extern BOOL CallBios32(Reg32 * pReg,PVOID pCallAddr);

BOOL search_pci_bios(PBYTE pBiosAddr,ULONG * pphOffset)
{
    DWORD       p=0;
    BIOS32      *x;
    UCHAR       flag=0;
    UCHAR       crc;
    int         i;

    BIOS32 *master_bios32=NULL;
    DEBUGMSG(1,(L"search_pci_bios start\r\n"));
    while(pphOffset && flag==0 && p<BIOS_LENGTH)
    {
        x=(BIOS32*)(pBiosAddr+p);
        if (x->magic==0x5F32335F)   /* _32_ */
        {
            for(i=0, crc=0; i<(x->prg_lens*16); i++)
            crc+=*(pBiosAddr+p+i);
            if(crc==0)
            {
                flag=1;
                master_bios32=x;
                *pphOffset=master_bios32->phys_bsd_entry-BIOS_START;
                DEBUGMSG(1,(L"CE Ethernet Bootloader found 32Bit BIOS Entry master_bios32=%x bios32_call_offset=%x for CE/PC \n",
                    master_bios32,*pphOffset));
                return TRUE;
            }
        }
        p+=0x10;
    }
    DEBUGMSG(1,(L"search_pci_bios end fails\r\n"));
    return FALSE;
}
#define PCI_FUNCTION_ID 0xB1
#define PCI_BIOS_PRESENT 0x01
#define FIND_PCI_DEVICE 0x02
#define FIND_PCI_CLASS_CODE 0x03
#define GENERATE_SPECIAL_CYCLE 0x06
#define READ_CONFIG_BYTE 0x8
#define READ_CONFIG_WORD 0x9
#define READ_CONFIG_DWORD 0xA
#define WRITE_CONFIG_BYTE 0xB
#define WRITE_CONFIG_WORD 0xC
#define WRITE_CONFIG_DWORD 0xD
#define GET_IRQ_ROUTING_OPTIONS 0xE
#define SET_PCI_IRQ 0xF

PVOID pBiosAddr=NULL;
IRQRountingOptionsBuffer irqRoutingOptionBuffer;
BYTE bIrqLinked [0x10];
WORD wBestPCIIrq=0;

extern DWORD GetDS();
void DumpRoutingOption(IRQRountingOptionsBuffer *pBuffer,WORD wExClusive)
{
    DEBUGMSG(1,(L"DumpRoutingOption with PCI Exclusive Irq Bit (wExClusive)  =%x \r\n",wExClusive));
    if (pBuffer) {
        RoutingOptionTable * pRoute;
        DWORD dwCurPos=0;
        DEBUGMSG(1,(L"DumpRoutingOption BufferSize = %d @ address %x \r\n", pBuffer->BufferSize,pBuffer->pDataBuffer));
        pRoute =(RoutingOptionTable * )(pBuffer->routingOptionTable);
        while (pRoute && dwCurPos + sizeof(RoutingOptionTable)<=pBuffer->BufferSize) {
            DEBUGMSG(1,(L"DumpRouting for Bus=%d ,Device=%d SlotNumber=%d\r\n",
                pRoute->PCIBusNumber,(pRoute->PCIDeviceNumber)>>3,pRoute->SlotNumber));
            DEBUGMSG(1,(L"     INTA_LinkValue=%x,INTA_IrqBitMap=%x\r\n",pRoute->INTA_LinkValue,pRoute->INTA_IrqBitMap));
            DEBUGMSG(1,(L"     INTB_LinkValue=%x,INTB_IrqBitMap=%x\r\n",pRoute->INTB_LinkValue,pRoute->INTB_IrqBitMap));
            DEBUGMSG(1,(L"     INTC_LinkValue=%x,INTC_IrqBitMap=%x\r\n",pRoute->INTC_LinkValue,pRoute->INTC_IrqBitMap));
            DEBUGMSG(1,(L"     INTD_LinkValue=%x,INTC_IrqBitMap=%x\r\n",pRoute->INTD_LinkValue,pRoute->INTD_IrqBitMap));
            dwCurPos +=sizeof(RoutingOptionTable);
            pRoute ++;
        }

    }
}
PBYTE pBiosVirtAddr=NULL;
BOOL search_pci_routing(PCI_ROUTING_TABLE ** pphAddr)
{
    DWORD       p=0;
    PCI_ROUTING_TABLE      *x;
    UCHAR       flag=0;
    UCHAR       crc;
    int         i;

    DEBUGMSG(1,(L"search_pci_routing\r\n"));
    while(pBiosVirtAddr && pphAddr && flag==0 && (ULONG)p<BIOS_LENGTH)
    {
        x=(PCI_ROUTING_TABLE *)(pBiosVirtAddr+p);
        if (x->Signature==*((DWORD *)"$PIR"))
        {
            for(i=0, crc=0; i<x->Table_Size; i++)
                crc+=*(pBiosVirtAddr+p+i);
            if(crc==0)
            {
                flag=1;
                *pphAddr=x;
                DEBUGMSG(1,(L"search_pci_routing found entry =%x  CE/PC \n",*pphAddr));
                return TRUE;
            }
            else
                DEBUGMSG(1,(L"search_pci_routing Entry Checksum Error @%x",x));
        }
        p+=0x10;
    }
    DEBUGMSG(1,(L"search_pci_routing end fails\r\n"));
    return FALSE;
}
BOOL BiosMapIqr(PDEVICE_LOCATION pDevLoc,BYTE bIrq)
{
    Reg32 mReg32;
    BOOL  bRet;
    if (pDevLoc && pBiosAddr) {
        mReg32.RegEax=PCI_FUNCTION_ID*0x100 + SET_PCI_IRQ;
        mReg32.RegEcx=((DWORD)bIrq)*0x100 + (pDevLoc->Pin & 0xff );
        mReg32.RegEbx=

⌨️ 快捷键说明

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