[HAL]
authorTimo Kreuzer <timo.kreuzer@reactos.org>
Fri, 26 Mar 2010 00:21:45 +0000 (00:21 +0000)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Fri, 26 Mar 2010 00:21:45 +0000 (00:21 +0000)
Add some files for amd64, just enough to make compilation start.

svn path=/trunk/; revision=46455

reactos/hal/halx86/generic/amd64/systimer.S [new file with mode: 0644]
reactos/hal/halx86/generic/amd64/x86bios.c [new file with mode: 0644]
reactos/hal/halx86/halamd64.rbuild
reactos/hal/halx86/mp/amd64/mps.S [new file with mode: 0644]

diff --git a/reactos/hal/halx86/generic/amd64/systimer.S b/reactos/hal/halx86/generic/amd64/systimer.S
new file mode 100644 (file)
index 0000000..1cb3b6e
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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 <reactos/asm.h>
+#include <ndk/amd64/asm.h>
+
+/* GLOBALS *******************************************************************/
+
+.data
+
+.global MsgUnimplemented
+MsgUnimplemented:
+.asciz "WARNING:  %s at %s:%d is UNIMPLEMENTED!\n"
+
+
+/* FUNCTIONS *****************************************************************/
+
+.text
+.code64
+
+PUBLIC HalpCalibrateStallExecution@0
+HalpCalibrateStallExecution@0:
+
+
+PUBLIC HalpProfileInterrupt
+HalpProfileInterrupt:
+
+
+PUBLIC KeStallExecutionProcessor
+KeStallExecutionProcessor:
+
+    /* Get the number of microseconds required */
+    jecxz Done
+
+    /* Multiply by the stall factor */
+    mov eax, gs:[KPCR_STALL_SCALE_FACTOR]
+    mul ecx
+
+    /* Align to 16 bytes */
+    .align 16
+
+    /* Jump to subtraction loop */
+    jmp SubtractLoop
+
+    /* Align to 16 bytes */
+    .align 16
+
+    /* Subtract one count */
+SubtractLoop:
+    sub eax, 1
+    jnz SubtractLoop
+
+Done:
+    /* Return */
+    ret 4
+
+
+PUBLIC HalpQuery8254Counter
+HalpQuery8254Counter:
+
+    /* Save EFLAGS and disable interrupts */
+    pushfq
+    cli
+
+    /* Set timer data */
+    mov al, 0
+    out 0x43, al
+    jmp $+2
+
+    /* Read current timer */
+    in al, 0x40
+    jmp $+2
+    movzx ecx, al
+    in al, 0x40
+    mov ch, al
+
+    /* Return it and restore interrupt state */
+    mov eax, ecx
+    popfq
+    ret
+
+PUBLIC HalpClockInterrupt
+HalpClockInterrupt:
+    UNIMPLEMENTED _HalpClockInterrupt
+    iret
+
diff --git a/reactos/hal/halx86/generic/amd64/x86bios.c b/reactos/hal/halx86/generic/amd64/x86bios.c
new file mode 100644 (file)
index 0000000..3b43bf1
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * PROJECT:         ReactOS HAL
+ * LICENSE:         GPL, See COPYING in the top level directory
+ * FILE:            hal/halx86/generic/amd64/x86bios.c
+ * PURPOSE:         
+ * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+//#define NDEBUG
+#include <debug.h>
+
+#include "x86emu.h"
+
+/* This page serves as fallback for pages used by Mm */
+#define DEFAULT_PAGE 0x21
+
+/* GLOBALS *******************************************************************/
+
+BOOLEAN x86BiosIsInitialized;
+LONG x86BiosBufferIsAllocated = 0;
+PUCHAR x86BiosMemoryMapping;
+
+
+VOID
+NTAPI
+DbgDumpPage(PUCHAR MemBuffer, USHORT Segment)
+{
+    ULONG x, y, Offset;
+
+    for (y = 0; y < 0x100; y++)
+    {
+        for (x = 0; x < 0x10; x++)
+        {
+            Offset = Segment * 16 + y * 16 + x;
+            DbgPrint("%02x ", MemBuffer[Offset]);
+        }
+        DbgPrint("\n");
+    }
+}
+
+VOID
+NTAPI
+HalInitializeBios(ULONG Unknown, PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+    PPFN_NUMBER PfnArray;
+    PFN_NUMBER Pfn, Last;
+    PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+    PLIST_ENTRY ListEntry;
+    PMDL Mdl;
+
+    /* Allocate an MDL for 1MB */
+    Mdl = IoAllocateMdl(NULL, 0x100000, FALSE, FALSE, NULL);
+    if (!Mdl)
+    {
+        ASSERT(FALSE);
+    }
+
+    /* Get pointer to the pfn array */
+    PfnArray = MmGetMdlPfnArray(Mdl);
+
+    /* Fill the array with low memory PFNs */
+    for (Pfn = 0; Pfn < 0x100; Pfn++)
+    {
+        PfnArray[Pfn] = Pfn;
+    }
+
+    /* Loop the memory descriptors */
+    for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+         ListEntry != &LoaderBlock->MemoryDescriptorListHead;
+         ListEntry = ListEntry->Flink)
+    {
+        /* Get the memory descriptor */
+        Descriptor = CONTAINING_RECORD(ListEntry,
+                                       MEMORY_ALLOCATION_DESCRIPTOR,
+                                       ListEntry);
+
+        /* Check if the memory is in the low range */
+        if (Descriptor->BasePage < 0x100)
+        {
+            /* Check if the memory type is firmware */
+            if (Descriptor->MemoryType != LoaderFirmwarePermanent &&
+                Descriptor->MemoryType != LoaderSpecialMemory)
+            {
+                /* It's something else, so don't use it! */
+                Last = min(Descriptor->BasePage + Descriptor->PageCount, 0x100);
+                for (Pfn = Descriptor->BasePage; Pfn < Last; Pfn++)
+                {
+                    /* Set each page to the default page */
+                    PfnArray[Pfn] = DEFAULT_PAGE;
+                }
+            }
+        }
+    }
+
+    Mdl->MdlFlags = MDL_PAGES_LOCKED;
+
+    /* Map the MDL to system space */
+    x86BiosMemoryMapping = MmGetSystemAddressForMdlSafe(Mdl, HighPagePriority);
+    ASSERT(x86BiosMemoryMapping);
+
+    DPRINT1("memory: %p, %p\n", *(PVOID*)x86BiosMemoryMapping, *(PVOID*)(x86BiosMemoryMapping + 8));
+    //DbgDumpPage(x86BiosMemoryMapping, 0xc351);
+
+    x86BiosIsInitialized = TRUE;
+    
+    HalpBiosDisplayReset();
+}
+
+NTSTATUS
+NTAPI
+x86BiosAllocateBuffer(
+    ULONG *Size,
+    USHORT *Segment,
+    USHORT *Offset)
+{
+    /* Check if the system is initialized and the buffer is large enough */
+    if (!x86BiosIsInitialized || *Size > PAGE_SIZE)
+    {
+        /* Something was wrong, fail! */
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* Check if the buffer is already allocated */
+    if (InterlockedBitTestAndSet(&x86BiosBufferIsAllocated, 0))
+    {
+        /* Buffer was already allocated, fail */
+        return STATUS_INSUFFICIENT_RESOURCES;
+    }
+
+    /* The buffer is sufficient, return hardcoded address and size */
+    *Size = PAGE_SIZE;
+    *Segment = 0x2000;
+    *Offset = 0;
+
+    return STATUS_SUCCESS;;
+}
+
+NTSTATUS
+NTAPI
+x86BiosFreeBuffer(
+    USHORT Segment,
+    USHORT Offset)
+{
+    /* Check if the system is initialized and if the address matches */
+    if (!x86BiosIsInitialized || Segment != 0x2000 || Offset != 0)
+    {
+        /* Something was wrong, fail */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Check if the buffer was allocated */
+    if (!InterlockedBitTestAndReset(&x86BiosBufferIsAllocated, 0))
+    {
+        /* It was not, fail */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Buffer is freed, nothing more to do */
+    return STATUS_SUCCESS;;
+}
+
+NTSTATUS
+NTAPI
+x86BiosReadMemory(
+    USHORT Segment,
+    USHORT Offset,
+    PVOID Buffer,
+    ULONG Size)
+{
+    ULONG_PTR Address;
+
+    /* Calculate the physical address */
+    Address = (Segment << 4) + Offset;
+
+    /* Check if it's valid */
+    if (!x86BiosIsInitialized || Address + Size > 0x100000)
+    {
+        /* Invalid */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Copy the memory to the buffer */
+    RtlCopyMemory(Buffer, x86BiosMemoryMapping + Address, Size);
+
+    /* Return success */
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+x86BiosWriteMemory(
+    USHORT Segment,
+    USHORT Offset,
+    PVOID Buffer,
+    ULONG Size)
+{
+    ULONG_PTR Address;
+
+    /* Calculate the physical address */
+    Address = (Segment << 4) + Offset;
+
+    /* Check if it's valid */
+    if (!x86BiosIsInitialized || Address + Size > 0x100000)
+    {
+        /* Invalid */
+        return STATUS_INVALID_PARAMETER;
+    }
+
+    /* Copy the memory from the buffer */
+    RtlCopyMemory(x86BiosMemoryMapping + Address, Buffer, Size);
+
+    /* Return success */
+    return STATUS_SUCCESS;
+}
+
+BOOLEAN
+NTAPI
+x86BiosCall(
+    ULONG InterruptNumber,
+    X86_BIOS_REGISTERS *Registers)
+{
+    X86_VM_STATE VmState;
+    struct
+    {
+        USHORT Ip;
+        USHORT SegCs;
+    } *InterrupTable;
+
+    /* Zero the VmState */
+    RtlZeroMemory(&VmState, sizeof(VmState));
+
+    /* Copy the registers */
+    VmState.BiosRegisters = *Registers;
+
+    /* Set the physical memory buffer */
+    VmState.MemBuffer = x86BiosMemoryMapping;
+
+    /* Set Eflags */
+    VmState.Registers.Eflags.Long = 0; // FIXME
+
+    /* Setup stack */
+    VmState.Registers.SegSs = 0; // FIXME
+    VmState.Registers.Sp = 0x2000 - 2; // FIXME
+
+    /* Initialize IP from the interrupt vector table */
+    InterrupTable = (PVOID)x86BiosMemoryMapping;
+    VmState.Registers.SegCs = InterrupTable[InterruptNumber].SegCs;
+    VmState.Registers.Eip = InterrupTable[InterruptNumber].Ip;
+    
+    /* Make the function return on IRET */
+    VmState.Flags.ReturnOnIret = 1;
+
+    /* Call the x86 emulator */
+    x86Emulator(&VmState);
+
+    /* Copy registers back to caller */
+    *Registers = VmState.BiosRegisters;
+
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+HalpBiosDisplayReset(VOID)
+{
+    X86_BIOS_REGISTERS Registers;
+    ULONG OldEflags;
+
+    /* Save flags and disable interrupts */
+    OldEflags = __readeflags();
+    _disable();
+
+    /* Set AH = 0 (Set video mode), AL = 0x12 (640x480x16 vga) */
+    Registers.Eax = 0x12;
+
+    /* Call INT 0x10 */
+    x86BiosCall(0x10, &Registers);
+
+    // FIXME: check result
+
+    /* Restore previous flags */
+    __writeeflags(OldEflags);
+
+    return TRUE;
+}
+
index 8b13789..4a09aa2 100644 (file)
@@ -1 +1,27 @@
+<?xml version="1.0"?>
+<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
+<group xmlns:xi="http://www.w3.org/2001/XInclude">
+<module name="hal" type="kernelmodedll" entrypoint="HalInitSystem" installbase="system32" installname="hal.dll">
+       <importlibrary base="hal" definition="../hal.pspec" />
+       <bootstrap installbase="$(CDOUTPUT)" nameoncd="hal.dll" />
+       <include base="hal">include</include>
+       <include base="ntoskrnl">include</include>
+       <!-- include base="x86emu">.</include -->
+       <define name="_DISABLE_TIDENTS" />
+       <define name="_NTHAL_" />
+       <define name="_X86BIOS_" />
+       <library>hal_generic</library>
+       <library>hal_generic_up</library>
+       <library>ntoskrnl</library>
+       <!-- library>x86emu</library -->
+
+       <directory name="mp">
+               <file>halinit_mp.c</file>
+               <file>halmp.rc</file>
+               <directory name="amd64">
+                       <!-- file>mps.S</file -->
+               </directory>
+       </directory>
+</module>
+</group>
 
diff --git a/reactos/hal/halx86/mp/amd64/mps.S b/reactos/hal/halx86/mp/amd64/mps.S
new file mode 100644 (file)
index 0000000..3543652
--- /dev/null
@@ -0,0 +1,96 @@
+/* 
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/hal/amd64/generic/mps.S
+ * PURPOSE:         Intel MultiProcessor specification support
+ * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <reactos/asm.h>
+#include <ndk/amd64/asm.h>
+
+/* FUNCTIONS *****************************************************************/
+
+#define BEFORE \
+  cld; \
+  push rax; \
+  push rbx; \
+  push rcx; \
+  push rdx; \
+  push rsi; \
+  push rdi; \
+  push fs; \
+  push gs; \
+  
+#define AFTER \
+  pop  gs; \
+  pop  fs; \
+  pop  rdi; \
+  pop  rsi; \
+  pop  rdx; \
+  pop  rcx; \
+  pop  rbx; \
+  pop  rax; \
+
+#ifdef CONFIG_SMP
+PUBLIC MpsIpiInterrupt
+MpsIpiInterrupt:
+    /* Save registers */       
+    BEFORE
+
+    /* Call the C handler */
+    call  MpsIpiHandler
+
+    /* Return to the caller */
+    AFTER
+    iret
+#endif
+  
+PUBLIC MpsErrorInterrupt
+MpsErrorInterrupt:
+    /* Save registers */       
+    BEFORE
+
+    /* Call the C handler */
+    call  MpsErrorHandler
+
+    /* Return to the caller */
+    AFTER
+    iret
+
+
+PUBLIC MpsSpuriousInterrupt
+MpsSpuriousInterrupt:
+    /* Save registers */       
+    BEFORE
+
+    /* Call the C handler */
+    call  MpsSpuriousHandler
+
+    /* Return to the caller */
+    AFTER
+    iret
+
+PUBLIC MpsTimerInterrupt
+MpsTimerInterrupt:
+    /* Save registers */       
+    BEFORE
+
+    mov        ebx, 0xef
+       mov eax, 0xceafbeef
+       push rax
+       push rsp
+       push rbx
+       call MpsTimerHandler
+       pop rax
+       pop rax
+       pop rax
+
+    /* Return to the caller */
+       AFTER
+       iret
+  
+  
+/* EOF */