[HAL]
authorJérôme Gardou <jerome.gardou@reactos.org>
Thu, 17 Jun 2010 00:20:20 +0000 (00:20 +0000)
committerJérôme Gardou <jerome.gardou@reactos.org>
Thu, 17 Jun 2010 00:20:20 +0000 (00:20 +0000)
  - yet another sync fun

svn path=/branches/reactos-yarotows/; revision=47791

hal/halx86/generic/legacy/bussupp.c [new file with mode: 0644]
hal/halx86/generic/memory.c [new file with mode: 0644]

diff --git a/hal/halx86/generic/legacy/bussupp.c b/hal/halx86/generic/legacy/bussupp.c
new file mode 100644 (file)
index 0000000..6faa60f
--- /dev/null
@@ -0,0 +1,1511 @@
+/*
+ * PROJECT:         ReactOS HAL
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            hal/halx86/generic/legacy/bussupp.c
+ * PURPOSE:         HAL Legacy Bus Support Code
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES *******************************************************************/
+
+#include <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ********************************************************************/
+
+extern KSPIN_LOCK HalpPCIConfigLock;
+ULONG HalpPciIrqMask;
+
+/* PRIVATE FUNCTIONS **********************************************************/
+
+PBUS_HANDLER
+NTAPI
+HalpAllocateBusHandler(IN INTERFACE_TYPE InterfaceType,
+                       IN BUS_DATA_TYPE BusDataType,
+                       IN ULONG BusNumber,
+                       IN INTERFACE_TYPE ParentBusInterfaceType,
+                       IN ULONG ParentBusNumber,
+                       IN ULONG BusSpecificData)
+{
+    PBUS_HANDLER Bus;
+    
+    /* Register the bus handler */
+    HalRegisterBusHandler(InterfaceType,
+                          BusDataType,
+                          BusNumber,
+                          ParentBusInterfaceType,
+                          ParentBusNumber,
+                          BusSpecificData,
+                          NULL,
+                          &Bus);
+    if (!Bus) return NULL;
+    
+    /* Check for a valid interface */
+    if (InterfaceType != InterfaceTypeUndefined)
+    {
+        /* Allocate address ranges and zero them out */
+        Bus->BusAddresses = ExAllocatePoolWithTag(NonPagedPool,
+                                                  sizeof(SUPPORTED_RANGES),
+                                                  ' laH');
+        RtlZeroMemory(Bus->BusAddresses, sizeof(SUPPORTED_RANGES));
+        
+        /* Build the data structure */
+        Bus->BusAddresses->Version = HAL_SUPPORTED_RANGE_VERSION;
+        Bus->BusAddresses->Dma.Limit = 7;
+        Bus->BusAddresses->Memory.Limit = 0xFFFFFFFF;
+        Bus->BusAddresses->IO.Limit = 0xFFFF;
+        Bus->BusAddresses->IO.SystemAddressSpace = 1;
+        Bus->BusAddresses->PrefetchMemory.Base = 1;
+    }
+    
+    /* Return the bus address */
+    return Bus;
+}
+
+VOID
+NTAPI
+HalpRegisterInternalBusHandlers(VOID)
+{
+    PBUS_HANDLER Bus;
+    
+    /* Only do processor 1 */
+    if (KeGetCurrentPrcb()->Number) return;
+    
+    /* Register root support */
+    HalpInitBusHandler();
+    
+    /* Allocate the system bus */
+    Bus = HalpAllocateBusHandler(Internal,
+                                 ConfigurationSpaceUndefined,
+                                 0,
+                                 InterfaceTypeUndefined,
+                                 0,
+                                 0);
+    if (Bus)
+    {
+        /* Set it up */
+        Bus->GetInterruptVector = HalpGetSystemInterruptVector;
+        Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;        
+    }
+    
+    /* Allocate the CMOS bus */
+    Bus = HalpAllocateBusHandler(InterfaceTypeUndefined,
+                                 Cmos,
+                                 0,
+                                 InterfaceTypeUndefined,
+                                 0,
+                                 0);
+    if (Bus)
+    {
+        /* Set it up */
+        Bus->GetBusData = HalpcGetCmosData;
+        Bus->SetBusData = HalpcSetCmosData;
+    }
+    
+    /* Allocate the CMOS bus */
+    Bus = HalpAllocateBusHandler(InterfaceTypeUndefined,
+                                 Cmos,
+                                 1,
+                                 InterfaceTypeUndefined,
+                                 0,
+                                 0);
+    if (Bus)
+    {
+        /* Set it up */
+        Bus->GetBusData = HalpcGetCmosData;
+        Bus->SetBusData = HalpcSetCmosData;
+    }
+
+    /* Allocate ISA bus */
+    Bus = HalpAllocateBusHandler(Isa,
+                                 ConfigurationSpaceUndefined,
+                                 0,
+                                 Internal,
+                                 0,
+                                 0);
+    if (Bus)
+    {
+        /* Set it up */
+        Bus->GetBusData = HalpNoBusData;
+        Bus->BusAddresses->Memory.Limit = 0xFFFFFF;
+        Bus->TranslateBusAddress = HalpTranslateIsaBusAddress;
+    }
+
+    /* No support for EISA or MCA */
+    ASSERT(HalpBusType == MACHINE_TYPE_ISA);
+}
+
+#ifndef _MINIHAL_
+NTSTATUS
+NTAPI
+HalpMarkChipsetDecode(BOOLEAN OverrideEnable)
+{
+    NTSTATUS Status;
+    UNICODE_STRING KeyString;
+    ULONG Data = OverrideEnable;
+    HANDLE KeyHandle, Handle;
+    
+    /* Open CCS key */
+    RtlInitUnicodeString(&KeyString,
+                         L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
+    Status = HalpOpenRegistryKey(&Handle, 0, &KeyString, KEY_ALL_ACCESS, FALSE);
+    if (NT_SUCCESS(Status))
+    {
+        /* Open PNP Bios key */
+        RtlInitUnicodeString(&KeyString, L"Control\\Biosinfo\\PNPBios");
+        Status = HalpOpenRegistryKey(&KeyHandle,
+                                     Handle,
+                                     &KeyString,
+                                     KEY_ALL_ACCESS,
+                                     TRUE);
+        
+        /* Close root key */
+        ZwClose(Handle);
+        
+        /* Check if PNP BIOS key exists */
+        if (NT_SUCCESS(Status))
+        {
+            /* Set the override value */
+            RtlInitUnicodeString(&KeyString, L"FullDecodeChipsetOverride");           
+            Status = ZwSetValueKey(KeyHandle,
+                                   &KeyString,
+                                   0,
+                                   REG_DWORD,
+                                   &Data,
+                                   sizeof(Data));
+            
+            /* Close subkey */
+            ZwClose(KeyHandle);
+        }
+    }
+    
+    /* Return status */
+    return Status;
+}
+
+PBUS_HANDLER
+NTAPI
+HalpAllocateAndInitPciBusHandler(IN ULONG PciType,
+                                 IN ULONG BusNo,
+                                 IN BOOLEAN TestAllocation)
+{
+    PBUS_HANDLER Bus;
+    PPCIPBUSDATA BusData;
+    
+    /* Allocate the bus handler */
+    Bus = HalpAllocateBusHandler(PCIBus,
+                                 PCIConfiguration,
+                                 BusNo,
+                                 Internal,
+                                 0,
+                                 sizeof(PCIPBUSDATA));
+    
+    /* Set it up */
+    Bus->GetBusData = (PGETSETBUSDATA)HalpGetPCIData;
+    Bus->SetBusData = (PGETSETBUSDATA)HalpSetPCIData;
+    Bus->GetInterruptVector = (PGETINTERRUPTVECTOR)HalpGetPCIIntOnISABus;
+    Bus->AdjustResourceList = (PADJUSTRESOURCELIST)HalpAdjustPCIResourceList;
+    Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES)HalpAssignPCISlotResources;
+    Bus->BusAddresses->Dma.Limit = 0;
+    
+    /* Get our custom bus data */
+    BusData = (PPCIPBUSDATA)Bus->BusData;
+    
+    /* Setup custom bus data */
+    BusData->CommonData.Tag = PCI_DATA_TAG;
+    BusData->CommonData.Version = PCI_DATA_VERSION;
+    BusData->CommonData.ReadConfig = (PciReadWriteConfig)HalpReadPCIConfig;
+    BusData->CommonData.WriteConfig = (PciReadWriteConfig)HalpWritePCIConfig;
+    BusData->CommonData.Pin2Line = (PciPin2Line)HalpPCIPin2ISALine;
+    BusData->CommonData.Line2Pin = (PciLine2Pin)HalpPCIISALine2Pin;
+    BusData->MaxDevice = PCI_MAX_DEVICES;
+    BusData->GetIrqRange = (PciIrqRange)HalpGetISAFixedPCIIrq;
+    
+    /* Initialize the bitmap */
+    RtlInitializeBitMap(&BusData->DeviceConfigured, BusData->ConfiguredBits, 256);
+    
+    /* Check the type of PCI bus */
+    switch (PciType)
+    {
+        /* Type 1 PCI Bus */
+        case 1:
+            
+            /* Copy the Type 1 handler data */
+            RtlCopyMemory(&PCIConfigHandler,
+                          &PCIConfigHandlerType1,
+                          sizeof(PCIConfigHandler));
+            
+            /* Set correct I/O Ports */
+            BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT;
+            BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
+            break;
+            
+        /* Type 2 PCI Bus */
+        case 2:
+            
+            /* Copy the Type 1 handler data */
+            RtlCopyMemory(&PCIConfigHandler,
+                          &PCIConfigHandlerType2,
+                          sizeof (PCIConfigHandler));
+            
+            /* Set correct I/O Ports */
+            BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
+            BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
+            BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
+            
+            /* Only 16 devices supported, not 32 */
+            BusData->MaxDevice = 16;
+            break;
+            
+        default:
+            
+            /* Invalid type */
+            DbgPrint("HAL: Unnkown PCI type\n");
+    }
+
+    /* Return the bus handler */
+    return Bus;
+}
+
+BOOLEAN
+NTAPI
+HalpIsValidPCIDevice(IN PBUS_HANDLER BusHandler,
+                     IN PCI_SLOT_NUMBER Slot)
+{
+    UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
+    PPCI_COMMON_CONFIG PciHeader = (PVOID)DataBuffer;
+    ULONG i;
+    ULONG_PTR Address;
+    
+    /* Read the PCI header */
+    HalpReadPCIConfig(BusHandler, Slot, PciHeader, 0, PCI_COMMON_HDR_LENGTH);
+    
+    /* Make sure it's a valid device */
+    if ((PciHeader->VendorID == PCI_INVALID_VENDORID) ||
+        (PCI_CONFIGURATION_TYPE(PciHeader) != PCI_DEVICE_TYPE))
+    {
+        /* Bail out */
+        return FALSE;
+    }
+    
+    /* Make sure interrupt numbers make sense */
+    if (((PciHeader->u.type0.InterruptPin) &&
+         (PciHeader->u.type0.InterruptPin > 4)) ||
+        (PciHeader->u.type0.InterruptLine & 0x70))
+    {
+        /* Bail out */
+        return FALSE;
+    }
+    
+    /* Now scan PCI BARs */
+    for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+    {
+        /* Check what kind of address it is */
+        Address = PciHeader->u.type0.BaseAddresses[i];
+        if (Address & PCI_ADDRESS_IO_SPACE)
+        {
+            /* Highest I/O port is 65535 */
+            if (Address > 0xFFFF) return FALSE;
+        }
+        else
+        {
+            /* MMIO should be higher than 0x80000 */
+            if ((Address > 0xF) && (Address < 0x80000)) return FALSE;
+        }
+        
+        /* Is this a 64-bit address? */
+        if (!(Address & PCI_ADDRESS_IO_SPACE) &&
+            ((Address & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
+        {
+            /* Check the next-next entry, since this one 64-bits wide */
+            i++;
+        }
+    }
+
+    /* Header, interrupt and address data all make sense */
+    return TRUE;
+}
+
+static BOOLEAN WarningsGiven[5];
+
+NTSTATUS
+NTAPI
+HalpGetChipHacks(IN USHORT VendorId,
+                 IN USHORT DeviceId,
+                 IN UCHAR RevisionId,
+                 IN PULONG HackFlags)
+{
+    UNICODE_STRING KeyName, ValueName;
+    NTSTATUS Status;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE KeyHandle;
+    WCHAR Buffer[32];
+    KEY_VALUE_PARTIAL_INFORMATION PartialInfo;
+    ULONG ResultLength;
+    
+    /* Setup the object attributes for the key */
+    RtlInitUnicodeString(&KeyName,
+                         L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\"
+                         L"Control\\HAL");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &KeyName,
+                               OBJ_CASE_INSENSITIVE,
+                               NULL,
+                               NULL);
+    
+    /* Open the key */
+    Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
+    if (!NT_SUCCESS(Status)) return Status;
+    
+    /* Query value */
+    swprintf(Buffer, L"%04X%04X", VendorId, DeviceId);
+    RtlInitUnicodeString(&ValueName, Buffer);
+    Status = ZwQueryValueKey(KeyHandle,
+                             &ValueName,
+                             KeyValuePartialInformation,
+                             &PartialInfo,
+                             sizeof(PartialInfo),
+                             &ResultLength);
+    if (NT_SUCCESS(Status))
+    {
+        /* Return the flags */
+        DbgPrint("\tFound HackFlags for your chipset\n");
+        *HackFlags = *(PULONG)PartialInfo.Data;
+        DbgPrint("\t\tHack Flags: %lx (Hack Revision: %lx-Your Revision: %lx)\n",
+                 *HackFlags, HALP_REVISION_FROM_HACK_FLAGS(*HackFlags), RevisionId);
+        
+        /* Does it apply to this revision? */
+        if ((RevisionId) && (RevisionId >= (HALP_REVISION_FROM_HACK_FLAGS(*HackFlags))))
+        {
+            /* Read the revision flags */
+            *HackFlags = HALP_REVISION_HACK_FLAGS(*HackFlags);
+        }
+
+        /* Throw out revision data */
+        *HackFlags = HALP_HACK_FLAGS(*HackFlags);
+        if (!*HackFlags) DbgPrint("\tNo HackFlags for your chipset's revision!\n");
+    }
+    
+    /* Close the handle and return */
+    ZwClose(KeyHandle);
+    return Status;
+}
+
+BOOLEAN
+NTAPI
+HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo,
+                     IN PPCI_COMMON_CONFIG PciData,
+                     IN ULONG Flags)
+{
+    ULONG ElementCount, i;
+    PPCI_CARD_DESCRIPTOR CardDescriptor;
+    
+    /* How many PCI Cards that we know about? */
+    ElementCount = PciRegistryInfo->ElementCount;
+    if (!ElementCount) return FALSE;
+
+    /* Loop all descriptors */
+    CardDescriptor = &PciRegistryInfo->CardList[0];
+    for (i = 0; i < ElementCount; i++, CardDescriptor++)
+    {
+        /* Check for flag match */
+        if (CardDescriptor->Flags != Flags) continue;
+        
+        /* Check for VID-PID match */
+        if ((CardDescriptor->VendorID != PciData->VendorID) ||
+            (CardDescriptor->DeviceID != PciData->DeviceID))
+        {
+            /* Skip */
+            continue;
+        }
+
+        /* Check for revision match, if requested */
+        if ((CardDescriptor->Flags & HALP_CHECK_CARD_REVISION_ID) &&
+            (CardDescriptor->RevisionID != PciData->RevisionID))
+        {
+            /* Skip */
+            continue;
+        }
+        
+        /* Check what kind of device this is */
+        switch (PCI_CONFIGURATION_TYPE(PciData))
+        {
+            /* CardBUS Bridge */
+            case PCI_CARDBUS_BRIDGE_TYPE:
+                
+                /* This means the real device header is in the device-specific data */
+                PciData = (PPCI_COMMON_CONFIG)PciData->DeviceSpecific;
+                
+            /* Normal PCI device */
+            case PCI_DEVICE_TYPE:
+
+                /* Check for subvendor match, if requested */
+                if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBVENDOR_ID) &&
+                    (CardDescriptor->SubsystemVendorID != PciData->u.type0.SubVendorID))
+                {
+                    /* Skip */
+                    continue;
+                }
+                
+                /* Check for subsystem match, if requested */
+                if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBSYSTEM_ID) &&
+                    (CardDescriptor->SubsystemID != PciData->u.type0.SubSystemID))
+                {
+                    /* Skip */
+                    continue;
+                }
+                
+                /* You made it! */
+                return TRUE;
+                
+            /* PCI Bridge -- don't bother */
+            case PCI_BRIDGE_TYPE:
+            default:
+             
+                /* Recognize it */
+                return TRUE;
+        }
+    }
+    
+    /* This means the card isn't recognized */
+    return FALSE;
+}
+
+BOOLEAN
+NTAPI
+HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData)
+{
+    /* Simple test first */
+    if ((PciData->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
+        (PciData->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR))
+    {
+        /* The device is nice enough to admit it */
+        return TRUE;
+    }
+    
+    /* Symphony 82C101 */
+    if (PciData->VendorID == 0x1C1C) return TRUE;
+    
+    /* ALi MS4803 or M5219 */
+    if ((PciData->VendorID == 0x10B9) &&
+        ((PciData->DeviceID == 0x5215) || (PciData->DeviceID == 0x5219)))
+    {
+        return TRUE;
+    }
+    
+    /* Appian Technology */
+    if ((PciData->VendorID == 0x1097) && (PciData->DeviceID == 0x38)) return TRUE;
+    
+    /* Compaq Triflex Dual EIDE Controller */
+    if ((PciData->VendorID == 0xE11) && (PciData->DeviceID == 0xAE33)) return TRUE;
+    
+    /* Micron PC Tech RZ1000 */
+    if ((PciData->VendorID == 0x1042) && (PciData->DeviceID == 0x1000)) return TRUE;
+    
+    /* SiS 85C601 or 5513 [IDE] */
+    if ((PciData->VendorID == 0x1039) &&
+        ((PciData->DeviceID == 0x601) || (PciData->DeviceID == 0x5513)))
+    {
+        return TRUE;
+    }
+    
+    /* Symphony Labs W83769F */
+    if ((PciData->VendorID == 0x10AD) &&
+        ((PciData->DeviceID == 0x1) || (PciData->DeviceID == 0x150)))
+    {
+        return TRUE;
+    }
+    
+    /* UMC UM8673F */
+    if ((PciData->VendorID == 0x1060) && (PciData->DeviceID == 0x101)) return TRUE;
+    
+    /* You've survived */
+    return FALSE;
+}
+
+BOOLEAN
+NTAPI
+HalpIsBridgeDevice(IN PPCI_COMMON_CONFIG PciData)
+{
+    /* Either this is a PCI-to-PCI Bridge, or a CardBUS Bridge */
+    return (((PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE) &&
+             (PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
+             (PciData->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI)) ||
+            ((PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE) &&
+             (PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
+             (PciData->SubClass == PCI_SUBCLASS_BR_CARDBUS)));
+}
+    
+BOOLEAN
+NTAPI
+HalpGetPciBridgeConfig(IN ULONG PciType,
+                       IN PUCHAR BusCount)
+{
+    PCI_SLOT_NUMBER PciSlot;
+    ULONG i, j, k;
+    UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
+    PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer;
+    PBUS_HANDLER BusHandler;
+    
+    /* Loop PCI buses */
+    PciSlot.u.bits.Reserved = 0;
+    for (i = 0; i < *BusCount; i++)
+    {
+        /* Get the bus handler */
+        BusHandler = HalHandlerForBus(PCIBus, i);
+        
+        /* Loop every device */
+        for (j = 0; j < PCI_MAX_DEVICES; j++)
+        {
+            /* Loop every function */
+            PciSlot.u.bits.DeviceNumber = j;
+            for (k = 0; k < PCI_MAX_FUNCTION; k++)
+            {
+                /* Build the final slot structure */
+                PciSlot.u.bits.FunctionNumber = k;
+                
+                /* Read the configuration information */
+                HalpReadPCIConfig(BusHandler,
+                                  PciSlot,
+                                  PciData,
+                                  0,
+                                  PCI_COMMON_HDR_LENGTH);
+                
+                /* Skip if this is an invalid function */
+                if (PciData->VendorID == PCI_INVALID_VENDORID) continue;
+                
+                /* Make sure that this is a PCI bridge or a cardbus bridge */
+                if (!HalpIsBridgeDevice(PciData)) continue;
+                
+                /* Not supported */
+                if (!WarningsGiven[2]++) DPRINT1("Your machine has a PCI-to-PCI or CardBUS Bridge. PCI devices may fail!\n");
+                continue;
+            }
+        }
+    }
+    
+    /* If we exited the loop, then there's no bridge to worry about */
+    return FALSE;
+}
+
+VOID
+NTAPI
+HalpFixupPciSupportedRanges(IN ULONG BusCount)
+{
+    ULONG i;
+    PBUS_HANDLER Bus, ParentBus;
+
+    /* Loop all buses */
+    for (i = 0; i < BusCount; i++)
+    {
+        /* Get PCI bus handler */
+        Bus = HalHandlerForBus(PCIBus, i);
+        
+        /* Loop all parent buses */
+        ParentBus = Bus->ParentHandler;
+        while (ParentBus)
+        {
+            /* Should merge addresses */
+            if (!WarningsGiven[0]++) DPRINT1("Found parent bus (indicating PCI Bridge). PCI devices may fail!\n");
+
+            /* Check the next parent */
+            ParentBus = ParentBus->ParentHandler;
+        }
+    }
+
+    /* Loop all buses again */
+    for (i = 0; i < BusCount; i++)
+    {
+        /* Get PCI bus handler */
+        Bus = HalHandlerForBus(PCIBus, i);
+        
+        /* Check if this is a PCI 2.2 Bus with Subtractive Decode */
+        if (!((PPCIPBUSDATA)Bus->BusData)->Subtractive)
+        {
+            /* Loop all parent buses */
+            ParentBus = Bus->ParentHandler;
+            while (ParentBus)
+            {
+                /* But check only PCI parent buses specifically */
+                if (ParentBus->InterfaceType == PCIBus)
+                {
+                    /* Should trim addresses */
+                    if (!WarningsGiven[1]++) DPRINT1("Found parent PCI Bus (indicating PCI-to-PCI Bridge). PCI devices may fail!\n");
+                }
+            
+                /* Check the next parent */
+                ParentBus = ParentBus->ParentHandler;
+            }
+        }
+    }
+
+    /* Loop buses one last time */
+    for (i = 0; i < BusCount; i++)
+    {
+        /* Get the PCI bus handler */
+        Bus = HalHandlerForBus(PCIBus, i);
+        
+        /* Sort and combine (trim) bus address range information */
+        DPRINT("Warning: Bus addresses not being optimized!\n");
+    }
+}
+
+VOID
+NTAPI
+ShowSize(ULONG x)
+{
+    if (!x) return;
+    DbgPrint(" [size=");
+    if (x < 1024)
+    {
+        DbgPrint("%d", (int) x);
+    }
+    else if (x < 1048576)
+    {   
+        DbgPrint("%dK", (int)(x / 1024));
+    }
+    else if (x < 0x80000000)
+    {
+        DbgPrint("%dM", (int)(x / 1048576));
+    }
+    else
+    {
+        DbgPrint("%d", x);
+    }
+    DbgPrint("]\n");
+}
+
+VOID
+NTAPI
+HalpDebugPciBus(IN ULONG i,
+                IN ULONG j,
+                IN ULONG k,
+                IN PPCI_COMMON_CONFIG PciData)
+{   
+    extern CHAR ClassTable[3922];
+    extern CHAR VendorTable[642355];
+    PCHAR p, ClassName, SubClassName, VendorName, ProductName, SubVendorName;
+    ULONG Length;
+    CHAR LookupString[16] = "";
+    CHAR bSubClassName[32] = "";
+    CHAR bVendorName[32] = "";
+    CHAR bProductName[32] = "Unknown device";
+    CHAR bSubVendorName[32] = "Unknown";
+    ULONG Size, Mem, b;
+
+    /* Isolate the class name */
+    sprintf(LookupString, "C %02x", PciData->BaseClass);
+    ClassName = strstr(ClassTable, LookupString);
+    if (ClassName)
+    {
+        /* Isolate the subclass name */
+        ClassName += 6;
+        sprintf(LookupString, "\t%02x", PciData->SubClass);
+        SubClassName = strstr(ClassName, LookupString);
+        if (SubClassName)
+        {
+            /* Copy the subclass into our buffer */
+            SubClassName += 5;
+            p = strchr(SubClassName, '\r');
+            Length = p - SubClassName;
+            if (Length > sizeof(bSubClassName)) Length = sizeof(bSubClassName);
+            strncpy(bSubClassName, SubClassName, Length);
+            bSubClassName[Length] = '\0';
+        }
+    }
+
+    /* Isolate the vendor name */
+    sprintf(LookupString, "\n%04x  ", PciData->VendorID);
+    VendorName = strstr(VendorTable, LookupString);
+    if (VendorName)
+    {
+        /* Copy the vendor name into our buffer */
+        VendorName += 7;
+        p = strchr(VendorName, '\r');
+        Length = p - VendorName;
+        if (Length > sizeof(bVendorName)) Length = sizeof(bVendorName);
+        strncpy(bVendorName, VendorName, Length);
+        bVendorName[Length ] = '\0';
+        
+        /* Isolate the product name */
+        sprintf(LookupString, "\t%04x", PciData->DeviceID);
+        ProductName = strstr(VendorName, LookupString);
+        if (ProductName)
+        {
+            /* Copy the product name into our buffer */
+            ProductName += 7;
+            p = strchr(ProductName, '\r');
+            Length = p - ProductName;
+            if (Length > sizeof(bProductName)) Length = sizeof(bProductName);
+            strncpy(bProductName, ProductName, Length);
+            bProductName[Length] = '\0';
+            
+            /* Isolate the subvendor and subsystem name */
+            sprintf(LookupString,
+                    "\t\t%04x %04x  ",
+                    PciData->u.type0.SubVendorID,
+                    PciData->u.type0.SubSystemID);
+            SubVendorName = strstr(ProductName, LookupString);
+            if (SubVendorName)
+            {
+                /* Copy the subvendor name into our buffer */
+                SubVendorName += 13;
+                p = strchr(SubVendorName, '\r');
+                Length = p - SubVendorName;
+                if (Length > sizeof(bSubVendorName)) Length = sizeof(bSubVendorName);
+                strncpy(bSubVendorName, SubVendorName, Length);
+                bSubVendorName[Length] = '\0';
+            }
+        }
+    }
+
+    /* Print out the data */
+    DbgPrint("%02x:%02x.%x %s [%02x%02x]: %s %s [%04x:%04x] (rev %02x)\n"
+             "\tSubsystem: %s [%04x:%04x]\n",
+             i,
+             j,
+             k,
+             bSubClassName,
+             PciData->BaseClass,
+             PciData->SubClass,
+             bVendorName,
+             bProductName,
+             PciData->VendorID,
+             PciData->DeviceID,
+             PciData->RevisionID,
+             bSubVendorName,
+             PciData->u.type0.SubVendorID,
+             PciData->u.type0.SubSystemID);
+    
+    /* Print out and decode flags */
+    DbgPrint("\tFlags:");
+    if (PciData->Command & PCI_ENABLE_BUS_MASTER) DbgPrint(" bus master,");
+    if (PciData->Status & PCI_STATUS_66MHZ_CAPABLE) DbgPrint(" 66MHz,");
+    if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x200) DbgPrint(" medium devsel,");
+    if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x400) DbgPrint(" fast devsel,");
+    DbgPrint(" latency %d", PciData->LatencyTimer);
+    if (PciData->u.type0.InterruptLine) DbgPrint(", IRQ %02d", PciData->u.type0.InterruptLine);
+    DbgPrint("\n");
+    
+    /* Scan addresses */
+    Size = 0;
+    for (b = 0; b < PCI_TYPE0_ADDRESSES; b++)
+    {
+        /* Check for a BAR */
+        Mem = PciData->u.type0.BaseAddresses[b];
+        if (Mem)
+        {   
+            /* Decode the address type */
+            if (Mem & PCI_ADDRESS_IO_SPACE)
+            {
+                /* Decode the size */
+                Size = 1 << 2;
+                while (!(Mem & Size) && (Size)) Size <<= 1;
+                
+                /* Print it out */
+                DbgPrint("\tI/O ports at %04lx", Mem & PCI_ADDRESS_IO_ADDRESS_MASK);
+                ShowSize(Size);
+            }
+            else
+            {
+                /* Decode the size */
+                Size = 1 << 8;
+                while (!(Mem & Size) && (Size)) Size <<= 1;
+                
+                /* Print it out */
+                DbgPrint("\tMemory at %08lx (%d-bit, %sprefetchable)",
+                         Mem & PCI_ADDRESS_MEMORY_ADDRESS_MASK,
+                         (Mem & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_32BIT ? 32 : 64,
+                         (Mem & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? "" : "non-");
+                ShowSize(Size);
+            }
+        }
+    }
+}
+#endif
+
+VOID
+NTAPI
+HalpInitializePciBus(VOID)
+{
+#ifndef _MINIHAL_
+    PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
+    UCHAR PciType;
+    PCI_SLOT_NUMBER PciSlot;
+    ULONG i, j, k;
+    UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
+    PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer;
+    PBUS_HANDLER BusHandler;
+    ULONG HackFlags;
+    BOOLEAN ExtendedAddressDecoding = FALSE;
+    NTSTATUS Status;
+    
+    /* Query registry information */
+    PciRegistryInfo = HalpQueryPciRegistryInfo();
+    if (!PciRegistryInfo) return;
+    
+    /* Initialize the PCI configuration lock */
+    KeInitializeSpinLock(&HalpPCIConfigLock);
+    
+    /* Get the type and free the info structure */
+    PciType = PciRegistryInfo->HardwareMechanism & 0xF;
+    
+    /* Check if this is a type 2 PCI bus with at least one bus */
+    if ((PciRegistryInfo->NoBuses) && (PciType == 2))
+    {
+        /* Setup the PCI slot */
+        PciSlot.u.bits.Reserved = 0;
+        PciSlot.u.bits.FunctionNumber = 0;
+        
+        /* Loop all slots */
+        for (i = 0; i < 32; i++)
+        {
+            /* Try to setup a Type 2 PCI slot */
+            PciType = 2;
+            BusHandler = HalpAllocateAndInitPciBusHandler(2, 0, TRUE);
+            if (!BusHandler) break;
+            
+            /* Now check if it's valid */
+            if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;
+            
+            /* Heh, the BIOS lied... try Type 1 */
+            PciType = 1;
+            BusHandler = HalpAllocateAndInitPciBusHandler(1, 0, TRUE);
+            if (!BusHandler) break;
+            
+            /* Now check if it's valid */
+            if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;
+            
+            /* Keep trying */
+            PciType = 2;
+        }
+        
+        /* Now allocate the correct kind of handler */
+        HalpAllocateAndInitPciBusHandler(PciType, 0, FALSE);
+    }
+    
+    /* Okay, now loop all PCI bridges */
+    do
+    {
+        /* Loop all PCI buses */
+        for (i = 0; i < PciRegistryInfo->NoBuses; i++)
+        {
+            /* Check if we have a handler for it */
+            if (!HalHandlerForBus(PCIBus, i))
+            {
+                /* Allocate it */
+                HalpAllocateAndInitPciBusHandler(PciType, i, FALSE);
+            }
+        }
+        /* Go to the next bridge */
+    } while (HalpGetPciBridgeConfig(PciType, &PciRegistryInfo->NoBuses));
+             
+    /* Now build correct address range informaiton */
+    HalpFixupPciSupportedRanges(PciRegistryInfo->NoBuses);
+    
+    /* Loop every bus */
+    DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n");
+    PciSlot.u.bits.Reserved = 0;
+    for (i = 0; i < PciRegistryInfo->NoBuses; i++)
+    {
+        /* Get the bus handler */
+        BusHandler = HalHandlerForBus(PCIBus, i);
+        
+        /* Loop every device */
+        for (j = 0; j < 32; j++)
+        {
+            /* Loop every function */
+            PciSlot.u.bits.DeviceNumber = j;
+            for (k = 0; k < 8; k++)
+            {
+                /* Build the final slot structure */
+                PciSlot.u.bits.FunctionNumber = k;
+                
+                /* Read the configuration information */
+                HalpReadPCIConfig(BusHandler,
+                                  PciSlot,
+                                  PciData,
+                                  0,
+                                  PCI_COMMON_HDR_LENGTH);
+                
+                /* Skip if this is an invalid function */
+                if (PciData->VendorID == PCI_INVALID_VENDORID) continue;
+                
+                /* Print out the entry */
+                HalpDebugPciBus(i, j, k, PciData);
+                
+                /* Check if this is a Cardbus bridge */
+                if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE)
+                {
+                    /* Not supported */
+                    DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n");
+                    continue;
+                }
+                
+                /* Check if this is a PCI device */
+                if (PCI_CONFIGURATION_TYPE(PciData) != PCI_BRIDGE_TYPE)
+                {
+                    /* Check if it has an interrupt pin and line registered */
+                    if ((PciData->u.type1.InterruptPin) && 
+                        (PciData->u.type1.InterruptLine))
+                    {
+                        /* Check if this interrupt line is connected to the bus */
+                        if (PciData->u.type1.InterruptLine < 16)
+                        {
+                            /* Is this an IDE device? */
+                            if (!HalpIsIdeDevice(PciData))
+                            {
+                                /* We'll mask out this interrupt then */
+                                DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n",
+                                         PciData->u.type1.InterruptLine);
+                                HalpPciIrqMask |= (1 << PciData->u.type1.InterruptLine);
+                            }
+                        }
+                    }
+                }
+                
+                /* Check for broken Intel chips */
+                if (PciData->VendorID == 0x8086)
+                {
+                    /* Check for broken 82830 PCI controller */
+                    if ((PciData->DeviceID == 0x04A3) &&
+                        (PciData->RevisionID < 0x11))
+                    {
+                        /* Skip */
+                        DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n");
+                        continue;
+                    }
+                    
+                    /* Check for broken 82378 PCI-to-ISA Bridge */
+                    if ((PciData->DeviceID == 0x0484) &&
+                        (PciData->RevisionID <= 3))
+                    {
+                        /* Skip */
+                        DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n");
+                        continue;
+                    }
+                    
+                    /* Check for broken 82450 PCI Bridge */
+                    if ((PciData->DeviceID == 0x84C4) &&
+                        (PciData->RevisionID <= 4))
+                    {
+                        DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n");
+                        continue;
+                    }
+                }
+                
+                /* Do we know this card? */
+                if (!ExtendedAddressDecoding)
+                {
+                    /* Check for it */
+                    if (HalpIsRecognizedCard(PciRegistryInfo,
+                                             PciData,
+                                             HALP_CARD_FEATURE_FULL_DECODE))
+                    {
+                        /* We'll do chipset checks later */
+                        DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n");
+                        ExtendedAddressDecoding = TRUE;
+                    }
+                }
+                
+                /* Check if this is a USB controller */
+                if ((PciData->BaseClass == PCI_CLASS_SERIAL_BUS_CTLR) &&
+                    (PciData->SubClass == PCI_SUBCLASS_SB_USB))
+                {
+                    /* Check if this is an OHCI controller */
+                    if (PciData->ProgIf == 0x10)
+                    {
+                        DbgPrint("\tDevice is an OHCI (USB) PCI Expansion Card. Turn off Legacy USB in your BIOS!\n\n");
+                        continue;
+                    }
+                    
+                    /* Check for Intel UHCI controller */
+                    if (PciData->VendorID == 0x8086)
+                    {
+                        DbgPrint("\tDevice is an Intel UHCI (USB) Controller. Turn off Legacy USB in your BIOS!\n\n");
+                        continue;
+                    }
+                    
+                    /* Check for VIA UHCI controller */
+                    if (PciData->VendorID == 0x1106)
+                    {
+                        DbgPrint("\tDevice is a VIA UHCI (USB) Controller. Turn off Legacy USB in your BIOS!\n\n");
+                        continue;
+                    }
+                }
+                
+                /* Now check the registry for chipset hacks */
+                Status = HalpGetChipHacks(PciData->VendorID,
+                                          PciData->DeviceID,
+                                          PciData->RevisionID,
+                                          &HackFlags);
+                if (NT_SUCCESS(Status))
+                {
+                    /* Check for broken ACPI routing */
+                    if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING)
+                    {
+                        DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n");
+                        continue;
+                    }
+                    
+                    /* Check for broken ACPI timer */
+                    if (HackFlags & HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER)
+                    {
+                         DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n");
+                         continue;
+                    }
+                    
+                    /* Check for hibernate-disable */
+                    if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE)
+                    {
+                        DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n");
+                        continue;
+                    }
+                    
+                    /* Check for USB controllers that generate SMIs */
+                    if (HackFlags & HAL_PCI_CHIP_HACK_USB_SMI_DISABLE)
+                    {
+                        DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n");
+                        continue;
+                    }
+                }
+                
+                /* Terminate the entry */
+                DbgPrint("\n");
+            }
+        }
+    }
+    
+    /* Initialize NMI Crash Flag */
+    HalpGetNMICrashFlag();
+        
+    /* Free the registry data */
+    ExFreePool(PciRegistryInfo);
+    
+    /* Tell PnP if this hard supports correct decoding */
+    HalpMarkChipsetDecode(ExtendedAddressDecoding);
+    DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n");
+#endif
+}
+
+VOID
+NTAPI
+HalpInitBusHandlers(VOID)
+{
+    /* Register the HAL Bus Handler support */
+    HalpRegisterInternalBusHandlers();
+}
+
+VOID
+NTAPI
+HalpRegisterKdSupportFunctions(VOID)
+{
+    /* Register PCI Device Functions */
+    KdSetupPciDeviceForDebugging = HalpSetupPciDeviceForDebugging;
+    KdReleasePciDeviceforDebugging = HalpReleasePciDeviceForDebugging;
+
+    /* Register memory functions */
+#ifndef _MINIHAL_
+    KdMapPhysicalMemory64 = HalpMapPhysicalMemory64;
+    KdUnmapVirtualAddress = HalpUnmapVirtualAddress;
+#endif
+
+    /* Register ACPI stub */
+    KdCheckPowerButton = HalpCheckPowerButton;
+}
+
+NTSTATUS
+NTAPI
+HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath,
+                        IN PUNICODE_STRING DriverClassName,
+                        IN PDRIVER_OBJECT DriverObject,
+                        IN PDEVICE_OBJECT DeviceObject,
+                        IN INTERFACE_TYPE BusType,
+                        IN ULONG BusNumber,
+                        IN ULONG SlotNumber,
+                        IN OUT PCM_RESOURCE_LIST *AllocatedResources)
+{
+    PBUS_HANDLER Handler;
+    NTSTATUS Status;
+    PAGED_CODE();
+    DPRINT1("Slot assignment for %d on bus %d\n", BusType, BusNumber);
+    
+    /* Find the handler */
+    Handler = HalReferenceHandlerForBus(BusType, BusNumber);
+    if (!Handler) return STATUS_NOT_FOUND;
+
+    /* Do the assignment */
+    Status = Handler->AssignSlotResources(Handler,
+                                          Handler,
+                                          RegistryPath,
+                                          DriverClassName,
+                                          DriverObject,
+                                          DeviceObject,
+                                          SlotNumber,
+                                          AllocatedResources);
+    
+    /* Dereference the handler and return */
+    HalDereferenceBusHandler(Handler);
+    return Status;
+}
+
+BOOLEAN
+NTAPI
+HaliFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress,
+                              IN OUT PULONG AddressSpace,
+                              OUT PPHYSICAL_ADDRESS TranslatedAddress,
+                              IN OUT PULONG_PTR Context,
+                              IN BOOLEAN NextBus)
+{
+    PHAL_BUS_HANDLER BusHandler;
+    PBUS_HANDLER Handler;
+    PLIST_ENTRY NextEntry;
+    ULONG ContextValue;
+
+    /* Make sure we have a context */
+    if (!Context) return FALSE;
+    ASSERT((*Context) || (NextBus == TRUE));
+    
+    /* Read the context */
+    ContextValue = *Context;
+    
+    /* Find the bus handler */
+    Handler = HalpContextToBusHandler(ContextValue);
+    if (!Handler) return FALSE;
+    
+    /* Check if this is an ongoing lookup */
+    if (NextBus)
+    {
+        /* Get the HAL bus handler */
+        BusHandler = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler);
+        NextEntry = &BusHandler->AllHandlers;
+        
+        /* Get the next one if we were already with one */
+        if (ContextValue) NextEntry = NextEntry->Flink;
+        
+        /* Start scanning */
+        while (TRUE)
+        {
+            /* Check if this is the last one */
+            if (NextEntry == &HalpAllBusHandlers)
+            {
+                /* Quit */
+                *Context = 1;
+                return FALSE;
+            }
+            
+            /* Call this translator */
+            BusHandler = CONTAINING_RECORD(NextEntry, HAL_BUS_HANDLER, AllHandlers);
+            if (HalTranslateBusAddress(BusHandler->Handler.InterfaceType,
+                                       BusHandler->Handler.BusNumber,
+                                       BusAddress,
+                                       AddressSpace,
+                                       TranslatedAddress)) break;
+            
+            /* Try the next one */
+            NextEntry = NextEntry->Flink;
+        }
+        
+        /* If we made it, we're done */
+        *Context = (ULONG_PTR)Handler;
+        return TRUE;
+    }
+    
+    /* Try the first one through */
+    if (!HalTranslateBusAddress(Handler->InterfaceType,
+                                Handler->BusNumber,
+                                BusAddress,
+                                AddressSpace,
+                                TranslatedAddress)) return FALSE;
+    
+    /* Remember for next time */
+    *Context = (ULONG_PTR)Handler;
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+HaliTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
+                        IN ULONG BusNumber,
+                        IN PHYSICAL_ADDRESS BusAddress,
+                        IN OUT PULONG AddressSpace,
+                        OUT PPHYSICAL_ADDRESS TranslatedAddress)
+{
+    PBUS_HANDLER Handler;
+    BOOLEAN Status;
+    
+    /* Find the handler */
+    Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber);
+    if (!(Handler) || !(Handler->TranslateBusAddress))
+    {
+        DPRINT1("No translator!\n");
+        return FALSE;
+    }
+    
+    /* Do the assignment */
+    Status = Handler->TranslateBusAddress(Handler,
+                                          Handler,
+                                          BusAddress,
+                                          AddressSpace,
+                                          TranslatedAddress);
+    
+    /* Dereference the handler and return */
+    HalDereferenceBusHandler(Handler);
+    return Status;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+HalAdjustResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST *ResourceList)
+{
+    PBUS_HANDLER Handler;
+    ULONG Status;
+    PAGED_CODE();
+    
+    /* Find the handler */
+    Handler = HalReferenceHandlerForBus((*ResourceList)->InterfaceType,
+                                        (*ResourceList)->BusNumber);
+    if (!Handler) return STATUS_SUCCESS;
+    
+    /* Do the assignment */
+    Status = Handler->AdjustResourceList(Handler,
+                                         Handler,
+                                         ResourceList);
+    
+    /* Dereference the handler and return */
+    HalDereferenceBusHandler(Handler);
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+HalAssignSlotResources(IN PUNICODE_STRING RegistryPath,
+                       IN PUNICODE_STRING DriverClassName,
+                       IN PDRIVER_OBJECT DriverObject,
+                       IN PDEVICE_OBJECT DeviceObject,
+                       IN INTERFACE_TYPE BusType,
+                       IN ULONG BusNumber,
+                       IN ULONG SlotNumber,
+                       IN OUT PCM_RESOURCE_LIST *AllocatedResources)
+{
+    PAGED_CODE();
+    
+    /* Check the bus type */
+    if (BusType != PCIBus)
+    {
+        /* Call our internal handler */
+        return HalpAssignSlotResources(RegistryPath,
+                                       DriverClassName,
+                                       DriverObject,
+                                       DeviceObject,
+                                       BusType,
+                                       BusNumber,
+                                       SlotNumber,
+                                       AllocatedResources);
+    }
+    else
+    {
+        /* Call the PCI registered function */
+        return HalPciAssignSlotResources(RegistryPath,
+                                         DriverClassName,
+                                         DriverObject,
+                                         DeviceObject,
+                                         PCIBus,
+                                         BusNumber,
+                                         SlotNumber,
+                                         AllocatedResources);
+    }
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+HalGetBusData(IN BUS_DATA_TYPE BusDataType,
+              IN ULONG BusNumber,
+              IN ULONG SlotNumber,
+              IN PVOID Buffer,
+              IN ULONG Length)
+{
+    /* Call the extended function */
+    return HalGetBusDataByOffset(BusDataType,
+                                 BusNumber,
+                                 SlotNumber,
+                                 Buffer,
+                                 0,
+                                 Length);
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
+                      IN ULONG BusNumber,
+                      IN ULONG SlotNumber,
+                      IN PVOID Buffer,
+                      IN ULONG Offset,
+                      IN ULONG Length)
+{
+    PBUS_HANDLER Handler;
+    ULONG Status;
+    
+    /* Find the handler */
+    Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber);
+    if (!Handler) return 0;
+    
+    /* Do the assignment */
+    Status = Handler->GetBusData(Handler,
+                                 Handler,
+                                 SlotNumber,
+                                 Buffer,
+                                 Offset,
+                                 Length);
+    
+    /* Dereference the handler and return */
+    HalDereferenceBusHandler(Handler);
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType,
+                      IN ULONG BusNumber,
+                      IN ULONG BusInterruptLevel,
+                      IN ULONG BusInterruptVector,
+                      OUT PKIRQL Irql,
+                      OUT PKAFFINITY Affinity)
+{
+    PBUS_HANDLER Handler;
+    ULONG Vector;
+    PAGED_CODE();
+    
+    /* Defaults */
+    *Irql = 0;
+    *Affinity = 0;
+    
+    /* Find the handler */
+    Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber);
+    if (!Handler) return 0;
+    
+    /* Do the assignment */
+    Vector = Handler->GetInterruptVector(Handler,
+                                         Handler,
+                                         BusInterruptLevel,
+                                         BusInterruptVector,
+                                         Irql,
+                                         Affinity);
+    if ((Vector != IRQ2VECTOR(BusInterruptLevel)) ||
+        (*Irql != VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel))))
+    {
+        DPRINT1("Returning IRQL %lx, Vector %lx for Level/Vector: %lx/%lx\n",
+                *Irql, Vector, BusInterruptLevel, BusInterruptVector);
+        DPRINT1("Old HAL would've returned IRQL %lx and Vector %lx\n",
+                VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel)),
+                IRQ2VECTOR(BusInterruptLevel));
+    }
+    
+    /* Dereference the handler and return */
+    HalDereferenceBusHandler(Handler);
+    return Vector;
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+HalSetBusData(IN BUS_DATA_TYPE BusDataType,
+              IN ULONG BusNumber,
+              IN ULONG SlotNumber,
+              IN PVOID Buffer,
+              IN ULONG Length)
+{
+    /* Call the extended function */
+    return HalSetBusDataByOffset(BusDataType,
+                                 BusNumber,
+                                 SlotNumber,
+                                 Buffer,
+                                 0,
+                                 Length);
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
+                      IN ULONG BusNumber,
+                      IN ULONG SlotNumber,
+                      IN PVOID Buffer,
+                      IN ULONG Offset,
+                      IN ULONG Length)
+{
+    PBUS_HANDLER Handler;
+    ULONG Status;
+    
+    /* Find the handler */
+    Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber);
+    if (!Handler) return 0;
+    
+    /* Do the assignment */
+    Status = Handler->SetBusData(Handler,
+                                 Handler,
+                                 SlotNumber,
+                                 Buffer,
+                                 Offset,
+                                 Length);
+    
+    /* Dereference the handler and return */
+    HalDereferenceBusHandler(Handler);
+    return Status;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
+                       IN ULONG BusNumber,
+                       IN PHYSICAL_ADDRESS BusAddress,
+                       IN OUT PULONG AddressSpace,
+                       OUT PPHYSICAL_ADDRESS TranslatedAddress)
+{
+    /* Look as the bus type */
+    if (InterfaceType == PCIBus)
+    {
+        /* Call the PCI registered function */
+        return HalPciTranslateBusAddress(PCIBus,
+                                         BusNumber,
+                                         BusAddress,
+                                         AddressSpace,
+                                         TranslatedAddress);
+    }
+    else
+    {
+        /* Call the bus handler */
+        return HaliTranslateBusAddress(InterfaceType,
+                                       BusNumber,
+                                       BusAddress,
+                                       AddressSpace,
+                                       TranslatedAddress);
+    }
+}
+
+/* EOF */
diff --git a/hal/halx86/generic/memory.c b/hal/halx86/generic/memory.c
new file mode 100644 (file)
index 0000000..74f20cb
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * PROJECT:         ReactOS HAL
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            hal/halx86/generic/memory.c
+ * PURPOSE:         HAL memory management
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+/* Share with Mm headers? */
+#define MM_HAL_VA_START     (PVOID)0xFFC00000
+#define MM_HAL_HEAP_START   (PVOID)((ULONG_PTR)MM_HAL_VA_START + (1024 * 1024))
+
+/* GLOBALS *******************************************************************/
+
+ULONG HalpUsedAllocDescriptors;
+MEMORY_ALLOCATION_DESCRIPTOR HalpAllocationDescriptorArray[64];
+PVOID HalpHeapStart = MM_HAL_HEAP_START;
+
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+
+ULONG
+NTAPI
+HalpAllocPhysicalMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
+                        IN ULONG MaxAddress,
+                        IN ULONG PageCount,
+                        IN BOOLEAN Aligned)
+{
+    ULONG UsedDescriptors, Alignment, PhysicalAddress;
+    PFN_NUMBER MaxPage, BasePage;
+    PLIST_ENTRY NextEntry;
+    PMEMORY_ALLOCATION_DESCRIPTOR MdBlock, NewBlock, FreeBlock;
+    
+    /* Highest page we'll go */
+    MaxPage = MaxAddress >> PAGE_SHIFT;
+    
+    /* We need at least two blocks */
+    if ((HalpUsedAllocDescriptors + 2) > 64) return 0;
+    
+    /* Remember how many we have now */
+    UsedDescriptors = HalpUsedAllocDescriptors;
+        
+    /* Loop the loader block memory descriptors */
+    NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+    while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
+    {
+        /* Get the block */
+        MdBlock = CONTAINING_RECORD(NextEntry,
+                                    MEMORY_ALLOCATION_DESCRIPTOR,
+                                    ListEntry);
+        
+        /* No alignment by default */
+        Alignment = 0;
+        
+        /* Unless requested, in which case we use a 64KB block alignment */
+        if (Aligned) Alignment = ((MdBlock->BasePage + 0x0F) & ~0x0F) - MdBlock->BasePage;
+        
+        /* Search for free memory */
+        if ((MdBlock->MemoryType == LoaderFree) ||
+            (MdBlock->MemoryType == LoaderFirmwareTemporary))
+        {
+            /* Make sure the page is within bounds, including alignment */
+            BasePage = MdBlock->BasePage;
+            if ((BasePage) &&
+                (MdBlock->PageCount >= PageCount + Alignment) &&
+                (BasePage + PageCount + Alignment < MaxPage))
+            {
+                
+                /* We found an address */
+                PhysicalAddress = (BasePage + Alignment) << PAGE_SHIFT;
+                break;
+            }
+        }
+        
+        /* Keep trying */
+        NextEntry = NextEntry->Flink;
+    }
+    
+    /* If we didn't find anything, get out of here */
+    if (NextEntry == &LoaderBlock->MemoryDescriptorListHead) return 0;
+    
+    /* Okay, now get a descriptor */
+    NewBlock = &HalpAllocationDescriptorArray[HalpUsedAllocDescriptors];
+    NewBlock->PageCount = PageCount;
+    NewBlock->BasePage = MdBlock->BasePage + Alignment;
+    NewBlock->MemoryType = LoaderHALCachedMemory;
+    
+    /* Update count */
+    UsedDescriptors++;
+    HalpUsedAllocDescriptors = UsedDescriptors;
+    
+    /* Check if we had any alignment */
+    if (Alignment)
+    {
+        /* Check if we had leftovers */
+        if ((MdBlock->PageCount - Alignment) != PageCount)
+        {
+            /* Get the next descriptor */
+            FreeBlock = &HalpAllocationDescriptorArray[UsedDescriptors];
+            FreeBlock->PageCount = MdBlock->PageCount - Alignment - PageCount;
+            FreeBlock->BasePage = MdBlock->BasePage + Alignment + PageCount;
+            
+            /* One more */
+            HalpUsedAllocDescriptors++;
+            
+            /* Insert it into the list */
+            InsertHeadList(&MdBlock->ListEntry, &FreeBlock->ListEntry);
+        }
+        
+        /* Use this descriptor */
+        NewBlock->PageCount = Alignment;
+        InsertHeadList(&MdBlock->ListEntry, &NewBlock->ListEntry);
+    }
+    else
+    {
+        /* Consume memory from this block */
+        MdBlock->BasePage += PageCount;
+        MdBlock->PageCount -= PageCount;
+        
+        /* Insert the descriptor */
+        InsertTailList(&MdBlock->ListEntry, &NewBlock->ListEntry);
+
+        /* Remove the entry if the whole block was allocated */
+        if (!MdBlock->PageCount == 0) RemoveEntryList(&MdBlock->ListEntry);
+    }
+
+    /* Return the address */
+    return PhysicalAddress;
+}
+
+PVOID
+NTAPI
+HalpMapPhysicalMemory64(IN PHYSICAL_ADDRESS PhysicalAddress,
+                        IN ULONG PageCount)
+{
+    PHARDWARE_PTE PointerPte;
+    ULONG UsedPages = 0;
+    PVOID VirtualAddress, BaseAddress;
+
+    /* Start at the current HAL heap base */
+    BaseAddress = HalpHeapStart;
+    VirtualAddress = BaseAddress;
+
+    /* Loop until we have all the pages required */
+    while (UsedPages < PageCount)
+    {
+        /* If this overflows past the HAL heap, it means there's no space */
+        if (VirtualAddress == NULL) return NULL;
+
+        /* Get the PTE for this address */
+        PointerPte = HalAddressToPte(VirtualAddress);
+
+        /* Go to the next page */
+        VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE);
+
+        /* Check if the page is available */
+        if (PointerPte->Valid)
+        {
+            /* PTE has data, skip it and start with a new base address */
+            BaseAddress = VirtualAddress;
+            UsedPages = 0;
+            continue;
+        }
+
+        /* PTE is available, keep going on this run */
+        UsedPages++;
+    }
+
+    /* Take the base address of the page plus the actual offset in the address */
+    VirtualAddress = (PVOID)((ULONG_PTR)BaseAddress +
+                             BYTE_OFFSET(PhysicalAddress.LowPart));
+
+    /* If we are starting at the heap, move the heap */
+    if (BaseAddress == HalpHeapStart)
+    {
+        /* Past this allocation */
+        HalpHeapStart = (PVOID)((ULONG_PTR)BaseAddress + (PageCount * PAGE_SIZE));
+    }
+
+    /* Loop pages that can be mapped */
+    while (UsedPages--)
+    {
+        /* Fill out the PTE */
+        PointerPte = HalAddressToPte(BaseAddress);
+        PointerPte->PageFrameNumber = PhysicalAddress.QuadPart >> PAGE_SHIFT;
+        PointerPte->Valid = 1;
+        PointerPte->Write = 1;
+
+        /* Move to the next address */
+        PhysicalAddress.QuadPart += PAGE_SIZE;
+        BaseAddress = (PVOID)((ULONG_PTR)BaseAddress + PAGE_SIZE);
+    }
+
+    /* Flush the TLB and return the address */
+    HalpFlushTLB();
+    return VirtualAddress;
+}
+
+VOID
+NTAPI
+HalpUnmapVirtualAddress(IN PVOID VirtualAddress,
+                        IN ULONG PageCount)
+{
+    PHARDWARE_PTE PointerPte;
+    ULONG i;
+
+    /* Only accept valid addresses */
+    if (VirtualAddress < MM_HAL_VA_START) return;
+
+    /* Align it down to page size */
+    VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress & ~(PAGE_SIZE - 1));
+
+    /* Loop PTEs */
+    PointerPte = HalAddressToPte(VirtualAddress);
+    for (i = 0; i < PageCount; i++)
+    {
+        *(PULONG)PointerPte = 0;
+        PointerPte++;
+    }
+
+    /* Flush the TLB */
+    HalpFlushTLB();
+
+    /* Put the heap back */
+    if (HalpHeapStart > VirtualAddress) HalpHeapStart = VirtualAddress;
+}
+