summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halfire/ppc/pxisabus.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/halfire/ppc/pxisabus.c')
-rw-r--r--private/ntos/nthals/halfire/ppc/pxisabus.c576
1 files changed, 576 insertions, 0 deletions
diff --git a/private/ntos/nthals/halfire/ppc/pxisabus.c b/private/ntos/nthals/halfire/ppc/pxisabus.c
new file mode 100644
index 000000000..59c62c743
--- /dev/null
+++ b/private/ntos/nthals/halfire/ppc/pxisabus.c
@@ -0,0 +1,576 @@
+/*
+ * 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;
+}