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

📄 pci.c

📁 Windows CE 6.0 BSP for VOIPAC Board (PXA270) Version 2b.
💻 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 + -