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

📄 register.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
字号:
//
// Permedia3 Sample Display Driver
// register.c
//
// Copyright (c) 2000 Microsoft Corporation. All rights reserved.
//
// This module contains code to initialize the card after it has been located
// on the PCI bus to a state where register writes are possible, as well as
// helpers for register writes and reads.

#include "pch.h"  // Precompiled header support.
#include "debug.h"
#include "const.h"
#include "struct.h"
#include "global.h"
#include "register.h"
#include "proto.h"

// This is a cached copy of the base address for the memory region 0. It is
// used whenever a region 0 register is accessed.

volatile ULONG * g_Region0Base;

BOOL
InitializeRegisters()
{
  // InitializeRegisters
  // This function uses only the PCI configuration information stored in the
  // g_Config global to initizlize the card such that general register access
  // is possible.

  // Local variables.

  BOOL FnRetVal = FALSE;  // Return value for this function.
  PHYSICAL_ADDRESS Region0Bus;
  PHYSICAL_ADDRESS Region0Physical;
  ULONG AddressSpace;

  Enter(L"InitializeRegisters");

  // VirtualAlloc enough virtual addresses in order to map the whole memory
  // region 0 into virtual space.

  g_Region0Base = VirtualAlloc(NULL,  // System locates virtual space
                               REGION0_SIZE,
                               MEM_RESERVE,
                               PAGE_NOACCESS);

  if (g_Region0Base != NULL) {

    // Use HalTranslateBusAddress to turn the PCI address into a physical
    // address. Essentially, this is finding out what physical address the
    // processor needs to issue to the PCI bus to get to the given PCI address.

    AddressSpace = 0;  // Memory mapped, not port mapped
    Region0Physical.QuadPart = 0;
    Region0Bus.LowPart = g_Config.PciCommonConfig.u.type0.BaseAddresses[0];
    Region0Bus.HighPart = 0;
    if (HalTranslateBusAddress(PCIBus,
                               g_Config.PciBusNumber,
                               Region0Bus,
                               &AddressSpace,
                               &Region0Physical)) {

      // Now, actually map the physical address to a virtual address. We need
      // to shift the physcial address right because when PAGE_PHYSICAL is
      // specified, VirtualCopy expects the high 32 bits of a 40 bit
      // address. The shift essentially sets those high 8 bits to 0.

      if (VirtualCopy((LPVOID)g_Region0Base,
                      (LPVOID)(Region0Physical.LowPart >> 8),
                      REGION0_SIZE,
                      PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL)) {  

        Message(L"Permedia3 registers sucessfully mapped.\n");

        FnRetVal = TRUE;
      }
      else {
        Error(L"Unable to map physical address to virtual address!\n");
      }
    }
    else {
      Error(L"Unable to translate bus address to physical address!\n");
    }
  }
  else {
    Error(L"Unable to allocate virtual address for memory region 0!\n");
  }

  Exit(L"InitializeRegisters");

  return FnRetVal;
}

void
WriteRegByte(
  ULONG Offset,
  BYTE  Value
  )
{
  // WriteRegByte
  // This function allows us to write into a memory region 0 register by
  // identifying the offset of that register and the value to put there.
  // We do not use the Enter/Exit routines here as this is not really a
  // function.

  *((BYTE *)g_Region0Base + Offset) = Value;
}

void
WriteMaskedRegByte(
  ULONG Offset,
  BYTE  Mask,
  BYTE  Value
  )
{
  // WriteMaskedRegByte
  // This function allows us to write to a register in memory region 0
  // identified by offset. We are also given a mask, which are the only bits
  // we will change. The Enter/Exit routines are not used here as this is not
  // really a function.

  *((BYTE *)g_Region0Base + Offset) = (*((BYTE *)g_Region0Base + Offset) & ~Mask) | (Value & Mask);
}

BYTE
ReadRegByte(
  ULONG Offset
  )
{
  // ReadRegByte
  // This function allows us to read a register in memory region 0 identified
  // by offset. An 8 bit value is returned. The Enter/Exit routines are not
  // used here as this is not really a function.

  return (*((BYTE *)g_Region0Base + Offset));
}

BYTE
ReadMaskedRegByte(
  ULONG Offset,
  BYTE  Mask
  )
{
  // ReadMaskedRegByte
  // This function allows us to read only the bits specified by a given mask
  // from a memory region 0 register specified by offset. An 8 bit value is
  // returned with 0s in all bits maksed off. The Enter/Exit routines are
  // not used here as this is not really a function.

  return (*((BYTE *)g_Region0Base + Offset) & Mask);
}

void
WriteRegUlong(
  ULONG Offset,
  ULONG Value
  )
{
  // WriteRegUlong
  // This function allows us to write into a memory region 0 register by
  // identifying the offset of that register and the value to put there.
  // We do not use the Enter/Exit routines here as this is not really a
  // function.

  *(ULONG *)((BYTE *)g_Region0Base + Offset) = Value;
}

void
WriteMaskedRegUlong(
  ULONG Offset,
  ULONG Mask,
  ULONG Value
  )
{
  // WriteMaskedRegUlong
  // This function allows us to write to a register in memory region 0
  // identified by offset. We are also given a mask, which are the only bits
  // we will change. The Enter/Exit routines are not used here as this is not
  // really a function.

  *(ULONG *)((BYTE *)g_Region0Base + Offset) = (*(ULONG *)((BYTE *)g_Region0Base + Offset) & ~Mask) | (Value & Mask);
}

ULONG
ReadRegUlong(
  ULONG Offset
  )
{
  // ReadRegUlong
  // This function allows us to read a register in memory region 0 identified
  // by offset. A 32 bit value is returned. The Enter/Exit routines are not
  // used here as this is not really a function.

  return (*(ULONG *)((BYTE *)g_Region0Base + Offset));
}

ULONG
ReadMaskedRegUlong(
  ULONG Offset,
  ULONG Mask
  )
{
  // ReadMaskedRegUlong
  // This function allows us to read only the bits specified by a given mask
  // from a memory region 0 register specified by offset. A 32 bit value is
  // returned with 0s in all bits maksed off. The Enter/Exit routines are
  // not used here as this is not really a function.

  return (*(ULONG *)((BYTE *)g_Region0Base + Offset) & Mask);
}

void
WriteRdReg(
  ULONG Index,
  BYTE  Value
  )
{
  // WriteRdReg
  // This function is used to write to one of the indexed RAMDAC registers
  // on the Permedia3. The register's index, and the value to be written is
  // passed. No Enter/Exit semantics for inlined functions.

  WriteRegByte(r_RDIndexLow, (BYTE)(Index & b_RDIndexLow_Index));
  WriteRegByte(r_RDIndexHigh, (BYTE)((Index >> 8) & b_RDIndexHigh_Index));
  WriteRegByte(r_RDIndexedData, Value);
}

void
WriteMaskedRdReg(
  ULONG Index,
  BYTE  Mask,
  BYTE  Value
  )
{
  // WriteMaskedRdReg
  // Write only the specified bits of a indexed RAMDAC register. The index of
  // the register, the value to write and the bits to mask out are specified.
  // No Enter/Exit semantics for an inlined function.

  WriteRegByte(r_RDIndexLow, (BYTE)(Index & b_RDIndexLow_Index));
  WriteRegByte(r_RDIndexHigh, (BYTE)((Index >> 8) & b_RDIndexHigh_Index));
  WriteRegByte(r_RDIndexedData, (BYTE)((ReadRegByte(r_RDIndexedData) & ~Mask) | (Value & Mask)));
}

BYTE
ReadRdReg(
  ULONG Index
  )
{
  // ReadRdReg
  // Read an indexed RAMDAC register. Index is specified, it's value returned.
  // No Enter/Exit semantics for inlined functions.

  WriteRegByte(r_RDIndexLow, (BYTE)(Index & b_RDIndexLow_Index));
  WriteRegByte(r_RDIndexHigh, (BYTE)((Index >> 8) & b_RDIndexHigh_Index));
  return (ReadRegByte(r_RDIndexedData));
}

BYTE
ReadMaskedRdReg(
  ULONG Index,
  BYTE  Mask
  )
{
  // ReadMaskedRdReg
  // This function allows us to read only the bits specified by a given mask
  // from an indexed RAMDAC register specified by index. A 32 bit value is
  // returned with 0s in all bits maksed off. The Enter/Exit routines are
  // not used for inlined functions.

  WriteRegByte(r_RDIndexLow, (BYTE)(Index & b_RDIndexLow_Index));
  WriteRegByte(r_RDIndexHigh, (BYTE)((Index >> 8) & b_RDIndexHigh_Index));
  return (ReadRegByte(r_RDIndexedData) & Mask);
}

void
WriteVgaReg(
  ULONG Index,
  BYTE  Value
  )
{
  // WriteVgaReg
  // This function is used to write to one of the indexed VGA sequencer 
  // registers on the Permedia3. The register's index, and the value to
  // be written is passed. No Enter/Exit semantics for inlined functions.

  WriteRegByte(r_SequencerIndexReg, (BYTE)(Index & b_SequencerIndexReg_Index));
  WriteRegByte(r_SequencerDataReg, Value);
}

void
WriteMaskedVgaReg(
  ULONG Index,
  BYTE  Mask,
  BYTE  Value
  )
{
  // WriteMaskedVgaReg
  // Write only the specified bits of a indexed VGA sequencer register.
  // The index of the register, the value to write and the bits to mask
  // out are specified. No Enter/Exit semantics for an inlined function.

  // Local variables.

  BYTE MaskedValue;

  WriteRegByte(r_SequencerIndexReg, (BYTE)(Index & b_SequencerIndexReg_Index));
  MaskedValue = (BYTE)((ReadRegByte(r_SequencerDataReg) & ~Mask) | (Value & Mask));
  WriteRegByte(r_SequencerIndexReg, (BYTE)(Index & b_SequencerIndexReg_Index));
  WriteRegByte(r_SequencerDataReg, MaskedValue);
}

BYTE
ReadVgaReg(
  ULONG Index
  )
{
  // ReadVgaReg
  // Read an indexed VGA sequencer register. Index is specified, it's
  // value returned. No Enter/Exit semantics for inlined functions.

  WriteRegByte(r_SequencerIndexReg, (BYTE)(Index & b_SequencerIndexReg_Index));
  return (ReadRegByte(r_SequencerDataReg));
}

BYTE
ReadMaskedVgaReg(
  ULONG Index,
  BYTE  Mask
  )
{
  // ReadMaskedVgaReg
  // This function allows us to read only the bits specified by a given mask
  // from an indexed VGA sequencer register specified by index. A 32 bit
  // value is returned with 0s in all bits maksed off. The Enter/Exit routines
  // are not used for inlined functions.

  WriteRegByte(r_SequencerIndexReg, (BYTE)(Index & b_SequencerIndexReg_Index));
  return (ReadRegByte(r_SequencerDataReg) & Mask);
}

void
WaitForInputFIFO(
  ULONG Writes
  )
{
  // WaitForInputFIFO
  // This method polls the InFIFOSpace register to insure that there is
  // sufficent space for a given number of register writes. Relies on the
  // fact that the g_Region0Base pointer is volatile. No Enter/Exit
  // semantics for inlined functions.

  while (ReadRegUlong(r_InFIFOSpace) < Writes);
}

  

⌨️ 快捷键说明

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