diff --git a/reactos/hal/halppc/directory.rbuild b/reactos/hal/halppc/directory.rbuild
new file mode 100644
index 00000000000..d1338a727ab
--- /dev/null
+++ b/reactos/hal/halppc/directory.rbuild
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/reactos/hal/halppc/generic/beep.c b/reactos/hal/halppc/generic/beep.c
new file mode 100644
index 00000000000..f4e9d3b07ea
--- /dev/null
+++ b/reactos/hal/halppc/generic/beep.c
@@ -0,0 +1,42 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/beep.c
+ * PURPOSE: Speaker function (it's only one)
+ * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de)
+ * UPDATE HISTORY:
+ * Created 31/01/99
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+
+/* CONSTANTS *****************************************************************/
+
+#define TIMER2 0x42
+#define TIMER3 0x43
+#define PORT_B 0x61
+#define CLOCKFREQ 1193167
+
+
+/* FUNCTIONS *****************************************************************/
+/*
+ * FUNCTION: Beeps the speaker.
+ * ARGUMENTS:
+ * Frequency = If 0, the speaker will be switched off, otherwise
+ * the speaker beeps with the specified frequency.
+ */
+
+BOOLEAN
+STDCALL
+HalMakeBeep (
+ ULONG Frequency
+ )
+{
+ return TRUE;
+}
+
diff --git a/reactos/hal/halppc/generic/bus.c b/reactos/hal/halppc/generic/bus.c
new file mode 100644
index 00000000000..35bac840f2c
--- /dev/null
+++ b/reactos/hal/halppc/generic/bus.c
@@ -0,0 +1,529 @@
+/* $Id: bus.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/bus.c
+ * PURPOSE: Bus functions
+ * PROGRAMMER: David Welch (welch@mcmail.com)
+ * UPDATE HISTORY:
+ * Created 22/05/98
+ *
+ *
+ * TODO:
+ * - Add bus handler functions for all busses
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+/* GLOBALS *******************************************************************/
+
+#define TAG_BUS TAG('B', 'U', 'S', 'H')
+
+KSPIN_LOCK HalpBusHandlerSpinLock = {0,};
+LIST_ENTRY HalpBusHandlerList;
+
+
+/* FUNCTIONS *****************************************************************/
+
+static NTSTATUS STDCALL
+HalpNoAdjustResourceList(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ PCM_RESOURCE_LIST Resources)
+{
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+static NTSTATUS STDCALL
+HalpNoAssignSlotResources(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ PUNICODE_STRING RegistryPath,
+ PUNICODE_STRING DriverClassName,
+ PDRIVER_OBJECT DriverObject,
+ PDEVICE_OBJECT DeviceObject,
+ ULONG SlotNumber,
+ PCM_RESOURCE_LIST *AllocatedResources)
+{
+ return STATUS_NOT_SUPPORTED;
+}
+
+
+static ULONG STDCALL
+HalpNoBusData(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length)
+{
+ return 0;
+}
+
+
+static ULONG STDCALL
+HalpNoGetInterruptVector(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ ULONG BusInterruptLevel,
+ ULONG BusInterruptVector,
+ PKIRQL Irql,
+ PKAFFINITY Affinity)
+{
+ return 0;
+}
+
+
+static ULONG STDCALL
+HalpNoTranslateBusAddress(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ PHYSICAL_ADDRESS BusAddress,
+ PULONG AddressSpace,
+ PPHYSICAL_ADDRESS TranslatedAddress)
+{
+ return 0;
+}
+
+
+PBUS_HANDLER
+HalpAllocateBusHandler(INTERFACE_TYPE InterfaceType,
+ BUS_DATA_TYPE BusDataType,
+ ULONG BusNumber)
+{
+ PBUS_HANDLER BusHandler = NULL;
+
+ DPRINT("HalpAllocateBusHandler()\n");
+
+ BusHandler = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(BUS_HANDLER),
+ TAG_BUS);
+ if (BusHandler == NULL)
+ return NULL;
+
+ RtlZeroMemory(BusHandler,
+ sizeof(BUS_HANDLER));
+
+ InsertTailList(&HalpBusHandlerList,
+ &BusHandler->Entry);
+
+ BusHandler->InterfaceType = InterfaceType;
+ BusHandler->BusDataType = BusDataType;
+ BusHandler->BusNumber = BusNumber;
+
+ /* initialize default bus handler functions */
+ BusHandler->GetBusData = HalpNoBusData;
+ BusHandler->SetBusData = HalpNoBusData;
+ BusHandler->AdjustResourceList = HalpNoAdjustResourceList;
+ BusHandler->AssignSlotResources = HalpNoAssignSlotResources;
+ BusHandler->GetInterruptVector = HalpNoGetInterruptVector;
+ BusHandler->TranslateBusAddress = HalpNoTranslateBusAddress;
+
+ /* any more ?? */
+
+ DPRINT("HalpAllocateBusHandler() done\n");
+
+ return BusHandler;
+}
+
+
+VOID
+HalpInitBusHandlers(VOID)
+{
+ PBUS_HANDLER BusHandler;
+
+ /* General preparations */
+ KeInitializeSpinLock(&HalpBusHandlerSpinLock);
+ InitializeListHead(&HalpBusHandlerList);
+
+ /* Initialize hal dispatch tables */
+ HalQuerySystemInformation = HalpQuerySystemInformation;
+
+#if 0
+ HalSetSystemInformation = HalpSetSystemInformation;
+
+ HalQueryBusSlots = HalpQueryBusSlots;
+#endif
+
+ /* Add system bus handler */
+ BusHandler = HalpAllocateBusHandler(Internal,
+ ConfigurationSpaceUndefined,
+ 0);
+ if (BusHandler == NULL)
+ return;
+ BusHandler->GetInterruptVector =
+ (pGetInterruptVector)HalpGetSystemInterruptVector;
+ BusHandler->TranslateBusAddress =
+ (pTranslateBusAddress)HalpTranslateSystemBusAddress;
+
+ /* Add cmos bus handler */
+ BusHandler = HalpAllocateBusHandler(InterfaceTypeUndefined,
+ Cmos,
+ 0);
+ if (BusHandler == NULL)
+ return;
+ BusHandler->GetBusData = (pGetSetBusData)HalpGetCmosData;
+ BusHandler->SetBusData = (pGetSetBusData)HalpSetCmosData;
+
+ /* Add isa bus handler */
+ BusHandler = HalpAllocateBusHandler(Isa,
+ ConfigurationSpaceUndefined,
+ 0);
+ if (BusHandler == NULL)
+ return;
+
+ BusHandler->GetInterruptVector =
+ (pGetInterruptVector)HalpGetIsaInterruptVector;
+ BusHandler->TranslateBusAddress =
+ (pTranslateBusAddress)HalpTranslateIsaBusAddress;
+
+ /* Add MicroChannel bus handler */
+ BusHandler = HalpAllocateBusHandler(MicroChannel,
+ Pos,
+ 0);
+ if (BusHandler == NULL)
+ return;
+
+ BusHandler->GetBusData = (pGetSetBusData)HalpGetMicroChannelData;
+}
+
+
+PBUS_HANDLER FASTCALL
+HaliHandlerForBus(INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber)
+{
+ PBUS_HANDLER BusHandler;
+ PLIST_ENTRY CurrentEntry;
+ KIRQL OldIrql;
+
+ KeAcquireSpinLock(&HalpBusHandlerSpinLock,
+ &OldIrql);
+
+ CurrentEntry = HalpBusHandlerList.Flink;
+ while (CurrentEntry != &HalpBusHandlerList)
+ {
+ BusHandler = (PBUS_HANDLER)CurrentEntry;
+ if (BusHandler->InterfaceType == InterfaceType &&
+ BusHandler->BusNumber == BusNumber)
+ {
+ KeReleaseSpinLock(&HalpBusHandlerSpinLock,
+ OldIrql);
+ return BusHandler;
+ }
+ CurrentEntry = CurrentEntry->Flink;
+ }
+ KeReleaseSpinLock(&HalpBusHandlerSpinLock,
+ OldIrql);
+
+ return NULL;
+}
+
+
+PBUS_HANDLER FASTCALL
+HaliHandlerForConfigSpace(BUS_DATA_TYPE BusDataType,
+ ULONG BusNumber)
+{
+ PBUS_HANDLER BusHandler;
+ PLIST_ENTRY CurrentEntry;
+ KIRQL OldIrql;
+
+ KeAcquireSpinLock(&HalpBusHandlerSpinLock,
+ &OldIrql);
+
+ CurrentEntry = HalpBusHandlerList.Flink;
+ while (CurrentEntry != &HalpBusHandlerList)
+ {
+ BusHandler = (PBUS_HANDLER)CurrentEntry;
+ if (BusHandler->BusDataType == BusDataType &&
+ BusHandler->BusNumber == BusNumber)
+ {
+ KeReleaseSpinLock(&HalpBusHandlerSpinLock,
+ OldIrql);
+ return BusHandler;
+ }
+ CurrentEntry = CurrentEntry->Flink;
+ }
+ KeReleaseSpinLock(&HalpBusHandlerSpinLock,
+ OldIrql);
+
+ return NULL;
+}
+
+
+PBUS_HANDLER FASTCALL
+HaliReferenceHandlerForBus(INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber)
+{
+ PBUS_HANDLER BusHandler;
+ PLIST_ENTRY CurrentEntry;
+ KIRQL OldIrql;
+
+ KeAcquireSpinLock(&HalpBusHandlerSpinLock,
+ &OldIrql);
+
+ CurrentEntry = HalpBusHandlerList.Flink;
+ while (CurrentEntry != &HalpBusHandlerList)
+ {
+ BusHandler = (PBUS_HANDLER)CurrentEntry;
+ if (BusHandler->InterfaceType == InterfaceType &&
+ BusHandler->BusNumber == BusNumber)
+ {
+ BusHandler->RefCount++;
+ KeReleaseSpinLock(&HalpBusHandlerSpinLock,
+ OldIrql);
+ return BusHandler;
+ }
+ CurrentEntry = CurrentEntry->Flink;
+ }
+ KeReleaseSpinLock(&HalpBusHandlerSpinLock,
+ OldIrql);
+
+ return NULL;
+}
+
+
+PBUS_HANDLER FASTCALL
+HaliReferenceHandlerForConfigSpace(BUS_DATA_TYPE BusDataType,
+ ULONG BusNumber)
+{
+ PBUS_HANDLER BusHandler;
+ PLIST_ENTRY CurrentEntry;
+ KIRQL OldIrql;
+
+ KeAcquireSpinLock(&HalpBusHandlerSpinLock,
+ &OldIrql);
+
+ CurrentEntry = HalpBusHandlerList.Flink;
+ while (CurrentEntry != &HalpBusHandlerList)
+ {
+ BusHandler = (PBUS_HANDLER)CurrentEntry;
+ if (BusHandler->BusDataType == BusDataType &&
+ BusHandler->BusNumber == BusNumber)
+ {
+ BusHandler->RefCount++;
+ KeReleaseSpinLock(&HalpBusHandlerSpinLock,
+ OldIrql);
+ return BusHandler;
+ }
+ CurrentEntry = CurrentEntry->Flink;
+ }
+ KeReleaseSpinLock(&HalpBusHandlerSpinLock,
+ OldIrql);
+
+ return NULL;
+}
+
+
+VOID FASTCALL
+HaliDereferenceBusHandler(PBUS_HANDLER BusHandler)
+{
+ KIRQL OldIrql;
+
+ KeAcquireSpinLock(&HalpBusHandlerSpinLock,
+ &OldIrql);
+ BusHandler->RefCount--;
+ KeReleaseSpinLock(&HalpBusHandlerSpinLock,
+ OldIrql);
+}
+
+
+NTSTATUS STDCALL
+HalAdjustResourceList(PCM_RESOURCE_LIST Resources)
+{
+ PBUS_HANDLER BusHandler;
+ NTSTATUS Status;
+
+ BusHandler = HaliReferenceHandlerForBus(Resources->List[0].InterfaceType,
+ Resources->List[0].BusNumber);
+ if (BusHandler == NULL)
+ return STATUS_SUCCESS;
+
+ Status = BusHandler->AdjustResourceList(BusHandler,
+ Resources->List[0].BusNumber,
+ Resources);
+ HaliDereferenceBusHandler (BusHandler);
+
+ return Status;
+}
+
+
+NTSTATUS STDCALL
+HalAssignSlotResources(PUNICODE_STRING RegistryPath,
+ PUNICODE_STRING DriverClassName,
+ PDRIVER_OBJECT DriverObject,
+ PDEVICE_OBJECT DeviceObject,
+ INTERFACE_TYPE BusType,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PCM_RESOURCE_LIST *AllocatedResources)
+{
+ PBUS_HANDLER BusHandler;
+ NTSTATUS Status;
+
+ BusHandler = HaliReferenceHandlerForBus(BusType,
+ BusNumber);
+ if (BusHandler == NULL)
+ return STATUS_NOT_FOUND;
+
+ Status = BusHandler->AssignSlotResources(BusHandler,
+ BusNumber,
+ RegistryPath,
+ DriverClassName,
+ DriverObject,
+ DeviceObject,
+ SlotNumber,
+ AllocatedResources);
+
+ HaliDereferenceBusHandler(BusHandler);
+
+ return Status;
+}
+
+
+ULONG STDCALL
+HalGetBusData(BUS_DATA_TYPE BusDataType,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Length)
+{
+ return (HalGetBusDataByOffset(BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length));
+}
+
+
+ULONG STDCALL
+HalGetBusDataByOffset(BUS_DATA_TYPE BusDataType,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length)
+{
+ PBUS_HANDLER BusHandler;
+ ULONG Result;
+
+ BusHandler = HaliReferenceHandlerForConfigSpace(BusDataType,
+ BusNumber);
+ if (BusHandler == NULL)
+ return 0;
+
+ Result = BusHandler->GetBusData(BusHandler,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length);
+
+ HaliDereferenceBusHandler (BusHandler);
+
+ return Result;
+}
+
+
+ULONG STDCALL
+HalGetInterruptVector(INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber,
+ ULONG BusInterruptLevel,
+ ULONG BusInterruptVector,
+ PKIRQL Irql,
+ PKAFFINITY Affinity)
+{
+ PBUS_HANDLER BusHandler;
+ ULONG Result;
+
+ BusHandler = HaliReferenceHandlerForBus(InterfaceType,
+ BusNumber);
+ if (BusHandler == NULL)
+ return 0;
+
+ Result = BusHandler->GetInterruptVector(BusHandler,
+ BusNumber,
+ BusInterruptLevel,
+ BusInterruptVector,
+ Irql,
+ Affinity);
+
+ HaliDereferenceBusHandler(BusHandler);
+
+ return Result;
+}
+
+
+ULONG STDCALL
+HalSetBusData(BUS_DATA_TYPE BusDataType,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Length)
+{
+ return (HalSetBusDataByOffset(BusDataType,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ 0,
+ Length));
+}
+
+
+ULONG STDCALL
+HalSetBusDataByOffset(BUS_DATA_TYPE BusDataType,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length)
+{
+ PBUS_HANDLER BusHandler;
+ ULONG Result;
+
+ BusHandler = HaliReferenceHandlerForConfigSpace(BusDataType,
+ BusNumber);
+ if (BusHandler == NULL)
+ return 0;
+
+ Result = BusHandler->SetBusData(BusHandler,
+ BusNumber,
+ SlotNumber,
+ Buffer,
+ Offset,
+ Length);
+
+ HaliDereferenceBusHandler(BusHandler);
+
+ return Result;
+}
+
+
+BOOLEAN STDCALL
+HalTranslateBusAddress(INTERFACE_TYPE InterfaceType,
+ ULONG BusNumber,
+ PHYSICAL_ADDRESS BusAddress,
+ PULONG AddressSpace,
+ PPHYSICAL_ADDRESS TranslatedAddress)
+{
+ PBUS_HANDLER BusHandler;
+ BOOLEAN Result;
+
+ BusHandler = HaliReferenceHandlerForBus(InterfaceType,
+ BusNumber);
+ if (BusHandler == NULL)
+ return FALSE;
+
+ Result = (BOOLEAN)BusHandler->TranslateBusAddress(BusHandler,
+ BusNumber,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress);
+
+ HaliDereferenceBusHandler(BusHandler);
+
+ return Result;
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/display.c b/reactos/hal/halppc/generic/display.c
new file mode 100644
index 00000000000..1874de23331
--- /dev/null
+++ b/reactos/hal/halppc/generic/display.c
@@ -0,0 +1,796 @@
+/*
+ * ReactOS kernel
+ * Copyright (C) 1998, 1999, 2000, 2001, 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: display.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/display.c
+ * PURPOSE: Blue screen display
+ * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
+ * UPDATE HISTORY:
+ * Created 08/10/99
+ */
+
+/*
+ * Portions of this code are from the XFree86 Project and available from the
+ * following license:
+ *
+ * Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
+ * NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the XFree86 Project shall
+ * not be used in advertising or otherwise to promote the sale, use or other
+ * dealings in this Software without prior written authorization from the
+ * XFree86 Project.
+*/
+
+/* DISPLAY OWNERSHIP
+ *
+ * So, who owns the physical display and is allowed to write to it?
+ *
+ * In MS NT, upon boot HAL owns the display. Somewhere in the boot
+ * sequence (haven't figured out exactly where or by who), some
+ * component calls HalAcquireDisplayOwnership. From that moment on,
+ * the display is owned by that component and is switched to graphics
+ * mode. The display is not supposed to return to text mode, except
+ * in case of a bug check. The bug check will call HalDisplayString
+ * to output a string to the text screen. HAL will notice that it
+ * currently doesn't own the display and will re-take ownership, by
+ * calling the callback function passed to HalAcquireDisplayOwnership.
+ * After the bugcheck, execution is halted. So, under NT, the only
+ * possible sequence of display modes is text mode -> graphics mode ->
+ * text mode (the latter hopefully happening very infrequently).
+ *
+ * Things are a little bit different in the current state of ReactOS.
+ * We want to have a functional interactive text mode. We should be
+ * able to switch from text mode to graphics mode when a GUI app is
+ * started and switch back to text mode when it's finished. Then, when
+ * another GUI app is started, another switch to and from graphics mode
+ * is possible. Also, when the system bugchecks in graphics mode we want
+ * to switch back to text mode to show the registers and stack trace.
+ * Last but not least, HalDisplayString is used a lot more in ReactOS,
+ * e.g. to print debug messages when the /DEBUGPORT=SCREEN boot option
+ * is present.
+ * 3 Components are involved in Reactos: HAL, BLUE.SYS and VIDEOPRT.SYS.
+ * As in NT, on boot HAL owns the display. When entering the text mode
+ * command interpreter, BLUE.SYS kicks in. It will write directly to the
+ * screen, more or less behind HALs back.
+ * When a GUI app is started, WIN32K.SYS will open the DISPLAY device.
+ * This open call will end up in VIDEOPRT.SYS. That component will then
+ * take ownership of the display by calling HalAcquireDisplayOwnership.
+ * When the GUI app terminates (WIN32K.SYS will close the DISPLAY device),
+ * we want to give ownership of the display back to HAL. Using the
+ * standard exported HAL functions, that's a bit of a problem, because
+ * there is no function defined to do that. In NT, this is handled by
+ * HalDisplayString, but that solution isn't satisfactory in ReactOS,
+ * because HalDisplayString is (in some cases) also used to output debug
+ * messages. If we do it the NT way, the first debug message output while
+ * in graphics mode would switch the display back to text mode.
+ * So, instead, if HalDisplayString detects that HAL doesn't have ownership
+ * of the display, it doesn't do anything.
+ * To return ownership to HAL, a new function is exported,
+ * HalReleaseDisplayOwnership. This function is called by the DISPLAY
+ * device Close routine in VIDEOPRT.SYS. It is also called at the beginning
+ * of a bug check, so HalDisplayString is activated again.
+ * Now, while the display is in graphics mode (not owned by HAL), BLUE.SYS
+ * should also refrain from writing to the screen buffer. The text mode
+ * screen buffer might overlap the graphics mode screen buffer, so changing
+ * something in the text mode buffer might mess up the graphics screen. To
+ * allow BLUE.SYS to detect if HAL owns the display, another new function is
+ * exported, HalQueryDisplayOwnership. BLUE.SYS will call this function to
+ * check if it's allowed to touch the text mode buffer.
+ *
+ * In an ideal world, when HAL takes ownership of the display, it should set
+ * up the CRT using real-mode (actually V86 mode, but who cares) INT 0x10
+ * calls. Unfortunately, this will require HAL to setup a real-mode interrupt
+ * table etc. So, we chickened out of that by having the loader set up the
+ * display before switching to protected mode. If HAL is given back ownership
+ * after a GUI app terminates, the INT 0x10 calls are made by VIDEOPRT.SYS,
+ * since there is already support for them via the VideoPortInt10 routine.
+ */
+
+#include
+#define NDEBUG
+#include
+
+
+#define SCREEN_SYNCHRONIZATION
+
+#define VGA_GRAPH_MEM 0xa0000
+#define VGA_CHAR_MEM 0xb8000
+#define VGA_END_MEM 0xbffff
+
+#define VGA_AC_INDEX 0x3c0
+#define VGA_AC_READ 0x3c1
+#define VGA_AC_WRITE 0x3c0
+
+#define VGA_MISC_WRITE 0x3c2
+
+#define VGA_SEQ_INDEX 0x3c4
+#define VGA_SEQ_DATA 0x3c5
+
+#define VGA_DAC_MASK 0x3c6
+#define VGA_DAC_READ_INDEX 0x3c7
+#define VGA_DAC_WRITE_INDEX 0x3c8
+#define VGA_DAC_DATA 0x3c9
+#define VGA_FEATURE_READ 0x3ca
+#define VGA_MISC_READ 0x3cc
+
+#define VGA_GC_INDEX 0x3ce
+#define VGA_GC_DATA 0x3cf
+
+#define VGA_CRTC_INDEX 0x3d4
+#define VGA_CRTC_DATA 0x3d5
+
+#define VGA_INSTAT_READ 0x3da
+
+#define VGA_SEQ_NUM_REGISTERS 5
+#define VGA_CRTC_NUM_REGISTERS 25
+#define VGA_GC_NUM_REGISTERS 9
+#define VGA_AC_NUM_REGISTERS 21
+
+#define CRTC_COLUMNS 0x01
+#define CRTC_OVERFLOW 0x07
+#define CRTC_ROWS 0x12
+#define CRTC_SCANLINES 0x09
+
+#define CRTC_CURHI 0x0e
+#define CRTC_CURLO 0x0f
+
+
+#define CHAR_ATTRIBUTE_BLACK 0x00 /* black on black */
+#define CHAR_ATTRIBUTE 0x17 /* grey on blue */
+
+#define FONT_AMOUNT (8*8192)
+
+/* VARIABLES ****************************************************************/
+
+static ULONG CursorX = 0; /* Cursor Position */
+static ULONG CursorY = 0;
+static ULONG SizeX = 80; /* Display size */
+static ULONG SizeY = 25;
+
+static BOOLEAN DisplayInitialized = FALSE;
+static BOOLEAN HalOwnsDisplay = TRUE;
+
+static PUSHORT VideoBuffer = NULL;
+static PUCHAR GraphVideoBuffer = NULL;
+
+static PHAL_RESET_DISPLAY_PARAMETERS HalResetDisplayParameters = NULL;
+
+static UCHAR SavedTextPalette[768];
+static UCHAR SavedTextMiscOutReg;
+static UCHAR SavedTextCrtcReg[VGA_CRTC_NUM_REGISTERS];
+static UCHAR SavedTextAcReg[VGA_AC_NUM_REGISTERS];
+static UCHAR SavedTextGcReg[VGA_GC_NUM_REGISTERS];
+static UCHAR SavedTextSeqReg[VGA_SEQ_NUM_REGISTERS];
+static UCHAR SavedTextFont[2][FONT_AMOUNT];
+static BOOLEAN TextPaletteEnabled = FALSE;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID FASTCALL
+HalClearDisplay (UCHAR CharAttribute)
+{
+ WORD *ptr = (WORD*)VideoBuffer;
+ ULONG i;
+
+ for (i = 0; i < SizeX * SizeY; i++, ptr++)
+ *ptr = ((CharAttribute << 8) + ' ');
+
+ CursorX = 0;
+ CursorY = 0;
+}
+
+
+/* STATIC FUNCTIONS *********************************************************/
+
+VOID STATIC
+HalScrollDisplay (VOID)
+{
+ PUSHORT ptr;
+ int i;
+
+ ptr = VideoBuffer + SizeX;
+ RtlMoveMemory(VideoBuffer,
+ ptr,
+ SizeX * (SizeY - 1) * 2);
+
+ ptr = VideoBuffer + (SizeX * (SizeY - 1));
+ for (i = 0; i < (int)SizeX; i++, ptr++)
+ {
+ *ptr = (CHAR_ATTRIBUTE << 8) + ' ';
+ }
+}
+
+VOID STATIC FASTCALL
+HalPutCharacter (CHAR Character)
+{
+ PUSHORT ptr;
+
+ ptr = VideoBuffer + ((CursorY * SizeX) + CursorX);
+ *ptr = (CHAR_ATTRIBUTE << 8) + Character;
+}
+
+VOID STATIC
+HalDisablePalette(VOID)
+{
+ (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, 0x20);
+ TextPaletteEnabled = FALSE;
+}
+
+VOID STATIC
+HalEnablePalette(VOID)
+{
+ (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, 0x00);
+ TextPaletteEnabled = TRUE;
+}
+
+UCHAR STATIC FASTCALL
+HalReadGc(ULONG Index)
+{
+ WRITE_PORT_UCHAR((PUCHAR)VGA_GC_INDEX, (UCHAR)Index);
+ return(READ_PORT_UCHAR((PUCHAR)VGA_GC_DATA));
+}
+
+VOID STATIC FASTCALL
+HalWriteGc(ULONG Index, UCHAR Value)
+{
+ WRITE_PORT_UCHAR((PUCHAR)VGA_GC_INDEX, (UCHAR)Index);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_GC_DATA, Value);
+}
+
+UCHAR STATIC FASTCALL
+HalReadSeq(ULONG Index)
+{
+ WRITE_PORT_UCHAR((PUCHAR)VGA_SEQ_INDEX, (UCHAR)Index);
+ return(READ_PORT_UCHAR((PUCHAR)VGA_SEQ_DATA));
+}
+
+VOID STATIC FASTCALL
+HalWriteSeq(ULONG Index, UCHAR Value)
+{
+ WRITE_PORT_UCHAR((PUCHAR)VGA_SEQ_INDEX, (UCHAR)Index);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_SEQ_DATA, Value);
+}
+
+VOID STATIC FASTCALL
+HalWriteAc(ULONG Index, UCHAR Value)
+{
+ if (TextPaletteEnabled)
+ {
+ Index &= ~0x20;
+ }
+ else
+ {
+ Index |= 0x20;
+ }
+ (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, (UCHAR)Index);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_AC_WRITE, Value);
+}
+
+UCHAR STATIC FASTCALL
+HalReadAc(ULONG Index)
+{
+ if (TextPaletteEnabled)
+ {
+ Index &= ~0x20;
+ }
+ else
+ {
+ Index |= 0x20;
+ }
+ (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_AC_INDEX, (UCHAR)Index);
+ return(READ_PORT_UCHAR((PUCHAR)VGA_AC_READ));
+}
+
+VOID STATIC FASTCALL
+HalWriteCrtc(ULONG Index, UCHAR Value)
+{
+ WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, (UCHAR)Index);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA, Value);
+}
+
+UCHAR STATIC FASTCALL
+HalReadCrtc(ULONG Index)
+{
+ WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, (UCHAR)Index);
+ return(READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA));
+}
+
+VOID STATIC FASTCALL
+HalResetSeq(BOOLEAN Start)
+{
+ if (Start)
+ {
+ HalWriteSeq(0x00, 0x01);
+ }
+ else
+ {
+ HalWriteSeq(0x00, 0x03);
+ }
+}
+
+VOID STATIC FASTCALL
+HalBlankScreen(BOOLEAN On)
+{
+ UCHAR Scrn;
+
+ Scrn = HalReadSeq(0x01);
+
+ if (On)
+ {
+ Scrn &= ~0x20;
+ }
+ else
+ {
+ Scrn |= 0x20;
+ }
+
+ HalResetSeq(TRUE);
+ HalWriteSeq(0x01, Scrn);
+ HalResetSeq(FALSE);
+}
+
+VOID STATIC
+HalSaveFont(VOID)
+{
+ UCHAR Attr10;
+ UCHAR MiscOut, Gc4, Gc5, Gc6, Seq2, Seq4;
+ ULONG i;
+
+ /* Check if we are already in graphics mode. */
+ Attr10 = HalReadAc(0x10);
+ if (Attr10 & 0x01)
+ {
+ return;
+ }
+
+ /* Save registers. */
+ MiscOut = READ_PORT_UCHAR((PUCHAR)VGA_MISC_READ);
+ Gc4 = HalReadGc(0x04);
+ Gc5 = HalReadGc(0x05);
+ Gc6 = HalReadGc(0x06);
+ Seq2 = HalReadSeq(0x02);
+ Seq4 = HalReadSeq(0x04);
+
+ /* Force colour mode. */
+ WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, (UCHAR)(MiscOut | 0x01));
+
+ HalBlankScreen(FALSE);
+
+ for (i = 0; i < 2; i++)
+ {
+ /* Save font 1 */
+ HalWriteSeq(0x02, (UCHAR)(0x04 << i)); /* Write to plane 2 or 3 */
+ HalWriteSeq(0x04, 0x06); /* Enable plane graphics. */
+ HalWriteGc(0x04, (UCHAR)(0x02 + i)); /* Read plane 2 or 3 */
+ HalWriteGc(0x05, 0x00); /* Write mode 0; read mode 0 */
+ HalWriteGc(0x06, 0x05); /* Set graphics. */
+ memcpy(SavedTextFont[i], GraphVideoBuffer, FONT_AMOUNT);
+ }
+
+ /* Restore registers. */
+ HalWriteAc(0x10, Attr10);
+ HalWriteSeq(0x02, Seq2);
+ HalWriteSeq(0x04, Seq4);
+ HalWriteGc(0x04, Gc4);
+ HalWriteGc(0x05, Gc5);
+ HalWriteGc(0x06, Gc6);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, MiscOut);
+
+ HalBlankScreen(TRUE);
+}
+
+VOID STATIC
+HalSaveMode(VOID)
+{
+ ULONG i;
+
+ SavedTextMiscOutReg = READ_PORT_UCHAR((PUCHAR)VGA_MISC_READ);
+
+ for (i = 0; i < VGA_CRTC_NUM_REGISTERS; i++)
+ {
+ SavedTextCrtcReg[i] = HalReadCrtc(i);
+ }
+
+ HalEnablePalette();
+ for (i = 0; i < VGA_AC_NUM_REGISTERS; i++)
+ {
+ SavedTextAcReg[i] = HalReadAc(i);
+ }
+ HalDisablePalette();
+
+ for (i = 0; i < VGA_GC_NUM_REGISTERS; i++)
+ {
+ SavedTextGcReg[i] = HalReadGc(i);
+ }
+
+ for (i = 0; i < VGA_SEQ_NUM_REGISTERS; i++)
+ {
+ SavedTextSeqReg[i] = HalReadSeq(i);
+ }
+}
+
+VOID STATIC
+HalDacDelay(VOID)
+{
+ (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
+ (VOID)READ_PORT_UCHAR((PUCHAR)VGA_INSTAT_READ);
+}
+
+VOID STATIC
+HalSavePalette(VOID)
+{
+ ULONG i;
+ WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_MASK, 0xFF);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_READ_INDEX, 0x00);
+ for (i = 0; i < 768; i++)
+ {
+ SavedTextPalette[i] = READ_PORT_UCHAR((PUCHAR)VGA_DAC_DATA);
+ HalDacDelay();
+ }
+}
+
+VOID STATIC
+HalRestoreFont(VOID)
+{
+ UCHAR MiscOut, Attr10, Gc1, Gc3, Gc4, Gc5, Gc6, Gc8;
+ UCHAR Seq2, Seq4;
+ ULONG i;
+
+ /* Save registers. */
+ MiscOut = READ_PORT_UCHAR((PUCHAR)VGA_MISC_READ);
+ Attr10 = HalReadAc(0x10);
+ Gc1 = HalReadGc(0x01);
+ Gc3 = HalReadGc(0x03);
+ Gc4 = HalReadGc(0x04);
+ Gc5 = HalReadGc(0x05);
+ Gc6 = HalReadGc(0x06);
+ Gc8 = HalReadGc(0x08);
+ Seq2 = HalReadSeq(0x02);
+ Seq4 = HalReadSeq(0x04);
+
+ /* Force into colour mode. */
+ WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, (UCHAR)(MiscOut | 0x10));
+
+ HalBlankScreen(FALSE);
+
+ HalWriteGc(0x03, 0x00); /* Don't rotate; write unmodified. */
+ HalWriteGc(0x08, 0xFF); /* Write all bits. */
+ HalWriteGc(0x01, 0x00); /* All planes from CPU. */
+
+ for (i = 0; i < 2; i++)
+ {
+ HalWriteSeq(0x02, (UCHAR)(0x04 << i)); /* Write to plane 2 or 3 */
+ HalWriteSeq(0x04, 0x06); /* Enable plane graphics. */
+ HalWriteGc(0x04, (UCHAR)(0x02 + i)); /* Read plane 2 or 3 */
+ HalWriteGc(0x05, 0x00); /* Write mode 0; read mode 0. */
+ HalWriteGc(0x06, 0x05); /* Set graphics. */
+ memcpy(GraphVideoBuffer, SavedTextFont[i], FONT_AMOUNT);
+ }
+
+ HalBlankScreen(TRUE);
+
+ /* Restore registers. */
+ WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, MiscOut);
+ HalWriteAc(0x10, Attr10);
+ HalWriteGc(0x01, Gc1);
+ HalWriteGc(0x03, Gc3);
+ HalWriteGc(0x04, Gc4);
+ HalWriteGc(0x05, Gc5);
+ HalWriteGc(0x06, Gc6);
+ HalWriteGc(0x08, Gc8);
+ HalWriteSeq(0x02, Seq2);
+ HalWriteSeq(0x04, Seq4);
+}
+
+VOID STATIC
+HalRestoreMode(VOID)
+{
+ ULONG i;
+
+ WRITE_PORT_UCHAR((PUCHAR)VGA_MISC_WRITE, SavedTextMiscOutReg);
+
+ for (i = 1; i < VGA_SEQ_NUM_REGISTERS; i++)
+ {
+ HalWriteSeq(i, SavedTextSeqReg[i]);
+ }
+
+ /* Unlock CRTC registers 0-7 */
+ HalWriteCrtc(17, (UCHAR)(SavedTextCrtcReg[17] & ~0x80));
+
+ for (i = 0; i < VGA_CRTC_NUM_REGISTERS; i++)
+ {
+ HalWriteCrtc(i, SavedTextCrtcReg[i]);
+ }
+
+ for (i = 0; i < VGA_GC_NUM_REGISTERS; i++)
+ {
+ HalWriteGc(i, SavedTextGcReg[i]);
+ }
+
+ HalEnablePalette();
+ for (i = 0; i < VGA_AC_NUM_REGISTERS; i++)
+ {
+ HalWriteAc(i, SavedTextAcReg[i]);
+ }
+ HalDisablePalette();
+}
+
+VOID STATIC
+HalRestorePalette(VOID)
+{
+ ULONG i;
+ WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_MASK, 0xFF);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_WRITE_INDEX, 0x00);
+ for (i = 0; i < 768; i++)
+ {
+ WRITE_PORT_UCHAR((PUCHAR)VGA_DAC_DATA, SavedTextPalette[i]);
+ HalDacDelay();
+ }
+ HalDisablePalette();
+}
+
+/* PRIVATE FUNCTIONS ********************************************************/
+
+VOID FASTCALL
+HalInitializeDisplay (PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
+/*
+ * FUNCTION: Initalize the display
+ * ARGUMENTS:
+ * InitParameters = Parameters setup by the boot loader
+ */
+{
+ PHYSICAL_ADDRESS PhysBuffer;
+
+ if (! DisplayInitialized)
+ {
+ ULONG ScanLines;
+ ULONG Data;
+
+ PhysBuffer.u.HighPart = 0;
+ PhysBuffer.u.LowPart = VGA_GRAPH_MEM;
+ GraphVideoBuffer = MmMapIoSpace(PhysBuffer, VGA_END_MEM - VGA_GRAPH_MEM + 1, MmNonCached);
+ if (NULL == GraphVideoBuffer)
+ {
+ return;
+ }
+ VideoBuffer = (PUSHORT) (GraphVideoBuffer + (VGA_CHAR_MEM - VGA_GRAPH_MEM));
+
+ /* Set cursor position */
+// CursorX = LoaderBlock->cursorx;
+// CursorY = LoaderBlock->cursory;
+ CursorX = 0;
+ CursorY = 0;
+
+ /* read screen size from the crtc */
+ /* FIXME: screen size should be read from the boot parameters */
+ WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_COLUMNS);
+ SizeX = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA) + 1;
+ WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_ROWS);
+ SizeY = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_OVERFLOW);
+ Data = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA);
+ SizeY |= (((Data & 0x02) << 7) | ((Data & 0x40) << 3));
+ SizeY++;
+ WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_SCANLINES);
+ ScanLines = (READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA) & 0x1F) + 1;
+ SizeY = SizeY / ScanLines;
+
+#ifdef BOCHS_30ROWS
+ SizeY=30;
+#endif
+ HalClearDisplay(CHAR_ATTRIBUTE_BLACK);
+
+ DisplayInitialized = TRUE;
+
+ /*
+ Save the VGA state at this point so we can restore it on a bugcheck.
+ */
+ HalSavePalette();
+ HalSaveMode();
+ HalSaveFont();
+ }
+}
+
+
+/* PUBLIC FUNCTIONS *********************************************************/
+
+VOID STDCALL
+HalReleaseDisplayOwnership(VOID)
+/*
+ * FUNCTION: Release ownership of display back to HAL
+ */
+{
+ if (HalResetDisplayParameters == NULL)
+ return;
+
+ if (HalOwnsDisplay == TRUE)
+ return;
+
+ if (!HalResetDisplayParameters(SizeX, SizeY))
+ {
+ HalRestoreMode();
+ HalRestoreFont();
+ HalRestorePalette();
+ }
+ HalOwnsDisplay = TRUE;
+ HalClearDisplay(CHAR_ATTRIBUTE);
+}
+
+
+VOID STDCALL
+HalAcquireDisplayOwnership(IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters)
+/*
+ * FUNCTION:
+ * ARGUMENTS:
+ * ResetDisplayParameters = Pointer to a driver specific
+ * reset routine.
+ */
+{
+ HalOwnsDisplay = FALSE;
+ HalResetDisplayParameters = ResetDisplayParameters;
+}
+
+VOID STDCALL
+HalDisplayString(IN PCH String)
+/*
+ * FUNCTION: Switches the screen to HAL console mode (BSOD) if not there
+ * already and displays a string
+ * ARGUMENT:
+ * string = ASCII string to display
+ * NOTE: Use with care because there is no support for returning from BSOD
+ * mode
+ */
+{
+ PCH pch;
+#ifdef SCREEN_SYNCHRONIZATION
+ int offset;
+#endif
+ static KSPIN_LOCK Lock;
+ KIRQL OldIrql;
+ ULONG Flags;
+
+ /* See comment at top of file */
+ if (! HalOwnsDisplay || ! DisplayInitialized)
+ {
+ return;
+ }
+
+ pch = String;
+
+ OldIrql = KfRaiseIrql(HIGH_LEVEL);
+ KiAcquireSpinLock(&Lock);
+
+ Ki386SaveFlags(Flags);
+ Ki386DisableInterrupts();
+
+#ifdef SCREEN_SYNCHRONIZATION
+ WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURHI);
+ offset = READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA)<<8;
+ WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURLO);
+ offset += READ_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA);
+
+ CursorY = offset / SizeX;
+ CursorX = offset % SizeX;
+#endif
+
+ while (*pch != 0)
+ {
+ if (*pch == '\n')
+ {
+ CursorY++;
+ CursorX = 0;
+ }
+ else if (*pch == '\b')
+ {
+ if (CursorX > 0)
+ {
+ CursorX--;
+ }
+ }
+ else if (*pch != '\r')
+ {
+ HalPutCharacter (*pch);
+ CursorX++;
+
+ if (CursorX >= SizeX)
+ {
+ CursorY++;
+ CursorX = 0;
+ }
+ }
+
+ if (CursorY >= SizeY)
+ {
+ HalScrollDisplay ();
+ CursorY = SizeY - 1;
+ }
+
+ pch++;
+ }
+
+#ifdef SCREEN_SYNCHRONIZATION
+ offset = (CursorY * SizeX) + CursorX;
+
+ WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURLO);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA, (UCHAR)(offset & 0xff));
+ WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_INDEX, CRTC_CURHI);
+ WRITE_PORT_UCHAR((PUCHAR)VGA_CRTC_DATA, (UCHAR)((offset >> 8) & 0xff));
+#endif
+ Ki386RestoreFlags(Flags);
+
+ KiReleaseSpinLock(&Lock);
+ KfLowerIrql(OldIrql);
+}
+
+VOID STDCALL
+HalQueryDisplayParameters(OUT PULONG DispSizeX,
+ OUT PULONG DispSizeY,
+ OUT PULONG CursorPosX,
+ OUT PULONG CursorPosY)
+{
+ if (DispSizeX)
+ *DispSizeX = SizeX;
+ if (DispSizeY)
+ *DispSizeY = SizeY;
+ if (CursorPosX)
+ *CursorPosX = CursorX;
+ if (CursorPosY)
+ *CursorPosY = CursorY;
+}
+
+
+VOID STDCALL
+HalSetDisplayParameters(IN ULONG CursorPosX,
+ IN ULONG CursorPosY)
+{
+ CursorX = (CursorPosX < SizeX) ? CursorPosX : SizeX - 1;
+ CursorY = (CursorPosY < SizeY) ? CursorPosY : SizeY - 1;
+}
+
+
+BOOLEAN STDCALL
+HalQueryDisplayOwnership(VOID)
+{
+ return !HalOwnsDisplay;
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/dma.c b/reactos/hal/halppc/generic/dma.c
new file mode 100644
index 00000000000..a461d845004
--- /dev/null
+++ b/reactos/hal/halppc/generic/dma.c
@@ -0,0 +1,1950 @@
+/* $Id: dma.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/dma.c
+ * PURPOSE: DMA functions
+ * PROGRAMMERS: David Welch (welch@mcmail.com)
+ * Filip Navara (navaraf@reactos.com)
+ * UPDATE HISTORY:
+ * Created 22/05/98
+ */
+
+/**
+ * @page DMA Implementation Notes
+ *
+ * Concepts:
+ *
+ * - Map register
+ *
+ * Abstract encapsulation of physically contiguous buffer that resides
+ * in memory accessible by both the DMA device / controller and the system.
+ * The map registers are allocated and distributed on demand and are
+ * scarce resource.
+ *
+ * The actual use of map registers is to allow transfers from/to buffer
+ * located in physical memory at address inaccessible by the DMA device /
+ * controller directly. For such transfers the map register buffers
+ * are used as intermediate data storage.
+ *
+ * - Master adapter
+ *
+ * A container for map registers (typically corresponding to one physical
+ * bus connection type). There can be master adapters for 24-bit address
+ * ranges, 32-bit address ranges, etc. Every time a new DMA adapter is
+ * created it's associated with a corresponding master adapter that
+ * is used for any map register allocation requests.
+ *
+ * - Bus-master / Slave DMA
+ *
+ * Slave DMA is term used for DMA transfers done by the system (E)ISA
+ * controller as opposed to transfers mastered by the device itself
+ * (hence the name).
+ *
+ * For slave DMA special care is taken to actually access the system
+ * controller and handle the transfers. The relevant code is in
+ * HalpDmaInitializeEisaAdapter, HalReadDmaCounter, IoFlushAdapterBuffers
+ * and IoMapTransfer.
+ *
+ * Implementation:
+ *
+ * - Allocation of map registers
+ *
+ * Initial set of map registers is allocated on the system start to
+ * ensure that low memory won't get filled up later. Additional map
+ * registers are allocated as needed by HalpGrowMapBuffers. This
+ * routine is called on two places:
+ *
+ * - HalGetAdapter, since we're at PASSIVE_LEVEL and it's known that
+ * more map registers will probably be needed.
+ * - IoAllocateAdapterChannel (indirectly using HalpGrowMapBufferWorker
+ * since we're at DISPATCH_LEVEL and call HalpGrowMapBuffers directly)
+ * when no more map registers are free.
+ *
+ * Note that even if no more map registers can be allocated it's not
+ * the end of the world. The adapters waiting for free map registers
+ * are queued in the master adapter's queue and once one driver hands
+ * back it's map registers (using IoFreeMapRegisters or indirectly using
+ * the execution routine callback in IoAllocateAdapterChannel) the
+ * queue gets processed and the map registers are reassigned.
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+static KEVENT HalpDmaLock;
+static LIST_ENTRY HalpDmaAdapterList;
+static PADAPTER_OBJECT HalpEisaAdapter[8];
+static BOOLEAN HalpEisaDma;
+static PADAPTER_OBJECT HalpMasterAdapter;
+
+static const ULONG_PTR HalpEisaPortPage[8] = {
+ FIELD_OFFSET(DMA_PAGE, Channel0),
+ FIELD_OFFSET(DMA_PAGE, Channel1),
+ FIELD_OFFSET(DMA_PAGE, Channel2),
+ FIELD_OFFSET(DMA_PAGE, Channel3),
+ 0,
+ FIELD_OFFSET(DMA_PAGE, Channel5),
+ FIELD_OFFSET(DMA_PAGE, Channel6),
+ FIELD_OFFSET(DMA_PAGE, Channel7)
+};
+
+static DMA_OPERATIONS HalpDmaOperations = {
+ sizeof(DMA_OPERATIONS),
+ (PPUT_DMA_ADAPTER)HalPutDmaAdapter,
+ (PALLOCATE_COMMON_BUFFER)HalAllocateCommonBuffer,
+ (PFREE_COMMON_BUFFER)HalFreeCommonBuffer,
+ NULL, /* Initialized in HalpInitDma() */
+ NULL, /* Initialized in HalpInitDma() */
+ NULL, /* Initialized in HalpInitDma() */
+ NULL, /* Initialized in HalpInitDma() */
+ NULL, /* Initialized in HalpInitDma() */
+ (PGET_DMA_ALIGNMENT)HalpDmaGetDmaAlignment,
+ (PREAD_DMA_COUNTER)HalReadDmaCounter,
+ /* FIXME: Implement the S/G funtions. */
+ NULL /*(PGET_SCATTER_GATHER_LIST)HalGetScatterGatherList*/,
+ NULL /*(PPUT_SCATTER_GATHER_LIST)HalPutScatterGatherList*/,
+ NULL /*(PCALCULATE_SCATTER_GATHER_LIST_SIZE)HalCalculateScatterGatherListSize*/,
+ NULL /*(PBUILD_SCATTER_GATHER_LIST)HalBuildScatterGatherList*/,
+ NULL /*(PBUILD_MDL_FROM_SCATTER_GATHER_LIST)HalBuildMdlFromScatterGatherList*/
+};
+
+#define MAX_MAP_REGISTERS 64
+
+#define TAG_DMA TAG('D','M','A',' ')
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+HalpInitDma(VOID)
+{
+ /*
+ * Initialize the DMA Operation table
+ */
+ HalpDmaOperations.AllocateAdapterChannel = (PALLOCATE_ADAPTER_CHANNEL)IoAllocateAdapterChannel;
+ HalpDmaOperations.FlushAdapterBuffers = (PFLUSH_ADAPTER_BUFFERS)IoFlushAdapterBuffers;
+ HalpDmaOperations.FreeAdapterChannel = (PFREE_ADAPTER_CHANNEL)IoFreeAdapterChannel;
+ HalpDmaOperations.FreeMapRegisters = (PFREE_MAP_REGISTERS)IoFreeMapRegisters;
+ HalpDmaOperations.MapTransfer = (PMAP_TRANSFER)IoMapTransfer;
+
+ /*
+ * Check if Extended DMA is available. We're just going to do a random
+ * read and write.
+ */
+
+ WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2), 0x2A);
+ if (READ_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)) == 0x2A)
+ HalpEisaDma = TRUE;
+
+ /*
+ * Intialize all the global variables and allocate master adapter with
+ * first map buffers.
+ */
+
+ InitializeListHead(&HalpDmaAdapterList);
+ KeInitializeEvent(&HalpDmaLock, NotificationEvent, TRUE);
+
+ HalpMasterAdapter = HalpDmaAllocateMasterAdapter();
+
+ /*
+ * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's
+ * used by IoGetDmaAdapter in the kernel.
+ */
+
+ HalGetDmaAdapter = HalpGetDmaAdapter;
+}
+
+/**
+ * @name HalpGetAdapterMaximumPhysicalAddress
+ *
+ * Get the maximum physical address acceptable by the device represented
+ * by the passed DMA adapter.
+ */
+
+PHYSICAL_ADDRESS STDCALL
+HalpGetAdapterMaximumPhysicalAddress(
+ IN PADAPTER_OBJECT AdapterObject)
+{
+ PHYSICAL_ADDRESS HighestAddress;
+
+ if (AdapterObject->MasterDevice)
+ {
+ if (AdapterObject->Dma64BitAddresses)
+ {
+ HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
+ return HighestAddress;
+ }
+ else if (AdapterObject->Dma32BitAddresses)
+ {
+ HighestAddress.QuadPart = 0xFFFFFFFF;
+ return HighestAddress;
+ }
+ }
+
+ HighestAddress.QuadPart = 0xFFFFFF;
+ return HighestAddress;
+}
+
+/**
+ * @name HalpGrowMapBuffers
+ *
+ * Allocate initial, or additional, map buffers for DMA master adapter.
+ *
+ * @param MasterAdapter
+ * DMA master adapter to allocate buffers for.
+ * @param SizeOfMapBuffers
+ * Size of the map buffers to allocate (not including the size
+ * already allocated).
+ */
+
+BOOLEAN STDCALL
+HalpGrowMapBuffers(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN ULONG SizeOfMapBuffers)
+{
+ PVOID VirtualAddress;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PHYSICAL_ADDRESS HighestAcceptableAddress;
+ PHYSICAL_ADDRESS LowestAcceptableAddress;
+ PHYSICAL_ADDRESS BoundryAddressMultiple;
+ KIRQL OldIrql;
+ ULONG MapRegisterCount;
+
+ /* FIXME: Check if enough map register slots are available. */
+
+ MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers);
+
+ /*
+ * Allocate memory for the new map registers. For 32-bit adapters we use
+ * two passes in order not to waste scare resource (low memory).
+ */
+
+ HighestAcceptableAddress =
+ HalpGetAdapterMaximumPhysicalAddress(AdapterObject);
+ LowestAcceptableAddress.HighPart = 0;
+ LowestAcceptableAddress.LowPart =
+ HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0;
+ BoundryAddressMultiple.QuadPart = 0;
+
+ VirtualAddress = MmAllocateContiguousMemorySpecifyCache(
+ MapRegisterCount << PAGE_SHIFT, LowestAcceptableAddress,
+ HighestAcceptableAddress, BoundryAddressMultiple, MmNonCached);
+
+ if (VirtualAddress == NULL && LowestAcceptableAddress.LowPart != 0)
+ {
+ LowestAcceptableAddress.LowPart = 0;
+ VirtualAddress = MmAllocateContiguousMemorySpecifyCache(
+ MapRegisterCount << PAGE_SHIFT, LowestAcceptableAddress,
+ HighestAcceptableAddress, BoundryAddressMultiple, MmNonCached);
+ }
+
+ if (VirtualAddress == NULL)
+ return FALSE;
+
+ PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
+
+ /*
+ * All the following must be done with the master adapter lock held
+ * to prevent corruption.
+ */
+
+ OldIrql = KfAcquireSpinLock(&AdapterObject->SpinLock);
+
+ /*
+ * Setup map register entries for the buffer allocated. Each entry has
+ * a virtual and physical address and corresponds to PAGE_SIZE large
+ * buffer.
+ */
+
+ if (MapRegisterCount > 0)
+ {
+ PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry;
+
+ CurrentEntry = AdapterObject->MapRegisterBase +
+ AdapterObject->NumberOfMapRegisters;
+ do
+ {
+ /*
+ * Leave one entry free for every non-contiguous memory region
+ * in the map register bitmap. This ensures that we can search
+ * using RtlFindClearBits for contiguous map register regions.
+ *
+ * Also for non-EISA DMA leave one free entry for every 64Kb
+ * break, because the DMA controller can handle only coniguous
+ * 64Kb regions.
+ */
+
+ if (CurrentEntry != AdapterObject->MapRegisterBase)
+ {
+ PreviousEntry = CurrentEntry - 1;
+ if (PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE ==
+ PhysicalAddress.LowPart)
+ {
+ if (!HalpEisaDma)
+ {
+ if ((PreviousEntry->PhysicalAddress.LowPart ^
+ PhysicalAddress.LowPart) & 0xFFFF0000)
+ {
+ CurrentEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+ }
+ }
+ else
+ {
+ CurrentEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ }
+ }
+
+ RtlClearBit(AdapterObject->MapRegisters,
+ CurrentEntry - AdapterObject->MapRegisterBase);
+ CurrentEntry->VirtualAddress = VirtualAddress;
+ CurrentEntry->PhysicalAddress = PhysicalAddress;
+
+ PhysicalAddress.LowPart += PAGE_SIZE;
+ VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE);
+
+ CurrentEntry++;
+ AdapterObject->NumberOfMapRegisters++;
+ MapRegisterCount--;
+ }
+ while (MapRegisterCount != 0);
+ }
+
+ KfReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
+
+ return TRUE;
+}
+
+/**
+ * @name HalpDmaAllocateMasterAdapter
+ *
+ * Helper routine to allocate and initialize master adapter object and it's
+ * associated map register buffers.
+ *
+ * @see HalpInitDma
+ */
+
+PADAPTER_OBJECT STDCALL
+HalpDmaAllocateMasterAdapter(VOID)
+{
+ PADAPTER_OBJECT MasterAdapter;
+ ULONG Size, SizeOfBitmap;
+
+ SizeOfBitmap = MAX_MAP_REGISTERS;
+ Size = sizeof(ADAPTER_OBJECT);
+ Size += sizeof(RTL_BITMAP);
+ Size += (SizeOfBitmap + 7) >> 3;
+
+ MasterAdapter = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_DMA);
+ if (MasterAdapter == NULL)
+ return NULL;
+
+ RtlZeroMemory(MasterAdapter, Size);
+
+ KeInitializeSpinLock(&MasterAdapter->SpinLock);
+ InitializeListHead(&MasterAdapter->AdapterQueue);
+
+ MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1);
+ RtlInitializeBitMap(
+ MasterAdapter->MapRegisters,
+ (PULONG)(MasterAdapter->MapRegisters + 1),
+ SizeOfBitmap);
+ RtlSetAllBits(MasterAdapter->MapRegisters);
+ MasterAdapter->NumberOfMapRegisters = 0;
+ MasterAdapter->CommittedMapRegisters = 0;
+
+ MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag(
+ NonPagedPool,
+ SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY),
+ TAG_DMA);
+ if (MasterAdapter->MapRegisterBase == NULL)
+ {
+ ExFreePool(MasterAdapter);
+ return NULL;
+ }
+
+ RtlZeroMemory(MasterAdapter->MapRegisterBase,
+ SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY));
+ if (!HalpGrowMapBuffers(MasterAdapter, 0x10000))
+ {
+ ExFreePool(MasterAdapter);
+ return NULL;
+ }
+
+ return MasterAdapter;
+}
+
+/**
+ * @name HalpDmaAllocateChildAdapter
+ *
+ * Helper routine of HalGetAdapter. Allocate child adapter object and
+ * fill out some basic fields.
+ *
+ * @see HalGetAdapter
+ */
+
+PADAPTER_OBJECT STDCALL
+HalpDmaAllocateChildAdapter(
+ ULONG NumberOfMapRegisters,
+ PDEVICE_DESCRIPTION DeviceDescription)
+{
+ PADAPTER_OBJECT AdapterObject;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ HANDLE Handle;
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ NULL,
+ OBJ_KERNEL_HANDLE | OBJ_PERMANENT,
+ NULL,
+ NULL);
+
+ Status = ObCreateObject(
+ KernelMode,
+ IoAdapterObjectType,
+ &ObjectAttributes,
+ KernelMode,
+ NULL,
+ sizeof(ADAPTER_OBJECT),
+ 0,
+ 0,
+ (PVOID)&AdapterObject);
+ if (!NT_SUCCESS(Status))
+ return NULL;
+
+ Status = ObReferenceObjectByPointer(
+ AdapterObject,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ IoAdapterObjectType,
+ KernelMode);
+ if (!NT_SUCCESS(Status))
+ return NULL;
+
+ RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
+
+ Status = ObInsertObject(
+ AdapterObject,
+ NULL,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ 0,
+ NULL,
+ &Handle);
+ if (!NT_SUCCESS(Status))
+ return NULL;
+
+ ZwClose(Handle);
+
+ AdapterObject->DmaHeader.Version = DeviceDescription->Version;
+ AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT);
+ AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations;
+ AdapterObject->MapRegistersPerChannel = 1;
+ AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
+ AdapterObject->ChannelNumber = 0xFF;
+ AdapterObject->MasterAdapter = HalpMasterAdapter;
+ KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
+
+ return AdapterObject;
+}
+
+/**
+ * @name HalpDmaInitializeEisaAdapter
+ *
+ * Setup DMA modes and extended modes for (E)ISA DMA adapter object.
+ */
+
+BOOLEAN STDCALL
+HalpDmaInitializeEisaAdapter(
+ PADAPTER_OBJECT AdapterObject,
+ PDEVICE_DESCRIPTION DeviceDescription)
+{
+ UCHAR Controller;
+ DMA_MODE DmaMode = {{0 }};
+ DMA_EXTENDED_MODE ExtendedMode = {{ 0 }};
+ PVOID AdapterBaseVa;
+
+ Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1;
+
+ if (Controller == 1)
+ AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController1);
+ else
+ AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController2);
+
+ AdapterObject->AdapterNumber = Controller;
+ AdapterObject->ChannelNumber = DeviceDescription->DmaChannel & 3;
+ AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel];
+ AdapterObject->Width16Bits = FALSE;
+ AdapterObject->AdapterBaseVa = AdapterBaseVa;
+
+ if (HalpEisaDma)
+ {
+ ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber;
+
+ switch (DeviceDescription->DmaSpeed)
+ {
+ case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break;
+ case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break;
+ case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break;
+ case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break;
+ default:
+ return FALSE;
+ }
+
+ switch (DeviceDescription->DmaWidth)
+ {
+ case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break;
+ case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break;
+ case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break;
+ default:
+ return FALSE;
+ }
+
+ if (Controller == 1)
+ WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode1),
+ ExtendedMode.Byte);
+ else
+ WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode2),
+ ExtendedMode.Byte);
+ }
+ else
+ {
+ /*
+ * Validate setup for non-busmaster DMA adapter. Secondary controller
+ * supports only 16-bit transfers and main controller supports only
+ * 8-bit transfers. Anything else is invalid.
+ */
+
+ if (!DeviceDescription->Master)
+ {
+ if (Controller == 2 && DeviceDescription->DmaWidth == Width16Bits)
+ AdapterObject->Width16Bits = TRUE;
+ else if (Controller != 1 || DeviceDescription->DmaWidth != Width8Bits)
+ return FALSE;
+ }
+ }
+
+ DmaMode.Channel = AdapterObject->ChannelNumber;
+ DmaMode.AutoInitialize = DeviceDescription->AutoInitialize;
+
+ /*
+ * Set the DMA request mode.
+ *
+ * For (E)ISA bus master devices just unmask (enable) the DMA channel
+ * and set it to cascade mode. Otherwise just select the right one
+ * bases on the passed device description.
+ */
+
+ if (DeviceDescription->Master)
+ {
+ DmaMode.RequestMode = CASCADE_REQUEST_MODE;
+ if (Controller == 1)
+ {
+ /* Set the Request Data */
+ WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode,
+ DmaMode.Byte);
+ /* Unmask DMA Channel */
+ WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask,
+ AdapterObject->ChannelNumber | DMA_CLEARMASK);
+ } else {
+ /* Set the Request Data */
+ WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode,
+ DmaMode.Byte);
+ /* Unmask DMA Channel */
+ WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask,
+ AdapterObject->ChannelNumber | DMA_CLEARMASK);
+ }
+ }
+ else
+ {
+ if (DeviceDescription->DemandMode)
+ DmaMode.RequestMode = DEMAND_REQUEST_MODE;
+ else
+ DmaMode.RequestMode = SINGLE_REQUEST_MODE;
+ }
+
+ AdapterObject->AdapterMode = DmaMode;
+
+ return TRUE;
+}
+
+/**
+ * @name HalGetAdapter
+ *
+ * Allocate an adapter object for DMA device.
+ *
+ * @param DeviceDescription
+ * Structure describing the attributes of the device.
+ * @param NumberOfMapRegisters
+ * On return filled with the maximum number of map registers the
+ * device driver can allocate for DMA transfer operations.
+ *
+ * @return The DMA adapter on success, NULL otherwise.
+ *
+ * @implemented
+ */
+
+PADAPTER_OBJECT STDCALL
+HalGetAdapter(
+ PDEVICE_DESCRIPTION DeviceDescription,
+ PULONG NumberOfMapRegisters)
+{
+ PADAPTER_OBJECT AdapterObject = NULL;
+ PADAPTER_OBJECT MasterAdapter;
+ BOOLEAN EisaAdapter;
+ ULONG MapRegisters;
+ ULONG MaximumLength;
+
+ /* Validate parameters in device description */
+ if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION2)
+ return NULL;
+
+ /*
+ * See if we're going to use ISA/EISA DMA adapter. These adapters are
+ * special since they're reused.
+ *
+ * Also note that we check for channel number since there are only 8 DMA
+ * channels on ISA, so any request above this requires new adapter.
+ */
+
+ if (DeviceDescription->InterfaceType == Isa || !DeviceDescription->Master)
+ {
+ if (DeviceDescription->InterfaceType == Isa &&
+ DeviceDescription->DmaChannel >= 8)
+ EisaAdapter = FALSE;
+ else
+ EisaAdapter = TRUE;
+ }
+ else
+ {
+ EisaAdapter = FALSE;
+ }
+
+ /*
+ * Disallow creating adapter for ISA/EISA DMA channel 4 since it's used
+ * for cascading the controllers and it's not available for software use.
+ */
+
+ if (EisaAdapter && DeviceDescription->DmaChannel == 4)
+ return NULL;
+
+ /*
+ * Calculate the number of map registers.
+ *
+ * - For EISA and PCI scatter/gather no map registers are needed.
+ * - For ISA slave scatter/gather one map register is needed.
+ * - For all other cases the number of map registers depends on
+ * DeviceDescription->MaximumLength.
+ */
+
+ MaximumLength = DeviceDescription->MaximumLength & MAXLONG;
+ if (DeviceDescription->ScatterGather &&
+ (DeviceDescription->InterfaceType == Eisa ||
+ DeviceDescription->InterfaceType == PCIBus))
+ {
+ MapRegisters = 0;
+ }
+ else if (DeviceDescription->ScatterGather &&
+ !DeviceDescription->Master)
+ {
+ MapRegisters = 1;
+ }
+ else
+ {
+ /*
+ * In the equation below the additional map register added by
+ * the "+1" accounts for the case when a transfer does not start
+ * at a page-aligned address.
+ */
+ MapRegisters = BYTES_TO_PAGES(MaximumLength) + 1;
+ if (MapRegisters > 16)
+ MapRegisters = 16;
+ }
+
+ /*
+ * Acquire the DMA lock that is used to protect adapter lists and
+ * EISA adapter array.
+ */
+
+ KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode,
+ FALSE, NULL);
+
+ /*
+ * Now we must get ahold of the adapter object. For first eight ISA/EISA
+ * channels there are static adapter objects that are reused and updated
+ * on succesive HalGetAdapter calls. In other cases a new adapter object
+ * is always created and it's to the DMA adapter list (HalpDmaAdapterList).
+ */
+
+ if (EisaAdapter)
+ {
+ AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel];
+ if (AdapterObject != NULL)
+ {
+ if (AdapterObject->NeedsMapRegisters &&
+ MapRegisters > AdapterObject->MapRegistersPerChannel)
+ AdapterObject->MapRegistersPerChannel = MapRegisters;
+ }
+ }
+
+ if (AdapterObject == NULL)
+ {
+ AdapterObject = HalpDmaAllocateChildAdapter(
+ MapRegisters, DeviceDescription);
+ if (AdapterObject == NULL)
+ {
+ KeSetEvent(&HalpDmaLock, 0, 0);
+ return NULL;
+ }
+
+ if (EisaAdapter)
+ {
+ HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject;
+ }
+
+ if (MapRegisters > 0)
+ {
+ AdapterObject->NeedsMapRegisters = TRUE;
+ MasterAdapter = HalpMasterAdapter;
+ AdapterObject->MapRegistersPerChannel = MapRegisters;
+
+ /*
+ * FIXME: Verify that the following makes sense. Actually
+ * MasterAdapter->NumberOfMapRegisters contains even the number
+ * of gaps, so this will not work correctly all the time. It
+ * doesn't matter much since it's only optimization to avoid
+ * queuing work items in HalAllocateAdapterChannel.
+ */
+
+ MasterAdapter->CommittedMapRegisters += MapRegisters;
+ if (MasterAdapter->CommittedMapRegisters > MasterAdapter->NumberOfMapRegisters)
+ HalpGrowMapBuffers(MasterAdapter, 0x10000);
+ }
+ else
+ {
+ AdapterObject->NeedsMapRegisters = FALSE;
+ if (DeviceDescription->Master)
+ AdapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(MaximumLength) + 1;
+ else
+ AdapterObject->MapRegistersPerChannel = 1;
+ }
+ }
+
+ if (!EisaAdapter)
+ InsertTailList(&HalpDmaAdapterList, &AdapterObject->AdapterList);
+
+ /*
+ * Release the DMA lock. HalpDmaAdapterList and HalpEisaAdapter will
+ * no longer be touched, so we don't need it.
+ */
+
+ KeSetEvent(&HalpDmaLock, 0, 0);
+
+ /*
+ * Setup the values in the adapter object that are common for all
+ * types of buses.
+ */
+
+ if (DeviceDescription->Version >= DEVICE_DESCRIPTION_VERSION1)
+ AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount;
+ else
+ AdapterObject->IgnoreCount = 0;
+
+ AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
+ AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses;
+ AdapterObject->ScatterGather = DeviceDescription->ScatterGather;
+ AdapterObject->MasterDevice = DeviceDescription->Master;
+ *NumberOfMapRegisters = AdapterObject->MapRegistersPerChannel;
+
+ /*
+ * For non-(E)ISA adapters we have already done all the work. On the
+ * other hand for (E)ISA adapters we must still setup the DMA modes
+ * and prepare the controller.
+ */
+
+ if (EisaAdapter)
+ {
+ if (!HalpDmaInitializeEisaAdapter(AdapterObject, DeviceDescription))
+ {
+ ObfDereferenceObject(AdapterObject);
+ return NULL;
+ }
+ }
+
+ return AdapterObject;
+}
+
+/**
+ * @name HalpGetDmaAdapter
+ *
+ * Internal routine to allocate PnP DMA adapter object. It's exported through
+ * HalDispatchTable and used by IoGetDmaAdapter.
+ *
+ * @see HalGetAdapter
+ */
+
+PDMA_ADAPTER STDCALL
+HalpGetDmaAdapter(
+ IN PVOID Context,
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ OUT PULONG NumberOfMapRegisters)
+{
+ return &HalGetAdapter(DeviceDescription, NumberOfMapRegisters)->DmaHeader;
+}
+
+/**
+ * @name HalPutDmaAdapter
+ *
+ * Internal routine to free DMA adapter and resources for reuse. It's exported
+ * using the DMA_OPERATIONS interface by HalGetAdapter.
+ *
+ * @see HalGetAdapter
+ */
+
+VOID STDCALL
+HalPutDmaAdapter(
+ PADAPTER_OBJECT AdapterObject)
+{
+ if (AdapterObject->ChannelNumber == 0xFF)
+ {
+ KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode,
+ FALSE, NULL);
+ RemoveEntryList(&AdapterObject->AdapterList);
+ KeSetEvent(&HalpDmaLock, 0, 0);
+ }
+
+ ObfDereferenceObject(AdapterObject);
+}
+
+/**
+ * @name HalAllocateCommonBuffer
+ *
+ * Allocates memory that is visible to both the processor(s) and the DMA
+ * device.
+ *
+ * @param AdapterObject
+ * Adapter object representing the bus master or system dma controller.
+ * @param Length
+ * Number of bytes to allocate.
+ * @param LogicalAddress
+ * Logical address the driver can use to access the buffer.
+ * @param CacheEnabled
+ * Specifies if the memory can be cached.
+ *
+ * @return The base virtual address of the memory allocated or NULL on failure.
+ *
+ * @remarks
+ * On real NT x86 systems the CacheEnabled parameter is ignored, we honour
+ * it. If it proves to cause problems change it.
+ *
+ * @see HalFreeCommonBuffer
+ *
+ * @implemented
+ */
+
+PVOID STDCALL
+HalAllocateCommonBuffer(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Length,
+ PPHYSICAL_ADDRESS LogicalAddress,
+ BOOLEAN CacheEnabled)
+{
+ PHYSICAL_ADDRESS LowestAcceptableAddress;
+ PHYSICAL_ADDRESS HighestAcceptableAddress;
+ PHYSICAL_ADDRESS BoundryAddressMultiple;
+ PVOID VirtualAddress;
+
+ LowestAcceptableAddress.QuadPart = 0;
+ HighestAcceptableAddress =
+ HalpGetAdapterMaximumPhysicalAddress(AdapterObject);
+ BoundryAddressMultiple.QuadPart = 0;
+
+ /*
+ * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For
+ * slave DMA devices the 64Kb boundary mustn't be crossed since the
+ * controller wouldn't be able to handle it.
+ */
+
+ if (AdapterObject->MasterDevice)
+ BoundryAddressMultiple.HighPart = 1;
+ else
+ BoundryAddressMultiple.LowPart = 0x10000;
+
+ VirtualAddress = MmAllocateContiguousMemorySpecifyCache(
+ Length, LowestAcceptableAddress, HighestAcceptableAddress,
+ BoundryAddressMultiple, CacheEnabled ? MmCached : MmNonCached);
+ if (VirtualAddress == NULL)
+ return NULL;
+
+ *LogicalAddress = MmGetPhysicalAddress(VirtualAddress);
+
+ return VirtualAddress;
+}
+
+/**
+ * @name HalFreeCommonBuffer
+ *
+ * Free common buffer allocated with HalAllocateCommonBuffer.
+ *
+ * @see HalAllocateCommonBuffer
+ *
+ * @implemented
+ */
+
+VOID STDCALL
+HalFreeCommonBuffer(
+ PADAPTER_OBJECT AdapterObject,
+ ULONG Length,
+ PHYSICAL_ADDRESS LogicalAddress,
+ PVOID VirtualAddress,
+ BOOLEAN CacheEnabled)
+{
+ MmFreeContiguousMemory(VirtualAddress);
+}
+
+/**
+ * @name HalpDmaGetDmaAlignment
+ *
+ * Internal routine to return the DMA alignment requirement. It's exported
+ * using the DMA_OPERATIONS interface by HalGetAdapter.
+ *
+ * @see HalGetAdapter
+ */
+
+ULONG STDCALL
+HalpDmaGetDmaAlignment(
+ PADAPTER_OBJECT AdapterObject)
+{
+ return 1;
+}
+
+/*
+ * @name HalReadDmaCounter
+ *
+ * Read DMA operation progress counter.
+ *
+ * @implemented
+ */
+
+ULONG STDCALL
+HalReadDmaCounter(
+ PADAPTER_OBJECT AdapterObject)
+{
+ KIRQL OldIrql;
+ ULONG Count, OldCount;
+
+ ASSERT(!AdapterObject->MasterDevice);
+
+ /*
+ * Acquire the master adapter lock since we're going to mess with the
+ * system DMA controller registers and we really don't want anyone
+ * to do the same at the same time.
+ */
+
+ KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
+
+ /* Send the request to the specific controller. */
+ if (AdapterObject->AdapterNumber == 1)
+ {
+ PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
+
+ Count = 0xffff00;
+ do
+ {
+ OldCount = Count;
+ /* Send Reset */
+ WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
+ /* Read Count */
+ Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
+ [AdapterObject->ChannelNumber].DmaBaseCount);
+ Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
+ [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
+ }
+ while (0xffff00 & (OldCount ^ Count));
+ }
+ else
+ {
+ PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
+
+ Count = 0xffff00;
+ do
+ {
+ OldCount = Count;
+ /* Send Reset */
+ WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
+ /* Read Count */
+ Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
+ [AdapterObject->ChannelNumber].DmaBaseCount);
+ Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
+ [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
+ }
+ while (0xffff00 & (OldCount ^ Count));
+ }
+
+ KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
+
+ Count++;
+ Count &= 0xffff;
+ if (AdapterObject->Width16Bits)
+ Count *= 2;
+
+ return Count;
+}
+
+/**
+ * @name HalpGrowMapBufferWorker
+ *
+ * Helper routine of HalAllocateAdapterChannel for allocating map registers
+ * at PASSIVE_LEVEL in work item.
+ */
+
+VOID STDCALL
+HalpGrowMapBufferWorker(PVOID DeferredContext)
+{
+ PGROW_WORK_ITEM WorkItem = (PGROW_WORK_ITEM)DeferredContext;
+ KIRQL OldIrql;
+ BOOLEAN Succeeded;
+
+ /*
+ * Try to allocate new map registers for the adapter.
+ *
+ * NOTE: The NT implementation actually tries to allocate more map
+ * registers than needed as an optimization.
+ */
+
+ KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode,
+ FALSE, NULL);
+ Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter,
+ WorkItem->NumberOfMapRegisters);
+ KeSetEvent(&HalpDmaLock, 0, 0);
+
+ if (Succeeded)
+ {
+ /*
+ * Flush the adapter queue now that new map registers are ready. The
+ * easiest way to do that is to call IoFreeMapRegisters to not free
+ * any registers. Note that we use the magic (PVOID)2 map register
+ * base to bypass the parameter checking.
+ */
+
+ OldIrql = KfRaiseIrql(DISPATCH_LEVEL);
+ IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0);
+ KfLowerIrql(OldIrql);
+ }
+
+ ExFreePool(WorkItem);
+}
+
+/**
+ * @name HalAllocateAdapterChannel
+ *
+ * Setup map registers for an adapter object.
+ *
+ * @param AdapterObject
+ * Pointer to an ADAPTER_OBJECT to set up.
+ * @param WaitContextBlock
+ * Context block to be used with ExecutionRoutine.
+ * @param NumberOfMapRegisters
+ * Number of map registers requested.
+ * @param ExecutionRoutine
+ * Callback to call when map registers are allocated.
+ *
+ * @return
+ * If not enough map registers can be allocated then
+ * STATUS_INSUFFICIENT_RESOURCES is returned. If the function
+ * succeeds or the callback is queued for later delivering then
+ * STATUS_SUCCESS is returned.
+ *
+ * @see IoFreeAdapterChannel
+ *
+ * @implemented
+ */
+
+NTSTATUS STDCALL
+HalAllocateAdapterChannel(
+ PADAPTER_OBJECT AdapterObject,
+ PWAIT_CONTEXT_BLOCK WaitContextBlock,
+ ULONG NumberOfMapRegisters,
+ PDRIVER_CONTROL ExecutionRoutine)
+{
+ PADAPTER_OBJECT MasterAdapter;
+ PGROW_WORK_ITEM WorkItem;
+ ULONG Index = ~0;
+ ULONG Result;
+ KIRQL OldIrql;
+
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ /* Set up the wait context block in case we can't run right away. */
+ WaitContextBlock->DeviceRoutine = ExecutionRoutine;
+ WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ /* Returns true if queued, else returns false and sets the queue to busy */
+ if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue, &WaitContextBlock->WaitQueueEntry))
+ return STATUS_SUCCESS;
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
+ AdapterObject->CurrentWcb = WaitContextBlock;
+
+ if (NumberOfMapRegisters && AdapterObject->NeedsMapRegisters)
+ {
+ if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
+ {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /*
+ * Get the map registers. This is partly complicated by the fact
+ * that new map registers can only be allocated at PASSIVE_LEVEL
+ * and we're currently at DISPATCH_LEVEL. The following code has
+ * two code paths:
+ *
+ * - If there is no adapter queued for map register allocation,
+ * try to see if enough contiguous map registers are present.
+ * In case they're we can just get them and proceed further.
+ *
+ * - If some adapter is already present in the queue we must
+ * respect the order of adapters asking for map registers and
+ * so the fast case described above can't take place.
+ * This case is also entered if not enough coniguous map
+ * registers are present.
+ *
+ * A work queue item is allocated and queued, the adapter is
+ * also queued into the master adapter queue. The worker
+ * routine does the job of allocating the map registers at
+ * PASSIVE_LEVEL and calling the ExecutionRoutine.
+ */
+
+ OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
+
+ if (IsListEmpty(&MasterAdapter->AdapterQueue))
+ {
+ Index = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters, NumberOfMapRegisters, 0);
+ if (Index != ~0)
+ {
+ AdapterObject->MapRegisterBase =
+ MasterAdapter->MapRegisterBase + Index;
+ if (!AdapterObject->ScatterGather)
+ {
+ AdapterObject->MapRegisterBase =
+ (PROS_MAP_REGISTER_ENTRY)(
+ (ULONG_PTR)AdapterObject->MapRegisterBase |
+ MAP_BASE_SW_SG);
+ }
+ }
+ }
+
+ if (Index == ~0)
+ {
+ WorkItem = ExAllocatePoolWithTag(
+ NonPagedPool, sizeof(GROW_WORK_ITEM), TAG_DMA);
+ if (WorkItem == NULL)
+ {
+ KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
+
+ ExInitializeWorkItem(
+ &WorkItem->WorkQueueItem, HalpGrowMapBufferWorker, WorkItem);
+ WorkItem->AdapterObject = AdapterObject;
+ WorkItem->NumberOfMapRegisters = NumberOfMapRegisters;
+
+ ExQueueWorkItem(&WorkItem->WorkQueueItem, DelayedWorkQueue);
+
+ KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+
+ return STATUS_SUCCESS;
+ }
+
+ KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+ }
+ else
+ {
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ AdapterObject->CurrentWcb = WaitContextBlock;
+
+ Result = ExecutionRoutine(
+ WaitContextBlock->DeviceObject, WaitContextBlock->CurrentIrp,
+ AdapterObject->MapRegisterBase, WaitContextBlock->DeviceContext);
+
+ /*
+ * Possible return values:
+ *
+ * - KeepObject
+ * Don't free any resources, the ADAPTER_OBJECT is still in use and
+ * the caller will call IoFreeAdapterChannel later.
+ *
+ * - DeallocateObject
+ * Deallocate the map registers and release the ADAPTER_OBJECT, so
+ * someone else can use it.
+ *
+ * - DeallocateObjectKeepRegisters
+ * Release the ADAPTER_OBJECT, but hang on to the map registers. The
+ * client will later call IoFreeMapRegisters.
+ *
+ * NOTE:
+ * IoFreeAdapterChannel runs the queue, so it must be called unless
+ * the adapter object is not to be freed.
+ */
+
+ if (Result == DeallocateObject)
+ {
+ IoFreeAdapterChannel(AdapterObject);
+ }
+ else if (Result == DeallocateObjectKeepRegisters)
+ {
+ AdapterObject->NumberOfMapRegisters = 0;
+ IoFreeAdapterChannel(AdapterObject);
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/**
+ * @name IoFreeAdapterChannel
+ *
+ * Free DMA resources allocated by IoAllocateAdapterChannel.
+ *
+ * @param AdapterObject
+ * Adapter object with resources to free.
+ *
+ * @remarks
+ * This function releases map registers registers assigned to the DMA
+ * adapter. After releasing the adapter, it checks the adapter's queue
+ * and runs each queued device object in series until the queue is
+ * empty. This is the only way the device queue is emptied.
+ *
+ * @see IoAllocateAdapterChannel
+ *
+ * @implemented
+ */
+
+VOID STDCALL
+IoFreeAdapterChannel(
+ PADAPTER_OBJECT AdapterObject)
+{
+ PADAPTER_OBJECT MasterAdapter;
+ PKDEVICE_QUEUE_ENTRY DeviceQueueEntry;
+ PWAIT_CONTEXT_BLOCK WaitContextBlock;
+ ULONG Index = ~0;
+ ULONG Result;
+ KIRQL OldIrql;
+
+ MasterAdapter = AdapterObject->MasterAdapter;
+
+ for (;;)
+ {
+ /*
+ * To keep map registers, call here with AdapterObject->
+ * NumberOfMapRegisters set to zero. This trick is used in
+ * HalAllocateAdapterChannel for example.
+ */
+ if (AdapterObject->NumberOfMapRegisters)
+ {
+ IoFreeMapRegisters(
+ AdapterObject,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters);
+ }
+
+ DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue);
+ if (DeviceQueueEntry == NULL)
+ {
+ break;
+ }
+
+ WaitContextBlock = CONTAINING_RECORD(
+ DeviceQueueEntry,
+ WAIT_CONTEXT_BLOCK,
+ WaitQueueEntry);
+
+ AdapterObject->CurrentWcb = WaitContextBlock;
+ AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters;
+
+ if (WaitContextBlock->NumberOfMapRegisters &&
+ AdapterObject->MasterAdapter)
+ {
+ OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
+
+ if (IsListEmpty(&MasterAdapter->AdapterQueue))
+ {
+ Index = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ WaitContextBlock->NumberOfMapRegisters, 0);
+ if (Index != ~0)
+ {
+ AdapterObject->MapRegisterBase =
+ MasterAdapter->MapRegisterBase + Index;
+ if (!AdapterObject->ScatterGather)
+ {
+ AdapterObject->MapRegisterBase =
+ (PROS_MAP_REGISTER_ENTRY)(
+ (ULONG_PTR)AdapterObject->MapRegisterBase |
+ MAP_BASE_SW_SG);
+ }
+ }
+ }
+
+ if (Index == ~0)
+ {
+ InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
+ KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+ break;
+ }
+
+ KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+ }
+ else
+ {
+ AdapterObject->MapRegisterBase = NULL;
+ AdapterObject->NumberOfMapRegisters = 0;
+ }
+
+ /* Call the adapter control routine. */
+ Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(
+ WaitContextBlock->DeviceObject, WaitContextBlock->CurrentIrp,
+ AdapterObject->MapRegisterBase, WaitContextBlock->DeviceContext);
+
+ switch (Result)
+ {
+ case KeepObject:
+ /*
+ * We're done until the caller manually calls IoFreeAdapterChannel
+ * or IoFreeMapRegisters.
+ */
+ return;
+
+ case DeallocateObjectKeepRegisters:
+ /*
+ * Hide the map registers so they aren't deallocated next time
+ * around.
+ */
+ AdapterObject->NumberOfMapRegisters = 0;
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+
+/**
+ * @name IoFreeMapRegisters
+ *
+ * Free map registers reserved by the system for a DMA.
+ *
+ * @param AdapterObject
+ * DMA adapter to free map registers on.
+ * @param MapRegisterBase
+ * Handle to map registers to free.
+ * @param NumberOfRegisters
+ * Number of map registers to be freed.
+ *
+ * @implemented
+ */
+
+VOID STDCALL
+IoFreeMapRegisters(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PVOID MapRegisterBase,
+ IN ULONG NumberOfMapRegisters)
+{
+ PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
+ PLIST_ENTRY ListEntry;
+ KIRQL OldIrql;
+ ULONG Index;
+ ULONG Result;
+
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ if (MasterAdapter == NULL || MapRegisterBase == NULL)
+ return;
+
+ OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
+
+ if (NumberOfMapRegisters != 0)
+ {
+ PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
+
+ RealMapRegisterBase =
+ (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
+ RtlClearBits(MasterAdapter->MapRegisters,
+ RealMapRegisterBase - MasterAdapter->MapRegisterBase,
+ NumberOfMapRegisters);
+ }
+
+ /*
+ * Now that we freed few map registers it's time to look at the master
+ * adapter queue and see if there is someone waiting for map registers.
+ */
+
+ while (!IsListEmpty(&MasterAdapter->AdapterQueue))
+ {
+ ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue);
+ AdapterObject = CONTAINING_RECORD(
+ ListEntry, struct _ADAPTER_OBJECT, AdapterQueue);
+
+ Index = RtlFindClearBitsAndSet(
+ MasterAdapter->MapRegisters,
+ AdapterObject->NumberOfMapRegisters,
+ MasterAdapter->NumberOfMapRegisters);
+ if (Index == ~0)
+ {
+ InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry);
+ break;
+ }
+
+ KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+
+ AdapterObject->MapRegisterBase =
+ MasterAdapter->MapRegisterBase + Index;
+ if (!AdapterObject->ScatterGather)
+ {
+ AdapterObject->MapRegisterBase =
+ (PROS_MAP_REGISTER_ENTRY)(
+ (ULONG_PTR)AdapterObject->MapRegisterBase |
+ MAP_BASE_SW_SG);
+ }
+
+ Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(
+ AdapterObject->CurrentWcb->DeviceObject,
+ AdapterObject->CurrentWcb->CurrentIrp,
+ AdapterObject->MapRegisterBase,
+ AdapterObject->CurrentWcb->DeviceContext);
+
+ switch (Result)
+ {
+ case DeallocateObjectKeepRegisters:
+ AdapterObject->NumberOfMapRegisters = 0;
+ /* fall through */
+
+ case DeallocateObject:
+ if (AdapterObject->NumberOfMapRegisters)
+ {
+ OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
+ RtlClearBits(MasterAdapter->MapRegisters,
+ AdapterObject->MapRegisterBase -
+ MasterAdapter->MapRegisterBase,
+ AdapterObject->NumberOfMapRegisters);
+ KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+ }
+ IoFreeAdapterChannel(AdapterObject);
+ break;
+
+ default:
+ break;
+ }
+
+ OldIrql = KfAcquireSpinLock(&MasterAdapter->SpinLock);
+ }
+
+ KfReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
+}
+
+/**
+ * @name HalpCopyBufferMap
+ *
+ * Helper function for copying data from/to map register buffers.
+ *
+ * @see IoFlushAdapterBuffers, IoMapTransfer
+ */
+
+VOID STDCALL
+HalpCopyBufferMap(
+ PMDL Mdl,
+ PROS_MAP_REGISTER_ENTRY MapRegisterBase,
+ PVOID CurrentVa,
+ ULONG Length,
+ BOOLEAN WriteToDevice)
+{
+ ULONG CurrentLength;
+ ULONG_PTR CurrentAddress;
+ ULONG ByteOffset;
+ PVOID VirtualAddress;
+
+ VirtualAddress = MmGetSystemAddressForMdlSafe(Mdl, HighPagePriority);
+ if (VirtualAddress == NULL)
+ {
+ /*
+ * NOTE: On real NT a mechanism with reserved pages is implemented
+ * to handle this case in a slow, but graceful non-fatal way.
+ */
+ /* FIXME: The correct bug check code isn't defined. */
+ /* KEBUGCHECKEX(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0); */
+ KEBUGCHECK(0);
+ }
+
+ CurrentAddress = (ULONG_PTR)VirtualAddress +
+ (ULONG_PTR)CurrentVa -
+ (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
+
+ while (Length > 0)
+ {
+ ByteOffset = BYTE_OFFSET(CurrentAddress);
+ CurrentLength = PAGE_SIZE - ByteOffset;
+ if (CurrentLength > Length)
+ CurrentLength = Length;
+
+ if (WriteToDevice)
+ {
+ RtlCopyMemory(
+ (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
+ (PVOID)CurrentAddress,
+ CurrentLength);
+ }
+ else
+ {
+ RtlCopyMemory(
+ (PVOID)CurrentAddress,
+ (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
+ CurrentLength);
+ }
+
+ Length -= CurrentLength;
+ CurrentAddress += CurrentLength;
+ MapRegisterBase++;
+ }
+}
+
+/**
+ * @name IoFlushAdapterBuffers
+ *
+ * Flush any data remaining in the DMA controller's memory into the host
+ * memory.
+ *
+ * @param AdapterObject
+ * The adapter object to flush.
+ * @param Mdl
+ * Original MDL to flush data into.
+ * @param MapRegisterBase
+ * Map register base that was just used by IoMapTransfer, etc.
+ * @param CurrentVa
+ * Offset into Mdl to be flushed into, same as was passed to
+ * IoMapTransfer.
+ * @param Length
+ * Length of the buffer to be flushed into.
+ * @param WriteToDevice
+ * TRUE if it's a write, FALSE if it's a read.
+ *
+ * @return TRUE in all cases.
+ *
+ * @remarks
+ * This copies data from the map register-backed buffer to the user's
+ * target buffer. Data are not in the user buffer until this function
+ * is called.
+ * For slave DMA transfers the controller channel is masked effectively
+ * stopping the current transfer.
+ *
+ * @unimplemented.
+ */
+
+BOOLEAN STDCALL
+IoFlushAdapterBuffers(
+ PADAPTER_OBJECT AdapterObject,
+ PMDL Mdl,
+ PVOID MapRegisterBase,
+ PVOID CurrentVa,
+ ULONG Length,
+ BOOLEAN WriteToDevice)
+{
+ BOOLEAN SlaveDma = FALSE;
+ PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
+
+ ASSERT_IRQL(DISPATCH_LEVEL);
+
+ if (AdapterObject != NULL && !AdapterObject->MasterDevice)
+ {
+ /* Mask out (disable) the DMA channel. */
+ if (AdapterObject->AdapterNumber == 1)
+ {
+ PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
+ WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
+ AdapterObject->ChannelNumber | DMA_SETMASK);
+ }
+ else
+ {
+ PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
+ WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
+ AdapterObject->ChannelNumber | DMA_SETMASK);
+ }
+ SlaveDma = TRUE;
+ }
+
+ /* This can happen if the device supports hardware scatter/gather. */
+ if (MapRegisterBase == NULL)
+ return TRUE;
+
+ RealMapRegisterBase =
+ (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
+
+ if (!WriteToDevice)
+ {
+ if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG)
+ {
+ if (RealMapRegisterBase->Counter != ~0)
+ {
+ if (SlaveDma && !AdapterObject->IgnoreCount)
+ Length -= HalReadDmaCounter(AdapterObject);
+ }
+
+ HalpCopyBufferMap(Mdl, RealMapRegisterBase, CurrentVa, Length, FALSE);
+ }
+ else
+ {
+ /* FIXME: Unimplemented case */
+ ASSERT(FALSE);
+ }
+ }
+
+ RealMapRegisterBase->Counter = 0;
+
+ return TRUE;
+}
+
+/**
+ * @name IoMapTransfer
+ *
+ * Map a DMA for transfer and do the DMA if it's a slave.
+ *
+ * @param AdapterObject
+ * Adapter object to do the DMA on. Bus-master may pass NULL.
+ * @param Mdl
+ * Locked-down user buffer to DMA in to or out of.
+ * @param MapRegisterBase
+ * Handle to map registers to use for this dma.
+ * @param CurrentVa
+ * Index into Mdl to transfer into/out of.
+ * @param Length
+ * Length of transfer. Number of bytes actually transferred on
+ * output.
+ * @param WriteToDevice
+ * TRUE if it's an output DMA, FALSE otherwise.
+ *
+ * @return
+ * A logical address that can be used to program a DMA controller, it's
+ * not meaningful for slave DMA device.
+ *
+ * @remarks
+ * This function does a copyover to contiguous memory <16MB represented
+ * by the map registers if needed. If the buffer described by MDL can be
+ * used as is no copyover is done.
+ * If it's a slave transfer, this function actually performs it.
+ *
+ * @implemented
+ */
+
+PHYSICAL_ADDRESS STDCALL
+IoMapTransfer(
+ IN PADAPTER_OBJECT AdapterObject,
+ IN PMDL Mdl,
+ IN PVOID MapRegisterBase,
+ IN PVOID CurrentVa,
+ IN OUT PULONG Length,
+ IN BOOLEAN WriteToDevice)
+{
+ PPFN_NUMBER MdlPagesPtr;
+ PFN_NUMBER MdlPage1, MdlPage2;
+ ULONG ByteOffset;
+ ULONG TransferOffset;
+ ULONG TransferLength;
+ BOOLEAN UseMapRegisters;
+ PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ PHYSICAL_ADDRESS HighestAcceptableAddress;
+ ULONG Counter;
+ DMA_MODE AdapterMode;
+ KIRQL OldIrql;
+
+ /*
+ * Precalculate some values that are used in all cases.
+ *
+ * ByteOffset is offset inside the page at which the transfer starts.
+ * MdlPagesPtr is pointer inside the MDL page chain at the page where the
+ * transfer start.
+ * PhysicalAddress is physical address corresponding to the transfer
+ * start page and offset.
+ * TransferLength is the inital length of the transfer, which is reminder
+ * of the first page. The actual value is calculated below.
+ *
+ * Note that all the variables can change during the processing which
+ * takes place below. These are just initial values.
+ */
+
+ ByteOffset = BYTE_OFFSET(CurrentVa);
+
+ MdlPagesPtr = MmGetMdlPfnArray(Mdl);
+ MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
+
+ PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
+ PhysicalAddress.QuadPart += ByteOffset;
+
+ TransferLength = PAGE_SIZE - ByteOffset;
+
+ /*
+ * Special case for bus master adapters with S/G support. We can directly
+ * use the buffer specified by the MDL, so not much work has to be done.
+ *
+ * Just return the passed VA's corresponding physical address and update
+ * length to the number of physically contiguous bytes found. Also
+ * pages crossing the 4Gb boundary aren't considered physically contiguous.
+ */
+
+ if (MapRegisterBase == NULL)
+ {
+ while (TransferLength < *Length)
+ {
+ MdlPage1 = *MdlPagesPtr;
+ MdlPage2 = *(MdlPagesPtr + 1);
+ if (MdlPage1 + 1 != MdlPage2)
+ break;
+ if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF)
+ break;
+ TransferLength += PAGE_SIZE;
+ MdlPagesPtr++;
+ }
+
+ if (TransferLength < *Length)
+ *Length = TransferLength;
+
+ return PhysicalAddress;
+ }
+
+ /*
+ * The code below applies to slave DMA adapters and bus master adapters
+ * without hardward S/G support.
+ */
+
+ RealMapRegisterBase =
+ (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
+
+ /*
+ * Try to calculate the size of the transfer. We can only transfer
+ * pages that are physically contiguous and that don't cross the
+ * 64Kb boundary (this limitation applies only for ISA controllers).
+ */
+
+ while (TransferLength < *Length)
+ {
+ MdlPage1 = *MdlPagesPtr;
+ MdlPage2 = *(MdlPagesPtr + 1);
+ if (MdlPage1 + 1 != MdlPage2)
+ break;
+ if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF))
+ break;
+ TransferLength += PAGE_SIZE;
+ MdlPagesPtr++;
+ }
+
+ if (TransferLength > *Length)
+ TransferLength = *Length;
+
+ /*
+ * If we're about to simulate software S/G and not all the pages are
+ * physically contiguous then we must use the map registers to store
+ * the data and allow the whole transfer to proceed at once.
+ */
+
+ if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG &&
+ TransferLength < *Length)
+ {
+ UseMapRegisters = TRUE;
+ PhysicalAddress = RealMapRegisterBase->PhysicalAddress;
+ PhysicalAddress.QuadPart += ByteOffset;
+ TransferLength = *Length;
+ RealMapRegisterBase->Counter = ~0;
+ Counter = 0;
+ }
+ else
+ {
+ /*
+ * This is ordinary DMA transfer, so just update the progress
+ * counters. These are used by IoFlushAdapterBuffers to track
+ * the transfer progress.
+ */
+
+ UseMapRegisters = FALSE;
+ Counter = RealMapRegisterBase->Counter;
+ RealMapRegisterBase->Counter += BYTES_TO_PAGES(ByteOffset + TransferLength);
+
+ /*
+ * Check if the buffer doesn't exceed the highest physical address
+ * limit of the device. In that case we must use the map registers to
+ * store the data.
+ */
+
+ HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject);
+ if (PhysicalAddress.QuadPart + TransferLength >
+ HighestAcceptableAddress.QuadPart)
+ {
+ UseMapRegisters = TRUE;
+ PhysicalAddress = RealMapRegisterBase->PhysicalAddress;
+ PhysicalAddress.QuadPart += ByteOffset;
+ if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG)
+ {
+ RealMapRegisterBase->Counter = ~0;
+ }
+ }
+ }
+
+ /*
+ * If we decided to use the map registers (see above) and we're about
+ * to transfer data to the device then copy the buffers into the map
+ * register memory.
+ */
+
+ if (UseMapRegisters && WriteToDevice)
+ {
+ HalpCopyBufferMap(Mdl, RealMapRegisterBase + Counter,
+ CurrentVa, TransferLength, WriteToDevice);
+ }
+
+ /*
+ * Return the length of transfer that actually takes place.
+ */
+
+ *Length = TransferLength;
+
+ /*
+ * If we're doing slave (system) DMA then program the (E)ISA controller
+ * to actually start the transfer.
+ */
+
+ if (AdapterObject != NULL && !AdapterObject->MasterDevice)
+ {
+ AdapterMode = AdapterObject->AdapterMode;
+
+ if (WriteToDevice)
+ {
+ AdapterMode.TransferType = WRITE_TRANSFER;
+ }
+ else
+ {
+ AdapterMode.TransferType = READ_TRANSFER;
+ if (AdapterObject->IgnoreCount)
+ {
+ RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress +
+ ByteOffset, TransferLength);
+ }
+ }
+
+ TransferOffset = PhysicalAddress.LowPart & 0xFFFF;
+ if (AdapterObject->Width16Bits)
+ {
+ TransferLength >>= 1;
+ TransferOffset >>= 1;
+ }
+
+ OldIrql = KfAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock);
+
+ if (AdapterObject->AdapterNumber == 1)
+ {
+ PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
+
+ /* Reset Register */
+ WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
+ /* Set the Mode */
+ WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte);
+ /* Set the Offset Register */
+ WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
+ (UCHAR)(TransferOffset));
+ WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
+ (UCHAR)(TransferOffset >> 8));
+ /* Set the Page Register */
+ WRITE_PORT_UCHAR(AdapterObject->PagePort +
+ FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
+ (UCHAR)(PhysicalAddress.LowPart >> 16));
+ if (HalpEisaDma)
+ {
+ WRITE_PORT_UCHAR(AdapterObject->PagePort +
+ FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
+ 0);
+ }
+ /* Set the Length */
+ WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
+ (UCHAR)(TransferLength - 1));
+ WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
+ (UCHAR)((TransferLength - 1) >> 8));
+ /* Unmask the Channel */
+ WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
+ AdapterObject->ChannelNumber | DMA_CLEARMASK);
+ }
+ else
+ {
+ PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
+
+ /* Reset Register */
+ WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
+ /* Set the Mode */
+ WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte);
+ /* Set the Offset Register */
+ WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
+ (UCHAR)(TransferOffset));
+ WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
+ (UCHAR)(TransferOffset >> 8));
+ /* Set the Page Register */
+ WRITE_PORT_UCHAR(AdapterObject->PagePort +
+ FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
+ (UCHAR)(PhysicalAddress.u.LowPart >> 16));
+ if (HalpEisaDma)
+ {
+ WRITE_PORT_UCHAR(AdapterObject->PagePort +
+ FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
+ 0);
+ }
+ /* Set the Length */
+ WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
+ (UCHAR)(TransferLength - 1));
+ WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
+ (UCHAR)((TransferLength - 1) >> 8));
+ /* Unmask the Channel */
+ WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
+ AdapterObject->ChannelNumber | DMA_CLEARMASK);
+ }
+
+ KfReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
+ }
+
+ /*
+ * Return physical address of the buffer with data that is used for the
+ * transfer. It can either point inside the Mdl that was passed by the
+ * caller or into the map registers if the Mdl buffer can't be used
+ * directly.
+ */
+
+ return PhysicalAddress;
+}
+
+/**
+ * @name HalFlushCommonBuffer
+ *
+ * @implemented
+ */
+
+BOOLEAN STDCALL
+HalFlushCommonBuffer(
+ ULONG Unknown1,
+ ULONG Unknown2,
+ ULONG Unknown3,
+ ULONG Unknown4,
+ ULONG Unknown5)
+{
+ return TRUE;
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/drive.c b/reactos/hal/halppc/generic/drive.c
new file mode 100644
index 00000000000..281e0e121c3
--- /dev/null
+++ b/reactos/hal/halppc/generic/drive.c
@@ -0,0 +1,33 @@
+/* $Id: drive.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: hal/x86/drive.c
+ * PURPOSE: Drive letter assignment
+ * PROGRAMMER:
+ * UPDATE HISTORY:
+ * 2000-03-25
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+/* FUNCTIONS *****************************************************************/
+
+VOID STDCALL
+IoAssignDriveLetters(IN struct _LOADER_PARAMETER_BLOCK *LoaderBlock,
+ IN PSTRING NtDeviceName,
+ OUT PUCHAR NtSystemPath,
+ OUT PSTRING NtSystemPathString)
+{
+ /* FIXME FIXME FIXME FUCK SOMEONE FIXME*/
+ HalIoAssignDriveLetters(NULL,
+ NtDeviceName,
+ NtSystemPath,
+ NtSystemPathString);
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/enum.c b/reactos/hal/halppc/generic/enum.c
new file mode 100644
index 00000000000..af8b06d4a87
--- /dev/null
+++ b/reactos/hal/halppc/generic/enum.c
@@ -0,0 +1,23 @@
+/* $Id: enum.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/enum.c
+ * PURPOSE: Motherboard device enumerator
+ * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * UPDATE HISTORY:
+ * Created 01/05/2001
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+VOID
+HalpStartEnumerator (VOID)
+{
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/fmutex.c b/reactos/hal/halppc/generic/fmutex.c
new file mode 100644
index 00000000000..a7624edb748
--- /dev/null
+++ b/reactos/hal/halppc/generic/fmutex.c
@@ -0,0 +1,101 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS HAL
+ * FILE: ntoskrnl/hal/x86/fmutex.c
+ * PURPOSE: Deprecated HAL Fast Mutex
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
+ */
+
+/*
+ * NOTE: Even HAL itself has #defines to use the Exi* APIs inside NTOSKRNL.
+ * These are only exported here for compatibility with really old
+ * drivers. Also note that in theory, these can be made much faster
+ * by using assembly and inlining all the operations, including
+ * raising and lowering irql.
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+#undef ExAcquireFastMutex
+#undef ExReleaseFastMutex
+#undef ExTryToAcquireFastMutex
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+FASTCALL
+ExAcquireFastMutex(PFAST_MUTEX FastMutex)
+{
+ KIRQL OldIrql;
+
+ /* Raise IRQL to APC */
+ OldIrql = KfRaiseIrql(APC_LEVEL);
+
+ /* Decrease the count */
+ if (InterlockedDecrement(&FastMutex->Count))
+ {
+ /* Someone is still holding it, use slow path */
+ FastMutex->Contention++;
+ KeWaitForSingleObject(&FastMutex->Gate,
+ WrExecutive,
+ KernelMode,
+ FALSE,
+ NULL);
+ }
+
+ /* Set the owner and IRQL */
+ FastMutex->Owner = KeGetCurrentThread();
+ FastMutex->OldIrql = OldIrql;
+}
+
+VOID
+FASTCALL
+ExReleaseFastMutex(PFAST_MUTEX FastMutex)
+{
+ KIRQL OldIrql;
+
+ /* Erase the owner */
+ FastMutex->Owner = (PVOID)1;
+ OldIrql = FastMutex->OldIrql;
+
+ /* Increase the count */
+ if (InterlockedIncrement(&FastMutex->Count) <= 0)
+ {
+ /* Someone was waiting for it, signal the waiter */
+ KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT);
+ }
+
+ /* Lower IRQL back */
+ KfLowerIrql(OldIrql);
+}
+
+BOOLEAN
+FASTCALL
+ExTryToAcquireFastMutex(PFAST_MUTEX FastMutex)
+{
+ KIRQL OldIrql;
+
+ /* Raise to APC_LEVEL */
+ OldIrql = KfRaiseIrql(APC_LEVEL);
+
+ /* Check if we can quickly acquire it */
+ if (InterlockedCompareExchange(&FastMutex->Count, 0, 1) == 1)
+ {
+ /* We have, set us as owners */
+ FastMutex->Owner = KeGetCurrentThread();
+ FastMutex->OldIrql = OldIrql;
+ return TRUE;
+ }
+ else
+ {
+ /* Acquire attempt failed */
+ KfLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/generic.rbuild b/reactos/hal/halppc/generic/generic.rbuild
new file mode 100644
index 00000000000..ab14f754594
--- /dev/null
+++ b/reactos/hal/halppc/generic/generic.rbuild
@@ -0,0 +1,26 @@
+
+ ../include
+ include
+
+
+
+ beep.c
+ bus.c
+ dma.c
+ drive.c
+ enum.c
+ fmutex.c
+ halinit.c
+ isa.c
+ kdbg.c
+ mca.c
+ misc.c
+ pci.c
+ portio.c
+ reboot.c
+ sysbus.c
+ sysinfo.c
+ time.c
+ timer.c
+ ../include/hal.h
+
diff --git a/reactos/hal/halppc/generic/halinit.c b/reactos/hal/halppc/generic/halinit.c
new file mode 100644
index 00000000000..fe78f9bc438
--- /dev/null
+++ b/reactos/hal/halppc/generic/halinit.c
@@ -0,0 +1,69 @@
+/* $Id: halinit.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/halinit.c
+ * PURPOSE: Initalize the x86 hal
+ * PROGRAMMER: David Welch (welch@cwcom.net)
+ * UPDATE HISTORY:
+ * 11/06/98: Created
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+/* GLOBALS *****************************************************************/
+
+PVOID HalpZeroPageMapping = NULL;
+HALP_HOOKS HalpHooks;
+
+/* FUNCTIONS ***************************************************************/
+
+NTSTATUS
+STDCALL
+DriverEntry(
+ PDRIVER_OBJECT DriverObject,
+ PUNICODE_STRING RegistryPath)
+{
+ return STATUS_SUCCESS;
+}
+
+BOOLEAN STDCALL
+HalInitSystem (ULONG BootPhase,
+ PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ if (BootPhase == 0)
+ {
+ RtlZeroMemory(&HalpHooks, sizeof(HALP_HOOKS));
+ HalpInitPhase0((PROS_LOADER_PARAMETER_BLOCK)LoaderBlock);
+ }
+ else if (BootPhase == 1)
+ {
+ /* Initialize the clock interrupt */
+ //HalpInitPhase1();
+
+ /* Initialize display and make the screen black */
+ HalInitializeDisplay ((PROS_LOADER_PARAMETER_BLOCK)LoaderBlock);
+ HalpInitBusHandlers();
+ HalpInitDma();
+
+ /* Enumerate the devices on the motherboard */
+ HalpStartEnumerator();
+ }
+ else if (BootPhase == 2)
+ {
+ PHYSICAL_ADDRESS Null = {{0}};
+
+ /* Go to blue screen */
+ HalClearDisplay (0x17); /* grey on blue */
+
+ HalpZeroPageMapping = MmMapIoSpace(Null, PAGE_SIZE, MmNonCached);
+ }
+
+ return TRUE;
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/ipi.c b/reactos/hal/halppc/generic/ipi.c
new file mode 100644
index 00000000000..739de8d716c
--- /dev/null
+++ b/reactos/hal/halppc/generic/ipi.c
@@ -0,0 +1,24 @@
+/* $Id: ipi.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: hal/halx86/generic/ipi.c
+ * PURPOSE: Miscellaneous hardware functions
+ * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+/* FUNCTIONS ****************************************************************/
+
+VOID STDCALL
+HalRequestIpi(ULONG ProcessorNo)
+{
+ DPRINT("HalRequestIpi(ProcessorNo %lu)\n", ProcessorNo);
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/irq.S b/reactos/hal/halppc/generic/irq.S
new file mode 100644
index 00000000000..585bb4c83b8
--- /dev/null
+++ b/reactos/hal/halppc/generic/irq.S
@@ -0,0 +1,631 @@
+/*
+ * FILE: hal/halx86/generic/irql.S
+ * COPYRIGHT: See COPYING in the top level directory
+ * PURPOSE: Software, System and Hardware IRQ Management
+ * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include
+#include
+.intel_syntax noprefix
+
+/* GLOBALS *******************************************************************/
+
+PICInitTable:
+
+ /* Master PIC */
+ .short 0x20 /* Port */
+ .byte 0x11 /* Edge,, cascade, CAI 8, ICW4 */
+ .byte PRIMARY_VECTOR_BASE /* Base */
+ .byte 4 /* IRQ 4 connected to slave */
+ .byte 1 /* Non buffered, not nested, 8086 */
+
+ /* Slave PIC */
+ .short 0xA0 /* Port */
+ .byte 0x11 /* Edge, cascade, CAI 8, ICW4 */
+ .byte PRIMARY_VECTOR_BASE + 8 /* Base */
+ .byte 2 /* Slave ID: Slave 2 */
+ .byte 1 /* Non buffered, not nested, 8086 */
+
+ /* End of initialization table */
+ .short 0
+
+KiI8259MaskTable:
+ .long 0 /* IRQL 0 */
+ .long 0 /* IRQL 1 */
+ .long 0 /* IRQL 2 */
+ .long 0 /* IRQL 3 */
+ .long 0xFF800000 /* IRQL 4 */
+ .long 0xFFC00000 /* IRQL 5 */
+ .long 0xFFE00000 /* IRQL 6 */
+ .long 0xFFF00000 /* IRQL 7 */
+ .long 0xFFF80000 /* IRQL 8 */
+ .long 0xFFFC0000 /* IRQL 9 */
+ .long 0xFFFE0000 /* IRQL 10 */
+ .long 0xFFFF0000 /* IRQL 11 */
+ .long 0xFFFF8000 /* IRQL 12 */
+ .long 0xFFFFC000 /* IRQL 13 */
+ .long 0xFFFFE000 /* IRQL 14 */
+ .long 0xFFFFF000 /* IRQL 15 */
+ .long 0xFFFFF800 /* IRQL 16 */
+ .long 0xFFFFFC00 /* IRQL 17 */
+ .long 0xFFFFFE00 /* IRQL 18 */
+ .long 0xFFFFFE00 /* IRQL 19 */
+ .long 0xFFFFFE80 /* IRQL 20 */
+ .long 0xFFFFFEC0 /* IRQL 21 */
+ .long 0xFFFFFEE0 /* IRQL 22 */
+ .long 0xFFFFFEF0 /* IRQL 23 */
+ .long 0xFFFFFEF8 /* IRQL 24 */
+ .long 0xFFFFFEF8 /* IRQL 25 */
+ .long 0xFFFFFEFA /* IRQL 26 */
+ .long 0xFFFFFFFA /* IRQL 27 */
+ .long 0xFFFFFFFB /* IRQL 28 */
+ .long 0xFFFFFFFB /* IRQL 29 */
+ .long 0xFFFFFFFB /* IRQL 30 */
+ .long 0xFFFFFFFB /* IRQL 31 */
+
+HalpSysIntHandler:
+.rept 8
+ .long GenericIRQ /* IRQ 0-7 */
+.endr
+ .long IRQ7 /* IRQ 7 */
+.rept 8
+ .long GenericIRQ /* IRQ 8-15 */
+.endr
+ .long IRQ15 /* IRQ 15 */
+.rept 20
+ .long GenericIRQ /* IRQ 16-35 */
+.endr
+
+SoftIntByteTable:
+ .byte PASSIVE_LEVEL /* IRR 0 */
+ .byte PASSIVE_LEVEL /* IRR 1 */
+ .byte APC_LEVEL /* IRR 2 */
+ .byte APC_LEVEL /* IRR 3 */
+ .byte DISPATCH_LEVEL /* IRR 4 */
+ .byte DISPATCH_LEVEL /* IRR 5 */
+ .byte DISPATCH_LEVEL /* IRR 6 */
+ .byte DISPATCH_LEVEL /* IRR 7 */
+
+SoftIntHandlerTable:
+ .long _KiUnexpectedInterrupt /* PASSIVE_LEVEL */
+ .long _HalpApcInterrupt /* APC_LEVEL */
+ .long _HalpDispatchInterrupt /* DISPATCH_LEVEL */
+
+SoftIntHandlerTable2:
+ .long _KiUnexpectedInterrupt /* PASSIVE_LEVEL */
+ .long _HalpApcInterrupt2ndEntry /* APC_LEVEL */
+ .long _HalpDispatchInterrupt2ndEntry /* DISPATCH_LEVEL */
+
+/* FUNCTIONS *****************************************************************/
+
+.globl _HalpInitPICs@0
+.func HalpInitPICs@0
+_HalpInitPICs@0:
+
+ /* Save ESI and disable interrupts */
+ push esi
+ pushf
+ cli
+
+ /* Read the init table */
+ lea esi, PICInitTable
+ lodsw
+
+InitLoop:
+
+ /* Put the port in EDX */
+ movzx edx, ax
+
+ /* Initialize the PIC, using a delay for each command */
+ outsb
+ jmp $+2
+ inc edx
+ outsb
+ jmp $+2
+ outsb
+ jmp $+2
+ outsb
+ jmp $+2
+
+ /* Mask all interrupts */
+ mov al, 0xFF
+ out dx, al
+
+ /* Check if we're done, otherwise initialize next PIC */
+ lodsw
+ cmp ax, 0
+ jnz InitLoop
+
+ /* Restore interrupts and return */
+ or dword ptr [esp], EFLAGS_INTERRUPT_MASK
+ popf
+ pop esi
+ ret
+.endfunc
+
+.globl @HalRequestSoftwareInterrupt@4
+.func @HalRequestSoftwareInterrupt@4
+_@HalRequestSoftwareInterrupt@4:
+@HalRequestSoftwareInterrupt@4:
+
+ /* Get IRR mask */
+ mov eax, 1
+ shl eax, cl
+
+ /* Disable interrupts */
+ pushf
+ cli
+
+ /* Set IRR and get IRQL */
+ or [fs:KPCR_IRR], eax
+ mov cl, [fs:KPCR_IRQL]
+
+ /* Get software IRR mask */
+ mov eax, [fs:KPCR_IRR]
+ and eax, 3
+
+ /* Get highest pending software interrupt and check if it's higher */
+ xor edx, edx
+ mov dl, SoftIntByteTable[eax]
+ cmp dl, cl
+ jbe AfterCall
+
+ /* Call the pending interrupt */
+ call SoftIntHandlerTable[edx*4]
+
+AfterCall:
+
+ /* Retore interrupts and return */
+ popf
+ ret
+.endfunc
+
+.globl _HalDisableSystemInterrupt@8
+.func HalDisableSystemInterrupt@8
+_HalDisableSystemInterrupt@8:
+
+ /* Convert to vector */
+ movzx ecx, byte ptr [esp+4]
+ sub ecx, PRIMARY_VECTOR_BASE
+
+ /* Disable interrupts and set the new IDR */
+ mov edx, 1
+ shl edx, cl
+ cli
+ or [fs:KPCR_IDR], edx
+
+ /* Get the current mask */
+ xor eax, eax
+ in al, 0xA1
+ shl eax, 8
+ in al, 0x21
+
+ /* Mask off the interrupt and write the new mask */
+ or eax, edx
+ out 0x21, al
+ shr eax, 8
+ out 0xA1, al
+
+ /* Return with interrupts enabled */
+ in al, 0xA1
+ sti
+ ret 8
+.endfunc
+
+.globl _HalEnableSystemInterrupt@12
+.func HalEnableSystemInterrupt@12
+_HalEnableSystemInterrupt@12:
+
+ /* Get the vector and validate it */
+ movzx ecx, byte ptr [esp+4]
+ sub ecx, PRIMARY_VECTOR_BASE
+ jb Invalid
+ cmp ecx, CLOCK2_LEVEL
+ jnb Invalid
+
+ /* Get the current PCI Edge/Level control registers */
+ mov edx, 0x4D1
+ in al, dx
+ shl ax, 8
+ mov eax, 0x4D0
+ in al, dx
+ mov dx, 1
+ shl dx, cl
+
+ /* Check if this is a latched interrupt */
+ cmp dword ptr [esp+12], 0
+ jnz Latched
+
+ /* Use OR for edge interrupt */
+ or ax, dx
+ jmp AfterMask
+Latched:
+
+ /* Mask it out for level interrupt */
+ not dx
+ and ax, dx
+
+AfterMask:
+
+ /* Set the PCI Edge/Level control registers */
+ mov edx, 0x4D0
+ out dx, al
+ shr ax, 8
+ mov edx, 0x4D1
+ out dx, al
+
+ /* Calculate the new IDR */
+ mov eax, 1
+ shl eax, cl
+ not eax
+ cli
+ and [fs:KPCR_IDR], eax
+
+ /* Get the current IRQL and mask the IRQs in the PIC */
+ movzx eax, byte ptr [fs:KPCR_IRQL]
+ mov eax, KiI8259MaskTable[eax*4]
+ or eax, [fs:KPCR_IDR]
+ out 0x21, al
+ shr eax, 8
+ out 0xA1, al
+
+ /* Enable interrupts and return TRUE */
+ sti
+ mov eax, 1
+ ret 12
+
+Invalid:
+
+ /* Fail, invalid IRQ */
+ xor eax, eax
+ ret 12
+.endfunc
+
+.globl _HalBeginSystemInterrupt@12
+.func HalBeginSystemInterrupt@12
+_HalBeginSystemInterrupt@12:
+
+ /* Convert to IRQ and call the handler */
+ mov edx, [esp+8]
+ sub edx, PRIMARY_VECTOR_BASE
+ jmp HalpSysIntHandler[edx*4]
+
+IRQ15:
+ /* This is IRQ 15, check if it's spurious */
+ mov al, 0xB
+ out 0xA0, al
+ in al, 0xA0
+ test al, 0x80
+ jnz GenericIRQ
+
+ /* Cascaded interrupt... dismiss it and return FALSE */
+ mov al, 0x62
+ out 0x20, al
+ mov eax, 0
+ ret 12
+
+IRQ7:
+ /* This is IRQ 7, check if it's spurious */
+ mov al, 0xB
+ out 0x20, al
+ in al, 0x20
+ test al, 0x80
+ jnz GenericIRQ
+
+ /* It is, return FALSE */
+ mov eax, 0
+ ret 12
+
+GenericIRQ:
+ /* Return the current IRQL */
+ mov eax, [esp+12]
+ movzx ecx, byte ptr [fs:KPCR_IRQL]
+ mov [eax], cl
+
+ /* Set the new IRQL */
+ movzx eax, byte ptr [esp+4]
+ mov [fs:KPCR_IRQL], al
+
+ /* Set IRQ mask in the PIC */
+ mov eax, KiI8259MaskTable[eax*4]
+ or eax, [fs:KPCR_IDR]
+ out 0x21, al
+ shr eax, 8
+ out 0xA1, al
+
+ /* Check to which PIC the EOI was sent */
+ mov eax, edx
+ cmp eax, 8
+ jnb Pic1
+
+ /* Write mask to master PIC */
+ or al, 0x60
+ out 0x20, al
+ jmp DoneBegin
+
+Pic1:
+ /* Write mask to slave PIC */
+ mov al, 0x20
+ out 0xA0, al
+ mov al, 0x62
+ out 0x20, al
+
+DoneBegin:
+ /* Enable interrupts and return TRUE */
+ in al, 0x21
+ sti
+ mov eax, 1
+ ret 12
+.endfunc
+
+.globl _HalEndSystemInterrupt@8
+.func HalEndSystemInterrupt@8
+_HalEndSystemInterrupt@8:
+
+ /* Get the IRQL and check if it's a software interrupt */
+ movzx ecx, byte ptr [esp+4]
+ cmp byte ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
+ jbe SkipMask2
+
+ /* Hardware interrupt, mask the appropriate IRQs in the PIC */
+ mov eax, KiI8259MaskTable[ecx*4]
+ or eax, [fs:KPCR_IDR]
+ out 0x21, al
+ shr eax, 8
+ out 0xA1, al
+
+SkipMask2:
+
+ /* Set IRQL and check if there are pending software interrupts */
+ mov [fs:KPCR_IRQL], cl
+ mov eax, [fs:KPCR_IRR]
+ mov al, SoftIntByteTable[eax]
+ cmp al, cl
+ ja DoCall
+ ret 8
+
+DoCall:
+
+ /* There are pending software interrupts, call their handlers */
+ add esp, 12
+ jmp SoftIntHandlerTable2[eax*4]
+.endfunc
+
+.globl @KfLowerIrql@4
+.func @KfLowerIrql@4
+_@KfLowerIrql@4:
+@KfLowerIrql@4:
+
+ /* Save flags since we'll disable interrupts */
+ pushf
+
+ /* Disable interrupts and check if IRQL is below DISPATCH_LEVEL */
+ movzx ecx, cl
+ cmp byte ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
+ cli
+ jbe SkipMask
+
+ /* Clear interrupt masks since there's a pending hardware interrupt */
+ mov eax, KiI8259MaskTable[ecx*4]
+ or eax, [fs:KPCR_IDR]
+ out 0x21, al
+ shr eax, 8
+ out 0xA1, al
+
+SkipMask:
+
+ /* Set the new IRQL and check if there's a pending software interrupt */
+ mov [fs:KPCR_IRQL], cl
+ mov eax, [fs:KPCR_IRR]
+ mov al, SoftIntByteTable[eax]
+ cmp al, cl
+ jbe DoCall3
+
+ /* There is, call it */
+ call SoftIntHandlerTable[eax*4]
+
+DoCall3:
+
+ /* Restore interrupts and return */
+ popf
+ ret
+.endfunc
+
+.globl @KfRaiseIrql@4
+.func @KfRaiseIrql@4
+_@KfRaiseIrql@4:
+@KfRaiseIrql@4:
+
+ /* Get the IRQL and check if it's Software level only */
+ xor eax, eax
+ mov al, [fs:KPCR_IRQL]
+ movzx ecx, cl
+ cmp cl, DISPATCH_LEVEL
+ jbe SetIrql
+
+ /* Save the current IRQL */
+ mov edx, eax
+
+ /* It's a hardware IRQL, so disable interrupts */
+ pushf
+ cli
+
+ /* Set the new IRQL */
+ mov [fs:KPCR_IRQL], cl
+
+ /* Mask the interrupts in the PIC */
+ mov eax, KiI8259MaskTable[ecx*4]
+ or eax, [fs:KPCR_IDR]
+ out 0x21, al
+ shr eax, 8
+ out 0xA1, al
+
+ /* Restore interrupts and return old IRQL */
+ popf
+ mov eax, edx
+ ret
+
+SetIrql:
+
+ /* Set the IRQL and return */
+ mov [fs:KPCR_IRQL], cl
+ ret
+.endfunc
+
+.globl _KeGetCurrentIrql@0
+.func KeGetCurrentIrql@0
+_KeGetCurrentIrql@0:
+
+ /* Return the IRQL */
+ movzx eax, word ptr [fs:KPCR_IRQL]
+ ret
+.endfunc
+
+.globl _KeRaiseIrqlToDpcLevel@0
+.func KeRaiseIrqlToDpcLevel@0
+_KeRaiseIrqlToDpcLevel@0:
+
+ /* Get the current IRQL */
+ xor eax, eax
+ mov al, [fs:KPCR_IRQL]
+
+ /* Set DISPATCH_LEVEL */
+ mov byte ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
+ ret
+.endfunc
+
+.globl _KeRaiseIrqlToSynchLevel@0
+.func KeRaiseIrqlToSynchLevel@0
+_KeRaiseIrqlToSynchLevel@0:
+
+ /* Disable interrupts */
+ pushf
+ cli
+
+ /* Mask out interrupts */
+ mov eax, KiI8259MaskTable[DISPATCH_LEVEL*4]
+ or eax, [fs:KPCR_IDR]
+ out 0x21, al
+ shr eax, 8
+ out 0xA1, al
+
+ /* Return the old IRQL, enable interrupts and set to DISPATCH */
+ mov al, [fs:KPCR_IRQL]
+ mov byte ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
+ popf
+ ret
+.endfunc
+
+.globl _HalpApcInterrupt
+.func HalpApcInterrupt
+_HalpApcInterrupt:
+
+ /* Create fake interrupt stack */
+ pop eax
+ pushf
+ push cs
+ push eax
+
+ /* Enter interrupt */
+ INT_PROLOG hapc, DoPushFakeErrorCode
+.endfunc
+
+.globl _HalpApcInterrupt2ndEntry
+.func HalpApcInterrupt2ndEntry
+_HalpApcInterrupt2ndEntry:
+
+ /* Save current IRQL and set to APC level */
+ push [fs:KPCR_IRQL]
+ mov byte ptr [fs:KPCR_IRQL], APC_LEVEL
+ and dword ptr [fs:KPCR_IRR], ~(1 << APC_LEVEL)
+
+ /* Enable interrupts and check if we came from User/V86 mode */
+ sti
+ mov eax, [ebp+KTRAP_FRAME_CS]
+ and eax, MODE_MASK
+ test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
+ jz DeliverApc
+
+ /* Set user mode delivery */
+ or eax, UserMode
+
+DeliverApc:
+
+ /* Deliver the APCs */
+ push ebp
+ push 0
+ push eax
+ call _KiDeliverApc@12
+
+ /* Disable interrupts and end it */
+ cli
+ call _HalpEndSoftwareInterrupt@4
+ jmp _Kei386EoiHelper@0
+.endfunc
+
+.globl _HalpDispatchInterrupt
+.func HalpDispatchInterrupt
+_HalpDispatchInterrupt:
+
+ /* Create fake interrupt stack */
+ pop eax
+ pushf
+ push cs
+ push eax
+
+ /* Enter interrupt */
+ INT_PROLOG hapc, DoPushFakeErrorCode
+.endfunc
+
+.globl _HalpDispatchInterrupt2ndEntry
+.func HalpDispatchInterrupt2ndEntry
+_HalpDispatchInterrupt2ndEntry:
+
+ /* Save current IRQL and set to DPC level */
+ push [fs:KPCR_IRQL]
+ mov byte ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
+ and dword ptr [fs:KPCR_IRR], ~(1 << DISPATCH_LEVEL)
+
+ /* Enable interrupts and let the kernel handle this */
+ sti
+ call _KiDispatchInterrupt@0
+
+ /* Disable interrupts and end it */
+ cli
+ call _HalpEndSoftwareInterrupt@4
+ jmp _Kei386EoiHelper@0
+.endfunc
+
+.globl _HalpEndSoftwareInterrupt@4
+.func HalpEndSoftwareInterrupt@4
+_HalpEndSoftwareInterrupt@4:
+
+ /* Get the IRQL and check if we're in the software region */
+ movzx ecx, byte ptr [esp+4]
+ cmp byte ptr [fs:KPCR_IRQL], DISPATCH_LEVEL
+ jbe SoftwareInt
+
+ /* Set the right mask in the PIC for the hardware IRQ */
+ mov eax, KiI8259MaskTable[ecx*4]
+ or eax, [fs:KPCR_IDR]
+ out 0x21, al
+ shr eax, 8
+ out 0xA1, al
+
+SoftwareInt:
+ /* Check if there are pending software interrupts */
+ mov [fs:KPCR_IRQL], cl
+ mov eax, [fs:KPCR_IRR]
+ mov al, SoftIntByteTable[eax]
+ cmp al, cl
+ ja DoCall2
+ ret 4
+
+DoCall2:
+ /* There are pending softwate interrupts, call their handlers */
+ add esp, 8
+ jmp SoftIntHandlerTable2[eax*4]
+.endfunc
diff --git a/reactos/hal/halppc/generic/irql.c b/reactos/hal/halppc/generic/irql.c
new file mode 100644
index 00000000000..fd55e42c1f7
--- /dev/null
+++ b/reactos/hal/halppc/generic/irql.c
@@ -0,0 +1,425 @@
+/* $Id$
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/irql.c
+ * PURPOSE: Implements IRQLs
+ * PROGRAMMER: David Welch (welch@cwcom.net)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+/* GLOBALS ******************************************************************/
+
+/*
+ * FIXME: Use EISA_CONTROL STRUCTURE INSTEAD OF HARD-CODED OFFSETS
+*/
+
+typedef union
+{
+ USHORT both;
+ struct
+ {
+ BYTE master;
+ BYTE slave;
+ };
+}
+PIC_MASK;
+
+/*
+ * PURPOSE: - Mask for HalEnableSystemInterrupt and HalDisableSystemInterrupt
+ * - At startup enable timer and cascade
+ */
+#if defined(__GNUC__)
+static PIC_MASK pic_mask = {.both = 0xFFFA};
+#else
+static PIC_MASK pic_mask = { 0xFFFA };
+#endif
+
+
+/*
+ * PURPOSE: Mask for disabling of acknowledged interrupts
+ */
+#if defined(__GNUC__)
+static PIC_MASK pic_mask_intr = {.both = 0x0000};
+#else
+static PIC_MASK pic_mask_intr = { 0 };
+#endif
+
+static ULONG HalpPendingInterruptCount[NR_IRQS];
+
+#define DIRQL_TO_IRQ(x) (PROFILE_LEVEL - x)
+#define IRQ_TO_DIRQL(x) (PROFILE_LEVEL - x)
+
+VOID STDCALL
+KiInterruptDispatch2 (ULONG Irq, KIRQL old_level);
+
+/* FUNCTIONS ****************************************************************/
+
+#undef KeGetCurrentIrql
+KIRQL STDCALL KeGetCurrentIrql (VOID)
+/*
+ * PURPOSE: Returns the current irq level
+ * RETURNS: The current irq level
+ */
+{
+ return(KeGetPcr()->Irql);
+}
+
+VOID NTAPI HalpInitPICs(VOID)
+{
+ memset(HalpPendingInterruptCount, 0, sizeof(HalpPendingInterruptCount));
+
+ /* Initialization sequence */
+ WRITE_PORT_UCHAR((PUCHAR)0x20, 0x11);
+ WRITE_PORT_UCHAR((PUCHAR)0xa0, 0x11);
+ /* Start of hardware irqs (0x24) */
+ WRITE_PORT_UCHAR((PUCHAR)0x21, IRQ_BASE);
+ WRITE_PORT_UCHAR((PUCHAR)0xa1, IRQ_BASE + 8);
+ /* 8259-1 is master */
+ WRITE_PORT_UCHAR((PUCHAR)0x21, 0x4);
+ /* 8259-2 is slave */
+ WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x2);
+ /* 8086 mode */
+ WRITE_PORT_UCHAR((PUCHAR)0x21, 0x1);
+ WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x1);
+ /* Enable interrupts */
+ WRITE_PORT_UCHAR((PUCHAR)0x21, pic_mask.master);
+ WRITE_PORT_UCHAR((PUCHAR)0xa1, pic_mask.slave);
+
+ /* We can now enable interrupts */
+ Ki386EnableInterrupts();
+}
+
+VOID HalpEndSystemInterrupt(KIRQL Irql)
+/*
+ * FUNCTION: Enable all irqs with higher priority.
+ */
+{
+ ULONG flags;
+ const USHORT mask[] =
+ {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0xc000, 0xe000, 0xf000,
+ 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80, 0xffc0, 0xffe0, 0xfff0,
+ 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
+ };
+
+ /* Interrupts should be disable while enabling irqs of both pics */
+ Ki386SaveFlags(flags);
+ Ki386DisableInterrupts();
+
+ pic_mask_intr.both &= mask[Irql];
+ WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master));
+ WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave));
+
+ /* restore flags */
+ Ki386RestoreFlags(flags);
+}
+
+VOID STATIC
+HalpExecuteIrqs(KIRQL NewIrql)
+{
+ ULONG IrqLimit, i;
+
+ IrqLimit = min(PROFILE_LEVEL - NewIrql, NR_IRQS);
+
+ /*
+ * For each irq if there have been any deferred interrupts then now
+ * dispatch them.
+ */
+ for (i = 0; i < IrqLimit; i++)
+ {
+ if (HalpPendingInterruptCount[i] > 0)
+ {
+ KeGetPcr()->Irql = (KIRQL)IRQ_TO_DIRQL(i);
+
+ while (HalpPendingInterruptCount[i] > 0)
+ {
+ /*
+ * For each deferred interrupt execute all the handlers at DIRQL.
+ */
+ HalpPendingInterruptCount[i]--;
+ KiInterruptDispatch2(i + IRQ_BASE, NewIrql);
+ }
+ KeGetPcr()->Irql--;
+ HalpEndSystemInterrupt(KeGetPcr()->Irql);
+ }
+ }
+
+}
+
+VOID STATIC
+HalpLowerIrql(KIRQL NewIrql)
+{
+ if (NewIrql >= PROFILE_LEVEL)
+ {
+ KeGetPcr()->Irql = NewIrql;
+ return;
+ }
+ HalpExecuteIrqs(NewIrql);
+ if (NewIrql >= DISPATCH_LEVEL)
+ {
+ KeGetPcr()->Irql = NewIrql;
+ return;
+ }
+ KeGetPcr()->Irql = DISPATCH_LEVEL;
+ if (((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST])
+ {
+ ((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = FALSE;
+ KiDispatchInterrupt();
+ }
+ KeGetPcr()->Irql = APC_LEVEL;
+ if (NewIrql == APC_LEVEL)
+ {
+ return;
+ }
+ if (KeGetCurrentThread() != NULL &&
+ KeGetCurrentThread()->ApcState.KernelApcPending)
+ {
+ KiDeliverApc(KernelMode, NULL, NULL);
+ }
+ KeGetPcr()->Irql = PASSIVE_LEVEL;
+}
+
+/**********************************************************************
+ * NAME EXPORTED
+ * KfLowerIrql
+ *
+ * DESCRIPTION
+ * Restores the irq level on the current processor
+ *
+ * ARGUMENTS
+ * NewIrql = Irql to lower to
+ *
+ * RETURN VALUE
+ * None
+ *
+ * NOTES
+ * Uses fastcall convention
+ */
+VOID FASTCALL
+KfLowerIrql (KIRQL NewIrql)
+{
+ DPRINT("KfLowerIrql(NewIrql %d)\n", NewIrql);
+
+ if (NewIrql > KeGetPcr()->Irql)
+ {
+ DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n",
+ __FILE__, __LINE__, NewIrql, KeGetPcr()->Irql);
+ KEBUGCHECK(0);
+ for(;;);
+ }
+
+ HalpLowerIrql(NewIrql);
+}
+
+/**********************************************************************
+ * NAME EXPORTED
+ * KfRaiseIrql
+ *
+ * DESCRIPTION
+ * Raises the hardware priority (irql)
+ *
+ * ARGUMENTS
+ * NewIrql = Irql to raise to
+ *
+ * RETURN VALUE
+ * previous irq level
+ *
+ * NOTES
+ * Uses fastcall convention
+ */
+
+KIRQL FASTCALL
+KfRaiseIrql (KIRQL NewIrql)
+{
+ KIRQL OldIrql;
+
+ DPRINT("KfRaiseIrql(NewIrql %d)\n", NewIrql);
+
+ if (NewIrql < KeGetPcr()->Irql)
+ {
+ DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n",
+ __FILE__,__LINE__,KeGetPcr()->Irql,NewIrql);
+ KEBUGCHECK (0);
+ for(;;);
+ }
+
+ OldIrql = KeGetPcr()->Irql;
+ KeGetPcr()->Irql = NewIrql;
+ return OldIrql;
+}
+
+/**********************************************************************
+ * NAME EXPORTED
+ * KeRaiseIrqlToDpcLevel
+ *
+ * DESCRIPTION
+ * Raises the hardware priority (irql) to DISPATCH level
+ *
+ * ARGUMENTS
+ * None
+ *
+ * RETURN VALUE
+ * Previous irq level
+ *
+ * NOTES
+ * Calls KfRaiseIrql
+ */
+
+KIRQL STDCALL
+KeRaiseIrqlToDpcLevel (VOID)
+{
+ return KfRaiseIrql (DISPATCH_LEVEL);
+}
+
+
+/**********************************************************************
+ * NAME EXPORTED
+ * KeRaiseIrqlToSynchLevel
+ *
+ * DESCRIPTION
+ * Raises the hardware priority (irql) to CLOCK2 level
+ *
+ * ARGUMENTS
+ * None
+ *
+ * RETURN VALUE
+ * Previous irq level
+ *
+ * NOTES
+ * Calls KfRaiseIrql
+ */
+
+KIRQL STDCALL
+KeRaiseIrqlToSynchLevel (VOID)
+{
+ return KfRaiseIrql (CLOCK2_LEVEL);
+}
+
+
+BOOLEAN STDCALL
+HalBeginSystemInterrupt (KIRQL Irql,
+ ULONG Vector,
+ PKIRQL OldIrql)
+{
+ ULONG irq;
+ if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
+ {
+ return(FALSE);
+ }
+ irq = Vector - IRQ_BASE;
+ pic_mask_intr.both |= ((1 << irq) & 0xfffe); // do not disable the timer interrupt
+
+ if (irq < 8)
+ {
+ WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master));
+ WRITE_PORT_UCHAR((PUCHAR)0x20, 0x20);
+ }
+ else
+ {
+ WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave));
+ /* Send EOI to the PICs */
+ WRITE_PORT_UCHAR((PUCHAR)0x20,0x20);
+ WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20);
+ }
+
+ if (KeGetPcr()->Irql >= Irql)
+ {
+ HalpPendingInterruptCount[irq]++;
+ return(FALSE);
+ }
+ *OldIrql = KeGetPcr()->Irql;
+ KeGetPcr()->Irql = Irql;
+
+ return(TRUE);
+}
+
+
+VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, ULONG Unknown2)
+/*
+ * FUNCTION: Finish a system interrupt and restore the specified irq level.
+ */
+{
+ HalpLowerIrql(Irql);
+ HalpEndSystemInterrupt(Irql);
+}
+
+BOOLEAN
+STDCALL
+HalDisableSystemInterrupt(
+ ULONG Vector,
+ KIRQL Irql)
+{
+ ULONG irq;
+
+ if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
+ return FALSE;
+
+ irq = Vector - IRQ_BASE;
+ pic_mask.both |= (1 << irq);
+ if (irq < 8)
+ {
+ WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.slave));
+ }
+ else
+ {
+ WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave));
+ }
+
+ return TRUE;
+}
+
+
+BOOLEAN
+STDCALL
+HalEnableSystemInterrupt(
+ ULONG Vector,
+ KIRQL Irql,
+ KINTERRUPT_MODE InterruptMode)
+{
+ ULONG irq;
+
+ if (Vector < IRQ_BASE || Vector >= IRQ_BASE + NR_IRQS)
+ return FALSE;
+
+ irq = Vector - IRQ_BASE;
+ pic_mask.both &= ~(1 << irq);
+ if (irq < 8)
+ {
+ WRITE_PORT_UCHAR((PUCHAR)0x21, (UCHAR)(pic_mask.master|pic_mask_intr.master));
+ }
+ else
+ {
+ WRITE_PORT_UCHAR((PUCHAR)0xa1, (UCHAR)(pic_mask.slave|pic_mask_intr.slave));
+ }
+
+ return TRUE;
+}
+
+
+VOID FASTCALL
+HalRequestSoftwareInterrupt(
+ IN KIRQL Request)
+{
+ switch (Request)
+ {
+ case APC_LEVEL:
+ ((PKIPCR)KeGetPcr())->HalReserved[HAL_APC_REQUEST] = TRUE;
+ break;
+
+ case DISPATCH_LEVEL:
+ ((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = TRUE;
+ break;
+
+ default:
+ KEBUGCHECK(0);
+ }
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/isa.c b/reactos/hal/halppc/generic/isa.c
new file mode 100644
index 00000000000..665bb1edd45
--- /dev/null
+++ b/reactos/hal/halppc/generic/isa.c
@@ -0,0 +1,75 @@
+/* $Id: isa.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/isa.c
+ * PURPOSE: Interfaces to the ISA bus
+ * PROGRAMMER: David Welch (welch@mcmail.com)
+ * UPDATE HISTORY:
+ * 05/06/98: Created
+ */
+
+/* INCLUDES ***************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+/* FUNCTIONS *****************************************************************/
+
+BOOLEAN HalIsaProbe(VOID)
+/*
+ * FUNCTION: Probes for an ISA bus
+ * RETURNS: True if detected
+ * NOTE: Since ISA is the default we are called last and always return
+ * true
+ */
+{
+ DbgPrint("Assuming ISA bus\n");
+
+ /*
+ * Probe for plug and play support
+ */
+ return(TRUE);
+}
+
+
+BOOLEAN STDCALL
+HalpTranslateIsaBusAddress(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ PHYSICAL_ADDRESS BusAddress,
+ PULONG AddressSpace,
+ PPHYSICAL_ADDRESS TranslatedAddress)
+{
+ BOOLEAN Result;
+
+ Result = HalTranslateBusAddress(PCIBus,
+ BusNumber,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress);
+ if (Result != FALSE)
+ return Result;
+
+ Result = HalTranslateBusAddress(Internal,
+ BusNumber,
+ BusAddress,
+ AddressSpace,
+ TranslatedAddress);
+ return Result;
+}
+
+ULONG STDCALL
+HalpGetIsaInterruptVector(PVOID BusHandler,
+ ULONG BusNumber,
+ ULONG BusInterruptLevel,
+ ULONG BusInterruptVector,
+ PKIRQL Irql,
+ PKAFFINITY Affinity)
+{
+ ULONG Vector = IRQ2VECTOR(BusInterruptVector);
+ *Irql = VECTOR2IRQL(Vector);
+ *Affinity = 0xFFFFFFFF;
+ return Vector;
+}
+/* EOF */
diff --git a/reactos/hal/halppc/generic/kdbg.c b/reactos/hal/halppc/generic/kdbg.c
new file mode 100644
index 00000000000..fdc0e223ae4
--- /dev/null
+++ b/reactos/hal/halppc/generic/kdbg.c
@@ -0,0 +1,547 @@
+/* $Id: kdbg.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/kdbg.c
+ * PURPOSE: Serial i/o functions for the kernel debugger.
+ * PROGRAMMER: Emanuele Aliberti
+ * Eric Kohl
+ * UPDATE HISTORY:
+ * Created 05/09/99
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+
+#define DEFAULT_BAUD_RATE 19200
+
+
+/* MACROS *******************************************************************/
+
+#define SER_RBR(x) ((x)+0)
+#define SER_THR(x) ((x)+0)
+#define SER_DLL(x) ((x)+0)
+#define SER_IER(x) ((x)+1)
+#define SR_IER_ERDA 0x01
+#define SR_IER_ETHRE 0x02
+#define SR_IER_ERLSI 0x04
+#define SR_IER_EMS 0x08
+#define SR_IER_ALL 0x0F
+#define SER_DLM(x) ((x)+1)
+#define SER_IIR(x) ((x)+2)
+#define SER_FCR(x) ((x)+2)
+#define SR_FCR_ENABLE_FIFO 0x01
+#define SR_FCR_CLEAR_RCVR 0x02
+#define SR_FCR_CLEAR_XMIT 0x04
+#define SER_LCR(x) ((x)+3)
+#define SR_LCR_CS5 0x00
+#define SR_LCR_CS6 0x01
+#define SR_LCR_CS7 0x02
+#define SR_LCR_CS8 0x03
+#define SR_LCR_ST1 0x00
+#define SR_LCR_ST2 0x04
+#define SR_LCR_PNO 0x00
+#define SR_LCR_POD 0x08
+#define SR_LCR_PEV 0x18
+#define SR_LCR_PMK 0x28
+#define SR_LCR_PSP 0x38
+#define SR_LCR_BRK 0x40
+#define SR_LCR_DLAB 0x80
+#define SER_MCR(x) ((x)+4)
+#define SR_MCR_DTR 0x01
+#define SR_MCR_RTS 0x02
+#define SR_MCR_OUT1 0x04
+#define SR_MCR_OUT2 0x08
+#define SR_MCR_LOOP 0x10
+#define SER_LSR(x) ((x)+5)
+#define SR_LSR_DR 0x01
+#define SR_LSR_TBE 0x20
+#define SER_MSR(x) ((x)+6)
+#define SR_MSR_CTS 0x10
+#define SR_MSR_DSR 0x20
+#define SER_SCR(x) ((x)+7)
+
+
+/* GLOBAL VARIABLES *********************************************************/
+
+ULONG KdComPortInUse = 0;
+
+
+/* STATIC VARIABLES *********************************************************/
+
+static ULONG ComPort = 0;
+static ULONG BaudRate = 0;
+static PUCHAR PortBase = (PUCHAR)0;
+
+/* The com port must only be initialized once! */
+static BOOLEAN PortInitialized = FALSE;
+
+
+/* STATIC FUNCTIONS *********************************************************/
+
+static BOOLEAN
+KdpDoesComPortExist (PUCHAR BaseAddress)
+{
+ BOOLEAN found;
+ UCHAR mcr;
+ UCHAR msr;
+
+ found = FALSE;
+
+ /* save Modem Control Register (MCR) */
+ mcr = READ_PORT_UCHAR (SER_MCR(BaseAddress));
+
+ /* enable loop mode (set Bit 4 of the MCR) */
+ WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x10);
+
+ /* clear all modem output bits */
+ WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x10);
+
+ /* read the Modem Status Register */
+ msr = READ_PORT_UCHAR (SER_MSR(BaseAddress));
+
+ /*
+ * the upper nibble of the MSR (modem output bits) must be
+ * equal to the lower nibble of the MCR (modem input bits)
+ */
+ if ((msr & 0xF0) == 0x00)
+ {
+ /* set all modem output bits */
+ WRITE_PORT_UCHAR (SER_MCR(BaseAddress), 0x1F);
+
+ /* read the Modem Status Register */
+ msr = READ_PORT_UCHAR (SER_MSR(BaseAddress));
+
+ /*
+ * the upper nibble of the MSR (modem output bits) must be
+ * equal to the lower nibble of the MCR (modem input bits)
+ */
+ if ((msr & 0xF0) == 0xF0)
+ {
+ /*
+ * setup a resonable state for the port:
+ * enable fifo and clear recieve/transmit buffers
+ */
+ WRITE_PORT_UCHAR (SER_FCR(BaseAddress),
+ (SR_FCR_ENABLE_FIFO | SR_FCR_CLEAR_RCVR | SR_FCR_CLEAR_XMIT));
+ WRITE_PORT_UCHAR (SER_FCR(BaseAddress), 0);
+ READ_PORT_UCHAR (SER_RBR(BaseAddress));
+ WRITE_PORT_UCHAR (SER_IER(BaseAddress), 0);
+ found = TRUE;
+ }
+ }
+
+ /* restore MCR */
+ WRITE_PORT_UCHAR (SER_MCR(BaseAddress), mcr);
+
+ return (found);
+}
+
+
+/* FUNCTIONS ****************************************************************/
+
+/* HAL.KdPortInitialize */
+BOOLEAN
+STDCALL
+KdPortInitialize (
+ PKD_PORT_INFORMATION PortInformation,
+ ULONG Unknown1,
+ ULONG Unknown2
+ )
+{
+ ULONG BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
+ char buffer[80];
+ ULONG divisor;
+ UCHAR lcr;
+
+ if (PortInitialized == FALSE)
+ {
+ if (PortInformation->BaudRate != 0)
+ {
+ BaudRate = PortInformation->BaudRate;
+ }
+ else
+ {
+ BaudRate = DEFAULT_BAUD_RATE;
+ }
+
+ if (PortInformation->ComPort == 0)
+ {
+ if (KdpDoesComPortExist ((PUCHAR)BaseArray[2]))
+ {
+ PortBase = (PUCHAR)BaseArray[2];
+ ComPort = 2;
+ PortInformation->BaseAddress = (ULONG)PortBase;
+ PortInformation->ComPort = ComPort;
+#ifndef NDEBUG
+ sprintf (buffer,
+ "\nSerial port COM%ld found at 0x%lx\n",
+ ComPort,
+ (ULONG)PortBase);
+ HalDisplayString (buffer);
+#endif /* NDEBUG */
+ }
+ else if (KdpDoesComPortExist ((PUCHAR)BaseArray[1]))
+ {
+ PortBase = (PUCHAR)BaseArray[1];
+ ComPort = 1;
+ PortInformation->BaseAddress = (ULONG)PortBase;
+ PortInformation->ComPort = ComPort;
+#ifndef NDEBUG
+ sprintf (buffer,
+ "\nSerial port COM%ld found at 0x%lx\n",
+ ComPort,
+ (ULONG)PortBase);
+ HalDisplayString (buffer);
+#endif /* NDEBUG */
+ }
+ else
+ {
+ sprintf (buffer,
+ "\nKernel Debugger: No COM port found!!!\n\n");
+ HalDisplayString (buffer);
+ return FALSE;
+ }
+ }
+ else
+ {
+ if (KdpDoesComPortExist ((PUCHAR)BaseArray[PortInformation->ComPort]))
+ {
+ PortBase = (PUCHAR)BaseArray[PortInformation->ComPort];
+ ComPort = PortInformation->ComPort;
+ PortInformation->BaseAddress = (ULONG)PortBase;
+#ifndef NDEBUG
+ sprintf (buffer,
+ "\nSerial port COM%ld found at 0x%lx\n",
+ ComPort,
+ (ULONG)PortBase);
+ HalDisplayString (buffer);
+#endif /* NDEBUG */
+ }
+ else
+ {
+ sprintf (buffer,
+ "\nKernel Debugger: No serial port found!!!\n\n");
+ HalDisplayString (buffer);
+ return FALSE;
+ }
+ }
+
+ PortInitialized = TRUE;
+ }
+
+ /*
+ * set baud rate and data format (8N1)
+ */
+
+ /* turn on DTR and RTS */
+ WRITE_PORT_UCHAR (SER_MCR(PortBase), SR_MCR_DTR | SR_MCR_RTS);
+
+ /* set DLAB */
+ lcr = READ_PORT_UCHAR (SER_LCR(PortBase)) | SR_LCR_DLAB;
+ WRITE_PORT_UCHAR (SER_LCR(PortBase), lcr);
+
+ /* set baud rate */
+ divisor = 115200 / BaudRate;
+ WRITE_PORT_UCHAR (SER_DLL(PortBase), (UCHAR)(divisor & 0xff));
+ WRITE_PORT_UCHAR (SER_DLM(PortBase), (UCHAR)((divisor >> 8) & 0xff));
+
+ /* reset DLAB and set 8N1 format */
+ WRITE_PORT_UCHAR (SER_LCR(PortBase),
+ SR_LCR_CS8 | SR_LCR_ST1 | SR_LCR_PNO);
+
+ /* read junk out of the RBR */
+ lcr = READ_PORT_UCHAR (SER_RBR(PortBase));
+
+ /*
+ * set global info
+ */
+ KdComPortInUse = (ULONG)PortBase;
+
+ /*
+ * print message to blue screen
+ */
+ sprintf (buffer,
+ "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
+ ComPort,
+ (ULONG)PortBase,
+ BaudRate);
+
+ HalDisplayString (buffer);
+
+ return TRUE;
+}
+
+
+/* HAL.KdPortInitializeEx */
+BOOLEAN
+STDCALL
+KdPortInitializeEx (
+ PKD_PORT_INFORMATION PortInformation,
+ ULONG Unknown1,
+ ULONG Unknown2
+ )
+{
+ ULONG BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8};
+ PUCHAR ComPortBase;
+ char buffer[80];
+ ULONG divisor;
+ UCHAR lcr;
+
+ if (PortInformation->BaudRate == 0)
+ {
+ PortInformation->BaudRate = DEFAULT_BAUD_RATE;
+ }
+
+ if (PortInformation->ComPort == 0)
+ {
+ return FALSE;
+ }
+ else
+ {
+ if (KdpDoesComPortExist ((PUCHAR)BaseArray[PortInformation->ComPort]))
+ {
+ ComPortBase = (PUCHAR)BaseArray[PortInformation->ComPort];
+ PortInformation->BaseAddress = (ULONG)ComPortBase;
+#ifndef NDEBUG
+ sprintf (buffer,
+ "\nSerial port COM%ld found at 0x%lx\n",
+ PortInformation->ComPort,
+ (ULONG)ComPortBase];
+ HalDisplayString (buffer);
+#endif /* NDEBUG */
+ }
+ else
+ {
+ sprintf (buffer,
+ "\nKernel Debugger: Serial port not found!!!\n\n");
+ HalDisplayString (buffer);
+ return FALSE;
+ }
+ }
+
+ /*
+ * set baud rate and data format (8N1)
+ */
+
+ /* turn on DTR and RTS */
+ WRITE_PORT_UCHAR (SER_MCR(ComPortBase), SR_MCR_DTR | SR_MCR_RTS);
+
+ /* set DLAB */
+ lcr = READ_PORT_UCHAR (SER_LCR(ComPortBase)) | SR_LCR_DLAB;
+ WRITE_PORT_UCHAR (SER_LCR(ComPortBase), lcr);
+
+ /* set baud rate */
+ divisor = 115200 / PortInformation->BaudRate;
+ WRITE_PORT_UCHAR (SER_DLL(ComPortBase), (UCHAR)(divisor & 0xff));
+ WRITE_PORT_UCHAR (SER_DLM(ComPortBase), (UCHAR)((divisor >> 8) & 0xff));
+
+ /* reset DLAB and set 8N1 format */
+ WRITE_PORT_UCHAR (SER_LCR(ComPortBase),
+ SR_LCR_CS8 | SR_LCR_ST1 | SR_LCR_PNO);
+
+ /* read junk out of the RBR */
+ lcr = READ_PORT_UCHAR (SER_RBR(ComPortBase));
+
+#ifndef NDEBUG
+
+ /*
+ * print message to blue screen
+ */
+ sprintf (buffer,
+ "\nKernel Debugger: COM%ld (Port 0x%lx) BaudRate %ld\n\n",
+ PortInformation->ComPort,
+ (ULONG)ComPortBase,
+ PortInformation->BaudRate);
+
+ HalDisplayString (buffer);
+
+#endif /* NDEBUG */
+
+ return TRUE;
+}
+
+
+/* HAL.KdPortGetByte */
+BOOLEAN
+STDCALL
+KdPortGetByte (
+ PUCHAR ByteRecieved
+ )
+{
+ if (PortInitialized == FALSE)
+ return FALSE;
+
+ if ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_DR))
+ {
+ *ByteRecieved = READ_PORT_UCHAR (SER_RBR(PortBase));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/* HAL.KdPortGetByteEx */
+BOOLEAN
+STDCALL
+KdPortGetByteEx (
+ PKD_PORT_INFORMATION PortInformation,
+ PUCHAR ByteRecieved
+ )
+{
+ PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress;
+
+ if ((READ_PORT_UCHAR (SER_LSR(ComPortBase)) & SR_LSR_DR))
+ {
+ *ByteRecieved = READ_PORT_UCHAR (SER_RBR(ComPortBase));
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/* HAL.KdPortPollByte */
+BOOLEAN
+STDCALL
+KdPortPollByte (
+ PUCHAR ByteRecieved
+ )
+{
+ if (PortInitialized == FALSE)
+ return FALSE;
+
+ while ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_DR) == 0)
+ ;
+
+ *ByteRecieved = READ_PORT_UCHAR (SER_RBR(PortBase));
+
+ return TRUE;
+}
+
+
+/* HAL.KdPortPollByteEx */
+BOOLEAN
+STDCALL
+KdPortPollByteEx (
+ PKD_PORT_INFORMATION PortInformation,
+ PUCHAR ByteRecieved
+ )
+{
+ PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress;
+
+ while ((READ_PORT_UCHAR (SER_LSR(ComPortBase)) & SR_LSR_DR) == 0)
+ ;
+
+ *ByteRecieved = READ_PORT_UCHAR (SER_RBR(ComPortBase));
+
+ return TRUE;
+}
+
+
+
+
+/* HAL.KdPortPutByte */
+VOID
+STDCALL
+KdPortPutByte (
+ UCHAR ByteToSend
+ )
+{
+ if (PortInitialized == FALSE)
+ return;
+
+ while ((READ_PORT_UCHAR (SER_LSR(PortBase)) & SR_LSR_TBE) == 0)
+ ;
+
+ WRITE_PORT_UCHAR (SER_THR(PortBase), ByteToSend);
+}
+
+/* HAL.KdPortPutByteEx */
+VOID
+STDCALL
+KdPortPutByteEx (
+ PKD_PORT_INFORMATION PortInformation,
+ UCHAR ByteToSend
+ )
+{
+ PUCHAR ComPortBase = (PUCHAR)PortInformation->BaseAddress;
+
+ while ((READ_PORT_UCHAR (SER_LSR(ComPortBase)) & SR_LSR_TBE) == 0)
+ ;
+
+ WRITE_PORT_UCHAR (SER_THR(ComPortBase), ByteToSend);
+}
+
+
+/* HAL.KdPortRestore */
+VOID
+STDCALL
+KdPortRestore (
+ VOID
+ )
+{
+}
+
+
+/* HAL.KdPortSave */
+VOID
+STDCALL
+KdPortSave (
+ VOID
+ )
+{
+}
+
+
+/* HAL.KdPortDisableInterrupts */
+BOOLEAN
+STDCALL
+KdPortDisableInterrupts()
+{
+ UCHAR ch;
+
+ if (PortInitialized == FALSE)
+ return FALSE;
+
+ ch = READ_PORT_UCHAR (SER_MCR (PortBase));
+ ch &= (~(SR_MCR_OUT1 | SR_MCR_OUT2));
+ WRITE_PORT_UCHAR (SER_MCR (PortBase), ch);
+
+ ch = READ_PORT_UCHAR (SER_IER (PortBase));
+ ch &= (~SR_IER_ALL);
+ WRITE_PORT_UCHAR (SER_IER (PortBase), ch);
+
+ return TRUE;
+}
+
+
+/* HAL.KdPortEnableInterrupts */
+BOOLEAN
+STDCALL
+KdPortEnableInterrupts()
+{
+ UCHAR ch;
+
+ if (PortInitialized == FALSE)
+ return FALSE;
+
+ ch = READ_PORT_UCHAR (SER_IER (PortBase));
+ ch &= (~SR_IER_ALL);
+ ch |= SR_IER_ERDA;
+ WRITE_PORT_UCHAR (SER_IER (PortBase), ch);
+
+ ch = READ_PORT_UCHAR (SER_MCR (PortBase));
+ ch &= (~SR_MCR_LOOP);
+ ch |= (SR_MCR_OUT1 | SR_MCR_OUT2);
+ WRITE_PORT_UCHAR (SER_MCR (PortBase), ch);
+
+ return TRUE;
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/mca.c b/reactos/hal/halppc/generic/mca.c
new file mode 100644
index 00000000000..8343c8a8f70
--- /dev/null
+++ b/reactos/hal/halppc/generic/mca.c
@@ -0,0 +1,79 @@
+/*
+ * ReactOS kernel
+ * Copyright (C) 2002 ReactOS Team
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: mca.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: hal/halx86/mca.c
+ * PURPOSE: Interfaces to the MicroChannel bus
+ * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
+ */
+
+/*
+ * TODO:
+ * What Adapter ID is read from an empty slot?
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+/* FUNCTIONS ****************************************************************/
+
+ULONG STDCALL
+HalpGetMicroChannelData(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length)
+{
+ PCM_MCA_POS_DATA PosData = (PCM_MCA_POS_DATA)Buffer;
+
+ DPRINT("HalpGetMicroChannelData() called.\n");
+ DPRINT(" BusNumber %lu\n", BusNumber);
+ DPRINT(" SlotNumber %lu\n", SlotNumber);
+ DPRINT(" Offset 0x%lx\n", Offset);
+ DPRINT(" Length 0x%lx\n", Length);
+
+ if ((BusNumber != 0) ||
+ (SlotNumber == 0) || (SlotNumber > 8) ||
+ (Length < sizeof(CM_MCA_POS_DATA)))
+ return(0);
+
+ /* Enter Setup-Mode for given slot */
+ WRITE_PORT_UCHAR((PUCHAR)0x96, (UCHAR)(((UCHAR)(SlotNumber - 1) & 0x07) | 0x08));
+
+ /* Read POS data */
+ PosData->AdapterId = (READ_PORT_UCHAR((PUCHAR)0x101) << 8) +
+ READ_PORT_UCHAR((PUCHAR)0x100);
+ PosData->PosData1 = READ_PORT_UCHAR((PUCHAR)0x102);
+ PosData->PosData2 = READ_PORT_UCHAR((PUCHAR)0x103);
+ PosData->PosData3 = READ_PORT_UCHAR((PUCHAR)0x104);
+ PosData->PosData4 = READ_PORT_UCHAR((PUCHAR)0x105);
+
+ /* Leave Setup-Mode for given slot */
+ WRITE_PORT_UCHAR((PUCHAR)0x96, (UCHAR)((UCHAR)(SlotNumber - 1) & 0x07));
+
+ return(sizeof(CM_MCA_POS_DATA));
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/misc.c b/reactos/hal/halppc/generic/misc.c
new file mode 100644
index 00000000000..14410083d2f
--- /dev/null
+++ b/reactos/hal/halppc/generic/misc.c
@@ -0,0 +1,72 @@
+/* $Id: misc.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/misc.c
+ * PURPOSE: Miscellaneous hardware functions
+ * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+
+/* FUNCTIONS ****************************************************************/
+
+PVOID STDCALL
+HalAllocateCrashDumpRegisters(IN PADAPTER_OBJECT AdapterObject,
+ IN OUT PULONG NumberOfMapRegisters)
+{
+ UNIMPLEMENTED;
+ return NULL;
+}
+
+
+VOID STDCALL
+HalHandleNMI(PVOID NmiInfo)
+{
+ UCHAR ucStatus;
+
+ ucStatus = READ_PORT_UCHAR((PUCHAR) 0x61);
+
+ HalDisplayString ("\n*** Hardware Malfunction\n\n");
+ HalDisplayString ("Call your hardware vendor for support\n\n");
+
+ if (ucStatus & 0x80)
+ HalDisplayString ("NMI: Parity Check / Memory Parity Error\n");
+
+ if (ucStatus & 0x40)
+ HalDisplayString ("NMI: Channel Check / IOCHK\n");
+
+ HalDisplayString ("\n*** The system has halted ***\n");
+ KeEnterKernelDebugger ();
+}
+
+
+VOID STDCALL
+HalProcessorIdle(VOID)
+{
+ // XXX Learn to use PSL_POW for this.
+}
+
+ULONG FASTCALL
+HalSystemVectorDispatchEntry (
+ ULONG Unknown1,
+ ULONG Unknown2,
+ ULONG Unknown3
+ )
+{
+ return 0;
+}
+
+
+VOID STDCALL
+KeFlushWriteBuffer(VOID)
+{
+ return;
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/pci.c b/reactos/hal/halppc/generic/pci.c
new file mode 100644
index 00000000000..f2fd74888f9
--- /dev/null
+++ b/reactos/hal/halppc/generic/pci.c
@@ -0,0 +1,812 @@
+/* $Id: pci.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/pci.c
+ * PURPOSE: Interfaces to the PCI bus
+ * PROGRAMMER: David Welch (welch@mcmail.com)
+ * Eric Kohl (ekohl@rz-online.de)
+ * UPDATE HISTORY:
+ * 05/06/1998: Created
+ * 17/08/2000: Added preliminary pci bus scanner
+ * 13/06/2001: Implemented access to pci configuration space
+ */
+
+/*
+ * NOTES: Sections copied from the Linux pci support
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+
+/* MACROS ******************************************************************/
+
+/* FIXME These are also defined in drivers/bus/pci/pcidef.h.
+ Maybe put PCI definitions in a central include file??? */
+
+/* access type 1 macros */
+#define CONFIG_CMD(bus, dev_fn, where) \
+ (0x80000000 | (((ULONG)(bus)) << 16) | (((dev_fn) & 0x1F) << 11) | (((dev_fn) & 0xE0) << 3) | ((where) & ~3))
+
+/* access type 2 macros */
+#define IOADDR(dev_fn, where) \
+ (0xC000 | (((dev_fn) & 0x1F) << 8) | (where))
+#define FUNC(dev_fn) \
+ ((((dev_fn) & 0xE0) >> 4) | 0xf0)
+
+#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
+#define PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
+#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
+#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
+#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
+#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
+#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
+/* bit 1 is reserved if address_space = 1 */
+
+
+/* GLOBALS ******************************************************************/
+
+#define TAG_PCI TAG('P', 'C', 'I', 'H')
+
+static ULONG BusConfigType = 0; /* undetermined config type */
+static KSPIN_LOCK PciLock;
+
+/* FUNCTIONS ****************************************************************/
+
+static NTSTATUS
+ReadPciConfigUchar(UCHAR Bus,
+ UCHAR Slot,
+ UCHAR Offset,
+ PUCHAR Value)
+{
+ KIRQL oldIrql;
+
+ switch (BusConfigType)
+ {
+ case 1:
+ KeAcquireSpinLock(&PciLock, &oldIrql);
+ WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+ *Value = READ_PORT_UCHAR((PUCHAR)0xCFC + (Offset & 3));
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ return STATUS_SUCCESS;
+
+ case 2:
+ KeAcquireSpinLock(&PciLock, &oldIrql);
+ WRITE_PORT_UCHAR((PUCHAR)0xCF8, (UCHAR)FUNC(Slot));
+ WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
+ *Value = READ_PORT_UCHAR((PUCHAR)(IOADDR(Slot, Offset)));
+ WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ return STATUS_SUCCESS;
+ }
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+static NTSTATUS
+ReadPciConfigUshort(UCHAR Bus,
+ UCHAR Slot,
+ UCHAR Offset,
+ PUSHORT Value)
+{
+ KIRQL oldIrql;
+
+ if ((Offset & 1) != 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ switch (BusConfigType)
+ {
+ case 1:
+ KeAcquireSpinLock(&PciLock, &oldIrql);
+ WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+ *Value = READ_PORT_USHORT((PUSHORT)0xCFC + (Offset & 2));
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ return STATUS_SUCCESS;
+
+ case 2:
+ KeAcquireSpinLock(&PciLock, &oldIrql);
+ WRITE_PORT_UCHAR((PUCHAR)0xCF8, (UCHAR)FUNC(Slot));
+ WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
+ *Value = READ_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)));
+ WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ return STATUS_SUCCESS;
+ }
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+static NTSTATUS
+ReadPciConfigUlong(UCHAR Bus,
+ UCHAR Slot,
+ UCHAR Offset,
+ PULONG Value)
+{
+ KIRQL oldIrql;
+
+ if ((Offset & 3) != 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ switch (BusConfigType)
+ {
+ case 1:
+ KeAcquireSpinLock(&PciLock, &oldIrql);
+ WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+ *Value = READ_PORT_ULONG((PULONG)0xCFC);
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ return STATUS_SUCCESS;
+
+ case 2:
+ KeAcquireSpinLock(&PciLock, &oldIrql);
+ WRITE_PORT_UCHAR((PUCHAR)0xCF8, (UCHAR)FUNC(Slot));
+ WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
+ *Value = READ_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)));
+ WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ return STATUS_SUCCESS;
+ }
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+static NTSTATUS
+WritePciConfigUchar(UCHAR Bus,
+ UCHAR Slot,
+ UCHAR Offset,
+ UCHAR Value)
+{
+ KIRQL oldIrql;
+
+ switch (BusConfigType)
+ {
+ case 1:
+ KeAcquireSpinLock(&PciLock, &oldIrql);
+ WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+ WRITE_PORT_UCHAR((PUCHAR)0xCFC + (Offset&3), Value);
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ return STATUS_SUCCESS;
+
+ case 2:
+ KeAcquireSpinLock(&PciLock, &oldIrql);
+ WRITE_PORT_UCHAR((PUCHAR)0xCF8, (UCHAR)FUNC(Slot));
+ WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
+ WRITE_PORT_UCHAR((PUCHAR)(IOADDR(Slot,Offset)), Value);
+ WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ return STATUS_SUCCESS;
+ }
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+static NTSTATUS
+WritePciConfigUshort(UCHAR Bus,
+ UCHAR Slot,
+ UCHAR Offset,
+ USHORT Value)
+{
+ KIRQL oldIrql;
+
+ if ((Offset & 1) != 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ switch (BusConfigType)
+ {
+ case 1:
+ KeAcquireSpinLock(&PciLock, &oldIrql);
+ WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+ WRITE_PORT_USHORT((PUSHORT)0xCFC + (Offset & 2), Value);
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ return STATUS_SUCCESS;
+
+ case 2:
+ KeAcquireSpinLock(&PciLock, &oldIrql);
+ WRITE_PORT_UCHAR((PUCHAR)0xCF8, (UCHAR)FUNC(Slot));
+ WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
+ WRITE_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)), Value);
+ WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ return STATUS_SUCCESS;
+ }
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+static NTSTATUS
+WritePciConfigUlong(UCHAR Bus,
+ UCHAR Slot,
+ UCHAR Offset,
+ ULONG Value)
+{
+ KIRQL oldIrql;
+
+ if ((Offset & 3) != 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ switch (BusConfigType)
+ {
+ case 1:
+ KeAcquireSpinLock(&PciLock, &oldIrql);
+ WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+ WRITE_PORT_ULONG((PULONG)0xCFC, Value);
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ return STATUS_SUCCESS;
+
+ case 2:
+ KeAcquireSpinLock(&PciLock, &oldIrql);
+ WRITE_PORT_UCHAR((PUCHAR)0xCF8, (UCHAR)FUNC(Slot));
+ WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
+ WRITE_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)), Value);
+ WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ return STATUS_SUCCESS;
+ }
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+static ULONG STDCALL
+HalpGetPciData(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length)
+{
+ PVOID Ptr = Buffer;
+ ULONG Address = Offset;
+ ULONG Len = Length;
+ ULONG Vendor;
+ UCHAR HeaderType;
+
+ DPRINT("HalpGetPciData() called.\n");
+ DPRINT(" BusNumber %lu\n", BusNumber);
+ DPRINT(" SlotNumber %lu\n", SlotNumber);
+ DPRINT(" Offset 0x%lx\n", Offset);
+ DPRINT(" Length 0x%lx\n", Length);
+
+ if ((Length == 0) || (BusConfigType == 0))
+ return 0;
+
+ ReadPciConfigUlong((UCHAR)BusNumber,
+ (UCHAR)(SlotNumber & 0x1F),
+ 0x00,
+ &Vendor);
+ /* some broken boards return 0 if a slot is empty: */
+ if (Vendor == 0xFFFFFFFF || Vendor == 0)
+ {
+ if (BusNumber == 0 && Offset == 0 && Length >= 2)
+ {
+ *(PUSHORT)Buffer = PCI_INVALID_VENDORID;
+ return 2;
+ }
+ return 0;
+ }
+
+ /* 0E=PCI_HEADER_TYPE */
+ ReadPciConfigUchar((UCHAR)BusNumber,
+ (UCHAR)(SlotNumber & 0x1F),
+ 0x0E,
+ &HeaderType);
+ if (((HeaderType & PCI_MULTIFUNCTION) == 0) && ((SlotNumber & 0xE0) != 0))
+ {
+ if (Offset == 0 && Length >= 2)
+ {
+ *(PUSHORT)Buffer = PCI_INVALID_VENDORID;
+ return 2;
+ }
+ return 0;
+ }
+ ReadPciConfigUlong((UCHAR)BusNumber,
+ (UCHAR)SlotNumber,
+ 0x00,
+ &Vendor);
+ /* some broken boards return 0 if a slot is empty: */
+ if (Vendor == 0xFFFFFFFF || Vendor == 0)
+ {
+ if (BusNumber == 0 && Offset == 0 && Length >= 2)
+ {
+ *(PUSHORT)Buffer = PCI_INVALID_VENDORID;
+ return 2;
+ }
+ return 0;
+ }
+
+ if ((Address & 1) && (Len >= 1))
+ {
+ ReadPciConfigUchar((UCHAR)BusNumber,
+ (UCHAR)SlotNumber,
+ (UCHAR)Address,
+ Ptr);
+ Ptr = (char*)Ptr + 1;
+ Address++;
+ Len--;
+ }
+
+ if ((Address & 2) && (Len >= 2))
+ {
+ ReadPciConfigUshort((UCHAR)BusNumber,
+ (UCHAR)SlotNumber,
+ (UCHAR)Address,
+ Ptr);
+ Ptr = (char*)Ptr + 2;
+ Address += 2;
+ Len -= 2;
+ }
+
+ while (Len >= 4)
+ {
+ ReadPciConfigUlong((UCHAR)BusNumber,
+ (UCHAR)SlotNumber,
+ (UCHAR)Address,
+ Ptr);
+ Ptr = (char*)Ptr + 4;
+ Address += 4;
+ Len -= 4;
+ }
+
+ if (Len >= 2)
+ {
+ ReadPciConfigUshort((UCHAR)BusNumber,
+ (UCHAR)SlotNumber,
+ (UCHAR)Address,
+ Ptr);
+ Ptr = (char*)Ptr + 2;
+ Address += 2;
+ Len -= 2;
+ }
+
+ if (Len >= 1)
+ {
+ ReadPciConfigUchar((UCHAR)BusNumber,
+ (UCHAR)SlotNumber,
+ (UCHAR)Address,
+ Ptr);
+ Ptr = (char*)Ptr + 1;
+ Address++;
+ Len--;
+ }
+
+ return Length - Len;
+}
+
+
+static ULONG STDCALL
+HalpSetPciData(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length)
+{
+ PVOID Ptr = Buffer;
+ ULONG Address = Offset;
+ ULONG Len = Length;
+ ULONG Vendor;
+ UCHAR HeaderType;
+
+ DPRINT("HalpSetPciData() called.\n");
+ DPRINT(" BusNumber %lu\n", BusNumber);
+ DPRINT(" SlotNumber %lu\n", SlotNumber);
+ DPRINT(" Offset 0x%lx\n", Offset);
+ DPRINT(" Length 0x%lx\n", Length);
+
+ if ((Length == 0) || (BusConfigType == 0))
+ return 0;
+
+ ReadPciConfigUlong((UCHAR)BusNumber,
+ (UCHAR)(SlotNumber & 0x1F),
+ 0x00,
+ &Vendor);
+ /* some broken boards return 0 if a slot is empty: */
+ if (Vendor == 0xFFFFFFFF || Vendor == 0)
+ return 0;
+
+
+ /* 0E=PCI_HEADER_TYPE */
+ ReadPciConfigUchar((UCHAR)BusNumber,
+ (UCHAR)(SlotNumber & 0x1F),
+ 0x0E,
+ &HeaderType);
+ if (((HeaderType & PCI_MULTIFUNCTION) == 0) && ((SlotNumber & 0xE0) != 0))
+ return 0;
+
+ ReadPciConfigUlong((UCHAR)BusNumber,
+ (UCHAR)SlotNumber,
+ 0x00,
+ &Vendor);
+ /* some broken boards return 0 if a slot is empty: */
+ if (Vendor == 0xFFFFFFFF || Vendor == 0)
+ return 0;
+
+ if ((Address & 1) && (Len >= 1))
+ {
+ WritePciConfigUchar((UCHAR)BusNumber,
+ (UCHAR)SlotNumber,
+ (UCHAR)Address,
+ *(PUCHAR)Ptr);
+ Ptr = (char*)Ptr + 1;
+ Address++;
+ Len--;
+ }
+
+ if ((Address & 2) && (Len >= 2))
+ {
+ WritePciConfigUshort((UCHAR)BusNumber,
+ (UCHAR)SlotNumber,
+ (UCHAR)Address,
+ *(PUSHORT)Ptr);
+ Ptr = (char*)Ptr + 2;
+ Address += 2;
+ Len -= 2;
+ }
+
+ while (Len >= 4)
+ {
+ WritePciConfigUlong((UCHAR)BusNumber,
+ (UCHAR)SlotNumber,
+ (UCHAR)Address,
+ *(PULONG)Ptr);
+ Ptr = (char*)Ptr + 4;
+ Address += 4;
+ Len -= 4;
+ }
+
+ if (Len >= 2)
+ {
+ WritePciConfigUshort((UCHAR)BusNumber,
+ (UCHAR)SlotNumber,
+ (UCHAR)Address,
+ *(PUSHORT)Ptr);
+ Ptr = (char*)Ptr + 2;
+ Address += 2;
+ Len -= 2;
+ }
+
+ if (Len >= 1)
+ {
+ WritePciConfigUchar((UCHAR)BusNumber,
+ (UCHAR)SlotNumber,
+ (UCHAR)Address,
+ *(PUCHAR)Ptr);
+ Ptr = (char*)Ptr + 1;
+ Address++;
+ Len--;
+ }
+
+ return Length - Len;
+}
+
+
+static ULONG
+GetBusConfigType(VOID)
+{
+ ULONG Value;
+ KIRQL oldIrql;
+
+ DPRINT("GetBusConfigType() called\n");
+
+ KeAcquireSpinLock(&PciLock, &oldIrql);
+
+ DPRINT("Checking configuration type 1:");
+ WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x01);
+ Value = READ_PORT_ULONG((PULONG)0xCF8);
+ WRITE_PORT_ULONG((PULONG)0xCF8, 0x80000000);
+ if (READ_PORT_ULONG((PULONG)0xCF8) == 0x80000000)
+ {
+ WRITE_PORT_ULONG((PULONG)0xCF8, Value);
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ DPRINT(" Success!\n");
+ return 1;
+ }
+ WRITE_PORT_ULONG((PULONG)0xCF8, Value);
+ DPRINT(" Unsuccessful!\n");
+
+ DPRINT("Checking configuration type 2:");
+ WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x00);
+ WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0x00);
+ WRITE_PORT_UCHAR((PUCHAR)0xCFA, 0x00);
+ if (READ_PORT_UCHAR((PUCHAR)0xCF8) == 0x00 &&
+ READ_PORT_UCHAR((PUCHAR)0xCFB) == 0x00)
+ {
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ DPRINT(" Success!\n");
+ return 2;
+ }
+ KeReleaseSpinLock(&PciLock, oldIrql);
+ DPRINT(" Unsuccessful!\n");
+
+ DPRINT("No pci bus found!\n");
+ return 0;
+}
+
+
+static ULONG STDCALL
+HalpGetPciInterruptVector(PVOID BusHandler,
+ ULONG BusNumber,
+ ULONG BusInterruptLevel,
+ ULONG BusInterruptVector,
+ PKIRQL Irql,
+ PKAFFINITY Affinity)
+{
+ ULONG Vector = IRQ2VECTOR(BusInterruptVector);
+ *Irql = VECTOR2IRQL(Vector);
+ *Affinity = 0xFFFFFFFF;
+ return Vector;
+}
+
+static BOOLEAN STDCALL
+HalpTranslatePciAddress(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ PHYSICAL_ADDRESS BusAddress,
+ PULONG AddressSpace,
+ PPHYSICAL_ADDRESS TranslatedAddress)
+{
+ if (*AddressSpace == 0)
+ {
+ /* memory space */
+
+ }
+ else if (*AddressSpace == 1)
+ {
+ /* io space */
+
+ }
+ else
+ {
+ /* other */
+ return FALSE;
+ }
+
+ TranslatedAddress->QuadPart = BusAddress.QuadPart;
+
+ return TRUE;
+}
+
+/*
+ * Find the extent of a PCI decode..
+ */
+static ULONG STDCALL
+PciSize(ULONG Base, ULONG Mask)
+{
+ ULONG Size = Mask & Base; /* Find the significant bits */
+ Size = Size & ~(Size - 1); /* Get the lowest of them to find the decode size */
+ return Size;
+}
+
+static NTSTATUS STDCALL
+HalpAssignPciSlotResources(IN PBUS_HANDLER BusHandler,
+ IN ULONG BusNumber,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources)
+{
+ ULONG DataSize;
+ PCI_COMMON_CONFIG PciConfig;
+ SIZE_T Address;
+ SIZE_T ResourceCount;
+ ULONG Size[PCI_TYPE0_ADDRESSES];
+ NTSTATUS Status = STATUS_SUCCESS;
+ UCHAR Offset;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+
+ /* FIXME: Should handle 64-bit addresses */
+
+ DataSize = HalpGetPciData(BusHandler,
+ BusNumber,
+ SlotNumber,
+ &PciConfig,
+ 0,
+ PCI_COMMON_HDR_LENGTH);
+ if (PCI_COMMON_HDR_LENGTH != DataSize)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Read the PCI configuration space for the device and store base address and
+ size information in temporary storage. Count the number of valid base addresses */
+ ResourceCount = 0;
+ for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
+ {
+ if (0xffffffff == PciConfig.u.type0.BaseAddresses[Address])
+ {
+ PciConfig.u.type0.BaseAddresses[Address] = 0;
+ }
+ if (0 != PciConfig.u.type0.BaseAddresses[Address])
+ {
+ ResourceCount++;
+ Offset = FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses[Address]);
+ Status = WritePciConfigUlong((UCHAR)BusNumber, (UCHAR)SlotNumber, Offset, 0xffffffff);
+ if (! NT_SUCCESS(Status))
+ {
+ WritePciConfigUlong((UCHAR)BusNumber, (UCHAR)SlotNumber, Offset,
+ PciConfig.u.type0.BaseAddresses[Address]);
+ return Status;
+ }
+ Status = ReadPciConfigUlong((UCHAR)BusNumber, (UCHAR)SlotNumber,
+ Offset, Size + Address);
+ if (! NT_SUCCESS(Status))
+ {
+ WritePciConfigUlong((UCHAR)BusNumber, (UCHAR)SlotNumber, Offset,
+ PciConfig.u.type0.BaseAddresses[Address]);
+ return Status;
+ }
+ Status = WritePciConfigUlong((UCHAR)BusNumber, (UCHAR)SlotNumber, Offset,
+ PciConfig.u.type0.BaseAddresses[Address]);
+ if (! NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
+ }
+
+ if (0 != PciConfig.u.type0.InterruptLine)
+ {
+ ResourceCount++;
+ }
+
+ /* Allocate output buffer and initialize */
+ *AllocatedResources = ExAllocatePoolWithTag(PagedPool,
+ sizeof(CM_RESOURCE_LIST) +
+ (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
+ TAG_PCI);
+ if (NULL == *AllocatedResources)
+ {
+ return STATUS_NO_MEMORY;
+ }
+ (*AllocatedResources)->Count = 1;
+ (*AllocatedResources)->List[0].InterfaceType = PCIBus;
+ (*AllocatedResources)->List[0].BusNumber = BusNumber;
+ (*AllocatedResources)->List[0].PartialResourceList.Version = 1;
+ (*AllocatedResources)->List[0].PartialResourceList.Revision = 1;
+ (*AllocatedResources)->List[0].PartialResourceList.Count = ResourceCount;
+ Descriptor = (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ /* Store configuration information */
+ for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
+ {
+ if (0 != PciConfig.u.type0.BaseAddresses[Address])
+ {
+ if (PCI_BASE_ADDRESS_SPACE_MEMORY ==
+ (PciConfig.u.type0.BaseAddresses[Address] & PCI_BASE_ADDRESS_SPACE))
+ {
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; /* FIXME Just a guess */
+ Descriptor->u.Memory.Start.QuadPart = (PciConfig.u.type0.BaseAddresses[Address] & PCI_BASE_ADDRESS_MEM_MASK);
+ Descriptor->u.Memory.Length = PciSize(Size[Address], PCI_BASE_ADDRESS_MEM_MASK);
+ }
+ else if (PCI_BASE_ADDRESS_SPACE_IO ==
+ (PciConfig.u.type0.BaseAddresses[Address] & PCI_BASE_ADDRESS_SPACE))
+ {
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
+ Descriptor->Flags = CM_RESOURCE_PORT_IO; /* FIXME Just a guess */
+ Descriptor->u.Port.Start.QuadPart = PciConfig.u.type0.BaseAddresses[Address] &= PCI_BASE_ADDRESS_IO_MASK;
+ Descriptor->u.Port.Length = PciSize(Size[Address], PCI_BASE_ADDRESS_IO_MASK & 0xffff);
+ }
+ else
+ {
+ ASSERT(FALSE);
+ return STATUS_UNSUCCESSFUL;
+ }
+ Descriptor++;
+ }
+ }
+
+ if (0 != PciConfig.u.type0.InterruptLine)
+ {
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->ShareDisposition = CmResourceShareShared; /* FIXME Just a guess */
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; /* FIXME Just a guess */
+ Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
+ Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
+ Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
+
+ Descriptor++;
+ }
+
+ ASSERT(Descriptor == (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors + ResourceCount);
+
+ /* FIXME: Should store the resources in the registry resource map */
+
+ return Status;
+}
+
+
+VOID
+HalpInitPciBus(VOID)
+{
+ PBUS_HANDLER BusHandler;
+
+ DPRINT("HalpInitPciBus() called.\n");
+
+ KeInitializeSpinLock (&PciLock);
+
+ BusConfigType = GetBusConfigType();
+ if (BusConfigType == 0)
+ return;
+
+ DPRINT("Bus configuration %lu used\n", BusConfigType);
+
+ /* pci bus (bus 0) handler */
+ BusHandler = HalpAllocateBusHandler(PCIBus,
+ PCIConfiguration,
+ 0);
+ BusHandler->GetBusData = (pGetSetBusData)HalpGetPciData;
+ BusHandler->SetBusData = (pGetSetBusData)HalpSetPciData;
+ BusHandler->GetInterruptVector =
+ (pGetInterruptVector)HalpGetPciInterruptVector;
+ BusHandler->TranslateBusAddress =
+ (pTranslateBusAddress)HalpTranslatePciAddress;
+// BusHandler->AdjustResourceList =
+// (pGetSetBusData)HalpAdjustPciResourceList;
+ BusHandler->AssignSlotResources =
+ (pAssignSlotResources)HalpAssignPciSlotResources;
+ if (NULL != HalpHooks.InitPciBus)
+ {
+ HalpHooks.InitPciBus(0, BusHandler);
+ }
+
+
+ /* agp bus (bus 1) handler */
+ BusHandler = HalpAllocateBusHandler(PCIBus,
+ PCIConfiguration,
+ 1);
+ BusHandler->GetBusData = (pGetSetBusData)HalpGetPciData;
+ BusHandler->SetBusData = (pGetSetBusData)HalpSetPciData;
+ BusHandler->GetInterruptVector =
+ (pGetInterruptVector)HalpGetPciInterruptVector;
+ BusHandler->TranslateBusAddress =
+ (pTranslateBusAddress)HalpTranslatePciAddress;
+// BusHandler->AdjustResourceList =
+// (pGetSetBusData)HalpAdjustPciResourceList;
+ BusHandler->AssignSlotResources =
+ (pAssignSlotResources)HalpAssignPciSlotResources;
+ if (NULL != HalpHooks.InitPciBus)
+ {
+ HalpHooks.InitPciBus(1, BusHandler);
+ }
+
+
+ /* PCI bus (bus 2) handler */
+ BusHandler = HalpAllocateBusHandler(PCIBus,
+ PCIConfiguration,
+ 2);
+ BusHandler->GetBusData = (pGetSetBusData)HalpGetPciData;
+ BusHandler->SetBusData = (pGetSetBusData)HalpSetPciData;
+ BusHandler->GetInterruptVector =
+ (pGetInterruptVector)HalpGetPciInterruptVector;
+ BusHandler->TranslateBusAddress =
+ (pTranslateBusAddress)HalpTranslatePciAddress;
+// BusHandler->AdjustResourceList =
+// (pGetSetBusData)HalpAdjustPciResourceList;
+ BusHandler->AssignSlotResources =
+ (pAssignSlotResources)HalpAssignPciSlotResources;
+ if (NULL != HalpHooks.InitPciBus)
+ {
+ HalpHooks.InitPciBus(2, BusHandler);
+ }
+
+ DPRINT("HalpInitPciBus() finished.\n");
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/portio.c b/reactos/hal/halppc/generic/portio.c
new file mode 100644
index 00000000000..c665beb1836
--- /dev/null
+++ b/reactos/hal/halppc/generic/portio.c
@@ -0,0 +1,289 @@
+/* $Id: portio.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/portio.c
+ * PURPOSE: Port I/O functions
+ * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de)
+ * UPDATE HISTORY:
+ * Created 18/10/99
+ */
+
+#include
+#define NDEBUG
+#include
+
+/* FUNCTIONS ****************************************************************/
+
+/*
+ * This file contains the definitions for the x86 IO instructions
+ * inb/inw/inl/outb/outw/outl and the "string versions" of the same
+ * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
+ * versions of the single-IO instructions (inb_p/inw_p/..).
+ *
+ * This file is not meant to be obfuscating: it's just complicated
+ * to (a) handle it all in a way that makes gcc able to optimize it
+ * as well as possible and (b) trying to avoid writing the same thing
+ * over and over again with slight variations and possibly making a
+ * mistake somewhere.
+ */
+
+/*
+ * Thanks to James van Artsdalen for a better timing-fix than
+ * the two short jumps: using outb's to a nonexistent port seems
+ * to guarantee better timings even on fast machines.
+ *
+ * On the other hand, I'd like to be sure of a non-existent port:
+ * I feel a bit unsafe about using 0x80 (should be safe, though)
+ *
+ * Linus
+ */
+
+#if defined(__GNUC__)
+
+#ifdef SLOW_IO_BY_JUMPING
+#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:")
+#else
+#define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80")
+#endif
+
+#elif defined(_MSC_VER)
+
+#ifdef SLOW_IO_BY_JUMPING
+#define __SLOW_DOWN_IO __asm jmp 1f __asm jmp 1f 1f:
+#else
+#define __SLOW_DOWN_IO __asm out 0x80, al
+#endif
+
+#else
+#error Unknown compiler for inline assembler
+#endif
+
+
+#ifdef REALLY_SLOW_IO
+#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; }
+#else
+#define SLOW_DOWN_IO __SLOW_DOWN_IO
+#endif
+
+extern int GetPhysByte(int Addr);
+extern void SetPhysByte(int Addr, int Val);
+extern int GetPhysWord(int Addr);
+extern void SetPhysWord(int Addr, int Val);
+extern int GetPhys(int Addr);
+extern void SetPhys(int Addr, int Val);
+
+__asm__("\t.globl GetPhys\n"
+ "GetPhys:\t\n"
+ "mflr 0\n\t"
+ "stwu 0,-16(1)\n\t"
+ "mfmsr 5\n\t"
+ "xori 3,3,4\n\t" /* Undo effects of LE without swapping */
+ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
+ "mtmsr 6\n\t"
+ "isync\n\t"
+ "sync\n\t"
+ "lwz 3,0(3)\n\t" /* Get actual value at phys addr r3 */
+ "mtmsr 5\n\t"
+ "isync\n\t"
+ "sync\n\t"
+ "lwz 0,0(1)\n\t"
+ "addi 1,1,16\n\t"
+ "mtlr 0\n\t"
+ "blr"
+ );
+
+__asm__("\t.globl GetPhysWord\n"
+ "GetPhysWord:\t\n"
+ "mflr 0\n\t"
+ "stwu 0,-16(1)\n\t"
+ "mfmsr 5\n\t"
+ "xori 3,3,6\n\t" /* Undo effects of LE without swapping */
+ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
+ "mtmsr 6\n\t"
+ "isync\n\t"
+ "sync\n\t"
+ "lhz 3,0(3)\n\t" /* Get actual value at phys addr r3 */
+ "mtmsr 5\n\t"
+ "isync\n\t"
+ "sync\n\t"
+ "lwz 0,0(1)\n\t"
+ "addi 1,1,16\n\t"
+ "mtlr 0\n\t"
+ "blr"
+ );
+
+__asm__("\t.globl GetPhysByte\n"
+ "GetPhysByte:\t\n"
+ "mflr 0\n\t"
+ "stwu 0,-16(1)\n\t"
+ "mfmsr 5\n\t"
+ "xori 3,3,7\n\t" /* Undo effects of LE without swapping */
+ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
+ "mtmsr 6\n\t"
+ "isync\n\t"
+ "sync\n\t"
+ "lbz 3,0(3)\n\t" /* Get actual value at phys addr r3 */
+ "mtmsr 5\n\t"
+ "isync\n\t"
+ "sync\n\t"
+ "lwz 0,0(1)\n\t"
+ "addi 1,1,16\n\t"
+ "mtlr 0\n\t"
+ "blr"
+ );
+
+__asm__("\t.globl SetPhys\n"
+ "SetPhys:\t\n"
+ "mflr 0\n\t"
+ "stwu 0,-16(1)\n\t"
+ "mfmsr 5\n\t"
+ "xori 3,3,4\n\t" /* Undo effects of LE without swapping */
+ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
+ "mtmsr 6\n\t"
+ "sync\n\t"
+ "eieio\n\t"
+ "stw 4,0(3)\n\t" /* Set actual value at phys addr r3 */
+ "dcbst 0,3\n\t"
+ "mtmsr 5\n\t"
+ "sync\n\t"
+ "eieio\n\t"
+ "mr 3,4\n\t"
+ "lwz 0,0(1)\n\t"
+ "addi 1,1,16\n\t"
+ "mtlr 0\n\t"
+ "blr"
+ );
+
+__asm__("\t.globl SetPhysWord\n"
+ "SetPhysWord:\t\n"
+ "mflr 0\n\t"
+ "stwu 0,-16(1)\n\t"
+ "mfmsr 5\n\t"
+ "xori 3,3,6\n\t" /* Undo effects of LE without swapping */
+ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
+ "mtmsr 6\n\t"
+ "sync\n\t"
+ "eieio\n\t"
+ "sth 4,0(3)\n\t" /* Set actual value at phys addr r3 */
+ "dcbst 0,3\n\t"
+ "mtmsr 5\n\t"
+ "sync\n\t"
+ "eieio\n\t"
+ "mr 3,4\n\t"
+ "lwz 0,0(1)\n\t"
+ "addi 1,1,16\n\t"
+ "mtlr 0\n\t"
+ "blr"
+ );
+
+__asm__("\t.globl SetPhysByte\n"
+ "SetPhysByte:\t\n"
+ "mflr 0\n\t"
+ "stwu 0,-16(1)\n\t"
+ "mfmsr 5\n\t"
+ "xori 3,3,7\n\t" /* Undo effects of LE without swapping */
+ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */
+ "mtmsr 6\n\t"
+ "sync\n\t"
+ "eieio\n\t"
+ "stb 4,0(3)\n\t" /* Set actual value at phys addr r3 */
+ "dcbst 0,3\n\t"
+ "mtmsr 5\n\t"
+ "sync\n\t"
+ "eieio\n\t"
+ "mr 3,4\n\t"
+ "lwz 0,0(1)\n\t"
+ "addi 1,1,16\n\t"
+ "mtlr 0\n\t"
+ "blr"
+ );
+
+VOID STDCALL
+READ_PORT_BUFFER_UCHAR (PUCHAR Port,
+ PUCHAR Buffer,
+ ULONG Count)
+{
+ while(Count--) { *Buffer++ = GetPhysByte((ULONG)Port); }
+}
+
+VOID STDCALL
+READ_PORT_BUFFER_USHORT (PUSHORT Port,
+ PUSHORT Buffer,
+ ULONG Count)
+{
+ while(Count--) { *Buffer++ = GetPhysWord((ULONG)Port); }
+}
+
+VOID STDCALL
+READ_PORT_BUFFER_ULONG (PULONG Port,
+ PULONG Buffer,
+ ULONG Count)
+{
+ while(Count--) { *Buffer++ = GetPhys((ULONG)Port); }
+}
+
+UCHAR STDCALL
+READ_PORT_UCHAR (PUCHAR Port)
+{
+ return GetPhys((ULONG)Port);
+}
+
+USHORT STDCALL
+READ_PORT_USHORT (PUSHORT Port)
+{
+ return GetPhysWord((ULONG)Port);
+}
+
+ULONG STDCALL
+READ_PORT_ULONG (PULONG Port)
+{
+ return GetPhys((ULONG)Port);
+}
+
+VOID STDCALL
+WRITE_PORT_BUFFER_UCHAR (PUCHAR Port,
+ PUCHAR Buffer,
+ ULONG Count)
+{
+ while(Count--) { SetPhysByte((ULONG)Port, *Buffer++); }
+}
+
+VOID STDCALL
+WRITE_PORT_BUFFER_USHORT (PUSHORT Port,
+ PUSHORT Buffer,
+ ULONG Count)
+{
+ while(Count--) { SetPhysWord((ULONG)Port, *Buffer++); }
+}
+
+VOID STDCALL
+WRITE_PORT_BUFFER_ULONG (PULONG Port,
+ PULONG Buffer,
+ ULONG Count)
+{
+ while(Count--) { SetPhys((ULONG)Port, *Buffer++); }
+}
+
+VOID STDCALL
+WRITE_PORT_UCHAR (PUCHAR Port,
+ UCHAR Value)
+{
+ SetPhysByte((ULONG)Port, Value);
+}
+
+VOID STDCALL
+WRITE_PORT_USHORT (PUSHORT Port,
+ USHORT Value)
+{
+ SetPhysWord((ULONG)Port, Value);
+}
+
+VOID STDCALL
+WRITE_PORT_ULONG (PULONG Port,
+ ULONG Value)
+{
+ SetPhys((ULONG)Port, Value);
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/processor.c b/reactos/hal/halppc/generic/processor.c
new file mode 100644
index 00000000000..25867253203
--- /dev/null
+++ b/reactos/hal/halppc/generic/processor.c
@@ -0,0 +1,50 @@
+/* $Id: processor.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: hal/halx86/generic/processor.c
+ * PURPOSE: Intel MultiProcessor specification support
+ * PROGRAMMER: David Welch (welch@cwcom.net)
+ * Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * NOTES: Parts adapted from linux SMP code
+ * UPDATE HISTORY:
+ * 22/05/1998 DW Created
+ * 12/04/2001 CSH Added MultiProcessor specification support
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+/* FUNCTIONS *****************************************************************/
+
+VOID STDCALL
+HalInitializeProcessor(ULONG ProcessorNumber,
+ PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ DPRINT("HalInitializeProcessor(%lu %p)\n", ProcessorNumber, LoaderBlock);
+ /* Set default IDR */
+ KeGetPcr()->IDR = 0xFFFFFFFB;
+ KeGetPcr()->StallScaleFactor = INITIAL_STALL_COUNT;
+}
+
+BOOLEAN STDCALL
+HalAllProcessorsStarted (VOID)
+{
+ DPRINT("HalAllProcessorsStarted()\n");
+
+ return TRUE;
+}
+
+BOOLEAN STDCALL
+HalStartNextProcessor(ULONG Unknown1,
+ ULONG ProcessorStack)
+{
+ DPRINT("HalStartNextProcessor(0x%lx 0x%lx)\n", Unknown1, ProcessorStack);
+
+ return TRUE;
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/pwroff.c b/reactos/hal/halppc/generic/pwroff.c
new file mode 100644
index 00000000000..cf6be7555b9
--- /dev/null
+++ b/reactos/hal/halppc/generic/pwroff.c
@@ -0,0 +1,121 @@
+/* $Id: pwroff.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * FILE : reactos/hal/x86/apm.c
+ * DESCRIPTION: Turn CPU off...
+ * PROJECT : ReactOS Operating System
+ * AUTHOR : D. Lindauer (July 11 1997)
+ * NOTE : This program is public domain
+ * REVISIONS :
+ * 1999-12-26
+ */
+
+#define APM_FUNCTION_AVAILABLE 0x5300
+#define APM_FUNCTION_CONNREAL 0x5301
+#define APM_FUNCTION_POWEROFF 0x5307
+#define APM_FUNCTION_ENABLECPU 0x530d
+#define APM_FUNCTION_ENABLEAPM 0x530e
+
+#define APM_DEVICE_BIOS 0
+#define APM_DEVICE_ALL 1
+
+#define APM_MODE_DISABLE 0
+#define APM_MODE_ENABLE 1
+
+
+
+#if defined(__GNUC__)
+
+nopm db 'No power management functionality',10,13,'$'
+errmsg db 'Power management error',10,13,'$'
+wrongver db 'Need APM version 1.1 or better',10,13,'$'
+;
+; Entry point
+;
+go:
+ mov dx,offset nopm
+ jc error
+ cmp ax,101h ; See if version 1.1 or greater
+ mov dx,offset wrongver
+ jc error
+
+ mov [ver],ax
+ mov ax,5301h ; Do a real mode connection
+ mov bx,0 ; device = BIOS
+ int 15h
+ jnc noconerr
+
+ cmp ah,2 ; Pass if already connected
+ mov dx,offset errmsg ; else error
+ jnz error
+noconerr:
+ mov ax,530eh ; Enable latest version of APM
+ mov bx,0 ; device = BIOS
+ mov cx,[ver] ; version
+ int 15h
+ mov dx,offset errmsg
+ jc error
+
+ mov ax,530dh ; Now engage and enable CPU management
+ mov bx,1 ; device = all
+ mov cx,1 ; enable
+ int 15h
+ mov dx,offset errmsg
+ jc error
+
+ mov ax,530fh
+ mov bx,1 ; device = ALL
+ mov cx,1 ; enable
+ int 15h
+ mov dx,offset errmsg
+ jc error
+
+ mov dx,offset errmsg
+error:
+ call print
+ mov ax,4c01h
+ int 21h
+ int 3
+ end start
+
+
+BOOLEAN
+ApmCall (
+ DWORD Function,
+ DWORD Device,
+ DWORD Mode
+ )
+{
+ /* AX <== Function */
+ /* BX <== Device */
+ /* CX <== Mode */
+ __asm__("int 21\n"); /* 0x15 */
+}
+
+#elif defined(_MSC_VER)
+#else
+#error Unknown compiler for inline assembler
+#endif
+
+
+BOOLEAN
+HalPowerOff (VOID)
+{
+ ApmCall (
+ APM_FUNCTION_AVAILABLE,
+ APM_DEVICE_BIOS,
+ 0
+ );
+ ApmCall (
+ APM_FUNCTION_ENABLEAPM,
+ );
+ /* Shutdown CPU */
+ ApmCall (
+ APM_FUNCTION_POWEROFF,
+ APM_DEVICE_ALL,
+ 3
+ );
+ return TRUE;
+}
+
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/reboot.c b/reactos/hal/halppc/generic/reboot.c
new file mode 100644
index 00000000000..89ab5c0d221
--- /dev/null
+++ b/reactos/hal/halppc/generic/reboot.c
@@ -0,0 +1,41 @@
+/* $Id: reboot.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/reboot.c
+ * PURPOSE: Reboot functions.
+ * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de)
+ * UPDATE HISTORY:
+ * Created 11/10/99
+ */
+
+#include
+#define NDEBUG
+#include
+
+typedef void (*void_fun)();
+static VOID
+HalReboot (VOID)
+{
+ void_fun reset_vector = (void_fun)0xfff00100;
+ reset_vector();
+}
+
+
+VOID STDCALL
+HalReturnToFirmware (
+ FIRMWARE_REENTRY Action
+ )
+{
+ if (Action == HalHaltRoutine)
+ {
+ DbgPrint ("HalReturnToFirmware called!\n");
+ DbgBreakPoint ();
+ }
+ else if (Action == HalRebootRoutine)
+ {
+ HalReboot ();
+ }
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/resource.c b/reactos/hal/halppc/generic/resource.c
new file mode 100644
index 00000000000..acf17ff151d
--- /dev/null
+++ b/reactos/hal/halppc/generic/resource.c
@@ -0,0 +1,31 @@
+/* $Id: resource.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: hal/halx86/generic/resource.c
+ * PURPOSE: Miscellaneous resource functions
+ * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+
+/* FUNCTIONS ****************************************************************/
+
+VOID STDCALL
+HalReportResourceUsage(VOID)
+{
+ /*
+ * FIXME: Report all resources used by hal.
+ * Calls IoReportHalResourceUsage()
+ */
+
+ /* Initialize PCI bus. */
+ HalpInitPciBus ();
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/spinlock.c b/reactos/hal/halppc/generic/spinlock.c
new file mode 100644
index 00000000000..30d66bb230b
--- /dev/null
+++ b/reactos/hal/halppc/generic/spinlock.c
@@ -0,0 +1,191 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/halx86/up/spinlock.c
+ * PURPOSE: Implements spinlocks
+ * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+#undef KeAcquireSpinLock
+#undef KeReleaseSpinLock
+#undef KeLowerIrql
+#undef KeRaiseIrql
+
+/* FUNCTIONS ***************************************************************/
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+KeLowerIrql(KIRQL NewIrql)
+{
+ /* Call the fastcall function */
+ KfLowerIrql(NewIrql);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+KeRaiseIrql(KIRQL NewIrql,
+ PKIRQL OldIrql)
+{
+ /* Call the fastcall function */
+ *OldIrql = KfRaiseIrql(NewIrql);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+KeAcquireSpinLock(PKSPIN_LOCK SpinLock,
+ PKIRQL OldIrql)
+{
+ /* Call the fastcall function */
+ *OldIrql = KfAcquireSpinLock(SpinLock);
+}
+
+/*
+ * @implemented
+ */
+KIRQL
+FASTCALL
+KeAcquireSpinLockRaiseToSynch(PKSPIN_LOCK SpinLock)
+{
+ /* Simply raise to dispatch */
+ return KfRaiseIrql(DISPATCH_LEVEL);
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+KeReleaseSpinLock(PKSPIN_LOCK SpinLock,
+ KIRQL NewIrql)
+{
+ /* Call the fastcall function */
+ KfReleaseSpinLock(SpinLock, NewIrql);
+}
+
+/*
+ * @implemented
+ */
+KIRQL
+FASTCALL
+KfAcquireSpinLock(PKSPIN_LOCK SpinLock)
+{
+ /* Simply raise to dispatch */
+ return KfRaiseIrql(DISPATCH_LEVEL);
+}
+
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+KfReleaseSpinLock(PKSPIN_LOCK SpinLock,
+ KIRQL OldIrql)
+{
+ /* Simply lower IRQL back */
+ KfLowerIrql(OldIrql);
+}
+
+/*
+ * @implemented
+ */
+KIRQL
+FASTCALL
+KeAcquireQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
+{
+ /* Simply raise to dispatch */
+ return KfRaiseIrql(DISPATCH_LEVEL);
+}
+
+/*
+ * @implemented
+ */
+KIRQL
+FASTCALL
+KeAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber)
+{
+ /* Simply raise to dispatch */
+ return KfRaiseIrql(DISPATCH_LEVEL);
+}
+
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock,
+ IN PKLOCK_QUEUE_HANDLE LockHandle)
+{
+ /* Simply raise to dispatch */
+ LockHandle->OldIrql = KfRaiseIrql(DISPATCH_LEVEL);
+}
+
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+KeReleaseQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle,
+ IN KIRQL OldIrql)
+{
+ /* Simply lower IRQL back */
+ KfLowerIrql(OldIrql);
+}
+
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle)
+{
+ /* Simply lower IRQL back */
+ KfLowerIrql(LockHandle->OldIrql);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+FASTCALL
+KeTryToAcquireQueuedSpinLockRaiseToSynch(IN PKLOCK_QUEUE_HANDLE LockHandle,
+ IN PKIRQL OldIrql)
+{
+ /* Simply raise to dispatch */
+ *OldIrql = KfRaiseIrql(DISPATCH_LEVEL);
+
+ /* Always return true on UP Machines */
+ return TRUE;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+FASTCALL
+KeTryToAcquireQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle,
+ IN PKIRQL OldIrql)
+{
+ /* Simply raise to dispatch */
+ *OldIrql = KfRaiseIrql(DISPATCH_LEVEL);
+
+ /* Always return true on UP Machines */
+ return TRUE;
+}
+
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/sysbus.c b/reactos/hal/halppc/generic/sysbus.c
new file mode 100644
index 00000000000..4955b122cfd
--- /dev/null
+++ b/reactos/hal/halppc/generic/sysbus.c
@@ -0,0 +1,66 @@
+/* $Id: sysbus.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/sysbus.c
+ * PURPOSE: System bus handler functions
+ * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
+ * UPDATE HISTORY:
+ * 09/04/2000 Created
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+
+/* FUNCTIONS ****************************************************************/
+
+ULONG STDCALL
+HalpGetSystemInterruptVector(PVOID BusHandler,
+ ULONG BusNumber,
+ ULONG BusInterruptLevel,
+ ULONG BusInterruptVector,
+ PKIRQL Irql,
+ PKAFFINITY Affinity)
+{
+ ULONG Vector = IRQ2VECTOR(BusInterruptVector);
+ *Irql = VECTOR2IRQL(Vector);
+ *Affinity = 0xFFFFFFFF;
+ return Vector;
+}
+
+
+BOOLEAN STDCALL
+HalpTranslateSystemBusAddress(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ PHYSICAL_ADDRESS BusAddress,
+ PULONG AddressSpace,
+ PPHYSICAL_ADDRESS TranslatedAddress)
+{
+ ULONG BaseAddress = 0;
+
+ if (*AddressSpace == 0)
+ {
+ /* memory space */
+
+ }
+ else if (*AddressSpace == 1)
+ {
+ /* io space */
+
+ }
+ else
+ {
+ /* other */
+ return FALSE;
+ }
+
+ TranslatedAddress->QuadPart = BusAddress.QuadPart + BaseAddress;
+
+ return TRUE;
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/sysinfo.c b/reactos/hal/halppc/generic/sysinfo.c
new file mode 100644
index 00000000000..a5ccfeb1be7
--- /dev/null
+++ b/reactos/hal/halppc/generic/sysinfo.c
@@ -0,0 +1,74 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/sysinfo.c
+ * PURPOSE: Getting system information
+ * PROGRAMMER: David Welch (welch@mcmail.com)
+ * UPDATE HISTORY:
+ * Created 22/05/98
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+
+
+/* FUNCTIONS ****************************************************************/
+
+NTSTATUS STDCALL
+HalpQuerySystemInformation(IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN OUT PVOID Buffer,
+ OUT PULONG ReturnedLength)
+{
+ ULONG DataLength;
+ NTSTATUS Status;
+
+ DPRINT1("HalpQuerySystemInformation() called\n");
+
+ *ReturnedLength = 0;
+
+ DataLength = 0;
+
+ switch(InformationClass)
+ {
+#if 0
+ case HalInstalledBusInformation:
+ Status = HalpQueryBusInformation(BufferSize,
+ Buffer,
+ ReturnedLength);
+ break;
+#endif
+
+ default:
+ DataLength = 0;
+ Status = STATUS_INVALID_LEVEL;
+ break;
+ }
+
+ if (DataLength != 0)
+ {
+ if (DataLength > BufferSize)
+ DataLength = BufferSize;
+
+// RtlCopyMemory();
+
+ *ReturnedLength = DataLength;
+ }
+
+ return(Status);
+}
+
+
+#if 0
+NTSTATUS
+HalpSetSystemInformation(VOID)
+{
+ UNIMPLEMENTED;
+}
+#endif
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/systimer.S b/reactos/hal/halppc/generic/systimer.S
new file mode 100644
index 00000000000..285686675a7
--- /dev/null
+++ b/reactos/hal/halppc/generic/systimer.S
@@ -0,0 +1,48 @@
+/*
+ * FILE: hal/halx86/generic/timer.S
+ * COPYRIGHT: See COPYING in the top level directory
+ * PURPOSE: System Timer Interrupt and Management
+ * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include
+#include
+.intel_syntax noprefix
+
+/* FUNCTIONS *****************************************************************/
+
+.globl _HalpClockInterrupt@0
+.func HalpClockInterrupt@0
+_HalpClockInterrupt@0:
+
+ /* Enter trap */
+ INT_PROLOG Hci, DoPushFakeErrorCode
+
+ /* Push vector and make stack for IRQL */
+ push 0x30
+ sub esp, 4
+
+ /* Begin the interrupt */
+ push esp
+ push 0x30
+ push CLOCK2_LEVEL
+ call _HalBeginSystemInterrupt@12
+
+ /* Check if it's spurious */
+ or al, al
+ jz Spurious
+
+ /* Do a tick */
+ mov eax, 100000
+ jmp _KeUpdateSystemTime@0
+
+Spurious:
+
+ /* Exit the interrupt */
+ add esp, 8
+ mov esi, $
+ jmp _Kei386EoiHelper@0
+.endfunc
+
diff --git a/reactos/hal/halppc/generic/time.c b/reactos/hal/halppc/generic/time.c
new file mode 100644
index 00000000000..bb81cc01cec
--- /dev/null
+++ b/reactos/hal/halppc/generic/time.c
@@ -0,0 +1,102 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/time.c
+ * PURPOSE: Getting time information
+ * UPDATE HISTORY:
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+
+/* MACROS and CONSTANTS ******************************************************/
+
+/* macro BCD_INT : convert bcd to int */
+#define BCD_INT(bcd) (((bcd & 0xf0) >> 4) * 10 + (bcd &0x0f))
+
+/* macro INT_BCD : convert int to bcd */
+#define INT_BCD(int) (((int / 10) << 4) + (int % 10))
+
+
+#define RTC_REGISTER_A 0x0A
+#define RTC_REG_A_UIP 0x80 /* Update In Progress bit */
+
+#define RTC_REGISTER_B 0x0B
+
+#define RTC_REGISTER_CENTURY 0x32
+
+/* GLOBALS ******************************************************************/
+
+/* FUNCTIONS *****************************************************************/
+
+BOOLEAN STDCALL
+HalQueryRealTimeClock(PTIME_FIELDS Time)
+{
+ return TRUE;
+}
+
+
+VOID STDCALL
+HalSetRealTimeClock(PTIME_FIELDS Time)
+{
+}
+
+
+BOOLEAN STDCALL
+HalGetEnvironmentVariable(PCH Name,
+ USHORT ValueLength,
+ PCH Value)
+{
+ strncpy(Value, "TRUE", ValueLength);
+ return TRUE;
+}
+
+
+BOOLEAN STDCALL
+HalSetEnvironmentVariable(PCH Name,
+ PCH Value)
+{
+ return TRUE;
+}
+
+
+ULONG STDCALL
+HalpGetCmosData(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length)
+{
+ DPRINT("HalpGetCmosData() called.\n");
+ DPRINT(" BusNumber %lu\n", BusNumber);
+ DPRINT(" SlotNumber %lu\n", SlotNumber);
+ DPRINT(" Offset 0x%lx\n", Offset);
+ DPRINT(" Length 0x%lx\n", Length);
+
+ return 0;
+}
+
+
+ULONG STDCALL
+HalpSetCmosData(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length)
+{
+ DPRINT("HalpSetCmosData() called.\n");
+ DPRINT(" BusNumber %lu\n", BusNumber);
+ DPRINT(" SlotNumber %lu\n", SlotNumber);
+ DPRINT(" Offset 0x%lx\n", Offset);
+ DPRINT(" Length 0x%lx\n", Length);
+
+ return 0;
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/timer.c b/reactos/hal/halppc/generic/timer.c
new file mode 100644
index 00000000000..9df30825631
--- /dev/null
+++ b/reactos/hal/halppc/generic/timer.c
@@ -0,0 +1,205 @@
+/*
+ * ReactOS kernel
+ * Copyright (C) 2000 David Welch
+ * Copyright (C) 1999 Gareth Owen , Ramon von Handel
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * This software is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING. If not, write
+ * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
+ * MA 02139, USA.
+ *
+ */
+/* $Id: timer.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/udelay.c
+ * PURPOSE: Busy waiting
+ * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk)
+ * UPDATE HISTORY:
+ * 06/11/99 Created
+ */
+
+/* INCLUDES ***************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+/* GLOBALS ******************************************************************/
+
+#define TMR_CTRL 0x43 /* I/O for control */
+#define TMR_CNT0 0x40 /* I/O for counter 0 */
+#define TMR_CNT1 0x41 /* I/O for counter 1 */
+#define TMR_CNT2 0x42 /* I/O for counter 2 */
+
+#define TMR_SC0 0 /* Select channel 0 */
+#define TMR_SC1 0x40 /* Select channel 1 */
+#define TMR_SC2 0x80 /* Select channel 2 */
+
+#define TMR_LOW 0x10 /* RW low byte only */
+#define TMR_HIGH 0x20 /* RW high byte only */
+#define TMR_BOTH 0x30 /* RW both bytes */
+
+#define TMR_MD0 0 /* Mode 0 */
+#define TMR_MD1 0x2 /* Mode 1 */
+#define TMR_MD2 0x4 /* Mode 2 */
+#define TMR_MD3 0x6 /* Mode 3 */
+#define TMR_MD4 0x8 /* Mode 4 */
+#define TMR_MD5 0xA /* Mode 5 */
+
+#define TMR_BCD 1 /* BCD mode */
+
+#define TMR_LATCH 0 /* Latch command */
+
+#define TMR_READ 0xF0 /* Read command */
+#define TMR_CNT 0x20 /* CNT bit (Active low, subtract it) */
+#define TMR_STAT 0x10 /* Status bit (Active low, subtract it) */
+#define TMR_CH2 0x8 /* Channel 2 bit */
+#define TMR_CH1 0x4 /* Channel 1 bit */
+#define TMR_CH0 0x2 /* Channel 0 bit */
+
+#define MILLISEC 10 /* Number of millisec between interrupts */
+#define HZ (1000 / MILLISEC) /* Number of interrupts per second */
+#define CLOCK_TICK_RATE 1193182 /* Clock frequency of the timer chip */
+#define LATCH (CLOCK_TICK_RATE / HZ) /* Count to program into the timer chip */
+#define PRECISION 8 /* Number of bits to calibrate for delay loop */
+
+static BOOLEAN UdelayCalibrated = FALSE;
+
+/* FUNCTIONS **************************************************************/
+
+static BOOLEAN PPCGetEEBit()
+{
+ ULONG Msr;
+ __asm__("mfmsr %0" : "=r" (Msr));
+ return (Msr & 0x8000) != 0;
+}
+
+/*
+ * NOTE: This function MUST NOT be optimized by the compiler!
+ * If it is, it obviously will not delay AT ALL, and the system
+ * will appear completely frozen at boot since
+ * HalpCalibrateStallExecution will never return.
+ * There are three options to stop optimization:
+ * 1. Use a volatile automatic variable. Making it delay quite a bit
+ * due to memory accesses, and keeping the code portable. However,
+ * as this involves memory access it depends on both the CPU cache,
+ * e.g. if the stack used is already in a cache line or not, and
+ * whether or not we're MP. If MP, another CPU could (probably would)
+ * also access RAM at the same time - making the delay imprecise.
+ * 2. Use compiler-specific #pragma's to disable optimization.
+ * 3. Use inline assembly, making it equally unportable as #2.
+ * For supported compilers we use inline assembler. For the others,
+ * portable plain C.
+ */
+DECLSPEC_NOINLINE VOID STDCALL
+__KeStallExecutionProcessor(ULONG Loops)
+{
+ ULONG DecInit, DecCount;
+ if (!Loops)
+ {
+ return;
+ }
+ __asm__("mfdec %0" : "=r" (DecInit));
+ do {
+ __asm__("mfdec %0" : "=r" (DecCount));
+ } while((DecCount - DecInit) < Loops);
+}
+
+VOID
+STDCALL
+KeStallExecutionProcessor(ULONG Microseconds)
+{
+ PKIPCR Pcr = (PKIPCR)KeGetPcr();
+ LARGE_INTEGER EndCount, CurrentCount;
+ ULONG NewCount;
+ __asm__("mfdec %0" : "=r" (NewCount));
+ EndCount.QuadPart = NewCount + Microseconds * (ULONGLONG)Pcr->Prcb->MHz;
+ do
+ {
+ __asm__("mfdec %0" : "=r" (NewCount));
+ if(NewCount < CurrentCount.LowPart)
+ CurrentCount.HighPart++;
+ CurrentCount.LowPart = NewCount;
+ }
+ while (CurrentCount.QuadPart < EndCount.QuadPart);
+}
+
+VOID HalpCalibrateStallExecution(VOID)
+{
+ PKIPCR Pcr;
+
+ if (UdelayCalibrated)
+ {
+ return;
+ }
+
+ UdelayCalibrated = TRUE;
+ Pcr = (PKIPCR)KeGetPcr();
+
+ // XXX arty FIXME
+ /* Pcr->Prcb.MHz = (ULONG)(EndCount.QuadPart - StartCount.QuadPart) / 10000; */
+ Pcr->Prcb->MHz = 300;
+ DPRINT1("%luMHz\n", Pcr->Prcb->MHz);
+}
+
+
+VOID STDCALL
+HalCalibratePerformanceCounter(ULONG Count)
+{
+ BOOLEAN InterruptsEnabled = PPCGetEEBit();
+
+ /* save flags and disable interrupts */
+ _disable();
+
+ __KeStallExecutionProcessor(Count);
+
+ /* restore flags */
+ if(InterruptsEnabled)
+ _enable();
+}
+
+
+LARGE_INTEGER
+STDCALL
+KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFreq)
+/*
+ * FUNCTION: Queries the finest grained running count available in the system
+ * ARGUMENTS:
+ * PerformanceFreq (OUT) = The routine stores the number of
+ * performance counter ticks per second here
+ * RETURNS: The number of performance counter ticks since boot
+ */
+{
+ PKIPCR Pcr;
+ LARGE_INTEGER Value;
+ BOOLEAN InterruptsEnabled = PPCGetEEBit();
+
+ _disable();
+
+ Pcr = (PKIPCR)KeGetPcr();
+
+ if (NULL != PerformanceFreq)
+ {
+ PerformanceFreq->QuadPart = Pcr->Prcb->MHz * (ULONGLONG)1000000;
+ }
+ __asm__("mfdec %0" : "=r" (Value.LowPart));
+
+ if(InterruptsEnabled)
+ _enable();
+
+ return Value;
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/include/apic.h b/reactos/hal/halppc/include/apic.h
new file mode 100644
index 00000000000..7454c210f72
--- /dev/null
+++ b/reactos/hal/halppc/include/apic.h
@@ -0,0 +1,214 @@
+/*
+ *
+ */
+
+#ifndef __INTERNAL_HAL_APIC_H
+#define __INTERNAL_HAL_APIC_H
+
+#define APIC_DEFAULT_BASE 0xFEE00000 /* Default Local APIC Base Register Address */
+
+/* APIC Register Address Map */
+#define APIC_ID 0x0020 /* Local APIC ID Register (R/W) */
+#define APIC_VER 0x0030 /* Local APIC Version Register (R) */
+#define APIC_TPR 0x0080 /* Task Priority Register (R/W) */
+#define APIC_APR 0x0090 /* Arbitration Priority Register (R) */
+#define APIC_PPR 0x00A0 /* Processor Priority Register (R) */
+#define APIC_EOI 0x00B0 /* EOI Register (W) */
+#define APIC_LDR 0x00D0 /* Logical Destination Register (R/W) */
+#define APIC_DFR 0x00E0 /* Destination Format Register (0-27 R, 28-31 R/W) */
+#define APIC_SIVR 0x00F0 /* Spurious Interrupt Vector Register (0-3 R, 4-9 R/W) */
+#define APIC_ISR 0x0100 /* Interrupt Service Register 0-255 (R) */
+#define APIC_TMR 0x0180 /* Trigger Mode Register 0-255 (R) */
+#define APIC_IRR 0x0200 /* Interrupt Request Register 0-255 (r) */
+#define APIC_ESR 0x0280 /* Error Status Register (R) */
+#define APIC_ICR0 0x0300 /* Interrupt Command Register 0-31 (R/W) */
+#define APIC_ICR1 0x0310 /* Interrupt Command Register 32-63 (R/W) */
+#define APIC_LVTT 0x0320 /* Local Vector Table (Timer) (R/W) */
+#define APIC_LVTTHMR 0x0330
+#define APIC_LVTPC 0x0340 /* Performance Counter LVT (R/W) */
+#define APIC_LINT0 0x0350 /* Local Vector Table (LINT0) (R/W) */
+#define APIC_LINT1 0x0360 /* Local Vector Table (LINT1) (R/W) */
+#define APIC_LVT3 0x0370 /* Local Vector Table (Error) (R/W) */
+#define APIC_ICRT 0x0380 /* Initial Count Register for Timer (R/W) */
+#define APIC_CCRT 0x0390 /* Current Count Register for Timer (R) */
+#define APIC_TDCR 0x03E0 /* Timer Divide Configuration Register (R/W) */
+
+#define APIC_ID_MASK (0xF << 24)
+#define GET_APIC_ID(x) (((x) & APIC_ID_MASK) >> 24)
+#define GET_APIC_LOGICAL_ID(x) (((x)>>24)&0xFF)
+#define APIC_VER_MASK 0xFF00FF
+#define GET_APIC_VERSION(x) ((x) & 0xFF)
+#define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFF)
+
+#define APIC_TPR_PRI 0xFF
+#define APIC_TPR_INT 0xF0
+#define APIC_TPR_SUB 0xF
+#define APIC_TPR_MAX 0xFF /* Maximum priority */
+#define APIC_TPR_MIN 0x20 /* Minimum priority */
+
+#define APIC_LDR_MASK (0xFF << 24)
+
+#define APIC_SIVR_ENABLE (0x1 << 8)
+#define APIC_SIVR_FOCUS (0x1 << 9)
+
+#define APIC_ESR_MASK (0xFE << 0) /* Error Mask */
+
+#define APIC_ICR0_VECTOR (0xFF << 0) /* Vector */
+#define APIC_ICR0_DM (0x7 << 8) /* Delivery Mode */
+#define APIC_ICR0_DESTM (0x1 << 11) /* Destination Mode */
+#define APIC_ICR0_DS (0x1 << 12) /* Delivery Status */
+#define APIC_ICR0_LEVEL (0x1 << 14) /* Level */
+#define APIC_ICR0_TM (0x1 << 15) /* Trigger Mode */
+#define APIC_ICR0_DESTS (0x3 << 18) /* Destination Shorthand */
+
+/* Delivery Modes */
+#define APIC_DM_FIXED (0x0 << 8)
+#define APIC_DM_LOWEST (0x1 << 8)
+#define APIC_DM_SMI (0x2 << 8)
+#define APIC_DM_REMRD (0x3 << 8)
+#define APIC_DM_NMI (0x4 << 8)
+#define APIC_DM_INIT (0x5 << 8)
+#define APIC_DM_STARTUP (0x6 << 8)
+#define APIC_DM_EXTINT (0x7 << 8)
+#define GET_APIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7)
+#define SET_APIC_DELIVERY_MODE(x,y) (((x) & ~0x700) | ((y) << 8))
+
+/* Destination Shorthand values */
+#define APIC_ICR0_DESTS_FIELD (0x0 << 0)
+#define APIC_ICR0_DESTS_SELF (0x1 << 18)
+#define APIC_ICR0_DESTS_ALL (0x2 << 18)
+#define APIC_ICR0_DESTS_ALL_BUT_SELF (0x3 << 18)
+
+#define APIC_ICR0_LEVEL_DEASSERT (0x0 << 14) /* Deassert level */
+#define APIC_ICR0_LEVEL_ASSERT (0x1 << 14) /* Assert level */
+
+#define GET_APIC_DEST_FIELD(x) (((x) >> 24) & 0xFF)
+#define SET_APIC_DEST_FIELD(x) (((x) & 0xFF) << 24)
+
+#define GET_APIC_TIMER_BASE(x) (((x) >> 18) & 0x3)
+#define SET_APIC_TIMER_BASE(x) ((x) << 18)
+#define APIC_TIMER_BASE_CLKIN 0x0
+#define APIC_TIMER_BASE_TMBASE 0x1
+#define APIC_TIMER_BASE_DIV 0x2
+
+#define APIC_LVT_VECTOR (0xFF << 0) /* Vector */
+#define APIC_LVT_DS (0x1 << 12) /* Delivery Status */
+#define APIC_LVT_REMOTE_IRR (0x1 << 14) /* Remote IRR */
+#define APIC_LVT_LEVEL_TRIGGER (0x1 << 15) /* Lvel Triggered */
+#define APIC_LVT_MASKED (0x1 << 16) /* Mask */
+#define APIC_LVT_PERIODIC (0x1 << 17) /* Timer Mode */
+
+#define APIC_LVT3_DM (0x7 << 8)
+#define APIC_LVT3_IIPP (0x1 << 13)
+#define APIC_LVT3_TM (0x1 << 15)
+#define APIC_LVT3_MASKED (0x1 << 16)
+#define APIC_LVT3_OS (0x1 << 17)
+
+#define APIC_TDCR_TMBASE (0x1 << 2)
+#define APIC_TDCR_MASK 0x0F
+#define APIC_TDCR_2 0x00
+#define APIC_TDCR_4 0x01
+#define APIC_TDCR_8 0x02
+#define APIC_TDCR_16 0x03
+#define APIC_TDCR_32 0x08
+#define APIC_TDCR_64 0x09
+#define APIC_TDCR_128 0x0A
+#define APIC_TDCR_1 0x0B
+
+#define APIC_LVT_VECTOR (0xFF << 0) /* Vector */
+#define APIC_LVT_DS (0x1 << 12) /* Delivery Status */
+#define APIC_LVT_REMOTE_IRR (0x1 << 14) /* Remote IRR */
+#define APIC_LVT_LEVEL_TRIGGER (0x1 << 15) /* Lvel Triggered */
+#define APIC_LVT_MASKED (0x1 << 16) /* Mask */
+#define APIC_LVT_PERIODIC (0x1 << 17) /* Timer Mode */
+
+#define APIC_LVT3_DM (0x7 << 8)
+#define APIC_LVT3_IIPP (0x1 << 13)
+#define APIC_LVT3_TM (0x1 << 15)
+#define APIC_LVT3_MASKED (0x1 << 16)
+#define APIC_LVT3_OS (0x1 << 17)
+
+#define APIC_TDCR_TMBASE (0x1 << 2)
+#define APIC_TDCR_MASK 0x0F
+#define APIC_TDCR_2 0x00
+#define APIC_TDCR_4 0x01
+#define APIC_TDCR_8 0x02
+#define APIC_TDCR_16 0x03
+#define APIC_TDCR_32 0x08
+#define APIC_TDCR_64 0x09
+#define APIC_TDCR_128 0x0A
+#define APIC_TDCR_1 0x0B
+
+#define APIC_TARGET_SELF 0x100
+#define APIC_TARGET_ALL 0x200
+#define APIC_TARGET_ALL_BUT_SELF 0x300
+
+#define APIC_INTEGRATED(version) (version & 0xF0)
+
+typedef enum {
+ amPIC = 0, /* IMCR and PIC compatibility mode */
+ amVWIRE /* Virtual Wire compatibility mode */
+} APIC_MODE;
+
+#ifdef CONFIG_SMP
+#define MAX_CPU 32
+#else
+#define MAX_CPU 1
+#endif
+
+/*
+ * Local APIC timer IRQ vector is on a different priority level,
+ * to work around the 'lost local interrupt if more than 2 IRQ
+ * sources per level' errata.
+ */
+#define LOCAL_TIMER_VECTOR 0xEF
+
+#define IPI_VECTOR 0xFB
+#define ERROR_VECTOR 0xFE
+#define SPURIOUS_VECTOR 0xFF /* Must be 0xXF */
+
+/* CPU flags */
+#define CPU_USABLE 0x01 /* 1 if the CPU is usable (ie. can be used) */
+#define CPU_ENABLED 0x02 /* 1 if the CPU is enabled */
+#define CPU_BSP 0x04 /* 1 if the CPU is the bootstrap processor */
+#define CPU_TSC 0x08 /* 1 if the CPU has a time stamp counter */
+
+typedef struct _CPU_INFO
+{
+ UCHAR Flags; /* CPU flags */
+ UCHAR APICId; /* Local APIC ID */
+ UCHAR APICVersion; /* Local APIC version */
+// UCHAR MaxLVT; /* Number of LVT registers */
+ ULONG BusSpeed; /* BUS speed */
+ ULONG CoreSpeed; /* Core speed */
+ UCHAR Padding[16-12]; /* Padding to 16-byte */
+} CPU_INFO, *PCPU_INFO;
+
+extern ULONG CPUCount; /* Total number of CPUs */
+extern ULONG BootCPU; /* Bootstrap processor */
+extern ULONG OnlineCPUs; /* Bitmask of online CPUs */
+extern CPU_INFO CPUMap[MAX_CPU]; /* Map of all CPUs in the system */
+
+/* Prototypes */
+
+__inline VOID APICWrite(ULONG Offset, ULONG Value);
+__inline ULONG APICRead(ULONG Offset);
+VOID APICSendIPI(ULONG Target, ULONG Mode);
+VOID APICSetup(VOID);
+VOID HaliInitBSP(VOID);
+VOID APICSyncArbIDs(VOID);
+__inline VOID APICSendEOI(VOID);
+VOID APICCalibrateTimer(ULONG CPU);
+VOID HaliStartApplicationProcessor(ULONG Cpu, ULONG Stack);
+
+static __inline ULONG ThisCPU(VOID)
+{
+ return (APICRead(APIC_ID) & APIC_ID_MASK) >> 24;
+}
+
+
+#endif
+
+
+/* EOF */
+
diff --git a/reactos/hal/halppc/include/bus.h b/reactos/hal/halppc/include/bus.h
new file mode 100644
index 00000000000..b231d5ecf22
--- /dev/null
+++ b/reactos/hal/halppc/include/bus.h
@@ -0,0 +1,133 @@
+/*
+
+ */
+
+#ifndef __INTERNAL_HAL_BUS_H
+#define __INTERNAL_HAL_BUS_H
+
+
+typedef NTSTATUS
+(STDCALL *pAdjustResourceList)(IN PBUS_HANDLER BusHandler,
+ IN ULONG BusNumber,
+ IN OUT PCM_RESOURCE_LIST Resources);
+
+typedef NTSTATUS
+(STDCALL *pAssignSlotResources)(IN PBUS_HANDLER BusHandler,
+ IN ULONG BusNumber,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources);
+
+typedef ULONG
+(STDCALL *pGetSetBusData)(IN PBUS_HANDLER BusHandler,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ OUT PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length);
+
+typedef ULONG
+(STDCALL *pGetInterruptVector)(IN PBUS_HANDLER BusHandler,
+ IN ULONG BusNumber,
+ IN ULONG BusInterruptLevel,
+ IN ULONG BusInterruptVector,
+ OUT PKIRQL Irql,
+ OUT PKAFFINITY Affinity);
+
+typedef ULONG
+(STDCALL *pTranslateBusAddress)(IN PBUS_HANDLER BusHandler,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ IN OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress);
+
+typedef struct _BUS_HANDLER
+{
+ LIST_ENTRY Entry;
+ INTERFACE_TYPE InterfaceType;
+ BUS_DATA_TYPE BusDataType;
+ ULONG BusNumber;
+ ULONG RefCount;
+
+ pGetSetBusData GetBusData;
+ pGetSetBusData SetBusData;
+ pAdjustResourceList AdjustResourceList;
+ pAssignSlotResources AssignSlotResources;
+ pGetInterruptVector GetInterruptVector;
+ pTranslateBusAddress TranslateBusAddress;
+} BUS_HANDLER;
+
+
+/* FUNCTIONS *****************************************************************/
+
+/* bus.c */
+PBUS_HANDLER
+HalpAllocateBusHandler(INTERFACE_TYPE InterfaceType,
+ BUS_DATA_TYPE BusDataType,
+ ULONG BusNumber);
+
+/* sysbus.h */
+ULONG STDCALL
+HalpGetSystemInterruptVector(PVOID BusHandler,
+ ULONG BusNumber,
+ ULONG BusInterruptLevel,
+ ULONG BusInterruptVector,
+ PKIRQL Irql,
+ PKAFFINITY Affinity);
+
+BOOLEAN STDCALL
+HalpTranslateSystemBusAddress(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ PHYSICAL_ADDRESS BusAddress,
+ PULONG AddressSpace,
+ PPHYSICAL_ADDRESS TranslatedAddress);
+
+/* isa.c */
+ULONG STDCALL
+HalpGetIsaInterruptVector(PVOID BusHandler,
+ ULONG BusNumber,
+ ULONG BusInterruptLevel,
+ ULONG BusInterruptVector,
+ PKIRQL Irql,
+ PKAFFINITY Affinity);
+
+BOOLEAN STDCALL
+HalpTranslateIsaBusAddress(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ PHYSICAL_ADDRESS BusAddress,
+ PULONG AddressSpace,
+ PPHYSICAL_ADDRESS TranslatedAddress);
+
+/* time.c */
+ULONG STDCALL
+HalpGetCmosData(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length);
+
+ULONG STDCALL
+HalpSetCmosData(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length);
+
+/* mca.h */
+ULONG STDCALL
+HalpGetMicroChannelData(PBUS_HANDLER BusHandler,
+ ULONG BusNumber,
+ ULONG SlotNumber,
+ PVOID Buffer,
+ ULONG Offset,
+ ULONG Length);
+
+#endif /* __INTERNAL_HAL_BUS_H */
+
+/* EOF */
+
diff --git a/reactos/hal/halppc/include/hal.h b/reactos/hal/halppc/include/hal.h
new file mode 100644
index 00000000000..b15a4d9800d
--- /dev/null
+++ b/reactos/hal/halppc/include/hal.h
@@ -0,0 +1,37 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Hardware Abstraction Layer
+ * FILE: hal/halx86/include/hal.h
+ * PURPOSE: HAL Header
+ * PROGRAMMER: Alex Ionescu (alex@relsoft.net)
+ */
+
+/* INCLUDES ******************************************************************/
+
+/* C Headers */
+#include
+
+/* IFS/DDK/NDK Headers */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define KPCR_BASE 0xFF000000 // HACK!
+
+/* Internal HAL Headers */
+#include "apic.h"
+#include "bus.h"
+#include "halirq.h"
+#include "haldma.h"
+#include "halp.h"
+#include "mps.h"
+#include "ioapic.h"
+
+/* Helper Header */
+#include
+
+/* EOF */
diff --git a/reactos/hal/halppc/include/haldma.h b/reactos/hal/halppc/include/haldma.h
new file mode 100644
index 00000000000..59ddb9338a0
--- /dev/null
+++ b/reactos/hal/halppc/include/haldma.h
@@ -0,0 +1,383 @@
+#ifndef HALDMA_H
+#define HALDMA_H
+
+/*
+ * DMA Page Register Structure
+ * 080 DMA RESERVED
+ * 081 DMA Page Register (channel 2)
+ * 082 DMA Page Register (channel 3)
+ * 083 DMA Page Register (channel 1)
+ * 084 DMA RESERVED
+ * 085 DMA RESERVED
+ * 086 DMA RESERVED
+ * 087 DMA Page Register (channel 0)
+ * 088 DMA RESERVED
+ * 089 PS/2-DMA Page Register (channel 6)
+ * 08A PS/2-DMA Page Register (channel 7)
+ * 08B PS/2-DMA Page Register (channel 5)
+ * 08C PS/2-DMA RESERVED
+ * 08D PS/2-DMA RESERVED
+ * 08E PS/2-DMA RESERVED
+ * 08F PS/2-DMA Page Register (channel 4)
+ */
+
+typedef struct _DMA_PAGE
+{
+ UCHAR Reserved1;
+ UCHAR Channel2;
+ UCHAR Channel3;
+ UCHAR Channel1;
+ UCHAR Reserved2[3];
+ UCHAR Channel0;
+ UCHAR Reserved3;
+ UCHAR Channel6;
+ UCHAR Channel7;
+ UCHAR Channel5;
+ UCHAR Reserved4[3];
+ UCHAR Channel4;
+} DMA_PAGE, *PDMA_PAGE;
+
+/*
+ * DMA Channel Mask Register Structure
+ *
+ * MSB LSB
+ * x x x x x x x x
+ * ------------------- - -----
+ * | | | 00 - Select channel 0 mask bit
+ * | | \---- 01 - Select channel 1 mask bit
+ * | | 10 - Select channel 2 mask bit
+ * | | 11 - Select channel 3 mask bit
+ * | |
+ * | \---------- 0 - Clear mask bit
+ * | 1 - Set mask bit
+ * |
+ * \----------------------- xx - Reserved
+ */
+
+typedef struct _DMA_CHANNEL_MASK
+{
+ UCHAR Channel: 2;
+ UCHAR SetMask: 1;
+ UCHAR Reserved: 5;
+} DMA_CHANNEL_MASK, *PDMA_CHANNEL_MASK;
+
+/*
+ * DMA Mask Register Structure
+ *
+ * MSB LSB
+ * x x x x x x x x
+ * \---/ - - ----- -----
+ * | | | | | 00 - Channel 0 select
+ * | | | | \---- 01 - Channel 1 select
+ * | | | | 10 - Channel 2 select
+ * | | | | 11 - Channel 3 select
+ * | | | |
+ * | | | | 00 - Verify transfer
+ * | | | \------------ 01 - Write transfer
+ * | | | 10 - Read transfer
+ * | | |
+ * | | \-------------------- 0 - Autoinitialized
+ * | | 1 - Non-autoinitialized
+ * | |
+ * | \------------------------ 0 - Address increment select
+ * |
+ * | 00 - Demand mode
+ * \------------------------------ 01 - Single mode
+ * 10 - Block mode
+ * 11 - Cascade mode
+ */
+
+typedef union _DMA_MODE
+{
+ struct
+ {
+ UCHAR Channel: 2;
+ UCHAR TransferType: 2;
+ UCHAR AutoInitialize: 1;
+ UCHAR AddressDecrement: 1;
+ UCHAR RequestMode: 2;
+ };
+ UCHAR Byte;
+} DMA_MODE, *PDMA_MODE;
+
+/*
+ * DMA Extended Mode Register Structure
+ *
+ * MSB LSB
+ * x x x x x x x x
+ * - - ----- ----- -----
+ * | | | | | 00 - Channel 0 select
+ * | | | | \---- 01 - Channel 1 select
+ * | | | | 10 - Channel 2 select
+ * | | | | 11 - Channel 3 select
+ * | | | |
+ * | | | | 00 - 8-bit I/O, by bytes
+ * | | | \------------ 01 - 16-bit I/O, by words, address shifted
+ * | | | 10 - 32-bit I/O, by bytes
+ * | | | 11 - 16-bit I/O, by bytes
+ * | | |
+ * | | \---------------------- 00 - Compatible
+ * | | 01 - Type A
+ * | | 10 - Type B
+ * | | 11 - Burst
+ * | |
+ * | \---------------------------- 0 - Terminal Count is Output
+ * |
+ * \---------------------------------0 - Disable Stop Register
+ * 1 - Enable Stop Register
+ */
+
+typedef union _DMA_EXTENDED_MODE
+{
+ struct
+ {
+ UCHAR ChannelNumber: 2;
+ UCHAR TransferSize: 2;
+ UCHAR TimingMode: 2;
+ UCHAR TerminalCountIsOutput: 1;
+ UCHAR EnableStopRegister: 1;
+ };
+ UCHAR Byte;
+} DMA_EXTENDED_MODE, *PDMA_EXTENDED_MODE;
+
+/* DMA Extended Mode Register Transfer Sizes */
+#define B_8BITS 0
+#define W_16BITS 1
+#define B_32BITS 2
+#define B_16BITS 3
+
+/* DMA Extended Mode Register Timing */
+#define COMPATIBLE_TIMING 0
+#define TYPE_A_TIMING 1
+#define TYPE_B_TIMING 2
+#define BURST_TIMING 3
+
+/* Channel Stop Registers for each Channel */
+typedef struct _DMA_CHANNEL_STOP
+{
+ UCHAR ChannelLow;
+ UCHAR ChannelMid;
+ UCHAR ChannelHigh;
+ UCHAR Reserved;
+} DMA_CHANNEL_STOP, *PDMA_CHANNEL_STOP;
+
+/* Transfer Types */
+#define VERIFY_TRANSFER 0x00
+#define READ_TRANSFER 0x01
+#define WRITE_TRANSFER 0x02
+
+/* Request Modes */
+#define DEMAND_REQUEST_MODE 0x00
+#define SINGLE_REQUEST_MODE 0x01
+#define BLOCK_REQUEST_MODE 0x02
+#define CASCADE_REQUEST_MODE 0x03
+
+#define DMA_SETMASK 4
+#define DMA_CLEARMASK 0
+#define DMA_READ 4
+#define DMA_WRITE 8
+#define DMA_SINGLE_TRANSFER 0x40
+#define DMA_AUTO_INIT 0x10
+
+typedef struct _DMA1_ADDRESS_COUNT
+{
+ UCHAR DmaBaseAddress;
+ UCHAR DmaBaseCount;
+} DMA1_ADDRESS_COUNT, *PDMA1_ADDRESS_COUNT;
+
+typedef struct _DMA2_ADDRESS_COUNT
+{
+ UCHAR DmaBaseAddress;
+ UCHAR Reserved1;
+ UCHAR DmaBaseCount;
+ UCHAR Reserved2;
+} DMA2_ADDRESS_COUNT, *PDMA2_ADDRESS_COUNT;
+
+typedef struct _DMA1_CONTROL
+{
+ DMA1_ADDRESS_COUNT DmaAddressCount[4];
+ UCHAR DmaStatus;
+ UCHAR DmaRequest;
+ UCHAR SingleMask;
+ UCHAR Mode;
+ UCHAR ClearBytePointer;
+ UCHAR MasterClear;
+ UCHAR ClearMask;
+ UCHAR AllMask;
+} DMA1_CONTROL, *PDMA1_CONTROL;
+
+typedef struct _DMA2_CONTROL
+{
+ DMA2_ADDRESS_COUNT DmaAddressCount[4];
+ UCHAR DmaStatus;
+ UCHAR Reserved1;
+ UCHAR DmaRequest;
+ UCHAR Reserved2;
+ UCHAR SingleMask;
+ UCHAR Reserved3;
+ UCHAR Mode;
+ UCHAR Reserved4;
+ UCHAR ClearBytePointer;
+ UCHAR Reserved5;
+ UCHAR MasterClear;
+ UCHAR Reserved6;
+ UCHAR ClearMask;
+ UCHAR Reserved7;
+ UCHAR AllMask;
+ UCHAR Reserved8;
+} DMA2_CONTROL, *PDMA2_CONTROL;
+
+/* This structure defines the I/O Map of the 82537 controller. */
+typedef struct _EISA_CONTROL
+{
+ /* DMA Controller 1 */
+ DMA1_CONTROL DmaController1; /* 00h-0Fh */
+ UCHAR Reserved1[16]; /* 0Fh-1Fh */
+
+ /* Interrupt Controller 1 (PIC) */
+ UCHAR Pic1Operation; /* 20h */
+ UCHAR Pic1Interrupt; /* 21h */
+ UCHAR Reserved2[30]; /* 22h-3Fh */
+
+ /* Timer */
+ UCHAR TimerCounter; /* 40h */
+ UCHAR TimerMemoryRefresh; /* 41h */
+ UCHAR Speaker; /* 42h */
+ UCHAR TimerOperation; /* 43h */
+ UCHAR TimerMisc; /* 44h */
+ UCHAR Reserved3[2]; /* 45-46h */
+ UCHAR TimerCounterControl; /* 47h */
+ UCHAR TimerFailSafeCounter; /* 48h */
+ UCHAR Reserved4; /* 49h */
+ UCHAR TimerCounter2; /* 4Ah */
+ UCHAR TimerOperation2; /* 4Bh */
+ UCHAR Reserved5[20]; /* 4Ch-5Fh */
+
+ /* NMI / Keyboard / RTC */
+ UCHAR Keyboard; /* 60h */
+ UCHAR NmiStatus; /* 61h */
+ UCHAR Reserved6[14]; /* 62h-6Fh */
+ UCHAR NmiEnable; /* 70h */
+ UCHAR Reserved7[15]; /* 71h-7Fh */
+
+ /* DMA Page Registers Controller 1 */
+ DMA_PAGE DmaController1Pages; /* 80h-8Fh */
+ UCHAR Reserved8[16]; /* 90h-9Fh */
+
+ /* Interrupt Controller 2 (PIC) */
+ UCHAR Pic2Operation; /* 0A0h */
+ UCHAR Pic2Interrupt; /* 0A1h */
+ UCHAR Reserved9[30]; /* 0A2h-0BFh */
+
+ /* DMA Controller 2 */
+ DMA1_CONTROL DmaController2; /* 0C0h-0CFh */
+
+ /* System Reserved Ports */
+ UCHAR SystemReserved[816]; /* 0D0h-3FFh */
+
+ /* Extended DMA Registers, Controller 1 */
+ UCHAR DmaHighByteCount1[8]; /* 400h-407h */
+ UCHAR Reserved10[2]; /* 408h-409h */
+ UCHAR DmaChainMode1; /* 40Ah */
+ UCHAR DmaExtendedMode1; /* 40Bh */
+ UCHAR DmaBufferControl; /* 40Ch */
+ UCHAR Reserved11[84]; /* 40Dh-460h */
+ UCHAR ExtendedNmiControl; /* 461h */
+ UCHAR NmiCommand; /* 462h */
+ UCHAR Reserved12; /* 463h */
+ UCHAR BusMaster; /* 464h */
+ UCHAR Reserved13[27]; /* 465h-47Fh */
+
+ /* DMA Page Registers Controller 2 */
+ DMA_PAGE DmaController2Pages; /* 480h-48Fh */
+ UCHAR Reserved14[48]; /* 490h-4BFh */
+
+ /* Extended DMA Registers, Controller 2 */
+ UCHAR DmaHighByteCount2[16]; /* 4C0h-4CFh */
+
+ /* Edge/Level Control Registers */
+ UCHAR Pic1EdgeLevel; /* 4D0h */
+ UCHAR Pic2EdgeLevel; /* 4D1h */
+ UCHAR Reserved15[2]; /* 4D2h-4D3h */
+
+ /* Extended DMA Registers, Controller 2 */
+ UCHAR DmaChainMode2; /* 4D4h */
+ UCHAR Reserved16; /* 4D5h */
+ UCHAR DmaExtendedMode2; /* 4D6h */
+ UCHAR Reserved17[9]; /* 4D7h-4DFh */
+
+ /* DMA Stop Registers */
+ DMA_CHANNEL_STOP DmaChannelStop[8]; /* 4E0h-4FFh */
+} EISA_CONTROL, *PEISA_CONTROL;
+
+typedef struct _ROS_MAP_REGISTER_ENTRY
+{
+ PVOID VirtualAddress;
+ PHYSICAL_ADDRESS PhysicalAddress;
+ ULONG Counter;
+} ROS_MAP_REGISTER_ENTRY, *PROS_MAP_REGISTER_ENTRY;
+
+struct _ADAPTER_OBJECT {
+ /*
+ * New style DMA object definition. The fact that it is at the beginning
+ * of the ADAPTER_OBJECT structure allows us to easily implement the
+ * fallback implementation of IoGetDmaAdapter.
+ */
+ DMA_ADAPTER DmaHeader;
+
+ /*
+ * For normal adapter objects pointer to master adapter that takes care
+ * of channel allocation. For master adapter set to NULL.
+ */
+ struct _ADAPTER_OBJECT *MasterAdapter;
+
+ ULONG MapRegistersPerChannel;
+ PVOID AdapterBaseVa;
+ PROS_MAP_REGISTER_ENTRY MapRegisterBase;
+
+ ULONG NumberOfMapRegisters;
+ ULONG CommittedMapRegisters;
+
+ PWAIT_CONTEXT_BLOCK CurrentWcb;
+ KDEVICE_QUEUE ChannelWaitQueue;
+ PKDEVICE_QUEUE RegisterWaitQueue;
+ LIST_ENTRY AdapterQueue;
+ KSPIN_LOCK SpinLock;
+ PRTL_BITMAP MapRegisters;
+ PUCHAR PagePort;
+ UCHAR ChannelNumber;
+ UCHAR AdapterNumber;
+ USHORT DmaPortAddress;
+ DMA_MODE AdapterMode;
+ BOOLEAN NeedsMapRegisters;
+ BOOLEAN MasterDevice;
+ BOOLEAN Width16Bits;
+ BOOLEAN ScatterGather;
+ BOOLEAN IgnoreCount;
+ BOOLEAN Dma32BitAddresses;
+ BOOLEAN Dma64BitAddresses;
+ LIST_ENTRY AdapterList;
+} ADAPTER_OBJECT;
+
+typedef struct _GROW_WORK_ITEM {
+ WORK_QUEUE_ITEM WorkQueueItem;
+ PADAPTER_OBJECT AdapterObject;
+ ULONG NumberOfMapRegisters;
+} GROW_WORK_ITEM, *PGROW_WORK_ITEM;
+
+#define MAP_BASE_SW_SG 1
+
+PADAPTER_OBJECT STDCALL
+HalpDmaAllocateMasterAdapter(VOID);
+
+PDMA_ADAPTER STDCALL
+HalpGetDmaAdapter(
+ IN PVOID Context,
+ IN PDEVICE_DESCRIPTION DeviceDescription,
+ OUT PULONG NumberOfMapRegisters);
+
+ULONG STDCALL
+HalpDmaGetDmaAlignment(
+ PADAPTER_OBJECT AdapterObject);
+
+#endif /* HALDMA_H */
diff --git a/reactos/hal/halppc/include/halirq.h b/reactos/hal/halppc/include/halirq.h
new file mode 100644
index 00000000000..6d072738f5f
--- /dev/null
+++ b/reactos/hal/halppc/include/halirq.h
@@ -0,0 +1,35 @@
+/*
+ * $Id: halirq.h 23907 2006-09-04 05:52:23Z arty $
+ */
+
+#ifndef __INCLUDE_HAL_HALIRQ
+#define __INCLUDE_HAL_HALIRQ
+
+#ifdef CONFIG_SMP
+
+#define FIRST_DEVICE_VECTOR (0x30)
+#define FIRST_SYSTEM_VECTOR (0xef)
+
+#define IRQ_BASE FIRST_DEVICE_VECTOR
+#define NR_IRQS (FIRST_SYSTEM_VECTOR - FIRST_DEVICE_VECTOR)
+
+/*
+ * FIXME:
+ * This does not work if we have more than 24 IRQs (ie. more than one I/O APIC)
+ */
+#define VECTOR2IRQ(vector) (23 - (vector - IRQ_BASE) / 8)
+#define VECTOR2IRQL(vector) (PROFILE_LEVEL - VECTOR2IRQ(vector))
+#define IRQ2VECTOR(irq) (((23 - (irq)) * 8) + FIRST_DEVICE_VECTOR)
+
+#else
+
+#define IRQ_BASE (0x30)
+#define NR_IRQS (16)
+
+#define VECTOR2IRQ(vector) ((vector) - IRQ_BASE)
+#define VECTOR2IRQL(vector) (PROFILE_LEVEL - VECTOR2IRQ(vector))
+#define IRQ2VECTOR(irq) ((irq) + IRQ_BASE)
+
+#endif
+
+#endif /* __INCLUDE_HAL_HALIRQ */
diff --git a/reactos/hal/halppc/include/halp.h b/reactos/hal/halppc/include/halp.h
new file mode 100644
index 00000000000..88f607e699d
--- /dev/null
+++ b/reactos/hal/halppc/include/halp.h
@@ -0,0 +1,97 @@
+/*
+ *
+ */
+
+#ifndef __INTERNAL_HAL_HAL_H
+#define __INTERNAL_HAL_HAL_H
+
+#define HAL_APC_REQUEST 0
+#define HAL_DPC_REQUEST 1
+
+//
+// Kernel Debugger Port Definition
+//
+typedef struct _KD_PORT_INFORMATION
+{
+ ULONG ComPort;
+ ULONG BaudRate;
+ ULONG BaseAddress;
+} KD_PORT_INFORMATION, *PKD_PORT_INFORMATION;
+
+/* display.c */
+VOID FASTCALL HalInitializeDisplay (struct _ROS_LOADER_PARAMETER_BLOCK *LoaderBlock);
+VOID FASTCALL HalClearDisplay (UCHAR CharAttribute);
+
+/* adapter.c */
+PADAPTER_OBJECT STDCALL HalpAllocateAdapterEx(ULONG NumberOfMapRegisters,BOOLEAN IsMaster, BOOLEAN Dma32BitAddresses);
+
+/* bus.c */
+VOID HalpInitBusHandlers (VOID);
+
+/* irql.c */
+VOID NTAPI HalpInitPICs(VOID);
+
+/* udelay.c */
+VOID HalpCalibrateStallExecution(VOID);
+
+/* pci.c */
+VOID HalpInitPciBus (VOID);
+
+/* enum.c */
+VOID HalpStartEnumerator (VOID);
+
+/* dma.c */
+VOID HalpInitDma (VOID);
+
+/* mem.c */
+PVOID HalpMapPhysMemory(ULONG PhysAddr, ULONG Size);
+
+/* Non-generic initialization */
+VOID HalpInitPhase0 (PROS_LOADER_PARAMETER_BLOCK LoaderBlock);
+VOID HalpInitPhase1(VOID);
+VOID NTAPI HalpClockInterrupt(VOID);
+
+/* sysinfo.c */
+NTSTATUS STDCALL
+HalpQuerySystemInformation(IN HAL_QUERY_INFORMATION_CLASS InformationClass,
+ IN ULONG BufferSize,
+ IN OUT PVOID Buffer,
+ OUT PULONG ReturnedLength);
+
+/* Non-standard functions */
+VOID STDCALL
+HalReleaseDisplayOwnership();
+
+BOOLEAN STDCALL
+HalQueryDisplayOwnership();
+
+#if defined(__GNUC__)
+#define Ki386SaveFlags(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
+#define Ki386RestoreFlags(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
+#define Ki386DisableInterrupts() __asm__ __volatile__("cli\n\t")
+#define Ki386EnableInterrupts() __asm__ __volatile__("sti\n\t")
+#define Ki386HaltProcessor() __asm__ __volatile__("hlt\n\t")
+#define Ki386RdTSC(x) __asm__ __volatile__("rdtsc\n\t" : "=A" (x.u.LowPart), "=d" (x.u.HighPart))
+#define Ki386Rdmsr(msr,val1,val2) __asm__ __volatile__("rdmsr" : "=a" (val1), "=d" (val2) : "c" (msr))
+#define Ki386Wrmsr(msr,val1,val2) __asm__ __volatile__("wrmsr" : /* no outputs */ : "c" (msr), "a" (val1), "d" (val2))
+#define Ki386ReadFsByte(offset,x) __asm__ __volatile__("movb %%fs:%c1,%0" : "=q" (x) : "i" (offset))
+#define Ki386WriteFsByte(offset,x) __asm__ __volatile__("movb %0,%%fs:%c1" : : "q" ((UCHAR)x), "i" (offset))
+
+#elif defined(_MSC_VER)
+#define Ki386SaveFlags(x) __asm pushfd __asm pop x;
+#define Ki386RestoreFlags(x) __asm push x __asm popfd;
+#define Ki386DisableInterrupts() __asm cli
+#define Ki386EnableInterrupts() __asm sti
+#define Ki386HaltProcessor() __asm hlt
+#else
+#error Unknown compiler for inline assembler
+#endif
+
+typedef struct tagHALP_HOOKS
+{
+ void (*InitPciBus)(ULONG BusNumber, PBUS_HANDLER BusHandler);
+} HALP_HOOKS, *PHALP_HOOKS;
+
+extern HALP_HOOKS HalpHooks;
+
+#endif /* __INTERNAL_HAL_HAL_H */
diff --git a/reactos/hal/halppc/include/ioapic.h b/reactos/hal/halppc/include/ioapic.h
new file mode 100644
index 00000000000..114853c4a6d
--- /dev/null
+++ b/reactos/hal/halppc/include/ioapic.h
@@ -0,0 +1,103 @@
+/*
+ *
+ */
+
+#ifndef __INTERNAL_HAL_IOAPIC_H
+#define __INTERNAL_HAL_IOAPIC_H
+
+/* I/O APIC Register Address Map */
+#define IOAPIC_IOREGSEL 0x0000 /* I/O Register Select (index) (R/W) */
+#define IOAPIC_IOWIN 0x0010 /* I/O window (data) (R/W) */
+
+#define IOAPIC_ID 0x0000 /* IO APIC ID (R/W) */
+#define IOAPIC_VER 0x0001 /* IO APIC Version (R) */
+#define IOAPIC_ARB 0x0002 /* IO APIC Arbitration ID (R) */
+#define IOAPIC_REDTBL 0x0010 /* Redirection Table (0-23 64-bit registers) (R/W) */
+
+#define IOAPIC_ID_MASK (0xF << 24)
+#define GET_IOAPIC_ID(x) (((x) & IOAPIC_ID_MASK) >> 24)
+#define SET_IOAPIC_ID(x) ((x) << 24)
+
+#define IOAPIC_VER_MASK (0xFF)
+#define GET_IOAPIC_VERSION(x) (((x) & IOAPIC_VER_MASK))
+#define IOAPIC_MRE_MASK (0xFF << 16) /* Maximum Redirection Entry */
+#define GET_IOAPIC_MRE(x) (((x) & IOAPIC_MRE_MASK) >> 16)
+
+#define IOAPIC_ARB_MASK (0xF << 24)
+#define GET_IOAPIC_ARB(x) (((x) & IOAPIC_ARB_MASK) >> 24)
+
+#define IOAPIC_TBL_DELMOD (0x7 << 10) /* Delivery Mode (see APIC_DM_*) */
+#define IOAPIC_TBL_DM (0x1 << 11) /* Destination Mode */
+#define IOAPIC_TBL_DS (0x1 << 12) /* Delivery Status */
+#define IOAPIC_TBL_INTPOL (0x1 << 13) /* Interrupt Input Pin Polarity */
+#define IOAPIC_TBL_RIRR (0x1 << 14) /* Remote IRR */
+#define IOAPIC_TBL_TM (0x1 << 15) /* Trigger Mode */
+#define IOAPIC_TBL_IM (0x1 << 16) /* Interrupt Mask */
+#define IOAPIC_TBL_DF0 (0xF << 56) /* Destination Field (physical mode) */
+#define IOAPIC_TBL_DF1 (0xFF<< 56) /* Destination Field (logical mode) */
+#define IOAPIC_TBL_VECTOR (0xFF << 0) /* Vector (10h - FEh) */
+
+#include
+typedef struct _IOAPIC_ROUTE_ENTRY {
+ ULONG vector : 8,
+ delivery_mode : 3, /* 000: FIXED
+ * 001: lowest priority
+ * 111: ExtINT
+ */
+ dest_mode : 1, /* 0: physical, 1: logical */
+ delivery_status : 1,
+ polarity : 1,
+ irr : 1,
+ trigger : 1, /* 0: edge, 1: level */
+ mask : 1, /* 0: enabled, 1: disabled */
+ __reserved_2 : 15;
+
+ union {
+ struct {
+ ULONG __reserved_1 : 24,
+ physical_dest : 4,
+ __reserved_2 : 4;
+ } physical;
+ struct {
+ ULONG __reserved_1 : 24,
+ logical_dest : 8;
+ } logical;
+ } dest;
+} IOAPIC_ROUTE_ENTRY, *PIOAPIC_ROUTE_ENTRY;
+#include
+
+typedef struct _IOAPIC_INFO
+{
+ ULONG ApicId; /* APIC ID */
+ ULONG ApicVersion; /* APIC version */
+ ULONG ApicAddress; /* APIC address */
+ ULONG EntryCount; /* Number of redirection entries */
+} IOAPIC_INFO, *PIOAPIC_INFO;
+
+#define IOAPIC_DEFAULT_BASE 0xFEC00000 /* Default I/O APIC Base Register Address */
+
+extern ULONG IRQCount; /* Number of IRQs */
+extern UCHAR BUSMap[MAX_BUS]; /* Map of all buses in the system */
+extern UCHAR PCIBUSMap[MAX_BUS]; /* Map of all PCI buses in the system */
+extern IOAPIC_INFO IOAPICMap[MAX_IOAPIC]; /* Map of all I/O APICs in the system */
+extern ULONG IOAPICCount; /* Number of I/O APICs in the system */
+extern ULONG APICMode; /* APIC mode at startup */
+extern MP_CONFIGURATION_INTSRC IRQMap[MAX_IRQ_SOURCE]; /* Map of all IRQs */
+
+VOID IOAPICSetupIrqs(VOID);
+VOID IOAPICEnable(VOID);
+VOID IOAPICSetupIds(VOID);
+VOID IOAPICMaskIrq(ULONG Irq);
+VOID IOAPICUnmaskIrq(ULONG Irq);
+
+VOID HaliReconfigurePciInterrupts(VOID);
+
+/* For debugging */
+VOID IOAPICDump(VOID);
+
+#endif
+
+
+
+/* EOF */
+
diff --git a/reactos/hal/halppc/include/mps.h b/reactos/hal/halppc/include/mps.h
new file mode 100644
index 00000000000..83f9cfbe501
--- /dev/null
+++ b/reactos/hal/halppc/include/mps.h
@@ -0,0 +1,204 @@
+#ifndef __INCLUDE_HAL_MPS
+#define __INCLUDE_HAL_MPS
+
+/*
+ * FIXME: This does not work if we have more than 24 IRQs (ie. more than one
+ * I/O APIC)
+ */
+#define IRQL2VECTOR(irql) (IRQ2VECTOR(PROFILE_LEVEL - (irql)))
+
+#define IRQL2TPR(irql) ((irql) >= IPI_LEVEL ? IPI_VECTOR : ((irql) >= PROFILE_LEVEL ? LOCAL_TIMER_VECTOR : ((irql) > DISPATCH_LEVEL ? IRQL2VECTOR(irql) : 0)))
+
+typedef struct _KIRQ_TRAPFRAME
+{
+ ULONG Magic;
+ ULONG Gs;
+ ULONG Fs;
+ ULONG Es;
+ ULONG Ds;
+ ULONG Eax;
+ ULONG Ecx;
+ ULONG Edx;
+ ULONG Ebx;
+ ULONG Esp;
+ ULONG Ebp;
+ ULONG Esi;
+ ULONG Edi;
+ ULONG Eip;
+ ULONG Cs;
+ ULONG Eflags;
+} KIRQ_TRAPFRAME, *PKIRQ_TRAPFRAME;
+
+#if 0
+/* This values are defined in halirql.h */
+#define FIRST_DEVICE_VECTOR 0x30
+#define FIRST_SYSTEM_VECTOR 0xEF
+#endif
+
+#define NUMBER_DEVICE_VECTORS (FIRST_SYSTEM_VECTOR - FIRST_DEVICE_VECTOR)
+
+
+/* MP Floating Pointer Structure */
+#define MPF_SIGNATURE (('_' << 24) | ('P' << 16) | ('M' << 8) | '_')
+
+#include
+typedef struct _MP_FLOATING_POINTER
+{
+ ULONG Signature; /* _MP_ */
+ ULONG Address; /* Physical Address Pointer (0 means no configuration table exist) */
+ UCHAR Length; /* Structure length in 16-byte paragraphs */
+ UCHAR Specification; /* Specification revision */
+ UCHAR Checksum; /* Checksum */
+ UCHAR Feature1; /* MP System Configuration Type */
+ UCHAR Feature2; /* Bit 7 set for IMCR|PIC */
+ UCHAR Feature3; /* Unused (0) */
+ UCHAR Feature4; /* Unused (0) */
+ UCHAR Feature5; /* Unused (0) */
+} MP_FLOATING_POINTER, *PMP_FLOATING_POINTER;
+
+
+#define FEATURE2_IMCRP 0x80
+
+/* MP Configuration Table Header */
+#define MPC_SIGNATURE (('P' << 24) | ('M' << 16) | ('C' << 8) | 'P')
+
+typedef struct _MP_CONFIGURATION_TABLE
+{
+ ULONG Signature; /* PCMP */
+ USHORT Length; /* Size of configuration table */
+ CHAR Specification; /* Specification Revision */
+ CHAR Checksum; /* Checksum */
+ CHAR Oem[8]; /* OEM ID */
+ CHAR ProductId[12]; /* Product ID */
+ ULONG OemTable; /* 0 if not present */
+ USHORT OemTableSize; /* 0 if not present */
+ USHORT EntryCount; /* Number of entries */
+ ULONG LocalAPICAddress; /* Local APIC address */
+ USHORT ExtTableLength; /* Extended Table Length */
+ UCHAR ExtTableChecksum; /* Extended Table Checksum */
+ UCHAR Reserved; /* Reserved */
+} MP_CONFIGURATION_TABLE, *PMP_CONFIGURATION_TABLE;
+
+/* MP Configuration Table Entries */
+#define MPCTE_PROCESSOR 0 /* One entry per processor */
+#define MPCTE_BUS 1 /* One entry per bus */
+#define MPCTE_IOAPIC 2 /* One entry per I/O APIC */
+#define MPCTE_INTSRC 3 /* One entry per bus interrupt source */
+#define MPCTE_LINTSRC 4 /* One entry per system interrupt source */
+
+
+typedef struct _MP_CONFIGURATION_PROCESSOR
+{
+ UCHAR Type; /* 0 */
+ UCHAR ApicId; /* Local APIC ID for the processor */
+ UCHAR ApicVersion; /* Local APIC version */
+ UCHAR CpuFlags; /* CPU flags */
+ ULONG CpuSignature; /* CPU signature */
+ ULONG FeatureFlags; /* CPUID feature value */
+ ULONG Reserved[2]; /* Reserved (0) */
+} MP_CONFIGURATION_PROCESSOR, *PMP_CONFIGURATION_PROCESSOR;
+
+
+
+typedef struct _MP_CONFIGURATION_BUS
+{
+ UCHAR Type; /* 1 */
+ UCHAR BusId; /* Bus ID */
+ CHAR BusType[6]; /* Bus type */
+} MP_CONFIGURATION_BUS, *PMP_CONFIGURATION_BUS;
+
+#define MAX_BUS 32
+
+#define MP_BUS_ISA 1
+#define MP_BUS_EISA 2
+#define MP_BUS_PCI 3
+#define MP_BUS_MCA 4
+
+#define BUSTYPE_EISA "EISA"
+#define BUSTYPE_ISA "ISA"
+#define BUSTYPE_INTERN "INTERN" /* Internal BUS */
+#define BUSTYPE_MCA "MCA"
+#define BUSTYPE_VL "VL" /* Local bus */
+#define BUSTYPE_PCI "PCI"
+#define BUSTYPE_PCMCIA "PCMCIA"
+#define BUSTYPE_CBUS "CBUS"
+#define BUSTYPE_CBUSII "CBUSII"
+#define BUSTYPE_FUTURE "FUTURE"
+#define BUSTYPE_MBI "MBI"
+#define BUSTYPE_MBII "MBII"
+#define BUSTYPE_MPI "MPI"
+#define BUSTYPE_MPSA "MPSA"
+#define BUSTYPE_NUBUS "NUBUS"
+#define BUSTYPE_TC "TC"
+#define BUSTYPE_VME "VME"
+#define BUSTYPE_XPRESS "XPRESS"
+
+
+typedef struct _MP_CONFIGURATION_IOAPIC
+{
+ UCHAR Type; /* 2 */
+ UCHAR ApicId; /* I/O APIC ID */
+ UCHAR ApicVersion; /* I/O APIC version */
+ UCHAR ApicFlags; /* I/O APIC flags */
+ ULONG ApicAddress; /* I/O APIC base address */
+} MP_CONFIGURATION_IOAPIC, *PMP_CONFIGURATION_IOAPIC;
+
+#define MAX_IOAPIC 2
+
+#define MP_IOAPIC_USABLE 0x01
+
+
+typedef struct _MP_CONFIGURATION_INTSRC
+{
+ UCHAR Type; /* 3 */
+ UCHAR IrqType; /* Interrupt type */
+ USHORT IrqFlag; /* Interrupt flags */
+ UCHAR SrcBusId; /* Source bus ID */
+ UCHAR SrcBusIrq; /* Source bus interrupt */
+ UCHAR DstApicId; /* Destination APIC ID */
+ UCHAR DstApicInt; /* Destination interrupt */
+} MP_CONFIGURATION_INTSRC, *PMP_CONFIGURATION_INTSRC;
+
+#define MAX_IRQ_SOURCE 128
+
+#define INT_VECTORED 0
+#define INT_NMI 1
+#define INT_SMI 2
+#define INT_EXTINT 3
+
+#define IRQDIR_DEFAULT 0
+#define IRQDIR_HIGH 1
+#define IRQDIR_LOW 3
+
+
+typedef struct _MP_CONFIGURATION_INTLOCAL
+{
+ UCHAR Type; /* 4 */
+ UCHAR IrqType; /* Interrupt type */
+ USHORT IrqFlag; /* Interrupt flags */
+ UCHAR SrcBusId; /* Source bus ID */
+ UCHAR SrcBusIrq; /* Source bus interrupt */
+ UCHAR DstApicId; /* Destination local APIC ID */
+ UCHAR DstApicLInt; /* Destination local APIC interrupt */
+} MP_CONFIGURATION_INTLOCAL, *PMP_CONFIGURATION_INTLOCAL;
+#include
+
+#define MP_APIC_ALL 0xFF
+
+#define CPU_FLAG_ENABLED 1 /* Processor is available */
+#define CPU_FLAG_BSP 2 /* Processor is the bootstrap processor */
+
+#define CPU_STEPPING_MASK 0x0F
+#define CPU_MODEL_MASK 0xF0
+#define CPU_FAMILY_MASK 0xF00
+
+#define PIC_IRQS 16
+
+/* Prototypes */
+
+VOID HalpInitMPS(VOID);
+
+
+#endif /* __INCLUDE_HAL_MPS */
+
+/* EOF */
diff --git a/reactos/hal/halppc/up/halinit_up.c b/reactos/hal/halppc/up/halinit_up.c
new file mode 100644
index 00000000000..38851c9dacf
--- /dev/null
+++ b/reactos/hal/halppc/up/halinit_up.c
@@ -0,0 +1,35 @@
+/* $Id: halinit_up.c 23907 2006-09-04 05:52:23Z arty $
+ *
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS kernel
+ * FILE: ntoskrnl/hal/x86/halinit.c
+ * PURPOSE: Initalize the x86 hal
+ * PROGRAMMER: David Welch (welch@cwcom.net)
+ * UPDATE HISTORY:
+ * 11/06/98: Created
+ */
+
+/* INCLUDES *****************************************************************/
+
+#include
+#define NDEBUG
+#include
+
+/* FUNCTIONS ***************************************************************/
+
+VOID
+HalpInitPhase0(PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ HalpInitPICs();
+
+ /* Setup busy waiting */
+ HalpCalibrateStallExecution();
+}
+
+VOID
+HalpInitPhase1(VOID)
+{
+ /* Nothing for now */
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/up/halup.rbuild b/reactos/hal/halppc/up/halup.rbuild
new file mode 100644
index 00000000000..0ba1b0888a8
--- /dev/null
+++ b/reactos/hal/halppc/up/halup.rbuild
@@ -0,0 +1,12 @@
+
+
+
+ ../include
+ include
+
+
+
+ halppc_generic
+ halinit_up.c
+ halup.rc
+
diff --git a/reactos/hal/halppc/up/halup.rc b/reactos/hal/halppc/up/halup.rc
new file mode 100644
index 00000000000..90af6b929ff
--- /dev/null
+++ b/reactos/hal/halppc/up/halup.rc
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION "X86 Uniprocessor Hardware Abstraction Layer\0"
+#define REACTOS_STR_INTERNAL_NAME "halup\0"
+#define REACTOS_STR_ORIGINAL_FILENAME "halup.dll\0"
+#include