Added freeldr and hal from PPC branch, along with needed headers and
authorArt Yerkes <art.yerkes@gmail.com>
Mon, 3 Sep 2007 01:57:36 +0000 (01:57 +0000)
committerArt Yerkes <art.yerkes@gmail.com>
Mon, 3 Sep 2007 01:57:36 +0000 (01:57 +0000)
build changes.

Next ntoskrnl and add ppc dir under libcntptr, which didn't exist when I
forked.

svn path=/trunk/; revision=28793

96 files changed:
reactos/Makefile
reactos/ReactOS-ppc.rbuild
reactos/boot/freeldr/bootsect/bootsect.rbuild
reactos/boot/freeldr/freeldr/arch/powerpc/boot.s
reactos/boot/freeldr/freeldr/arch/powerpc/compat.h [new file with mode: 0644]
reactos/boot/freeldr/freeldr/arch/powerpc/loader.c [new file with mode: 0644]
reactos/boot/freeldr/freeldr/arch/powerpc/mach.c
reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c
reactos/boot/freeldr/freeldr/arch/powerpc/mmu.c [new file with mode: 0644]
reactos/boot/freeldr/freeldr/arch/powerpc/ofw_util.s [new file with mode: 0644]
reactos/boot/freeldr/freeldr/arch/powerpc/prep.c [new file with mode: 0644]
reactos/boot/freeldr/freeldr/arch/powerpc/prep.h [new file with mode: 0644]
reactos/boot/freeldr/freeldr/arch/powerpc/prep_ide.c [new file with mode: 0644]
reactos/boot/freeldr/freeldr/arch/powerpc/prep_pci.c [new file with mode: 0644]
reactos/boot/freeldr/freeldr/arch/powerpc/prep_vga.c [new file with mode: 0644]
reactos/boot/freeldr/freeldr/freeldr.rbuild
reactos/boot/freeldr/freeldr/freeldr_arch.rbuild
reactos/boot/freeldr/freeldr/fs/fat.c
reactos/boot/freeldr/freeldr/fs/fs.c
reactos/boot/freeldr/freeldr/fs/fsrec.c
reactos/boot/freeldr/freeldr/include/bytesex.h [new file with mode: 0644]
reactos/boot/freeldr/freeldr/include/freeldr.h
reactos/boot/freeldr/freeldr/include/of.h
reactos/boot/freeldr/freeldr/mm/mm.c
reactos/hal/hal.rbuild
reactos/hal/hal/hal.rbuild
reactos/hal/halppc/generic/beep.c [new file with mode: 0644]
reactos/hal/halppc/generic/bus.c [new file with mode: 0644]
reactos/hal/halppc/generic/cmos.c [new file with mode: 0644]
reactos/hal/halppc/generic/display.c [new file with mode: 0644]
reactos/hal/halppc/generic/dma.c [new file with mode: 0644]
reactos/hal/halppc/generic/drive.c [new file with mode: 0644]
reactos/hal/halppc/generic/enum.c [new file with mode: 0644]
reactos/hal/halppc/generic/fmutex.c [new file with mode: 0644]
reactos/hal/halppc/generic/font.c [new file with mode: 0644]
reactos/hal/halppc/generic/generic.rbuild [new file with mode: 0644]
reactos/hal/halppc/generic/halinit.c [new file with mode: 0644]
reactos/hal/halppc/generic/ipi.c [new file with mode: 0644]
reactos/hal/halppc/generic/irql.c [new file with mode: 0644]
reactos/hal/halppc/generic/isa.c [new file with mode: 0644]
reactos/hal/halppc/generic/kdbg.c [new file with mode: 0644]
reactos/hal/halppc/generic/mca.c [new file with mode: 0644]
reactos/hal/halppc/generic/misc.c [new file with mode: 0644]
reactos/hal/halppc/generic/pci.c [new file with mode: 0644]
reactos/hal/halppc/generic/portio.c [new file with mode: 0644]
reactos/hal/halppc/generic/processor.c [new file with mode: 0644]
reactos/hal/halppc/generic/profil.c [new file with mode: 0644]
reactos/hal/halppc/generic/pwroff.c [new file with mode: 0644]
reactos/hal/halppc/generic/reboot.c [new file with mode: 0644]
reactos/hal/halppc/generic/resource.c [new file with mode: 0644]
reactos/hal/halppc/generic/spinlock.c [new file with mode: 0644]
reactos/hal/halppc/generic/sysbus.c [new file with mode: 0644]
reactos/hal/halppc/generic/sysinfo.c [new file with mode: 0644]
reactos/hal/halppc/generic/systimer.S [new file with mode: 0644]
reactos/hal/halppc/generic/time.c [new file with mode: 0644]
reactos/hal/halppc/generic/timer.c [new file with mode: 0644]
reactos/hal/halppc/include/apic.h [new file with mode: 0644]
reactos/hal/halppc/include/bus.h [new file with mode: 0644]
reactos/hal/halppc/include/hal.h [new file with mode: 0644]
reactos/hal/halppc/include/haldma.h [new file with mode: 0644]
reactos/hal/halppc/include/halirq.h [new file with mode: 0644]
reactos/hal/halppc/include/halp.h [new file with mode: 0644]
reactos/hal/halppc/include/ioapic.h [new file with mode: 0644]
reactos/hal/halppc/include/mps.h [new file with mode: 0644]
reactos/hal/halppc/up/halinit_up.c [new file with mode: 0644]
reactos/hal/halppc/up/halup.rbuild [new file with mode: 0644]
reactos/hal/halppc/up/halup.rc [new file with mode: 0644]
reactos/include/ddk/winddk.h
reactos/include/ndk/powerpc/ketypes.h
reactos/include/ndk/powerpc/mmtypes.h
reactos/include/psdk/intrin_ppc.h [new file with mode: 0644]
reactos/include/psdk/rpc.h
reactos/include/psdk/winnt.h
reactos/include/reactos/arc/arc.h
reactos/include/reactos/debug.h
reactos/include/reactos/elf/elf-powerpc.h [new file with mode: 0644]
reactos/include/reactos/elf/machine.h
reactos/include/reactos/elf/reactos.h [new file with mode: 0644]
reactos/include/reactos/libs/ppcmmu/mmu.h [new file with mode: 0644]
reactos/include/reactos/libs/ppcmmu/mmuutil.h [new file with mode: 0644]
reactos/include/reactos/ppcboot.h [new file with mode: 0644]
reactos/include/reactos/ppcdebug.h [new file with mode: 0644]
reactos/include/reactos/ppcfont.h [new file with mode: 0644]
reactos/include/reactos/rosldr.h
reactos/lib/rtl/exception.c
reactos/lib/rtl/powerpc/debug.c [new file with mode: 0644]
reactos/lib/rtl/powerpc/except.c [new file with mode: 0644]
reactos/lib/rtl/powerpc/interlocked.c [new file with mode: 0644]
reactos/lib/rtl/powerpc/thread.c [new file with mode: 0644]
reactos/lib/rtl/rtl.rbuild
reactos/ntoskrnl/include/internal/powerpc/intrin_i.h [new file with mode: 0644]
reactos/tools/rbuild/backend/mingw/modulehandler.cpp
reactos/tools/rbuild/backend/mingw/modulehandler.h
reactos/tools/rbuild/bootstrap.cpp
reactos/tools/rbuild/module.cpp
reactos/tools/rbuild/rbuild.h

index 6fb7488..4c64926 100644 (file)
@@ -414,7 +414,11 @@ PREAUTO := \
        $(ERRCODES_H) \
        $(ERRCODES_RC) \
        $(GENDIB_DIB_FILES) \
-       $(NCI_SERVICE_FILES)
+       $(NCI_SERVICE_FILES) \
+       $(OFW_INTERFACE_SERVICE_FILES)
+ifeq ($(ARCH),powerpc)
+PREAUTO += $(PPCMMU_TARGETS)
+endif
 
 $(ROS_AUTOMAKE): $(RBUILD_TARGET) $(PREAUTO) $(XMLBUILDFILES)
        ${mkdir} $(OUTPUT_)media$(SEP)inf 2>$(NUL)
index 26891ad..092cbc3 100644 (file)
@@ -9,22 +9,27 @@
 
   <xi:include href="ReactOS-generic.rbuild" />
 
-  <property name="BOOTPROG_PREPARE" value="ppc-le2be" />
-  <property name="BOOTPROG_FLATFORMAT" value="-O elf32-powerpc -B powerpc:common" />
-  <property name="BOOTPROG_LINKFORMAT" value="-melf32ppc --no-omagic -Ttext 0xe00000 -Tdata 0xe10000" />
-  <property name="BOOTPROG_COPYFORMAT" value="--only-section=.text --only-section=.data --only-section=.bss -O aixcoff-rs6000" />
+  <property name="OFWLDR_LINKFORMAT" value="-L$(INTERMEDIATE)/lib/ppcmmu -lppcmmu_code"/>
 
   <define name="_M_PPC" />
   <define name="_PPC_" />
   <define name="__PowerPC__" />
-  <define name="__MINGW_IMPORT" empty="true" />
+  <define name="_REACTOS_" />
   <define name="stdcall" empty="true" />       
   <define name="__stdcall__" empty="true" />
   <define name="fastcall" empty="true" />
   <define name="cdecl" empty="true" />
   <define name="__cdecl__" empty="true" />
   <define name="dllimport" empty="true" />
-  <compilerflag>-v</compilerflag>
-  <compilerflag>-Wpointer-arith</compilerflag>
+  <define name="WORDS_BIGENDIAN" empty="true" />
+  <define name="MB_CUR_MAX">1</define>
+  <define name="_BSDTYPES_DEFINED"/>
+  <compilerflag>-fshort-wchar</compilerflag>
+  <compilerflag>-fsigned-char</compilerflag>
+  <compilerflag>-mfull-toc</compilerflag>
+  <compilerflag>-meabi</compilerflag>
+  <compilerflag>-O2</compilerflag>
+  <compilerflag>-Wno-strict-aliasing</compilerflag>
+  <compilerflag>-Wno-trampolines</compilerflag>
 
 </project>
index 65334cc..b3b7f2f 100644 (file)
@@ -22,9 +22,3 @@
        <bootstrap base="loader" nameoncd="isobtrt.bin" />
        <file>isobtrt.asm</file>
 </module>
-<if property="ARCH" value="powerpc">
-       <module name="ofwldr" type="bootprogram" payload="freeldr">
-               <bootstrap base="loader" nameoncd="boot/ofwldr" />
-               <file>ofwboot.s</file>
-       </module>
-</if>
\ No newline at end of file
index a507daa..7efff45 100644 (file)
@@ -1,3 +1,103 @@
+       .section ".text"
        .extern PpcInit
+       .globl _start
+       .globl call_ofw
 _start:
