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

📄 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 <vr4131.h>

//------------------------------------------------------------------------------

UINT32 OALPCICfgRead(
    UINT32 busId, OAL_PCI_LOCATION pciLoc, UINT32 offset, UINT32 size,
    VOID *pData
) {
    VR4131_PCIU_REGS *pPCIURegs = OALPAtoUA(VR4131_REG_PA_PCIU);
    UINT32 address, value, count = 0;
    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
    ));

    // We support only one bus
    if (busId != 0) goto cleanUp;
    
    // First check region to read
    if ((offset + size) > 256) goto cleanUp;

    // Get configuration address
    if (pciLoc.bus == 0) {
        // type 0 configuration
        address = (1 << (pciLoc.dev + 10))|(pciLoc.fnc << 8);
    } else {
        // type 1 configuration
        address = 1 |(pciLoc.fnc << 8) |(pciLoc.dev << 11) |(pciLoc.bus << 16);
    }

    // First read any unaligned data on start
    if ((offset & 0x03) != 0) {
        OUTREG32(&pPCIURegs->PCICONFA, address + (offset & ~0x03));
        OALStall(10);
        value = INREG32(&pPCIURegs->PCICONFD);
        value >>= (offset & 0x03) << 3;
        while ((offset & 0x03) != 0 && size > 0) {
            *p++ = (UINT8)value;
            value >>= 8;
            offset++;
            size--;
            count++;
        }
    }      
    
    // Then read full DWORDs
    while (size >= 4) {
        OUTREG32(&pPCIURegs->PCICONFA, address + offset);
        OALStall(10);
        value = INREG32(&pPCIURegs->PCICONFD);
        *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) {
        OUTREG32(&pPCIURegs->PCICONFA, address + offset);
        OALStall(10);
        value = INREG32(&pPCIURegs->PCICONFD);
        while (size > 0) {
            *p++ = (UINT8)value;
            value >>= 8;
            size--;
            count++;
        }
    }

cleanUp:
    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
) {
    VR4131_PCIU_REGS *pPCIURegs = OALPAtoUA(VR4131_REG_PA_PCIU);
    UINT32 address, value, count = 0;
    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
    ));

    // We support only one bus
    if (busId != 0) goto cleanUp;
    
    // Check region to read
    if ((offset + size) > 256) goto cleanUp;

    // Get configuration address
    if (pciLoc.bus == 0) {
        // type 0 configuration
        address = (1 << (pciLoc.dev + 10))|(pciLoc.fnc << 8);
    } else {
        // type 1 configuration
        address = 1 |(pciLoc.fnc << 8) |(pciLoc.dev << 11) |(pciLoc.bus << 16);
    }

    // First write any unaligned data on start
    if ((offset & 0x03) != 0) {
        OUTREG32(&pPCIURegs->PCICONFA, address + (offset & ~0x03));
        OALStall(10);
        value = INREG32(&pPCIURegs->PCICONFD);
        while ((offset & 0x03) != 0 && size > 0) {
            value &= ~(0xFF << ((offset & 0x03) << 3));
            value |= (UINT32)(*p++ << ((offset & 0x03) << 3));
            offset++;
            size--;
            count++;
        }
        OUTREG32(&pPCIURegs->PCICONFA, address + ((offset - 1)&~0x03));
        OALStall(10);
        OUTREG32(&pPCIURegs->PCICONFD, value);
        OALStall(10);
    }
    
    // Then write full DWORDs
    while (size >= 4) {
       value =  (UINT32)(*p++);
       value |= (UINT32)(*p++ << 8);
       value |= (UINT32)(*p++ << 16);
       value |= (UINT32)(*p++ << 24);
       OUTREG32(&pPCIURegs->PCICONFA, address + offset);
       OALStall(10);
       OUTREG32(&pPCIURegs->PCICONFD, value);
       OALStall(10);
       offset += 4;
       size -= 4;
       count += 4;
    }
    
    // And remaining data at end    
    if (size > 0) {
        OUTREG32(&pPCIURegs->PCICONFA, address + offset);
        OALStall(10);
        value = INREG32(&pPCIURegs->PCICONFD);
        while (size > 0) {
            value &= ~(0xFF << ((offset & 0x03) << 3));
            value |= (UINT32)(*p++ << ((offset & 0x03) << 3));
            offset++;
            size--;
            count++;
        }
        OUTREG32(&pPCIURegs->PCICONFA, address + ((offset - 1)&~0x03));
        OALStall(10);
        OUTREG32(&pPCIURegs->PCICONFD, value);
    }

cleanUp:
    OALMSG(OAL_PCI&&OAL_FUNC, (L"-OALPCICfgWrite(count = %d)\r\n", count));
    return count;
}

//------------------------------------------------------------------------------

VOID OALPCIPowerOff(UINT32 busId)
{
}

//------------------------------------------------------------------------------

VOID OALPCIPowerOn(UINT32 busId)
{
}

//------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -