mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
290 lines
7.7 KiB
290 lines
7.7 KiB
/*++
|
|
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
ixpciint.c
|
|
|
|
Abstract:
|
|
|
|
All PCI bus interrupt mapping is in this module, so that a real
|
|
system which doesn't have all the limitations which PC PCI
|
|
systems have can replaced this code easly.
|
|
(bus memory & i/o address mappings can also be fix here)
|
|
|
|
Author:
|
|
|
|
Ken Reneris
|
|
Jim Wooldridge - Ported to PowerPC
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
#include "halp.h"
|
|
#include "pci.h"
|
|
#include "pcip.h"
|
|
#include "ibmppc.h"
|
|
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
|
|
#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
|
|
#endif
|
|
|
|
#define PCI_DISPLAY_CONTROLLER 0x03
|
|
#define PCI_PRE_REV_2 0x0
|
|
#define IsVideoDevice(a) \
|
|
(((a->BaseClass == PCI_DISPLAY_CONTROLLER) && \
|
|
(a->SubClass == 0)) || \
|
|
(((a->BaseClass == PCI_PRE_REV_2) && \
|
|
(a->SubClass == 1))))
|
|
|
|
#define P91_DEVICE_ID 0x9100100E
|
|
extern PHYSICAL_ADDRESS HalpP9CoprocPhysicalAddress; // in pxp91.c
|
|
|
|
ULONG
|
|
HalpGetPCIData (
|
|
IN PBUS_HANDLER BusHandler,
|
|
IN PBUS_HANDLER RootHandler,
|
|
IN PCI_SLOT_NUMBER SlotNumber,
|
|
IN PVOID Buffer,
|
|
IN ULONG Offset,
|
|
IN ULONG Length
|
|
);
|
|
|
|
ULONG
|
|
HalpGetPCIIntOnISABus (
|
|
IN PBUS_HANDLER BusHandler,
|
|
IN PBUS_HANDLER RootHandler,
|
|
IN ULONG BusInterruptLevel,
|
|
IN ULONG BusInterruptVector,
|
|
OUT PKIRQL Irql,
|
|
OUT PKAFFINITY Affinity
|
|
)
|
|
{
|
|
if (BusInterruptLevel < 1) {
|
|
// bogus bus level
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// Current PCI buses just map their IRQs ontop of the ISA space,
|
|
// so foreward this to the isa handler for the isa vector
|
|
// (the isa vector was saved away at either HalSetBusData or
|
|
// IoAssignReosurces time - if someone is trying to connect a
|
|
// PCI interrupt without performing one of those operations first,
|
|
// they are broken).
|
|
//
|
|
|
|
return HalGetInterruptVector (
|
|
Internal, 0,
|
|
BusInterruptLevel,
|
|
BusInterruptVector,
|
|
Irql,
|
|
Affinity
|
|
);
|
|
}
|
|
|
|
|
|
VOID
|
|
HalpPCIPin2ISALine (
|
|
IN PBUS_HANDLER BusHandler,
|
|
IN PBUS_HANDLER RootHandler,
|
|
IN PCI_SLOT_NUMBER SlotNumber,
|
|
IN PPCI_COMMON_CONFIG PciData
|
|
)
|
|
/*++
|
|
|
|
// This function maps the device's InterruptPin to an InterruptLine
|
|
// value.
|
|
//
|
|
// On Sandalfoot and Polo machines PCI interrupts are statically routed
|
|
// via slot number. This routine just returns and the static routing
|
|
// is done in HalpGetIsaFixedPCIIrq
|
|
//
|
|
|
|
--*/
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
HalpPCIISALine2Pin (
|
|
IN PBUS_HANDLER BusHandler,
|
|
IN PBUS_HANDLER RootHandler,
|
|
IN PCI_SLOT_NUMBER SlotNumber,
|
|
IN PPCI_COMMON_CONFIG PciNewData,
|
|
IN PPCI_COMMON_CONFIG PciOldData
|
|
)
|
|
/*++
|
|
|
|
This functions maps the device's InterruptLine to it's
|
|
device specific InterruptPin value.
|
|
|
|
|
|
--*/
|
|
{
|
|
}
|
|
|
|
NTSTATUS
|
|
HalpAdjustPCIResourceList (
|
|
IN PBUS_HANDLER BusHandler,
|
|
IN PBUS_HANDLER RootHandler,
|
|
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
|
|
)
|
|
/*++
|
|
Rewrite the callers requested resource list to fit within
|
|
the supported ranges of this bus
|
|
--*/
|
|
{
|
|
NTSTATUS Status;
|
|
PPCIPBUSDATA BusData;
|
|
PCI_SLOT_NUMBER PciSlot;
|
|
PSUPPORTED_RANGE Interrupt;
|
|
PPCI_COMMON_CONFIG PciData;
|
|
UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
|
|
ULONG cnt;
|
|
|
|
BusData = (PPCIPBUSDATA) BusHandler->BusData;
|
|
PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
|
|
|
|
PciData = (PPCI_COMMON_CONFIG) iBuffer;
|
|
|
|
//
|
|
// Determine PCI device's interrupt restrictions
|
|
//
|
|
|
|
Status = BusData->GetIrqRange(BusHandler, RootHandler, PciSlot, &Interrupt);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
DbgPrint("Bad IRQ range\n");
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Adjust resources
|
|
//
|
|
|
|
Status = HaliAdjustResourceListRange (
|
|
BusHandler->BusAddresses,
|
|
Interrupt,
|
|
pResourceList
|
|
);
|
|
|
|
ExFreePool (Interrupt);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
DbgPrint("Bad HaliAdjustResourceListRange\n");
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// This next part is a major HACK. The Weitek video
|
|
// adapter (which is one of IBM's favorites) needs
|
|
// to have its frame buffer enabled by the HAL so
|
|
// that the HAL can write to the screen. The device
|
|
// driver for this card needs to touch the frame buffer
|
|
// during its initialization phase, which overlaps with
|
|
// the period of time that the HAL is writing to the
|
|
// screen. So, to avoid breaking one or the other,
|
|
// we need to force the device driver to use the
|
|
// same I/O space for the frame buffer that the HAL
|
|
// was using. Unfortunately, this is the only place
|
|
// to do it. -- Jake Oshins 1/2/96
|
|
|
|
HalpGetPCIData(BusHandler,
|
|
RootHandler,
|
|
PciSlot,
|
|
PciData,
|
|
0,
|
|
PCI_COMMON_HDR_LENGTH
|
|
);
|
|
|
|
//
|
|
// We want to do this only for video devices that are
|
|
// already decoding a range of memory.
|
|
//
|
|
if ((IsVideoDevice(PciData)) &&
|
|
(PciData->u.type0.BaseAddresses[0] & 0xfffffffe))
|
|
{
|
|
for (cnt = (*pResourceList)->List->Count; cnt; cnt--) {
|
|
switch ((*pResourceList)->List->Descriptors->Type) {
|
|
case CmResourceTypeInterrupt:
|
|
case CmResourceTypePort:
|
|
case CmResourceTypeDma:
|
|
break;
|
|
|
|
case CmResourceTypeMemory:
|
|
|
|
//
|
|
// Set the bottom of the range to the value in the Base Address Register
|
|
//
|
|
(*pResourceList)->List->Descriptors->u.Memory.MinimumAddress.LowPart =
|
|
PciData->u.type0.BaseAddresses[0];
|
|
|
|
//
|
|
// Set the top of the range to the BAR plus the requested length
|
|
//
|
|
(*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart =
|
|
PciData->u.type0.BaseAddresses[0] +
|
|
(*pResourceList)->List->Descriptors->u.Memory.Length;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// JAKETEMP pull this out when reworking Baby Blue code!!!!
|
|
|
|
// Yet another MAJOR HACK!
|
|
//
|
|
// If this is a Doral/Terlingua, then space on the primary PCI bus is
|
|
// limited. The Baby Blue card, if it is plugged in, will require the
|
|
// entire upper half. Although this is ridiculous, we want to support
|
|
// it. And since all boot devices initialize before video, we have to
|
|
// make sure that nothing has claimed the upper half of the bus'
|
|
// address space. -- Jake Oshins 3/7/96
|
|
|
|
if ((HalpSystemType == IBM_DORAL) && (BusHandler->BusNumber == 0)) {
|
|
for (cnt = (*pResourceList)->List->Count; cnt; cnt--) {
|
|
switch ((*pResourceList)->List->Descriptors->Type) {
|
|
case CmResourceTypeInterrupt:
|
|
case CmResourceTypePort:
|
|
case CmResourceTypeDma:
|
|
break;
|
|
|
|
case CmResourceTypeMemory:
|
|
|
|
//
|
|
// If the requested range maximum is above the first 256MB of
|
|
// memory space, then the requested maximum is 256MB and the
|
|
// minimum is 0. (i.e. Let IoAssignResources place it anywhere
|
|
// in the first 256MB.
|
|
//
|
|
|
|
if ((*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart > 0x0fffffff) {
|
|
(*pResourceList)->List->Descriptors->u.Memory.MinimumAddress.LowPart = 0x0;
|
|
(*pResourceList)->List->Descriptors->u.Memory.MaximumAddress.LowPart = 0x0fffffff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|
|
return Status;
|
|
|
|
}
|
|
|
|
|