📄 route.c
字号:
//
// 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 + -