-       b       PpcInit+4
+       sync                    
+       isync
+
+       lis     %r1,stackend@ha    
+       addi    %r1,%r1,stackend@l
+
+       /* Store ofw call addr */
+       mr      %r21,%r5
+       lis     %r10,ofw_call_addr@ha
+       stw     %r5,ofw_call_addr@l(%r10)
+
+       bl      zero_registers
+       
+       /* Zero CTR */
+       mtcr    %r31
+
+       lis     %r3,PpcInit@ha
+       addi    %r3,%r3,PpcInit@l
+       mtlr    %r3
+
+       /* Check for ofw */
+       lis     %r3,ofw_call_addr@ha
+       lwz     %r3,ofw_call_addr@l(%r3)
+       cmpw    %r3,%r31 /* Zero? */
+       mr      %r3,%r31
+       beq     bootme
+               
+       lis     %r3,call_ofw@ha
+       addi    %r3,%r3,call_ofw@l
+
+bootme:        
+       blr
+
+zero_registers:
+       xor     %r2,%r2,%r2
+       mr      %r0,%r2
+       mr      %r3,%r2
+       
+       mr      %r4,%r2
+       mr      %r5,%r2
+       mr      %r6,%r2
+       mr      %r7,%r2
+
+       mr      %r8,%r2
+       mr      %r9,%r2
+       mr      %r10,%r2
+       mr      %r11,%r2
+
+       mr      %r12,%r2
+       mr      %r13,%r2
+       mr      %r14,%r2
+       mr      %r15,%r2
+       
+       mr      %r12,%r2
+       mr      %r13,%r2
+       mr      %r14,%r2
+       mr      %r15,%r2
+       
+       mr      %r16,%r2
+       mr      %r17,%r2
+       mr      %r18,%r2
+       mr      %r19,%r2
+       
+       mr      %r20,%r2
+       mr      %r21,%r2
+       mr      %r22,%r2
+       mr      %r23,%r2
+       
+       mr      %r24,%r2
+       mr      %r25,%r2
+       mr      %r26,%r2
+       mr      %r27,%r2
+       
+       mr      %r28,%r2
+       mr      %r29,%r2
+       mr      %r30,%r2
+       mr      %r31,%r2
+
+       blr
+       
+ofw_memory_size:
+       .long   0
+       .long   0
+       .long   0
+       .long   0
+
+       .align  4
+stack:
+       .space  0x4000
+stackend:
+       .long   0,0,0,0
+       
+       .globl _bss
+       .section ".bss"
+_bss:
+       .long   0
+
+       .align  4
diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/compat.h b/reactos/boot/freeldr/freeldr/arch/powerpc/compat.h
new file mode 100644 (file)
index 0000000..66797a6
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef _FREELDR_ARCH_COMPAT_H
+#define _FREELDR_ARCH_COMPAT_H
+
+#define __init
+#define __initdata
+
+#define SPRN_MSSCR0     0x3f6   /* Memory Subsystem Control Register 0 */
+#define SPRN_MSSSR0     0x3f7   /* Memory Subsystem Status Register 1 */
+#define SPRN_LDSTCR     0x3f8   /* Load/Store control register */
+#define SPRN_LDSTDB     0x3f4   /* */
+#define SPRN_LR         0x008   /* Link Register */
+#ifndef SPRN_PIR
+#define SPRN_PIR        0x3FF   /* Processor Identification Register */
+#endif
+#define SPRN_PTEHI      0x3D5   /* 981 7450 PTE HI word (S/W TLB load) */
+#define SPRN_PTELO      0x3D6   /* 982 7450 PTE LO word (S/W TLB load) */
+#define SPRN_PURR       0x135   /* Processor Utilization of Resources Reg */
+#define SPRN_PVR        0x11F   /* Processor Version Register */
+#define SPRN_RPA        0x3D6   /* Required Physical Address Register */
+#define SPRN_SDA        0x3BF   /* Sampled Data Address Register */
+#define SPRN_SDR1       0x019   /* MMU Hash Base Register */
+#define SPRN_ASR        0x118   /* Address Space Register */
+#define SPRN_SIA        0x3BB   /* Sampled Instruction Address Register */
+#define SPRN_SPRG0      0x110   /* Special Purpose Register General 0 */
+#define SPRN_SPRG1      0x111   /* Special Purpose Register General 1 */
+#define SPRN_SPRG2      0x112   /* Special Purpose Register General 2 */
+#define SPRN_SPRG3      0x113   /* Special Purpose Register General 3 */
+#define SPRN_SPRG4      0x114   /* Special Purpose Register General 4 */
+#define SPRN_SPRG5      0x115   /* Special Purpose Register General 5 */
+#define SPRN_SPRG6      0x116   /* Special Purpose Register General 6 */
+#define SPRN_SPRG7      0x117   /* Special Purpose Register General 7 */
+#define SPRN_SRR0       0x01A   /* Save/Restore Register 0 */
+#define SPRN_SRR1       0x01B   /* Save/Restore Register 1 */
+#ifndef SPRN_SVR
+#define SPRN_SVR        0x11E   /* System Version Register */
+#endif
+#define SPRN_THRM1      0x3FC           /* Thermal Management Register 1 */
+/* these bits were defined in inverted endian sense originally, ugh, confusing */
+
+/* Values for PP (assumes Ks=0, Kp=1) */
+#define PP_RWXX 0       /* Supervisor read/write, User none */
+#define PP_RWRX 1       /* Supervisor read/write, User read */
+#define PP_RWRW 2       /* Supervisor read/write, User read/write */
+#define PP_RXRX 3       /* Supervisor read,       User read */
+
+/* Block size masks */
+#define BL_128K 0x000
+#define BL_256K 0x001
+#define BL_512K 0x003
+#define BL_1M   0x007
+#define BL_2M   0x00F
+#define BL_4M   0x01F
+#define BL_8M   0x03F
+#define BL_16M  0x07F
+#define BL_32M  0x0FF
+#define BL_64M  0x1FF
+#define BL_128M 0x3FF
+#define BL_256M 0x7FF
+
+/* BAT Access Protection */
+#define BPP_XX  0x00            /* No access */
+#define BPP_RX  0x01            /* Read only */
+#define BPP_RW  0x02            /* Read/write */
+
+/* Definitions for 40x embedded chips. */
+#define _PAGE_GUARDED   0x001   /* G: page is guarded from prefetch */
+#define _PAGE_FILE      0x001   /* when !present: nonlinear file mapping */
+#define _PAGE_PRESENT   0x002   /* software: PTE contains a translation */
+#define _PAGE_NO_CACHE  0x004   /* I: caching is inhibited */
+#define _PAGE_WRITETHRU 0x008   /* W: caching is write-through */
+#define _PAGE_USER      0x010   /* matches one of the zone permission bits */
+#define _PAGE_RW        0x040   /* software: Writes permitted */
+#define _PAGE_DIRTY     0x080   /* software: dirty page */
+#define _PAGE_HWWRITE   0x100   /* hardware: Dirty & RW, set in exception */
+#define _PAGE_HWEXEC    0x200   /* hardware: EX permission */
+#define _PAGE_ACCESSED  0x400   /* software: R: page referenced */
+
+#define _PMD_PRESENT    0x400   /* PMD points to page of PTEs */
+#define _PMD_BAD        0x802
+#define _PMD_SIZE       0x0e0   /* size field, != 0 for large-page PMD entry */
+#define _PMD_SIZE_4M    0x0c0
+#define _PMD_SIZE_16M   0x0e0
+#define PMD_PAGE_SIZE(pmdval)   (1024 << (((pmdval) & _PMD_SIZE) >> 4))
+
+#define PVR_VER(pvr)(((pvr) >>  16) & 0xFFFF) /* Version field */
+
+#define KERNELBASE 0x80000000
+
+typedef unsigned char __u8;
+typedef unsigned short __u16;
+typedef unsigned int __u32;
+
+typedef struct _pci_reg_property {
+    struct {
+       int a_hi, a_mid, a_lo;
+    } addr;
+    int size_hi, size_lo;
+} pci_reg_property;
+
+void btext_drawstring(const char *c);
+void btext_drawhex(unsigned long v);
+
+void *ioremap(__u32 phys, __u32 size);
+void iounmap(void *logical);
+
+__u32 GetPVR();
+
+#endif/*_FREELDR_ARCH_COMPAT_H*/
diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/loader.c b/reactos/boot/freeldr/freeldr/arch/powerpc/loader.c
new file mode 100644 (file)
index 0000000..0dea8ef
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ *  FreeLoader
+ *  Copyright (C) 1998-2003  Brian Palmer  <brianp@sginet.com>
+ *  Copyright (C) 2005       Alex Ionescu  <alex@relsoft.net>
+ *
+ *  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.
+ */
+#define _NTSYSTEM_
+#include <freeldr.h>
+
+#define NDEBUG
+#include <debug.h>
+#undef DbgPrint
+
+extern PVOID KernelMemory;
+
+PVOID
+NTAPI
+LdrPEGetExportByName(PVOID BaseAddress,
+                     PUCHAR SymbolName,
+                     USHORT Hint);
+
+/* FUNCTIONS *****************************************************************/
+
+PLOADER_MODULE
+NTAPI
+LdrGetModuleObject(PCHAR ModuleName)
+{
+    ULONG i;
+
+    for (i = 0; i < LoaderBlock.ModsCount; i++)
+    {
+        if (strstr(_strupr((PCHAR)reactos_modules[i].String), _strupr(ModuleName)))
+        {
+            return &reactos_modules[i];
+        }
+    }
+
+    return NULL;
+}
+
+PVOID
+NTAPI
+LdrPEFixupForward(IN PCHAR ForwardName)
+{
+    CHAR NameBuffer[128];
+    PCHAR p;
+    PLOADER_MODULE ModuleObject;
+
+    strcpy(NameBuffer, ForwardName);
+    p = strchr(NameBuffer, '.');
+    if (p == NULL) return NULL;
+    *p = 0;
+
+    ModuleObject = LdrGetModuleObject(NameBuffer);
+    if (!ModuleObject)
+    {
+        DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
+        return NULL;
+    }
+
+    return LdrPEGetExportByName((PVOID)ModuleObject->ModStart, (PUCHAR)(p + 1), 0xffff);
+}
+
+PVOID
+NTAPI
+LdrPEGetExportByName(PVOID BaseAddress,
+                     PUCHAR SymbolName,
+                     USHORT Hint)
+{
+    PIMAGE_EXPORT_DIRECTORY ExportDir;
+    PULONG * ExFunctions;
+    PULONG * ExNames;
+    USHORT * ExOrdinals;
+    PVOID ExName;
+    ULONG Ordinal;
+    PVOID Function;
+    LONG minn, maxn, mid, res;
+    ULONG ExportDirSize;
+
+    /* HAL and NTOS use a virtual address, switch it to physical mode */
+    if ((ULONG_PTR)BaseAddress & 0x80000000)
+    {
+        BaseAddress = (PVOID)((ULONG_PTR)BaseAddress - KSEG0_BASE + (ULONG)KernelMemory);
+    }
+
+    ExportDir = (PIMAGE_EXPORT_DIRECTORY)
+        RtlImageDirectoryEntryToData(BaseAddress,
+                                     TRUE,
+                                     IMAGE_DIRECTORY_ENTRY_EXPORT,
+                                     &ExportDirSize);
+    if (!ExportDir)
+    {
+        DbgPrint("LdrPEGetExportByName(): no export directory!\n");
+        return NULL;
+    }
+
+    /* The symbol names may be missing entirely */
+    if (!ExportDir->AddressOfNames)
+    {
+        DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n");
+        return NULL;
+    }
+
+    /*
+    * Get header pointers
+    */
+    ExNames = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfNames);
+    ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
+    ExFunctions = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfFunctions);
+
+    /*
+    * Check the hint first
+    */
+    if (Hint < ExportDir->NumberOfNames)
+    {
+        ExName = RVA(BaseAddress, ExNames[Hint]);
+        if (strcmp(ExName, (PCHAR)SymbolName) == 0)
+        {
+            Ordinal = ExOrdinals[Hint];
+            Function = RVA(BaseAddress, ExFunctions[Ordinal]);
+            if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
+                (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
+            {
+                Function = LdrPEFixupForward((PCHAR)Function);
+                if (Function == NULL)
+                {
+                    DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function);
+                }
+                return Function;
+            }
+
+            if (Function != NULL) return Function;
+        }
+    }
+
+    /*
+    * Binary search
+    */
+    minn = 0;
+    maxn = ExportDir->NumberOfNames - 1;
+    while (minn <= maxn)
+    {
+        mid = (minn + maxn) / 2;
+
+        ExName = RVA(BaseAddress, ExNames[mid]);
+        res = strcmp(ExName, (PCHAR)SymbolName);
+        if (res == 0)
+        {
+            Ordinal = ExOrdinals[mid];
+            Function = RVA(BaseAddress, ExFunctions[Ordinal]);
+            if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
+                (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
+            {
+                Function = LdrPEFixupForward((PCHAR)Function);
+                if (Function == NULL)
+                {
+                    DbgPrint("1: failed to find %s\n", Function);
+                }
+                return Function;
+            }
+            if (Function != NULL)
+            {
+                return Function;
+            }
+        }
+        else if (res > 0)
+        {
+            maxn = mid - 1;
+        }
+        else
+        {
+            minn = mid + 1;
+        }
+    }
+
+    /* Fall back on unsorted */
+    minn = 0;
+    maxn = ExportDir->NumberOfNames - 1;
+    while (minn <= maxn)
+    {
+        ExName = RVA(BaseAddress, ExNames[minn]);
+        res = strcmp(ExName, (PCHAR)SymbolName);
+        if (res == 0)
+        {
+            Ordinal = ExOrdinals[minn];
+            Function = RVA(BaseAddress, ExFunctions[Ordinal]);
+            if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
+                (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
+            {
+                DbgPrint("Forward: %s\n", (PCHAR)Function);
+                Function = LdrPEFixupForward((PCHAR)Function);
+                if (Function == NULL)
+                {
+                    DbgPrint("LdrPEGetExportByName(): failed to find %s\n",SymbolName);
+                }
+                return Function;
+            }
+           if (Function != NULL)
+           {
+               return Function;
+           }
+           DbgPrint("Failed to get function %s\n", SymbolName);
+       }
+       minn++;
+    }
+
+    DbgPrint("2: failed to find %s\n",SymbolName);
+    return (PVOID)NULL;
+}
+
+NTSTATUS
+NTAPI
+LdrPEProcessImportDirectoryEntry(PVOID DriverBase,
+                                 PLOADER_MODULE LoaderModule,
+                                 PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory)
+{
+    PVOID* ImportAddressList;
+    PULONG FunctionNameList;
+
+    if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0)
+    {
+        return STATUS_UNSUCCESSFUL;
+    }
+
+    /* Get the import address list. */
+    ImportAddressList = (PVOID*)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
+
+    /* Get the list of functions to import. */
+    if (ImportModuleDirectory->OriginalFirstThunk != 0)
+    {
+        FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->OriginalFirstThunk);
+    }
+    else
+    {
+        FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
+    }
+
+    /* Walk through function list and fixup addresses. */
+    while (*FunctionNameList != 0L)
+    {
+        if ((*FunctionNameList) & 0x80000000)
+        {
+            DbgPrint("Failed to import ordinal from %s\n", LoaderModule->String);
+            return STATUS_UNSUCCESSFUL;
+        }
+        else
+        {
+            IMAGE_IMPORT_BY_NAME *pe_name;
+            pe_name = RVA(DriverBase, *FunctionNameList);
+            *ImportAddressList = LdrPEGetExportByName((PVOID)LoaderModule->ModStart, pe_name->Name, pe_name->Hint);
+
+            /* Fixup the address to be virtual */
+            *ImportAddressList = (PVOID)((ULONG_PTR)*ImportAddressList + (KSEG0_BASE - (ULONG_PTR)KernelMemory));
+
+            //DbgPrint("Looked for: %s and found: %p\n", pe_name->Name, *ImportAddressList);
+            if ((*ImportAddressList) == NULL)
+            {
+                DbgPrint("Failed to import %s from %s\n", pe_name->Name, LoaderModule->String);
+                return STATUS_UNSUCCESSFUL;
+            }
+        }
+        ImportAddressList++;
+        FunctionNameList++;
+    }
+    return STATUS_SUCCESS;
+}
+
+extern BOOLEAN FrLdrLoadDriver(PCHAR szFileName, INT nPos);
+
+NTSTATUS
+NTAPI
+LdrPEGetOrLoadModule(IN PCHAR ModuleName,
+                     IN PCHAR ImportedName,
+                     IN PLOADER_MODULE* ImportedModule)
+{
+    NTSTATUS Status = STATUS_SUCCESS;
+
+    *ImportedModule = LdrGetModuleObject(ImportedName);
+    if (*ImportedModule == NULL)
+    {
+        /*
+         * For now, we only support import-loading the HAL.
+         * Later, FrLdrLoadDriver should be made to share the same
+         * code, and we'll just call it instead.
+         */
+       FrLdrLoadDriver(ImportedName, 0);
+       
+       /* Return the new module */
+       *ImportedModule = LdrGetModuleObject(ImportedName);
+       if (*ImportedModule == NULL)
+       {
+           DbgPrint("Error loading import: %s\n", ImportedName);
+           return STATUS_UNSUCCESSFUL;
+       }
+    }
+
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+LdrPEFixupImports(IN PVOID DllBase,
+                  IN PCHAR DllName)
+{
+    PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
+    PCHAR ImportedName;
+    NTSTATUS Status;
+    PLOADER_MODULE ImportedModule;
+    ULONG Size;
+
+    printf("Fixing up %x (%s)\n", DllBase, DllName);
+
+    /*  Process each import module  */
+    ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
+        RtlImageDirectoryEntryToData(DllBase,
+                                     TRUE,
+                                     IMAGE_DIRECTORY_ENTRY_IMPORT,
+                                     &Size);
+    while (ImportModuleDirectory && ImportModuleDirectory->Name)
+    {
+        /*  Check to make sure that import lib is kernel  */
+        ImportedName = (PCHAR) DllBase + ImportModuleDirectory->Name;
+        //DbgPrint("Processing imports for file: %s into file: %s\n", DllName, ImportedName);
+
+        Status = LdrPEGetOrLoadModule(DllName, ImportedName, &ImportedModule);
+        if (!NT_SUCCESS(Status)) return Status;
+
+        Status = LdrPEProcessImportDirectoryEntry(DllBase, ImportedModule, ImportModuleDirectory);
+        if (!NT_SUCCESS(Status)) return Status;
+
+        //DbgPrint("Imports for file: %s into file: %s complete\n", DllName, ImportedName);
+        ImportModuleDirectory++;
+    }
+
+    return STATUS_SUCCESS;
+}
index c79d506..de937c0 100644 (file)
  */
 #include "freeldr.h"
 #include "machine.h"
+#include "ppcmmu/mmu.h"
 #include "of.h"
+#include "ppcboot.h"
+#include "prep.h"
+#include "compat.h"
 
-extern void BootMain( char * );
-extern char *GetFreeLoaderVersionString();
+extern void BootMain( LPSTR CmdLine );
+extern PCHAR GetFreeLoaderVersionString();
+extern ULONG CacheSizeLimit;
 of_proxy ofproxy;
 void *PageDirectoryStart, *PageDirectoryEnd;
-static int chosen_package, stdin_handle, part_handle = -1;
+static int chosen_package, stdin_handle, stdout_handle, 
+  part_handle = -1, kernel_mem = 0;
+int mmu_handle = 0, FixedMemory = 0;
 BOOLEAN AcpiPresent = FALSE;
-char BootPath[0x100] = { 0 }, BootPart[0x100] = { 0 }, CmdLine[0x100] = { 0 };
+char BootPath[0x100] = { 0 }, BootPart[0x100] = { 0 }, CmdLine[0x100] = { "bootprep" };
 jmp_buf jmp;
+volatile char *video_mem = 0;
+boot_infos_t BootInfo;
 
-void le_swap( const void *start_addr_v, 
-              const void *end_addr_v, 
-              const void *target_addr_v ) {
-    long *start_addr = (long *)ROUND_DOWN((long)start_addr_v,8), 
-        *end_addr = (long *)ROUND_UP((long)end_addr_v,8), 
-        *target_addr = (long *)ROUND_DOWN((long)target_addr_v,8);
-    long tmp;
-    while( start_addr <= end_addr ) {
-        tmp = start_addr[0];
-        target_addr[0] = REV(start_addr[1]);
-        target_addr[1] = REV(tmp);
-        start_addr += 2;
-        target_addr += 2;
-    }
-}
-
-int ofw_finddevice( const char *name ) {
-    int ret, len;
-
-    len = strlen(name);
-    le_swap( name, name + len, name );
-    ret = ofproxy( 0, (char *)name, NULL, NULL, NULL );
-    le_swap( name, name + len, name );
-    return ret;
-}
-
-int ofw_getprop( int package, const char *name, void *buffer, int buflen ) {
-    int ret, len = strlen(name);
-    le_swap( name, name + len, name );
-    le_swap( buffer, (char *)buffer + buflen, buffer );
-    ret = ofproxy
-        ( 4, (void *)package, (char *)name, buffer, (void *)buflen );
-    le_swap( buffer, (char *)buffer + buflen, buffer );
-    le_swap( name, name + len, name );
-    return ret;
-}
-
-/* Since this is from external storage, it doesn't need swapping */
-int ofw_write( int handle, const char *data, int len ) {
-    int ret;
-    le_swap( data, data + len, data );
-    ret = ofproxy
-        ( 8, (void *)handle, (char *)data, (void *)len, NULL );
-    le_swap( data, data + len, data );
-    return ret;
-}
-
-/* Since this is from external storage, it doesn't need swapping */
-int ofw_read( int handle, const char *data, int len ) {
-    int ret;
-
-    le_swap( data, data + len, data );
-    ret = ofproxy
-        ( 12, (void *)handle, (char *)data, (void *)len, NULL );
-    le_swap( data, data + len, data );
-
-    return ret;
-}
-
-void ofw_exit() {
-    ofproxy( 16, NULL, NULL, NULL, NULL );
-}
-
-void ofw_dumpregs() {
-    ofproxy( 20, NULL, NULL, NULL, NULL );
-}
-
-void ofw_print_string( const char *str ) {
-    int len = strlen(str);
-    le_swap( (char *)str, str + len, (char *)str );
-    ofproxy( 24, (void *)str, NULL, NULL, NULL );
-    le_swap( (char *)str, str + len, (char *)str );
-}
-
-void ofw_print_number( int num ) {
-    ofproxy( 28, (void *)num, NULL, NULL, NULL );
-}
-
-int ofw_open( const char *name ) {
-    int ret, len;
-
-    len = strlen(name);
-    le_swap( name, name + len, name );
-    ret = ofproxy( 32, (char *)name, NULL, NULL, NULL );
-    le_swap( name, name + len, name );
-    return ret;
-}
-
-int ofw_child( int package ) {
-    return ofproxy( 36, (void *)package, NULL, NULL, NULL );
-}
-
-int ofw_peer( int package ) {
-    return ofproxy( 40, (void *)package, NULL, NULL, NULL );
-}
-
-int ofw_seek( int handle, long long location ) {
-    return ofproxy( 44, (void *)handle, (void *)(int)(location >> 32), (void *)(int)location, NULL );
-}
-
-void PpcPutChar( int ch ) {
+void PpcOfwPutChar( int ch ) {
     char buf[3];
     if( ch == 0x0a ) { buf[0] = 0x0d; buf[1] = 0x0a; } 
     else { buf[0] = ch; buf[1] = 0; }
     buf[2] = 0;
-    ofw_print_string( buf );
+    ofw_write(stdout_handle, buf, strlen(buf));
 }
 
 int PpcFindDevice( int depth, int parent, char *devname, int *nth ) {
@@ -156,7 +65,7 @@ int PpcFindDevice( int depth, int parent, char *devname, int *nth ) {
 
     if( !nth && match ) return parent;
 
-    for( i = 0; i < depth; i++ ) PpcPutChar( ' ' );
+    for( i = 0; i < depth; i++ ) PpcOfwPutChar( ' ' );
     
     if( depth == 1 ) {
        if( gotname > 0 ) {
@@ -176,7 +85,7 @@ int PpcFindDevice( int depth, int parent, char *devname, int *nth ) {
 }
 
 BOOLEAN PpcConsKbHit() {
-    return TRUE;
+    return FALSE;
 }
 
 int PpcConsGetCh() {
@@ -186,29 +95,28 @@ int PpcConsGetCh() {
 }
 
 void PpcVideoClearScreen( UCHAR Attr ) {
-    ofw_print_string("ClearScreen\n");
-}
-
-VIDEODISPLAYMODE PpcVideoSetDisplayMode( char *DisplayMode, BOOLEAN Init ) {
-    printf( "DisplayMode: %s %s\n", DisplayMode, Init ? "true" : "false" );
-    return VideoGraphicsMode;
 }
 
-/* FIXME: Query */
 VOID PpcVideoGetDisplaySize( PULONG Width, PULONG Height, PULONG Depth ) {
-    ofw_print_string("GetDisplaySize\n");
-    *Width = 640;
-    *Height = 480;
-    *Depth = 8;
+    *Width = 80;
+    *Height = 25;
+    *Depth = 16;
 }
 
 ULONG PpcVideoGetBufferSize() {
     ULONG Width, Height, Depth;
-    ofw_print_string("PpcVideoGetBufferSize\n");
-    PpcVideoGetDisplaySize( &Width, &Height, &Depth );
+    MachVideoGetDisplaySize( &Width, &Height, &Depth );
     return Width * Height * Depth / 8;
 }
 
+VIDEODISPLAYMODE PpcVideoSetDisplayMode( char *DisplayMode, BOOLEAN Init ) {
+    //printf( "DisplayMode: %s %s\n", DisplayMode, Init ? "true" : "false" );
+    if( Init && !video_mem ) {
+       video_mem = MmAllocateMemory( PpcVideoGetBufferSize() );
+    }
+    return VideoTextMode;
+}
+
 VOID PpcVideoSetTextCursorPosition( ULONG X, ULONG Y ) {
     printf("SetTextCursorPosition(%d,%d)\n", X,Y);
 }
@@ -222,7 +130,22 @@ VOID PpcVideoPutChar( int Ch, UCHAR Attr, unsigned X, unsigned Y ) {
 }
 
 VOID PpcVideoCopyOffScreenBufferToVRAM( PVOID Buffer ) {
-    printf( "CopyOffScreenBufferToVRAM(%x)\n", Buffer );
+    int i,j;
+    ULONG w,h,d;
+    PCHAR ChBuf = Buffer;
+    int offset = 0;
+
+    MachVideoGetDisplaySize( &w, &h, &d );
+
+    for( i = 0; i < h; i++ ) {
+       for( j = 0; j < w; j++ ) {
+           offset = (j * 2) + (i * w * 2);
+           if( ChBuf[offset] != video_mem[offset] ) {
+               video_mem[offset] = ChBuf[offset];
+               MachVideoPutChar(ChBuf[offset],0,j+1,i+1);
+           }
+       }
+    }
 }
 
 BOOLEAN PpcVideoIsPaletteFixed() {
@@ -243,27 +166,187 @@ VOID PpcVideoSync() {
     printf( "Sync\n" );
 }
 
-VOID PpcVideoPrepareForReactOS() {
-    printf( "PrepareForReactOS\n");
+static int prom_next_node(int *nodep)
+{
+       int node;
+
+       if ((node = *nodep) != 0
+           && (*nodep = ofw_child(node)) != 0)
+               return 1;
+       if ((*nodep = ofw_peer(node)) != 0)
+               return 1;
+       for (;;) {
+               if ((node = ofw_parent(node)) == 0)
+                       return 0;
+               if ((*nodep = ofw_peer(node)) != 0)
+                       return 1;
+       }
 }
-/* XXX FIXME:
- * According to the linux people (this is backed up by my own experience),
- * the memory object in older ofw does not do getprop right.
- *
- * The "right" way is to probe the pci bridge. *sigh*
+
+/* Appropriated from linux' btext.c
+ * author:
+ * Benjamin Herrenschmidt <benh@kernel.crashing.org>
+ */
+VOID PpcVideoPrepareForReactOS(BOOLEAN Setup) {
+    int i, j, k, /* display_handle, */ display_package, display_size = 0;
+    int node, ret, elts;
+    int device_address;
+    //pci_reg_property display_regs[8];
+    char type[256], path[256], name[256];
+    char logo[] = {
+       "          "
+       "  XXXXXX  "
+       " X      X "
+       " X X  X X "
+       " X      X "
+       " X XXXX X "
+       " X  XX  X "
+       " X      X "
+       "  XXXXXX  "
+       "          "
+    };
+    int logo_x = 10, logo_y = 10;
+    int logo_scale_x = 8, logo_scale_y = 8;
+
+
+    for( node = ofw_finddevice("/"); prom_next_node(&node); ) {
+       memset(type, 0, sizeof(type));
+       memset(path, 0, sizeof(path));
+       
+       ret = ofw_getprop(node, "name", name, sizeof(name));
+
+       if(ofw_getprop(node, "device_type", type, sizeof(type)) <= 0) {
+           printf("Could not get type for node %x\n", node);
+           continue;
+       }
+
+       printf("Node %x ret %d name %s type %s\n", node, ret, name, type);
+
+       if(strcmp(type, "display") == 0) break;
+    }
+
+    if(!node) return;
+
+    if(ofw_package_to_path(node, path, sizeof(path)) < 0) {
+       printf("could not get path for display package %x\n", node);
+       return;
+    }
+
+    printf("Opening display package: %s\n", path);
+    display_package = ofw_finddevice(path);
+    printf("display package %x\n", display_package);
+
+    BootInfo.dispDeviceRect[0] = BootInfo.dispDeviceRect[1] = 0;
+
+    ofw_getprop(display_package, "width", 
+               (void *)&BootInfo.dispDeviceRect[2], sizeof(int));
+    ofw_getprop(display_package, "height",
+               (void *)&BootInfo.dispDeviceRect[3], sizeof(int));
+    ofw_getprop(display_package, "depth",
+               (void *)&BootInfo.dispDeviceDepth, sizeof(int));
+    ofw_getprop(display_package, "linebytes",
+               (void *)&BootInfo.dispDeviceRowBytes, sizeof(int));
+
+    BootInfo.dispDeviceRect[2] = BootInfo.dispDeviceRect[2];
+    BootInfo.dispDeviceRect[3] = BootInfo.dispDeviceRect[3];
+    BootInfo.dispDeviceDepth = BootInfo.dispDeviceDepth;
+    BootInfo.dispDeviceRowBytes = BootInfo.dispDeviceRowBytes;
+
+    if(ofw_getprop
+       (display_package,
+       "address",
+       (void *)&device_address,
+       sizeof(device_address)) < 1) {
+       printf("Could not get device base\n");
+       return;
+    }
+
+    BootInfo.dispDeviceBase = (PVOID)(device_address);
+
+    display_size = BootInfo.dispDeviceRowBytes * BootInfo.dispDeviceRect[3];
+
+    printf("Display size is %x bytes (%x per row times %x rows)\n",
+          display_size, 
+          BootInfo.dispDeviceRowBytes,
+          BootInfo.dispDeviceRect[3]);
+
+    printf("display is at %x\n", BootInfo.dispDeviceBase);
+
+    for( i = 0; i < logo_y * logo_scale_y; i++ ) {
+       for( j = 0; j < logo_x * logo_scale_x; j++ ) {
+           elts = (j/logo_scale_x) + ((i/logo_scale_y) * logo_x);
+
+           for( k = 0; k < BootInfo.dispDeviceDepth/8; k++ ) {
+               SetPhysByte(((ULONG_PTR)BootInfo.dispDeviceBase)+
+                           k +
+                           ((j * (BootInfo.dispDeviceDepth/8)) + 
+                            (i * (BootInfo.dispDeviceRowBytes))),
+                           logo[elts] == ' ' ? 0 : 255);
+           }
+       }
+    }
+}
+
+/* 
+ * Get memory the proper openfirmware way
  */
 ULONG PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap,
                        ULONG MaxMemoryMapSize ) {
-    printf("GetMemoryMap(chosen=%x)\n", chosen_package);
+    int i, memhandle, returned, total = 0, slots = 0;
+    int memdata[0x40];
 
-    BiosMemoryMap[0].Type = BiosMemoryUsable;
-    BiosMemoryMap[0].BaseAddress = 0;
-    BiosMemoryMap[0].Length = 32 * 1024 * 1024; /* Assume 32 meg for now */
+    printf("PpcGetMemoryMap(%d)\n", MaxMemoryMapSize);
 
-    printf( "Returning memory map (%dk total)\n", 
-            (int)BiosMemoryMap[0].Length / 1024 );
+    memhandle = ofw_finddevice("/memory");
 
-    return 1;
+    returned = ofw_getprop(memhandle, "available", 
+                          (char *)memdata, sizeof(memdata));
+
+    printf("Returned data: %d\n", returned);
+    if( returned == -1 ) {
+       printf("getprop /memory[@reg] failed\n");
+       return 0;
+    }
+
+    for( i = 0; i < returned; i++ ) {
+       printf("%x ", memdata[i]);
+    }
+    printf("\n");
+
+    for( i = 0; i < returned / 2; i++ ) {
+       BiosMemoryMap[slots].Type = 1/*MEMTYPE_USABLE*/;
+       BiosMemoryMap[slots].BaseAddress = memdata[i*2];
+       BiosMemoryMap[slots].Length = memdata[i*2+1];
+       printf("MemoryMap[%d] = (%x:%x)\n", 
+              i, 
+              (int)BiosMemoryMap[slots].BaseAddress,
+              (int)BiosMemoryMap[slots].Length);
+
+       /* Hack for pearpc */
+       if( kernel_mem ) {
+           BiosMemoryMap[slots].Length = kernel_mem * 1024;
+           if( !FixedMemory ) {
+               ofw_claim((int)BiosMemoryMap[slots].BaseAddress,
+                         (int)BiosMemoryMap[slots].Length,
+                         0x1000);
+               FixedMemory = BiosMemoryMap[slots].BaseAddress;
+           }
+           total += BiosMemoryMap[slots].Length;
+           slots++;
+           break;
+       /* Normal way */
+       } else if( BiosMemoryMap[slots].Length &&
+                  ofw_claim((int)BiosMemoryMap[slots].BaseAddress,
+                            (int)BiosMemoryMap[slots].Length,
+                            0x1000) ) {
+           total += BiosMemoryMap[slots].Length;
+           slots++;
+       }
+    }
+
+    printf( "Returning memory map (%dk total)\n", total / 1024 );
+
+    return slots;
 }
 
 /* Strategy:
@@ -288,7 +371,14 @@ BOOLEAN PpcDiskGetSystemVolume( char *SystemPath,
                              PULONGLONG StartSector, 
                              PULONGLONG SectorCount, 
                              int *FsType ) {
-    return FALSE;
+    char *remain = strchr(SystemPath, '\\');
+    if( remain ) {
+       strcpy( RemainingPath, remain+1 );
+    } else {
+       RemainingPath[0] = 0;
+    }
+    *Device = 0;
+    return MachDiskGetBootVolume(DriveNumber, StartSector, SectorCount, FsType);
 }
 
 BOOLEAN PpcDiskGetBootPath( char *OutBootPath, unsigned Size ) {
@@ -305,7 +395,7 @@ BOOLEAN PpcDiskBootingFromFloppy(VOID) {
 }
 
 BOOLEAN PpcDiskReadLogicalSectors( ULONG DriveNumber, ULONGLONG SectorNumber,
-                                ULONG SectorCount, PVOID Buffer ) {
+                                  ULONG SectorCount, PVOID Buffer ) {
     int rlen = 0;
 
     if( part_handle == -1 ) {
@@ -322,11 +412,14 @@ BOOLEAN PpcDiskReadLogicalSectors( ULONG DriveNumber, ULONGLONG SectorNumber,
        return FALSE;
     }
 
-    if( ofw_seek( part_handle, SectorNumber * 512 ) ) {
-       printf("Seek to %x failed\n", SectorNumber * 512);
+    if( ofw_seek( part_handle, 
+                  (ULONG)(SectorNumber >> 25), 
+                  (ULONG)((SectorNumber * 512) & 0xffffffff) ) ) {
+       printf("Seek to %x failed\n", (ULONG)(SectorNumber * 512));
        return FALSE;
     }
-    rlen = ofw_read( part_handle, Buffer, SectorCount * 512 );
+
+    rlen = ofw_read( part_handle, Buffer, (ULONG)(SectorCount * 512) );
     return rlen > 0;
 }
 
@@ -351,31 +444,75 @@ ULONG PpcDiskGetCacheableBlockCount( ULONG DriveNumber ) {
 
 VOID PpcRTCGetCurrentDateTime( PULONG Hear, PULONG Month, PULONG Day, 
                                PULONG Hour, PULONG Minute, PULONG Second ) {
-    printf("RTCGeturrentDateTime\n");
+    //printf("RTCGeturrentDateTime\n");
 }
 
 VOID PpcHwDetect() {
     printf("PpcHwDetect\n");
 }
 
-typedef unsigned int uint32_t;
+BOOLEAN PpcDiskNormalizeSystemPath(char *SystemPath, unsigned Size) {
+       CHAR BootPath[256];
+       ULONG PartitionNumber;
+       ULONG DriveNumber;
+       PARTITION_TABLE_ENTRY PartEntry;
+       char *p;
 
-void PpcInit( of_proxy the_ofproxy ) {
-    int len;
-    ofproxy = the_ofproxy;
+       if (!DissectArcPath(SystemPath, BootPath, &DriveNumber, &PartitionNumber))
+       {
+               return FALSE;
+       }
 
+       if (0 != PartitionNumber)
+       {
+               return TRUE;
+       }
+
+       if (! DiskGetActivePartitionEntry(DriveNumber,
+                                         &PartEntry,
+                                         &PartitionNumber) ||
+           PartitionNumber < 1 || 9 < PartitionNumber)
+       {
+               return FALSE;
+       }
+
+       p = SystemPath;
+       while ('\0' != *p && 0 != _strnicmp(p, "partition(", 10)) {
+               p++;
+       }
+       p = strchr(p, ')');
+       if (NULL == p || '0' != *(p - 1)) {
+               return FALSE;
+       }
+       *(p - 1) = '0' + PartitionNumber;
+
+       return TRUE;
+}
+
+extern int _bss;
+typedef unsigned int uint32_t;
+
+void PpcOfwInit()
+{
     chosen_package = ofw_finddevice( "/chosen" );
 
+    ofw_getprop(chosen_package, "bootargs",
+               CmdLine, sizeof(CmdLine));
     ofw_getprop( chosen_package, "stdin",
-                 &stdin_handle, sizeof(stdin_handle) );
+                (char *)&stdin_handle, sizeof(stdin_handle) );
+    ofw_getprop( chosen_package, "stdout",
+                (char *)&stdout_handle, sizeof(stdout_handle) );
+    ofw_getprop( chosen_package, "mmu",
+                (char *)&mmu_handle, sizeof(mmu_handle) );
 
-    stdin_handle = REV(stdin_handle);
-
-    MachVtbl.ConsPutChar = PpcPutChar;
+    MachVtbl.ConsPutChar = PpcOfwPutChar;
     MachVtbl.ConsKbHit   = PpcConsKbHit;
     MachVtbl.ConsGetCh   = PpcConsGetCh;
-    
-    printf( "stdin_handle is %x\n", stdin_handle );
+
+    printf( "chosen_package %x, stdin_handle is %x\n", 
+           chosen_package, stdin_handle );
+    printf("virt2phys (0xe00000,D) -> %x\n", PpcVirt2phys(0xe00000,0));
+    printf("virt2phys (0xe01000,D) -> %x\n", PpcVirt2phys(0xe01000,0));
 
     MachVtbl.VideoClearScreen = PpcVideoClearScreen;
     MachVtbl.VideoSetDisplayMode = PpcVideoSetDisplayMode;
@@ -394,6 +531,7 @@ void PpcInit( of_proxy the_ofproxy ) {
 
     MachVtbl.GetMemoryMap = PpcGetMemoryMap;
 
+    MachVtbl.DiskNormalizeSystemPath = PpcDiskNormalizeSystemPath;
     MachVtbl.DiskGetBootVolume = PpcDiskGetBootVolume;
     MachVtbl.DiskGetSystemVolume = PpcDiskGetSystemVolume;
     MachVtbl.DiskGetBootPath = PpcDiskGetBootPath;
@@ -408,19 +546,27 @@ void PpcInit( of_proxy the_ofproxy ) {
 
     MachVtbl.HwDetect = PpcHwDetect;
 
-    printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
-
-    len = ofw_getprop(chosen_package, "bootargs",
-                     CmdLine, sizeof(CmdLine));
+    // Allow forcing prep for broken OFW
+    if(!strncmp(CmdLine, "bootprep", 8))
+    {
+       printf("Going to PREP init...\n");
+       PpcPrepInit();
+       return;
+    }
 
-    if( len < 0 ) len = 0;
-    CmdLine[len] = 0;
+    printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
 
     BootMain( CmdLine );
 }
 
+void PpcInit( of_proxy the_ofproxy ) {
+    ofproxy = the_ofproxy;
+    if(ofproxy) PpcOfwInit();
+    else PpcPrepInit();
+}
+
 void MachInit(const char *CmdLine) {
-    int len, i;
+    int i, len;
     char *sep;
 
     BootPart[0] = 0;
@@ -428,15 +574,19 @@ void MachInit(const char *CmdLine) {
 
     printf( "Determining boot device: [%s]\n", CmdLine );
 
-    printf( "Boot Args: %s\n", CmdLine );
     sep = NULL;
     for( i = 0; i < strlen(CmdLine); i++ ) {
        if( strncmp(CmdLine + i, "boot=", 5) == 0) {
            strcpy(BootPart, CmdLine + i + 5);
-           sep = strchr(BootPart, ' ');
+           sep = strchr(BootPart, ',');
            if( sep )
                *sep = 0;
-           break;
+           while(CmdLine[i] && CmdLine[i]!=',') i++;
+       }
+       if( strncmp(CmdLine + i, "mem=", 4) == 0) {
+           kernel_mem = atoi(CmdLine+i+4);
+           printf("Allocate %dk kernel memory\n", kernel_mem);
+           while(CmdLine[i] && CmdLine[i]!=',') i++;
        }
     }
 
@@ -464,10 +614,11 @@ void beep() {
 }
 
 UCHAR NTAPI READ_PORT_UCHAR(PUCHAR Address) {
-    return 0xff;
+    return GetPhysByte(((ULONG)Address)+0x80000000);
 }
 
 void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value) {
+    SetPhysByte(((ULONG)Address)+0x80000000, Value);
 }
 
 void DiskStopFloppyMotor() {
@@ -484,3 +635,7 @@ void BootNewLinuxKernel() {
 void ChainLoadBiosBootSectorCode() {
     ofw_exit();
 }
+
+void DbgBreakPoint() {
+    ofw_exit();
+}
index 23997df..17de0f6 100644 (file)
@@ -1,65 +1,74 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         Freeloader
- * FILE:            boot/freeldr/freeldr/multiboot.c
- * PURPOSE:         ReactOS Loader
- * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
+ *  FreeLoader
+ *  Copyright (C) 1998-2003  Brian Palmer  <brianp@sginet.com>
+ *  Copyright (C) 2005       Alex Ionescu  <alex@relsoft.net>
+ *
+ *  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.
  */
 
 #include <freeldr.h>
-#include <internal/powerpc/ke.h>
+#include <elf/elf.h>
+#include <elf/reactos.h>
+#include <of_call.h>
+#include "ppcboot.h"
+#include "ppcmmu/mmu.h"
+#include "compat.h"
+#include "ppcfont.h"
 
 #define NDEBUG
 #include <debug.h>
 
-/* Base Addres of Kernel in Physical Memory */
-#define KERNEL_BASE_PHYS 0x200000
+PVOID KernelMemory = 0;
+extern boot_infos_t BootInfo;
 
 /* Bits to shift to convert a Virtual Address into an Offset in the Page Table */
 #define PFN_SHIFT 12
 
 /* Bits to shift to convert a Virtual Address into an Offset in the Page Directory */
-#define PDE_SHIFT 20
+#define PDE_SHIFT 22
 #define PDE_SHIFT_PAE 18
 
-  
-/* Converts a Relative Address read from the Kernel into a Physical Address */
-#define RaToPa(p) \
-    (ULONG_PTR)((ULONG_PTR)p + KERNEL_BASE_PHYS)
-   
-/* Converts a Phsyical Address Pointer into a Page Frame Number */
-#define PaPtrToPfn(p) \
-    (((ULONG_PTR)&p) >> PFN_SHIFT)
-    
-/* Converts a Phsyical Address into a Page Frame Number */
-#define PaToPfn(p) \
-    ((p) >> PFN_SHIFT)
-
-#define STARTUP_BASE                0xF0000000
-#define HYPERSPACE_BASE             0xF0800000
+#define STARTUP_BASE                0xC0000000
+#define HYPERSPACE_BASE             0xC0400000
+#define HYPERSPACE_PAE_BASE         0xC0800000
 #define APIC_BASE                   0xFEC00000
 #define KPCR_BASE                   0xFF000000
-    
+
 #define LowMemPageTableIndex        0
-#define StartupPageTableIndex       (STARTUP_BASE >> 20)    / sizeof(HARDWARE_PTE_X86)
-#define HyperspacePageTableIndex    (HYPERSPACE_BASE >> 20) / sizeof(HARDWARE_PTE_X86)
-#define KpcrPageTableIndex          (KPCR_BASE >> 20)       / sizeof(HARDWARE_PTE_X86)
-#define ApicPageTableIndex          (APIC_BASE >> 20)       / sizeof(HARDWARE_PTE_X86)
+#define StartupPageTableIndex       (STARTUP_BASE >> 22)
+#define HyperspacePageTableIndex    (HYPERSPACE_BASE >> 22)
+#define KpcrPageTableIndex          (KPCR_BASE >> 22)
+#define ApicPageTableIndex          (APIC_BASE >> 22)
 
 #define LowMemPageTableIndexPae     0
 #define StartupPageTableIndexPae    (STARTUP_BASE >> 21)
-#define HyperspacePageTableIndexPae (HYPERSPACE_BASE >> 21)
+#define HyperspacePageTableIndexPae (HYPERSPACE_PAE_BASE >> 21)
 #define KpcrPageTableIndexPae       (KPCR_BASE >> 21)
 #define ApicPageTableIndexPae       (APIC_BASE >> 21)
 
 
+#define BAT_GRANULARITY             (64 * 1024)
+#define KernelMemorySize            (8 * 1024 * 1024)
 #define KernelEntryPoint            (KernelEntry - KERNEL_BASE_PHYS) + KernelBase
+#define XROUNDUP(x,n)               ((((ULONG)x) + ((n) - 1)) & (~((n) - 1)))
 
 /* Load Address of Next Module */
 ULONG_PTR NextModuleBase = 0;
 
 /* Currently Opened Module */
-VOID *CurrentModule = NULL;
+PLOADER_MODULE CurrentModule = NULL;
 
 /* Unrelocated Kernel Base in Virtual Memory */
 ULONG_PTR KernelBase;
@@ -70,10 +79,22 @@ BOOLEAN PaeModeEnabled;
 /* Kernel Entrypoint in Physical Memory */
 ULONG_PTR KernelEntry;
 
+/* Dummy to bring in memmove */
+PVOID memmove_dummy = memmove;
+
+PLOADER_MODULE
+NTAPI
+LdrGetModuleObject(PCHAR ModuleName);
+
+NTSTATUS
+NTAPI
+LdrPEFixupImports(IN PVOID DllBase,
+                  IN PCHAR DllName);
+
 /* FUNCTIONS *****************************************************************/
 
 /*++
- * FrLdrStartup 
+ * FrLdrStartup
  * INTERNAL
  *
  *     Prepares the system for loading the Kernel.
@@ -88,24 +109,128 @@ ULONG_PTR KernelEntry;
  *     None.
  *
  *--*/
+
+typedef void (*KernelEntryFn)( void * );
+
+int MmuPageMiss(int inst, ppc_trap_frame_t *trap)
+{
+    int i;
+    printf("inst %x\n", inst);
+    for( i = 0; i < 40; i++ )
+       printf("r[%d] %x\n", i, trap->gpr[i]);
+    printf("HALT!\n");
+    while(1);
+}
+
 VOID
 NTAPI
 FrLdrStartup(ULONG Magic)
-{   
-#if 0   
-    /* Disable Interrupts */
-    KeArchDisableInterrupts();
-    
-    /* Re-initalize EFLAGS */
-    KeArchEraseFlags();
-    
-    /* Initialize the page directory */
-    FrLdrSetupPageDirectory();
-#endif
+{
+    KernelEntryFn KernelEntryAddress = 
+       (KernelEntryFn)(KernelEntry + KernelBase);
+    ULONG_PTR i, j, page, count;
+    PCHAR ModHeader;
+    boot_infos_t *LocalBootInfo = &BootInfo;
+    LocalBootInfo->dispFont = (font_char *)&LocalBootInfo[1];
+    LoaderBlock.ArchExtra = (ULONG)LocalBootInfo;
+    ppc_map_info_t *info = MmAllocateMemory(0x80 * sizeof(*info));
+
+    for(i = 0; i < LoaderBlock.ModsCount; i++)
+    {
+       ModHeader = ((PCHAR)reactos_modules[i].ModStart);
+       if(ModHeader[0] == 'M' && ModHeader[1] == 'Z')
+           LdrPEFixupImports
+               ((PVOID)reactos_modules[i].ModStart,
+                (PCHAR)reactos_modules[i].String);
+    }
+
+    /* We'll use vsid 1 for freeldr (expendable) */
+    MmuAllocVsid(1, 0xff);
+    MmuSetVsid(0, 8, 1);
+
+    MmuAllocVsid(0, 0xff00);
+    MmuSetVsid(8, 16, 0);
+
+    MmuSetPageCallback(MmuPageMiss);
+
+    info = MmAllocateMemory((KernelMemorySize >> PAGE_SHIFT) * sizeof(*info));
+
+    /* Map kernel space 0x80000000 ... */
+    for( i = (ULONG)KernelMemory, page = 0; 
+        i < (ULONG)KernelMemory + KernelMemorySize; 
+        i += (1<<PFN_SHIFT), page++ ) {
+       info[page].proc = 0;
+       info[page].addr = KernelBase + (page << PAGE_SHIFT);
+       info[page].phys = i; //PpcVirt2phys(i, 1);
+       info[page].flags = MMU_ALL_RW;
+    }
+
+    MmuMapPage(info, page);
+
+    /* Map module name strings */
+    for( count = 0, i = 0; i < LoaderBlock.ModsCount; i++ )
+    {
+       page = ROUND_DOWN(((ULONG)reactos_modules[i].String), (1<<PFN_SHIFT));
+       for( j = 0; j < count; j++ )
+       {
+           if(info[j].addr == page) break;
+       }
+       if( j != count )
+       {
+           info[count].flags = MMU_ALL_RW;
+           info[count].proc = 1;
+           info[count].addr = page;
+           info[count].phys = page; // PpcVirt2phys(page, 0);
+           count++;
+       }
+    }
+
+    page = ROUND_DOWN((vaddr_t)&LoaderBlock, (1 << PAGE_SHIFT));
+    for( j = 0; j < count; j++ )
+    {
+       if(info[j].addr == page) break;
+    }
+    if( j != count )
+    {
+       info[count].flags = MMU_ALL_RW;
+       info[count].proc = 1;
+       info[count].addr = page;
+       info[count].phys = page; // PpcVirt2phys(page, 0);
+       count++;
+    }
+    MmuMapPage(info, count);
+
+    MmuTurnOn(KernelEntryAddress, (void*)&LoaderBlock);
+
+    /* Nothing more */
+    while(1);
 }
 
 /*++
- * FrLdrGetKernelBase 
+ * FrLdrSetupPae
+ * INTERNAL
+ *
+ *     Configures PAE on a MP System, and sets the PDBR if it's supported, or if
+ *     the system is UP.
+ *
+ * Params:
+ *     Magic - Multiboot Magic
+ *
+ * Returns:
+ *     None.
+ *
+ * Remarks:
+ *     None.
+ *
+ *--*/
+VOID
+FASTCALL
+FrLdrSetupPae(ULONG Magic)
+{
+}
+
+/*++
+ * FrLdrGetKernelBase
  * INTERNAL
  *
  *     Gets the Kernel Base to use.
@@ -125,31 +250,57 @@ FASTCALL
 FrLdrGetKernelBase(VOID)
 {
     PCHAR p;
-     
+
+    /* Default kernel base at 2GB */
+    KernelBase = 0x80000000;
+
+    /* Set KernelBase */
+    LoaderBlock.KernelBase = KernelBase;
+
     /* Read Command Line */
     p = (PCHAR)LoaderBlock.CommandLine;
     while ((p = strchr(p, '/')) != NULL) {
-        
+
         /* Find "/3GB" */
-        if (!strnicmp(p + 1, "3GB", 3)) {
-            
+        if (!_strnicmp(p + 1, "3GB", 3)) {
+
             /* Make sure there's nothing following it */
             if (p[4] == ' ' || p[4] == 0) {
-                
+
                 /* Use 3GB */
-                KernelBase = 0xC0000000;
+                KernelBase = 0xE0000000;
+                LoaderBlock.KernelBase = 0xC0000000;
             }
         }
 
         p++;
     }
-          
-    /* Set KernelBase */
-    LoaderBlock.KernelBase = KernelBase;
 }
 
 /*++
- * FrLdrSetupPageDirectory 
+ * FrLdrGetPaeMode
+ * INTERNAL
+ *
+ *     Determines whether PAE mode shoudl be enabled or not.
+ *
+ * Params:
+ *     None.
+ *
+ * Returns:
+ *     None.
+ *
+ * Remarks:
+ *     None.
+ *
+ *--*/
+VOID
+FASTCALL
+FrLdrGetPaeMode(VOID)
+{
+}
+
+/*++
+ * FrLdrSetupPageDirectory
  * INTERNAL
  *
  *     Sets up the ReactOS Startup Page Directory.
@@ -169,199 +320,277 @@ VOID
 FASTCALL
 FrLdrSetupPageDirectory(VOID)
 {
-#if 0
-    PPAGE_DIRECTORY_X86 PageDir;
-    PPAGE_DIRECTORY_TABLE_X64 PageDirTablePae;
-    PPAGE_DIRECTORY_X64 PageDirPae;
-    ULONG KernelPageTableIndex;
-    ULONG i;
+}
 
-    if (PaeModeEnabled) {
+/*++
+ * FrLdrMapModule
+ * INTERNAL
+ *
+ *     Loads the indicated elf image as PE.  The target will appear to be
+ *     a PE image whose ImageBase has ever been KernelAddr.
+ *
+ * Params:
+ *     Image -- File to load
+ *     ImageName -- Name of image for the modules list
+ *     MemLoadAddr -- Freeldr address of module
+ *     KernelAddr -- Kernel address of module
+ *--*/
+#define ELF_SECTION(n) ((Elf32_Shdr*)(sptr + (n * shsize)))
+#define COFF_FIRST_SECTION(h) ((PIMAGE_SECTION_HEADER) ((DWORD)h+FIELD_OFFSET(IMAGE_NT_HEADERS,OptionalHeader)+(SWAPW(((PIMAGE_NT_HEADERS)(h))->FileHeader.SizeOfOptionalHeader))))
+
+BOOLEAN
+NTAPI
+FrLdrMapModule(FILE *KernelImage, PCHAR ImageName, PCHAR MemLoadAddr, ULONG KernelAddr)
+{
+    PIMAGE_DOS_HEADER ImageHeader = 0;
+    PIMAGE_NT_HEADERS NtHeader = 0;
+    PIMAGE_SECTION_HEADER Section;
+    ULONG SectionCount;
+    ULONG ImageSize;
+    INT i, j;
+    PLOADER_MODULE ModuleData;
+    int phsize, phnum, shsize, shnum, relsize, SectionAddr = 0;
+    PCHAR sptr;
+    Elf32_Ehdr ehdr;
+    Elf32_Shdr *shdr;
+    LPSTR TempName;
+
+    TempName = strrchr(ImageName, '\\');
+    if(TempName) TempName++; else TempName = (LPSTR)ImageName;
+    ModuleData = LdrGetModuleObject(TempName);
     
-        /* Get the Kernel Table Index */
-        KernelPageTableIndex = (KernelBase >> 21);
+    if(ModuleData) 
+    {
+       return TRUE;
+    }
 
-        /* Get the Startup Page Directory Table */
-        PageDirTablePae = (PPAGE_DIRECTORY_TABLE_X64)&startup_pagedirectorytable_pae;
+    if(!KernelAddr)
+       KernelAddr = (ULONG)NextModuleBase - (ULONG)KernelMemory + KernelBase;
+    if(!MemLoadAddr)
+       MemLoadAddr = (PCHAR)NextModuleBase;
 
-        /* Get the Startup Page Directory */
-        PageDirPae = (PPAGE_DIRECTORY_X64)&startup_pagedirectory_pae;
+    ModuleData = &reactos_modules[LoaderBlock.ModsCount];
+    printf("Loading file (elf at %x)\n", KernelAddr);
 
-        /* Set the Startup page directory table */
-        for (i = 0; i < 4; i++)
-        {
-            PageDirTablePae->Pde[i].Valid = 1;
-            PageDirTablePae->Pde[i].PageFrameNumber = PaPtrToPfn(startup_pagedirectory_pae) + i;
-        }
+    /* Load the first 1024 bytes of the kernel image so we can read the PE header */
+    if (!FsReadFile(KernelImage, sizeof(ehdr), NULL, &ehdr)) {
 
-        /* Set up the Low Memory PDE */
-        for (i = 0; i < 2; i++)
-        {
-            PageDirPae->Pde[LowMemPageTableIndexPae + i].Valid = 1;
-            PageDirPae->Pde[LowMemPageTableIndexPae + i].Write = 1;
-            PageDirPae->Pde[LowMemPageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(lowmem_pagetable_pae) + i;
-        }
+        /* Fail if we couldn't read */
+       printf("Couldn't read the elf header\n");
+        return FALSE;
+    }
 
-        /* Set up the Kernel PDEs */
-        for (i = 0; i < 3; i++)
-        {
-            PageDirPae->Pde[KernelPageTableIndex + i].Valid = 1;
-            PageDirPae->Pde[KernelPageTableIndex + i].Write = 1;
-            PageDirPae->Pde[KernelPageTableIndex + i].PageFrameNumber = PaPtrToPfn(kernel_pagetable_pae) + i;
-        }
-    
-        /* Set up the Startup PDE */
-        for (i = 0; i < 4; i++)
-        {
-            PageDirPae->Pde[StartupPageTableIndexPae + i].Valid = 1;
-            PageDirPae->Pde[StartupPageTableIndexPae + i].Write = 1;
-            PageDirPae->Pde[StartupPageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(startup_pagedirectory_pae) + i;
-        }
-    
-        /* Set up the Hyperspace PDE */
-        for (i = 0; i < 2; i++)
-        {
-            PageDirPae->Pde[HyperspacePageTableIndexPae + i].Valid = 1;
-            PageDirPae->Pde[HyperspacePageTableIndexPae + i].Write = 1;
-            PageDirPae->Pde[HyperspacePageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(hyperspace_pagetable_pae) + i;
-        }
-    
-        /* Set up the Apic PDE */   
-        for (i = 0; i < 2; i++)
-        {
-            PageDirPae->Pde[ApicPageTableIndexPae + i].Valid = 1;
-            PageDirPae->Pde[ApicPageTableIndexPae + i].Write = 1;
-            PageDirPae->Pde[ApicPageTableIndexPae + i].PageFrameNumber = PaPtrToPfn(apic_pagetable_pae) + i;
-        }
-        
-        /* Set up the KPCR PDE */
-        PageDirPae->Pde[KpcrPageTableIndexPae].Valid = 1;
-        PageDirPae->Pde[KpcrPageTableIndexPae].Write = 1;
-        PageDirPae->Pde[KpcrPageTableIndexPae].PageFrameNumber = PaPtrToPfn(kpcr_pagetable_pae);
-    
-        /* Set up Low Memory PTEs */
-        PageDirPae = (PPAGE_DIRECTORY_X64)&lowmem_pagetable_pae;
-        for (i=0; i<1024; i++) {
-        
-            PageDirPae->Pde[i].Valid = 1;
-            PageDirPae->Pde[i].Write = 1;
-            PageDirPae->Pde[i].Owner = 1;
-            PageDirPae->Pde[i].PageFrameNumber = i;
-        }
-            
-        /* Set up Kernel PTEs */
-        PageDirPae = (PPAGE_DIRECTORY_X64)&kernel_pagetable_pae;
-        for (i=0; i<1536; i++) {
-        
-            PageDirPae->Pde[i].Valid = 1;
-            PageDirPae->Pde[i].Write = 1;
-            PageDirPae->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS) + i;
-        }
-        
-        /* Set up APIC PTEs */
-        PageDirPae = (PPAGE_DIRECTORY_X64)&apic_pagetable_pae;
-        PageDirPae->Pde[0].Valid = 1;
-        PageDirPae->Pde[0].Write = 1;
-        PageDirPae->Pde[0].CacheDisable = 1;
-        PageDirPae->Pde[0].WriteThrough = 1;
-        PageDirPae->Pde[0].PageFrameNumber = PaToPfn(APIC_BASE);
-        PageDirPae->Pde[0x200].Valid = 1;
-        PageDirPae->Pde[0x200].Write = 1;
-        PageDirPae->Pde[0x200].CacheDisable = 1;
-        PageDirPae->Pde[0x200].WriteThrough = 1;
-        PageDirPae->Pde[0x200].PageFrameNumber = PaToPfn(APIC_BASE + KERNEL_BASE_PHYS);
-    
-        /* Set up KPCR PTEs */
-        PageDirPae = (PPAGE_DIRECTORY_X64)&kpcr_pagetable_pae;
-        PageDirPae->Pde[0].Valid = 1;
-        PageDirPae->Pde[0].Write = 1;
-        PageDirPae->Pde[0].PageFrameNumber = 1;      
-    
-    } else {
-            
-        /* Get the Kernel Table Index */
-        KernelPageTableIndex = (KernelBase >> PDE_SHIFT) / sizeof(HARDWARE_PTE_X86);
-        
-        /* Get the Startup Page Directory */
-        PageDir = (PPAGE_DIRECTORY_X86)&startup_pagedirectory;
-        
-        /* Set up the Low Memory PDE */
-        PageDir->Pde[LowMemPageTableIndex].Valid = 1;
-        PageDir->Pde[LowMemPageTableIndex].Write = 1;
-        PageDir->Pde[LowMemPageTableIndex].PageFrameNumber = PaPtrToPfn(lowmem_pagetable);
-    
-        /* Set up the Kernel PDEs */
-        PageDir->Pde[KernelPageTableIndex].Valid = 1;
-        PageDir->Pde[KernelPageTableIndex].Write = 1;
-        PageDir->Pde[KernelPageTableIndex].PageFrameNumber = PaPtrToPfn(kernel_pagetable);
-        PageDir->Pde[KernelPageTableIndex + 1].Valid = 1;
-        PageDir->Pde[KernelPageTableIndex + 1].Write = 1;
-        PageDir->Pde[KernelPageTableIndex + 1].PageFrameNumber = PaPtrToPfn(kernel_pagetable + 4096);
-        
-        /* Set up the Startup PDE */
-        PageDir->Pde[StartupPageTableIndex].Valid = 1;
-        PageDir->Pde[StartupPageTableIndex].Write = 1;
-        PageDir->Pde[StartupPageTableIndex].PageFrameNumber = PaPtrToPfn(startup_pagedirectory);
-        
-        /* Set up the Hyperspace PDE */
-        PageDir->Pde[HyperspacePageTableIndex].Valid = 1;
-        PageDir->Pde[HyperspacePageTableIndex].Write = 1;
-        PageDir->Pde[HyperspacePageTableIndex].PageFrameNumber = PaPtrToPfn(hyperspace_pagetable);
-    
-        /* Set up the Apic PDE */   
-        PageDir->Pde[ApicPageTableIndex].Valid = 1;
-        PageDir->Pde[ApicPageTableIndex].Write = 1;
-        PageDir->Pde[ApicPageTableIndex].PageFrameNumber = PaPtrToPfn(apic_pagetable);
-        
-        /* Set up the KPCR PDE */
-        PageDir->Pde[KpcrPageTableIndex].Valid = 1;
-        PageDir->Pde[KpcrPageTableIndex].Write = 1;
-        PageDir->Pde[KpcrPageTableIndex].PageFrameNumber = PaPtrToPfn(kpcr_pagetable);
-    
-        /* Set up Low Memory PTEs */
-        PageDir = (PPAGE_DIRECTORY_X86)&lowmem_pagetable;
-        for (i=0; i<1024; i++) {
-        
-            PageDir->Pde[i].Valid = 1;
-            PageDir->Pde[i].Write = 1;
-            PageDir->Pde[i].Owner = 1;
-            PageDir->Pde[i].PageFrameNumber = PaToPfn(i * PAGE_SIZE);
-        }
-        
-        /* Set up Kernel PTEs */
-        PageDir = (PPAGE_DIRECTORY_X86)&kernel_pagetable;
-        for (i=0; i<1536; i++) {
-        
-            PageDir->Pde[i].Valid = 1;
-            PageDir->Pde[i].Write = 1;
-            PageDir->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS + i * PAGE_SIZE);
+    /* Start by getting elf headers */
+    phsize = ehdr.e_phentsize;
+    phnum = ehdr.e_phnum;
+    shsize = ehdr.e_shentsize;
+    shnum = ehdr.e_shnum;
+    sptr = (PCHAR)MmAllocateMemory(shnum * shsize);
+
+    /* Read section headers */
+    FsSetFilePointer(KernelImage,  ehdr.e_shoff);
+    FsReadFile(KernelImage, shsize * shnum, NULL, sptr);
+
+    printf("Loaded section headers\n");
+
+    /* Now we'll get the PE Header */
+    for( i = 0; i < shnum; i++ ) 
+    {
+       shdr = ELF_SECTION(i);
+       shdr->sh_addr = 0;
+
+       /* Find the PE Header */
+       if (shdr->sh_type == TYPE_PEHEADER)
+       {
+           FsSetFilePointer(KernelImage, shdr->sh_offset);
+           FsReadFile(KernelImage, shdr->sh_size, NULL, MemLoadAddr);
+           ImageHeader = (PIMAGE_DOS_HEADER)MemLoadAddr;
+           NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)MemLoadAddr + SWAPD(ImageHeader->e_lfanew));
+           printf("NtHeader at %x\n", SWAPD(ImageHeader->e_lfanew));
+           printf("SectionAlignment %x\n", 
+                  SWAPD(NtHeader->OptionalHeader.SectionAlignment));
+           SectionAddr = ROUND_UP
+               (shdr->sh_size, SWAPD(NtHeader->OptionalHeader.SectionAlignment));
+           printf("Header ends at %x\n", SectionAddr);
+           break;
+       }
+    }
+
+    if(i == shnum) 
+    {
+       printf("No peheader section encountered :-(\n");
+       return 0;
+    }
+
+    /* Save the Image Base */
+    NtHeader->OptionalHeader.ImageBase = SWAPD(KernelAddr);
+
+    /* Load the file image */
+    Section = COFF_FIRST_SECTION(NtHeader);
+    SectionCount = SWAPW(NtHeader->FileHeader.NumberOfSections);
+
+    printf("Section headers at %x\n", Section);
+
+    /* Walk each section */
+    for (i=0; i < SectionCount; i++, Section++)
+    {
+       shdr = ELF_SECTION((SWAPD(Section->PointerToRawData)+1));
+
+       shdr->sh_addr = SectionAddr = SWAPD(Section->VirtualAddress);
+       shdr->sh_addr += KernelAddr;
+
+       Section->PointerToRawData = SWAPD((Section->VirtualAddress - KernelAddr));
+
+       if (shdr->sh_type != SHT_NOBITS)
+       {
+           /* Content area */
+           printf("Loading section %d at %x (real: %x:%d)\n", i, KernelAddr + SectionAddr, MemLoadAddr+SectionAddr, shdr->sh_size);
+           FsSetFilePointer(KernelImage, shdr->sh_offset);
+           FsReadFile(KernelImage, shdr->sh_size, NULL, MemLoadAddr + SectionAddr);
+       } 
+       else
+       {
+           /* Zero it out */
+           printf("BSS section %d at %x\n", i, KernelAddr + SectionAddr);
+           memset(MemLoadAddr + SectionAddr, 0, 
+                  ROUND_UP(shdr->sh_size, 
+                           SWAPD(NtHeader->OptionalHeader.SectionAlignment)));
         }
-        
-        /* Set up APIC PTEs */
-        PageDir = (PPAGE_DIRECTORY_X86)&apic_pagetable;
-        PageDir->Pde[0].Valid = 1;
-        PageDir->Pde[0].Write = 1;
-        PageDir->Pde[0].CacheDisable = 1;
-        PageDir->Pde[0].WriteThrough = 1;
-        PageDir->Pde[0].PageFrameNumber = PaToPfn(APIC_BASE);
-        PageDir->Pde[0x200].Valid = 1;
-        PageDir->Pde[0x200].Write = 1;
-        PageDir->Pde[0x200].CacheDisable = 1;
-        PageDir->Pde[0x200].WriteThrough = 1;
-        PageDir->Pde[0x200].PageFrameNumber = PaToPfn(APIC_BASE + KERNEL_BASE_PHYS);
-    
-        /* Set up KPCR PTEs */
-        PageDir = (PPAGE_DIRECTORY_X86)&kpcr_pagetable;
-        PageDir->Pde[0].Valid = 1;
-        PageDir->Pde[0].Write = 1;
-        PageDir->Pde[0].PageFrameNumber = 1;      
     }
-    return;
+
+    ImageSize = SWAPD(NtHeader->OptionalHeader.SizeOfImage);
+    KernelEntry = SWAPD(NtHeader->OptionalHeader.AddressOfEntryPoint);
+    printf("Total image size is %x\n", ImageSize);
+    
+    /* Handle relocation sections */
+    for (i = 0; i < shnum; i++) {
+       Elf32_Rela reloc = { };
+       ULONG *Target32, x;
+       USHORT *Target16;
+       int numreloc, relstart, targetSection;
+       Elf32_Sym symbol;
+       PCHAR RelocSection, SymbolSection;
+       
+       shdr = ELF_SECTION(i);
+       /* Only relocs here */
+       if((shdr->sh_type != SHT_REL) &&
+          (shdr->sh_type != SHT_RELA)) continue;
+       
+       relstart = shdr->sh_offset;
+       relsize = shdr->sh_type == SHT_RELA ? 12 : 8;
+       numreloc = shdr->sh_size / relsize;
+       targetSection = shdr->sh_info;
+
+       if (!ELF_SECTION(targetSection)->sh_addr) continue;
+
+       RelocSection = MmAllocateMemory(shdr->sh_size);
+       FsSetFilePointer(KernelImage, relstart);
+       FsReadFile(KernelImage, shdr->sh_size, NULL, RelocSection);
+
+       /* Get the symbol section */
+       shdr = ELF_SECTION(shdr->sh_link);
+
+       SymbolSection = MmAllocateMemory(shdr->sh_size);
+       FsSetFilePointer(KernelImage, shdr->sh_offset);
+       FsReadFile(KernelImage, shdr->sh_size, NULL, SymbolSection);
+
+       for(j = 0; j < numreloc; j++)
+       {
+           ULONG S,A,P;
+           
+           /* Get the reloc */
+           memcpy(&reloc, RelocSection + (j * relsize), sizeof(reloc));
+
+           /* Get the symbol */
+           memcpy(&symbol, SymbolSection + (ELF32_R_SYM(reloc.r_info) * sizeof(symbol)), sizeof(symbol));
+
+           /* Compute addends */
+           S = symbol.st_value + ELF_SECTION(symbol.st_shndx)->sh_addr;
+           A = reloc.r_addend;
+           P = reloc.r_offset + ELF_SECTION(targetSection)->sh_addr;
+
+#if 0
+           printf("Symbol[%d] %d -> %d(%x:%x) -> %x(+%x)@%x\n",
+                  ELF32_R_TYPE(reloc.r_info),
+                  ELF32_R_SYM(reloc.r_info), 
+                  symbol.st_shndx, 
+                  ELF_SECTION(symbol.st_shndx)->sh_addr,
+                  symbol.st_value,
+                  S,
+                  A,
+                  P);
 #endif
+
+           Target32 = (ULONG*)(((PCHAR)MemLoadAddr) + (P - KernelAddr));
+           Target16 = (USHORT *)Target32;
+           x = *Target32;
+           
+           switch (ELF32_R_TYPE(reloc.r_info))
+           {
+           case R_PPC_NONE:
+               break;
+           case R_PPC_ADDR32:
+               *Target32 = S + A;
+               break;
+           case R_PPC_REL32:
+               *Target32 = S + A - P;
+               break;
+           case R_PPC_UADDR32: /* Special: Treat as RVA */
+               *Target32 = S + A - KernelAddr;
+               break;
+           case R_PPC_ADDR24:
+               *Target32 = (ADDR24_MASK & (S+A)) | (*Target32 & ~ADDR24_MASK);
+               break;
+           case R_PPC_REL24:
+               *Target32 = (ADDR24_MASK & (S+A-P)) | (*Target32 & ~ADDR24_MASK);
+               break;
+           case R_PPC_ADDR16_LO:
+               *Target16 = S + A;
+               break;
+           case R_PPC_ADDR16_HA:
+               *Target16 = (S + A + 0x8000) >> 16;
+               break;
+           default:
+               break;
+           }
+           
+#if 0
+           printf("reloc[%d:%x]: (type %x sym %d val %d) off %x add %x (old %x new %x)\n", 
+                  j,
+                  ((ULONG)Target32) - ((ULONG)MemLoadAddr),
+                  ELF32_R_TYPE(reloc.r_info),
+                  ELF32_R_SYM(reloc.r_info), 
+                  symbol.st_value,
+                  reloc.r_offset, reloc.r_addend,
+                  x, *Target32);           
+#endif
+       }
+
+       MmFreeMemory(SymbolSection);
+       MmFreeMemory(RelocSection);
+    }
+
+    MmFreeMemory(sptr);
+
+    ModuleData->ModStart = (ULONG)MemLoadAddr;
+    /* Increase the next Load Base */
+    NextModuleBase = ROUND_UP((ULONG)MemLoadAddr + ImageSize, PAGE_SIZE);
+    ModuleData->ModEnd = NextModuleBase;
+    ModuleData->String = (ULONG)MmAllocateMemory(strlen(ImageName)+1);
+    strcpy((PCHAR)ModuleData->String, ImageName);
+    printf("Module %s (%x-%x) next at %x\n",
+          ModuleData->String, 
+          ModuleData->ModStart,
+          ModuleData->ModEnd,
+          NextModuleBase);
+    LoaderBlock.ModsCount++;
+
+    /* Return Success */
+    return TRUE;
 }
 
 /*++
- * FrLdrMapKernel 
+ * FrLdrMapKernel
  * INTERNAL
  *
  *     Maps the Kernel into memory, does PE Section Mapping, initalizes the
@@ -381,207 +610,63 @@ BOOLEAN
 NTAPI
 FrLdrMapKernel(FILE *KernelImage)
 {
-#if 0
-    PIMAGE_DOS_HEADER ImageHeader;
-    PIMAGE_NT_HEADERS NtHeader;
-    PIMAGE_SECTION_HEADER Section;
-    ULONG SectionCount;
-    ULONG ImageSize;
-    ULONG_PTR SourceSection;
-    ULONG_PTR TargetSection;
-    ULONG SectionSize;
-    LONG i;
-    PIMAGE_DATA_DIRECTORY RelocationDDir;
-    PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
-    ULONG Count;
-    ULONG_PTR Address, MaxAddress;
-    PUSHORT TypeOffset;
-    ULONG_PTR Delta;
-    PUSHORT ShortPtr;
-    PULONG LongPtr;
-
-    /* Allocate 1024 bytes for PE Header */
-    ImageHeader = (PIMAGE_DOS_HEADER)MmAllocateMemory(1024);
-    
-    /* Make sure it was succesful */
-    if (ImageHeader == NULL) {
-        
-        return FALSE;
-    }
-
-    /* Load the first 1024 bytes of the kernel image so we can read the PE header */
-    if (!FsReadFile(KernelImage, 1024, NULL, ImageHeader)) {
-
-        /* Fail if we couldn't read */
-        MmFreeMemory(ImageHeader);
-        return FALSE;
-    }
-
-    /* Now read the MZ header to get the offset to the PE Header */
-    NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)ImageHeader + ImageHeader->e_lfanew);
-     
     /* Get Kernel Base */
-    KernelBase = NtHeader->OptionalHeader.ImageBase;  
     FrLdrGetKernelBase();
-    
-    /* Save Entrypoint */
-    KernelEntry = RaToPa(NtHeader->OptionalHeader.AddressOfEntryPoint);
-    
-    /* Save the Image Size */
-    ImageSize = NtHeader->OptionalHeader.SizeOfImage;
-     
-    /* Free the Header */
-    MmFreeMemory(ImageHeader);
-
-    /* Set the file pointer to zero */
-    FsSetFilePointer(KernelImage, 0);
 
-    /* Load the file image */
-    FsReadFile(KernelImage, ImageSize, NULL, (PVOID)KERNEL_BASE_PHYS);
-    
-    /* Reload the NT Header */
-    NtHeader = (PIMAGE_NT_HEADERS)((PCHAR)KERNEL_BASE_PHYS + ImageHeader->e_lfanew);
-    
-    /* Load the first section */
-    Section = IMAGE_FIRST_SECTION(NtHeader);
-    SectionCount = NtHeader->FileHeader.NumberOfSections - 1;
-    
-    /* Now go to the last section */
-    Section += SectionCount;
-    
-    /* Walk each section backwards */    
-    for (i=SectionCount; i >= 0; i--, Section--) {
-    
-        /* Get the disk location and the memory location, and the size */          
-        SourceSection = RaToPa(Section->PointerToRawData);
-        TargetSection = RaToPa(Section->VirtualAddress);
-        SectionSize = Section->SizeOfRawData;
-   
-        /* If the section is already mapped correctly, go to the next */
-        if (SourceSection == TargetSection) continue;
-        
-        /* Load it into memory */
-        memmove((PVOID)TargetSection, (PVOID)SourceSection, SectionSize);
-        
-        /* Check for unitilizated data */
-        if (Section->SizeOfRawData < Section->Misc.VirtualSize) {
-            
-            /* Zero it out */
-            memset((PVOID)RaToPa(Section->VirtualAddress + Section->SizeOfRawData), 
-                   0,
-                   Section->Misc.VirtualSize - Section->SizeOfRawData);
-        }
-    }
-       
-    /* Get the Relocation Data Directory */
-    RelocationDDir = &NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
-    
-    /* Get the Relocation Section Start and End*/
-    RelocationDir = (PIMAGE_BASE_RELOCATION)(KERNEL_BASE_PHYS + RelocationDDir->VirtualAddress);
-    RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDDir->Size);
-   
-    /* Calculate Difference between Real Base and Compiled Base*/
-    Delta = KernelBase - NtHeader->OptionalHeader.ImageBase;;
-    
-    /* Determine how far we shoudl relocate */
-    MaxAddress = KERNEL_BASE_PHYS + ImageSize;
-    
-    /* Relocate until we've processed all the blocks */
-    while (RelocationDir < RelocationEnd && RelocationDir->SizeOfBlock > 0) {
-        
-        /* See how many Relocation Blocks we have */
-        Count = (RelocationDir->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
-        
-        /* Calculate the Address of this Directory */
-        Address = KERNEL_BASE_PHYS + RelocationDir->VirtualAddress;
-        
-        /* Calculate the Offset of the Type */
-        TypeOffset = (PUSHORT)(RelocationDir + 1);
-
-        for (i = 0; i < Count; i++) {
-            
-            ShortPtr = (PUSHORT)(Address + (*TypeOffset & 0xFFF));
-
-            /* Don't relocate after the end of the loaded driver */
-            if ((ULONG_PTR)ShortPtr >= MaxAddress) break;
-
-            switch (*TypeOffset >> 12) {
-                
-                case IMAGE_REL_BASED_ABSOLUTE:
-                    break;
-
-                case IMAGE_REL_BASED_HIGH:
-                    *ShortPtr += HIWORD(Delta);
-                    break;
-
-                case IMAGE_REL_BASED_LOW:
-                    *ShortPtr += LOWORD(Delta);
-                    break;
-
-                case IMAGE_REL_BASED_HIGHLOW:
-                    LongPtr = (PULONG)ShortPtr;
-                    *LongPtr += Delta;
-                    break;
-            }
-            
-            TypeOffset++;
-        }
-        
-        /* Move to the next Relocation Table */
-        RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + RelocationDir->SizeOfBlock);
-    }
-    
-    /* Increase the next Load Base */
-    NextModuleBase = ROUND_UP(KERNEL_BASE_PHYS + ImageSize, PAGE_SIZE);
+    /* Allocate kernel memory */
+    KernelMemory = MmAllocateMemory(KernelMemorySize);
+    printf("Kernel Memory @%x\n", (int)KernelMemory);
 
-    /* Return Success */
-#endif
-    return TRUE;
+    return FrLdrMapModule(KernelImage, "ntoskrnl.exe", KernelMemory, KernelBase);
 }
 
 ULONG_PTR
 NTAPI
-FrLdrLoadModule(FILE *ModuleImage, 
-                LPCSTR ModuleName, 
+FrLdrLoadModule(FILE *ModuleImage,
+                LPCSTR ModuleName,
                 PULONG ModuleSize)
 {
-#if 0
     ULONG LocalModuleSize;
-    PFRLDR_MODULE ModuleData;
+    PLOADER_MODULE ModuleData;
     LPSTR NameBuffer;
     LPSTR TempName;
 
     /* Get current module data structure and module name string array */
-    ModuleData = &multiboot_modules[LoaderBlock.ModsCount];
-    
+    ModuleData = &reactos_modules[LoaderBlock.ModsCount];
+
     /* Get only the Module Name */
     do {
-        
+
         TempName = strchr(ModuleName, '\\');
-        
+
         if(TempName) {
             ModuleName = TempName + 1;
         }
 
     } while(TempName);
-    NameBuffer = multiboot_module_strings[LoaderBlock.ModsCount];
+    NameBuffer = reactos_module_strings[LoaderBlock.ModsCount];
 
     /* Get Module Size */
     LocalModuleSize = FsGetFileSize(ModuleImage);
-    
+
     /* Fill out Module Data Structure */
-    ModuleData->ModuleStart = NextModuleBase;
-    ModuleData->ModuleEnd = NextModuleBase + LocalModuleSize;
-    
+    ModuleData->ModStart = NextModuleBase;
+    ModuleData->ModEnd = NextModuleBase + LocalModuleSize;
+
+    printf("Module size %x len %x name %s\n", 
+          ModuleData->ModStart,
+          ModuleData->ModEnd - ModuleData->ModStart,
+          ModuleName);
+
     /* Save name */
     strcpy(NameBuffer, ModuleName);
-    ModuleData->ModuleName = NameBuffer;
+    ModuleData->String = (ULONG_PTR)NameBuffer;
 
     /* Load the file image */
     FsReadFile(ModuleImage, LocalModuleSize, NULL, (PVOID)NextModuleBase);
 
     /* Move to next memory block and increase Module Count */
-    NextModuleBase = ROUND_UP(ModuleData->ModuleEnd, PAGE_SIZE);
+    NextModuleBase = ROUND_UP(ModuleData->ModEnd, PAGE_SIZE);
     LoaderBlock.ModsCount++;
 
     /* Return Module Size if required */
@@ -589,63 +674,55 @@ FrLdrLoadModule(FILE *ModuleImage,
         *ModuleSize = LocalModuleSize;
     }
 
-    return(ModuleData->ModuleStart);
-#else
-    return 0;
-#endif
+    return(ModuleData->ModStart);
 }
 
 ULONG_PTR
 NTAPI
 FrLdrCreateModule(LPCSTR ModuleName)
 {
-#if 0
-    PFRLDR_MODULE ModuleData;
+    PLOADER_MODULE ModuleData;
     LPSTR NameBuffer;
 
     /* Get current module data structure and module name string array */
-    ModuleData = &multiboot_modules[LoaderBlock.ModsCount];
-    NameBuffer = multiboot_module_strings[LoaderBlock.ModsCount];
+    ModuleData = &reactos_modules[LoaderBlock.ModsCount];
+    NameBuffer = reactos_module_strings[LoaderBlock.ModsCount];
 
     /* Set up the structure */
-    ModuleData->ModuleStart = NextModuleBase;
-    ModuleData->ModuleEnd = -1;
-    
+    ModuleData->ModStart = NextModuleBase;
+    ModuleData->ModEnd = -1;
+
     /* Copy the name */
     strcpy(NameBuffer, ModuleName);
-    ModuleData->ModuleName = NameBuffer;
+    ModuleData->String = (ULONG_PTR)NameBuffer;
 
     /* Set the current Module */
     CurrentModule = ModuleData;
 
     /* Return Module Base Address */
-    return(ModuleData->ModuleStart);
-#else
-    return 0;
-#endif
+    return(ModuleData->ModStart);
 }
 
 BOOLEAN
 NTAPI
-FrLdrCloseModule(ULONG_PTR ModuleBase, 
+FrLdrCloseModule(ULONG_PTR ModuleBase,
                  ULONG ModuleSize)
 {
-#if 0
-    PFRLDR_MODULE ModuleData = CurrentModule;
+    PLOADER_MODULE ModuleData = CurrentModule;
 
     /* Make sure a module is opened */
     if (ModuleData) {
-    
+
         /* Make sure this is the right module and that it hasn't been closed */
-        if ((ModuleBase == ModuleData->ModuleStart) && (ModuleData->ModuleEnd == -1)) {
-        
+        if ((ModuleBase == ModuleData->ModStart) && (ModuleData->ModEnd == (ULONG_PTR)-1)) {
+
             /* Close the Module */
-            ModuleData->ModuleEnd = ModuleData->ModuleStart + ModuleSize;
+            ModuleData->ModEnd = ModuleData->ModStart + ModuleSize;
 
             /* Set the next Module Base and increase the number of modules */
-            NextModuleBase = ROUND_UP(ModuleData->ModuleEnd, PAGE_SIZE);
+            NextModuleBase = ROUND_UP(ModuleData->ModEnd, PAGE_SIZE);
             LoaderBlock.ModsCount++;
-            
+
             /* Close the currently opened module */
             CurrentModule = NULL;
 
@@ -655,6 +732,5 @@ FrLdrCloseModule(ULONG_PTR ModuleBase,
     }
 
     /* Failure path */
-#endif
     return(FALSE);
 }
diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/mmu.c b/reactos/boot/freeldr/freeldr/arch/powerpc/mmu.c
new file mode 100644 (file)
index 0000000..18676a2
--- /dev/null
@@ -0,0 +1,398 @@
+#include <freeldr.h>
+#include "ppcmmu/mmu.h"
+
+inline int GetMSR() {
+    register int res asm ("r3");
+    __asm__("mfmsr 3");
+    return res;
+}
+
+inline int GetDEC() {
+    register int res asm ("r3");
+    __asm__("mfdec 3");
+    return res;
+}
+
+__asm__("\t.globl GetPhys\n"
+       "GetPhys:\t\n"
+       "mflr  0\n\t"
+       "stwu  0,-16(1)\n\t"
+       "mfmsr 5\n\t"
+       "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 GetPhysHalf\n"
+       "GetPhysHalf:\t\n"
+       "mflr  0\n\t"
+       "stwu  0,-16(1)\n\t"
+       "mfmsr 5\n\t"
+       "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"
+       "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"
+       "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 SetPhysHalf\n"
+       "SetPhysHalf:\t\n"
+       "mflr  0\n\t"
+       "stwu  0,-16(1)\n\t"
+       "mfmsr 5\n\t"
+       "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"
+       "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"
+    );
+
+inline int GetSR(int n) {
+    register int res asm ("r3");
+    switch( n ) {
+    case 0:
+       __asm__("mfsr 3,0");
+       break;
+    case 1:
+       __asm__("mfsr 3,1");
+       break;
+    case 2:
+       __asm__("mfsr 3,2");
+       break;
+    case 3:
+       __asm__("mfsr 3,3");
+       break;
+    case 4:
+       __asm__("mfsr 3,4");
+       break;
+    case 5:
+       __asm__("mfsr 3,5");
+       break;
+    case 6:
+       __asm__("mfsr 3,6");
+       break;
+    case 7:
+       __asm__("mfsr 3,7");
+       break;
+    case 8:
+       __asm__("mfsr 3,8");
+       break;
+    case 9:
+       __asm__("mfsr 3,9");
+       break;
+    case 10:
+       __asm__("mfsr 3,10");
+       break;
+    case 11:
+       __asm__("mfsr 3,11");
+       break;
+    case 12:
+       __asm__("mfsr 3,12");
+       break;
+    case 13:
+       __asm__("mfsr 3,13");
+       break;
+    case 14:
+       __asm__("mfsr 3,14");
+       break;
+    case 15:
+       __asm__("mfsr 3,15");
+       break;
+    }
+    return res;
+}
+
+inline void GetBat( int bat, int inst, int *batHi, int *batLo ) {
+    register int bh asm("r3"), bl asm("r4");
+    if( inst ) {
+       switch( bat ) {
+       case 0:
+           __asm__("mfibatu 3,0");
+           __asm__("mfibatl 4,0");
+           break;
+       case 1:
+           __asm__("mfibatu 3,1");
+           __asm__("mfibatl 4,1");
+           break;
+       case 2:
+           __asm__("mfibatu 3,2");
+           __asm__("mfibatl 4,2");
+           break;
+       case 3:
+           __asm__("mfibatu 3,3");
+           __asm__("mfibatl 4,3");
+           break;
+       }
+    } else {
+       switch( bat ) {
+       case 0:
+           __asm__("mfdbatu 3,0");
+           __asm__("mfdbatl 4,0");
+           break;
+       case 1:
+           __asm__("mfdbatu 3,1");
+           __asm__("mfdbatl 4,1");
+           break;
+       case 2:
+           __asm__("mfdbatu 3,2");
+           __asm__("mfdbatl 4,2");
+           break;
+       case 3:
+           __asm__("mfdbatu 3,3");
+           __asm__("mfdbatl 4,3");
+           break;
+       }
+    }
+    *batHi = bh;
+    *batLo = bl;
+}
+
+inline void SetBat( int bat, int inst, int batHi, int batLo ) {
+    register int bh asm("r3"), bl asm("r4");
+    bh = batHi;
+    bl = batLo;
+    if( inst ) {
+       switch( bat ) {
+       case 0:
+           __asm__("mtibatu 0,3");
+           __asm__("mtibatl 0,4");
+           break;
+       case 1:
+           __asm__("mtibatu 1,3");
+           __asm__("mtibatl 1,4");
+           break;
+       case 2:
+           __asm__("mtibatu 2,3");
+           __asm__("mtibatl 2,4");
+           break;
+       case 3:
+           __asm__("mtibatu 3,3");
+           __asm__("mtibatl 3,4");
+           break;
+       }
+    } else {
+       switch( bat ) {
+       case 0:
+           __asm__("mtdbatu 0,3");
+           __asm__("mtdbatl 0,4");
+           break;
+       case 1:
+           __asm__("mtdbatu 1,3");
+           __asm__("mtdbatl 1,4");
+           break;
+       case 2:
+           __asm__("mtdbatu 2,3");
+           __asm__("mtdbatl 2,4");
+           break;
+       case 3:
+           __asm__("mtdbatu 3,3");
+           __asm__("mtdbatl 3,4");
+           break;
+       }
+    }
+    __asm__("isync\n\tsync");
+}
+
+inline int GetSDR1() {
+    register int res asm("r3");
+    __asm__("mfsdr1 3");
+    return res;
+}
+
+inline void SetSDR1( int sdr ) {
+#if 0
+    int i,j;
+#endif
+    __asm__("mtsdr1 3");
+#if 0
+    __asm__("sync");
+    __asm__("isync");
+    __asm__("ptesync");
+    
+    for( i = 0; i < 256; i++ ) {
+       j = i << 12;
+       __asm__("tlbie %0,0" : : "r" (j));
+    }
+    __asm__("eieio");
+    __asm__("tlbsync");
+    __asm__("ptesync");
+#endif
+}
+
+inline int BatHit( int bath, int batl, int virt ) {
+    int mask = 0xfffe0000 & ~((batl & 0x3f) << 17);
+    return (batl & 0x40) && ((virt & mask) == (bath & mask));
+}
+
+inline int BatTranslate( int bath, int batl, int virt ) {
+    return (virt & 0x007fffff) | (batl & 0xfffe0000);
+}
+
+/* translate address */
+int PpcVirt2phys( int virt, int inst ) {
+    int msr = GetMSR();
+    int txmask = inst ? 0x20 : 0x10;
+    int i, bath, batl, sr, sdr1, physbase, vahi, valo;
+    int npteg, hash, hashmask, ptehi, ptelo, ptegaddr;
+    int vsid, pteh, ptevsid, pteapi;
+               
+    if( msr & txmask ) {
+       sr = GetSR( virt >> 28 );
+       vsid = sr & 0xfffffff;
+       vahi = vsid >> 4;
+       valo = (vsid << 28) | (virt & 0xfffffff);
+       if( sr & 0x80000000 ) {
+           return valo;
+       }
+
+       for( i = 0; i < 4; i++ ) {
+           GetBat( i, inst, &bath, &batl );
+           if( BatHit( bath, batl, virt ) ) {
+               return BatTranslate( bath, batl, virt );
+           }
+       }
+
+       sdr1 = GetSDR1();
+
+       physbase = sdr1 & ~0xffff;
+       hashmask = ((sdr1 & 0x1ff) << 10) | 0x3ff;
+       hash = (vsid & 0x7ffff) ^ ((valo >> 12) & 0xffff);
+       npteg = hashmask + 1;
+
+       for( pteh = 0; pteh < 0x80; pteh += 64, hash ^= 0x7ffff ) {
+           ptegaddr = ((hashmask & hash) * 64) + physbase;
+
+           for( i = 0; i < 8; i++ ) {
+               ptehi = GetPhys( ptegaddr + (i * 8) );
+               ptelo = GetPhys( ptegaddr + (i * 8) + 4 );
+
+               ptevsid = (ptehi >> 7) & 0xffffff;
+               pteapi = ptehi & 0x3f;
+
+               if( (ptehi & 64) != pteh ) continue;
+               if( ptevsid != (vsid & 0xffffff) ) continue;
+               if( pteapi != ((virt >> 22) & 0x3f) ) continue;
+               
+               return (ptelo & 0xfffff000) | (virt & 0xfff);
+           }
+       }
+       return -1;
+    } else {
+       return virt;
+    }
+}
+
+/* Add a new page table entry for the indicated mapping */
+BOOLEAN InsertPageEntry( int virt, int phys, int slot, int _sdr1 ) {
+    int i, ptehi, ptelo;
+    int sdr1 = _sdr1 ? _sdr1 : GetSDR1();
+    int sr = GetSR( (virt >> 28) & 0xf );
+    int vsid = sr & 0xfffffff;
+    int physbase = sdr1 & ~0xffff;
+    int hashmask = ((sdr1 & 0x1ff) << 10) | 0x3ff;
+    int valo = (vsid << 28) | (virt & 0xfffffff);
+    int hash = (vsid & 0x7ffff) ^ ((valo >> 12) & 0xffff);
+    int ptegaddr = ((hashmask & hash) * 64) + physbase;
+
+    for( i = 0; i < 8; i++ ) {
+       ptehi = GetPhys( ptegaddr + (i * 8) );
+       
+       if( (slot != i) && (ptehi & 0x80000000) ) continue;
+
+       ptehi = (1 << 31) | (vsid << 7) | ((virt >> 22) & 0x3f);
+       ptelo = phys & ~0xfff;
+
+       SetPhys( ptegaddr + (i * 8), ptehi );
+       SetPhys( ptegaddr + (i * 8) + 4, ptelo );
+
+       return TRUE;
+    }
+
+    return FALSE;
+}
diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/ofw_util.s b/reactos/boot/freeldr/freeldr/arch/powerpc/ofw_util.s
new file mode 100644 (file)
index 0000000..df92154
--- /dev/null
@@ -0,0 +1,49 @@
+       .section .text
+       .globl ofw_functions
+       .globl ofw_call_addr
+       .globl call_ofw
+call_ofw:      
+       /* R3 has the function offset to call (n * 4)
+        * Other arg registers are unchanged. */
+       subi    %r1,%r1,0x100
+       stw     %r8,24(%r1)
+       mflr    %r8
+       stw     %r8,0(%r1)
+       stw     %r3,4(%r1)
+       stw     %r4,8(%r1)
+       stw     %r5,12(%r1)
+       stw     %r6,16(%r1)
+       stw     %r7,20(%r1)
+       stw     %r9,28(%r1)
+       stw     %r10,32(%r1)
+       stw     %r20,36(%r1)
+
+       lis     %r10,ofw_functions@ha
+       addi    %r8,%r10,ofw_functions@l
+       add     %r8,%r3,%r8
+       lwz     %r9,0(%r8)
+       mtctr   %r9
+
+       mr      %r3,%r4
+       mr      %r4,%r5
+       mr      %r5,%r6
+       mr      %r6,%r7
+       mr      %r7,%r8
+       mr      %r8,%r9
+
+       /* Call ofw proxy function */
+       bctrl
+
+       lwz     %r8,0(%r1)
+       mtlr    %r8
+       lwz     %r4,8(%r1)
+       lwz     %r5,12(%r1)
+       lwz     %r6,16(%r1)
+       lwz     %r7,20(%r1)
+       lwz     %r8,24(%r1)
+       lwz     %r9,28(%r1)
+       lwz     %r10,32(%r1)
+       lwz     %r20,36(%r1)
+       addi    %r1,%r1,0x100
+       blr
+
diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/prep.c b/reactos/boot/freeldr/freeldr/arch/powerpc/prep.c
new file mode 100644 (file)
index 0000000..b3fe7d5
--- /dev/null
@@ -0,0 +1,112 @@
+#include "freeldr.h"
+#include "machine.h"
+#include "ppcmmu/mmu.h"
+#include "prep.h"
+
+int prep_serial = 0x800003f8;
+
+void sync() { __asm__("eieio\n\tsync"); }
+
+/* Simple serial */
+
+void PpcPrepPutChar( int ch ) {
+    if( ch == 0x0a ) {
+       SetPhysByte(prep_serial, 0x0d);
+       sync();
+    }
+    SetPhysByte(prep_serial, ch);
+    sync();
+}
+
+BOOLEAN PpcPrepDiskReadLogicalSectors
+( ULONG DriveNumber, ULONGLONG SectorNumber,
+  ULONG SectorCount, PVOID Buffer ) {
+    int secct;
+    
+    for(secct = 0; secct < SectorCount; secct++)
+    {
+       ide_seek(&ide1_desc, SectorNumber + secct, 0);
+       ide_read(&ide1_desc, ((PCHAR)Buffer) + secct * 512, 512);
+    }
+    /* Never give up! */
+    return TRUE;
+}
+
+BOOLEAN PpcPrepConsKbHit()
+{
+    return 1;
+    //return GetPhysByte(prep_serial+5) & 1;
+}
+
+int PpcPrepConsGetCh() 
+{
+    while(!PpcPrepConsKbHit());
+    return GetPhysByte(prep_serial);
+}
+
+void PpcPrepVideoClearScreen(UCHAR Attr)
+{
+    printf("\033c");
+}
+
+VIDEODISPLAYMODE PpcPrepVideoSetDisplayMode( char *DisplayMode, BOOLEAN Init )
+{
+    return VideoTextMode;
+}
+
+void PpcPrepVideoGetDisplaySize( PULONG Width, PULONG Height, PULONG Depth )
+{
+    *Width = 80;
+    *Height = 25;
+    *Depth = 16;
+}
+
+void PpcPrepVideoPrepareForReactOS()
+{
+    pci_setup(&pci1_desc);
+}
+
+int mmu_initialized = 0;
+
+ULONG PpcPrepGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap,
+                          ULONG MaxMemoryMapSize )
+{
+    // xxx fixme
+    BiosMemoryMap[0].Type = 1;
+    BiosMemoryMap[0].BaseAddress = 0xe80000;
+    BiosMemoryMap[0].Length = (64 * 1024 * 1024) - BiosMemoryMap[0].BaseAddress;
+    if(!mmu_initialized)
+    {
+       MmuInit();
+       mmu_initialized = 1;
+    }
+    MmuSetMemorySize(BiosMemoryMap[0].Length + BiosMemoryMap[0].BaseAddress);
+    return 1;
+}
+
+void PpcPrepInit()
+{
+    MachVtbl.ConsPutChar = PpcPrepPutChar;
+
+    printf("Serial on\n");
+
+    ide_setup( &ide1_desc );
+
+    MachVtbl.DiskReadLogicalSectors = PpcPrepDiskReadLogicalSectors;
+    
+    MachVtbl.ConsKbHit   = PpcPrepConsKbHit;
+    MachVtbl.ConsGetCh   = PpcPrepConsGetCh;
+
+    MachVtbl.VideoClearScreen = PpcPrepVideoClearScreen;
+    MachVtbl.VideoSetDisplayMode = PpcPrepVideoSetDisplayMode;
+    MachVtbl.VideoGetDisplaySize = PpcPrepVideoGetDisplaySize;
+
+    MachVtbl.VideoPrepareForReactOS = PpcPrepVideoPrepareForReactOS;
+
+    MachVtbl.GetMemoryMap = PpcPrepGetMemoryMap;
+
+    printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() );
+
+    BootMain( "" );
+}
+
diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/prep.h b/reactos/boot/freeldr/freeldr/arch/powerpc/prep.h
new file mode 100644 (file)
index 0000000..ce2cfbf
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef FREELDR_ARCH_POWERPC_PREP_H
+#define FREELDR_ARCH_POWERPC_PREP_H
+
+extern struct _pci_desc pci1_desc;
+extern struct _idectl_desc ide1_desc;
+extern struct _vga_desc vga1_desc;
+struct _pci_bar {
+    unsigned long data;
+};
+
+void sync();
+void PpcPrepInit();
+void ide_seek( void *extension, int low, int high );
+int  ide_read( void *extension, char *buffer, int bytes );
+void ide_setup( void *extension );
+
+void print_bar( struct _pci_bar *bar );
+void pci_setup( struct _pci_desc *pci_desc );
+void pci_read_bar( struct _pci_desc *pci_desc, int bus, int dev, int fn, int bar, struct _pci_bar *bar_data );
+
+void vga_setup( struct _pci_desc *pci_desc, struct _vga_desc *vga_desc, 
+               int bus, int dev, int fn );
+
+#endif//FREELDR_ARCH_POWERPC_PREP_H
diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/prep_ide.c b/reactos/boot/freeldr/freeldr/arch/powerpc/prep_ide.c
new file mode 100644 (file)
index 0000000..abfcf75
--- /dev/null
@@ -0,0 +1,106 @@
+#include "freeldr.h"
+#include "machine.h"
+#include "ppcmmu/mmu.h"
+#include "prep.h"
+
+#define SWAP_W(x) ((((x) & 0xff) << 8) | (((x) >> 8) & 0xff))
+
+typedef struct _idectl_desc {
+    int port;
+    long long seekto;
+    int seek_cylinder, seek_head, seek_sector;
+    int cylinders, heads, sectors, bytespersec;
+} idectl_desc;
+
+idectl_desc ide1_desc = { 0x800001f0 };
+
+void ide_seek( void *extension, int low, int high ) {
+    idectl_desc *desc = (idectl_desc *)extension;
+    long long seekto = ((((long long)high) << 32) | (low & 0xffffffff));
+    /* order = sector, head, cylinder */
+    desc->seek_sector = seekto % desc->sectors;
+    seekto /= desc->sectors;
+    desc->seek_head = seekto % desc->heads;
+    seekto /= desc->heads;
+    desc->seek_cylinder = seekto;
+    desc->seekto = seekto;
+}
+
+/* Thanks chuck moore.  This is based on the color forth ide code */
+/* Wait for ready */
+void ide_rdy( void *extension ) {
+    idectl_desc *desc = (idectl_desc *)extension;
+    while( !(GetPhysByte(desc->port+7) & 0x40) ) sync(); 
+}
+
+void ide_drq( void *extension ) {
+    idectl_desc *desc = (idectl_desc *)extension;
+    while( !(GetPhysByte(desc->port+7) & 0x08) ) sync(); 
+}
+
+void ide_bsy( void *extension ) {
+    idectl_desc *desc = (idectl_desc *)extension;
+    while( GetPhysByte(desc->port+7) & 0x80 ) 
+    {
+       printf("Waiting for not busy\n");
+       sync(); 
+    }
+}
+
+int ide_read( void *extension, char *buffer, int bytes ) {
+    idectl_desc *desc = (idectl_desc *)extension;
+    short *databuf = (short *)buffer;
+    int inwords;
+
+    ide_bsy( extension );
+    SetPhysByte(desc->port+2, bytes / desc->bytespersec);
+    SetPhysByte(desc->port+3, desc->seek_sector + 1);
+    SetPhysByte(desc->port+4, desc->seek_cylinder);
+    SetPhysByte(desc->port+5, desc->seek_cylinder >> 8);
+    SetPhysByte(desc->port+6, desc->seek_head | 0xa0);
+    SetPhysByte(desc->port+7, 0x20);
+    
+    for( inwords = 0; inwords < desc->bytespersec / sizeof(short); inwords++ ) {
+       databuf[inwords] = GetPhysHalf(desc->port);
+    }
+
+    desc->seekto += desc->bytespersec;
+    ide_seek( extension, desc->seekto, desc->seekto >> 32 );
+
+    return bytes - (bytes % desc->bytespersec);
+}
+
+void ide_setup( void *extension ) {
+    idectl_desc *desc = (idectl_desc *)extension;
+    short identbuffer[256];
+    char namebuf[41];
+    short *databuf = (short *)identbuffer, in;
+    int inwords;
+
+    ide_rdy( extension );
+    ide_bsy( extension );
+    desc->bytespersec = 512;
+    SetPhysByte(desc->port+2, 1);
+    SetPhysByte(desc->port+3, 0);
+    SetPhysByte(desc->port+4, 0);
+    SetPhysByte(desc->port+5, 0);
+    SetPhysByte(desc->port+6, 0);
+    SetPhysByte(desc->port+7, 0xec);
+    ide_drq( extension );
+
+    for( inwords = 0; inwords < desc->bytespersec / sizeof(short); inwords++ ) {
+       in = GetPhysHalf(desc->port);
+       databuf[inwords] = SWAP_W(in);
+       sync();
+    }
+
+    desc->cylinders = identbuffer[1];
+    desc->heads = identbuffer[3];
+    desc->sectors = identbuffer[6];
+
+    /* Debug: Write out hard disc model */
+
+    strncpy(namebuf, (char *)(identbuffer+0x1b), 41);
+    printf("HARD DISC MODEL: %s c,h,s %d,%d,%d\n", 
+          namebuf, desc->cylinders, desc->heads, desc->sectors);
+}
diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/prep_pci.c b/reactos/boot/freeldr/freeldr/arch/powerpc/prep_pci.c
new file mode 100644 (file)
index 0000000..6254723
--- /dev/null
@@ -0,0 +1,127 @@
+#include <freeldr.h>
+#include "prep.h"
+
+typedef struct _pci_cfg {
+    unsigned long addr;
+    unsigned long data;
+} pci_cfg;
+
+typedef struct _pci_desc {
+    pci_cfg *cfg;
+} pci_desc;
+
+pci_desc pci1_desc = { (void *)0x80000cf8 };
+#define rev16(x) ((((x)>>8)&0xff)|(((x)&0xff)<<8))
+#define rev32(x) ((((x)>>24)&0xff)|(((x)>>8)&0xff00)|(((x)&0xff00)<<8)|(((x)&0xff)<<24))
+#define pci_addr(bus,dev,fn,reg) \
+         (0x80000000 | \
+          ((bus & 0xff) << 16) | \
+          ((dev & 0x1f) << 11) | \
+          ((fn & 7) << 8) | \
+          (reg & 0xfc))
+#if 0
+#define pci_cfg_addr(bus,dev,fn,reg) \
+        ((bus == 0) ? \
+         ((1 << (dev + 16)) | \
+          (dev << 11) | \
+          (fn << 8) | \
+          ((reg & 0xfc) | 1)) : pci_addr(bus,dev,fn,reg))
+#else
+#define pci_cfg_addr(bus,dev,fn,reg) pci_addr(bus,dev,fn,reg)
+#endif
+    unsigned long pci_read( pci_desc *desc, int bus, int dev, int fn, int reg, int len ) {
+       sync();
+       unsigned long save_state = desc->cfg->addr, ret = 0;
+       unsigned long addr = pci_cfg_addr(bus,dev,fn,reg);
+       unsigned long offset = reg & 3;
+       desc->cfg->addr = rev32(addr);
+       sync();
+       switch( len ) {
+       case 4:
+           ret = desc->cfg->data;
+           break;
+       case 2:
+           ret = desc->cfg->data;
+           ret = (ret >> (offset << 3)) & 0xffff;
+           break;
+       case 1:
+           ret = desc->cfg->data;
+           ret = (ret >> (offset << 3)) & 0xff;
+           break;
+       }
+       desc->cfg->addr = save_state;
+       sync();
+       return ret;
+    }
+
+void pci_read_bar( pci_desc *desc, int bus, int dev, int fn, int bar, 
+                  struct _pci_bar *bar_data ) {
+    bar_data->data = pci_read( desc, bus, dev, fn, 0x10 + (bar * 4), 4 );
+}
+
+/* 
+ * Imagine: offset 3, len 1
+ * let oldval = 0x12345678 and val = 0xabcd1234;
+ * mask = ((1 << 8) - 1) << 24; // 0xff000000
+ * oldval = (0x12345678 & 0x00ffffff) | (0xabcd1234 & 0xff000000) = 0xab345678;
+ */
+void pci_write( pci_desc *desc, int bus, int dev, int fn, int reg, int len, int val ) {
+    unsigned long save_state = desc->cfg->addr;
+    unsigned long addr = pci_cfg_addr(bus,dev,fn,reg);
+    unsigned long offset = reg & 3;
+    unsigned long oldval = pci_read( desc, bus, dev, fn, reg & ~3, 4 );
+    unsigned long mask = ((1 << (len * 8)) - 1) << (offset << 3);
+    oldval = (oldval & ~mask) | ((val << (offset << 3)) & mask);
+    desc->cfg->addr = rev32(addr);
+    sync();
+    desc->cfg->data = rev32(oldval);
+    sync();
+    desc->cfg->addr = save_state;
+    sync();
+}
+
+void pci_write_bar( pci_desc *desc, int bus, int dev, int fn, int bar, struct _pci_bar *bar_data ) {
+    pci_write( desc, bus, dev, fn, 0x10 + (bar * 4), 4, bar_data->data );
+}
+
+void print_bar( struct _pci_bar *bar ) {
+    printf("BAR: %x\n", bar->data);
+}
+
+#define PCI_VENDORID 0
+#define PCI_DEVICEID 2
+#define PCI_HEADER_TYPE 0xe
+#define PCI_BASECLASS   0xb
+
+void pci_setup( pci_desc *desc ) {
+    unsigned char type;
+    unsigned short vendor, device, devclass;
+    int funcs, bus, dev, fn;
+
+    pci1_desc.cfg = (pci_cfg *)0x80000cf8;
+
+    printf("PCI Bus:\n");
+    for( bus = 0; bus < 1; bus++ ) {
+        for( dev = 0; dev < 32; dev++ ) {
+            type = pci_read(desc,bus,dev,0,PCI_HEADER_TYPE,1);
+            vendor = pci_read(desc,bus,dev,0,PCI_VENDORID,2);
+            device = pci_read(desc,bus,dev,0,PCI_DEVICEID,2);
+            
+            if(vendor == 0 || vendor == 0xffff) continue;
+            if(type & 0x80) funcs = 8; else funcs = 1;
+
+            for( fn = 0; fn < funcs; fn++ ) {
+                devclass = pci_read(desc,bus,dev,fn,PCI_BASECLASS,1);
+               printf(" %d:%d -> vendor:device:class %x:%x:%x\n",
+                      bus, dev, vendor, device, devclass);
+                
+                if( devclass == 3 ) {
+                   printf("Setting up vga...\n");
+                    vga_setup(desc,&vga1_desc,bus,dev,fn);
+                   printf("Done with vga\n");
+                }
+            }
+        }
+    }
+    printf("^-- end PCI\n");
+}
diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/prep_vga.c b/reactos/boot/freeldr/freeldr/arch/powerpc/prep_vga.c
new file mode 100644 (file)
index 0000000..24d8368
--- /dev/null
@@ -0,0 +1,30 @@
+#include <freeldr.h>
+#include "prep.h"
+#include "ppcboot.h"
+
+extern boot_infos_t BootInfo;
+
+struct _vga_desc {
+    char *port;
+    char *addr;
+};
+
+#define VGA_WIDTH 1024
+#define VGA_HEIGHT 768
+struct _vga_desc vga1_desc = { (char *)0x800003c0 };
+
+void vga_setup( struct _pci_desc *desc, struct _vga_desc *vga_desc, 
+               int bus, int dev, int fn ) {
+    struct _pci_bar bar_data;
+    int i;
+
+    for( i = 0; i < 6; i++ ) {
+        pci_read_bar( desc, bus, dev, fn, i, &bar_data );
+        print_bar( &bar_data );
+        if( (bar_data.data > 0x10000) || ((bar_data.data&1) == 1) ) {
+            vga_desc->addr = (char *)(0xc0000000 + (bar_data.data & ~0x7ff));
+           BootInfo.dispDeviceBase = vga_desc->addr;
+            break;
+        }
+    }
+}
index a410268..025ab5c 100644 (file)
@@ -1,12 +1,26 @@
-<module name="freeldr" type="bootloader">
-    <bootstrap base="loader" />
-    <library>freeldr_startup</library>
-    <library>freeldr_base64k</library>
-    <library>freeldr_base</library>
-    <library>freeldr_arch</library>
-    <library>freeldr_main</library>
-    <library>rossym</library>
-    <library>cmlib</library>
-    <library>rtl</library>
-    <library>libcntpr</library>
-</module>
+<if property="ARCH" value="i386">
+        <module name="freeldr" type="bootloader">
+            <bootstrap base="loader" />
+            <library>freeldr_startup</library>
+            <library>freeldr_base64k</library>
+            <library>freeldr_base</library>
+            <library>freeldr_arch</library>
+            <library>freeldr_main</library>
+            <library>rossym</library>
+            <library>cmlib</library>
+            <library>rtl</library>
+            <library>libcntpr</library>
+        </module>
+</if>
+<if property="ARCH" value="powerpc">
+        <module name="ofwldr" type="elfexecutable" buildtype="OFWLDR">
+            <library>freeldr_startup</library>
+            <library>freeldr_base64k</library>
+            <library>freeldr_base</library>
+            <library>freeldr_arch</library>
+            <library>freeldr_main</library>
+            <library>rossym</library>
+            <library>cmlib</library>
+            <library>rtl</library>
+        </module>
+</if>
index 310680e..6f55745 100644 (file)
@@ -47,6 +47,8 @@
                                <include base="freeldr_base">include</include>
                                <include base="freeldr_base">cache</include>
                                <include base="ntoskrnl">include</include>
+                               <include base="ReactOS">include/reactos/libs</include>
+                               <include base="ReactOS">include/reactos/elf</include>
                                <define name="__USE_W32API" />
                                <define name="_NTHAL_" />
                                <compilerflag>-ffreestanding</compilerflag>
index 14cf1d4..1fbcb2d 100644 (file)
@@ -18,6 +18,8 @@
  */
 
 #include <freeldr.h>
+
+#define NDEBUG
 #include <debug.h>
 
 ULONG                  BytesPerSector;                 /* Number of bytes per sector */
@@ -35,6 +37,84 @@ ULONG                        DataSectorStart;                /* Starting sector of the data area */
 ULONG                  FatType = 0;                    /* FAT12, FAT16, FAT32, FATX16 or FATX32 */
 ULONG                  FatDriveNumber = 0;
 
+VOID FatSwapFatBootSector(PFAT_BOOTSECTOR Obj)
+{
+    SW(Obj, BytesPerSector);
+    SW(Obj, ReservedSectors);
+    SW(Obj, RootDirEntries);
+    SW(Obj, TotalSectors);
+    SW(Obj, SectorsPerFat);
+    SW(Obj, SectorsPerTrack);
+    SW(Obj, NumberOfHeads);
+    SD(Obj, HiddenSectors);
+    SD(Obj, TotalSectorsBig);
+    SD(Obj, VolumeSerialNumber);
+    SW(Obj, BootSectorMagic);
+}
+
+VOID FatSwapFat32BootSector(PFAT32_BOOTSECTOR Obj)
+{
+    SW(Obj, BytesPerSector);
+    SW(Obj, ReservedSectors);
+    SW(Obj, RootDirEntries);
+    SW(Obj, TotalSectors);
+    SW(Obj, SectorsPerFat);
+    SW(Obj, NumberOfHeads);
+    SD(Obj, HiddenSectors);
+    SD(Obj, TotalSectorsBig);
+    SD(Obj, SectorsPerFatBig);
+    SW(Obj, ExtendedFlags);
+    SW(Obj, FileSystemVersion);
+    SD(Obj, RootDirStartCluster);
+    SW(Obj, FsInfo);
+    SW(Obj, BackupBootSector);
+    SD(Obj, VolumeSerialNumber);
+    SW(Obj, BootSectorMagic);
+}
+
+VOID FatSwapFatXBootSector(PFATX_BOOTSECTOR Obj)
+{
+    SD(Obj, VolumeSerialNumber);
+    SD(Obj, SectorsPerCluster);
+    SW(Obj, NumberOfFats);
+}
+
+VOID FatSwapDirEntry(PDIRENTRY Obj)
+{
+    SW(Obj, CreateTime);
+    SW(Obj, CreateDate);
+    SW(Obj, LastAccessDate);
+    SW(Obj, ClusterHigh);
+    SW(Obj, Time);
+    SW(Obj, Date);
+    SW(Obj, ClusterLow);
+    SD(Obj, Size);
+}
+
+VOID FatSwapLFNDirEntry(PLFN_DIRENTRY Obj)
+{
+    int i;
+    SW(Obj, StartCluster);
+    for(i = 0; i < 5; i++)
+       Obj->Name0_4[i] = SWAPW(Obj->Name0_4[i]);
+    for(i = 0; i < 6; i++)
+       Obj->Name5_10[i] = SWAPW(Obj->Name5_10[i]);
+    for(i = 0; i < 2; i++)
+       Obj->Name11_12[i] = SWAPW(Obj->Name11_12[i]);
+}
+
+VOID FatSwapFatXDirEntry(PFATX_DIRENTRY Obj)
+{
+    SD(Obj, StartCluster);
+    SD(Obj, Size);
+    SW(Obj, Time);
+    SW(Obj, Date);
+    SW(Obj, CreateTime);
+    SW(Obj, CreateDate);
+    SW(Obj, LastAccessTime);
+    SW(Obj, LastAccessDate);
+}
+
 BOOLEAN FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG PartitionSectorCount)
 {
        char ErrMsg[80];
@@ -73,13 +153,17 @@ BOOLEAN FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG Partitio
        }
        RtlCopyMemory(FatVolumeBootSector, (PVOID)DISKREADBUFFER, 512);
 
+
        // Get the FAT type
        FatType = FatDetermineFatType(FatVolumeBootSector, PartitionSectorCount);
 
+#ifdef DEBUG
+
        DbgPrint((DPRINT_FILESYSTEM, "Dumping boot sector:\n"));
 
        if (ISFATX(FatType))
        {
+               FatSwapFatXBootSector(FatXVolumeBootSector);
                DbgPrint((DPRINT_FILESYSTEM, "sizeof(FATX_BOOTSECTOR) = 0x%x.\n", sizeof(FATX_BOOTSECTOR)));
 
                DbgPrint((DPRINT_FILESYSTEM, "FileSystemType: %c%c%c%c.\n", FatXVolumeBootSector->FileSystemType[0], FatXVolumeBootSector->FileSystemType[1], FatXVolumeBootSector->FileSystemType[2], FatXVolumeBootSector->FileSystemType[3]));
@@ -93,6 +177,7 @@ BOOLEAN FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG Partitio
        }
        else if (FatType == FAT32)
        {
+               FatSwapFat32BootSector(Fat32VolumeBootSector);
                DbgPrint((DPRINT_FILESYSTEM, "sizeof(FAT32_BOOTSECTOR) = 0x%x.\n", sizeof(FAT32_BOOTSECTOR)));
 
                DbgPrint((DPRINT_FILESYSTEM, "JumpBoot: 0x%x 0x%x 0x%x\n", Fat32VolumeBootSector->JumpBoot[0], Fat32VolumeBootSector->JumpBoot[1], Fat32VolumeBootSector->JumpBoot[2]));
@@ -126,6 +211,7 @@ BOOLEAN FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG Partitio
        }
        else
        {
+               FatSwapFatBootSector(FatVolumeBootSector);
                DbgPrint((DPRINT_FILESYSTEM, "sizeof(FAT_BOOTSECTOR) = 0x%x.\n", sizeof(FAT_BOOTSECTOR)));
 
                DbgPrint((DPRINT_FILESYSTEM, "JumpBoot: 0x%x 0x%x 0x%x\n", FatVolumeBootSector->JumpBoot[0], FatVolumeBootSector->JumpBoot[1], FatVolumeBootSector->JumpBoot[2]));
@@ -151,7 +237,9 @@ BOOLEAN FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG Partitio
                DbgPrint((DPRINT_FILESYSTEM, "BootSectorMagic: 0x%x\n", FatVolumeBootSector->BootSectorMagic));
        }
 
-       //
+#endif // defined DEBUG
+
+        //
        // Set the correct partition offset
        //
        FatVolumeStartSector = VolumeStartSector;
@@ -199,7 +287,7 @@ BOOLEAN FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG Partitio
        if (ISFATX(FatType))
        {
                BytesPerSector = 512;
-               SectorsPerCluster = FatXVolumeBootSector->SectorsPerCluster;
+               SectorsPerCluster = SWAPD(FatXVolumeBootSector->SectorsPerCluster);
                FatSectorStart = (4096 / BytesPerSector);
                ActiveFatSectorStart = FatSectorStart;
                NumberOfFats = 1;
@@ -254,6 +342,7 @@ BOOLEAN FatOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector, ULONG Partitio
        //
        // Initialize the disk cache for this drive
        //
+       printf("About to do cache init\n");
        if (!CacheInitializeDrive(DriveNumber))
        {
                return FALSE;
@@ -301,10 +390,10 @@ ULONG FatDetermineFatType(PFAT_BOOTSECTOR FatBootSector, ULONG PartitionSectorCo
        }
        else
        {
-               RootDirSectors = ((FatBootSector->RootDirEntries * 32) + (FatBootSector->BytesPerSector - 1)) / FatBootSector->BytesPerSector;
-               SectorsPerFat = FatBootSector->SectorsPerFat ? FatBootSector->SectorsPerFat : Fat32BootSector->SectorsPerFatBig;
-               TotalSectors = FatBootSector->TotalSectors ? FatBootSector->TotalSectors : FatBootSector->TotalSectorsBig;
-               DataSectorCount = TotalSectors - (FatBootSector->ReservedSectors + (FatBootSector->NumberOfFats * SectorsPerFat) + RootDirSectors);
+               RootDirSectors = ((SWAPW(FatBootSector->RootDirEntries) * 32) + (SWAPW(FatBootSector->BytesPerSector) - 1)) / SWAPW(FatBootSector->BytesPerSector);
+               SectorsPerFat = SWAPW(FatBootSector->SectorsPerFat) ? SWAPW(FatBootSector->SectorsPerFat) : SWAPD(Fat32BootSector->SectorsPerFatBig);
+               TotalSectors = SWAPW(FatBootSector->TotalSectors) ? SWAPW(FatBootSector->TotalSectors) : SWAPD(FatBootSector->TotalSectorsBig);
+               DataSectorCount = TotalSectors - (SWAPW(FatBootSector->ReservedSectors) + (FatBootSector->NumberOfFats * SectorsPerFat) + RootDirSectors);
 
 //mjl
                if (FatBootSector->SectorsPerCluster == 0)
@@ -396,11 +485,13 @@ BOOLEAN FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySi
 {
        ULONG           EntryCount;
        ULONG           CurrentEntry;
-       PDIRENTRY       DirEntry;
-       PLFN_DIRENTRY   LfnDirEntry;
        CHAR            LfnNameBuffer[265];
        CHAR            ShortNameBuffer[20];
        ULONG           StartCluster;
+       DIRENTRY        OurDirEntry;
+       LFN_DIRENTRY    OurLfnDirEntry;
+       PDIRENTRY       DirEntry = &OurDirEntry;
+       PLFN_DIRENTRY   LfnDirEntry = &OurLfnDirEntry;
 
        EntryCount = DirectorySize / sizeof(DIRENTRY);
 
@@ -409,10 +500,12 @@ BOOLEAN FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySi
        memset(ShortNameBuffer, 0, 13 * sizeof(CHAR));
        memset(LfnNameBuffer, 0, 261 * sizeof(CHAR));
 
-       DirEntry = (PDIRENTRY) DirectoryBuffer;
-       for (CurrentEntry=0; CurrentEntry<EntryCount; CurrentEntry++, DirEntry++)
+       for (CurrentEntry=0; CurrentEntry<EntryCount; CurrentEntry++, DirectoryBuffer = ((PDIRENTRY)DirectoryBuffer)+1)
        {
-               LfnDirEntry = (PLFN_DIRENTRY)DirEntry;
+               OurLfnDirEntry = *((PLFN_DIRENTRY) DirectoryBuffer);
+               FatSwapLFNDirEntry(LfnDirEntry);
+               OurDirEntry = *((PDIRENTRY) DirectoryBuffer);
+               FatSwapDirEntry(DirEntry);
 
                //DbgPrint((DPRINT_FILESYSTEM, "Dumping directory entry %d:\n", CurrentEntry));
                //DbgDumpBuffer(DPRINT_FILESYSTEM, DirEntry, sizeof(DIRENTRY));
@@ -425,7 +518,7 @@ BOOLEAN FatSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG DirectorySi
                //
                if (DirEntry->FileName[0] == '\0')
                {
-                       return FALSE;
+                       return FALSE;
                }
 
                //
@@ -607,17 +700,20 @@ static BOOLEAN FatXSearchDirectoryBufferForFile(PVOID DirectoryBuffer, ULONG Dir
 {
        ULONG           EntryCount;
        ULONG           CurrentEntry;
-       PFATX_DIRENTRY  DirEntry;
        ULONG           FileNameLen;
+       FATX_DIRENTRY   OurDirEntry;
+       PFATX_DIRENTRY  DirEntry = &OurDirEntry;
 
        EntryCount = DirectorySize / sizeof(FATX_DIRENTRY);
 
        DbgPrint((DPRINT_FILESYSTEM, "FatXSearchDirectoryBufferForFile() DirectoryBuffer = 0x%x EntryCount = %d FileName = %s\n", DirectoryBuffer, EntryCount, FileName));
 
        FileNameLen = strlen(FileName);
-       DirEntry = (PFATX_DIRENTRY) DirectoryBuffer;
-       for (CurrentEntry = 0; CurrentEntry < EntryCount; CurrentEntry++, DirEntry++)
+
+       for (CurrentEntry = 0; CurrentEntry < EntryCount; CurrentEntry++, DirectoryBuffer = ((PFATX_DIRENTRY)DirectoryBuffer)+1)
        {
+               OurDirEntry = *(PFATX_DIRENTRY) DirectoryBuffer;
+               FatSwapFatXDirEntry(&OurDirEntry);
                if (0xff == DirEntry->FileNameSize)
                {
                        break;
@@ -715,6 +811,7 @@ BOOLEAN FatLookupFile(PCSTR FileName, PFAT_FILE_INFO FatFileInfoPointer)
                // Buffer the directory contents
                //
                DirectoryBuffer = FatBufferDirectory(DirectoryStartCluster, &DirectorySize, (i == 0) );
+
                if (DirectoryBuffer == NULL)
                {
                        return FALSE;
@@ -848,6 +945,7 @@ BOOLEAN FatGetFatEntry(ULONG Cluster, ULONG* ClusterPointer)
                }
 
                fat = *((USHORT *) ((ULONG_PTR)FILESYSBUFFER + ThisFatEntOffset));
+               fat = SWAPW(fat);
                if (Cluster & 0x0001)
                        fat = fat >> 4; /* Cluster number is ODD */
                else
@@ -868,6 +966,7 @@ BOOLEAN FatGetFatEntry(ULONG Cluster, ULONG* ClusterPointer)
                }
 
                fat = *((USHORT *) ((ULONG_PTR)FILESYSBUFFER + ThisFatEntOffset));
+               fat = SWAPW(fat);
 
                break;
 
@@ -885,6 +984,7 @@ BOOLEAN FatGetFatEntry(ULONG Cluster, ULONG* ClusterPointer)
 
                // Get the fat entry
                fat = (*((ULONG *) ((ULONG_PTR)FILESYSBUFFER + ThisFatEntOffset))) & 0x0FFFFFFF;
+               fat = SWAPD(fat);
 
                break;
 
index a665438..f7116b9 100644 (file)
@@ -18,6 +18,8 @@
  */
 
 #include <freeldr.h>
+
+#define NDEBUG
 #include <debug.h>
 
 /////////////////////////////////////////////////////////////////////////////////////////////
@@ -25,6 +27,7 @@
 /////////////////////////////////////////////////////////////////////////////////////////////
 
 ULONG                  FsType = 0;     // Type of filesystem on boot device, set by FsOpenVolume()
+PVOID                   FsStaticBufferDisk = 0, FsStaticBufferData = 0;
 
 /////////////////////////////////////////////////////////////////////////////////////////////
 // FUNCTIONS
@@ -49,8 +52,20 @@ static BOOLEAN FsOpenVolume(ULONG DriveNumber, ULONGLONG StartSector, ULONGLONG
 {
        CHAR ErrorText[80];
 
+       printf("FsOpenVolume: (disk=%d,start=%d,count=%d,type=%d)\n",
+              DriveNumber, StartSector, SectorCount, Type);
+
        FsType = Type;
 
+       if( !FsStaticBufferDisk )
+           FsStaticBufferDisk = MmAllocateMemory( 0x20000 );
+       if( !FsStaticBufferDisk )
+       {
+               FileSystemError("could not allocate filesystem static buffer");
+               return FALSE;
+       }
+       FsStaticBufferData = ((PCHAR)FsStaticBufferDisk) + 0x10000;
+           
        switch (FsType)
        {
        case FS_FAT:
@@ -150,6 +165,7 @@ PFILE FsOpenFile(PCSTR FileName)
                break;
        }
 
+#ifdef DEBUG
        //
        // Check return value
        //
@@ -161,6 +177,7 @@ PFILE FsOpenFile(PCSTR FileName)
        {
                DbgPrint((DPRINT_FILESYSTEM, "FsOpenFile() failed.\n"));
        }
+#endif // defined DEBUG
 
        return FileHandle;
 }
index b341877..32a7354 100644 (file)
@@ -18,6 +18,8 @@
  */
 
 #include <freeldr.h>
+
+#define NDEBUG
 #include <debug.h>
 
 /////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/reactos/boot/freeldr/freeldr/include/bytesex.h b/reactos/boot/freeldr/freeldr/include/bytesex.h
new file mode 100644 (file)
index 0000000..ccbfc7c
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __BYTESEX_H_
+#define __BYTESEX_H_
+
+#ifdef _PPC_
+#define SWAPD(x) ((((x)&0xff)<<24)|(((x)&0xff00)<<8)|(((x)>>8)&0xff00)|(((x)>>24)&0xff))
+#define SWAPW(x) ((((x)&0xff)<<8)|(((x)>>8)&0xff))
+#else
+#define SWAPD(x) x
+#define SWAPW(x) x
+#endif
+#define SD(Object,Field) Object->Field = SWAPD(Object->Field)
+#define SW(Object,Field) Object->Field = SWAPW(Object->Field)
+
+#endif/*__BYTESEX_H_*/
index 57f307a..b8a3353 100644 (file)
@@ -87,6 +87,8 @@
 #include <reactos/helper.h>
 /* Needed if debuging is enabled */
 #include <comm.h>
+/* Swap */
+#include <bytesex.h>
 
 #define Ke386EraseFlags(x)     __asm__ __volatile__("pushl $0 ; popfl\n")
 
index 445f665..2f623d5 100644 (file)
@@ -4,23 +4,14 @@
 #define OF_FAILED 0
 #define ERR_NOT_FOUND 0xc0000010
 
-#define REV(x) (((x)>>24)&0xff)|(((x)>>8)&0xff00)|(((x)<<24)&0xff000000)|(((x)<<8)&0xff0000)
+#include "of_call.h"
+#include <string.h>
 
 typedef int (*of_proxy)
-    ( int table_off, void *arg1, void *arg2, void *arg3, void *arg4 );
+    ( int table_off, void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6 );
 typedef long jmp_buf[100];
-
 extern of_proxy ofproxy;
 
-int ofw_finddevice( const char *name );
-int ofw_getprop( int package, const char *name, void *buffer, int size );
-int ofw_open( const char *name );
-int ofw_write( int handle, const char *buffer, int size );
-int ofw_read( int handle, const char *buffer, int size );
-void ofw_print_string(const char *);
-void ofw_print_number(int);
-void ofw_exit();
-
 int setjmp( jmp_buf buf );
 int longjmp( jmp_buf buf, int retval );
 
index b510f9a..2d0371d 100644 (file)
@@ -19,6 +19,9 @@
 
 #include <freeldr.h>
 #include <debug.h>
+#ifdef _M_PPC
+#include "of.h"
+#endif
 
 ULONG                  AllocationCount = 0;
 
@@ -65,6 +68,12 @@ PVOID MmAllocateMemory(ULONG MemorySize)
 
        if (MemorySize == 0)
        {
+#ifdef _M_PPC
+               ULONG ptr;
+               printf("Allocating %d bytes directly ...\n", MemorySize);
+               ptr = ofw_claim(0,MemorySize,MM_PAGE_SIZE);
+               MemPointer = (PVOID)(ptr);
+#endif
                DbgPrint((DPRINT_MEMORY, "MmAllocateMemory() called for 0 bytes. Returning NULL.\n"));
                UiMessageBoxCritical("Memory allocation failed: MmAllocateMemory() called for 0 bytes.");
                return NULL;
index 552e330..ea9ce8d 100644 (file)
@@ -2,7 +2,14 @@
 <directory name="hal">
        <xi:include href="hal/hal.rbuild" />
 </directory>
-<directory name="halx86">
-       <xi:include href="halx86/directory.rbuild" />
-</directory>
+<if property="ARCH" value="i386">
+        <directory name="halx86">
+               <xi:include href="halx86/directory.rbuild" />
+        </directory>
+</if>
+<if property="ARCH" value="powerpc">
+        <directory name="halppc">
+               <xi:include href="halppc/directory.rbuild" />
+        </directory>
+</if>
 </group>
index ded2af3..bc0e94a 100644 (file)
@@ -9,8 +9,13 @@
        <file>hal.rc</file>
 </module>
 
-<module ifnot="${MP}" name="halupalias" type="alias" installbase="system32" installname="hal.dll" aliasof="halup">
-</module>
+<if property="ARCH" value="i386">
+       <module ifnot="${MP}" name="halupalias" type="alias" installbase="system32" installname="hal.dll" aliasof="halup">
+       </module>
 
-<module if="${MP}" name="halmpalias" type="alias" installbase="system32" installname="hal.dll" aliasof="halmp">
-</module>
+       <module if="${MP}" name="halmpalias" type="alias" installbase="system32" installname="hal.dll" aliasof="halmp">
+       </module>
+</if>
+<if property="ARCH" value="powerpc">
+       <module name="halupalias" type="alias" installbase="system32" installname="hal.dll" aliasof="halppc_up"/>
+</if>
diff --git a/reactos/hal/halppc/generic/beep.c b/reactos/hal/halppc/generic/beep.c
new file mode 100644 (file)
index 0000000..f4e9d3b
--- /dev/null
@@ -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 <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+
+/* 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 (file)
index 0000000..a35adbe
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * PROJECT:         ReactOS HAL
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            hal/halx86/generic/bus.c
+ * PURPOSE:         Bus Support Routines
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+
+ULONG HalpBusType;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+NTAPI
+HalpRegisterKdSupportFunctions(VOID)
+{
+    /* Register PCI Device Functions */
+    KdSetupPciDeviceForDebugging = HalpSetupPciDeviceForDebugging;
+    KdReleasePciDeviceforDebugging = HalpReleasePciDeviceForDebugging;
+
+    /* Register memory functions */
+    KdMapPhysicalMemory64 = HalpMapPhysicalMemory64;
+    KdUnmapVirtualAddress = HalpUnmapVirtualAddress;
+
+    /* Register ACPI stub */
+    KdCheckPowerButton = HalpCheckPowerButton;
+}
+
+NTSTATUS
+NTAPI
+HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath,
+                        IN PUNICODE_STRING DriverClassName,
+                        IN PDRIVER_OBJECT DriverObject,
+                        IN PDEVICE_OBJECT DeviceObject,
+                        IN INTERFACE_TYPE BusType,
+                        IN ULONG BusNumber,
+                        IN ULONG SlotNumber,
+                        IN OUT PCM_RESOURCE_LIST *AllocatedResources)
+{
+    BUS_HANDLER BusHandler;
+    PAGED_CODE();
+
+    /* Only PCI is supported */
+    if (BusType != PCIBus) return STATUS_NOT_IMPLEMENTED;
+
+    /* Setup fake PCI Bus handler */
+    RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
+    BusHandler.BusNumber = BusNumber;
+
+    /* Call the PCI function */
+    return HalpAssignPCISlotResources(&BusHandler,
+                                      &BusHandler,
+                                      RegistryPath,
+                                      DriverClassName,
+                                      DriverObject,
+                                      DeviceObject,
+                                      SlotNumber,
+                                      AllocatedResources);
+}
+
+BOOLEAN
+NTAPI
+HalpTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
+                        IN ULONG BusNumber,
+                        IN PHYSICAL_ADDRESS BusAddress,
+                        IN OUT PULONG AddressSpace,
+                        OUT PPHYSICAL_ADDRESS TranslatedAddress)
+{
+    /* Translation is easy */
+    TranslatedAddress->QuadPart = BusAddress.QuadPart;
+    return TRUE;
+}
+
+ULONG
+NTAPI
+HalpGetSystemInterruptVector(IN ULONG BusNumber,
+                             IN ULONG BusInterruptLevel,
+                             IN ULONG BusInterruptVector,
+                             OUT PKIRQL Irql,
+                             OUT PKAFFINITY Affinity)
+{
+    ULONG Vector = IRQ2VECTOR(BusInterruptLevel);
+    *Irql = (KIRQL)VECTOR2IRQL(Vector);
+    *Affinity = 0xFFFFFFFF;
+    return Vector;
+}
+
+BOOLEAN
+NTAPI
+HalpFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress,
+                              IN OUT PULONG AddressSpace,
+                              OUT PPHYSICAL_ADDRESS TranslatedAddress,
+                              IN OUT PULONG_PTR Context,
+                              IN BOOLEAN NextBus)
+{
+    /* Make sure we have a context */
+    if (!Context) return FALSE;
+
+    /* If we have data in the context, then this shouldn't be a new lookup */
+    if ((*Context) && (NextBus == TRUE)) return FALSE;
+
+    /* Return bus data */
+    TranslatedAddress->QuadPart = BusAddress.QuadPart;
+
+    /* Set context value and return success */
+    *Context = 1;
+    return TRUE;
+}
+
+VOID
+NTAPI
+HalpInitNonBusHandler(VOID)
+{
+    /* These should be written by the PCI driver later, but we give defaults */
+    HalPciTranslateBusAddress = HalpTranslateBusAddress;
+    HalPciAssignSlotResources = HalpAssignSlotResources;
+    HalFindBusAddressTranslation = HalpFindBusAddressTranslation;
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+HalAdjustResourceList(IN PCM_RESOURCE_LIST Resources)
+{
+    /* Deprecated, return success */
+    return STATUS_SUCCESS;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+HalAssignSlotResources(IN PUNICODE_STRING RegistryPath,
+                       IN PUNICODE_STRING DriverClassName,
+                       IN PDRIVER_OBJECT DriverObject,
+                       IN PDEVICE_OBJECT DeviceObject,
+                       IN INTERFACE_TYPE BusType,
+                       IN ULONG BusNumber,
+                       IN ULONG SlotNumber,
+                       IN OUT PCM_RESOURCE_LIST *AllocatedResources)
+{
+    /* Check the bus type */
+    if (BusType != PCIBus)
+    {
+        /* Call our internal handler */
+        return HalpAssignSlotResources(RegistryPath,
+                                       DriverClassName,
+                                       DriverObject,
+                                       DeviceObject,
+                                       BusType,
+                                       BusNumber,
+                                       SlotNumber,
+                                       AllocatedResources);
+    }
+    else
+    {
+        /* Call the PCI registered function */
+        return HalPciAssignSlotResources(RegistryPath,
+                                         DriverClassName,
+                                         DriverObject,
+                                         DeviceObject,
+                                         PCIBus,
+                                         BusNumber,
+                                         SlotNumber,
+                                         AllocatedResources);
+    }
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+HalGetBusData(IN BUS_DATA_TYPE BusDataType,
+              IN ULONG BusNumber,
+              IN ULONG SlotNumber,
+              IN PVOID Buffer,
+              IN ULONG Length)
+{
+    /* Call the extended function */
+    return HalGetBusDataByOffset(BusDataType,
+                                 BusNumber,
+                                 SlotNumber,
+                                 Buffer,
+                                 0,
+                                 Length);
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
+                      IN ULONG BusNumber,
+                      IN ULONG SlotNumber,
+                      IN PVOID Buffer,
+                      IN ULONG Offset,
+                      IN ULONG Length)
+{
+    BUS_HANDLER BusHandler;
+
+    /* Look as the bus type */
+    if (BusDataType == Cmos)
+    {
+        /* Call CMOS Function */
+        return HalpGetCmosData(0, SlotNumber, Buffer, Length);
+    }
+    else if (BusDataType == EisaConfiguration)
+    {
+        /* FIXME: TODO */
+        KEBUGCHECK(0);
+    }
+    else if ((BusDataType == PCIConfiguration) &&
+             (HalpPCIConfigInitialized) &&
+             ((BusNumber >= HalpMinPciBus) && (BusNumber <= HalpMaxPciBus)))
+    {
+        /* Setup fake PCI Bus handler */
+        RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
+        BusHandler.BusNumber = BusNumber;
+
+        /* Call PCI function */
+        return HalpGetPCIData(&BusHandler,
+                              &BusHandler,
+                              *(PPCI_SLOT_NUMBER)&SlotNumber,
+                              Buffer,
+                              Offset,
+                              Length);
+    }
+
+    /* Invalid bus */
+    return 0;
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType,
+                      IN ULONG BusNumber,
+                      IN ULONG BusInterruptLevel,
+                      IN ULONG BusInterruptVector,
+                      OUT PKIRQL Irql,
+                      OUT PKAFFINITY Affinity)
+{
+    /* Call the system bus translator */
+    return HalpGetSystemInterruptVector(BusNumber,
+                                        BusInterruptLevel,
+                                        BusInterruptVector,
+                                        Irql,
+                                        Affinity);
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+HalSetBusData(IN BUS_DATA_TYPE BusDataType,
+              IN ULONG BusNumber,
+              IN ULONG SlotNumber,
+              IN PVOID Buffer,
+              IN ULONG Length)
+{
+    /* Call the extended function */
+    return HalSetBusDataByOffset(BusDataType,
+                                 BusNumber,
+                                 SlotNumber,
+                                 Buffer,
+                                 0,
+                                 Length);
+}
+
+/*
+ * @implemented
+ */
+ULONG
+NTAPI
+HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
+                      IN ULONG BusNumber,
+                      IN ULONG SlotNumber,
+                      IN PVOID Buffer,
+                      IN ULONG Offset,
+                      IN ULONG Length)
+{
+    BUS_HANDLER BusHandler;
+
+    /* Look as the bus type */
+    if (BusDataType == Cmos)
+    {
+        /* Call CMOS Function */
+        return HalpSetCmosData(0, SlotNumber, Buffer, Length);
+    }
+    else if ((BusDataType == PCIConfiguration) && (HalpPCIConfigInitialized))
+    {
+        /* Setup fake PCI Bus handler */
+        RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
+        BusHandler.BusNumber = BusNumber;
+
+        /* Call PCI function */
+        return HalpSetPCIData(&BusHandler,
+                              &BusHandler,
+                              *(PPCI_SLOT_NUMBER)&SlotNumber,
+                              Buffer,
+                              Offset,
+                              Length);
+    }
+
+    /* Invalid bus */
+    return 0;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
+                       IN ULONG BusNumber,
+                       IN PHYSICAL_ADDRESS BusAddress,
+                       IN OUT PULONG AddressSpace,
+                       OUT PPHYSICAL_ADDRESS TranslatedAddress)
+{
+    /* Look as the bus type */
+    if (InterfaceType == PCIBus)
+    {
+        /* Call the PCI registered function */
+        return HalPciTranslateBusAddress(PCIBus,
+                                         BusNumber,
+                                         BusAddress,
+                                         AddressSpace,
+                                         TranslatedAddress);
+    }
+    else
+    {
+        /* Translation is easy */
+        TranslatedAddress->QuadPart = BusAddress.QuadPart;
+        return TRUE;
+    }
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/cmos.c b/reactos/hal/halppc/generic/cmos.c
new file mode 100644 (file)
index 0000000..14cd589
--- /dev/null
@@ -0,0 +1,291 @@
+/*\r
+ * PROJECT:         ReactOS HAL\r
+ * LICENSE:         GPL - See COPYING in the top level directory\r
+ * FILE:            hal/halx86/generic/cmos.c\r
+ * PURPOSE:         CMOS Access Routines (Real Time Clock and LastKnownGood)\r
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)\r
+ *                  Eric Kohl (ekohl@abo.rhein-zeitung.de)\r
+ */\r
+\r
+/* INCLUDES ******************************************************************/\r
+\r
+#include <hal.h>\r
+#define NDEBUG\r
+#include <debug.h>\r
+\r
+/* GLOBALS *******************************************************************/\r
+\r
+KSPIN_LOCK HalpSystemHardwareLock;\r
+\r
+/* PRIVATE FUNCTIONS *********************************************************/\r
+\r
+UCHAR\r
+FORCEINLINE\r
+HalpReadCmos(IN UCHAR Reg)\r
+{\r
+    /* Select the register */\r
+    WRITE_PORT_UCHAR(CMOS_CONTROL_PORT, Reg);\r
+\r
+    /* Query the value */\r
+    return READ_PORT_UCHAR(CMOS_DATA_PORT);\r
+}\r
+\r
+VOID\r
+FORCEINLINE\r
+HalpWriteCmos(IN UCHAR Reg,\r
+              IN UCHAR Value)\r
+{\r
+    /* Select the register */\r
+    WRITE_PORT_UCHAR(CMOS_CONTROL_PORT, Reg);\r
+\r
+    /* Write the value */\r
+    WRITE_PORT_UCHAR(CMOS_DATA_PORT, Value);\r
+}\r
+\r
+ULONG\r
+NTAPI\r
+HalpGetCmosData(IN ULONG BusNumber,\r
+                IN ULONG SlotNumber,\r
+                IN PVOID Buffer,\r
+                IN ULONG Length)\r
+{\r
+    PUCHAR Ptr = (PUCHAR)Buffer;\r
+    ULONG Address = SlotNumber;\r
+    ULONG Len = Length;\r
+\r
+    /* FIXME: Acquire CMOS Lock */\r
+\r
+    /* Do nothing if we don't have a length */\r
+    if (!Length) return 0;\r
+\r
+    /* Check if this is simple CMOS */\r
+    if (!BusNumber)\r
+    {\r
+        /* Loop the buffer up to 0xFF */\r
+        while ((Len > 0) && (Address < 0x100))\r
+        {\r
+            /* Read the data */\r
+            *Ptr = HalpReadCmos((UCHAR)Address);\r
+\r
+            /* Update position and length */\r
+            Ptr++;\r
+            Address++;\r
+            Len--;\r
+        }\r
+    }\r
+    else if (BusNumber == 1)\r
+    {\r
+        /* Loop the buffer up to 0xFFFF */\r
+        while ((Len > 0) && (Address < 0x10000))\r
+        {\r
+            /* Write the data */\r
+            *Ptr = HalpReadCmos((UCHAR)Address);\r
+\r
+            /* Update position and length */\r
+            Ptr++;\r
+            Address++;\r
+            Len--;\r
+        }\r
+    }\r
+\r
+    /* FIXME: Release the CMOS Lock */\r
+\r
+    /* Return length read */\r
+    return Length - Len;\r
+}\r
+\r
+ULONG\r
+NTAPI\r
+HalpSetCmosData(IN ULONG BusNumber,\r
+                IN ULONG SlotNumber,\r
+                IN PVOID Buffer,\r
+                IN ULONG Length)\r
+{\r
+    PUCHAR Ptr = (PUCHAR)Buffer;\r
+    ULONG Address = SlotNumber;\r
+    ULONG Len = Length;\r
+\r
+    /* FIXME: Acquire CMOS Lock */\r
+\r
+    /* Do nothing if we don't have a length */\r
+    if (!Length) return 0;\r
+\r
+    /* Check if this is simple CMOS */\r
+    if (!BusNumber)\r
+    {\r
+        /* Loop the buffer up to 0xFF */\r
+        while ((Len > 0) && (Address < 0x100))\r
+        {\r
+            /* Write the data */\r
+            HalpWriteCmos((UCHAR)Address, *Ptr);\r
+\r
+            /* Update position and length */\r
+            Ptr++;\r
+            Address++;\r
+            Len--;\r
+        }\r
+    }\r
+    else if (BusNumber == 1)\r
+    {\r
+        /* Loop the buffer up to 0xFFFF */\r
+        while ((Len > 0) && (Address < 0x10000))\r
+        {\r
+            /* Write the data */\r
+            HalpWriteCmos((UCHAR)Address, *Ptr);\r
+\r
+            /* Update position and length */\r
+            Ptr++;\r
+            Address++;\r
+            Len--;\r
+        }\r
+    }\r
+\r
+    /* FIXME: Release the CMOS Lock */\r
+\r
+    /* Return length read */\r
+    return Length - Len;\r
+}\r
+\r
+/* PUBLIC FUNCTIONS **********************************************************/\r
+\r
+/*\r
+ * @implemented\r
+ */\r
+ARC_STATUS\r
+NTAPI\r
+HalGetEnvironmentVariable(IN PCH Name,\r
+                          IN USHORT ValueLength,\r
+                          IN PCH Value)\r
+{\r
+    UCHAR Val;\r
+\r
+    /* Only variable supported on x86 */\r
+    if (_stricmp(Name, "LastKnownGood")) return ENOENT;\r
+\r
+    /* FIXME: Acquire CMOS Lock */\r
+\r
+    /* Query the current value */\r
+    Val = HalpReadCmos(RTC_REGISTER_B) & 0x01;\r
+\r
+    /* FIXME: Release CMOS lock */\r
+\r
+    /* Check the flag */\r
+    if (Val)\r
+    {\r
+        /* Return false */\r
+        strncpy(Value, "FALSE", ValueLength);\r
+    }\r
+    else\r
+    {\r
+        /* Return true */\r
+        strncpy(Value, "TRUE", ValueLength);\r
+    }\r
+\r
+    /* Return success */\r
+    return ESUCCESS;\r
+}\r
+\r
+/*\r
+ * @implemented\r
+ */\r
+ARC_STATUS\r
+NTAPI\r
+HalSetEnvironmentVariable(IN PCH Name,\r
+                          IN PCH Value)\r
+{\r
+    UCHAR Val;\r
+\r
+    /* Only variable supported on x86 */\r
+    if (_stricmp(Name, "LastKnownGood")) return ENOMEM;\r
+\r
+    /* Check if this is true or false */\r
+    if (!_stricmp(Value, "TRUE"))\r
+    {\r
+        /* It's true, acquire CMOS lock (FIXME) */\r
+\r
+        /* Read the current value and add the flag */\r
+        Val = HalpReadCmos(RTC_REGISTER_B) | 1;\r
+    }\r
+    else if (!_stricmp(Value, "FALSE"))\r
+    {\r
+        /* It's false, acquire CMOS lock (FIXME) */\r
+\r
+        /* Read the current value and mask out  the flag */\r
+        Val = HalpReadCmos(RTC_REGISTER_B) & ~1;\r
+    }\r
+    else\r
+    {\r
+        /* Fail */\r
+        return ENOMEM;\r
+    }\r
+\r
+    /* Write new value */\r
+    HalpWriteCmos(RTC_REGISTER_B, Val);\r
+\r
+    /* Release the lock and return success */\r
+    return ESUCCESS;\r
+}\r
+\r
+/*\r
+ * @implemented\r
+ */\r
+BOOLEAN\r
+NTAPI\r
+HalQueryRealTimeClock(OUT PTIME_FIELDS Time)\r
+{\r
+    /* FIXME: Acquire CMOS Lock */\r
+\r
+    /* Loop while update is in progress */\r
+    while ((HalpReadCmos(RTC_REGISTER_A)) & RTC_REG_A_UIP);\r
+\r
+    /* Set the time data */\r
+    Time->Second = BCD_INT(HalpReadCmos(0));\r
+    Time->Minute = BCD_INT(HalpReadCmos(2));\r
+    Time->Hour = BCD_INT(HalpReadCmos(4));\r
+    Time->Weekday = BCD_INT(HalpReadCmos(6));\r
+    Time->Day = BCD_INT(HalpReadCmos(7));\r
+    Time->Month = BCD_INT(HalpReadCmos(8));\r
+    Time->Year = BCD_INT(HalpReadCmos(9));\r
+    Time->Milliseconds = 0;\r
+\r
+    /* FIXME: Check century byte */\r
+\r
+    /* Compensate for the century field */\r
+    Time->Year += (Time->Year > 80) ? 1900: 2000;\r
+\r
+    /* FIXME: Release CMOS Lock */\r
+\r
+    /* Always return TRUE */\r
+    return TRUE;\r
+}\r
+\r
+/*\r
+ * @implemented\r
+ */\r
+BOOLEAN\r
+NTAPI\r
+HalSetRealTimeClock(IN PTIME_FIELDS Time)\r
+{\r
+    /* FIXME: Acquire CMOS Lock */\r
+\r
+    /* Loop while update is in progress */\r
+    while ((HalpReadCmos(RTC_REGISTER_A)) & RTC_REG_A_UIP);\r
+\r
+    /* Write time fields to CMOS RTC */\r
+    HalpWriteCmos(0, INT_BCD(Time->Second));\r
+    HalpWriteCmos(2, INT_BCD(Time->Minute));\r
+    HalpWriteCmos(4, INT_BCD(Time->Hour));\r
+    HalpWriteCmos(6, INT_BCD(Time->Weekday));\r
+    HalpWriteCmos(7, INT_BCD(Time->Day));\r
+    HalpWriteCmos(8, INT_BCD(Time->Month));\r
+    HalpWriteCmos(9, INT_BCD(Time->Year % 100));\r
+\r
+    /* FIXME: Set the century byte */\r
+\r
+    /* FIXME: Release the CMOS Lock */\r
+\r
+    /* Always return TRUE */\r
+    return TRUE;\r
+}\r
+\r
+/* EOF */\r
diff --git a/reactos/hal/halppc/generic/display.c b/reactos/hal/halppc/generic/display.c
new file mode 100644 (file)
index 0000000..4e0d8ed
--- /dev/null
@@ -0,0 +1,385 @@
+/*
+ *  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 <hal.h>
+#include <rosldr.h>
+#include <ppcboot.h>
+#include <ppcdebug.h>
+
+#define NDEBUG
+#include <debug.h>
+
+boot_infos_t PpcEarlybootInfo;
+
+#define SCREEN_SYNCHRONIZATION
+
+/* 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 ULONG GraphVideoBuffer = 0;
+static PHAL_RESET_DISPLAY_PARAMETERS HalResetDisplayParameters = NULL;
+
+extern UCHAR XboxFont8x16[];
+extern void SetPhys( ULONG Addr, ULONG Data );
+extern ULONG GetPhys( ULONG Addr );
+extern void SetPhysByte( ULONG Addr, ULONG Data );
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID FASTCALL
+HalClearDisplay (UCHAR CharAttribute)
+{
+   ULONG i;
+   ULONG deviceSize = 
+       PpcEarlybootInfo.dispDeviceRowBytes *
+       PpcEarlybootInfo.dispDeviceRect[3];
+   for(i = 0; i < deviceSize; i += sizeof(int) ) 
+       SetPhys(GraphVideoBuffer + i, CharAttribute);
+
+   CursorX = 0;
+   CursorY = 0;
+}
+
+
+/* STATIC FUNCTIONS *********************************************************/
+
+VOID STATIC
+HalScrollDisplay (VOID)
+{
+    ULONG i, deviceSize = 
+       PpcEarlybootInfo.dispDeviceRowBytes *
+       PpcEarlybootInfo.dispDeviceRect[3];
+    ULONG Dest = (ULONG)GraphVideoBuffer, 
+       Src = (ULONG)(GraphVideoBuffer + (16 * PpcEarlybootInfo.dispDeviceRowBytes));
+    ULONG End  = (ULONG)
+       GraphVideoBuffer + 
+       (PpcEarlybootInfo.dispDeviceRowBytes *
+        (PpcEarlybootInfo.dispDeviceRect[3]-16));
+    
+    while( Src < End ) 
+    {
+       SetPhys((ULONG)Dest, GetPhys(Src));
+       Src += 4; Dest += 4;
+    }
+
+    /* Clear the bottom row */
+    for(i = End; i < deviceSize; i += sizeof(int) ) 
+       SetPhys(GraphVideoBuffer + i, 1);
+}
+
+VOID STATIC FASTCALL
+HalPutCharacter (CHAR Character)
+{
+    WRITE_PORT_UCHAR((PVOID)0x3f8, Character);
+#if 0
+    int i,j,k;
+    ULONG Dest =
+       (GraphVideoBuffer + 
+        (16 * PpcEarlybootInfo.dispDeviceRowBytes * CursorY) + 
+        (8 * (PpcEarlybootInfo.dispDeviceDepth / 8) * CursorX)), RowDest;
+    UCHAR ByteToPlace;
+
+    for( i = 0; i < 16; i++ ) {
+       RowDest = Dest;
+       for( j = 0; j < 8; j++ ) {
+           ByteToPlace = ((128 >> j) & (XboxFont8x16[(16 * Character) + i])) ? 0xff : 1;
+           for( k = 0; k < PpcEarlybootInfo.dispDeviceDepth / 8; k++, RowDest++ ) {
+               SetPhysByte(RowDest, ByteToPlace);
+           }
+       }
+       Dest += PpcEarlybootInfo.dispDeviceRowBytes;
+    }
+#endif
+}
+
+/* PRIVATE FUNCTIONS ********************************************************/
+
+VOID FASTCALL
+HalInitializeDisplay (PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
+/*
+ * FUNCTION: Initalize the display
+ * ARGUMENTS:
+ *         InitParameters = Parameters setup by the boot loader
+ */
+{
+    if (! DisplayInitialized)
+    {
+      boot_infos_t *XBootInfo = (boot_infos_t *)LoaderBlock->ArchExtra;
+      GraphVideoBuffer = (ULONG)XBootInfo->dispDeviceBase;
+      memcpy(&PpcEarlybootInfo, XBootInfo, sizeof(*XBootInfo));
+
+      /* Set cursor position */
+      CursorX = 0;
+      CursorY = 0;
+
+      SizeX = XBootInfo->dispDeviceRowBytes / XBootInfo->dispDeviceDepth;
+      SizeY = XBootInfo->dispDeviceRect[3] / 16;
+
+      HalClearDisplay(1);
+
+      DisplayInitialized = TRUE;
+    }
+}
+
+
+/* PUBLIC FUNCTIONS *********************************************************/
+
+VOID STDCALL
+HalReleaseDisplayOwnership(VOID)
+/*
+ * FUNCTION: Release ownership of display back to HAL
+ */
+{
+  if (HalResetDisplayParameters == NULL)
+    return;
+
+  if (HalOwnsDisplay == TRUE)
+    return;
+
+  HalOwnsDisplay = TRUE;
+  HalClearDisplay(0);
+}
+
+
+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;
+  //static KSPIN_LOCK Lock;
+  KIRQL OldIrql;
+  BOOLEAN InterruptsEnabled = __readmsr();
+
+  /* See comment at top of file */
+  if (! HalOwnsDisplay || ! DisplayInitialized)
+    {
+      return;
+    }
+
+  pch = String;
+
+  KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+  //KiAcquireSpinLock(&Lock);
+
+  _disable();
+  
+  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++;
+    }
+
+  __writemsr(InterruptsEnabled);
+
+  //KiReleaseSpinLock(&Lock);
+  KeLowerIrql(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 (file)
index 0000000..f0d7f0a
--- /dev/null
@@ -0,0 +1,2024 @@
+/* $Id: dma.c 24759 2006-11-14 20:59:48Z ion $
+ *
+ * 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 <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+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 = (USHORT)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 = (UCHAR)(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.
+       */
+
+      KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+      IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0);
+      KeLowerIrql(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;
+   PHYSICAL_ADDRESS HighestAcceptableAddress;
+   PHYSICAL_ADDRESS PhysicalAddress;
+   PPFN_NUMBER MdlPagesPtr;
+
+   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
+      {
+         MdlPagesPtr = MmGetMdlPfnArray(Mdl);
+         MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
+
+         PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
+         PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa);
+
+         HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject);
+         if (PhysicalAddress.QuadPart + Length >
+             HighestAcceptableAddress.QuadPart)
+         {
+            HalpCopyBufferMap(Mdl, RealMapRegisterBase, CurrentVa, Length, 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[Counter].PhysicalAddress;
+         PhysicalAddress.QuadPart += ByteOffset;
+         if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG)
+         {
+            RealMapRegisterBase->Counter = ~0;
+            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
+NTAPI
+HalFlushCommonBuffer(IN PADAPTER_OBJECT AdapterObject,
+                     IN ULONG Length,
+                     IN PHYSICAL_ADDRESS LogicalAddress,
+                     IN PVOID VirtualAddress)
+{
+    /* Function always returns true */
+    return TRUE;
+}
+
+/*
+ * @implemented
+ */
+PVOID
+NTAPI
+HalAllocateCrashDumpRegisters(IN PADAPTER_OBJECT AdapterObject,
+                              IN OUT PULONG NumberOfMapRegisters)
+{
+    PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
+    ULONG MapRegisterNumber;
+
+    /* Check if it needs map registers */
+    if (AdapterObject->NeedsMapRegisters)
+    {
+        /* Check if we have enough */
+        if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
+        {
+            /* We don't, fail */
+            AdapterObject->NumberOfMapRegisters = 0;
+            return NULL;
+        }
+
+        /* Try to find free map registers */
+        MapRegisterNumber = -1;
+        MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
+                                                   *NumberOfMapRegisters,
+                                                   0);
+
+        /* Check if nothing was found */
+        if (MapRegisterNumber == -1)
+        {
+            /* No free registers found, so use the base registers */
+            RtlSetBits(MasterAdapter->MapRegisters,
+                       0,
+                       *NumberOfMapRegisters);
+            MapRegisterNumber = 0;
+        }
+
+        /* Calculate the new base */
+        AdapterObject->MapRegisterBase =
+            (PROS_MAP_REGISTER_ENTRY)(MasterAdapter->MapRegisterBase +
+                                      MapRegisterNumber);
+
+        /* Check if scatter gather isn't supported */
+        if (!AdapterObject->ScatterGather)
+        {
+            /* Set the flag */
+            AdapterObject->MapRegisterBase =
+                (PROS_MAP_REGISTER_ENTRY)
+                ((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
+        }
+    }
+    else
+    {
+        AdapterObject->MapRegisterBase = NULL;
+        AdapterObject->NumberOfMapRegisters = 0;
+    }
+
+    /* Return the base */
+    return AdapterObject->MapRegisterBase;
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/drive.c b/reactos/hal/halppc/generic/drive.c
new file mode 100644 (file)
index 0000000..fc489c9
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * PROJECT:         ReactOS HAL
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            hal/halx86/generic/drive.c
+ * PURPOSE:         I/O HAL Routines for Disk Access
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+NTAPI
+HalpAssignDriveLetters(IN struct _LOADER_PARAMETER_BLOCK *LoaderBlock,
+                       IN PSTRING NtDeviceName,
+                       OUT PUCHAR NtSystemPath,
+                       OUT PSTRING NtSystemPathString)
+{
+    /* Call the kernel */
+    IoAssignDriveLetters(LoaderBlock,
+                         NtDeviceName,
+                         NtSystemPath,
+                         NtSystemPathString);
+}
+
+NTSTATUS
+NTAPI
+HalpReadPartitionTable(IN PDEVICE_OBJECT DeviceObject,
+                       IN ULONG SectorSize,
+                       IN BOOLEAN ReturnRecognizedPartitions,
+                       IN OUT PDRIVE_LAYOUT_INFORMATION *PartitionBuffer)
+{
+    /* Call the kernel */
+    return IoReadPartitionTable(DeviceObject,
+                                SectorSize,
+                                ReturnRecognizedPartitions,
+                                PartitionBuffer);
+}
+
+NTSTATUS
+NTAPI
+HalpWritePartitionTable(IN PDEVICE_OBJECT DeviceObject,
+                        IN ULONG SectorSize,
+                        IN ULONG SectorsPerTrack,
+                        IN ULONG NumberOfHeads,
+                        IN PDRIVE_LAYOUT_INFORMATION PartitionBuffer)
+{
+    /* Call the kernel */
+    return IoWritePartitionTable(DeviceObject,
+                                 SectorSize,
+                                 SectorsPerTrack,
+                                 NumberOfHeads,
+                                 PartitionBuffer);
+}
+
+NTSTATUS
+NTAPI
+HalpSetPartitionInformation(IN PDEVICE_OBJECT DeviceObject,
+                            IN ULONG SectorSize,
+                            IN ULONG PartitionNumber,
+                            IN ULONG PartitionType)
+{
+    /* Call the kernel */
+    return IoSetPartitionInformation(DeviceObject,
+                                     SectorSize,
+                                     PartitionNumber,
+                                     PartitionType);
+}
+/* EOF */
diff --git a/reactos/hal/halppc/generic/enum.c b/reactos/hal/halppc/generic/enum.c
new file mode 100644 (file)
index 0000000..af8b06d
--- /dev/null
@@ -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 <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+VOID
+HalpStartEnumerator (VOID)
+{
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/fmutex.c b/reactos/hal/halppc/generic/fmutex.c
new file mode 100644 (file)
index 0000000..8ec41f4
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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 <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+#undef ExAcquireFastMutex
+#undef ExReleaseFastMutex
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+FASTCALL
+ExAcquireFastMutex(PFAST_MUTEX FastMutex)
+{
+    KIRQL OldIrql;
+
+    /* Raise IRQL to APC */
+    KeRaiseIrql(APC_LEVEL, &OldIrql);
+
+    /* 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 */
+    KeLowerIrql(OldIrql);
+}
+
+BOOLEAN
+FASTCALL
+ExiTryToAcquireFastMutex(PFAST_MUTEX FastMutex)
+{
+    KIRQL OldIrql;
+
+    /* Raise to APC_LEVEL */
+    KeRaiseIrql(APC_LEVEL, &OldIrql);
+
+    /* 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 */
+        KeLowerIrql(OldIrql);
+        return FALSE;
+    }
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/font.c b/reactos/hal/halppc/generic/font.c
new file mode 100644 (file)
index 0000000..570cc5f
--- /dev/null
@@ -0,0 +1,278 @@
+/* $Id: font.c 21840 2006-05-07 18:56:52Z ion $
+ *
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         Xbox HAL
+ * FILE:            hal/halx86/xbox/font.h
+ * PURPOSE:         Font glyphs
+ * PROGRAMMER:      Ge van Geldorp (gvg@reactos.com)
+ * UPDATE HISTORY:
+ *                  Created 2004/12/02
+ *
+ * Note: Converted from the XFree vga.bdf font
+ */
+
+#define NDEBUG
+#include <debug.h>
+
+unsigned char XboxFont8x16[256 * 16] =
+{
+  0x00,0x00,0x00,0x7c,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00, /* 0x00 */
+  0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xa5,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, /* 0x01 */
+  0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xdb,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00, /* 0x02 */
+  0x00,0x00,0x00,0x00,0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00, /* 0x03 */
+  0x00,0x00,0x00,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,0x00, /* 0x04 */
+  0x00,0x00,0x00,0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, /* 0x05 */
+  0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, /* 0x06 */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x07 */
+  0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff, /* 0x08 */
+  0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0x00,0x00,0x00,0x00, /* 0x09 */
+  0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff, /* 0x0a */
+  0x00,0x00,0x1e,0x06,0x0e,0x1a,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, /* 0x0b */
+  0x00,0x00,0x3c,0x66,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00, /* 0x0c */
+  0x00,0x00,0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0,0x00,0x00,0x00,0x00, /* 0x0d */
+  0x00,0x00,0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0,0x00,0x00,0x00, /* 0x0e */
+  0x00,0x00,0x00,0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18,0x00,0x00,0x00,0x00, /* 0x0f */
+  0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00, /* 0x10 */
+  0x00,0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, /* 0x11 */
+  0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,0x00, /* 0x12 */
+  0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, /* 0x13 */
+  0x00,0x00,0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00, /* 0x14 */
+  0x00,0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00, /* 0x15 */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe,0x00,0x00,0x00,0x00, /* 0x16 */
+  0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, /* 0x17 */
+  0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, /* 0x18 */
+  0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00, /* 0x19 */
+  0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x1a */
+  0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x1b */
+  0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x1c */
+  0x00,0x00,0x00,0x00,0x00,0x28,0x6c,0xfe,0x6c,0x28,0x00,0x00,0x00,0x00,0x00,0x00, /* 0x1d */
+  0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00, /* 0x1e */
+  0x00,0x00,0x00,0x00,0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, /* 0x1f */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /*   */
+  0x00,0x00,0x18,0x3c,0x3c,0x3c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, /* ! */
+  0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* " */
+  0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c,0x00,0x00,0x00,0x00, /* # */
+  0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18,0x00,0x00, /* $ */
+  0x00,0x00,0x00,0x00,0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86,0x00,0x00,0x00,0x00, /* % */
+  0x00,0x00,0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, /* & */
+  0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ' */
+  0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00,0x00,0x00, /* ( */
+  0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00,0x00, /* ) */
+  0x00,0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x00,0x00,0x00, /* * */
+  0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, /* + */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00, /* , */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* - */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, /* . */
+  0x00,0x00,0x00,0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,0x00,0x00,0x00, /* / */
+  0x00,0x00,0x38,0x6c,0xc6,0xc6,0xd6,0xd6,0xc6,0xc6,0x6c,0x38,0x00,0x00,0x00,0x00, /* 0 */
+  0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00, /* 1 */
+  0x00,0x00,0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe,0x00,0x00,0x00,0x00, /* 2 */
+  0x00,0x00,0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 3 */
+  0x00,0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, /* 4 */
+  0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 5 */
+  0x00,0x00,0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 6 */
+  0x00,0x00,0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, /* 7 */
+  0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 8 */
+  0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78,0x00,0x00,0x00,0x00, /* 9 */
+  0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, /* : */
+  0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00, /* ; */
+  0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00, /* < */
+  0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* = */
+  0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,0x00, /* > */
+  0x00,0x00,0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, /* ? */
+  0x00,0x00,0x00,0x7c,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00, /* @ */
+  0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, /* A */
+  0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc,0x00,0x00,0x00,0x00, /* B */
+  0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x00,0x00,0x00,0x00, /* C */
+  0x00,0x00,0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8,0x00,0x00,0x00,0x00, /* D */
+  0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, /* E */
+  0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, /* F */
+  0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a,0x00,0x00,0x00,0x00, /* G */
+  0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, /* H */
+  0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, /* I */
+  0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, /* J */
+  0x00,0x00,0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, /* K */
+  0x00,0x00,0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, /* L */
+  0x00,0x00,0xc6,0xee,0xfe,0xfe,0xd6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, /* M */
+  0x00,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, /* N */
+  0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, /* O */
+  0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, /* P */
+  0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e,0x00,0x00, /* Q */
+  0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, /* R */
+  0x00,0x00,0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, /* S */
+  0x00,0x00,0x7e,0x7e,0x5a,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, /* T */
+  0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, /* U */
+  0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x6c,0x38,0x10,0x00,0x00,0x00,0x00, /* V */
+  0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xd6,0xd6,0xd6,0xfe,0xee,0x6c,0x00,0x00,0x00,0x00, /* W */
+  0x00,0x00,0xc6,0xc6,0x6c,0x7c,0x38,0x38,0x7c,0x6c,0xc6,0xc6,0x00,0x00,0x00,0x00, /* X */
+  0x00,0x00,0x66,0x66,0x66,0x66,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, /* Y */
+  0x00,0x00,0xfe,0xc6,0x86,0x0c,0x18,0x30,0x60,0xc2,0xc6,0xfe,0x00,0x00,0x00,0x00, /* Z */
+  0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,0x00, /* [ */
+  0x00,0x00,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, /* \ */
+  0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,0x00, /* ] */
+  0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ^ */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00, /* _ */
+  0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ` */
+  0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, /* a */
+  0x00,0x00,0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x00, /* b */
+  0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, /* c */
+  0x00,0x00,0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, /* d */
+  0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, /* e */
+  0x00,0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, /* f */
+  0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78,0x00, /* g */
+  0x00,0x00,0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, /* h */
+  0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, /* i */
+  0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00, /* j */
+  0x00,0x00,0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6,0x00,0x00,0x00,0x00, /* k */
+  0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, /* l */
+  0x00,0x00,0x00,0x00,0x00,0xec,0xfe,0xd6,0xd6,0xd6,0xd6,0xc6,0x00,0x00,0x00,0x00, /* m */
+  0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, /* n */
+  0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, /* o */
+  0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00, /* p */
+  0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e,0x00, /* q */
+  0x00,0x00,0x00,0x00,0x00,0xdc,0x76,0x66,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, /* r */
+  0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,0x00, /* s */
+  0x00,0x00,0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c,0x00,0x00,0x00,0x00, /* t */
+  0x00,0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, /* u */
+  0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, /* v */
+  0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xd6,0xd6,0xd6,0xfe,0x6c,0x00,0x00,0x00,0x00, /* w */
+  0x00,0x00,0x00,0x00,0x00,0xc6,0x6c,0x38,0x38,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00, /* x */
+  0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00, /* y */
+  0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, /* z */
+  0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00, /* { */
+  0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, /* | */
+  0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, /* } */
+  0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* ~ */
+  0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00, /* 0x7f */
+  0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c,0x00,0x00, /* 0x80 */
+  0x00,0x00,0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, /* 0x81 */
+  0x00,0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 0x82 */
+  0x00,0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, /* 0x83 */
+  0x00,0x00,0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, /* 0x84 */
+  0x00,0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, /* 0x85 */
+  0x00,0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, /* 0x86 */
+  0x00,0x00,0x00,0x00,0x3c,0x66,0x60,0x60,0x66,0x3c,0x0c,0x06,0x3c,0x00,0x00,0x00, /* 0x87 */
+  0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 0x88 */
+  0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 0x89 */
+  0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 0x8a */
+  0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, /* 0x8b */
+  0x00,0x18,0x3c,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, /* 0x8c */
+  0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, /* 0x8d */
+  0x00,0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, /* 0x8e */
+  0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, /* 0x8f */
+  0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe,0x00,0x00,0x00,0x00, /* 0x90 */
+  0x00,0x00,0x00,0x00,0x00,0xcc,0x76,0x36,0x7e,0xd8,0xd8,0x6e,0x00,0x00,0x00,0x00, /* 0x91 */
+  0x00,0x00,0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce,0x00,0x00,0x00,0x00, /* 0x92 */
+  0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 0x93 */
+  0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 0x94 */
+  0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 0x95 */
+  0x00,0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, /* 0x96 */
+  0x00,0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, /* 0x97 */
+  0x00,0x00,0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00, /* 0x98 */
+  0x00,0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 0x99 */
+  0x00,0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 0x9a */
+  0x00,0x18,0x18,0x3c,0x66,0x60,0x60,0x60,0x66,0x3c,0x18,0x18,0x00,0x00,0x00,0x00, /* 0x9b */
+  0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc,0x00,0x00,0x00,0x00, /* 0x9c */
+  0x00,0x00,0x66,0x66,0x3c,0x18,0x7e,0x18,0x7e,0x18,0x18,0x18,0x00,0x00,0x00,0x00, /* 0x9d */
+  0x00,0xf8,0xcc,0xcc,0xf8,0xc4,0xcc,0xde,0xcc,0xcc,0xcc,0xc6,0x00,0x00,0x00,0x00, /* 0x9e */
+  0x00,0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70,0x00,0x00, /* 0x9f */
+  0x00,0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, /* 0xa0 */
+  0x00,0x0c,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, /* 0xa1 */
+  0x00,0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 0xa2 */
+  0x00,0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, /* 0xa3 */
+  0x00,0x00,0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, /* 0xa4 */
+  0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, /* 0xa5 */
+  0x00,0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xa6 */
+  0x00,0x38,0x6c,0x6c,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xa7 */
+  0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, /* 0xa8 */
+  0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00, /* 0xa9 */
+  0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, /* 0xaa */
+  0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xdc,0x86,0x0c,0x18,0x3e,0x00,0x00, /* 0xab */
+  0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x9e,0x3e,0x06,0x06,0x00,0x00, /* 0xac */
+  0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3c,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00, /* 0xad */
+  0x00,0x00,0x00,0x00,0x00,0x36,0x6c,0xd8,0x6c,0x36,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xae */
+  0x00,0x00,0x00,0x00,0x00,0xd8,0x6c,0x36,0x6c,0xd8,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xaf */
+  0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, /* 0xb0 */
+  0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, /* 0xb1 */
+  0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77, /* 0xb2 */
+  0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xb3 */
+  0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xb4 */
+  0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xb5 */
+  0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 0xb6 */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 0xb7 */
+  0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xb8 */
+  0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 0xb9 */
+  0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 0xba */
+  0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 0xbb */
+  0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xbc */
+  0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xbd */
+  0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xbe */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xbf */
+  0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xc0 */
+  0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xc1 */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xc2 */
+  0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xc3 */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xc4 */
+  0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xc5 */
+  0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xc6 */
+  0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 0xc7 */
+  0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xc8 */
+  0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 0xc9 */
+  0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xca */
+  0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 0xcb */
+  0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 0xcc */
+  0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xcd */
+  0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 0xce */
+  0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xcf */
+  0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xd0 */
+  0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xd1 */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 0xd2 */
+  0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xd3 */
+  0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xd4 */
+  0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xd5 */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 0xd6 */
+  0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 0xd7 */
+  0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xd8 */
+  0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xd9 */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xda */
+  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0xdb */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 0xdc */
+  0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, /* 0xdd */
+  0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, /* 0xde */
+  0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xdf */
+  0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76,0x00,0x00,0x00,0x00, /* 0xe0 */
+  0x00,0x00,0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc,0x00,0x00,0x00,0x00, /* 0xe1 */
+  0x00,0x00,0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, /* 0xe2 */
+  0x00,0x00,0x00,0x00,0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00, /* 0xe3 */
+  0x00,0x00,0x00,0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, /* 0xe4 */
+  0x00,0x00,0x00,0x00,0x00,0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, /* 0xe5 */
+  0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0,0x00,0x00,0x00, /* 0xe6 */
+  0x00,0x00,0x00,0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, /* 0xe7 */
+  0x00,0x00,0x00,0x7e,0x18,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, /* 0xe8 */
+  0x00,0x00,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38,0x00,0x00,0x00,0x00, /* 0xe9 */
+  0x00,0x00,0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee,0x00,0x00,0x00,0x00, /* 0xea */
+  0x00,0x00,0x1e,0x30,0x18,0x0c,0x3e,0x66,0x66,0x66,0x66,0x3c,0x00,0x00,0x00,0x00, /* 0xeb */
+  0x00,0x00,0x00,0x00,0x00,0x7e,0xdb,0xdb,0xdb,0x7e,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xec */
+  0x00,0x00,0x00,0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0,0x00,0x00,0x00,0x00, /* 0xed */
+  0x00,0x00,0x1c,0x30,0x60,0x60,0x7c,0x60,0x60,0x60,0x30,0x1c,0x00,0x00,0x00,0x00, /* 0xee */
+  0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, /* 0xef */
+  0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00, /* 0xf0 */
+  0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff,0x00,0x00,0x00,0x00, /* 0xf1 */
+  0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00,0x7e,0x00,0x00,0x00,0x00, /* 0xf2 */
+  0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x7e,0x00,0x00,0x00,0x00, /* 0xf3 */
+  0x00,0x00,0x0e,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 0xf4 */
+  0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, /* 0xf5 */
+  0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7e,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, /* 0xf6 */
+  0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xf7 */
+  0x00,0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xf8 */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xf9 */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xfa */
+  0x00,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c,0x00,0x00,0x00,0x00, /* 0xfb */
+  0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xfc */
+  0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 0xfd */
+  0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00, /* 0xfe */
+  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00  /* 0xff */
+};
+
+/* EOF */
+
diff --git a/reactos/hal/halppc/generic/generic.rbuild b/reactos/hal/halppc/generic/generic.rbuild
new file mode 100644 (file)
index 0000000..dd40b0d
--- /dev/null
@@ -0,0 +1,29 @@
+<module name="halppc_generic" type="objectlibrary">
+       <include base="halppc_generic">../include</include>
+       <include base="ntoskrnl">include</include>
+       <define name="_DISABLE_TIDENTS" />
+       <define name="__USE_W32API" />
+       <define name="_NTHAL_" />
+       <file>beep.c</file>
+       <file>bus.c</file>
+       <file>cmos.c</file>
+       <file>display.c</file>
+       <file>dma.c</file>
+       <file>drive.c</file>
+       <file>enum.c</file>
+       <file>fmutex.c</file>
+       <file>font.c</file>
+       <file>halinit.c</file>
+       <file>irql.c</file>
+       <file>isa.c</file>
+       <file>misc.c</file>
+       <file>pci.c</file>
+       <file>portio.c</file>
+       <file>processor.c</file>
+       <file>profil.c</file>
+       <file>reboot.c</file>
+       <file>spinlock.c</file>
+       <file>sysinfo.c</file>
+       <file>timer.c</file>
+       <pch>../include/hal.h</pch>
+</module>
diff --git a/reactos/hal/halppc/generic/halinit.c b/reactos/hal/halppc/generic/halinit.c
new file mode 100644 (file)
index 0000000..d7a81ad
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * PROJECT:         ReactOS HAL
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            hal/halx86/generic/halinit.c
+ * PURPOSE:         HAL Entrypoint and Initialization
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+
+HALP_HOOKS HalpHooks;
+BOOLEAN HalpPciLockSettings;
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+NTAPI
+HalpGetParameters(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+    PCHAR CommandLine;
+
+    /* Make sure we have a loader block and command line */
+    if ((LoaderBlock) && (LoaderBlock->LoadOptions))
+    {
+        /* Read the command line */
+        CommandLine = LoaderBlock->LoadOptions;
+
+        /* Check if PCI is locked */
+        if (strstr(CommandLine, "PCILOCK")) HalpPciLockSettings = TRUE;
+
+        /* Check for initial breakpoint */
+        if (strstr(CommandLine, "BREAK")) DbgBreakPoint();
+    }
+}
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+HalInitSystem(IN ULONG BootPhase,
+              IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+    KIRQL CurIrql;
+    PKPRCB Prcb = KeGetCurrentPrcb();
+
+    DbgPrint("Prcb: %x BuildType %x\n", Prcb, Prcb->BuildType);
+
+    /* Check the boot phase */
+    if (!BootPhase)
+    {
+        /* Phase 0... save bus type */
+        HalpBusType = LoaderBlock->u.I386.MachineType & 0xFF;
+
+        /* Get command-line parameters */
+        HalpGetParameters(LoaderBlock);
+
+        /* Checked HAL requires checked kernel */
+#if DBG
+        if (!(Prcb->BuildType & PRCB_BUILD_DEBUG))
+        {
+            /* No match, bugcheck */
+            KeBugCheckEx(MISMATCHED_HAL, 2, Prcb->BuildType, 1, 0);
+        }
+#else
+        /* Release build requires release HAL */
+        if (Prcb->BuildType & PRCB_BUILD_DEBUG)
+        {
+            /* No match, bugcheck */
+            KeBugCheckEx(MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+        }
+#endif
+
+#ifdef CONFIG_SMP
+        /* SMP HAL requires SMP kernel */
+        if (Prcb->BuildType & PRCB_BUILD_UNIPROCESSOR)
+        {
+            /* No match, bugcheck */
+            KeBugCheckEx(MISMATCHED_HAL, 2, Prcb->BuildType, 0, 0);
+        }
+#endif
+
+        /* Validate the PRCB */
+        if (Prcb->MajorVersion != PRCB_MAJOR_VERSION)
+        {
+            /* Validation failed, bugcheck */
+            KeBugCheckEx(MISMATCHED_HAL, 1, Prcb->MajorVersion, 1, 0);
+        }
+
+        /* Initialize the PICs */
+        HalpInitPICs();
+
+        /* Force initial PIC state */
+        KeRaiseIrql(KeGetCurrentIrql(), &CurIrql);
+
+        /* Initialize the clock */
+        HalpInitializeClock();
+
+        /* Setup busy waiting */
+        //HalpCalibrateStallExecution();
+
+        /* Fill out the dispatch tables */
+        HalQuerySystemInformation = HaliQuerySystemInformation;
+        HalSetSystemInformation = HaliSetSystemInformation;
+        HalInitPnpDriver = NULL; // FIXME: TODO
+        HalGetDmaAdapter = HalpGetDmaAdapter;
+        HalGetInterruptTranslator = NULL;  // FIXME: TODO
+
+        /* Initialize the hardware lock (CMOS) */
+        KeInitializeSpinLock(&HalpSystemHardwareLock);
+    }
+    else if (BootPhase == 1)
+    {
+        /* Initialize the default HAL stubs for bus handling functions */
+        HalpInitNonBusHandler();
+
+#if 0
+        /* Enable the clock interrupt */
+        ((PKIPCR)KeGetPcr())->IDT[0x30].ExtendedOffset =
+            (USHORT)(((ULONG_PTR)HalpClockInterrupt >> 16) & 0xFFFF);
+        ((PKIPCR)KeGetPcr())->IDT[0x30].Offset =
+            (USHORT)((ULONG_PTR)HalpClockInterrupt);
+#endif
+        HalEnableSystemInterrupt(0x30, CLOCK2_LEVEL, Latched);
+
+        /* Initialize DMA. NT does this in Phase 0 */
+        HalpInitDma();
+    }
+
+    /* All done, return */
+    return TRUE;
+}
+
+/*
+ * @unimplemented
+ */
+VOID
+NTAPI
+HalReportResourceUsage(VOID)
+{
+    /* Initialize PCI bus. */
+    HalpInitializePciBus();
+
+    /* FIXME: This is done in ReactOS MP HAL only*/
+    //HaliReconfigurePciInterrupts();
+
+    /* FIXME: Report HAL Usage to kernel */
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/ipi.c b/reactos/hal/halppc/generic/ipi.c
new file mode 100644 (file)
index 0000000..739de8d
--- /dev/null
@@ -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 <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS ****************************************************************/
+
+VOID STDCALL
+HalRequestIpi(ULONG ProcessorNo)
+{
+  DPRINT("HalRequestIpi(ProcessorNo %lu)\n", ProcessorNo);
+}
+
+/* EOF */
diff --git a/reactos/hal/halppc/generic/irql.c b/reactos/hal/halppc/generic/irql.c
new file mode 100644 (file)
index 0000000..ed3ad45
--- /dev/null
@@ -0,0 +1,450 @@
+/* $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 <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS ******************************************************************/
+
+/*
+ * FIXME: Use EISA_CONTROL STRUCTURE INSTEAD OF HARD-CODED OFFSETS 
+*/
+
+typedef union
+{
+   USHORT both;
+   struct
+   {
+      UCHAR master;
+      UCHAR 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)
+
+#ifdef _MSC_VER
+
+#define KiInterruptDispatch2(x, y)
+
+#else
+
+VOID STDCALL
+KiInterruptDispatch2 (ULONG Irq, KIRQL old_level);
+
+#endif
+
+/* 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, 0xFF);
+  WRITE_PORT_UCHAR((PUCHAR)0xa1, 0xFF);
+  
+  /* We can now enable interrupts */
+  _enable();
+}
+
+VOID HalpEndSystemInterrupt(KIRQL Irql)
+/*
+ * FUNCTION: Enable all irqs with higher priority.
+ */
+{
+  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 */
+  _disable();
+
+  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 ints */
+  _enable();
+}
+
+VOID
+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]--;
+              //HalpHardwareInt[i]();
+            }
+          //KeGetPcr()->Irql--;
+          //HalpEndSystemInterrupt(KeGetPcr()->Irql);
+       }
+    }
+
+}
+
+VOID
+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 (DISPATCH_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 0
+  if (KeGetPcr()->Irql >= Irql)
+    {
+      HalpPendingInterruptCount[irq]++;
+      return(FALSE);
+    }
+#endif
+  *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);
+  }
+}
+
+VOID FASTCALL
+HalClearSoftwareInterrupt(
+  IN KIRQL Request)
+{
+  switch (Request)
+  {
+    case APC_LEVEL:
+      ((PKIPCR)KeGetPcr())->HalReserved[HAL_APC_REQUEST] = FALSE;
+      break;
+
+    case DISPATCH_LEVEL:
+      ((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = FALSE;
+      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 (file)
index 0000000..665bb1e
--- /dev/null
@@ -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 <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+/* 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 (file)
index 0000000..c9e4474
--- /dev/null
@@ -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 <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+
+#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 *********************************************************/
+
+#define KdComPortInUse _KdComPortInUse
+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 (file)
index 0000000..8343c8a
--- /dev/null
@@ -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 <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+/* 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 (file)
index 0000000..7eb1d91
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * PROJECT:         ReactOS HAL
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            hal/halx86/generic/misc.c
+ * PURPOSE:         Miscellanous Routines
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ *                  Eric Kohl (ekohl@abo.rhein-zeitung.de)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+/* PRIVATE FUNCTIONS *********************************************************/
+
+VOID
+NTAPI
+HalpCheckPowerButton(VOID)
+{
+    /* Nothing to do on non-ACPI */
+    return;
+}
+
+PVOID
+NTAPI
+HalpMapPhysicalMemory64(IN PHYSICAL_ADDRESS PhysicalAddress,
+                        IN ULONG NumberPage)
+{
+    /* Use kernel memory manager I/O map facilities */
+    return MmMapIoSpace(PhysicalAddress,
+                        NumberPage << PAGE_SHIFT,
+                        MmNonCached);
+}
+
+VOID
+NTAPI
+HalpUnmapVirtualAddress(IN PVOID VirtualAddress,
+                        IN ULONG NumberPages)
+{
+    /* Use kernel memory manager I/O map facilities */
+    MmUnmapIoSpace(VirtualAddress, NumberPages << PAGE_SHIFT);
+}
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+HalHandleNMI(IN PVOID NmiInfo)
+{
+    UCHAR ucStatus;
+
+    /* Get the NMI Flag */
+    ucStatus = READ_PORT_UCHAR((PUCHAR)0x61);
+
+    /* Display NMI failure string */
+    HalDisplayString ("\n*** Hardware Malfunction\n\n");
+    HalDisplayString ("Call your hardware vendor for support\n\n");
+
+    /* Check for parity error */
+    if (ucStatus & 0x80)
+    {
+        /* Display message */
+        HalDisplayString ("NMI: Parity Check / Memory Parity Error\n");
+    }
+
+    /* Check for I/O failure */
+    if (ucStatus & 0x40)
+    {
+        /* Display message */
+        HalDisplayString ("NMI: Channel Check / IOCHK\n");
+    }
+
+    /* Halt the system */
+    HalDisplayString("\n*** The system has halted ***\n");
+    //KeEnterKernelDebugger();
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+FASTCALL
+HalSystemVectorDispatchEntry(IN ULONG Vector,
+                             OUT PKINTERRUPT_ROUTINE **FlatDispatch,
+                             OUT PKINTERRUPT_ROUTINE *NoConnection)
+{
+    /* Not implemented on x86 */
+    return FALSE;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+KeFlushWriteBuffer(VOID)
+{
+    /* Not implemented on x86 */
+    return;
+}
diff --git a/reactos/hal/halppc/generic/pci.c b/reactos/hal/halppc/generic/pci.c
new file mode 100644 (file)
index 0000000..51d5910
--- /dev/null
@@ -0,0 +1,778 @@
+/*
+ * PROJECT:         ReactOS HAL
+ * LICENSE:         GPL - See COPYING in the top level directory
+ * FILE:            hal/halx86/generic/pci.c
+ * PURPOSE:         PCI Bus Support (Configuration Space, Resource Allocation)
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <hal.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+
+BOOLEAN HalpPCIConfigInitialized;
+ULONG HalpMinPciBus, HalpMaxPciBus;
+KSPIN_LOCK HalpPCIConfigLock;
+PCI_CONFIG_HANDLER PCIConfigHandler;
+
+/* PCI Operation Matrix */
+UCHAR PCIDeref[4][4] =
+{
+    {0, 1, 2, 2},   // ULONG-aligned offset
+    {1, 1, 1, 1},   // UCHAR-aligned offset
+    {2, 1, 2, 2},   // USHORT-aligned offset
+    {1, 1, 1, 1}    // UCHAR-aligned offset
+};
+
+/* Type 1 PCI Bus */
+PCI_CONFIG_HANDLER PCIConfigHandlerType1 =
+{
+    /* Synchronization */
+    (FncSync)HalpPCISynchronizeType1,
+    (FncReleaseSync)HalpPCIReleaseSynchronzationType1,
+
+    /* Read */
+    {
+        (FncConfigIO)HalpPCIReadUlongType1,
+        (FncConfigIO)HalpPCIReadUcharType1,
+        (FncConfigIO)HalpPCIReadUshortType1
+    },
+
+    /* Write */
+    {
+        (FncConfigIO)HalpPCIWriteUlongType1,
+        (FncConfigIO)HalpPCIWriteUcharType1,
+        (FncConfigIO)HalpPCIWriteUshortType1
+    }
+};
+
+/* Type 2 PCI Bus */
+PCI_CONFIG_HANDLER PCIConfigHandlerType2 =
+{
+    /* Synchronization */
+    (FncSync)HalpPCISynchronizeType2,
+    (FncReleaseSync)HalpPCIReleaseSynchronzationType2,
+
+    /* Read */
+    {
+        (FncConfigIO)HalpPCIReadUlongType2,
+        (FncConfigIO)HalpPCIReadUcharType2,
+        (FncConfigIO)HalpPCIReadUshortType2
+    },
+
+    /* Write */
+    {
+        (FncConfigIO)HalpPCIWriteUlongType2,
+        (FncConfigIO)HalpPCIWriteUcharType2,
+        (FncConfigIO)HalpPCIWriteUshortType2
+    }
+};
+
+PCIPBUSDATA HalpFakePciBusData =
+{
+    {
+        PCI_DATA_TAG,
+        PCI_DATA_VERSION,
+        HalpReadPCIConfig,
+        HalpWritePCIConfig,
+        NULL,
+        NULL,
+        {{{0}}},
+        {0, 0, 0, 0}
+    },
+    {{0}},
+    32,
+};
+
+BUS_HANDLER HalpFakePciBusHandler =
+{
+    1,
+    PCIBus,
+    PCIConfiguration,
+    0,
+    NULL,
+    NULL,
+    &HalpFakePciBusData,
+    0,
+    {0, 0, 0, 0},
+    HalpGetPCIData,
+    HalpSetPCIData,
+    NULL,
+    HalpAssignPCISlotResources,
+    NULL,
+    NULL
+};
+
+/* TYPE 1 FUNCTIONS **********************************************************/
+
+VOID
+NTAPI
+HalpPCISynchronizeType1(IN PBUS_HANDLER BusHandler,
+                        IN PCI_SLOT_NUMBER Slot,
+                        IN PKIRQL Irql,
+                        IN PPCI_TYPE1_CFG_BITS PciCfg1)
+{
+    /* Setup the PCI Configuration Register */
+    PciCfg1->u.AsULONG = 0;
+    PciCfg1->u.bits.BusNumber = BusHandler->BusNumber;
+    PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
+    PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
+    PciCfg1->u.bits.Enable = TRUE;
+
+    /* Acquire the lock */
+    KeRaiseIrql(HIGH_LEVEL, Irql);
+    KiAcquireSpinLock(&HalpPCIConfigLock);
+}
+
+VOID
+NTAPI
+HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler,
+                                  IN KIRQL Irql)
+{
+    PCI_TYPE1_CFG_BITS PciCfg1;
+
+    /* Clear the PCI Configuration Register */
+    PciCfg1.u.AsULONG = 0;
+    WRITE_PORT_ULONG(((PPCIPBUSDATA)BusHandler->BusData)->Config.Type1.Address,
+                     PciCfg1.u.AsULONG);
+
+    /* Release the lock */
+    KiReleaseSpinLock(&HalpPCIConfigLock);
+    KeLowerIrql(Irql);
+}
+
+TYPE1_READ(HalpPCIReadUcharType1, UCHAR)
+TYPE1_READ(HalpPCIReadUshortType1, USHORT)
+TYPE1_READ(HalpPCIReadUlongType1, ULONG)
+TYPE1_WRITE(HalpPCIWriteUcharType1, UCHAR)
+TYPE1_WRITE(HalpPCIWriteUshortType1, USHORT)
+TYPE1_WRITE(HalpPCIWriteUlongType1, ULONG)
+
+/* TYPE 2 FUNCTIONS **********************************************************/
+
+VOID
+NTAPI
+HalpPCISynchronizeType2(IN PBUS_HANDLER BusHandler,
+                        IN PCI_SLOT_NUMBER Slot,
+                        IN PKIRQL Irql,
+                        IN PPCI_TYPE2_ADDRESS_BITS PciCfg)
+{
+    PCI_TYPE2_CSE_BITS PciCfg2Cse;
+    PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+    /* Setup the configuration register */
+    PciCfg->u.AsUSHORT = 0;
+    PciCfg->u.bits.Agent = (USHORT)Slot.u.bits.DeviceNumber;
+    PciCfg->u.bits.AddressBase = (USHORT)BusData->Config.Type2.Base;
+
+    /* Acquire the lock */
+    KeRaiseIrql(HIGH_LEVEL, Irql);
+    KiAcquireSpinLock(&HalpPCIConfigLock);
+
+    /* Setup the CSE Register */
+    PciCfg2Cse.u.AsUCHAR = 0;
+    PciCfg2Cse.u.bits.Enable = TRUE;
+    PciCfg2Cse.u.bits.FunctionNumber = (UCHAR)Slot.u.bits.FunctionNumber;
+    PciCfg2Cse.u.bits.Key = -1;
+
+    /* Write the bus number and CSE */
+    WRITE_PORT_UCHAR(BusData->Config.Type2.Forward,
+                     (UCHAR)BusHandler->BusNumber);
+    WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
+}
+
+VOID
+NTAPI
+HalpPCIReleaseSynchronzationType2(IN PBUS_HANDLER BusHandler,
+                                  IN KIRQL Irql)
+{
+    PCI_TYPE2_CSE_BITS PciCfg2Cse;
+    PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
+
+    /* Clear CSE and bus number */
+    PciCfg2Cse.u.AsUCHAR = 0;
+    WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
+    WRITE_PORT_UCHAR(BusData->Config.Type2.Forward, 0);
+
+    /* Release the lock */
+    KiReleaseSpinLock(&HalpPCIConfigLock);
+    KeLowerIrql(Irql);
+}
+
+TYPE2_READ(HalpPCIReadUcharType2, UCHAR)
+TYPE2_READ(HalpPCIReadUshortType2, USHORT)
+TYPE2_READ(HalpPCIReadUlongType2, ULONG)
+TYPE2_WRITE(HalpPCIWriteUcharType2, UCHAR)
+TYPE2_WRITE(HalpPCIWriteUshortType2, USHORT)
+TYPE2_WRITE(HalpPCIWriteUlongType2, ULONG)
+
+/* PCI CONFIGURATION SPACE ***************************************************/
+
+VOID
+NTAPI
+HalpPCIConfig(IN PBUS_HANDLER BusHandler,
+              IN PCI_SLOT_NUMBER Slot,
+              IN PUCHAR Buffer,
+              IN ULONG Offset,
+              IN ULONG Length,
+              IN FncConfigIO *ConfigIO)
+{
+    KIRQL OldIrql;
+    ULONG i;
+    UCHAR State[20];
+
+    /* Synchronize the operation */
+    PCIConfigHandler.Synchronize(BusHandler, Slot, &OldIrql, State);
+
+    /* Loop every increment */
+    while (Length)
+    {
+        /* Find out the type of read/write we need to do */
+        i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
+
+        /* Do the read/write and return the number of bytes */
+        i = ConfigIO[i]((PPCIPBUSDATA)BusHandler->BusData,
+                        State,
+                        Buffer,
+                        Offset);
+
+        /* Increment the buffer position and offset, and decrease the length */
+        Offset += i;
+        Buffer += i;
+        Length -= i;
+    }
+
+    /* Release the lock and PCI bus */
+    PCIConfigHandler.ReleaseSynchronzation(BusHandler, OldIrql);
+}
+
+VOID
+NTAPI
+HalpReadPCIConfig(IN PBUS_HANDLER BusHandler,
+                  IN PCI_SLOT_NUMBER Slot,
+                  IN PVOID Buffer,
+                  IN ULONG Offset,
+                  IN ULONG Length)
+{
+    /* Validate the PCI Slot */
+    if (!HalpValidPCISlot(BusHandler, Slot))
+    {
+        /* Fill the buffer with invalid data */
+        RtlFillMemory(Buffer, Length, -1);
+    }
+    else
+    {
+        /* Send the request */
+        HalpPCIConfig(BusHandler,
+                      Slot,
+                      Buffer,
+                      Offset,
+                      Length,
+                      PCIConfigHandler.ConfigRead);
+    }
+}
+
+VOID
+NTAPI