Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

576 lines
14 KiB

/*
* Copyright (c) 1995 FirePower Systems, Inc.
* DO NOT DISTRIBUTE without permission
*
* $RCSfile: pxisabus.c $
* $Revision: 1.21 $
* $Date: 1996/05/14 02:34:36 $
* $Locker: $
*/
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
pxisabus.c
Abstract:
Author:
Environment:
Revision History:
--*/
#include "fpdebug.h"
#include "halp.h"
#include "phsystem.h"
ULONG
HalpGetIsaInterruptVector(
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN ULONG BusInterruptLevel,
IN ULONG BusInterruptVector,
OUT PKIRQL Irql,
OUT PKAFFINITY Affinity
);
NTSTATUS
HalpAdjustIsaResourceList (
IN PVOID BusHandler,
IN PVOID RootHandler,
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
);
#define TBS " "
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,HalpGetIsaInterruptVector)
#pragma alloc_text(PAGE,HalpAdjustIsaResourceList)
#pragma alloc_text(PAGE,HalpAdjustResourceListLimits)
#endif
/*++
Routine Description: ULONG HalpGetIsaInterruptVector()
This function returns the system interrupt vector and IRQL level
corresponding to the specified bus interrupt level and/or vector. The
system interrupt vector and IRQL are suitable for use in a subsequent call
to KeInitializeInterrupt.
Arguments:
BusHandle - Per bus specific structure
Irql - Returns the system request priority.
Affinity - Returns the system wide irq affinity.
Return Value:
Returns the system interrupt vector corresponding to the specified device.
--*/
ULONG
HalpGetIsaInterruptVector(
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN ULONG BusInterruptLevel,
IN ULONG BusInterruptVector,
OUT PKIRQL Irql,
OUT PKAFFINITY Affinity
)
{
//
// irq2 shows up on irq9
//
HDBG(DBG_INTERRUPTS,
HalpDebugPrint("HalpGetIsaInterruptVector: 0x%x, 0x%x, 0x%x 0x%x \n",
BusInterruptLevel, BusInterruptVector, *Irql, *Affinity ););
if (BusInterruptLevel == 2) {
BusInterruptLevel = 9;
BusInterruptVector = 9;
}
//
// Hack Hack:
//
// NOTE: NOTE:
// The Ethernet driver reports itself as an ISA device but with a
// PCI interrupt so need to fixup the interrupt if it looks correct
// for the pci bus vector:
if (BusInterruptLevel > 15) {
return 0;
}
//
// There are 4 cases to check here:
// A) One of the entries ( BusIntLvl || BusIntVec ) is zero,
// B) Both of the entries are the same value,
// C) One of the entries is == 5 ( Which is the SPL for external
// devices on PowerPC NT )
// D) none of the above
//
switch(BusInterruptLevel) {
case 0:
if (BusInterruptVector) {
BusInterruptLevel = BusInterruptVector;
} else {
// they're both zero, so hope this is the profile int.
}
break;
case 5:
//
// In this case, BusInterruptLevel is probably indicating the
// system SPL for external ints, so assume the BusInterruptVector
// contains the real interrupt info
//
break;
default:
//
// Since BusInterruptLevel is nonzero and not equal to 5, then see
// if BusInterruptVector is zero or equal to 5. If it's neither,
// then print out the level and vector values and spin since this
// is a combination I've never seen before.
//
if( BusInterruptVector ) {
ULONG tmp;
if( BusInterruptVector == (BusInterruptLevel + 0x20) ) {
BusInterruptVector = BusInterruptLevel;
HDBG(DBG_INTERRUPTS,
HalpDebugPrint("HalpGetISAInt: BusIntVec(0x%x) = BusIntLvl(0x%x) +0x20 \n",
BusInterruptVector, BusInterruptLevel ));
HDBG(DBG_INTERRUPTS,
HalpDebugPrint("HalpGetISAInt: ****** Please Fix Driver to use BusInterruptVector correctly \n"));
// NOTE("Hack for audio driver to work")
}
if(( BusInterruptLevel != BusInterruptVector)
&& ( BusInterruptVector != 5 )) {
HalpDebugPrint("Wierd BusIntVec & BusIntLvl (spin now)\n");
HalpDebugPrint(" BusIntLvl = 0x%x, BusIntVec = 0x%x\n",
BusInterruptLevel, BusInterruptVector );
for (;;) {
}
}
//
// Here, BusInterruptVector is known to be non-zero, = 5 or
// BusLevel. So, assume it's the 5 choice and swap it with
// level.
//
HDBG(DBG_INTERRUPTS,
HalpDebugPrint("\t\tSwap BusIntLvl & BusIntVec %x, %x...\n",
BusInterruptLevel, BusInterruptVector););
tmp = BusInterruptLevel;
BusInterruptLevel = BusInterruptVector;
BusInterruptVector = tmp;
//
// Now, BusInterruptVector has the interesting value so the
// HalpGetSystemInterrupt can correctly key on
// BusInterruptVector.
//
} else {
//
// since BusInterruptVector is zero
//
BusInterruptVector = BusInterruptLevel;
}
}
//
// Get parent's translation from here..
//
return BusHandler->ParentHandler->GetInterruptVector (
BusHandler->ParentHandler,
RootHandler,
BusInterruptLevel,
BusInterruptVector,
Irql,
Affinity
);
}
NTSTATUS
HalpAdjustIsaResourceList (
IN PVOID BusHandler,
IN PVOID RootHandler,
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
)
{
UCHAR Irq[15], c;
for (c=0; c < 15; c++) {
Irq[c] = IRQ_VALID;
}
HDBG(DBG_INTERNAL, HalpDebugPrint("HalpAdjustIsaResourceList: called\n"));
return HalpAdjustResourceListLimits (
BusHandler, RootHandler, pResourceList,
0, 0xffffff, // Bus supports up to memory 0xFFFFFF
0, 0, // No special range for prefetch
FALSE,
0, 0xffff, // Bus supports up to I/O port 0xFFFF
Irq, 15, // Bus supports up to 15 IRQs
0, 7 // Bus supports up to Dma channel 7
);
}
NTSTATUS
HalpAdjustResourceListLimits (
IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList,
IN ULONG MinimumMemoryAddress,
IN ULONG MaximumMemoryAddress,
IN ULONG MinimumPrefetchMemoryAddress,
IN ULONG MaximumPrefetchMemoryAddress,
IN BOOLEAN LimitedIOSupport,
IN ULONG MinimumPortAddress,
IN ULONG MaximumPortAddress,
IN PUCHAR IrqTable,
IN ULONG IrqTableSize,
IN ULONG MinimumDmaChannel,
IN ULONG MaximumDmaChannel
)
{
PIO_RESOURCE_REQUIREMENTS_LIST InCompleteList, OutCompleteList;
PIO_RESOURCE_LIST InResourceList, OutResourceList;
PIO_RESOURCE_DESCRIPTOR InDesc, OutDesc, HeadOutDesc;
BOOLEAN GotPFRange, FirstDescBuilt;
ULONG len, alt, cnt, i;
UCHAR LastIrqState, NewIrqState;
ULONG PFAddress, icnt, pcnt;
HDBG(DBG_INTERNAL,
HalpDebugPrint("HalpAdjustResourceListLimits: BusHandler=0x%08x, ResList=0x%08x\n",
BusHandler, pResourceList););
InCompleteList = *pResourceList;
len = InCompleteList->ListSize;
PFAddress =
MinimumPrefetchMemoryAddress || MaximumPrefetchMemoryAddress ? 1 : 0;
icnt = 0;
pcnt = 0;
//
// Worste case, add an extra interrupt descriptor for every different
// IRQ range present
//
LastIrqState = 0;
for (i=0; i < IrqTableSize; i++) {
if (IrqTable[i] != LastIrqState) {
icnt += 1;
LastIrqState = IrqTable[i];
}
}
//
// If LimitiedIOSupport, then the supported I/O ranges are
// limited to 256bytes on every 1K aligned boundry within the
// range specified. Worste case add an extra N descriptors for
// every I/O range passed.
//
if (LimitedIOSupport && MaximumPortAddress > MinimumPortAddress) {
pcnt = (MaximumPortAddress - MinimumPortAddress) / 1024;
}
//
// Scan input list - verify revision #'s, and increase len varible
// by amount output list may increase.
//
i = 0;
InResourceList = InCompleteList->List;
for (alt=0; alt < InCompleteList->AlternativeLists; alt++) {
if (InResourceList->Version != 1 || InResourceList->Revision < 1) {
HDBG(DBG_INTERRUPTS,
HalpDebugPrint("%sVersion is not 1, or revision is < 1.\n",
TBS););
return STATUS_INVALID_PARAMETER;
}
InDesc = InResourceList->Descriptors;
for (cnt = InResourceList->Count; cnt; cnt--) {
switch (InDesc->Type) {
case CmResourceTypePort: i += pcnt; break;
case CmResourceTypeInterrupt: i += icnt; break;
case CmResourceTypeMemory: i += PFAddress; break;
case CmResourceTypeDma: break;
default:
HDBG(DBG_INTERRUPTS,
HalpDebugPrint("%sINVALID PARAM ..InDesc->Type: 0x%x\n",
TBS,InDesc->Type););
return STATUS_INVALID_PARAMETER;
}
// Next descriptor
InDesc++;
}
// Next Resource List
InResourceList = (PIO_RESOURCE_LIST) InDesc;
}
len += i * sizeof (IO_RESOURCE_DESCRIPTOR);
//
// Allocate output list
//
OutCompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST)
ExAllocatePool (PagedPool, len);
if (!OutCompleteList) {
HDBG(DBG_INTERRUPTS,
HalpDebugPrint("%sOutCompleteList is null ( No memory? ) \n",TBS););
return STATUS_NO_MEMORY;
}
//
// Walk each ResourceList and build output structure
//
InResourceList = InCompleteList->List;
*OutCompleteList = *InCompleteList;
OutResourceList = OutCompleteList->List;
for (alt=0; alt < InCompleteList->AlternativeLists; alt++) {
OutResourceList->Version = 1;
OutResourceList->Revision = 1;
InDesc = InResourceList->Descriptors;
OutDesc = OutResourceList->Descriptors;
HeadOutDesc = OutDesc;
for (cnt = InResourceList->Count; cnt; cnt--) {
//
// Copy descriptor
//
*OutDesc = *InDesc;
//
// Limit desctiptor to be with the buses supported ranges
//
switch (OutDesc->Type) {
case CmResourceTypePort:
if (OutDesc->u.Port.MinimumAddress.QuadPart < MinimumPortAddress) {
OutDesc->u.Port.MinimumAddress.QuadPart = MinimumPortAddress;
}
if (OutDesc->u.Port.MaximumAddress.QuadPart > MaximumPortAddress) {
OutDesc->u.Port.MaximumAddress.QuadPart = MaximumPortAddress;
}
if (!LimitedIOSupport) {
break;
}
// In the case of LimitiedIOSupport the caller will only
// pass in 1K aligned values
FirstDescBuilt = FALSE;
for (i = MinimumPortAddress; i < MaximumPortAddress; i += 1024) {
if (InDesc->u.Port.MinimumAddress.QuadPart < i) {
OutDesc->u.Port.MinimumAddress.QuadPart = i;
}
if (InDesc->u.Port.MaximumAddress.QuadPart > i + 256) {
OutDesc->u.Port.MaximumAddress.QuadPart = i + 256;
}
if (OutDesc->u.Port.MinimumAddress.QuadPart <=
OutDesc->u.Port.MaximumAddress.QuadPart) {
//
// Valid I/O descriptor build, start another one.
//
FirstDescBuilt = TRUE;
OutDesc++;
*OutDesc = *InDesc;
OutDesc->Option |= IO_RESOURCE_ALTERNATIVE;
}
}
if (FirstDescBuilt) {
OutDesc--;
}
break;
case CmResourceTypeInterrupt:
HDBG(DBG_INTERRUPTS,
HalpDebugPrint("HalpAdjustResourceListLimits: new CmResourceTypeInterrupt \n"););
//
// Build a list of interrupt descriptors which are
// a subset of the IrqTable and the current descriptor
// passed in on the input list.
//
FirstDescBuilt = FALSE;
LastIrqState = 0;
for (i=0; i < IrqTableSize; i++) {
NewIrqState = IrqTable[i];
while (LastIrqState != NewIrqState) {
if (LastIrqState) {
OutDesc++; // done with last desc
LastIrqState = 0; // new state
continue;
}
//
// Start a new descriptor
//
*OutDesc = *InDesc;
OutDesc->u.Interrupt.MinimumVector = i;
if (NewIrqState & IRQ_PREFERRED) {
OutDesc->Option |= IO_RESOURCE_PREFERRED;
}
if (FirstDescBuilt) {
OutDesc->Option |= IO_RESOURCE_ALTERNATIVE;
}
LastIrqState = NewIrqState;
FirstDescBuilt = TRUE;
}
OutDesc->u.Interrupt.MaximumVector = i;
}
if (!LastIrqState) {
if (!FirstDescBuilt) {
OutDesc->u.Interrupt.MinimumVector =
IrqTableSize + 1;
} else {
OutDesc--;
}
}
break;
case CmResourceTypeMemory:
if (PFAddress && (OutDesc->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) ) {
//
// There's a Prefetch range & this resource supports
// Prefetching. Build two descriptors - one for the
// supported Prefetch range as preferred, and the other
// normal memory range.
//
OutDesc->Option |= IO_RESOURCE_PREFERRED;
if (OutDesc->u.Memory.MinimumAddress.QuadPart < MinimumPrefetchMemoryAddress) {
OutDesc->u.Memory.MinimumAddress.QuadPart = MinimumPrefetchMemoryAddress;
}
if (OutDesc->u.Memory.MaximumAddress.QuadPart > MaximumPrefetchMemoryAddress) {
OutDesc->u.Memory.MaximumAddress.QuadPart = MaximumPrefetchMemoryAddress;
}
GotPFRange = FALSE;
if (OutDesc->u.Memory.MaximumAddress.QuadPart >=
OutDesc->u.Memory.MinimumAddress.QuadPart) {
//
// got a valid descriptor in the Prefetch range, keep it,
//
OutDesc++;
GotPFRange = TRUE;
}
*OutDesc = *InDesc;
if (GotPFRange) {
// next descriptor is an alternative
OutDesc->Option |= IO_RESOURCE_ALTERNATIVE;
}
}
//
// Fill in memory descriptor for range
//
if (OutDesc->u.Memory.MinimumAddress.QuadPart < MinimumMemoryAddress) {
OutDesc->u.Memory.MinimumAddress.QuadPart = MinimumMemoryAddress;
}
if (OutDesc->u.Memory.MaximumAddress.QuadPart > MaximumMemoryAddress) {
OutDesc->u.Memory.MaximumAddress.QuadPart = MaximumMemoryAddress;
}
break;
case CmResourceTypeDma:
if (OutDesc->u.Dma.MinimumChannel < MinimumDmaChannel) {
OutDesc->u.Dma.MinimumChannel = MinimumDmaChannel;
}
if (OutDesc->u.Dma.MaximumChannel > MaximumDmaChannel) {
OutDesc->u.Dma.MaximumChannel = MaximumDmaChannel;
}
break;
#if DBG
default:
DbgPrint ("HalAdjustResourceList: Unkown resource type\n");
break;
#endif
}
//
// Next descriptor
//
InDesc++;
OutDesc++;
}
OutResourceList->Count = OutDesc - HeadOutDesc;
//
// Next Resource List
//
InResourceList = (PIO_RESOURCE_LIST) InDesc;
OutResourceList = (PIO_RESOURCE_LIST) OutDesc;
}
//
// Free input list, and return output list
//
ExFreePool (InCompleteList);
OutCompleteList->ListSize =
(ULONG) ((PUCHAR) OutResourceList - (PUCHAR) OutCompleteList);
*pResourceList = OutCompleteList;
return STATUS_SUCCESS;
}