📄 config.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.
//
//------------------------------------------------------------------------------
//
// File: config.c
//
#include <windows.h>
#include <ceddk.h>
#include <oal_log.h>
#include <oal_pci.h>
//------------------------------------------------------------------------------
//
// Define: OAL_PCI_LATENCY_TIMER
//
// Defines the value used to set the PCI latency
//
#define OAL_PCI_LATENCY_TIMER 64
//------------------------------------------------------------------------------
//
// Define: OAL_PCI_CACHE_LINE_SIZE
//
// Defines the value used to set the PCI cache line size
//
#define OAL_PCI_CACHE_LINE_SIZE 4
//------------------------------------------------------------------------------
static VOID PCIConfigBus(
UINT32 busId, UINT32 bus, UINT32 *pSubBus, UINT32 *pMem, UINT32 *pIo,
UINT32 count, OAL_PCI_LOCATION *pPciLoc
);
static VOID PCIScanLocation(
UINT32 busId, OAL_PCI_LOCATION pciLoc, UINT32 *pSubBus, UINT32 *pMem,
UINT32 *pIo, UINT32 count, OAL_PCI_LOCATION *aPciLoc
);
static VOID PCIConfigDevice(
UINT32 busId, OAL_PCI_LOCATION pciLoc, UINT32 *pMemBase, UINT32 *pIoBase
);
static VOID PCIConfigBridge(
UINT32 busId, OAL_PCI_LOCATION pciLoc, UINT32 secBus, UINT32 subBus,
UINT32 *pMemBase, UINT32 memSize, UINT32 *pIoBase, UINT32 ioSize
);
//------------------------------------------------------------------------------
//
// Function: OALPCIConfig
//
// This function is intend to be used for PCI bus configuration. It allows
// initialize on PCI bus hiearchy (only bus numbers on bridges are initialized)
// when it is called with count parameter equal zero. When count value is
// minus one function configures all devices. For other values devices
// on position defined by DEVICE_LOCATION structure are configured.
//
// Note: Current implementation doesn't check memory/io window size
//
BOOL OALPCIConfig(
UINT32 busId, UINT32 memBase, UINT32 memSize, UINT32 ioBase,
UINT32 ioSize, UINT32 pciLocCount, OAL_PCI_LOCATION *aPciLoc
) {
UINT32 mem, io, subBus;
OALMSG(OAL_FUNC&&OAL_PCI, (
L"+OALPCIConfig(%d, 0x%08x, 0x%08x, 0x%08x, 0x%08x, %d, 0x%08x)\r\n",
busId, memBase, memSize, ioBase, ioSize, pciLocCount, aPciLoc
));
OALMSG(OAL_INFO, (L"INFO: PCI configuration start\r\n"));
mem = memBase;
io = ioBase;
subBus = 0;
PCIConfigBus(busId, 0, &subBus, &mem, &io, pciLocCount, aPciLoc);
OALMSG(OAL_INFO, (L"INFO: PCI configuration complete\r\n"));
OALMSG(OAL_FUNC&&OAL_PCI, (L"-OALPCIConfig(rc = 1)\r\n"));
return TRUE;
}
//------------------------------------------------------------------------------
//
// Function: CfgPCIBus
//
// Description: Simplified PCI bus configuration
//
static VOID PCIConfigBus(
UINT32 busId, UINT32 bus, UINT32 *pSubBus, UINT32 *pMem, UINT32 *pIo,
UINT32 count, OAL_PCI_LOCATION *aPciLoc
) {
OAL_PCI_LOCATION pciLoc;
UINT32 id;
OALMSG(OAL_PCI&&OAL_FUNC, (
L"+PCIConfigBus(%d, %d, %d, 0x%08x, 0x%08x, %d, 0x%08x)\r\n",
busId, bus, *pSubBus, *pMem, *pIo, count, aPciLoc
));
// Loop over all possible devices
pciLoc.bus = bus;
for (pciLoc.dev = 0; pciLoc.dev < PCI_MAX_DEVICES; pciLoc.dev++) {
// Try read vendor id, if it fails there isn't device at position
pciLoc.fnc = 0;
id = OALPCIGetId(busId, pciLoc);
if (
LOWORD(id) == PCI_INVALID_VENDORID ||
HIWORD(id) == PCI_INVALID_DEVICEID
) continue;
OALMSG(OAL_INFO, (
L"INFO: Bus %d Device %d: VendorId 0x%x DeviceId 0x%x\r\n",
pciLoc.bus, pciLoc.dev, LOWORD(id), HIWORD(id)
));
// Scan this device
PCIScanLocation(busId, pciLoc, pSubBus, pMem, pIo, count, aPciLoc);
}
OALMSG(OAL_PCI&&OAL_FUNC, (
L"-PCIConfigBus(subBus = %d, mem = 0x%X, io = 0x%X)\r\n",
*pSubBus, *pMem, *pIo
));
}
//------------------------------------------------------------------------------
//
// Function: PCIScanLocation
//
static VOID PCIScanLocation(
UINT32 busId, OAL_PCI_LOCATION pciLoc, UINT32 *pSubBus, UINT32 *pMem,
UINT32 *pIo, UINT32 count, OAL_PCI_LOCATION *aPciLoc
) {
UINT8 header;
UINT32 secBus;
UINT32 ix, mem, io;
OALMSG(OAL_PCI&&OAL_FUNC, (
L"+PCIScanLocation(%d, %d/%d/%d, %d, 0x%x, 0x%08x, %d, 0x%x)\r\n",
busId, pciLoc.bus, pciLoc.dev, pciLoc.fnc, *pSubBus, *pMem, *pIo,
count, aPciLoc
));
// Loop over all possible device functions
for (pciLoc.fnc = 0; pciLoc.fnc < PCI_MAX_FUNCTION; pciLoc.fnc++) {
// Read header to find device type
header = OALPCIGetHeaderType(busId, pciLoc);
if (header == 0xFF) break;
// Depending on device type do configuration
switch (header & ~PCI_MULTIFUNCTION) {
case PCI_DEVICE_TYPE:
// Depending on mode configure device
if (count == -1) {
PCIConfigDevice(busId, pciLoc, pMem, pIo);
} else {
for (ix = 0; ix < count; ix++) {
if (
aPciLoc[ix].bus == pciLoc.bus &&
aPciLoc[ix].dev == pciLoc.dev &&
aPciLoc[ix].fnc == pciLoc.fnc
) {
PCIConfigDevice(busId, pciLoc, pMem, pIo);
break;
}
}
}
break;
case PCI_BRIDGE_TYPE:
case PCI_CARDBUS_TYPE:
secBus = ++(*pSubBus);
// Set primary, secondary and subordinate bus numbers
PCIConfigBridge(busId, pciLoc, secBus, 0xFF, pMem, 0, pIo, 0);
// Call config routing recursively
mem = *pMem;
io = *pIo;
PCIConfigBus(
busId, *pSubBus, pSubBus, pMem, pIo, count, aPciLoc
);
// Set bus numbers and configure bridge if device is behind it
PCIConfigBridge(
busId, pciLoc, secBus, *pSubBus, &mem, *pMem - mem,
&io, *pIo - io
);
break;
}
// Break loop if device isn't multifunction
if (pciLoc.fnc == 0 && (header & PCI_MULTIFUNCTION) == 0) break;
}
OALMSG(OAL_PCI&&OAL_FUNC, (
L"-PCIScanLocation(memBase = 0x%08x, ioBase = 0x%08x)\r\n", *pMem, *pIo
));
}
//------------------------------------------------------------------------------
//
// Function: PCIConfigDevice
//
static VOID PCIConfigDevice(
UINT32 busId, OAL_PCI_LOCATION pciLoc, UINT32 *pMemBase, UINT32 *pIoBase
) {
UINT32 offset, address, size, ix;
UINT16 u16;
UINT8 u8;
OALMSG(OAL_PCI&&OAL_FUNC, (
L"+PCIConfigDevice(%d, %d/%d/%d, 0x%08x, 0x%08x\r\n",
busId, pciLoc.bus, pciLoc.dev, pciLoc.fnc, *pMemBase, *pIoBase
));
// Scan all base registers
offset = FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses);
for (ix = 0; ix < PCI_TYPE0_ADDRESSES; ix++) {
// Get required resource type and size
address = 0xFFFFFFFF;
OALPCICfgWrite(busId, pciLoc, offset, sizeof(address), &address);
OALPCICfgRead(busId, pciLoc, offset, sizeof(address), &address);
if ((address & 1) != 0) {
// Check size result
size = ~(address & 0xFFFFFFFC) + 1;
if ((size & (size - 1)) != 0 || size == 0) continue;
// Assign io space
address = (*pIoBase + size - 1) & ~(size - 1);
*pIoBase = address + size;
OALMSG(OAL_INFO, (
L"INFO: PCIConfigDevice: IO BAR[%d] 0x%x Size 0x%x\r\n",
ix, address, size
));
} else {
// Check size result
size = ~(address & 0xFFFFFFF0) + 1;
if ((size & (size - 1)) != 0 || size == 0) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -