NT4/private/ntos/nthals/halfire/ppc/pxpciint.c
2020-09-30 17:12:29 +02:00

399 lines
8.8 KiB
C

/*
* Copyright (c) 1995 FirePower Systems, Inc.
* DO NOT DISTRIBUTE without permission
*
* $RCSfile: pxpciint.c $
* $Revision: 1.26 $
* $Date: 1996/05/15 00:06:27 $
* $Locker: $
*/
/*++
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 "phsystem.h"
#include "pci.h"
#include "pcip.h"
#include "stdio.h"
#include "fpdebug.h"
ULONG PciAllowedInts = 0;
#define PCI_DEVICE_VECTOR 0x10
#define PCI_IO_ADDRESS_SPACE 0x81000000
ULONG HalpGetPciIntVector( PBUS_HANDLER,
PBUS_HANDLER,
ULONG,
ULONG,
PKIRQL,
PKAFFINITY );
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,HalpGetPCIIntOnISABus)
#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
#endif
/*
* HalpGetPciIntVector:
* This routine is a mirror ( but better ) version of HalpGetPCIIntOnISABus
*
*/
ULONG
HalpGetPciIntVector(
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN ULONG BusInterruptLevel,
IN ULONG BusInterruptVector,
OUT PKIRQL Irql,
OUT PKAFFINITY Affinity
)
{
// since we can't see who's asking for an interrupt, must rely upon some
// known data: First, check to see if there is already one specified out
// among the pci devices: ( need to keep in mind some stubborn drivers
// that request several times for a particular interrupt i.e. scsi ).
//
// For now, to deal with a screwed up amd scsi driver, permanently map
// any requests for f ( as well as d which is what firmware sets this
// device to ) to 0x19, corresponding to the bit in our interrupt word.
//
HDBG(DBG_INTERRUPTS,
HalpDebugPrint("HalpGetPciIntVector: %x, %x \n",
BusInterruptLevel, BusInterruptVector ););
#if defined(HALDEBUG_ON)
if (DBGSET(DBG_INTERRUPTS)) {
switch( BusInterruptVector ) {
case 0xd:
case 0xf:
HalpDebugPrint(" BusIntVec set to 0x%x \n",
BusInterruptVector);
break;
case 0xe:
HalpDebugPrint(" BusIntVec set to 0x%x \n",
BusInterruptVector);
break;
default:
HalpDebugPrint(" BusIntVec unchanged: \n");
break;
}
}
#endif
return HalGetInterruptVector (
Internal, 0,
BusInterruptLevel,
BusInterruptVector,
Irql,
Affinity
);
}
ULONG
HalpGetPCIIntOnISABus (
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN ULONG BusInterruptLevel,
IN ULONG BusInterruptVector,
OUT PKIRQL Irql,
OUT PKAFFINITY Affinity
)
{
HDBG(DBG_INTERRUPTS,
HalpDebugPrint("HalpGetPCIIntOnIsaBus: 0x%x, 0x%x, %x, %x, %x, %x \n",
BusHandler,
RootHandler,
BusInterruptLevel,
BusInterruptVector,
*Irql,
*Affinity ););
if (BusInterruptLevel < 1) {
// bogus bus level
return 0;
}
//
// Check that the requested interrupt is valid and return 0
// if the interrupt is not in the allowed set of interrupts.
if (((1 << BusInterruptVector) & PciAllowedInts) == 0) {
return 0;
}
//
//
// For FirePOWER, pci interrupts are not mapped onto the isa bus ( with the
// exception of the amd ethernet drive which will always believe it's isa )
// so for the moment map their "isa" int values so that they're picked up
// correctly by HalpGetSystem...
//
switch( BusInterruptVector ) {
case 0xa:
//
// For now, map this vector back down to ISA level since the
// audio driver is confused, thinking it's on the pci bus.
//
//BusInterruptVector = 0xa - PCI_DEVICE_VECTOR;
HDBG(DBG_INTERRUPTS,
HalpDebugPrint("%sVector is not PCI based vector: 0x%x\n",
" ", BusInterruptVector ););
break;
case 0xd:
case 0xf:
BusInterruptVector = 0xd +0xc ;
HDBG(DBG_INTERRUPTS,
HalpDebugPrint(" BusIntVect set to 0x19 \n"););
break;
case 0xe:
BusInterruptVector = 0xe +0xc;
HDBG(DBG_INTERRUPTS,
HalpDebugPrint(" BusIntVect set to 0x1a \n"););
break;
default:
break;
}
HDBG(DBG_INTERRUPTS,
HalpDebugPrint("%sBusInterruptVector set to: 0x%x \n",
" ", BusInterruptVector););
//BusInterruptVector += PCI_DEVICE_VECTOR;
BusInterruptLevel = BusInterruptVector;
HDBG(DBG_INTERRUPTS,
HalpDebugPrint("%sBusIntVec set to 0x%x \n",
" ", BusInterruptVector););
//
// 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
);
}
/*++
// Routine Description: VOID HalpPCIPin2ISALine ()
//
// 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
HalpPCIPin2ISALine (
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN PCI_SLOT_NUMBER SlotNumber,
IN PPCI_COMMON_CONFIG PciData
)
{
}
/*++
Routine Description: VOID HalpPCIISALine2Pin ()
This functions maps the device's InterruptLine to it's
device specific InterruptPin value.
--*/
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
)
{
}
/*++
Routine Description: VOID HalpPCIISALine2Pin ()
Translate PCI bus address.
Verify the address is within the range of the bus.
Arguments:
Return Value:
STATUS_SUCCESS or error
--*/
NTSTATUS
HalpTranslatePCIBusAddress (
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN PHYSICAL_ADDRESS BusAddress,
IN OUT PULONG AddressSpace,
OUT PPHYSICAL_ADDRESS TranslatedAddress
)
{
BOOLEAN status;
PPCIPBUSDATA BusData;
if (BusAddress.HighPart) {
return FALSE;
}
BusData = (PPCIPBUSDATA) BusHandler->BusData;
switch (*AddressSpace) {
case MEMORY_ADDRESS_SPACE:
//
// verify memory address is within PCI buses memory limits
//
status = BusAddress.LowPart >= BusData->MemoryBase &&
BusAddress.LowPart <= BusData->MemoryLimit;
if (!status) {
status = BusAddress.LowPart >= BusData->PFMemoryBase &&
BusAddress.LowPart <= BusData->PFMemoryLimit;
}
break;
//
// Everyone should be assumed IO space if not otherwise requested
//
default:
case IO_ADDRESS_SPACE:
//
// verify memory address is within PCI buses io limits
//
status = BusAddress.LowPart >= BusData->IOBase &&
BusAddress.LowPart <= BusData->IOLimit;
break;
case SYSTEM_ADDRESS_SPACE:
// #pragma NOTE("SYSTEM_ADDRESS_SPACE, verify?")
status = BusAddress.LowPart < BusData->IOBase &&
BusAddress.LowPart >= 0;
break;
}
if (!status) {
return FALSE;
}
//
// Valid address for this bus - foreward it to the parent bus
//
return BusHandler->ParentHandler->TranslateBusAddress (
BusHandler->ParentHandler,
RootHandler,
BusAddress,
AddressSpace,
TranslatedAddress
);
}
/*++
Routine Description: NTSTATUS HalpAdjustPCIResourceList ()
Rewrite the callers requested resource list to fit within
the supported ranges of this bus
--*/
NTSTATUS
HalpAdjustPCIResourceList (
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
)
{
NTSTATUS Status;
PPCIPBUSDATA BusData;
PCI_SLOT_NUMBER PciSlot;
UCHAR IrqTable[255];
PFPHAL_BUSNODE FpNode;
FpNode = (PFPHAL_BUSNODE) BusHandler->BusData;
// BusData = (PPCIPBUSDATA) BusHandler->BusData;
BusData = (PPCIPBUSDATA) &(FpNode->Bus);
PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber);
//
// Determine PCI device's interrupt restrictions
//
// ======= Here's where thePCI interrupts are determined and set as a
// result of the call to HalpAdjustResourceListLimits
RtlZeroMemory(IrqTable, sizeof (IrqTable));
Status = BusData->GetIrqTable(BusHandler, RootHandler, PciSlot, IrqTable);
if (!NT_SUCCESS(Status)) {
return Status;
}
//
// Adjust resources
//
return HalpAdjustResourceListLimits (
BusHandler, RootHandler, pResourceList,
BusData->MemoryBase, BusData->MemoryLimit,
BusData->PFMemoryBase, BusData->PFMemoryLimit,
BusData->LimitedIO,
BusData->IOBase, BusData->IOLimit,
IrqTable, 0xff,
0, 0xffff // dma
);
}