📄 init.c
字号:
//
// Permedia3 Sample Display Driver
// init.c
//
// Copyright (c) 2000 Microsoft Corporation. All rights reserved.
//
// This module contains all of the code necessary to locate the Permedia3
// device on the PCI bus, read it's configuration, and initialize it. This
// code also initializes the global structures with the memory mapped IO
// addresses, video memory information and other configuration information
// from the PCI bus and the card's ROM.
#include "pch.h" // Precompiled header support.
#include "const.h"
#include "debug.h"
#include "struct.h"
#include "proto.h"
#include "global.h"
#include "register.h"
// This global contains all of the configuration information about the
// device.
PERM3_CONFIG g_Config;
// Internal prototypes. These functions are not exposed outside this module.
static BOOL
PciFindDevice(
USHORT VendorId,
USHORT DeviceId,
PULONG BusNumber,
PPCI_SLOT_NUMBER SlotNumber,
PPCI_COMMON_CONFIG CommonConfig
);
static BOOL
InitializeRom();
static BOOL
CopyRomTable(
LPVOID RomImage
);
static BOOL
GenerateRomTable();
static void
ResetChip();
static void
ProcessInitializationTable();
BOOL
InitializeHardware()
{
// InitializeHardware
// This top-level function coordinates locating the device, initializing it,
// reading it's configuration data, and making sure the driver data
// structures are initialize correcrtly. We expect to only be called ONCE.
// Local variables.
BOOL FnRetVal = FALSE; // Return value for this function.
Enter(L"InitializeHardware");
// Scour the PCI bus for our device.
if (PciFindDevice(VENDOR_ID,
DEVICE_ID,
&g_Config.PciBusNumber,
&g_Config.PciSlotNumber,
&g_Config.PciCommonConfig)) {
if (InitializeRegisters()) {
if (InitializeRom()) {
if (InitializeVideoMem()) {
if (InitializeModes()) {
if (InitializeDMA()) {
if (InitializeInterrupts()) {
FnRetVal = TRUE;
Message(L"Permedia3 hardware initialized.\n");
}
else {
Error(L"Unable to initialize interrupts!\n");
}
}
else {
Error(L"Unable to initialize Permedia3 DMA support!\n");
}
}
else {
Error(L"Unable to initialize Permedia3 display mode handler!\n");
}
}
else {
Error(L"Unable to initialize Permedia3 video memory!\n");
}
}
else {
Error(L"Unable to initialize Permedia3 register access!\n");
}
}
else {
Error(L"Unable to read Permedia3 ROM initialization table!\n");
}
}
else {
Error(L"Unable to locate Permedia3 device on PCI bus!\n");
}
Exit(L"InitializeHardware");
return FnRetVal;
}
BOOL
PciFindDevice(
USHORT VendorId,
USHORT DeviceId,
PULONG BusNumber,
PPCI_SLOT_NUMBER SlotNumber,
PPCI_COMMON_CONFIG CommonConfig
)
{
// PciFindDevice
// Examines all functions on all devices on all buses on the PCI subsystem
// for the matching vendor and device ID. Returns the bus number, slot
// number, and the configuration if the device is found (function returns
// TRUE.)
// Local variables.
BOOL FnRetVal = FALSE; // Return value for this function.
ULONG Bus, Device, Function, ConfigLength;
// Check parameters.
// VendorId and DeviceId can be anything.
AssertWritePtr(BusNumber, sizeof(ULONG));
AssertWritePtr(SlotNumber, sizeof(PCI_SLOT_NUMBER));
AssertWritePtr(CommonConfig, sizeof(PCI_COMMON_CONFIG));
Enter(L"PciFindDevice");
// Iterate over all buses, devices and functions.
for (Bus = 0; Bus < PCI_MAX_BUS; Bus++) {
for (Device = 0; Device < PCI_MAX_DEVICES; Device++) {
SlotNumber->u.bits.DeviceNumber = Device;
for (Function = 0; Function < PCI_MAX_FUNCTION; Function++) {
SlotNumber->u.bits.FunctionNumber = Function;
// Check out this bus/device/function. It might be the one we are
// looking for.
ConfigLength = HalGetBusData(PCIConfiguration,
Bus,
SlotNumber->u.AsULONG,
CommonConfig,
sizeof(PCI_COMMON_CONFIG));
if (ConfigLength == 0 ||
CommonConfig->VendorID == 0xFFFF) {
// !TODO! Nothing here. Unfortuantly, I don't know if we can stop at
// this point.
break;
}
if (VendorId == CommonConfig->VendorID &&
DeviceId == CommonConfig->DeviceID) {
// This is it. Save the bus number and set our loop variables to
// break us out of the loops.
*BusNumber = Bus;
Function = PCI_MAX_FUNCTION;
Device = PCI_MAX_DEVICES;
Bus = PCI_MAX_BUS;
FnRetVal = TRUE;
Message(L"Located Permedia3 on PCI bus.\n");
}
}
}
}
Exit(L"PciFindDevice");
return FnRetVal;
}
BOOL
InitializeRom()
{
// InitializeRom
// This function reads the initialization sequence stored in the Permedia3's
// Rom BIOS. This is a table of register writes that will be used later (once
// we have initialized access to the Memory Region 0) to initialize the chip.
// Local variables.
BOOL FnRetVal = FALSE; // Return value for this function.
PHYSICAL_ADDRESS RomBus;
PHYSICAL_ADDRESS RomPhysical;
ULONG AddressSpace;
PVOID RomImage = NULL;
Enter(L"InitializeRom");
if (g_Config.PciCommonConfig.u.type0.ROMBaseAddress != 0) {
// Try to enable access to the rom.
g_Config.PciCommonConfig.u.type0.ROMBaseAddress |= b_CFGRomAddr_AccessDecodeEnable;
if (HalSetBusDataByOffset(PCIConfiguration,
g_Config.PciBusNumber,
g_Config.PciSlotNumber.u.AsULONG,
&g_Config.PciCommonConfig.u.type0.ROMBaseAddress,
r_CFGRomAddr,
sizeof(ULONG)) != sizeof(ULONG)) {
// We can continue if we fail: we will genertae an initialization table
// ourselves.
Message(L"Unable to send bus configuration to Permedia3!\n");
}
// See if we have successfully enabled rom access.
if (g_Config.PciCommonConfig.u.type0.ROMBaseAddress & b_CFGRomAddr_AccessDecodeEnable) {
// VirtualAlloc enough virtual addresses in order to map the whole rom
// region into virtual space.
RomImage = VirtualAlloc(NULL, // System locates virtual space
ROM_SIZE,
MEM_RESERVE,
PAGE_NOACCESS);
if (RomImage != 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
RomPhysical.QuadPart = 0;
RomBus.LowPart = g_Config.PciCommonConfig.u.type0.ROMBaseAddress;
RomBus.HighPart = 0;
if (HalTranslateBusAddress(PCIBus,
g_Config.PciBusNumber,
RomBus,
&AddressSpace,
&RomPhysical)) {
// 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(RomImage,
(LPVOID)(RomPhysical.LowPart >> 8),
ROM_SIZE,
PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL)) {
Message(L"ROM initialization table sucessfully mapped.\n");
// Locate and copy the initialization table into g_Config.
FnRetVal = CopyRomTable(RomImage);
// Free the ROM mapping. We do not need it any longer. (Don't care
// if this call fails.)
VirtualFree(RomImage,
0, // Must == 0 because we specify MEM_RELEASE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -