?? pcicfg.cpp
字號:
//
// 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.
//
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <cardserv.h>
#include <cardapi.h>
#include <tuple.h>
#include <devload.h>
#include <PCIbus.h>
#include <debug.h>
//
// Function prototypes
//
static BOOL ConfigRsrc(
PPCI_DEV_INFO pInfo,
PPCI_RSRC pMemHead,
PPCI_RSRC pIoHead,
DWORD *pMemSize,
DWORD *pIoSize
);
static BOOL ConfigSize(
PPCI_DEV_INFO pInfo
);
static BOOL ConfigInit(
PPCI_DEV_INFO pInfo
);
__inline static DWORD
PCIConfig_Read(
ULONG BusNumber,
ULONG Device,
ULONG Function,
ULONG Offset
);
__inline static void
PCIConfig_Write(
ULONG BusNumber,
ULONG Device,
ULONG Function,
ULONG Offset,
ULONG Value,
ULONG Size = sizeof(DWORD)
);
//
// DeviceConfig
//
EXTERN_C DWORD GenericConfig(
DWORD Command,
PPCI_DEV_INFO pInfo,
PPCI_RSRC pRsrc1,
PPCI_RSRC pRsrc2,
DWORD *pMemSize,
DWORD *pIoSize
)
{
DEBUGMSG(1, (L"ATAPI:PCIConfig!DeviceConfig+(%d)\r\n", Command));
switch (Command) {
case PCIBUS_CONFIG_RSRC:
if (ConfigRsrc(pInfo, pRsrc1, pRsrc2, pMemSize, pIoSize)) {
return ERROR_SUCCESS;
} else {
return ERROR_GEN_FAILURE;
}
case PCIBUS_CONFIG_SET:
return ERROR_NOT_SUPPORTED;
case PCIBUS_CONFIG_SIZE:
if (ConfigSize(pInfo)) {
return ERROR_SUCCESS;
} else {
return ERROR_GEN_FAILURE;
}
case PCIBUS_CONFIG_INIT:
if (ConfigInit(pInfo)) {
return ERROR_SUCCESS;
} else {
return ERROR_GEN_FAILURE;
}
default:
break;
}
DEBUGMSG(1, (L"ATAPI:PCIConfig!DeviceConfig-: ERROR: Command %d not recognized\r\n", Command));
return ERROR_BAD_COMMAND;
}
// Inline functions
__inline static DWORD
PCIConfig_Read(
ULONG BusNumber,
ULONG Device,
ULONG Function,
ULONG Offset
)
{
ULONG RetVal = FALSE;
PCI_SLOT_NUMBER SlotNumber;
SlotNumber.u.AsULONG = 0;
SlotNumber.u.bits.DeviceNumber = Device;
SlotNumber.u.bits.FunctionNumber = Function;
HalGetBusDataByOffset(PCIConfiguration, BusNumber, SlotNumber.u.AsULONG, &RetVal, Offset, sizeof(RetVal));
return RetVal;
}
// Inline functions
__inline static BYTE
PCIConfig_ReadByte(
ULONG BusNumber,
ULONG Device,
ULONG Function,
ULONG Offset
)
{
BYTE RetVal = FALSE;
PCI_SLOT_NUMBER SlotNumber;
SlotNumber.u.AsULONG = 0;
SlotNumber.u.bits.DeviceNumber = Device;
SlotNumber.u.bits.FunctionNumber = Function;
HalGetBusDataByOffset(PCIConfiguration, BusNumber, SlotNumber.u.AsULONG, &RetVal, Offset, sizeof(RetVal));
return RetVal;
}
__inline static void
PCIConfig_Write(
ULONG BusNumber,
ULONG Device,
ULONG Function,
ULONG Offset,
ULONG Value,
ULONG Size
)
{
PCI_SLOT_NUMBER SlotNumber;
SlotNumber.u.AsULONG = 0;
SlotNumber.u.bits.DeviceNumber = Device;
SlotNumber.u.bits.FunctionNumber = Function;
HalSetBusDataByOffset(PCIConfiguration, BusNumber, SlotNumber.u.AsULONG, &Value, Offset, Size);
}
__inline static void
InsertRsrc(
PPCI_RSRC Ptr,
PPCI_RSRC Rsrc
)
{
Rsrc->Next = Ptr;
Rsrc->Prev = Ptr->Prev;
Ptr->Prev->Next = Rsrc;
Ptr->Prev = Rsrc;
}
__inline static void
RemoveRsrc(
PPCI_RSRC Rsrc
)
{
Rsrc->Prev->Next = Rsrc->Next;
Rsrc->Next->Prev = Rsrc->Prev;
}
void
PCIRsrc_Add(
PPCI_RSRC Head,
PPCI_RSRC Rsrc
)
{
PPCI_RSRC Ptr;
// Find place to insert Rsrc. Sort first on Placed then Size.
for (Ptr = Head->Next; Ptr != Head; Ptr = Ptr->Next) {
if (Rsrc->Placed) {
if (!Ptr->Placed) break;
if (Rsrc->Size > Ptr->Size) break;
} else {
if (Ptr->Placed) continue;
if (Rsrc->Size > Ptr->Size) break;
}
}
// Insert Rsrc node
InsertRsrc(Ptr, Rsrc);
}
PPCI_RSRC
PCIRsrc_New(
DWORD Bus,
DWORD Device,
DWORD Function,
DWORD Offset,
DWORD Base,
DWORD Size,
BOOL Bridge,
DWORD SecBus,
BOOL Placed,
PPCI_CFG_INFO ConfigInfo
)
{
PPCI_RSRC Rsrc;
Rsrc = (PPCI_RSRC)LocalAlloc(0, sizeof(PCI_RSRC));
if (!Rsrc) return NULL;
Rsrc->Bus = Bus;
Rsrc->Device = Device;
Rsrc->Function = Function;
Rsrc->Offset = Offset;
Rsrc->Base = Base;
Rsrc->Size = Size;
Rsrc->Bridge = Bridge;
Rsrc->SecBus = SecBus;
Rsrc->Placed = Placed;
Rsrc->ConfigInfo = ConfigInfo;
Rsrc->Next = Rsrc;
Rsrc->Prev = Rsrc;
return Rsrc;
}
//
// ConfigRsrc
//
static BOOL ConfigRsrc(
PPCI_DEV_INFO pInfo,
PPCI_RSRC pMemHead,
PPCI_RSRC pIoHead,
DWORD *pMemSize,
DWORD *pIoSize
)
{
DWORD NumberOfRegs;
ULONG Offset;
ULONG i;
ULONG BaseAddress;
ULONG Size;
ULONG Type;
DWORD Reg;
BOOL SizeFound;
DWORD IoIndex = 0;
DWORD MemIndex = 0;
DWORD Bus = pInfo->Bus;
DWORD Device = pInfo->Device;
DWORD Function = pInfo->Function;
PPCI_COMMON_CONFIG pCfg = pInfo->Cfg;
DEBUGMSG(ZONE_PCI | ZONE_INIT, (L"ATAPI:PCIConfig!ConfigRsrc+(Bus %d, Device %d, Function %d)\r\n",
Bus, Device, Function));
// Determine number of BARs to examine from header type
switch (pCfg->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 = pCfg->u.type0.BaseAddresses[i];
Type = Reg & PCI_ADDRESS_IO_SPACE;
// Probe hardware for size
PCIConfig_Write(Bus,Device,Function,Offset,0xFFFFFFFF);
BaseAddress = PCIConfig_Read(Bus,Device,Function,Offset);
PCIConfig_Write(Bus, Device, Function, Offset, Reg);
if (Type) {
// IO space
// Re-adjust BaseAddress if upper 16-bits are 0 (allowable in PCI 2.2 spec)
if (((BaseAddress & PCI_ADDRESS_IO_ADDRESS_MASK) != 0) && ((BaseAddress & 0xFFFF0000) == 0)) {
BaseAddress |= 0xFFFF0000;
}
Size = ~(BaseAddress & PCI_ADDRESS_IO_ADDRESS_MASK);
Reg &= PCI_ADDRESS_IO_ADDRESS_MASK;
} else {
// Memory space
if ((Reg & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_20BIT) {
// PCI 2.2 spec no longer supports this type of memory addressing
DEBUGMSG(ZONE_ERROR, (L"ATAPI:PCIConfig!ConfigRsrc: 20-bit addressing not supported\r\n"));
return FALSE;
}
// Re-adjust BaseAddress if upper 16-bits are 0 (allowed by PCI 2.2 spec)
if (((BaseAddress & PCI_ADDRESS_MEMORY_ADDRESS_MASK) != 0) && ((BaseAddress & 0xFFFF0000) == 0)) {
BaseAddress |= 0xFFFF0000;
}
Size = ~(BaseAddress & PCI_ADDRESS_MEMORY_ADDRESS_MASK);
Reg &= PCI_ADDRESS_MEMORY_ADDRESS_MASK;
}
// Check that the register has a valid format; it should have consecutive high 1's and consecutive low 0's
SizeFound = (BaseAddress != 0) && (BaseAddress != 0xFFFFFFFF) && (((Size + 1) & Size) == 0);
Size +=1;
if (SizeFound) {
PPCI_RSRC Rsrc = PCIRsrc_New(Bus, Device, Function, Offset, Reg, Size, FALSE, 0, FALSE, pInfo->ConfigInfo);
if (!Rsrc) {
DEBUGMSG(ZONE_PCI | ZONE_ERROR, (L"ATAPI:PCIConfig!ConfigRsrc: Failed local alloc of Rsrc\r\n"));
return FALSE;
}
if (Type == PCI_ADDRESS_IO_SPACE) {
*pIoSize += Size;
PCIRsrc_Add(pIoHead, Rsrc);
} else {
*pMemSize += Size;
PCIRsrc_Add(pMemHead, Rsrc);
}
DEBUGMSG(ZONE_PCI | ZONE_INIT, (L"ATAPI:PCIConfig!ConfigRsrc: BAR(%d/%d/%d): Offset 0x%x, Type %s, Size 0x%X\r\n",
Bus, Device, Function, Offset, (Type == PCI_ADDRESS_IO_SPACE) ? TEXT("I/O") : TEXT("Memory"), Size));
} else {
// Some devices have invalid BARs before valid ones (even though the spec says you can't). Skip invalid BARs.
continue;
}
// check for 64 bit device (memory only)
if ((Type == PCI_ADDRESS_MEMORY_SPACE) && ((Reg & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)) {
// 64 bit device - BAR is twice as wide - zero out high part
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -