pciconfig.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 282 行

C
282
字号
/*++
 
Copyright (c) 1998  Microsoft Corporation
 
Module Name:
 
    pciconfig.c
 
Abstract:
 
    Routines for PCI config cycles on altoona board
 
Author:
 
    John Cooper (johncoop) 98-Jun-18
 
Environment:
 
    Environment
 
Revision History:
 
--*/

#include "windows.h"
#include <bootldr.h>
#include "alt_def.h"
#include "vrc5074.h"
#include "alt_io.h"

ULONG
PCIConfig_Read(
    ULONG BusNumber,
    ULONG Slot,
    ULONG Function,
    ULONG Offset
    )
 
/*++
 
Routine Description:
 
    Routine to perform read of pci config register
 
Arguments:
 
    Slot - supplies slot number of card.
    Offset - supplies offset within config register space
    Value - returns value read
 
Return Value:
 
    returns value read
 
--*/

{
    PVRC5074_CONTROL pVrc5074;
    ULONG InitSaveLo;
    ULONG InitSaveHi;
    ULONG Value;

    //
    // Can only access slots above 11
    //

    if (Slot < 11) {
        return 0xFFFFFFFF;
    }

    //
    // Can't access Vrc5074's config registers via PCI bus
    //

    if ((BusNumber == 0) && (Slot == IDSEL_VRC5074)) {
        return *(PULONG)(KSEG1_BASE + VRC5074_BASE + 0x200 + Offset);
    }

    //
    // Save the value in PCIINIT1 register
    // Program register to do config cycle
    //

    pVrc5074 = (PVRC5074_CONTROL) (VRC5074_BASE + KSEG1_BASE);
    InitSaveLo = pVrc5074->PCIINIT1.Low;
    InitSaveHi = pVrc5074->PCIINIT1.Hi;

    pVrc5074->PCIINIT1.Hi = 0;
    pVrc5074->PCIINIT1.Lo = PCIINIT_TYPE_CONFIG |
                            PCIINIT_ACCESS_32 |
                            ((BusNumber == 0) ? PCIINIT_CONFIGTYPE0 :
                                                PCIINIT_CONFIGTYPE1);

    FLUSH_WRITE_BUFFER;

    //
    // Do config cycle
    //

    if (BusNumber == 0) {
        if ((ULONG)(1 << Slot) >= (ULONG)PCI_CONFIG_SIZE) {

            //
            // If idsel number is above size of PCIINIT1 window, then set
            // bits in the PCIADD field of PCIINIT1 register
            //

            pVrc5074->PCIINIT1.Lo |= (1 << Slot);
            FLUSH_WRITE_BUFFER;
            Value = *(PULONG)(PCI_CONFIG_BASE |
                              KSEG1_BASE |
                              (Function << 8) |
                              (Offset << 0));
        } else {

            //
            // offset of address within pci config space appears directly
            // on pci bus.
            //

            Value = *(PULONG)(PCI_CONFIG_BASE |
                              KSEG1_BASE |
                              (1 << Slot) |
                              (Function << 8) |
                              (Offset << 0));
        }

    } else {

        //
        // offset of address within pci config space appears directly
        // on pci bus.
        //

        Value = *(PULONG)(PCI_CONFIG_BASE |
                          KSEG1_BASE |
                          (BusNumber << 16) |
                          ((Slot-11) << 11) |
                          (Function << 8) |
                          (Offset << 0));
    }

    //
    // Restore PciInit registers
    //

    pVrc5074->PCIINIT1.Lo = InitSaveLo;
    pVrc5074->PCIINIT1.Hi = InitSaveHi;
    FLUSH_WRITE_BUFFER;

    return Value;
}


VOID
PCIConfig_Write(
    ULONG BusNumber,
    ULONG Slot,
    ULONG Function,
    ULONG Offset,
    ULONG Value
    )
 
/*++
 
Routine Description:
 
    Routine to perform read of pci config register
 
Arguments:
 
    Slot - supplies slot number of card.
    Offset - supplies offset within config register space
    BusNumber - supplies BusNumber field for Type 1 config cycles
    Value - supplies value to write
 
Return Value:
 
    None.
 
--*/

{
    PVRC5074_CONTROL pVrc5074;
    ULONG InitSaveLo;
    ULONG InitSaveHi;

    //
    // Can only access slots above 11
    //

    if (Slot < 11) {
        return;
    }

    //
    // Can't access Vrc5074 config registers via PCI bus - will hang machine
    //

    if ((BusNumber == 0) && (Slot == IDSEL_VRC5074)) {
        *(PULONG)(KSEG1_BASE + VRC5074_BASE + 0x200 + Offset) = Value;
        FLUSH_WRITE_BUFFER;
        return;
    }

    pVrc5074 = (PVRC5074_CONTROL) (VRC5074_BASE + KSEG1_BASE);

    //
    // Save the value in PCIINIT1 register
    // Program register to do config cycle
    //

    InitSaveLo = pVrc5074->PCIINIT1.Low;
    InitSaveHi = pVrc5074->PCIINIT1.Hi;

    pVrc5074->PCIINIT1.Hi = 0;
    pVrc5074->PCIINIT1.Lo = PCIINIT_TYPE_CONFIG |
                            PCIINIT_ACCESS_32 |
                            ((BusNumber == 0) ? PCIINIT_CONFIGTYPE0 :
                                                PCIINIT_CONFIGTYPE1);

    FLUSH_WRITE_BUFFER;

    //
    // Do config cycle
    //

    if (BusNumber == 0) {
        if ((ULONG)(1 << Slot) >= (ULONG)PCI_CONFIG_SIZE) {

            //
            // If idsel number is above size of PCIINIT1 window, then set
            // bits in the PCIADD field of PCIINIT1 register
            //

            pVrc5074->PCIINIT1.Lo |= (1 << Slot);
            FLUSH_WRITE_BUFFER;
            *(PULONG)(KSEG1_BASE |
                      PCI_CONFIG_BASE |
                      (Function << 8) |
                      (Offset << 0)) = Value;
        } else {

            //
            // offset of address within pci config space appears directly
            // on pci bus.
            //

            *(PULONG)(KSEG1_BASE |
                      PCI_CONFIG_BASE |
                      (1 << Slot) |
                      (Function << 8) |
                      (Offset << 0)) = Value;
        }

    } else {

        //
        // offset of address within pci config space appears directly
        // on pci bus.
        //

        *(PULONG)(KSEG1_BASE |
                  PCI_CONFIG_BASE |
                  (BusNumber << 16) |
                  ((Slot-11) << 11) |
                  (Function << 8) |
                  (Offset << 0)) = Value;
    }

    FLUSH_WRITE_BUFFER;

    //
    // Restore PciInit registers
    //

    pVrc5074->PCIINIT1.Lo = InitSaveLo;
    pVrc5074->PCIINIT1.Hi = InitSaveHi;
    FLUSH_WRITE_BUFFER;

}

⌨️ 快捷键说明

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