/*++
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;
}