📄 pci.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: pci.c
//
#include <windows.h>
#include <ceddk.h>
#include <oal.h>
#include <au1.h>
//------------------------------------------------------------------------------
PVOID SC_VirtualAlloc(PVOID pAddress, DWORD size, DWORD type, DWORD protect);
BOOL SC_VirtualFree(PVOID lpAddress, DWORD size, DWORD freeType);
BOOL SC_VirtualCopy(PVOID pvDest, PVOID pvSrc, DWORD size, DWORD protect);
//------------------------------------------------------------------------------
static BOOL PCIAbort()
{
BOOL rc = FALSE;
AU1_PCI_REGS *pPciRegs = OALPAtoUA(AU1_PCI_REGS_PA);
UINT32 value;
value = INREG32(&pPciRegs->CONFIG);
if ((value & PCI_CONFIG_ERRS) != 0) {
OUTREG32(&pPciRegs->CONFIG, value & ~PCI_CONFIG_ERRS);
rc = TRUE;
}
return rc;
}
//------------------------------------------------------------------------------
UINT32 OALPCICfgRead(
UINT32 busId, OAL_PCI_LOCATION pciLoc, UINT32 offset, UINT32 size,
VOID *pData
) {
UINT32 count = 0;
UINT32 base, value, va = 0;
UINT64 address;
UINT8 *p = (UINT8*)pData;
OALMSG(OAL_PCI&&OAL_FUNC, (
L"+OALPCICfgRead(%d, %d/%d/%d, %d, %d, 0x%08x)\r\n", busId,
pciLoc.bus, pciLoc.dev, pciLoc.fnc, offset, size, pData
));
// First check for valid parameters
if (
busId != 0 || pciLoc.bus > 127 || pciLoc.dev > 31 || pciLoc.fnc > 8 ||
offset > 256 || size == 0 || pData == NULL
) goto cleanUp;
// Based on bus number calculate address for config cycle
address = AU1_PCI_CFG_REGS_PA;
if (pciLoc.bus == 0) {
address += (1<<(pciLoc.dev + 11))|(pciLoc.fnc<<8);
} else {
address += (1<<31)|(pciLoc.bus<<16)|(pciLoc.dev<<11)|(pciLoc.fnc<<8);
}
// Physical address must start at page boundary
base = (UINT32)(address & (PAGE_SIZE - 1));
address -= base;
// Get base address for physical memory map (256 bytes only)
va = (UINT32)SC_VirtualAlloc(0, 0x1000, MEM_RESERVE, PAGE_NOACCESS);
if (va == 0) goto cleanUp;
// Ok, create mapping
if (!SC_VirtualCopy(
(VOID*)va, (VOID*)(address >> 8), 0x1000,
PAGE_READWRITE | PAGE_PHYSICAL | PAGE_NOCACHE
)) goto cleanUp;
// We need read from this offset
offset += base;
// First make sure that there isn't pending bus error
PCIAbort();
// First read any unaligned data on start
if ((offset & 0x03) != 0) {
value = INREG32((UINT32*)(va + (offset & ~0x03)));
if (PCIAbort()) value = 0xFFFFFFFF;
value >>= (offset & 0x03) << 3;
while ((offset & 0x03) != 0 && size > 0) {
*p++ = (UINT8)value;
value >>= 8;
offset++;
size--;
count++;
}
}
// Then read full 32-bit words
while (size >= 4) {
value = INREG32((UINT32*)(va + offset));
if (PCIAbort()) value = 0xFFFFFFFF;
*p++ = (UINT8)value;
*p++ = (UINT8)(value >> 8);
*p++ = (UINT8)(value >> 16);
*p++ = (UINT8)(value >> 24);
offset += 4;
size -= 4;
count += 4;
}
// And remaining data at end
if (size > 0) {
value = INREG32((UINT32*)(va + offset));
if (PCIAbort()) value = 0xFFFFFFFF;
while (size > 0) {
*p++ = (UINT8)value;
value >>= 8;
size--;
count++;
}
}
cleanUp:
if (va != 0) SC_VirtualFree((VOID*)va, 0, MEM_RELEASE);
OALMSG(OAL_PCI&&OAL_FUNC, (L"-OALPCICfgRead(count = %d)\r\n", count));
return count;
}
//------------------------------------------------------------------------------
UINT32 OALPCICfgWrite(
UINT32 busId, OAL_PCI_LOCATION pciLoc, UINT32 offset, UINT32 size,
VOID *pData
) {
UINT32 count = 0;
UINT32 base, value, va = 0;
UINT64 address;
UINT8 *p = (UINT8*)pData;
OALMSG(OAL_PCI&&OAL_FUNC, (
L"+OALPCICfgWrite(%d, %d/%d/%d, %d, %d, 0x%08x\r\n", busId,
pciLoc.bus, pciLoc.dev, pciLoc.fnc, offset, size, pData
));
// First check for valid parameters
if (
busId != 0 || pciLoc.bus > 127 || pciLoc.dev > 31 || pciLoc.fnc > 8 ||
offset > 256 || size == 0 || pData == NULL
) goto cleanUp;
// Based on bus number calculate address for config cycle
address = AU1_PCI_CFG_REGS_PA;
if (pciLoc.bus == 0) {
address += (1<<(pciLoc.dev + 11))|(pciLoc.fnc<<8);
} else {
address += (1<<31)|(pciLoc.bus<<16)|(pciLoc.dev<<11)|(pciLoc.fnc<<8);
}
// Physical address must start at page boundary
base = (UINT32)(address & (PAGE_SIZE - 1));
address -= base;
// Get base address for physical memory map (256 bytes only)
va = (UINT32)SC_VirtualAlloc(0, 0x1000, MEM_RESERVE, PAGE_NOACCESS);
if (va == 0) goto cleanUp;
// Ok, create mapping
if (!SC_VirtualCopy(
(VOID*)va, (VOID*)(address >> 8), 0x1000,
PAGE_READWRITE | PAGE_PHYSICAL | PAGE_NOCACHE
)) goto cleanUp;
// We need read from this offset
offset += base;
// First make sure that there isn't pending bus error
PCIAbort();
// First write any unaligned data on start
if ((offset & 0x03) != 0) {
value = INREG32((UINT32*)(va + (offset & ~0x03)));
while ((offset & 0x03) != 0 && size > 0) {
value &= ~(0xFF << ((offset & 0x03) << 3));
value |= (UINT32)(*p++ << ((offset & 0x03) << 3));
offset++;
size--;
count++;
}
OUTREG32((UINT32*)(va + ((offset - 1) & ~0x03)), value);
}
// Then write full 32-bit words
while (size >= 4) {
value = (UINT32)(*p++);
value |= (UINT32)(*p++ << 8);
value |= (UINT32)(*p++ << 16);
value |= (UINT32)(*p++ << 24);
OUTREG32((UINT32*)(va + offset), value);
offset += 4;
size -= 4;
count += 4;
}
// And remaining data at end
if (size > 0) {
value = INREG32((UINT32*)(va + offset));
while (size > 0) {
value &= ~(0xFF << ((offset & 0x03) << 3));
value |= (UINT32)(*p++ << ((offset & 0x03) << 3));
offset++;
size--;
count++;
}
OUTREG32((UINT32*)(va + ((offset - 1) & ~0x03)), value);
}
cleanUp:
OALMSG(OAL_PCI&&OAL_FUNC, (L"-OALPCICfgWrite(count = %d)\r\n", count));
return count;
}
//------------------------------------------------------------------------------
BOOL OALPCITransBusAddress(
UINT32 busNumber, UINT64 busAddress, UINT32 *pAddressSpace,
UINT64 *pSystemAddress
) {
BOOL rc = FALSE;
OALMSG(OAL_PCI&&OAL_FUNC, (
L"+OALPCITranslateBusAddress(%d, 0x%08x%08x, %d)\r\n",
busNumber, (UINT32)(busAddress >> 32), (UINT32)busAddress,
*pAddressSpace
));
if (pAddressSpace == NULL || pSystemAddress == NULL) goto cleanUp;
switch (*pAddressSpace) {
case 0:
*pSystemAddress = AU1_PCI_MEM_REGS_PA + busAddress;
rc = TRUE;
break;
case 1:
*pSystemAddress = AU1_PCI_IO_REGS_PA + busAddress;
*pAddressSpace = 0;
rc = TRUE;
break;
}
cleanUp:
OALMSG(OAL_PCI&&OAL_FUNC, (
L"-OALPCITranslateBusAddress(addressSpace = %d, "
L"systemAddress = 0x%08x%08x, rc = %d)\r\n", *pAddressSpace,
(UINT32)(*pSystemAddress >> 32), (UINT32)*pSystemAddress, rc
));
return rc;
}
//------------------------------------------------------------------------------
VOID OALPCIPowerOff(UINT32 busId)
{
}
//------------------------------------------------------------------------------
VOID OALPCIPowerOn(UINT32 busId)
{
}
//------------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -