Leaked source code of windows server 2003
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.
 
 
 
 
 
 

437 lines
12 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
ixisabus.c
Abstract:
Author:
Environment:
Revision History:
--*/
#include "halp.h"
BOOLEAN
HalpTranslateIsaBusAddress (
IN PVOID BusHandler,
IN PVOID RootHandler,
IN PHYSICAL_ADDRESS BusAddress,
IN OUT PULONG AddressSpace,
OUT PPHYSICAL_ADDRESS TranslatedAddress
);
BOOLEAN
HalpTranslateEisaBusAddress (
IN PVOID BusHandler,
IN PVOID RootHandler,
IN PHYSICAL_ADDRESS BusAddress,
IN OUT PULONG AddressSpace,
OUT PPHYSICAL_ADDRESS TranslatedAddress
);
BOOLEAN
HalpTranslateSystemBusAddress (
IN PVOID BusHandler,
IN PVOID RootHandler,
IN PHYSICAL_ADDRESS BusAddress,
IN OUT PULONG AddressSpace,
OUT PPHYSICAL_ADDRESS TranslatedAddress
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,HalIrqTranslateResourceRequirementsIsa)
#pragma alloc_text(PAGE,HalIrqTranslateResourcesIsa)
#endif
NTSTATUS
HalIrqTranslateResourceRequirementsIsa(
IN PVOID Context,
IN PIO_RESOURCE_DESCRIPTOR Source,
IN PDEVICE_OBJECT PhysicalDeviceObject,
OUT PULONG TargetCount,
OUT PIO_RESOURCE_DESCRIPTOR *Target
)
/*++
Routine Description:
This function is basically a wrapper for
HalIrqTranslateResourceRequirementsRoot that understands
the weirdnesses of the ISA bus.
Arguments:
Return Value:
status
--*/
{
PIO_RESOURCE_DESCRIPTOR modSource, target, rootTarget;
NTSTATUS status;
BOOLEAN picSlaveDeleted = FALSE;
BOOLEAN deleteResource;
ULONG sourceCount = 0;
ULONG targetCount = 0;
ULONG resource;
ULONG rootCount;
ULONG invalidIrq;
PAGED_CODE();
ASSERT(Source->Type == CmResourceTypeInterrupt);
modSource = ExAllocatePoolWithTag(
NonPagedPool,
//
// we will have at most nine ranges when we are done
//
sizeof(IO_RESOURCE_DESCRIPTOR) * 9,
HAL_POOL_TAG
);
if (!modSource) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(modSource, sizeof(IO_RESOURCE_DESCRIPTOR) * 9);
//
// Is the PIC_SLAVE_IRQ in this resource?
//
if ((Source->u.Interrupt.MinimumVector <= PIC_SLAVE_IRQ) &&
(Source->u.Interrupt.MaximumVector >= PIC_SLAVE_IRQ)) {
//
// Clip the maximum
//
if (Source->u.Interrupt.MinimumVector < PIC_SLAVE_IRQ) {
modSource[sourceCount] = *Source;
modSource[sourceCount].u.Interrupt.MinimumVector =
Source->u.Interrupt.MinimumVector;
modSource[sourceCount].u.Interrupt.MaximumVector =
PIC_SLAVE_IRQ - 1;
sourceCount++;
}
//
// Clip the minimum
//
if (Source->u.Interrupt.MaximumVector > PIC_SLAVE_IRQ) {
modSource[sourceCount] = *Source;
modSource[sourceCount].u.Interrupt.MaximumVector =
Source->u.Interrupt.MaximumVector;
modSource[sourceCount].u.Interrupt.MinimumVector =
PIC_SLAVE_IRQ + 1;
sourceCount++;
}
//
// In ISA machines, the PIC_SLAVE_IRQ is rerouted
// to PIC_SLAVE_REDIRECT. So find out if PIC_SLAVE_REDIRECT
// is within this list. If it isn't we need to add it.
//
if (!((Source->u.Interrupt.MinimumVector <= PIC_SLAVE_REDIRECT) &&
(Source->u.Interrupt.MaximumVector >= PIC_SLAVE_REDIRECT))) {
modSource[sourceCount] = *Source;
modSource[sourceCount].u.Interrupt.MinimumVector=PIC_SLAVE_REDIRECT;
modSource[sourceCount].u.Interrupt.MaximumVector=PIC_SLAVE_REDIRECT;
sourceCount++;
}
} else {
*modSource = *Source;
sourceCount = 1;
}
//
// Now that the PIC_SLAVE_IRQ has been handled, we have
// to take into account IRQs that may have been steered
// away to the PCI bus.
//
// N.B. The algorithm used below may produce resources
// with minimums greater than maximums. Those will
// be stripped out later.
//
for (invalidIrq = 0; invalidIrq < PIC_VECTORS; invalidIrq++) {
//
// Look through all the resources, possibly removing
// this IRQ from them.
//
for (resource = 0; resource < sourceCount; resource++) {
deleteResource = FALSE;
if (HalpPciIrqMask & (1 << invalidIrq)) {
//
// This IRQ belongs to the PCI bus.
//
if (!((HalpBusType == MACHINE_TYPE_EISA) &&
((modSource[resource].Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)))) {
//
// And this resource is not an EISA-style,
// level-triggered interrupt.
//
// N.B. Only the system BIOS truely knows
// whether an IRQ on a PCI bus can be
// shared with an IRQ on an ISA bus.
// This code assumes that, in the case
// that the BIOS set an EISA device to
// the same interrupt as a PCI device,
// the machine can actually function.
//
deleteResource = TRUE;
}
}
if (deleteResource) {
if (modSource[resource].u.Interrupt.MinimumVector == invalidIrq) {
modSource[resource].u.Interrupt.MinimumVector++;
} else if (modSource[resource].u.Interrupt.MaximumVector == invalidIrq) {
modSource[resource].u.Interrupt.MaximumVector--;
} else if ((modSource[resource].u.Interrupt.MinimumVector < invalidIrq) &&
(modSource[resource].u.Interrupt.MaximumVector > invalidIrq)) {
//
// Copy the current resource into a new resource.
//
modSource[sourceCount] = modSource[resource];
//
// Clip the current resource to a range below invalidIrq.
//
modSource[resource].u.Interrupt.MaximumVector = invalidIrq - 1;
//
// Clip the new resource to a range above invalidIrq.
//
modSource[sourceCount].u.Interrupt.MinimumVector = invalidIrq + 1;
sourceCount++;
}
}
}
}
target = ExAllocatePoolWithTag(PagedPool,
sizeof(IO_RESOURCE_DESCRIPTOR) * sourceCount,
HAL_POOL_TAG
);
if (!target) {
ExFreePool(modSource);
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Now send each of these ranges through
// HalIrqTranslateResourceRequirementsRoot.
//
for (resource = 0; resource < sourceCount; resource++) {
//
// Skip over resources that we have previously
// clobbered (while deleting PCI IRQs.)
//
if (modSource[resource].u.Interrupt.MinimumVector >
modSource[resource].u.Interrupt.MaximumVector) {
continue;
}
status = HalIrqTranslateResourceRequirementsRoot(
Context,
&modSource[resource],
PhysicalDeviceObject,
&rootCount,
&rootTarget
);
if (!NT_SUCCESS(status)) {
ExFreePool(target);
goto HalIrqTranslateResourceRequirementsIsaExit;
}
//
// HalIrqTranslateResourceRequirementsRoot should return
// either one resource or, occasionally, zero.
//
ASSERT(rootCount <= 1);
if (rootCount == 1) {
target[targetCount] = *rootTarget;
targetCount++;
ExFreePool(rootTarget);
}
}
*TargetCount = targetCount;
if (targetCount > 0) {
*Target = target;
} else {
ExFreePool(target);
}
status = STATUS_TRANSLATION_COMPLETE;
HalIrqTranslateResourceRequirementsIsaExit:
ExFreePool(modSource);
return status;
}
NTSTATUS
HalIrqTranslateResourcesIsa(
IN PVOID Context,
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
IN RESOURCE_TRANSLATION_DIRECTION Direction,
IN ULONG AlternativesCount, OPTIONAL
IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
IN PDEVICE_OBJECT PhysicalDeviceObject,
OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
)
/*++
Routine Description:
This function is basically a wrapper for
HalIrqTranslateResourcesRoot that understands
the weirdnesses of the ISA bus.
Arguments:
Return Value:
status
--*/
{
CM_PARTIAL_RESOURCE_DESCRIPTOR modSource;
NTSTATUS status;
BOOLEAN usePicSlave = FALSE;
ULONG i;
modSource = *Source;
if (Direction == TranslateChildToParent) {
if (Source->u.Interrupt.Vector == PIC_SLAVE_IRQ) {
modSource.u.Interrupt.Vector = PIC_SLAVE_REDIRECT;
modSource.u.Interrupt.Level = PIC_SLAVE_REDIRECT;
}
}
status = HalIrqTranslateResourcesRoot(
Context,
&modSource,
Direction,
AlternativesCount,
Alternatives,
PhysicalDeviceObject,
Target);
if (!NT_SUCCESS(status)) {
return status;
}
if (Direction == TranslateParentToChild) {
//
// Because the ISA interrupt controller is
// cascaded, there is one case where there is
// a two-to-one mapping for interrupt sources.
// (On a PC, both 2 and 9 trigger vector 9.)
//
// We need to account for this and deliver the
// right value back to the driver.
//
if (Target->u.Interrupt.Level == PIC_SLAVE_REDIRECT) {
//
// Search the Alternatives list. If it contains
// PIC_SLAVE_IRQ but not PIC_SLAVE_REDIRECT,
// we should return PIC_SLAVE_IRQ.
//
for (i = 0; i < AlternativesCount; i++) {
if ((Alternatives[i].u.Interrupt.MinimumVector >= PIC_SLAVE_REDIRECT) &&
(Alternatives[i].u.Interrupt.MaximumVector <= PIC_SLAVE_REDIRECT)) {
//
// The list contains, PIC_SLAVE_REDIRECT. Stop
// looking.
//
usePicSlave = FALSE;
break;
}
if ((Alternatives[i].u.Interrupt.MinimumVector >= PIC_SLAVE_IRQ) &&
(Alternatives[i].u.Interrupt.MaximumVector <= PIC_SLAVE_IRQ)) {
//
// The list contains, PIC_SLAVE_IRQ. Use it
// unless we find PIC_SLAVE_REDIRECT later.
//
usePicSlave = TRUE;
}
}
if (usePicSlave) {
Target->u.Interrupt.Level = PIC_SLAVE_IRQ;
Target->u.Interrupt.Vector = PIC_SLAVE_IRQ;
}
}
}
return status;
}