From 81f092736fbbf02462da976c927b99c939d24988 Mon Sep 17 00:00:00 2001 From: Art Yerkes Date: Mon, 3 Sep 2007 01:57:36 +0000 Subject: [PATCH] Added freeldr and hal from PPC branch, along with needed headers and build changes. Next ntoskrnl and add ppc dir under libcntptr, which didn't exist when I forked. svn path=/trunk/; revision=28793 --- reactos/Makefile | 6 +- reactos/ReactOS-ppc.rbuild | 19 +- reactos/boot/freeldr/bootsect/bootsect.rbuild | 6 - .../boot/freeldr/freeldr/arch/powerpc/boot.s | 102 +- .../freeldr/freeldr/arch/powerpc/compat.h | 108 + .../freeldr/freeldr/arch/powerpc/loader.c | 349 +++ .../boot/freeldr/freeldr/arch/powerpc/mach.c | 481 ++-- .../boot/freeldr/freeldr/arch/powerpc/mboot.c | 950 ++++---- .../boot/freeldr/freeldr/arch/powerpc/mmu.c | 398 ++++ .../freeldr/freeldr/arch/powerpc/ofw_util.s | 49 + .../boot/freeldr/freeldr/arch/powerpc/prep.c | 112 + .../boot/freeldr/freeldr/arch/powerpc/prep.h | 24 + .../freeldr/freeldr/arch/powerpc/prep_ide.c | 106 + .../freeldr/freeldr/arch/powerpc/prep_pci.c | 127 ++ .../freeldr/freeldr/arch/powerpc/prep_vga.c | 30 + reactos/boot/freeldr/freeldr/freeldr.rbuild | 38 +- .../boot/freeldr/freeldr/freeldr_arch.rbuild | 2 + reactos/boot/freeldr/freeldr/fs/fat.c | 130 +- reactos/boot/freeldr/freeldr/fs/fs.c | 17 + reactos/boot/freeldr/freeldr/fs/fsrec.c | 2 + .../boot/freeldr/freeldr/include/bytesex.h | 14 + .../boot/freeldr/freeldr/include/freeldr.h | 2 + reactos/boot/freeldr/freeldr/include/of.h | 15 +- reactos/boot/freeldr/freeldr/mm/mm.c | 9 + reactos/hal/hal.rbuild | 13 +- reactos/hal/hal/hal.rbuild | 13 +- reactos/hal/halppc/generic/beep.c | 42 + reactos/hal/halppc/generic/bus.c | 356 +++ reactos/hal/halppc/generic/cmos.c | 291 +++ reactos/hal/halppc/generic/display.c | 385 ++++ reactos/hal/halppc/generic/dma.c | 2024 +++++++++++++++++ reactos/hal/halppc/generic/drive.c | 74 + reactos/hal/halppc/generic/enum.c | 23 + reactos/hal/halppc/generic/fmutex.c | 100 + reactos/hal/halppc/generic/font.c | 278 +++ reactos/hal/halppc/generic/generic.rbuild | 29 + reactos/hal/halppc/generic/halinit.c | 158 ++ reactos/hal/halppc/generic/ipi.c | 24 + reactos/hal/halppc/generic/irql.c | 450 ++++ reactos/hal/halppc/generic/isa.c | 75 + reactos/hal/halppc/generic/kdbg.c | 547 +++++ reactos/hal/halppc/generic/mca.c | 79 + reactos/hal/halppc/generic/misc.c | 105 + reactos/hal/halppc/generic/pci.c | 778 +++++++ reactos/hal/halppc/generic/portio.c | 283 +++ reactos/hal/halppc/generic/processor.c | 76 + reactos/hal/halppc/generic/profil.c | 61 + reactos/hal/halppc/generic/pwroff.c | 121 + reactos/hal/halppc/generic/reboot.c | 41 + reactos/hal/halppc/generic/resource.c | 31 + reactos/hal/halppc/generic/spinlock.c | 210 ++ reactos/hal/halppc/generic/sysbus.c | 66 + reactos/hal/halppc/generic/sysinfo.c | 41 + reactos/hal/halppc/generic/systimer.S | 48 + reactos/hal/halppc/generic/time.c | 102 + reactos/hal/halppc/generic/timer.c | 138 ++ reactos/hal/halppc/include/apic.h | 214 ++ reactos/hal/halppc/include/bus.h | 296 +++ reactos/hal/halppc/include/hal.h | 53 + reactos/hal/halppc/include/haldma.h | 383 ++++ reactos/hal/halppc/include/halirq.h | 35 + reactos/hal/halppc/include/halp.h | 132 ++ reactos/hal/halppc/include/ioapic.h | 103 + reactos/hal/halppc/include/mps.h | 204 ++ reactos/hal/halppc/up/halinit_up.c | 32 + reactos/hal/halppc/up/halup.rbuild | 13 + reactos/hal/halppc/up/halup.rc | 5 + reactos/include/ddk/winddk.h | 69 + reactos/include/ndk/powerpc/ketypes.h | 713 +++--- reactos/include/ndk/powerpc/mmtypes.h | 31 + reactos/include/psdk/intrin_ppc.h | 969 ++++++++ reactos/include/psdk/rpc.h | 2 +- reactos/include/psdk/winnt.h | 88 + reactos/include/reactos/arc/arc.h | 6 + reactos/include/reactos/debug.h | 2 + reactos/include/reactos/elf/elf-powerpc.h | 158 ++ reactos/include/reactos/elf/machine.h | 4 + reactos/include/reactos/elf/reactos.h | 7 + reactos/include/reactos/libs/ppcmmu/mmu.h | 228 ++ reactos/include/reactos/libs/ppcmmu/mmuutil.h | 23 + reactos/include/reactos/ppcboot.h | 14 + reactos/include/reactos/ppcdebug.h | 20 + reactos/include/reactos/ppcfont.h | 259 +++ reactos/include/reactos/rosldr.h | 1 + reactos/lib/rtl/exception.c | 2 + reactos/lib/rtl/powerpc/debug.c | 42 + reactos/lib/rtl/powerpc/except.c | 62 + reactos/lib/rtl/powerpc/interlocked.c | 124 + reactos/lib/rtl/powerpc/thread.c | 38 + reactos/lib/rtl/rtl.rbuild | 8 + .../include/internal/powerpc/intrin_i.h | 6 + .../rbuild/backend/mingw/modulehandler.cpp | 51 +- .../rbuild/backend/mingw/modulehandler.h | 9 + reactos/tools/rbuild/bootstrap.cpp | 1 + reactos/tools/rbuild/module.cpp | 26 +- reactos/tools/rbuild/rbuild.h | 4 +- 96 files changed, 13666 insertions(+), 929 deletions(-) create mode 100644 reactos/boot/freeldr/freeldr/arch/powerpc/compat.h create mode 100644 reactos/boot/freeldr/freeldr/arch/powerpc/loader.c create mode 100644 reactos/boot/freeldr/freeldr/arch/powerpc/mmu.c create mode 100644 reactos/boot/freeldr/freeldr/arch/powerpc/ofw_util.s create mode 100644 reactos/boot/freeldr/freeldr/arch/powerpc/prep.c create mode 100644 reactos/boot/freeldr/freeldr/arch/powerpc/prep.h create mode 100644 reactos/boot/freeldr/freeldr/arch/powerpc/prep_ide.c create mode 100644 reactos/boot/freeldr/freeldr/arch/powerpc/prep_pci.c create mode 100644 reactos/boot/freeldr/freeldr/arch/powerpc/prep_vga.c create mode 100644 reactos/boot/freeldr/freeldr/include/bytesex.h create mode 100644 reactos/hal/halppc/generic/beep.c create mode 100644 reactos/hal/halppc/generic/bus.c create mode 100644 reactos/hal/halppc/generic/cmos.c create mode 100644 reactos/hal/halppc/generic/display.c create mode 100644 reactos/hal/halppc/generic/dma.c create mode 100644 reactos/hal/halppc/generic/drive.c create mode 100644 reactos/hal/halppc/generic/enum.c create mode 100644 reactos/hal/halppc/generic/fmutex.c create mode 100644 reactos/hal/halppc/generic/font.c create mode 100644 reactos/hal/halppc/generic/generic.rbuild create mode 100644 reactos/hal/halppc/generic/halinit.c create mode 100644 reactos/hal/halppc/generic/ipi.c create mode 100644 reactos/hal/halppc/generic/irql.c create mode 100644 reactos/hal/halppc/generic/isa.c create mode 100644 reactos/hal/halppc/generic/kdbg.c create mode 100644 reactos/hal/halppc/generic/mca.c create mode 100644 reactos/hal/halppc/generic/misc.c create mode 100644 reactos/hal/halppc/generic/pci.c create mode 100644 reactos/hal/halppc/generic/portio.c create mode 100644 reactos/hal/halppc/generic/processor.c create mode 100644 reactos/hal/halppc/generic/profil.c create mode 100644 reactos/hal/halppc/generic/pwroff.c create mode 100644 reactos/hal/halppc/generic/reboot.c create mode 100644 reactos/hal/halppc/generic/resource.c create mode 100644 reactos/hal/halppc/generic/spinlock.c create mode 100644 reactos/hal/halppc/generic/sysbus.c create mode 100644 reactos/hal/halppc/generic/sysinfo.c create mode 100644 reactos/hal/halppc/generic/systimer.S create mode 100644 reactos/hal/halppc/generic/time.c create mode 100644 reactos/hal/halppc/generic/timer.c create mode 100644 reactos/hal/halppc/include/apic.h create mode 100644 reactos/hal/halppc/include/bus.h create mode 100644 reactos/hal/halppc/include/hal.h create mode 100644 reactos/hal/halppc/include/haldma.h create mode 100644 reactos/hal/halppc/include/halirq.h create mode 100644 reactos/hal/halppc/include/halp.h create mode 100644 reactos/hal/halppc/include/ioapic.h create mode 100644 reactos/hal/halppc/include/mps.h create mode 100644 reactos/hal/halppc/up/halinit_up.c create mode 100644 reactos/hal/halppc/up/halup.rbuild create mode 100644 reactos/hal/halppc/up/halup.rc create mode 100644 reactos/include/psdk/intrin_ppc.h create mode 100644 reactos/include/reactos/elf/elf-powerpc.h create mode 100644 reactos/include/reactos/elf/reactos.h create mode 100644 reactos/include/reactos/libs/ppcmmu/mmu.h create mode 100644 reactos/include/reactos/libs/ppcmmu/mmuutil.h create mode 100644 reactos/include/reactos/ppcboot.h create mode 100644 reactos/include/reactos/ppcdebug.h create mode 100644 reactos/include/reactos/ppcfont.h create mode 100644 reactos/lib/rtl/powerpc/debug.c create mode 100644 reactos/lib/rtl/powerpc/except.c create mode 100644 reactos/lib/rtl/powerpc/interlocked.c create mode 100644 reactos/lib/rtl/powerpc/thread.c create mode 100644 reactos/ntoskrnl/include/internal/powerpc/intrin_i.h diff --git a/reactos/Makefile b/reactos/Makefile index 6fb7488618b..4c64926fd85 100644 --- a/reactos/Makefile +++ b/reactos/Makefile @@ -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) diff --git a/reactos/ReactOS-ppc.rbuild b/reactos/ReactOS-ppc.rbuild index 26891addcac..092cbc3aa4a 100644 --- a/reactos/ReactOS-ppc.rbuild +++ b/reactos/ReactOS-ppc.rbuild @@ -9,22 +9,27 @@ - - - - + - + - -v - -Wpointer-arith + + 1 + + -fshort-wchar + -fsigned-char + -mfull-toc + -meabi + -O2 + -Wno-strict-aliasing + -Wno-trampolines diff --git a/reactos/boot/freeldr/bootsect/bootsect.rbuild b/reactos/boot/freeldr/bootsect/bootsect.rbuild index 65334cc0be4..b3b7f2f3c47 100644 --- a/reactos/boot/freeldr/bootsect/bootsect.rbuild +++ b/reactos/boot/freeldr/bootsect/bootsect.rbuild @@ -22,9 +22,3 @@ isobtrt.asm - - - - ofwboot.s - - \ No newline at end of file diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/boot.s b/reactos/boot/freeldr/freeldr/arch/powerpc/boot.s index a507daafab4..7efff45fb7b 100644 --- a/reactos/boot/freeldr/freeldr/arch/powerpc/boot.s +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/boot.s @@ -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 index 00000000000..66797a6929d --- /dev/null +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/compat.h @@ -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 index 00000000000..0dea8ef0ca9 --- /dev/null +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/loader.c @@ -0,0 +1,349 @@ +/* + * FreeLoader + * Copyright (C) 1998-2003 Brian Palmer + * Copyright (C) 2005 Alex Ionescu + * + * 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 + +#define NDEBUG +#include +#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; +} diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/mach.c b/reactos/boot/freeldr/freeldr/arch/powerpc/mach.c index c79d5062bc7..de937c04bd0 100644 --- a/reactos/boot/freeldr/freeldr/arch/powerpc/mach.c +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/mach.c @@ -18,123 +18,32 @@ */ #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 + */ +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"); } +BOOLEAN PpcDiskNormalizeSystemPath(char *SystemPath, unsigned Size) { + CHAR BootPath[256]; + ULONG PartitionNumber; + ULONG DriveNumber; + PARTITION_TABLE_ENTRY PartEntry; + char *p; + + 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 PpcInit( of_proxy the_ofproxy ) { - int len; - ofproxy = the_ofproxy; - +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; + // Allow forcing prep for broken OFW + if(!strncmp(CmdLine, "bootprep", 8)) + { + printf("Going to PREP init...\n"); + PpcPrepInit(); + return; + } + printf( "FreeLDR version [%s]\n", GetFreeLoaderVersionString() ); - len = ofw_getprop(chosen_package, "bootargs", - CmdLine, sizeof(CmdLine)); - - if( len < 0 ) len = 0; - CmdLine[len] = 0; - 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(); +} diff --git a/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c b/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c index 23997df7c78..17de0f61daa 100644 --- a/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c @@ -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 + * Copyright (C) 2005 Alex Ionescu + * + * 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 -#include +#include +#include +#include +#include "ppcboot.h" +#include "ppcmmu/mmu.h" +#include "compat.h" +#include "ppcfont.h" #define NDEBUG #include -/* 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<> 21); - - /* Get the Startup Page Directory Table */ - PageDirTablePae = (PPAGE_DIRECTORY_TABLE_X64)&startup_pagedirectorytable_pae; - - /* Get the Startup Page Directory */ - PageDirPae = (PPAGE_DIRECTORY_X64)&startup_pagedirectory_pae; - - /* 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; - } - - /* 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; - } - - /* 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); - } - - /* 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; -#endif } /*++ - * FrLdrMapKernel + * 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); + + if(ModuleData) + { + return TRUE; + } + + if(!KernelAddr) + KernelAddr = (ULONG)NextModuleBase - (ULONG)KernelMemory + KernelBase; + if(!MemLoadAddr) + MemLoadAddr = (PCHAR)NextModuleBase; + + ModuleData = &reactos_modules[LoaderBlock.ModsCount]; + printf("Loading file (elf at %x)\n", KernelAddr); + + /* Load the first 1024 bytes of the kernel image so we can read the PE header */ + if (!FsReadFile(KernelImage, sizeof(ehdr), NULL, &ehdr)) { + + /* Fail if we couldn't read */ + printf("Couldn't read the elf header\n"); + return FALSE; + } + + /* 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))); + } + } + + 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 * 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); + /* Allocate kernel memory */ + KernelMemory = MmAllocateMemory(KernelMemorySize); + printf("Kernel Memory @%x\n", (int)KernelMemory); - /* 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); - - /* 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 index 00000000000..18676a2a9ea --- /dev/null +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/mmu.c @@ -0,0 +1,398 @@ +#include +#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 index 00000000000..df921547ee8 --- /dev/null +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/ofw_util.s @@ -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 index 00000000000..b3fe7d56ae9 --- /dev/null +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/prep.c @@ -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 index 00000000000..ce2cfbff75d --- /dev/null +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/prep.h @@ -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 index 00000000000..abfcf753313 --- /dev/null +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/prep_ide.c @@ -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 index 00000000000..6254723f25b --- /dev/null +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/prep_pci.c @@ -0,0 +1,127 @@ +#include +#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 index 00000000000..24d8368e245 --- /dev/null +++ b/reactos/boot/freeldr/freeldr/arch/powerpc/prep_vga.c @@ -0,0 +1,30 @@ +#include +#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; + } + } +} diff --git a/reactos/boot/freeldr/freeldr/freeldr.rbuild b/reactos/boot/freeldr/freeldr/freeldr.rbuild index a4102685021..025ab5c7c6a 100644 --- a/reactos/boot/freeldr/freeldr/freeldr.rbuild +++ b/reactos/boot/freeldr/freeldr/freeldr.rbuild @@ -1,12 +1,26 @@ - - - freeldr_startup - freeldr_base64k - freeldr_base - freeldr_arch - freeldr_main - rossym - cmlib - rtl - libcntpr - + + + + freeldr_startup + freeldr_base64k + freeldr_base + freeldr_arch + freeldr_main + rossym + cmlib + rtl + libcntpr + + + + + freeldr_startup + freeldr_base64k + freeldr_base + freeldr_arch + freeldr_main + rossym + cmlib + rtl + + diff --git a/reactos/boot/freeldr/freeldr/freeldr_arch.rbuild b/reactos/boot/freeldr/freeldr/freeldr_arch.rbuild index 310680e56ff..6f55745e3c6 100644 --- a/reactos/boot/freeldr/freeldr/freeldr_arch.rbuild +++ b/reactos/boot/freeldr/freeldr/freeldr_arch.rbuild @@ -47,6 +47,8 @@ include cache include + include/reactos/libs + include/reactos/elf -ffreestanding diff --git a/reactos/boot/freeldr/freeldr/fs/fat.c b/reactos/boot/freeldr/freeldr/fs/fat.c index 14cf1d4ab98..1fbcb2d257c 100644 --- a/reactos/boot/freeldr/freeldr/fs/fat.c +++ b/reactos/boot/freeldr/freeldr/fs/fat.c @@ -18,6 +18,8 @@ */ #include + +#define NDEBUG #include 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; CurrentEntryFileName[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; diff --git a/reactos/boot/freeldr/freeldr/fs/fs.c b/reactos/boot/freeldr/freeldr/fs/fs.c index a6654380043..f7116b9bca0 100644 --- a/reactos/boot/freeldr/freeldr/fs/fs.c +++ b/reactos/boot/freeldr/freeldr/fs/fs.c @@ -18,6 +18,8 @@ */ #include + +#define NDEBUG #include ///////////////////////////////////////////////////////////////////////////////////////////// @@ -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; } diff --git a/reactos/boot/freeldr/freeldr/fs/fsrec.c b/reactos/boot/freeldr/freeldr/fs/fsrec.c index b34187780f8..32a73549a4b 100644 --- a/reactos/boot/freeldr/freeldr/fs/fsrec.c +++ b/reactos/boot/freeldr/freeldr/fs/fsrec.c @@ -18,6 +18,8 @@ */ #include + +#define NDEBUG #include ///////////////////////////////////////////////////////////////////////////////////////////// diff --git a/reactos/boot/freeldr/freeldr/include/bytesex.h b/reactos/boot/freeldr/freeldr/include/bytesex.h new file mode 100644 index 00000000000..ccbfc7cad05 --- /dev/null +++ b/reactos/boot/freeldr/freeldr/include/bytesex.h @@ -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_*/ diff --git a/reactos/boot/freeldr/freeldr/include/freeldr.h b/reactos/boot/freeldr/freeldr/include/freeldr.h index 57f307adfe5..b8a335379fd 100644 --- a/reactos/boot/freeldr/freeldr/include/freeldr.h +++ b/reactos/boot/freeldr/freeldr/include/freeldr.h @@ -87,6 +87,8 @@ #include /* Needed if debuging is enabled */ #include +/* Swap */ +#include #define Ke386EraseFlags(x) __asm__ __volatile__("pushl $0 ; popfl\n") diff --git a/reactos/boot/freeldr/freeldr/include/of.h b/reactos/boot/freeldr/freeldr/include/of.h index 445f6654dfe..2f623d5f9a5 100644 --- a/reactos/boot/freeldr/freeldr/include/of.h +++ b/reactos/boot/freeldr/freeldr/include/of.h @@ -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 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 ); diff --git a/reactos/boot/freeldr/freeldr/mm/mm.c b/reactos/boot/freeldr/freeldr/mm/mm.c index b510f9a251c..2d0371dec91 100644 --- a/reactos/boot/freeldr/freeldr/mm/mm.c +++ b/reactos/boot/freeldr/freeldr/mm/mm.c @@ -19,6 +19,9 @@ #include #include +#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; diff --git a/reactos/hal/hal.rbuild b/reactos/hal/hal.rbuild index 552e3306f9a..ea9ce8db0b5 100644 --- a/reactos/hal/hal.rbuild +++ b/reactos/hal/hal.rbuild @@ -2,7 +2,14 @@ - - - + + + + + + + + + + diff --git a/reactos/hal/hal/hal.rbuild b/reactos/hal/hal/hal.rbuild index ded2af3c3a8..bc0e94ab53b 100644 --- a/reactos/hal/hal/hal.rbuild +++ b/reactos/hal/hal/hal.rbuild @@ -9,8 +9,13 @@ hal.rc - - + + + - - + + + + + + diff --git a/reactos/hal/halppc/generic/beep.c b/reactos/hal/halppc/generic/beep.c new file mode 100644 index 00000000000..f4e9d3b07ea --- /dev/null +++ b/reactos/hal/halppc/generic/beep.c @@ -0,0 +1,42 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/beep.c + * PURPOSE: Speaker function (it's only one) + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * Created 31/01/99 + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + + +/* CONSTANTS *****************************************************************/ + +#define TIMER2 0x42 +#define TIMER3 0x43 +#define PORT_B 0x61 +#define CLOCKFREQ 1193167 + + +/* FUNCTIONS *****************************************************************/ +/* + * FUNCTION: Beeps the speaker. + * ARGUMENTS: + * Frequency = If 0, the speaker will be switched off, otherwise + * the speaker beeps with the specified frequency. + */ + +BOOLEAN +STDCALL +HalMakeBeep ( + ULONG Frequency + ) +{ + return TRUE; +} + diff --git a/reactos/hal/halppc/generic/bus.c b/reactos/hal/halppc/generic/bus.c new file mode 100644 index 00000000000..a35adbe315a --- /dev/null +++ b/reactos/hal/halppc/generic/bus.c @@ -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 +#define NDEBUG +#include + +/* 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 index 00000000000..14cd589b0e5 --- /dev/null +++ b/reactos/hal/halppc/generic/cmos.c @@ -0,0 +1,291 @@ +/* + * PROJECT: ReactOS HAL + * LICENSE: GPL - See COPYING in the top level directory + * FILE: hal/halx86/generic/cmos.c + * PURPOSE: CMOS Access Routines (Real Time Clock and LastKnownGood) + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + * Eric Kohl (ekohl@abo.rhein-zeitung.de) + */ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +KSPIN_LOCK HalpSystemHardwareLock; + +/* PRIVATE FUNCTIONS *********************************************************/ + +UCHAR +FORCEINLINE +HalpReadCmos(IN UCHAR Reg) +{ + /* Select the register */ + WRITE_PORT_UCHAR(CMOS_CONTROL_PORT, Reg); + + /* Query the value */ + return READ_PORT_UCHAR(CMOS_DATA_PORT); +} + +VOID +FORCEINLINE +HalpWriteCmos(IN UCHAR Reg, + IN UCHAR Value) +{ + /* Select the register */ + WRITE_PORT_UCHAR(CMOS_CONTROL_PORT, Reg); + + /* Write the value */ + WRITE_PORT_UCHAR(CMOS_DATA_PORT, Value); +} + +ULONG +NTAPI +HalpGetCmosData(IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Length) +{ + PUCHAR Ptr = (PUCHAR)Buffer; + ULONG Address = SlotNumber; + ULONG Len = Length; + + /* FIXME: Acquire CMOS Lock */ + + /* Do nothing if we don't have a length */ + if (!Length) return 0; + + /* Check if this is simple CMOS */ + if (!BusNumber) + { + /* Loop the buffer up to 0xFF */ + while ((Len > 0) && (Address < 0x100)) + { + /* Read the data */ + *Ptr = HalpReadCmos((UCHAR)Address); + + /* Update position and length */ + Ptr++; + Address++; + Len--; + } + } + else if (BusNumber == 1) + { + /* Loop the buffer up to 0xFFFF */ + while ((Len > 0) && (Address < 0x10000)) + { + /* Write the data */ + *Ptr = HalpReadCmos((UCHAR)Address); + + /* Update position and length */ + Ptr++; + Address++; + Len--; + } + } + + /* FIXME: Release the CMOS Lock */ + + /* Return length read */ + return Length - Len; +} + +ULONG +NTAPI +HalpSetCmosData(IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Length) +{ + PUCHAR Ptr = (PUCHAR)Buffer; + ULONG Address = SlotNumber; + ULONG Len = Length; + + /* FIXME: Acquire CMOS Lock */ + + /* Do nothing if we don't have a length */ + if (!Length) return 0; + + /* Check if this is simple CMOS */ + if (!BusNumber) + { + /* Loop the buffer up to 0xFF */ + while ((Len > 0) && (Address < 0x100)) + { + /* Write the data */ + HalpWriteCmos((UCHAR)Address, *Ptr); + + /* Update position and length */ + Ptr++; + Address++; + Len--; + } + } + else if (BusNumber == 1) + { + /* Loop the buffer up to 0xFFFF */ + while ((Len > 0) && (Address < 0x10000)) + { + /* Write the data */ + HalpWriteCmos((UCHAR)Address, *Ptr); + + /* Update position and length */ + Ptr++; + Address++; + Len--; + } + } + + /* FIXME: Release the CMOS Lock */ + + /* Return length read */ + return Length - Len; +} + +/* PUBLIC FUNCTIONS **********************************************************/ + +/* + * @implemented + */ +ARC_STATUS +NTAPI +HalGetEnvironmentVariable(IN PCH Name, + IN USHORT ValueLength, + IN PCH Value) +{ + UCHAR Val; + + /* Only variable supported on x86 */ + if (_stricmp(Name, "LastKnownGood")) return ENOENT; + + /* FIXME: Acquire CMOS Lock */ + + /* Query the current value */ + Val = HalpReadCmos(RTC_REGISTER_B) & 0x01; + + /* FIXME: Release CMOS lock */ + + /* Check the flag */ + if (Val) + { + /* Return false */ + strncpy(Value, "FALSE", ValueLength); + } + else + { + /* Return true */ + strncpy(Value, "TRUE", ValueLength); + } + + /* Return success */ + return ESUCCESS; +} + +/* + * @implemented + */ +ARC_STATUS +NTAPI +HalSetEnvironmentVariable(IN PCH Name, + IN PCH Value) +{ + UCHAR Val; + + /* Only variable supported on x86 */ + if (_stricmp(Name, "LastKnownGood")) return ENOMEM; + + /* Check if this is true or false */ + if (!_stricmp(Value, "TRUE")) + { + /* It's true, acquire CMOS lock (FIXME) */ + + /* Read the current value and add the flag */ + Val = HalpReadCmos(RTC_REGISTER_B) | 1; + } + else if (!_stricmp(Value, "FALSE")) + { + /* It's false, acquire CMOS lock (FIXME) */ + + /* Read the current value and mask out the flag */ + Val = HalpReadCmos(RTC_REGISTER_B) & ~1; + } + else + { + /* Fail */ + return ENOMEM; + } + + /* Write new value */ + HalpWriteCmos(RTC_REGISTER_B, Val); + + /* Release the lock and return success */ + return ESUCCESS; +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +HalQueryRealTimeClock(OUT PTIME_FIELDS Time) +{ + /* FIXME: Acquire CMOS Lock */ + + /* Loop while update is in progress */ + while ((HalpReadCmos(RTC_REGISTER_A)) & RTC_REG_A_UIP); + + /* Set the time data */ + Time->Second = BCD_INT(HalpReadCmos(0)); + Time->Minute = BCD_INT(HalpReadCmos(2)); + Time->Hour = BCD_INT(HalpReadCmos(4)); + Time->Weekday = BCD_INT(HalpReadCmos(6)); + Time->Day = BCD_INT(HalpReadCmos(7)); + Time->Month = BCD_INT(HalpReadCmos(8)); + Time->Year = BCD_INT(HalpReadCmos(9)); + Time->Milliseconds = 0; + + /* FIXME: Check century byte */ + + /* Compensate for the century field */ + Time->Year += (Time->Year > 80) ? 1900: 2000; + + /* FIXME: Release CMOS Lock */ + + /* Always return TRUE */ + return TRUE; +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +HalSetRealTimeClock(IN PTIME_FIELDS Time) +{ + /* FIXME: Acquire CMOS Lock */ + + /* Loop while update is in progress */ + while ((HalpReadCmos(RTC_REGISTER_A)) & RTC_REG_A_UIP); + + /* Write time fields to CMOS RTC */ + HalpWriteCmos(0, INT_BCD(Time->Second)); + HalpWriteCmos(2, INT_BCD(Time->Minute)); + HalpWriteCmos(4, INT_BCD(Time->Hour)); + HalpWriteCmos(6, INT_BCD(Time->Weekday)); + HalpWriteCmos(7, INT_BCD(Time->Day)); + HalpWriteCmos(8, INT_BCD(Time->Month)); + HalpWriteCmos(9, INT_BCD(Time->Year % 100)); + + /* FIXME: Set the century byte */ + + /* FIXME: Release the CMOS Lock */ + + /* Always return TRUE */ + return TRUE; +} + +/* EOF */ diff --git a/reactos/hal/halppc/generic/display.c b/reactos/hal/halppc/generic/display.c new file mode 100644 index 00000000000..4e0d8edd6b7 --- /dev/null +++ b/reactos/hal/halppc/generic/display.c @@ -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 +#include +#include +#include + +#define NDEBUG +#include + +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 index 00000000000..f0d7f0a1000 --- /dev/null +++ b/reactos/hal/halppc/generic/dma.c @@ -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 +#define NDEBUG +#include + +static KEVENT HalpDmaLock; +static LIST_ENTRY HalpDmaAdapterList; +static PADAPTER_OBJECT HalpEisaAdapter[8]; +static BOOLEAN HalpEisaDma; +static PADAPTER_OBJECT HalpMasterAdapter; + +static const ULONG_PTR HalpEisaPortPage[8] = { + FIELD_OFFSET(DMA_PAGE, Channel0), + FIELD_OFFSET(DMA_PAGE, Channel1), + FIELD_OFFSET(DMA_PAGE, Channel2), + FIELD_OFFSET(DMA_PAGE, Channel3), + 0, + FIELD_OFFSET(DMA_PAGE, Channel5), + FIELD_OFFSET(DMA_PAGE, Channel6), + FIELD_OFFSET(DMA_PAGE, Channel7) +}; + +static DMA_OPERATIONS HalpDmaOperations = { + sizeof(DMA_OPERATIONS), + (PPUT_DMA_ADAPTER)HalPutDmaAdapter, + (PALLOCATE_COMMON_BUFFER)HalAllocateCommonBuffer, + (PFREE_COMMON_BUFFER)HalFreeCommonBuffer, + NULL, /* Initialized in HalpInitDma() */ + NULL, /* Initialized in HalpInitDma() */ + NULL, /* Initialized in HalpInitDma() */ + NULL, /* Initialized in HalpInitDma() */ + NULL, /* Initialized in HalpInitDma() */ + (PGET_DMA_ALIGNMENT)HalpDmaGetDmaAlignment, + (PREAD_DMA_COUNTER)HalReadDmaCounter, + /* FIXME: Implement the S/G funtions. */ + NULL /*(PGET_SCATTER_GATHER_LIST)HalGetScatterGatherList*/, + NULL /*(PPUT_SCATTER_GATHER_LIST)HalPutScatterGatherList*/, + NULL /*(PCALCULATE_SCATTER_GATHER_LIST_SIZE)HalCalculateScatterGatherListSize*/, + NULL /*(PBUILD_SCATTER_GATHER_LIST)HalBuildScatterGatherList*/, + NULL /*(PBUILD_MDL_FROM_SCATTER_GATHER_LIST)HalBuildMdlFromScatterGatherList*/ +}; + +#define MAX_MAP_REGISTERS 64 + +#define TAG_DMA TAG('D','M','A',' ') + +/* FUNCTIONS *****************************************************************/ + +VOID +HalpInitDma(VOID) +{ + /* + * Initialize the DMA Operation table + */ + HalpDmaOperations.AllocateAdapterChannel = (PALLOCATE_ADAPTER_CHANNEL)IoAllocateAdapterChannel; + HalpDmaOperations.FlushAdapterBuffers = (PFLUSH_ADAPTER_BUFFERS)IoFlushAdapterBuffers; + HalpDmaOperations.FreeAdapterChannel = (PFREE_ADAPTER_CHANNEL)IoFreeAdapterChannel; + HalpDmaOperations.FreeMapRegisters = (PFREE_MAP_REGISTERS)IoFreeMapRegisters; + HalpDmaOperations.MapTransfer = (PMAP_TRANSFER)IoMapTransfer; + + /* + * Check if Extended DMA is available. We're just going to do a random + * read and write. + */ + + WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2), 0x2A); + if (READ_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)) == 0x2A) + HalpEisaDma = TRUE; + + /* + * Intialize all the global variables and allocate master adapter with + * first map buffers. + */ + + InitializeListHead(&HalpDmaAdapterList); + KeInitializeEvent(&HalpDmaLock, NotificationEvent, TRUE); + + HalpMasterAdapter = HalpDmaAllocateMasterAdapter(); + + /* + * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's + * used by IoGetDmaAdapter in the kernel. + */ + + HalGetDmaAdapter = HalpGetDmaAdapter; +} + +/** + * @name HalpGetAdapterMaximumPhysicalAddress + * + * Get the maximum physical address acceptable by the device represented + * by the passed DMA adapter. + */ + +PHYSICAL_ADDRESS STDCALL +HalpGetAdapterMaximumPhysicalAddress( + IN PADAPTER_OBJECT AdapterObject) +{ + PHYSICAL_ADDRESS HighestAddress; + + if (AdapterObject->MasterDevice) + { + if (AdapterObject->Dma64BitAddresses) + { + HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL; + return HighestAddress; + } + else if (AdapterObject->Dma32BitAddresses) + { + HighestAddress.QuadPart = 0xFFFFFFFF; + return HighestAddress; + } + } + + HighestAddress.QuadPart = 0xFFFFFF; + return HighestAddress; +} + +/** + * @name HalpGrowMapBuffers + * + * Allocate initial, or additional, map buffers for DMA master adapter. + * + * @param MasterAdapter + * DMA master adapter to allocate buffers for. + * @param SizeOfMapBuffers + * Size of the map buffers to allocate (not including the size + * already allocated). + */ + +BOOLEAN STDCALL +HalpGrowMapBuffers( + IN PADAPTER_OBJECT AdapterObject, + IN ULONG SizeOfMapBuffers) +{ + PVOID VirtualAddress; + PHYSICAL_ADDRESS PhysicalAddress; + PHYSICAL_ADDRESS HighestAcceptableAddress; + PHYSICAL_ADDRESS LowestAcceptableAddress; + PHYSICAL_ADDRESS BoundryAddressMultiple; + KIRQL OldIrql; + ULONG MapRegisterCount; + + /* FIXME: Check if enough map register slots are available. */ + + MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers); + + /* + * Allocate memory for the new map registers. For 32-bit adapters we use + * two passes in order not to waste scare resource (low memory). + */ + + HighestAcceptableAddress = + HalpGetAdapterMaximumPhysicalAddress(AdapterObject); + LowestAcceptableAddress.HighPart = 0; + LowestAcceptableAddress.LowPart = + HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0; + BoundryAddressMultiple.QuadPart = 0; + + VirtualAddress = MmAllocateContiguousMemorySpecifyCache( + MapRegisterCount << PAGE_SHIFT, LowestAcceptableAddress, + HighestAcceptableAddress, BoundryAddressMultiple, MmNonCached); + + if (VirtualAddress == NULL && LowestAcceptableAddress.LowPart != 0) + { + LowestAcceptableAddress.LowPart = 0; + VirtualAddress = MmAllocateContiguousMemorySpecifyCache( + MapRegisterCount << PAGE_SHIFT, LowestAcceptableAddress, + HighestAcceptableAddress, BoundryAddressMultiple, MmNonCached); + } + + if (VirtualAddress == NULL) + return FALSE; + + PhysicalAddress = MmGetPhysicalAddress(VirtualAddress); + + /* + * All the following must be done with the master adapter lock held + * to prevent corruption. + */ + + OldIrql = KfAcquireSpinLock(&AdapterObject->SpinLock); + + /* + * Setup map register entries for the buffer allocated. Each entry has + * a virtual and physical address and corresponds to PAGE_SIZE large + * buffer. + */ + + if (MapRegisterCount > 0) + { + PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry; + + CurrentEntry = AdapterObject->MapRegisterBase + + AdapterObject->NumberOfMapRegisters; + do + { + /* + * Leave one entry free for every non-contiguous memory region + * in the map register bitmap. This ensures that we can search + * using RtlFindClearBits for contiguous map register regions. + * + * Also for non-EISA DMA leave one free entry for every 64Kb + * break, because the DMA controller can handle only coniguous + * 64Kb regions. + */ + + if (CurrentEntry != AdapterObject->MapRegisterBase) + { + PreviousEntry = CurrentEntry - 1; + if (PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE == + PhysicalAddress.LowPart) + { + if (!HalpEisaDma) + { + if ((PreviousEntry->PhysicalAddress.LowPart ^ + PhysicalAddress.LowPart) & 0xFFFF0000) + { + CurrentEntry++; + AdapterObject->NumberOfMapRegisters++; + } + } + } + else + { + CurrentEntry++; + AdapterObject->NumberOfMapRegisters++; + } + } + + RtlClearBit(AdapterObject->MapRegisters, + CurrentEntry - AdapterObject->MapRegisterBase); + CurrentEntry->VirtualAddress = VirtualAddress; + CurrentEntry->PhysicalAddress = PhysicalAddress; + + PhysicalAddress.LowPart += PAGE_SIZE; + VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE); + + CurrentEntry++; + AdapterObject->NumberOfMapRegisters++; + MapRegisterCount--; + } + while (MapRegisterCount != 0); + } + + KfReleaseSpinLock(&AdapterObject->SpinLock, OldIrql); + + return TRUE; +} + +/** + * @name HalpDmaAllocateMasterAdapter + * + * Helper routine to allocate and initialize master adapter object and it's + * associated map register buffers. + * + * @see HalpInitDma + */ + +PADAPTER_OBJECT STDCALL +HalpDmaAllocateMasterAdapter(VOID) +{ + PADAPTER_OBJECT MasterAdapter; + ULONG Size, SizeOfBitmap; + + SizeOfBitmap = MAX_MAP_REGISTERS; + Size = sizeof(ADAPTER_OBJECT); + Size += sizeof(RTL_BITMAP); + Size += (SizeOfBitmap + 7) >> 3; + + MasterAdapter = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_DMA); + if (MasterAdapter == NULL) + return NULL; + + RtlZeroMemory(MasterAdapter, Size); + + KeInitializeSpinLock(&MasterAdapter->SpinLock); + InitializeListHead(&MasterAdapter->AdapterQueue); + + MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1); + RtlInitializeBitMap( + MasterAdapter->MapRegisters, + (PULONG)(MasterAdapter->MapRegisters + 1), + SizeOfBitmap); + RtlSetAllBits(MasterAdapter->MapRegisters); + MasterAdapter->NumberOfMapRegisters = 0; + MasterAdapter->CommittedMapRegisters = 0; + + MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag( + NonPagedPool, + SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY), + TAG_DMA); + if (MasterAdapter->MapRegisterBase == NULL) + { + ExFreePool(MasterAdapter); + return NULL; + } + + RtlZeroMemory(MasterAdapter->MapRegisterBase, + SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY)); + if (!HalpGrowMapBuffers(MasterAdapter, 0x10000)) + { + ExFreePool(MasterAdapter); + return NULL; + } + + return MasterAdapter; +} + +/** + * @name HalpDmaAllocateChildAdapter + * + * Helper routine of HalGetAdapter. Allocate child adapter object and + * fill out some basic fields. + * + * @see HalGetAdapter + */ + +PADAPTER_OBJECT STDCALL +HalpDmaAllocateChildAdapter( + ULONG NumberOfMapRegisters, + PDEVICE_DESCRIPTION DeviceDescription) +{ + PADAPTER_OBJECT AdapterObject; + OBJECT_ATTRIBUTES ObjectAttributes; + NTSTATUS Status; + HANDLE Handle; + + InitializeObjectAttributes( + &ObjectAttributes, + NULL, + OBJ_KERNEL_HANDLE | OBJ_PERMANENT, + NULL, + NULL); + + Status = ObCreateObject( + KernelMode, + IoAdapterObjectType, + &ObjectAttributes, + KernelMode, + NULL, + sizeof(ADAPTER_OBJECT), + 0, + 0, + (PVOID)&AdapterObject); + if (!NT_SUCCESS(Status)) + return NULL; + + Status = ObReferenceObjectByPointer( + AdapterObject, + FILE_READ_DATA | FILE_WRITE_DATA, + IoAdapterObjectType, + KernelMode); + if (!NT_SUCCESS(Status)) + return NULL; + + RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT)); + + Status = ObInsertObject( + AdapterObject, + NULL, + FILE_READ_DATA | FILE_WRITE_DATA, + 0, + NULL, + &Handle); + if (!NT_SUCCESS(Status)) + return NULL; + + ZwClose(Handle); + + AdapterObject->DmaHeader.Version = (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 index 00000000000..fc489c9c8d6 --- /dev/null +++ b/reactos/hal/halppc/generic/drive.c @@ -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 +#define NDEBUG +#include + +/* 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 index 00000000000..af8b06d4a87 --- /dev/null +++ b/reactos/hal/halppc/generic/enum.c @@ -0,0 +1,23 @@ +/* $Id: enum.c 23907 2006-09-04 05:52:23Z arty $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/enum.c + * PURPOSE: Motherboard device enumerator + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * Created 01/05/2001 + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +VOID +HalpStartEnumerator (VOID) +{ +} + +/* EOF */ diff --git a/reactos/hal/halppc/generic/fmutex.c b/reactos/hal/halppc/generic/fmutex.c new file mode 100644 index 00000000000..8ec41f4ce11 --- /dev/null +++ b/reactos/hal/halppc/generic/fmutex.c @@ -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 +#define NDEBUG +#include + +#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 index 00000000000..570cc5f1e51 --- /dev/null +++ b/reactos/hal/halppc/generic/font.c @@ -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 + +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 index 00000000000..dd40b0d6626 --- /dev/null +++ b/reactos/hal/halppc/generic/generic.rbuild @@ -0,0 +1,29 @@ + + ../include + include + + + + beep.c + bus.c + cmos.c + display.c + dma.c + drive.c + enum.c + fmutex.c + font.c + halinit.c + irql.c + isa.c + misc.c + pci.c + portio.c + processor.c + profil.c + reboot.c + spinlock.c + sysinfo.c + timer.c + ../include/hal.h + diff --git a/reactos/hal/halppc/generic/halinit.c b/reactos/hal/halppc/generic/halinit.c new file mode 100644 index 00000000000..d7a81adc2cc --- /dev/null +++ b/reactos/hal/halppc/generic/halinit.c @@ -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 +#define NDEBUG +#include + +/* 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 index 00000000000..739de8d716c --- /dev/null +++ b/reactos/hal/halppc/generic/ipi.c @@ -0,0 +1,24 @@ +/* $Id: ipi.c 23907 2006-09-04 05:52:23Z arty $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: hal/halx86/generic/ipi.c + * PURPOSE: Miscellaneous hardware functions + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +VOID STDCALL +HalRequestIpi(ULONG ProcessorNo) +{ + DPRINT("HalRequestIpi(ProcessorNo %lu)\n", ProcessorNo); +} + +/* EOF */ diff --git a/reactos/hal/halppc/generic/irql.c b/reactos/hal/halppc/generic/irql.c new file mode 100644 index 00000000000..ed3ad450a84 --- /dev/null +++ b/reactos/hal/halppc/generic/irql.c @@ -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 +#define NDEBUG +#include + +/* 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 index 00000000000..665bb1edd45 --- /dev/null +++ b/reactos/hal/halppc/generic/isa.c @@ -0,0 +1,75 @@ +/* $Id: isa.c 23907 2006-09-04 05:52:23Z arty $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/isa.c + * PURPOSE: Interfaces to the ISA bus + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 05/06/98: Created + */ + +/* INCLUDES ***************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN HalIsaProbe(VOID) +/* + * FUNCTION: Probes for an ISA bus + * RETURNS: True if detected + * NOTE: Since ISA is the default we are called last and always return + * true + */ +{ + DbgPrint("Assuming ISA bus\n"); + + /* + * Probe for plug and play support + */ + return(TRUE); +} + + +BOOLEAN STDCALL +HalpTranslateIsaBusAddress(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress) +{ + BOOLEAN Result; + + Result = HalTranslateBusAddress(PCIBus, + BusNumber, + BusAddress, + AddressSpace, + TranslatedAddress); + if (Result != FALSE) + return Result; + + Result = HalTranslateBusAddress(Internal, + BusNumber, + BusAddress, + AddressSpace, + TranslatedAddress); + return Result; +} + +ULONG STDCALL +HalpGetIsaInterruptVector(PVOID BusHandler, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity) +{ + ULONG Vector = IRQ2VECTOR(BusInterruptVector); + *Irql = VECTOR2IRQL(Vector); + *Affinity = 0xFFFFFFFF; + return Vector; +} +/* EOF */ diff --git a/reactos/hal/halppc/generic/kdbg.c b/reactos/hal/halppc/generic/kdbg.c new file mode 100644 index 00000000000..c9e4474fa8a --- /dev/null +++ b/reactos/hal/halppc/generic/kdbg.c @@ -0,0 +1,547 @@ +/* $Id: kdbg.c 23907 2006-09-04 05:52:23Z arty $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/kdbg.c + * PURPOSE: Serial i/o functions for the kernel debugger. + * PROGRAMMER: Emanuele Aliberti + * Eric Kohl + * UPDATE HISTORY: + * Created 05/09/99 + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + + +#define DEFAULT_BAUD_RATE 19200 + + +/* MACROS *******************************************************************/ + +#define SER_RBR(x) ((x)+0) +#define SER_THR(x) ((x)+0) +#define SER_DLL(x) ((x)+0) +#define SER_IER(x) ((x)+1) +#define SR_IER_ERDA 0x01 +#define SR_IER_ETHRE 0x02 +#define SR_IER_ERLSI 0x04 +#define SR_IER_EMS 0x08 +#define SR_IER_ALL 0x0F +#define SER_DLM(x) ((x)+1) +#define SER_IIR(x) ((x)+2) +#define SER_FCR(x) ((x)+2) +#define SR_FCR_ENABLE_FIFO 0x01 +#define SR_FCR_CLEAR_RCVR 0x02 +#define SR_FCR_CLEAR_XMIT 0x04 +#define SER_LCR(x) ((x)+3) +#define SR_LCR_CS5 0x00 +#define SR_LCR_CS6 0x01 +#define SR_LCR_CS7 0x02 +#define SR_LCR_CS8 0x03 +#define SR_LCR_ST1 0x00 +#define SR_LCR_ST2 0x04 +#define SR_LCR_PNO 0x00 +#define SR_LCR_POD 0x08 +#define SR_LCR_PEV 0x18 +#define SR_LCR_PMK 0x28 +#define SR_LCR_PSP 0x38 +#define SR_LCR_BRK 0x40 +#define SR_LCR_DLAB 0x80 +#define SER_MCR(x) ((x)+4) +#define SR_MCR_DTR 0x01 +#define SR_MCR_RTS 0x02 +#define SR_MCR_OUT1 0x04 +#define SR_MCR_OUT2 0x08 +#define SR_MCR_LOOP 0x10 +#define SER_LSR(x) ((x)+5) +#define SR_LSR_DR 0x01 +#define SR_LSR_TBE 0x20 +#define SER_MSR(x) ((x)+6) +#define SR_MSR_CTS 0x10 +#define SR_MSR_DSR 0x20 +#define SER_SCR(x) ((x)+7) + + +/* GLOBAL VARIABLES *********************************************************/ + +#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 index 00000000000..8343c8a8f70 --- /dev/null +++ b/reactos/hal/halppc/generic/mca.c @@ -0,0 +1,79 @@ +/* + * ReactOS kernel + * Copyright (C) 2002 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +/* $Id: mca.c 23907 2006-09-04 05:52:23Z arty $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: hal/halx86/mca.c + * PURPOSE: Interfaces to the MicroChannel bus + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +/* + * TODO: + * What Adapter ID is read from an empty slot? + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +ULONG STDCALL +HalpGetMicroChannelData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PCM_MCA_POS_DATA PosData = (PCM_MCA_POS_DATA)Buffer; + + DPRINT("HalpGetMicroChannelData() called.\n"); + DPRINT(" BusNumber %lu\n", BusNumber); + DPRINT(" SlotNumber %lu\n", SlotNumber); + DPRINT(" Offset 0x%lx\n", Offset); + DPRINT(" Length 0x%lx\n", Length); + + if ((BusNumber != 0) || + (SlotNumber == 0) || (SlotNumber > 8) || + (Length < sizeof(CM_MCA_POS_DATA))) + return(0); + + /* Enter Setup-Mode for given slot */ + WRITE_PORT_UCHAR((PUCHAR)0x96, (UCHAR)(((UCHAR)(SlotNumber - 1) & 0x07) | 0x08)); + + /* Read POS data */ + PosData->AdapterId = (READ_PORT_UCHAR((PUCHAR)0x101) << 8) + + READ_PORT_UCHAR((PUCHAR)0x100); + PosData->PosData1 = READ_PORT_UCHAR((PUCHAR)0x102); + PosData->PosData2 = READ_PORT_UCHAR((PUCHAR)0x103); + PosData->PosData3 = READ_PORT_UCHAR((PUCHAR)0x104); + PosData->PosData4 = READ_PORT_UCHAR((PUCHAR)0x105); + + /* Leave Setup-Mode for given slot */ + WRITE_PORT_UCHAR((PUCHAR)0x96, (UCHAR)((UCHAR)(SlotNumber - 1) & 0x07)); + + return(sizeof(CM_MCA_POS_DATA)); +} + +/* EOF */ diff --git a/reactos/hal/halppc/generic/misc.c b/reactos/hal/halppc/generic/misc.c new file mode 100644 index 00000000000..7eb1d9170f9 --- /dev/null +++ b/reactos/hal/halppc/generic/misc.c @@ -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 +#define NDEBUG +#include + +/* 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 index 00000000000..51d5910f50f --- /dev/null +++ b/reactos/hal/halppc/generic/pci.c @@ -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 +#define NDEBUG +#include + +/* 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 +HalpWritePCIConfig(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)) + { + /* Send the request */ + HalpPCIConfig(BusHandler, + Slot, + Buffer, + Offset, + Length, + PCIConfigHandler.ConfigWrite); + } +} + +BOOLEAN +NTAPI +HalpValidPCISlot(IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot) +{ + PCI_SLOT_NUMBER MultiSlot; + PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData; + UCHAR HeaderType; + ULONG Device; + + /* Simple validation */ + if (Slot.u.bits.Reserved) return FALSE; + if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) return FALSE; + + /* Function 0 doesn't need checking */ + if (!Slot.u.bits.FunctionNumber) return TRUE; + + /* Functions 0+ need Multi-Function support, so check the slot */ + Device = Slot.u.bits.DeviceNumber; + MultiSlot = Slot; + MultiSlot.u.bits.FunctionNumber = 0; + + /* Send function 0 request to get the header back */ + HalpReadPCIConfig(BusHandler, + MultiSlot, + &HeaderType, + FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType), + sizeof(UCHAR)); + + /* Now make sure the header is multi-function */ + if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) return FALSE; + return TRUE; +} + +/* HAL PCI CALLBACKS *********************************************************/ + +ULONG +NTAPI +HalpGetPCIData(IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length) +{ + UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH]; + PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer; + ULONG Len = 0; + + /* Normalize the length */ + if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG); + + /* Check if this is a vendor-specific read */ + if (Offset >= PCI_COMMON_HDR_LENGTH) + { + /* Read the header */ + HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG)); + + /* Make sure the vendor is valid */ + if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0; + } + else + { + /* Read the entire header */ + Len = PCI_COMMON_HDR_LENGTH; + HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len); + + /* Validate the vendor ID */ + if (PciConfig->VendorID == PCI_INVALID_VENDORID) + { + /* It's invalid, but we want to return this much */ + PciConfig->VendorID = PCI_INVALID_VENDORID; + Len = sizeof(USHORT); + } + + /* Now check if there's space left */ + if (Len < Offset) return 0; + + /* There is, so return what's after the offset and normalize */ + Len -= Offset; + if (Len > Length) Len = Length; + + /* Copy the data into the caller's buffer */ + RtlMoveMemory(Buffer, PciBuffer + Offset, Len); + + /* Update buffer and offset, decrement total length */ + Offset += Len; + Buffer += Len; + Length -= Len; + } + + /* Now we still have something to copy */ + if (Length) + { + /* Check if it's vendor-specific data */ + if (Offset >= PCI_COMMON_HDR_LENGTH) + { + /* Read it now */ + HalpReadPCIConfig(BusHandler, Slot, Buffer, Offset, Length); + Len += Length; + } + } + + /* Update the total length read */ + return Len; +} + +ULONG +NTAPI +HalpSetPCIData(IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER Slot, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length) +{ + UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH]; + PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer; + ULONG Len = 0; + + /* Normalize the length */ + if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG); + + /* Check if this is a vendor-specific read */ + if (Offset >= PCI_COMMON_HDR_LENGTH) + { + /* Read the header */ + HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG)); + + /* Make sure the vendor is valid */ + if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0; + } + else + { + /* Read the entire header and validate the vendor ID */ + Len = PCI_COMMON_HDR_LENGTH; + HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len); + if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0; + + /* Return what's after the offset and normalize */ + Len -= Offset; + if (Len > Length) Len = Length; + + /* Copy the specific caller data */ + RtlMoveMemory(PciBuffer + Offset, Buffer, Len); + + /* Write the actual configuration data */ + HalpWritePCIConfig(BusHandler, Slot, PciBuffer + Offset, Offset, Len); + + /* Update buffer and offset, decrement total length */ + Offset += Len; + Buffer += Len; + Length -= Len; + } + + /* Now we still have something to copy */ + if (Length) + { + /* Check if it's vendor-specific data */ + if (Offset >= PCI_COMMON_HDR_LENGTH) + { + /* Read it now */ + HalpWritePCIConfig(BusHandler, Slot, Buffer, Offset, Length); + Len += Length; + } + } + + /* Update the total length read */ + return Len; +} + +NTSTATUS +NTAPI +HalpSetupPciDeviceForDebugging(IN PVOID LoaderBlock, + IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice) +{ + DPRINT1("Unimplemented!\n"); + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice) +{ + DPRINT1("Unimplemented!\n"); + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN ULONG Slot, + IN OUT PCM_RESOURCE_LIST *pAllocatedResources) +{ + KEBUGCHECK(0); + return STATUS_SUCCESS; +} + +ULONG +NTAPI +HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler, + IN ULONG BusNumber, + IN PCI_SLOT_NUMBER SlotNumber, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length) +{ + BUS_HANDLER BusHandler; + PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)Buffer; + + /* Setup fake PCI Bus handler */ + RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER)); + BusHandler.BusNumber = BusNumber; + + /* Read configuration data */ + HalpReadPCIConfig(&BusHandler, SlotNumber, Buffer, Offset, Length); + + /* Check if caller only wanted at least Vendor ID */ + if (Length >= 2) + { + /* Validate it */ + if (PciData->VendorID != PCI_INVALID_VENDORID) + { + /* Check if this is the new maximum bus number */ + if (HalpMaxPciBus < BusHandler.BusNumber) + { + /* Set it */ + HalpMaxPciBus = BusHandler.BusNumber; + } + } + } + + /* Return length */ + return Length; +} + +PPCI_REGISTRY_INFO_INTERNAL +NTAPI +HalpQueryPciRegistryInfo(VOID) +{ + WCHAR NameBuffer[8]; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING KeyName, ConfigName, IdentName; + HANDLE KeyHandle, BusKeyHandle; + NTSTATUS Status; + UCHAR KeyBuffer[sizeof(PPCI_REGISTRY_INFO) + 100]; + PKEY_VALUE_FULL_INFORMATION ValueInfo = (PVOID)KeyBuffer; + ULONG ResultLength; + PWSTR Tag; + ULONG i; + PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor; + PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; + PPCI_REGISTRY_INFO PciRegInfo; + PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; + + /* Setup the object attributes for the key */ + RtlInitUnicodeString(&KeyName, + L"\\Registry\\Machine\\Hardware\\Description\\" + L"System\\MultiFunctionAdapter"); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + NULL, + NULL); + + /* Open the key */ + Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes); + if (!NT_SUCCESS(Status)) return NULL; + + /* Setup the receiving string */ + KeyName.Buffer = NameBuffer; + KeyName.MaximumLength = sizeof(NameBuffer); + + /* Setup the configuration and identifier key names */ + RtlInitUnicodeString(&ConfigName, L"ConfigurationData"); + RtlInitUnicodeString(&IdentName, L"Identifier"); + + /* Keep looping for each ID */ + for (i = 0; TRUE; i++) + { + /* Setup the key name */ + RtlIntegerToUnicodeString(i, 10, &KeyName); + InitializeObjectAttributes(&ObjectAttributes, + &KeyName, + OBJ_CASE_INSENSITIVE, + KeyHandle, + NULL); + + /* Open it */ + Status = ZwOpenKey(&BusKeyHandle, KEY_READ, &ObjectAttributes); + if (!NT_SUCCESS(Status)) + { + /* None left, fail */ + ZwClose(KeyHandle); + return NULL; + } + + /* Read the registry data */ + Status = ZwQueryValueKey(BusKeyHandle, + &IdentName, + KeyValueFullInformation, + ValueInfo, + sizeof(KeyBuffer), + &ResultLength); + if (!NT_SUCCESS(Status)) + { + /* Failed, try the next one */ + ZwClose(BusKeyHandle); + continue; + } + + /* Get the PCI Tag and validate it */ + Tag = (PWSTR)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset); + if ((Tag[0] != L'P') || + (Tag[1] != L'C') || + (Tag[2] != L'I') || + (Tag[3])) + { + /* Not a valid PCI entry, skip it */ + ZwClose(BusKeyHandle); + continue; + } + + /* Now read our PCI structure */ + Status = ZwQueryValueKey(BusKeyHandle, + &ConfigName, + KeyValueFullInformation, + ValueInfo, + sizeof(KeyBuffer), + &ResultLength); + ZwClose(BusKeyHandle); + if (!NT_SUCCESS(Status)) continue; + + /* We read it OK! Get the actual resource descriptors */ + FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) + ((ULONG_PTR)ValueInfo + ValueInfo->DataOffset); + PartialDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) + ((ULONG_PTR)FullDescriptor-> + PartialResourceList.PartialDescriptors); + + /* Check if this is our PCI Registry Information */ + if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific) + { + /* Close the key */ + ZwClose(KeyHandle); + + /* FIXME: Check PnP\PCI\CardList */ + + /* Get the PCI information */ + PciRegInfo = (PPCI_REGISTRY_INFO)(PartialDescriptor + 1); + + /* Allocate the return structure */ + PciRegistryInfo = ExAllocatePoolWithTag(NonPagedPool, + sizeof(PCI_REGISTRY_INFO_INTERNAL), + TAG('H', 'a', 'l', ' ')); + if (!PciRegistryInfo) return NULL; + + /* Fill it out */ + PciRegistryInfo->HardwareMechanism = PciRegInfo->HardwareMechanism; + PciRegistryInfo->NoBuses = PciRegInfo->NoBuses; + PciRegistryInfo->MajorRevision = PciRegInfo->MajorRevision; + PciRegistryInfo->MinorRevision = PciRegInfo->MinorRevision; + PciRegistryInfo->ElementCount = 0; + } + } +} + +VOID +NTAPI +HalpInitializePciStubs(VOID) +{ + PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; + UCHAR PciType; + PPCIPBUSDATA BusData = (PPCIPBUSDATA)HalpFakePciBusHandler.BusData; + ULONG i; + PCI_SLOT_NUMBER j; + ULONG VendorId = 0; + + /* Query registry information */ + PciRegistryInfo = HalpQueryPciRegistryInfo(); + if (!PciRegistryInfo) + { + /* Assume type 1 */ + PciType = 1; + } + else + { + /* Get the type and free the info structure */ + PciType = PciRegistryInfo->HardwareMechanism & 0xF; + ExFreePool(PciRegistryInfo); + } + + /* Initialize the PCI lock */ + KeInitializeSpinLock(&HalpPCIConfigLock); + + /* Check the type of PCI bus */ + switch (PciType) + { + /* Type 1 PCI Bus */ + case 1: + + /* Copy the Type 1 handler data */ + RtlCopyMemory(&PCIConfigHandler, + &PCIConfigHandlerType1, + sizeof(PCIConfigHandler)); + + /* Set correct I/O Ports */ + BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT; + BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT; + break; + + /* Type 2 PCI Bus */ + case 2: + + /* Copy the Type 1 handler data */ + RtlCopyMemory(&PCIConfigHandler, + &PCIConfigHandlerType2, + sizeof (PCIConfigHandler)); + + /* Set correct I/O Ports */ + BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT; + BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT; + BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE; + + /* Only 16 devices supported, not 32 */ + BusData->MaxDevice = 16; + break; + + default: + + /* Invalid type */ + DbgPrint("HAL: Unnkown PCI type\n"); + } + + /* Loop all possible buses */ + for (i = 0; i < 256; i++) + { + /* Loop all devices */ + for (j.u.AsULONG = 0; j.u.AsULONG < 32; j.u.AsULONG++) + { + /* Query the interface */ + if (HaliPciInterfaceReadConfig(NULL, + i, + j, + &VendorId, + 0, + sizeof(ULONG))) + { + /* Validate the vendor ID */ + if ((USHORT)VendorId != PCI_INVALID_VENDORID) + { + /* Set this as the maximum ID */ + HalpMaxPciBus = i; + break; + } + } + } + } + + /* We're done */ + HalpPCIConfigInitialized = TRUE; +} + +VOID +NTAPI +HalpInitializePciBus(VOID) +{ + /* Initialize the stubs */ + HalpInitializePciStubs(); + + /* FIXME: Initialize NMI Crash Flag */ +} + +/* EOF */ diff --git a/reactos/hal/halppc/generic/portio.c b/reactos/hal/halppc/generic/portio.c new file mode 100644 index 00000000000..19caddccc11 --- /dev/null +++ b/reactos/hal/halppc/generic/portio.c @@ -0,0 +1,283 @@ +/* $Id: portio.c 23907 2006-09-04 05:52:23Z arty $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/portio.c + * PURPOSE: Port I/O functions + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * Created 18/10/99 + */ + +#include +#define NDEBUG +#include + +/* FUNCTIONS ****************************************************************/ + +/* + * This file contains the definitions for the x86 IO instructions + * inb/inw/inl/outb/outw/outl and the "string versions" of the same + * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" + * versions of the single-IO instructions (inb_p/inw_p/..). + * + * This file is not meant to be obfuscating: it's just complicated + * to (a) handle it all in a way that makes gcc able to optimize it + * as well as possible and (b) trying to avoid writing the same thing + * over and over again with slight variations and possibly making a + * mistake somewhere. + */ + +/* + * Thanks to James van Artsdalen for a better timing-fix than + * the two short jumps: using outb's to a nonexistent port seems + * to guarantee better timings even on fast machines. + * + * On the other hand, I'd like to be sure of a non-existent port: + * I feel a bit unsafe about using 0x80 (should be safe, though) + * + * Linus + */ + +#if defined(__GNUC__) + +#ifdef SLOW_IO_BY_JUMPING +#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:") +#else +#define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80") +#endif + +#elif defined(_MSC_VER) + +#ifdef SLOW_IO_BY_JUMPING +#define __SLOW_DOWN_IO __asm jmp 1f __asm jmp 1f 1f: +#else +#define __SLOW_DOWN_IO __asm out 0x80, al +#endif + +#else +#error Unknown compiler for inline assembler +#endif + + +#ifdef REALLY_SLOW_IO +#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } +#else +#define SLOW_DOWN_IO __SLOW_DOWN_IO +#endif + +extern int GetPhysByte(int Addr); +extern void SetPhysByte(int Addr, int Val); +extern int GetPhysWord(int Addr); +extern void SetPhysWord(int Addr, int Val); +extern int GetPhys(int Addr); +extern void SetPhys(int Addr, int Val); + +__asm__("\t.globl GetPhys\n" + "GetPhys:\t\n" + "mflr 0\n\t" + "stwu 0,-16(1)\n\t" + "mfmsr 5\n\t" + "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */ + "mtmsr 6\n\t" + "isync\n\t" + "sync\n\t" + "lwz 3,0(3)\n\t" /* Get actual value at phys addr r3 */ + "mtmsr 5\n\t" + "isync\n\t" + "sync\n\t" + "lwz 0,0(1)\n\t" + "addi 1,1,16\n\t" + "mtlr 0\n\t" + "blr" + ); + +__asm__("\t.globl GetPhysWord\n" + "GetPhysWord:\t\n" + "mflr 0\n\t" + "stwu 0,-16(1)\n\t" + "mfmsr 5\n\t" + "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 SetPhysWord\n" + "SetPhysWord:\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" + ); + +VOID STDCALL +READ_PORT_BUFFER_UCHAR (PUCHAR Port, + PUCHAR Buffer, + ULONG Count) +{ + while(Count--) { *Buffer++ = GetPhysByte((ULONG)Port); } +} + +VOID STDCALL +READ_PORT_BUFFER_USHORT (PUSHORT Port, + PUSHORT Buffer, + ULONG Count) +{ + while(Count--) { *Buffer++ = GetPhysWord((ULONG)Port); } +} + +VOID STDCALL +READ_PORT_BUFFER_ULONG (PULONG Port, + PULONG Buffer, + ULONG Count) +{ + while(Count--) { *Buffer++ = GetPhys((ULONG)Port); } +} + +UCHAR STDCALL +READ_PORT_UCHAR (PUCHAR Port) +{ + return GetPhys((ULONG)Port); +} + +USHORT STDCALL +READ_PORT_USHORT (PUSHORT Port) +{ + return GetPhysWord((ULONG)Port); +} + +ULONG STDCALL +READ_PORT_ULONG (PULONG Port) +{ + return GetPhys((ULONG)Port); +} + +VOID STDCALL +WRITE_PORT_BUFFER_UCHAR (PUCHAR Port, + PUCHAR Buffer, + ULONG Count) +{ + while(Count--) { SetPhysByte((ULONG)Port, *Buffer++); } +} + +VOID STDCALL +WRITE_PORT_BUFFER_USHORT (PUSHORT Port, + PUSHORT Buffer, + ULONG Count) +{ + while(Count--) { SetPhysWord((ULONG)Port, *Buffer++); } +} + +VOID STDCALL +WRITE_PORT_BUFFER_ULONG (PULONG Port, + PULONG Buffer, + ULONG Count) +{ + while(Count--) { SetPhys((ULONG)Port, *Buffer++); } +} + +VOID STDCALL +WRITE_PORT_UCHAR (PUCHAR Port, + UCHAR Value) +{ + SetPhysByte((ULONG)Port, Value); +} + +VOID STDCALL +WRITE_PORT_USHORT (PUSHORT Port, + USHORT Value) +{ + SetPhysWord((ULONG)Port, Value); +} + +VOID STDCALL +WRITE_PORT_ULONG (PULONG Port, + ULONG Value) +{ + SetPhys((ULONG)Port, Value); +} + +/* EOF */ diff --git a/reactos/hal/halppc/generic/processor.c b/reactos/hal/halppc/generic/processor.c new file mode 100644 index 00000000000..430435319ac --- /dev/null +++ b/reactos/hal/halppc/generic/processor.c @@ -0,0 +1,76 @@ +/* $Id: processor.c 23907 2006-09-04 05:52:23Z arty $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: hal/halx86/generic/processor.c + * PURPOSE: Intel MultiProcessor specification support + * PROGRAMMER: David Welch (welch@cwcom.net) + * Casper S. Hornstrup (chorns@users.sourceforge.net) + * NOTES: Parts adapted from linux SMP code + * UPDATE HISTORY: + * 22/05/1998 DW Created + * 12/04/2001 CSH Added MultiProcessor specification support + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +#define INITIAL_STALL_COUNT 0x10000 + +VOID STDCALL +HalInitializeProcessor(ULONG ProcessorNumber, + PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + DPRINT("HalInitializeProcessor(%lu %p)\n", ProcessorNumber, LoaderBlock); + KeGetPcr()->StallScaleFactor = INITIAL_STALL_COUNT; +} + +BOOLEAN STDCALL +HalAllProcessorsStarted (VOID) +{ + DPRINT("HalAllProcessorsStarted()\n"); + + return TRUE; +} + +NTHALAPI +BOOLEAN +NTAPI +HalStartNextProcessor( + IN struct _LOADER_PARAMETER_BLOCK *LoaderBlock, + IN PKPROCESSOR_STATE ProcessorState + ) +{ + DPRINT("HalStartNextProcessor(0x%lx 0x%lx)\n", LoaderBlock, ProcessorState); + + return TRUE; +} + +/* + * @implemented + */ +VOID +NTAPI +HalProcessorIdle(VOID) +{ + /* Enable interrupts and halt the processor */ + _enable(); +} + +/* + * @implemented + */ +VOID +NTAPI +HalRequestIpi(ULONG Reserved) +{ + /* Not implemented on NT */ + __debugbreak(); +} + +/* EOF */ diff --git a/reactos/hal/halppc/generic/profil.c b/reactos/hal/halppc/generic/profil.c new file mode 100644 index 00000000000..b8dec298311 --- /dev/null +++ b/reactos/hal/halppc/generic/profil.c @@ -0,0 +1,61 @@ +/* + * PROJECT: ReactOS HAL + * LICENSE: GPL - See COPYING in the top level directory + * FILE: hal/halx86/generic/profil.c + * PURPOSE: System Profiling + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS *****************************************************************/ + +/* + * @unimplemented + */ +VOID +NTAPI +HalStopProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) +{ + KEBUGCHECK(0); + return; +} + +/* + * @unimplemented + */ +VOID +NTAPI +HalStartProfileInterrupt(IN KPROFILE_SOURCE ProfileSource) +{ + KEBUGCHECK(0); + return; +} + +/* + * @unimplemented + */ +ULONG_PTR +NTAPI +HalSetProfileInterval(IN ULONG_PTR Interval) +{ + KEBUGCHECK(0); + return Interval; +} + +ULONG HalpDecrementerRoll = 0; + +LARGE_INTEGER +KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFrequency) +{ + LARGE_INTEGER Result; + /* for now */ + if(PerformanceFrequency) PerformanceFrequency->QuadPart = 100000000; + Result.HighPart = HalpDecrementerRoll; + Result.LowPart = __rdtsc(); + return Result; +} diff --git a/reactos/hal/halppc/generic/pwroff.c b/reactos/hal/halppc/generic/pwroff.c new file mode 100644 index 00000000000..cf6be7555b9 --- /dev/null +++ b/reactos/hal/halppc/generic/pwroff.c @@ -0,0 +1,121 @@ +/* $Id: pwroff.c 23907 2006-09-04 05:52:23Z arty $ + * + * FILE : reactos/hal/x86/apm.c + * DESCRIPTION: Turn CPU off... + * PROJECT : ReactOS Operating System + * AUTHOR : D. Lindauer (July 11 1997) + * NOTE : This program is public domain + * REVISIONS : + * 1999-12-26 + */ + +#define APM_FUNCTION_AVAILABLE 0x5300 +#define APM_FUNCTION_CONNREAL 0x5301 +#define APM_FUNCTION_POWEROFF 0x5307 +#define APM_FUNCTION_ENABLECPU 0x530d +#define APM_FUNCTION_ENABLEAPM 0x530e + +#define APM_DEVICE_BIOS 0 +#define APM_DEVICE_ALL 1 + +#define APM_MODE_DISABLE 0 +#define APM_MODE_ENABLE 1 + + + +#if defined(__GNUC__) + +nopm db 'No power management functionality',10,13,'$' +errmsg db 'Power management error',10,13,'$' +wrongver db 'Need APM version 1.1 or better',10,13,'$' +; +; Entry point +; +go: + mov dx,offset nopm + jc error + cmp ax,101h ; See if version 1.1 or greater + mov dx,offset wrongver + jc error + + mov [ver],ax + mov ax,5301h ; Do a real mode connection + mov bx,0 ; device = BIOS + int 15h + jnc noconerr + + cmp ah,2 ; Pass if already connected + mov dx,offset errmsg ; else error + jnz error +noconerr: + mov ax,530eh ; Enable latest version of APM + mov bx,0 ; device = BIOS + mov cx,[ver] ; version + int 15h + mov dx,offset errmsg + jc error + + mov ax,530dh ; Now engage and enable CPU management + mov bx,1 ; device = all + mov cx,1 ; enable + int 15h + mov dx,offset errmsg + jc error + + mov ax,530fh + mov bx,1 ; device = ALL + mov cx,1 ; enable + int 15h + mov dx,offset errmsg + jc error + + mov dx,offset errmsg +error: + call print + mov ax,4c01h + int 21h + int 3 + end start + + +BOOLEAN +ApmCall ( + DWORD Function, + DWORD Device, + DWORD Mode + ) +{ + /* AX <== Function */ + /* BX <== Device */ + /* CX <== Mode */ + __asm__("int 21\n"); /* 0x15 */ +} + +#elif defined(_MSC_VER) +#else +#error Unknown compiler for inline assembler +#endif + + +BOOLEAN +HalPowerOff (VOID) +{ + ApmCall ( + APM_FUNCTION_AVAILABLE, + APM_DEVICE_BIOS, + 0 + ); + ApmCall ( + APM_FUNCTION_ENABLEAPM, + ); + /* Shutdown CPU */ + ApmCall ( + APM_FUNCTION_POWEROFF, + APM_DEVICE_ALL, + 3 + ); + return TRUE; +} + + +/* EOF */ diff --git a/reactos/hal/halppc/generic/reboot.c b/reactos/hal/halppc/generic/reboot.c new file mode 100644 index 00000000000..89ab5c0d221 --- /dev/null +++ b/reactos/hal/halppc/generic/reboot.c @@ -0,0 +1,41 @@ +/* $Id: reboot.c 23907 2006-09-04 05:52:23Z arty $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/reboot.c + * PURPOSE: Reboot functions. + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * Created 11/10/99 + */ + +#include +#define NDEBUG +#include + +typedef void (*void_fun)(); +static VOID +HalReboot (VOID) +{ + void_fun reset_vector = (void_fun)0xfff00100; + reset_vector(); +} + + +VOID STDCALL +HalReturnToFirmware ( + FIRMWARE_REENTRY Action + ) +{ + if (Action == HalHaltRoutine) + { + DbgPrint ("HalReturnToFirmware called!\n"); + DbgBreakPoint (); + } + else if (Action == HalRebootRoutine) + { + HalReboot (); + } +} + +/* EOF */ diff --git a/reactos/hal/halppc/generic/resource.c b/reactos/hal/halppc/generic/resource.c new file mode 100644 index 00000000000..acf17ff151d --- /dev/null +++ b/reactos/hal/halppc/generic/resource.c @@ -0,0 +1,31 @@ +/* $Id: resource.c 23907 2006-09-04 05:52:23Z arty $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: hal/halx86/generic/resource.c + * PURPOSE: Miscellaneous resource functions + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + + +/* FUNCTIONS ****************************************************************/ + +VOID STDCALL +HalReportResourceUsage(VOID) +{ + /* + * FIXME: Report all resources used by hal. + * Calls IoReportHalResourceUsage() + */ + + /* Initialize PCI bus. */ + HalpInitPciBus (); +} + +/* EOF */ diff --git a/reactos/hal/halppc/generic/spinlock.c b/reactos/hal/halppc/generic/spinlock.c new file mode 100644 index 00000000000..987762c96b5 --- /dev/null +++ b/reactos/hal/halppc/generic/spinlock.c @@ -0,0 +1,210 @@ +/* + * PROJECT: ReactOS HAL + * LICENSE: GPL - See COPYING in the top level directory + * FILE: hal/halx86/up/spinlock.c + * PURPOSE: Spinlock and Queued Spinlock Support + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +#undef KeAcquireSpinLock +#undef KeReleaseSpinLock +#undef KeLowerIrql +#undef KeRaiseIrql + + +KIRQL FASTCALL +KfRaiseIrql (KIRQL NewIrql); + +VOID FASTCALL +KfLowerIrql (KIRQL NewIrql); + +/* FUNCTIONS *****************************************************************/ + +/* + * @implemented + */ +VOID +NTAPI +KeLowerIrql(KIRQL NewIrql) +{ + /* Call the fastcall function */ + KfLowerIrql(NewIrql); +} + +/* + * @implemented + */ +NTKERNELAPI +KIRQL +NTAPI +KeRaiseIrql(KIRQL NewIrql, + PKIRQL OldIrql) +{ + /* Call the fastcall function */ + return *OldIrql = KfRaiseIrql(NewIrql); +} + +/* + * @implemented + */ +VOID +NTAPI +KeAcquireSpinLock(PKSPIN_LOCK SpinLock, + PKIRQL OldIrql) +{ + /* Call the fastcall function */ + *OldIrql = KfAcquireSpinLock(SpinLock); +} + +/* + * @implemented + */ +KIRQL +FASTCALL +KeAcquireSpinLockRaiseToSynch(PKSPIN_LOCK SpinLock) +{ + /* Simply raise to dispatch */ + return KfRaiseIrql(DISPATCH_LEVEL); +} + +/* + * @implemented + */ +VOID +NTAPI +KeReleaseSpinLock(PKSPIN_LOCK SpinLock, + KIRQL NewIrql) +{ + /* Call the fastcall function */ + KfReleaseSpinLock(SpinLock, NewIrql); +} + +/* + * @implemented + */ +KIRQL +FASTCALL +KfAcquireSpinLock(PKSPIN_LOCK SpinLock) +{ + /* Simply raise to dispatch */ + return KfRaiseIrql(DISPATCH_LEVEL); +} + +/* + * @implemented + */ +VOID +FASTCALL +KfReleaseSpinLock(PKSPIN_LOCK SpinLock, + KIRQL OldIrql) +{ + /* Simply lower IRQL back */ + KfLowerIrql(OldIrql); +} + +/* + * @implemented + */ +KIRQL +FASTCALL +KeAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber) +{ + /* Simply raise to dispatch */ + return KfRaiseIrql(DISPATCH_LEVEL); +} + +/* + * @implemented + */ +KIRQL +FASTCALL +KeAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber) +{ + /* Simply raise to dispatch */ + return KfRaiseIrql(DISPATCH_LEVEL); +} + +/* + * @implemented + */ +VOID +FASTCALL +KeAcquireInStackQueuedSpinLock(IN PKSPIN_LOCK SpinLock, + IN PKLOCK_QUEUE_HANDLE LockHandle) +{ + /* Simply raise to dispatch */ + LockHandle->OldIrql = KfRaiseIrql(DISPATCH_LEVEL); +} + +/* + * @implemented + */ +VOID +FASTCALL +KeAcquireInStackQueuedSpinLockRaiseToSynch(IN PKSPIN_LOCK SpinLock, + IN PKLOCK_QUEUE_HANDLE LockHandle) +{ + /* Simply raise to synch */ + LockHandle->OldIrql = KfRaiseIrql(SYNCH_LEVEL); +} + +/* + * @implemented + */ +VOID +FASTCALL +KeReleaseQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, + IN KIRQL OldIrql) +{ + /* Simply lower IRQL back */ + KfLowerIrql(OldIrql); +} + +/* + * @implemented + */ +VOID +FASTCALL +KeReleaseInStackQueuedSpinLock(IN PKLOCK_QUEUE_HANDLE LockHandle) +{ + /* Simply lower IRQL back */ + KfLowerIrql(LockHandle->OldIrql); +} + +/* + * @implemented + */ +BOOLEAN +FASTCALL +KeTryToAcquireQueuedSpinLockRaiseToSynch(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, + IN PKIRQL OldIrql) +{ + /* Simply raise to dispatch */ + *OldIrql = KfRaiseIrql(DISPATCH_LEVEL); + + /* Always return true on UP Machines */ + return TRUE; +} + +/* + * @implemented + */ +LOGICAL +FASTCALL +KeTryToAcquireQueuedSpinLock(IN KSPIN_LOCK_QUEUE_NUMBER LockNumber, + OUT PKIRQL OldIrql) +{ + /* Simply raise to dispatch */ + *OldIrql = KfRaiseIrql(DISPATCH_LEVEL); + + /* Always return true on UP Machines */ + return TRUE; +} + +/* EOF */ diff --git a/reactos/hal/halppc/generic/sysbus.c b/reactos/hal/halppc/generic/sysbus.c new file mode 100644 index 00000000000..4955b122cfd --- /dev/null +++ b/reactos/hal/halppc/generic/sysbus.c @@ -0,0 +1,66 @@ +/* $Id: sysbus.c 23907 2006-09-04 05:52:23Z arty $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/sysbus.c + * PURPOSE: System bus handler functions + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * 09/04/2000 Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + + +/* FUNCTIONS ****************************************************************/ + +ULONG STDCALL +HalpGetSystemInterruptVector(PVOID BusHandler, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity) +{ + ULONG Vector = IRQ2VECTOR(BusInterruptVector); + *Irql = VECTOR2IRQL(Vector); + *Affinity = 0xFFFFFFFF; + return Vector; +} + + +BOOLEAN STDCALL +HalpTranslateSystemBusAddress(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress) +{ + ULONG BaseAddress = 0; + + if (*AddressSpace == 0) + { + /* memory space */ + + } + else if (*AddressSpace == 1) + { + /* io space */ + + } + else + { + /* other */ + return FALSE; + } + + TranslatedAddress->QuadPart = BusAddress.QuadPart + BaseAddress; + + return TRUE; +} + +/* EOF */ diff --git a/reactos/hal/halppc/generic/sysinfo.c b/reactos/hal/halppc/generic/sysinfo.c new file mode 100644 index 00000000000..b27b2bc32c7 --- /dev/null +++ b/reactos/hal/halppc/generic/sysinfo.c @@ -0,0 +1,41 @@ +/* + * PROJECT: ReactOS HA: + * LICENSE: GPL - See COPYING in the top level directory + * FILE: hal/halx86/generic/sysinfo.c + * PURPOSE: HAL Information Routines + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +#define KdComPortInUse _KdComPortInUse +ULONG KdComPortInUse = 0; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +NTAPI +HaliQuerySystemInformation(IN HAL_QUERY_INFORMATION_CLASS InformationClass, + IN ULONG BufferSize, + IN OUT PVOID Buffer, + OUT PULONG ReturnedLength) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +NTAPI +HaliSetSystemInformation(IN HAL_SET_INFORMATION_CLASS InformationClass, + IN ULONG BufferSize, + IN OUT PVOID Buffer) +{ + UNIMPLEMENTED; + return STATUS_NOT_IMPLEMENTED; +} + +/* EOF */ diff --git a/reactos/hal/halppc/generic/systimer.S b/reactos/hal/halppc/generic/systimer.S new file mode 100644 index 00000000000..285686675a7 --- /dev/null +++ b/reactos/hal/halppc/generic/systimer.S @@ -0,0 +1,48 @@ +/* + * FILE: hal/halx86/generic/timer.S + * COPYRIGHT: See COPYING in the top level directory + * PURPOSE: System Timer Interrupt and Management + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +.intel_syntax noprefix + +/* FUNCTIONS *****************************************************************/ + +.globl _HalpClockInterrupt@0 +.func HalpClockInterrupt@0 +_HalpClockInterrupt@0: + + /* Enter trap */ + INT_PROLOG Hci, DoPushFakeErrorCode + + /* Push vector and make stack for IRQL */ + push 0x30 + sub esp, 4 + + /* Begin the interrupt */ + push esp + push 0x30 + push CLOCK2_LEVEL + call _HalBeginSystemInterrupt@12 + + /* Check if it's spurious */ + or al, al + jz Spurious + + /* Do a tick */ + mov eax, 100000 + jmp _KeUpdateSystemTime@0 + +Spurious: + + /* Exit the interrupt */ + add esp, 8 + mov esi, $ + jmp _Kei386EoiHelper@0 +.endfunc + diff --git a/reactos/hal/halppc/generic/time.c b/reactos/hal/halppc/generic/time.c new file mode 100644 index 00000000000..bb81cc01cec --- /dev/null +++ b/reactos/hal/halppc/generic/time.c @@ -0,0 +1,102 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/time.c + * PURPOSE: Getting time information + * UPDATE HISTORY: + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + + +/* MACROS and CONSTANTS ******************************************************/ + +/* macro BCD_INT : convert bcd to int */ +#define BCD_INT(bcd) (((bcd & 0xf0) >> 4) * 10 + (bcd &0x0f)) + +/* macro INT_BCD : convert int to bcd */ +#define INT_BCD(int) (((int / 10) << 4) + (int % 10)) + + +#define RTC_REGISTER_A 0x0A +#define RTC_REG_A_UIP 0x80 /* Update In Progress bit */ + +#define RTC_REGISTER_B 0x0B + +#define RTC_REGISTER_CENTURY 0x32 + +/* GLOBALS ******************************************************************/ + +/* FUNCTIONS *****************************************************************/ + +BOOLEAN STDCALL +HalQueryRealTimeClock(PTIME_FIELDS Time) +{ + return TRUE; +} + + +VOID STDCALL +HalSetRealTimeClock(PTIME_FIELDS Time) +{ +} + + +BOOLEAN STDCALL +HalGetEnvironmentVariable(PCH Name, + USHORT ValueLength, + PCH Value) +{ + strncpy(Value, "TRUE", ValueLength); + return TRUE; +} + + +BOOLEAN STDCALL +HalSetEnvironmentVariable(PCH Name, + PCH Value) +{ + return TRUE; +} + + +ULONG STDCALL +HalpGetCmosData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + DPRINT("HalpGetCmosData() called.\n"); + DPRINT(" BusNumber %lu\n", BusNumber); + DPRINT(" SlotNumber %lu\n", SlotNumber); + DPRINT(" Offset 0x%lx\n", Offset); + DPRINT(" Length 0x%lx\n", Length); + + return 0; +} + + +ULONG STDCALL +HalpSetCmosData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + DPRINT("HalpSetCmosData() called.\n"); + DPRINT(" BusNumber %lu\n", BusNumber); + DPRINT(" SlotNumber %lu\n", SlotNumber); + DPRINT(" Offset 0x%lx\n", Offset); + DPRINT(" Length 0x%lx\n", Length); + + return 0; +} + +/* EOF */ diff --git a/reactos/hal/halppc/generic/timer.c b/reactos/hal/halppc/generic/timer.c new file mode 100644 index 00000000000..a3e23fc83dd --- /dev/null +++ b/reactos/hal/halppc/generic/timer.c @@ -0,0 +1,138 @@ +/* + * PROJECT: ReactOS HAL + * LICENSE: GPL - See COPYING in the top level directory + * FILE: hal/halx86/generic/timer.c + * PURPOSE: HAL Timer Routines + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +BOOLEAN HalpClockSetMSRate; +ULONG HalpCurrentTimeIncrement; +ULONG HalpCurrentRollOver; +ULONG HalpNextMSRate = 14; +ULONG HalpLargestClockMS = 15; + +LARGE_INTEGER HalpRolloverTable[15] = +{ + {{1197, 10032}}, + {{2394, 20064}}, + {{3591, 30096}}, + {{4767, 39952}}, + {{5964, 49984}}, + {{7161, 60016}}, + {{8358, 70048}}, + {{9555, 80080}}, + {{10731, 89936}}, + {{11949, 100144}}, + {{13125, 110000}}, + {{14322, 120032}}, + {{15519, 130064}}, + {{16695, 139920}}, + {{17892, 149952}} +}; + +/* PRIVATE FUNCTIONS *********************************************************/ + +VOID +NTAPI +HalpInitializeClock(VOID) +{ + //PKPRCB Prcb = KeGetCurrentPrcb(); + ULONG Increment; + USHORT RollOver; + ULONG Flags = 0; + + /* Get increment and rollover for the largest time clock ms possible */ + Increment = HalpRolloverTable[HalpLargestClockMS - 1].HighPart; + RollOver = (USHORT)HalpRolloverTable[HalpLargestClockMS - 1].LowPart; + + /* Set the maximum and minimum increment with the kernel */ + HalpCurrentTimeIncrement = Increment; + KeSetTimeIncrement(Increment, HalpRolloverTable[0].HighPart); + + /* Disable interrupts */ + Flags = __readmsr(); + _disable(); + + /* Set the rollover */ + __outbyte(TIMER_CONTROL_PORT, TIMER_SC0 | TIMER_BOTH | TIMER_MD2); + __outbyte(TIMER_DATA_PORT0, RollOver & 0xFF); + __outbyte(TIMER_DATA_PORT0, RollOver >> 8); + + /* Restore interrupts if they were previously enabled */ + __writemsr(Flags); + + /* Save rollover and return */ + HalpCurrentRollOver = RollOver; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +/* + * @implemented + */ +VOID +NTAPI +HalCalibratePerformanceCounter(IN volatile PLONG Count, + IN ULONGLONG NewCount) +{ + ULONG Flags = 0; + + /* Disable interrupts */ + Flags = __readmsr(); + _disable(); + + /* Do a decrement for this CPU */ + _InterlockedDecrement(Count); + + /* Wait for other CPUs */ + while (*Count); + + /* Restore interrupts if they were previously enabled */ + __writemsr(Flags); +} + +/* + * @implemented + */ +ULONG +NTAPI +HalSetTimeIncrement(IN ULONG Increment) +{ + /* Round increment to ms */ + Increment /= 10000; + + /* Normalize between our minimum (1 ms) and maximum (variable) setting */ + if (Increment > HalpLargestClockMS) Increment = HalpLargestClockMS; + if (Increment <= 0) Increment = 1; + + /* Set the rate and tell HAL we want to change it */ + HalpNextMSRate = Increment; + HalpClockSetMSRate = TRUE; + + /* Return the increment */ + return HalpRolloverTable[Increment - 1].HighPart; +} + +VOID +NTHALAPI +KeStallExecutionProcessor(ULONG USec) +{ + LARGE_INTEGER Freq, Start = KeQueryPerformanceCounter(&Freq), End; + LARGE_INTEGER Timebase, Remainder; + Timebase.QuadPart = 1000000; + Freq.QuadPart *= USec; + End = RtlLargeIntegerDivide(Freq, Timebase, &Remainder); + End.QuadPart += Start.QuadPart; + while(End.QuadPart > __rdtsc()); +} + +/* EOF */ diff --git a/reactos/hal/halppc/include/apic.h b/reactos/hal/halppc/include/apic.h new file mode 100644 index 00000000000..7454c210f72 --- /dev/null +++ b/reactos/hal/halppc/include/apic.h @@ -0,0 +1,214 @@ +/* + * + */ + +#ifndef __INTERNAL_HAL_APIC_H +#define __INTERNAL_HAL_APIC_H + +#define APIC_DEFAULT_BASE 0xFEE00000 /* Default Local APIC Base Register Address */ + +/* APIC Register Address Map */ +#define APIC_ID 0x0020 /* Local APIC ID Register (R/W) */ +#define APIC_VER 0x0030 /* Local APIC Version Register (R) */ +#define APIC_TPR 0x0080 /* Task Priority Register (R/W) */ +#define APIC_APR 0x0090 /* Arbitration Priority Register (R) */ +#define APIC_PPR 0x00A0 /* Processor Priority Register (R) */ +#define APIC_EOI 0x00B0 /* EOI Register (W) */ +#define APIC_LDR 0x00D0 /* Logical Destination Register (R/W) */ +#define APIC_DFR 0x00E0 /* Destination Format Register (0-27 R, 28-31 R/W) */ +#define APIC_SIVR 0x00F0 /* Spurious Interrupt Vector Register (0-3 R, 4-9 R/W) */ +#define APIC_ISR 0x0100 /* Interrupt Service Register 0-255 (R) */ +#define APIC_TMR 0x0180 /* Trigger Mode Register 0-255 (R) */ +#define APIC_IRR 0x0200 /* Interrupt Request Register 0-255 (r) */ +#define APIC_ESR 0x0280 /* Error Status Register (R) */ +#define APIC_ICR0 0x0300 /* Interrupt Command Register 0-31 (R/W) */ +#define APIC_ICR1 0x0310 /* Interrupt Command Register 32-63 (R/W) */ +#define APIC_LVTT 0x0320 /* Local Vector Table (Timer) (R/W) */ +#define APIC_LVTTHMR 0x0330 +#define APIC_LVTPC 0x0340 /* Performance Counter LVT (R/W) */ +#define APIC_LINT0 0x0350 /* Local Vector Table (LINT0) (R/W) */ +#define APIC_LINT1 0x0360 /* Local Vector Table (LINT1) (R/W) */ +#define APIC_LVT3 0x0370 /* Local Vector Table (Error) (R/W) */ +#define APIC_ICRT 0x0380 /* Initial Count Register for Timer (R/W) */ +#define APIC_CCRT 0x0390 /* Current Count Register for Timer (R) */ +#define APIC_TDCR 0x03E0 /* Timer Divide Configuration Register (R/W) */ + +#define APIC_ID_MASK (0xF << 24) +#define GET_APIC_ID(x) (((x) & APIC_ID_MASK) >> 24) +#define GET_APIC_LOGICAL_ID(x) (((x)>>24)&0xFF) +#define APIC_VER_MASK 0xFF00FF +#define GET_APIC_VERSION(x) ((x) & 0xFF) +#define GET_APIC_MAXLVT(x) (((x) >> 16) & 0xFF) + +#define APIC_TPR_PRI 0xFF +#define APIC_TPR_INT 0xF0 +#define APIC_TPR_SUB 0xF +#define APIC_TPR_MAX 0xFF /* Maximum priority */ +#define APIC_TPR_MIN 0x20 /* Minimum priority */ + +#define APIC_LDR_MASK (0xFF << 24) + +#define APIC_SIVR_ENABLE (0x1 << 8) +#define APIC_SIVR_FOCUS (0x1 << 9) + +#define APIC_ESR_MASK (0xFE << 0) /* Error Mask */ + +#define APIC_ICR0_VECTOR (0xFF << 0) /* Vector */ +#define APIC_ICR0_DM (0x7 << 8) /* Delivery Mode */ +#define APIC_ICR0_DESTM (0x1 << 11) /* Destination Mode */ +#define APIC_ICR0_DS (0x1 << 12) /* Delivery Status */ +#define APIC_ICR0_LEVEL (0x1 << 14) /* Level */ +#define APIC_ICR0_TM (0x1 << 15) /* Trigger Mode */ +#define APIC_ICR0_DESTS (0x3 << 18) /* Destination Shorthand */ + +/* Delivery Modes */ +#define APIC_DM_FIXED (0x0 << 8) +#define APIC_DM_LOWEST (0x1 << 8) +#define APIC_DM_SMI (0x2 << 8) +#define APIC_DM_REMRD (0x3 << 8) +#define APIC_DM_NMI (0x4 << 8) +#define APIC_DM_INIT (0x5 << 8) +#define APIC_DM_STARTUP (0x6 << 8) +#define APIC_DM_EXTINT (0x7 << 8) +#define GET_APIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7) +#define SET_APIC_DELIVERY_MODE(x,y) (((x) & ~0x700) | ((y) << 8)) + +/* Destination Shorthand values */ +#define APIC_ICR0_DESTS_FIELD (0x0 << 0) +#define APIC_ICR0_DESTS_SELF (0x1 << 18) +#define APIC_ICR0_DESTS_ALL (0x2 << 18) +#define APIC_ICR0_DESTS_ALL_BUT_SELF (0x3 << 18) + +#define APIC_ICR0_LEVEL_DEASSERT (0x0 << 14) /* Deassert level */ +#define APIC_ICR0_LEVEL_ASSERT (0x1 << 14) /* Assert level */ + +#define GET_APIC_DEST_FIELD(x) (((x) >> 24) & 0xFF) +#define SET_APIC_DEST_FIELD(x) (((x) & 0xFF) << 24) + +#define GET_APIC_TIMER_BASE(x) (((x) >> 18) & 0x3) +#define SET_APIC_TIMER_BASE(x) ((x) << 18) +#define APIC_TIMER_BASE_CLKIN 0x0 +#define APIC_TIMER_BASE_TMBASE 0x1 +#define APIC_TIMER_BASE_DIV 0x2 + +#define APIC_LVT_VECTOR (0xFF << 0) /* Vector */ +#define APIC_LVT_DS (0x1 << 12) /* Delivery Status */ +#define APIC_LVT_REMOTE_IRR (0x1 << 14) /* Remote IRR */ +#define APIC_LVT_LEVEL_TRIGGER (0x1 << 15) /* Lvel Triggered */ +#define APIC_LVT_MASKED (0x1 << 16) /* Mask */ +#define APIC_LVT_PERIODIC (0x1 << 17) /* Timer Mode */ + +#define APIC_LVT3_DM (0x7 << 8) +#define APIC_LVT3_IIPP (0x1 << 13) +#define APIC_LVT3_TM (0x1 << 15) +#define APIC_LVT3_MASKED (0x1 << 16) +#define APIC_LVT3_OS (0x1 << 17) + +#define APIC_TDCR_TMBASE (0x1 << 2) +#define APIC_TDCR_MASK 0x0F +#define APIC_TDCR_2 0x00 +#define APIC_TDCR_4 0x01 +#define APIC_TDCR_8 0x02 +#define APIC_TDCR_16 0x03 +#define APIC_TDCR_32 0x08 +#define APIC_TDCR_64 0x09 +#define APIC_TDCR_128 0x0A +#define APIC_TDCR_1 0x0B + +#define APIC_LVT_VECTOR (0xFF << 0) /* Vector */ +#define APIC_LVT_DS (0x1 << 12) /* Delivery Status */ +#define APIC_LVT_REMOTE_IRR (0x1 << 14) /* Remote IRR */ +#define APIC_LVT_LEVEL_TRIGGER (0x1 << 15) /* Lvel Triggered */ +#define APIC_LVT_MASKED (0x1 << 16) /* Mask */ +#define APIC_LVT_PERIODIC (0x1 << 17) /* Timer Mode */ + +#define APIC_LVT3_DM (0x7 << 8) +#define APIC_LVT3_IIPP (0x1 << 13) +#define APIC_LVT3_TM (0x1 << 15) +#define APIC_LVT3_MASKED (0x1 << 16) +#define APIC_LVT3_OS (0x1 << 17) + +#define APIC_TDCR_TMBASE (0x1 << 2) +#define APIC_TDCR_MASK 0x0F +#define APIC_TDCR_2 0x00 +#define APIC_TDCR_4 0x01 +#define APIC_TDCR_8 0x02 +#define APIC_TDCR_16 0x03 +#define APIC_TDCR_32 0x08 +#define APIC_TDCR_64 0x09 +#define APIC_TDCR_128 0x0A +#define APIC_TDCR_1 0x0B + +#define APIC_TARGET_SELF 0x100 +#define APIC_TARGET_ALL 0x200 +#define APIC_TARGET_ALL_BUT_SELF 0x300 + +#define APIC_INTEGRATED(version) (version & 0xF0) + +typedef enum { + amPIC = 0, /* IMCR and PIC compatibility mode */ + amVWIRE /* Virtual Wire compatibility mode */ +} APIC_MODE; + +#ifdef CONFIG_SMP +#define MAX_CPU 32 +#else +#define MAX_CPU 1 +#endif + +/* + * Local APIC timer IRQ vector is on a different priority level, + * to work around the 'lost local interrupt if more than 2 IRQ + * sources per level' errata. + */ +#define LOCAL_TIMER_VECTOR 0xEF + +#define IPI_VECTOR 0xFB +#define ERROR_VECTOR 0xFE +#define SPURIOUS_VECTOR 0xFF /* Must be 0xXF */ + +/* CPU flags */ +#define CPU_USABLE 0x01 /* 1 if the CPU is usable (ie. can be used) */ +#define CPU_ENABLED 0x02 /* 1 if the CPU is enabled */ +#define CPU_BSP 0x04 /* 1 if the CPU is the bootstrap processor */ +#define CPU_TSC 0x08 /* 1 if the CPU has a time stamp counter */ + +typedef struct _CPU_INFO +{ + UCHAR Flags; /* CPU flags */ + UCHAR APICId; /* Local APIC ID */ + UCHAR APICVersion; /* Local APIC version */ +// UCHAR MaxLVT; /* Number of LVT registers */ + ULONG BusSpeed; /* BUS speed */ + ULONG CoreSpeed; /* Core speed */ + UCHAR Padding[16-12]; /* Padding to 16-byte */ +} CPU_INFO, *PCPU_INFO; + +extern ULONG CPUCount; /* Total number of CPUs */ +extern ULONG BootCPU; /* Bootstrap processor */ +extern ULONG OnlineCPUs; /* Bitmask of online CPUs */ +extern CPU_INFO CPUMap[MAX_CPU]; /* Map of all CPUs in the system */ + +/* Prototypes */ + +__inline VOID APICWrite(ULONG Offset, ULONG Value); +__inline ULONG APICRead(ULONG Offset); +VOID APICSendIPI(ULONG Target, ULONG Mode); +VOID APICSetup(VOID); +VOID HaliInitBSP(VOID); +VOID APICSyncArbIDs(VOID); +__inline VOID APICSendEOI(VOID); +VOID APICCalibrateTimer(ULONG CPU); +VOID HaliStartApplicationProcessor(ULONG Cpu, ULONG Stack); + +static __inline ULONG ThisCPU(VOID) +{ + return (APICRead(APIC_ID) & APIC_ID_MASK) >> 24; +} + + +#endif + + +/* EOF */ + diff --git a/reactos/hal/halppc/include/bus.h b/reactos/hal/halppc/include/bus.h new file mode 100644 index 00000000000..2c82d3ed61d --- /dev/null +++ b/reactos/hal/halppc/include/bus.h @@ -0,0 +1,296 @@ +#ifndef __INTERNAL_HAL_BUS_H +#define __INTERNAL_HAL_BUS_H + +// +// Helper Macros +// +#define PASTE2(x,y) x ## y +#define POINTER_TO_(x) PASTE2(P,x) +#define READ_FROM(x) PASTE2(READ_PORT_, x) +#define WRITE_TO(x) PASTE2(WRITE_PORT_, x) + +// +// Declares a PCI Register Read/Write Routine +// +#define TYPE_DEFINE(x, y) \ + ULONG \ + NTAPI \ + x( \ + IN PPCIPBUSDATA BusData, \ + IN y PciCfg, \ + IN PUCHAR Buffer, \ + IN ULONG Offset \ + ) +#define TYPE1_DEFINE(x) TYPE_DEFINE(x, PPCI_TYPE1_CFG_BITS); +#define TYPE2_DEFINE(x) TYPE_DEFINE(x, PPCI_TYPE2_ADDRESS_BITS); + +// +// Defines a PCI Register Read/Write Type 1 Routine Prologue and Epilogue +// +#define TYPE1_START(x, y) \ + TYPE_DEFINE(x, PPCI_TYPE1_CFG_BITS) \ +{ \ + ULONG i = Offset % sizeof(ULONG); \ + PciCfg->u.bits.RegisterNumber = Offset / sizeof(ULONG); \ + WRITE_PORT_ULONG(BusData->Config.Type1.Address, PciCfg->u.AsULONG); +#define TYPE1_END(y) \ + return sizeof(y); } +#define TYPE2_END TYPE1_END + +// +// PCI Register Read Type 1 Routine +// +#define TYPE1_READ(x, y) \ + TYPE1_START(x, y) \ + *((POINTER_TO_(y))Buffer) = \ + READ_FROM(y)((POINTER_TO_(y))(BusData->Config.Type1.Data + i)); \ + TYPE1_END(y) + +// +// PCI Register Write Type 1 Routine +// +#define TYPE1_WRITE(x, y) \ + TYPE1_START(x, y) \ + WRITE_TO(y)((POINTER_TO_(y))(BusData->Config.Type1.Data + i), \ + *((POINTER_TO_(y))Buffer)); \ + TYPE1_END(y) + +// +// Defines a PCI Register Read/Write Type 2 Routine Prologue and Epilogue +// +#define TYPE2_START(x, y) \ + TYPE_DEFINE(x, PPCI_TYPE2_ADDRESS_BITS) \ +{ \ + PciCfg->u.bits.RegisterNumber = (USHORT)Offset; + +// +// PCI Register Read Type 2 Routine +// +#define TYPE2_READ(x, y) \ + TYPE2_START(x, y) \ + *((POINTER_TO_(y))Buffer) = \ + READ_FROM(y)((POINTER_TO_(y))(ULONG)PciCfg->u.AsUSHORT); \ + TYPE2_END(y) + +// +// PCI Register Write Type 2 Routine +// +#define TYPE2_WRITE(x, y) \ + TYPE2_START(x, y) \ + WRITE_TO(y)((POINTER_TO_(y))(ULONG)PciCfg->u.AsUSHORT, \ + *((POINTER_TO_(y))Buffer)); \ + TYPE2_END(y) + +typedef struct _PCIPBUSDATA +{ + PCIBUSDATA CommonData; + union + { + struct + { + PULONG Address; + ULONG Data; + } Type1; + struct + { + PUCHAR CSE; + PUCHAR Forward; + ULONG Base; + } Type2; + } Config; + ULONG MaxDevice; +} PCIPBUSDATA, *PPCIPBUSDATA; + +typedef ULONG +(NTAPI *FncConfigIO)( + IN PPCIPBUSDATA BusData, + IN PVOID State, + IN PUCHAR Buffer, + IN ULONG Offset +); + +typedef VOID +(NTAPI *FncSync)( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PVOID State +); + +typedef VOID +(NTAPI *FncReleaseSync)( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql +); + +typedef struct _PCI_CONFIG_HANDLER +{ + FncSync Synchronize; + FncReleaseSync ReleaseSynchronzation; + FncConfigIO ConfigRead[3]; + FncConfigIO ConfigWrite[3]; +} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER; + +typedef struct _PCI_REGISTRY_INFO_INTERNAL +{ + UCHAR MajorRevision; + UCHAR MinorRevision; + UCHAR NoBuses; + UCHAR HardwareMechanism; + ULONG ElementCount; + PCI_CARD_DESCRIPTOR CardList[ANYSIZE_ARRAY]; +} PCI_REGISTRY_INFO_INTERNAL, *PPCI_REGISTRY_INFO_INTERNAL; + +/* FUNCTIONS *****************************************************************/ + +VOID +NTAPI +HalpPCISynchronizeType1( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PPCI_TYPE1_CFG_BITS PciCfg +); + +VOID +NTAPI +HalpPCIReleaseSynchronzationType1( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql +); + +VOID +NTAPI +HalpPCISynchronizeType2( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PKIRQL Irql, + IN PPCI_TYPE2_ADDRESS_BITS PciCfg +); + +VOID +NTAPI +HalpPCIReleaseSynchronzationType2( + IN PBUS_HANDLER BusHandler, + IN KIRQL Irql +); + +TYPE1_DEFINE(HalpPCIReadUcharType1); +TYPE1_DEFINE(HalpPCIReadUshortType1); +TYPE1_DEFINE(HalpPCIReadUlongType1); +TYPE2_DEFINE(HalpPCIReadUcharType2); +TYPE2_DEFINE(HalpPCIReadUshortType2); +TYPE2_DEFINE(HalpPCIReadUlongType2); +TYPE1_DEFINE(HalpPCIWriteUcharType1); +TYPE1_DEFINE(HalpPCIWriteUshortType1); +TYPE1_DEFINE(HalpPCIWriteUlongType1); +TYPE2_DEFINE(HalpPCIWriteUcharType2); +TYPE2_DEFINE(HalpPCIWriteUshortType2); +TYPE2_DEFINE(HalpPCIWriteUlongType2); + +BOOLEAN +NTAPI +HalpValidPCISlot( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot +); + +VOID +NTAPI +HalpReadPCIConfig( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length +); + +VOID +NTAPI +HalpWritePCIConfig( + IN PBUS_HANDLER BusHandler, + IN PCI_SLOT_NUMBER Slot, + IN PVOID Buffer, + IN ULONG Offset, + IN ULONG Length +); + +ULONG +NTAPI +HalpGetSystemInterruptVector( + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity +); + +ULONG +NTAPI +HalpGetCmosData( + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Length +); + +ULONG +NTAPI +HalpSetCmosData( + IN ULONG BusNumber, + IN ULONG SlotNumber, + IN PVOID Buffer, + IN ULONG Length +); + +ULONG +NTAPI +HalpGetPCIData( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootBusHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length +); + +ULONG +NTAPI +HalpSetPCIData( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootBusHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PUCHAR Buffer, + IN ULONG Offset, + IN ULONG Length +); + +NTSTATUS +NTAPI +HalpAssignPCISlotResources( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName OPTIONAL, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject OPTIONAL, + IN ULONG Slot, + IN OUT PCM_RESOURCE_LIST *pAllocatedResources +); + +VOID +NTAPI +HalpInitializePciBus( + VOID +); + +extern ULONG HalpBusType; +extern BOOLEAN HalpPCIConfigInitialized; +extern BUS_HANDLER HalpFakePciBusHandler; +extern ULONG HalpMinPciBus, HalpMaxPciBus; + +#endif /* __INTERNAL_HAL_BUS_H */ + +/* EOF */ + + diff --git a/reactos/hal/halppc/include/hal.h b/reactos/hal/halppc/include/hal.h new file mode 100644 index 00000000000..5220140dfe4 --- /dev/null +++ b/reactos/hal/halppc/include/hal.h @@ -0,0 +1,53 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Hardware Abstraction Layer + * FILE: hal/halx86/include/hal.h + * PURPOSE: HAL Header + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + */ + +/* INCLUDES ******************************************************************/ + +/* C Headers */ +#include + +/* WDK HAL Compilation hack */ +#ifdef _MSC_VER +#include +#include +#undef _NTHAL_ +#undef DECLSPEC_IMPORT +#define DECLSPEC_IMPORT +#define __declspec(dllimport) +#endif + +/* IFS/DDK/NDK Headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Internal kernel headers */ +#include "internal/pci.h" +#include "internal/powerpc/intrin_i.h" + +/* Internal HAL Headers */ +#include "apic.h" +#include "bus.h" +#include "halirq.h" +#include "haldma.h" +#include "halp.h" +#include "mps.h" +#include "ioapic.h" + +/* Helper Header */ +#include + +/* EOF */ diff --git a/reactos/hal/halppc/include/haldma.h b/reactos/hal/halppc/include/haldma.h new file mode 100644 index 00000000000..59ddb9338a0 --- /dev/null +++ b/reactos/hal/halppc/include/haldma.h @@ -0,0 +1,383 @@ +#ifndef HALDMA_H +#define HALDMA_H + +/* + * DMA Page Register Structure + * 080 DMA RESERVED + * 081 DMA Page Register (channel 2) + * 082 DMA Page Register (channel 3) + * 083 DMA Page Register (channel 1) + * 084 DMA RESERVED + * 085 DMA RESERVED + * 086 DMA RESERVED + * 087 DMA Page Register (channel 0) + * 088 DMA RESERVED + * 089 PS/2-DMA Page Register (channel 6) + * 08A PS/2-DMA Page Register (channel 7) + * 08B PS/2-DMA Page Register (channel 5) + * 08C PS/2-DMA RESERVED + * 08D PS/2-DMA RESERVED + * 08E PS/2-DMA RESERVED + * 08F PS/2-DMA Page Register (channel 4) + */ + +typedef struct _DMA_PAGE +{ + UCHAR Reserved1; + UCHAR Channel2; + UCHAR Channel3; + UCHAR Channel1; + UCHAR Reserved2[3]; + UCHAR Channel0; + UCHAR Reserved3; + UCHAR Channel6; + UCHAR Channel7; + UCHAR Channel5; + UCHAR Reserved4[3]; + UCHAR Channel4; +} DMA_PAGE, *PDMA_PAGE; + +/* + * DMA Channel Mask Register Structure + * + * MSB LSB + * x x x x x x x x + * ------------------- - ----- + * | | | 00 - Select channel 0 mask bit + * | | \---- 01 - Select channel 1 mask bit + * | | 10 - Select channel 2 mask bit + * | | 11 - Select channel 3 mask bit + * | | + * | \---------- 0 - Clear mask bit + * | 1 - Set mask bit + * | + * \----------------------- xx - Reserved + */ + +typedef struct _DMA_CHANNEL_MASK +{ + UCHAR Channel: 2; + UCHAR SetMask: 1; + UCHAR Reserved: 5; +} DMA_CHANNEL_MASK, *PDMA_CHANNEL_MASK; + +/* + * DMA Mask Register Structure + * + * MSB LSB + * x x x x x x x x + * \---/ - - ----- ----- + * | | | | | 00 - Channel 0 select + * | | | | \---- 01 - Channel 1 select + * | | | | 10 - Channel 2 select + * | | | | 11 - Channel 3 select + * | | | | + * | | | | 00 - Verify transfer + * | | | \------------ 01 - Write transfer + * | | | 10 - Read transfer + * | | | + * | | \-------------------- 0 - Autoinitialized + * | | 1 - Non-autoinitialized + * | | + * | \------------------------ 0 - Address increment select + * | + * | 00 - Demand mode + * \------------------------------ 01 - Single mode + * 10 - Block mode + * 11 - Cascade mode + */ + +typedef union _DMA_MODE +{ + struct + { + UCHAR Channel: 2; + UCHAR TransferType: 2; + UCHAR AutoInitialize: 1; + UCHAR AddressDecrement: 1; + UCHAR RequestMode: 2; + }; + UCHAR Byte; +} DMA_MODE, *PDMA_MODE; + +/* + * DMA Extended Mode Register Structure + * + * MSB LSB + * x x x x x x x x + * - - ----- ----- ----- + * | | | | | 00 - Channel 0 select + * | | | | \---- 01 - Channel 1 select + * | | | | 10 - Channel 2 select + * | | | | 11 - Channel 3 select + * | | | | + * | | | | 00 - 8-bit I/O, by bytes + * | | | \------------ 01 - 16-bit I/O, by words, address shifted + * | | | 10 - 32-bit I/O, by bytes + * | | | 11 - 16-bit I/O, by bytes + * | | | + * | | \---------------------- 00 - Compatible + * | | 01 - Type A + * | | 10 - Type B + * | | 11 - Burst + * | | + * | \---------------------------- 0 - Terminal Count is Output + * | + * \---------------------------------0 - Disable Stop Register + * 1 - Enable Stop Register + */ + +typedef union _DMA_EXTENDED_MODE +{ + struct + { + UCHAR ChannelNumber: 2; + UCHAR TransferSize: 2; + UCHAR TimingMode: 2; + UCHAR TerminalCountIsOutput: 1; + UCHAR EnableStopRegister: 1; + }; + UCHAR Byte; +} DMA_EXTENDED_MODE, *PDMA_EXTENDED_MODE; + +/* DMA Extended Mode Register Transfer Sizes */ +#define B_8BITS 0 +#define W_16BITS 1 +#define B_32BITS 2 +#define B_16BITS 3 + +/* DMA Extended Mode Register Timing */ +#define COMPATIBLE_TIMING 0 +#define TYPE_A_TIMING 1 +#define TYPE_B_TIMING 2 +#define BURST_TIMING 3 + +/* Channel Stop Registers for each Channel */ +typedef struct _DMA_CHANNEL_STOP +{ + UCHAR ChannelLow; + UCHAR ChannelMid; + UCHAR ChannelHigh; + UCHAR Reserved; +} DMA_CHANNEL_STOP, *PDMA_CHANNEL_STOP; + +/* Transfer Types */ +#define VERIFY_TRANSFER 0x00 +#define READ_TRANSFER 0x01 +#define WRITE_TRANSFER 0x02 + +/* Request Modes */ +#define DEMAND_REQUEST_MODE 0x00 +#define SINGLE_REQUEST_MODE 0x01 +#define BLOCK_REQUEST_MODE 0x02 +#define CASCADE_REQUEST_MODE 0x03 + +#define DMA_SETMASK 4 +#define DMA_CLEARMASK 0 +#define DMA_READ 4 +#define DMA_WRITE 8 +#define DMA_SINGLE_TRANSFER 0x40 +#define DMA_AUTO_INIT 0x10 + +typedef struct _DMA1_ADDRESS_COUNT +{ + UCHAR DmaBaseAddress; + UCHAR DmaBaseCount; +} DMA1_ADDRESS_COUNT, *PDMA1_ADDRESS_COUNT; + +typedef struct _DMA2_ADDRESS_COUNT +{ + UCHAR DmaBaseAddress; + UCHAR Reserved1; + UCHAR DmaBaseCount; + UCHAR Reserved2; +} DMA2_ADDRESS_COUNT, *PDMA2_ADDRESS_COUNT; + +typedef struct _DMA1_CONTROL +{ + DMA1_ADDRESS_COUNT DmaAddressCount[4]; + UCHAR DmaStatus; + UCHAR DmaRequest; + UCHAR SingleMask; + UCHAR Mode; + UCHAR ClearBytePointer; + UCHAR MasterClear; + UCHAR ClearMask; + UCHAR AllMask; +} DMA1_CONTROL, *PDMA1_CONTROL; + +typedef struct _DMA2_CONTROL +{ + DMA2_ADDRESS_COUNT DmaAddressCount[4]; + UCHAR DmaStatus; + UCHAR Reserved1; + UCHAR DmaRequest; + UCHAR Reserved2; + UCHAR SingleMask; + UCHAR Reserved3; + UCHAR Mode; + UCHAR Reserved4; + UCHAR ClearBytePointer; + UCHAR Reserved5; + UCHAR MasterClear; + UCHAR Reserved6; + UCHAR ClearMask; + UCHAR Reserved7; + UCHAR AllMask; + UCHAR Reserved8; +} DMA2_CONTROL, *PDMA2_CONTROL; + +/* This structure defines the I/O Map of the 82537 controller. */ +typedef struct _EISA_CONTROL +{ + /* DMA Controller 1 */ + DMA1_CONTROL DmaController1; /* 00h-0Fh */ + UCHAR Reserved1[16]; /* 0Fh-1Fh */ + + /* Interrupt Controller 1 (PIC) */ + UCHAR Pic1Operation; /* 20h */ + UCHAR Pic1Interrupt; /* 21h */ + UCHAR Reserved2[30]; /* 22h-3Fh */ + + /* Timer */ + UCHAR TimerCounter; /* 40h */ + UCHAR TimerMemoryRefresh; /* 41h */ + UCHAR Speaker; /* 42h */ + UCHAR TimerOperation; /* 43h */ + UCHAR TimerMisc; /* 44h */ + UCHAR Reserved3[2]; /* 45-46h */ + UCHAR TimerCounterControl; /* 47h */ + UCHAR TimerFailSafeCounter; /* 48h */ + UCHAR Reserved4; /* 49h */ + UCHAR TimerCounter2; /* 4Ah */ + UCHAR TimerOperation2; /* 4Bh */ + UCHAR Reserved5[20]; /* 4Ch-5Fh */ + + /* NMI / Keyboard / RTC */ + UCHAR Keyboard; /* 60h */ + UCHAR NmiStatus; /* 61h */ + UCHAR Reserved6[14]; /* 62h-6Fh */ + UCHAR NmiEnable; /* 70h */ + UCHAR Reserved7[15]; /* 71h-7Fh */ + + /* DMA Page Registers Controller 1 */ + DMA_PAGE DmaController1Pages; /* 80h-8Fh */ + UCHAR Reserved8[16]; /* 90h-9Fh */ + + /* Interrupt Controller 2 (PIC) */ + UCHAR Pic2Operation; /* 0A0h */ + UCHAR Pic2Interrupt; /* 0A1h */ + UCHAR Reserved9[30]; /* 0A2h-0BFh */ + + /* DMA Controller 2 */ + DMA1_CONTROL DmaController2; /* 0C0h-0CFh */ + + /* System Reserved Ports */ + UCHAR SystemReserved[816]; /* 0D0h-3FFh */ + + /* Extended DMA Registers, Controller 1 */ + UCHAR DmaHighByteCount1[8]; /* 400h-407h */ + UCHAR Reserved10[2]; /* 408h-409h */ + UCHAR DmaChainMode1; /* 40Ah */ + UCHAR DmaExtendedMode1; /* 40Bh */ + UCHAR DmaBufferControl; /* 40Ch */ + UCHAR Reserved11[84]; /* 40Dh-460h */ + UCHAR ExtendedNmiControl; /* 461h */ + UCHAR NmiCommand; /* 462h */ + UCHAR Reserved12; /* 463h */ + UCHAR BusMaster; /* 464h */ + UCHAR Reserved13[27]; /* 465h-47Fh */ + + /* DMA Page Registers Controller 2 */ + DMA_PAGE DmaController2Pages; /* 480h-48Fh */ + UCHAR Reserved14[48]; /* 490h-4BFh */ + + /* Extended DMA Registers, Controller 2 */ + UCHAR DmaHighByteCount2[16]; /* 4C0h-4CFh */ + + /* Edge/Level Control Registers */ + UCHAR Pic1EdgeLevel; /* 4D0h */ + UCHAR Pic2EdgeLevel; /* 4D1h */ + UCHAR Reserved15[2]; /* 4D2h-4D3h */ + + /* Extended DMA Registers, Controller 2 */ + UCHAR DmaChainMode2; /* 4D4h */ + UCHAR Reserved16; /* 4D5h */ + UCHAR DmaExtendedMode2; /* 4D6h */ + UCHAR Reserved17[9]; /* 4D7h-4DFh */ + + /* DMA Stop Registers */ + DMA_CHANNEL_STOP DmaChannelStop[8]; /* 4E0h-4FFh */ +} EISA_CONTROL, *PEISA_CONTROL; + +typedef struct _ROS_MAP_REGISTER_ENTRY +{ + PVOID VirtualAddress; + PHYSICAL_ADDRESS PhysicalAddress; + ULONG Counter; +} ROS_MAP_REGISTER_ENTRY, *PROS_MAP_REGISTER_ENTRY; + +struct _ADAPTER_OBJECT { + /* + * New style DMA object definition. The fact that it is at the beginning + * of the ADAPTER_OBJECT structure allows us to easily implement the + * fallback implementation of IoGetDmaAdapter. + */ + DMA_ADAPTER DmaHeader; + + /* + * For normal adapter objects pointer to master adapter that takes care + * of channel allocation. For master adapter set to NULL. + */ + struct _ADAPTER_OBJECT *MasterAdapter; + + ULONG MapRegistersPerChannel; + PVOID AdapterBaseVa; + PROS_MAP_REGISTER_ENTRY MapRegisterBase; + + ULONG NumberOfMapRegisters; + ULONG CommittedMapRegisters; + + PWAIT_CONTEXT_BLOCK CurrentWcb; + KDEVICE_QUEUE ChannelWaitQueue; + PKDEVICE_QUEUE RegisterWaitQueue; + LIST_ENTRY AdapterQueue; + KSPIN_LOCK SpinLock; + PRTL_BITMAP MapRegisters; + PUCHAR PagePort; + UCHAR ChannelNumber; + UCHAR AdapterNumber; + USHORT DmaPortAddress; + DMA_MODE AdapterMode; + BOOLEAN NeedsMapRegisters; + BOOLEAN MasterDevice; + BOOLEAN Width16Bits; + BOOLEAN ScatterGather; + BOOLEAN IgnoreCount; + BOOLEAN Dma32BitAddresses; + BOOLEAN Dma64BitAddresses; + LIST_ENTRY AdapterList; +} ADAPTER_OBJECT; + +typedef struct _GROW_WORK_ITEM { + WORK_QUEUE_ITEM WorkQueueItem; + PADAPTER_OBJECT AdapterObject; + ULONG NumberOfMapRegisters; +} GROW_WORK_ITEM, *PGROW_WORK_ITEM; + +#define MAP_BASE_SW_SG 1 + +PADAPTER_OBJECT STDCALL +HalpDmaAllocateMasterAdapter(VOID); + +PDMA_ADAPTER STDCALL +HalpGetDmaAdapter( + IN PVOID Context, + IN PDEVICE_DESCRIPTION DeviceDescription, + OUT PULONG NumberOfMapRegisters); + +ULONG STDCALL +HalpDmaGetDmaAlignment( + PADAPTER_OBJECT AdapterObject); + +#endif /* HALDMA_H */ diff --git a/reactos/hal/halppc/include/halirq.h b/reactos/hal/halppc/include/halirq.h new file mode 100644 index 00000000000..32b77abc8a3 --- /dev/null +++ b/reactos/hal/halppc/include/halirq.h @@ -0,0 +1,35 @@ +/* + * $Id: halirq.h 23669 2006-08-23 16:58:43Z ion $ + */ + +#ifndef __INCLUDE_HAL_HALIRQ +#define __INCLUDE_HAL_HALIRQ + +#ifdef CONFIG_SMP + +#define FIRST_DEVICE_VECTOR (0x30) +#define FIRST_SYSTEM_VECTOR (0xef) + +#define IRQ_BASE FIRST_DEVICE_VECTOR +#define NR_IRQS (FIRST_SYSTEM_VECTOR - FIRST_DEVICE_VECTOR) + +/* + * FIXME: + * This does not work if we have more than 24 IRQs (ie. more than one I/O APIC) + */ +#define VECTOR2IRQ(vector) (23 - (vector - IRQ_BASE) / 8) +#define VECTOR2IRQL(vector) (PROFILE_LEVEL - VECTOR2IRQ(vector)) +#define IRQ2VECTOR(irq) (((23 - (irq)) * 8) + FIRST_DEVICE_VECTOR) + +#else + +#define IRQ_BASE (0x30) +#define NR_IRQS (16) + +#define VECTOR2IRQ(vector) ((vector) - IRQ_BASE) +#define VECTOR2IRQL(vector) (PROFILE_LEVEL - VECTOR2IRQ(vector)) +#define IRQ2VECTOR(irq) ((irq) + IRQ_BASE) + +#endif + +#endif /* __INCLUDE_HAL_HALIRQ */ diff --git a/reactos/hal/halppc/include/halp.h b/reactos/hal/halppc/include/halp.h new file mode 100644 index 00000000000..cb540295512 --- /dev/null +++ b/reactos/hal/halppc/include/halp.h @@ -0,0 +1,132 @@ +/* + * + */ + +#ifndef __INTERNAL_HAL_HAL_H +#define __INTERNAL_HAL_HAL_H + +/* Temporary hack */ +#define KPCR_BASE 0xFF000000 + +/* WDK Hack */ +#define KdComPortInUse _KdComPortInUse + +#define HAL_APC_REQUEST 0 +#define HAL_DPC_REQUEST 1 + +/* CMOS Registers and Ports */ +#define CMOS_CONTROL_PORT (PUCHAR)0x70 +#define CMOS_DATA_PORT (PUCHAR)0x71 +#define RTC_REGISTER_A 0x0A +#define RTC_REGISTER_B 0x0B +#define RTC_REG_A_UIP 0x80 +#define RTC_REGISTER_CENTURY 0x32 + +/* Timer Registers and Ports */ +#define TIMER_CONTROL_PORT 0x43 +#define TIMER_DATA_PORT0 0x40 +#define TIMER_SC0 0 +#define TIMER_BOTH 0x30 +#define TIMER_MD2 0x4 + +/* Conversion functions */ +#define BCD_INT(bcd) \ + (((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F)) +#define INT_BCD(int) \ + (UCHAR)(((int / 10) << 4) + (int % 10)) + +/* adapter.c */ +PADAPTER_OBJECT STDCALL HalpAllocateAdapterEx(ULONG NumberOfMapRegisters,BOOLEAN IsMaster, BOOLEAN Dma32BitAddresses); + +/* bus.c */ +VOID NTAPI HalpInitNonBusHandler (VOID); + +/* irql.c */ +VOID NTAPI HalpInitPICs(VOID); + +/* udelay.c */ +VOID NTAPI HalpInitializeClock(VOID); + +/* pci.c */ +VOID HalpInitPciBus (VOID); + +/* dma.c */ +VOID HalpInitDma (VOID); + +/* Non-generic initialization */ +VOID HalpInitPhase0 (PLOADER_PARAMETER_BLOCK LoaderBlock); +VOID HalpInitPhase1(VOID); +VOID NTAPI HalpClockInterrupt(VOID); + +// +// KD Support +// +VOID +NTAPI +HalpCheckPowerButton( + VOID +); + +VOID +NTAPI +HalpRegisterKdSupportFunctions( + VOID +); + +NTSTATUS +NTAPI +HalpSetupPciDeviceForDebugging( + IN PVOID LoaderBlock, + IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice +); + +NTSTATUS +NTAPI +HalpReleasePciDeviceForDebugging( + IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice +); + +// +// Memory routines +// +PVOID +NTAPI +HalpMapPhysicalMemory64( + IN PHYSICAL_ADDRESS PhysicalAddress, + IN ULONG NumberPage +); + +VOID +NTAPI +HalpUnmapVirtualAddress( + IN PVOID VirtualAddress, + IN ULONG NumberPages +); + +/* sysinfo.c */ +NTSTATUS +NTAPI +HaliQuerySystemInformation( + IN HAL_QUERY_INFORMATION_CLASS InformationClass, + IN ULONG BufferSize, + IN OUT PVOID Buffer, + OUT PULONG ReturnedLength +); + +NTSTATUS +NTAPI +HaliSetSystemInformation( + IN HAL_SET_INFORMATION_CLASS InformationClass, + IN ULONG BufferSize, + IN OUT PVOID Buffer +); + +typedef struct tagHALP_HOOKS +{ + void (*InitPciBus)(ULONG BusNumber, PBUS_HANDLER BusHandler); +} HALP_HOOKS, *PHALP_HOOKS; + +extern HALP_HOOKS HalpHooks; +extern KSPIN_LOCK HalpSystemHardwareLock; + +#endif /* __INTERNAL_HAL_HAL_H */ diff --git a/reactos/hal/halppc/include/ioapic.h b/reactos/hal/halppc/include/ioapic.h new file mode 100644 index 00000000000..114853c4a6d --- /dev/null +++ b/reactos/hal/halppc/include/ioapic.h @@ -0,0 +1,103 @@ +/* + * + */ + +#ifndef __INTERNAL_HAL_IOAPIC_H +#define __INTERNAL_HAL_IOAPIC_H + +/* I/O APIC Register Address Map */ +#define IOAPIC_IOREGSEL 0x0000 /* I/O Register Select (index) (R/W) */ +#define IOAPIC_IOWIN 0x0010 /* I/O window (data) (R/W) */ + +#define IOAPIC_ID 0x0000 /* IO APIC ID (R/W) */ +#define IOAPIC_VER 0x0001 /* IO APIC Version (R) */ +#define IOAPIC_ARB 0x0002 /* IO APIC Arbitration ID (R) */ +#define IOAPIC_REDTBL 0x0010 /* Redirection Table (0-23 64-bit registers) (R/W) */ + +#define IOAPIC_ID_MASK (0xF << 24) +#define GET_IOAPIC_ID(x) (((x) & IOAPIC_ID_MASK) >> 24) +#define SET_IOAPIC_ID(x) ((x) << 24) + +#define IOAPIC_VER_MASK (0xFF) +#define GET_IOAPIC_VERSION(x) (((x) & IOAPIC_VER_MASK)) +#define IOAPIC_MRE_MASK (0xFF << 16) /* Maximum Redirection Entry */ +#define GET_IOAPIC_MRE(x) (((x) & IOAPIC_MRE_MASK) >> 16) + +#define IOAPIC_ARB_MASK (0xF << 24) +#define GET_IOAPIC_ARB(x) (((x) & IOAPIC_ARB_MASK) >> 24) + +#define IOAPIC_TBL_DELMOD (0x7 << 10) /* Delivery Mode (see APIC_DM_*) */ +#define IOAPIC_TBL_DM (0x1 << 11) /* Destination Mode */ +#define IOAPIC_TBL_DS (0x1 << 12) /* Delivery Status */ +#define IOAPIC_TBL_INTPOL (0x1 << 13) /* Interrupt Input Pin Polarity */ +#define IOAPIC_TBL_RIRR (0x1 << 14) /* Remote IRR */ +#define IOAPIC_TBL_TM (0x1 << 15) /* Trigger Mode */ +#define IOAPIC_TBL_IM (0x1 << 16) /* Interrupt Mask */ +#define IOAPIC_TBL_DF0 (0xF << 56) /* Destination Field (physical mode) */ +#define IOAPIC_TBL_DF1 (0xFF<< 56) /* Destination Field (logical mode) */ +#define IOAPIC_TBL_VECTOR (0xFF << 0) /* Vector (10h - FEh) */ + +#include +typedef struct _IOAPIC_ROUTE_ENTRY { + ULONG vector : 8, + delivery_mode : 3, /* 000: FIXED + * 001: lowest priority + * 111: ExtINT + */ + dest_mode : 1, /* 0: physical, 1: logical */ + delivery_status : 1, + polarity : 1, + irr : 1, + trigger : 1, /* 0: edge, 1: level */ + mask : 1, /* 0: enabled, 1: disabled */ + __reserved_2 : 15; + + union { + struct { + ULONG __reserved_1 : 24, + physical_dest : 4, + __reserved_2 : 4; + } physical; + struct { + ULONG __reserved_1 : 24, + logical_dest : 8; + } logical; + } dest; +} IOAPIC_ROUTE_ENTRY, *PIOAPIC_ROUTE_ENTRY; +#include + +typedef struct _IOAPIC_INFO +{ + ULONG ApicId; /* APIC ID */ + ULONG ApicVersion; /* APIC version */ + ULONG ApicAddress; /* APIC address */ + ULONG EntryCount; /* Number of redirection entries */ +} IOAPIC_INFO, *PIOAPIC_INFO; + +#define IOAPIC_DEFAULT_BASE 0xFEC00000 /* Default I/O APIC Base Register Address */ + +extern ULONG IRQCount; /* Number of IRQs */ +extern UCHAR BUSMap[MAX_BUS]; /* Map of all buses in the system */ +extern UCHAR PCIBUSMap[MAX_BUS]; /* Map of all PCI buses in the system */ +extern IOAPIC_INFO IOAPICMap[MAX_IOAPIC]; /* Map of all I/O APICs in the system */ +extern ULONG IOAPICCount; /* Number of I/O APICs in the system */ +extern ULONG APICMode; /* APIC mode at startup */ +extern MP_CONFIGURATION_INTSRC IRQMap[MAX_IRQ_SOURCE]; /* Map of all IRQs */ + +VOID IOAPICSetupIrqs(VOID); +VOID IOAPICEnable(VOID); +VOID IOAPICSetupIds(VOID); +VOID IOAPICMaskIrq(ULONG Irq); +VOID IOAPICUnmaskIrq(ULONG Irq); + +VOID HaliReconfigurePciInterrupts(VOID); + +/* For debugging */ +VOID IOAPICDump(VOID); + +#endif + + + +/* EOF */ + diff --git a/reactos/hal/halppc/include/mps.h b/reactos/hal/halppc/include/mps.h new file mode 100644 index 00000000000..83f9cfbe501 --- /dev/null +++ b/reactos/hal/halppc/include/mps.h @@ -0,0 +1,204 @@ +#ifndef __INCLUDE_HAL_MPS +#define __INCLUDE_HAL_MPS + +/* + * FIXME: This does not work if we have more than 24 IRQs (ie. more than one + * I/O APIC) + */ +#define IRQL2VECTOR(irql) (IRQ2VECTOR(PROFILE_LEVEL - (irql))) + +#define IRQL2TPR(irql) ((irql) >= IPI_LEVEL ? IPI_VECTOR : ((irql) >= PROFILE_LEVEL ? LOCAL_TIMER_VECTOR : ((irql) > DISPATCH_LEVEL ? IRQL2VECTOR(irql) : 0))) + +typedef struct _KIRQ_TRAPFRAME +{ + ULONG Magic; + ULONG Gs; + ULONG Fs; + ULONG Es; + ULONG Ds; + ULONG Eax; + ULONG Ecx; + ULONG Edx; + ULONG Ebx; + ULONG Esp; + ULONG Ebp; + ULONG Esi; + ULONG Edi; + ULONG Eip; + ULONG Cs; + ULONG Eflags; +} KIRQ_TRAPFRAME, *PKIRQ_TRAPFRAME; + +#if 0 +/* This values are defined in halirql.h */ +#define FIRST_DEVICE_VECTOR 0x30 +#define FIRST_SYSTEM_VECTOR 0xEF +#endif + +#define NUMBER_DEVICE_VECTORS (FIRST_SYSTEM_VECTOR - FIRST_DEVICE_VECTOR) + + +/* MP Floating Pointer Structure */ +#define MPF_SIGNATURE (('_' << 24) | ('P' << 16) | ('M' << 8) | '_') + +#include +typedef struct _MP_FLOATING_POINTER +{ + ULONG Signature; /* _MP_ */ + ULONG Address; /* Physical Address Pointer (0 means no configuration table exist) */ + UCHAR Length; /* Structure length in 16-byte paragraphs */ + UCHAR Specification; /* Specification revision */ + UCHAR Checksum; /* Checksum */ + UCHAR Feature1; /* MP System Configuration Type */ + UCHAR Feature2; /* Bit 7 set for IMCR|PIC */ + UCHAR Feature3; /* Unused (0) */ + UCHAR Feature4; /* Unused (0) */ + UCHAR Feature5; /* Unused (0) */ +} MP_FLOATING_POINTER, *PMP_FLOATING_POINTER; + + +#define FEATURE2_IMCRP 0x80 + +/* MP Configuration Table Header */ +#define MPC_SIGNATURE (('P' << 24) | ('M' << 16) | ('C' << 8) | 'P') + +typedef struct _MP_CONFIGURATION_TABLE +{ + ULONG Signature; /* PCMP */ + USHORT Length; /* Size of configuration table */ + CHAR Specification; /* Specification Revision */ + CHAR Checksum; /* Checksum */ + CHAR Oem[8]; /* OEM ID */ + CHAR ProductId[12]; /* Product ID */ + ULONG OemTable; /* 0 if not present */ + USHORT OemTableSize; /* 0 if not present */ + USHORT EntryCount; /* Number of entries */ + ULONG LocalAPICAddress; /* Local APIC address */ + USHORT ExtTableLength; /* Extended Table Length */ + UCHAR ExtTableChecksum; /* Extended Table Checksum */ + UCHAR Reserved; /* Reserved */ +} MP_CONFIGURATION_TABLE, *PMP_CONFIGURATION_TABLE; + +/* MP Configuration Table Entries */ +#define MPCTE_PROCESSOR 0 /* One entry per processor */ +#define MPCTE_BUS 1 /* One entry per bus */ +#define MPCTE_IOAPIC 2 /* One entry per I/O APIC */ +#define MPCTE_INTSRC 3 /* One entry per bus interrupt source */ +#define MPCTE_LINTSRC 4 /* One entry per system interrupt source */ + + +typedef struct _MP_CONFIGURATION_PROCESSOR +{ + UCHAR Type; /* 0 */ + UCHAR ApicId; /* Local APIC ID for the processor */ + UCHAR ApicVersion; /* Local APIC version */ + UCHAR CpuFlags; /* CPU flags */ + ULONG CpuSignature; /* CPU signature */ + ULONG FeatureFlags; /* CPUID feature value */ + ULONG Reserved[2]; /* Reserved (0) */ +} MP_CONFIGURATION_PROCESSOR, *PMP_CONFIGURATION_PROCESSOR; + + + +typedef struct _MP_CONFIGURATION_BUS +{ + UCHAR Type; /* 1 */ + UCHAR BusId; /* Bus ID */ + CHAR BusType[6]; /* Bus type */ +} MP_CONFIGURATION_BUS, *PMP_CONFIGURATION_BUS; + +#define MAX_BUS 32 + +#define MP_BUS_ISA 1 +#define MP_BUS_EISA 2 +#define MP_BUS_PCI 3 +#define MP_BUS_MCA 4 + +#define BUSTYPE_EISA "EISA" +#define BUSTYPE_ISA "ISA" +#define BUSTYPE_INTERN "INTERN" /* Internal BUS */ +#define BUSTYPE_MCA "MCA" +#define BUSTYPE_VL "VL" /* Local bus */ +#define BUSTYPE_PCI "PCI" +#define BUSTYPE_PCMCIA "PCMCIA" +#define BUSTYPE_CBUS "CBUS" +#define BUSTYPE_CBUSII "CBUSII" +#define BUSTYPE_FUTURE "FUTURE" +#define BUSTYPE_MBI "MBI" +#define BUSTYPE_MBII "MBII" +#define BUSTYPE_MPI "MPI" +#define BUSTYPE_MPSA "MPSA" +#define BUSTYPE_NUBUS "NUBUS" +#define BUSTYPE_TC "TC" +#define BUSTYPE_VME "VME" +#define BUSTYPE_XPRESS "XPRESS" + + +typedef struct _MP_CONFIGURATION_IOAPIC +{ + UCHAR Type; /* 2 */ + UCHAR ApicId; /* I/O APIC ID */ + UCHAR ApicVersion; /* I/O APIC version */ + UCHAR ApicFlags; /* I/O APIC flags */ + ULONG ApicAddress; /* I/O APIC base address */ +} MP_CONFIGURATION_IOAPIC, *PMP_CONFIGURATION_IOAPIC; + +#define MAX_IOAPIC 2 + +#define MP_IOAPIC_USABLE 0x01 + + +typedef struct _MP_CONFIGURATION_INTSRC +{ + UCHAR Type; /* 3 */ + UCHAR IrqType; /* Interrupt type */ + USHORT IrqFlag; /* Interrupt flags */ + UCHAR SrcBusId; /* Source bus ID */ + UCHAR SrcBusIrq; /* Source bus interrupt */ + UCHAR DstApicId; /* Destination APIC ID */ + UCHAR DstApicInt; /* Destination interrupt */ +} MP_CONFIGURATION_INTSRC, *PMP_CONFIGURATION_INTSRC; + +#define MAX_IRQ_SOURCE 128 + +#define INT_VECTORED 0 +#define INT_NMI 1 +#define INT_SMI 2 +#define INT_EXTINT 3 + +#define IRQDIR_DEFAULT 0 +#define IRQDIR_HIGH 1 +#define IRQDIR_LOW 3 + + +typedef struct _MP_CONFIGURATION_INTLOCAL +{ + UCHAR Type; /* 4 */ + UCHAR IrqType; /* Interrupt type */ + USHORT IrqFlag; /* Interrupt flags */ + UCHAR SrcBusId; /* Source bus ID */ + UCHAR SrcBusIrq; /* Source bus interrupt */ + UCHAR DstApicId; /* Destination local APIC ID */ + UCHAR DstApicLInt; /* Destination local APIC interrupt */ +} MP_CONFIGURATION_INTLOCAL, *PMP_CONFIGURATION_INTLOCAL; +#include + +#define MP_APIC_ALL 0xFF + +#define CPU_FLAG_ENABLED 1 /* Processor is available */ +#define CPU_FLAG_BSP 2 /* Processor is the bootstrap processor */ + +#define CPU_STEPPING_MASK 0x0F +#define CPU_MODEL_MASK 0xF0 +#define CPU_FAMILY_MASK 0xF00 + +#define PIC_IRQS 16 + +/* Prototypes */ + +VOID HalpInitMPS(VOID); + + +#endif /* __INCLUDE_HAL_MPS */ + +/* EOF */ diff --git a/reactos/hal/halppc/up/halinit_up.c b/reactos/hal/halppc/up/halinit_up.c new file mode 100644 index 00000000000..cbb18bc665e --- /dev/null +++ b/reactos/hal/halppc/up/halinit_up.c @@ -0,0 +1,32 @@ +/* $Id: halinit_up.c 24964 2006-11-29 08:28:20Z ion $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/halinit.c + * PURPOSE: Initalize the x86 hal + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 11/06/98: Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +/* FUNCTIONS ***************************************************************/ + +VOID +HalpInitPhase0(IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + +} + +VOID +HalpInitPhase1(VOID) +{ + +} + +/* EOF */ diff --git a/reactos/hal/halppc/up/halup.rbuild b/reactos/hal/halppc/up/halup.rbuild new file mode 100644 index 00000000000..34efd0e7bbb --- /dev/null +++ b/reactos/hal/halppc/up/halup.rbuild @@ -0,0 +1,13 @@ + + + + ../include + include + + + + halppc_generic + ntoskrnl + halinit_up.c + halup.rc + diff --git a/reactos/hal/halppc/up/halup.rc b/reactos/hal/halppc/up/halup.rc new file mode 100644 index 00000000000..90af6b929ff --- /dev/null +++ b/reactos/hal/halppc/up/halup.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "X86 Uniprocessor Hardware Abstraction Layer\0" +#define REACTOS_STR_INTERNAL_NAME "halup\0" +#define REACTOS_STR_ORIGINAL_FILENAME "halup.dll\0" +#include diff --git a/reactos/include/ddk/winddk.h b/reactos/include/ddk/winddk.h index 7d10216dcee..43866dcd38e 100644 --- a/reactos/include/ddk/winddk.h +++ b/reactos/include/ddk/winddk.h @@ -5330,6 +5330,75 @@ typedef struct _KFLOATING_SAVE { ULONG Dummy; } KFLOATING_SAVE, *PKFLOATING_SAVE; +#elif defined(__PowerPC__) + +typedef ULONG PFN_NUMBER, *PPFN_NUMBER; + +#define PASSIVE_LEVEL 0 +#define LOW_LEVEL 0 +#define APC_LEVEL 1 +#define DISPATCH_LEVEL 2 +#define PROFILE_LEVEL 27 +#define CLOCK1_LEVEL 28 +#define CLOCK2_LEVEL 28 +#define IPI_LEVEL 29 +#define POWER_LEVEL 30 +#define HIGH_LEVEL 31 + +typedef struct _KFLOATING_SAVE { + ULONG Dummy; +} KFLOATING_SAVE, *PKFLOATING_SAVE; + +typedef struct _KPCR_TIB { + PVOID ExceptionList; /* 00 */ + PVOID StackBase; /* 04 */ + PVOID StackLimit; /* 08 */ + PVOID SubSystemTib; /* 0C */ + _ANONYMOUS_UNION union { + PVOID FiberData; /* 10 */ + DWORD Version; /* 10 */ + } DUMMYUNIONNAME; + PVOID ArbitraryUserPointer; /* 14 */ + struct _KPCR_TIB *Self; /* 18 */ +} KPCR_TIB, *PKPCR_TIB; /* 1C */ + +#define PCR_MINOR_VERSION 1 +#define PCR_MAJOR_VERSION 1 + +typedef struct _KPCR { + KPCR_TIB Tib; /* 00 */ + struct _KPCR *Self; /* 1C */ + struct _KPRCB *Prcb; /* 20 */ + KIRQL Irql; /* 24 */ + ULONG IRR; /* 28 */ + ULONG IrrActive; /* 2C */ + ULONG IDR; /* 30 */ + PVOID KdVersionBlock; /* 34 */ + PUSHORT IDT; /* 38 */ + PUSHORT GDT; /* 3C */ + struct _KTSS *TSS; /* 40 */ + USHORT MajorVersion; /* 44 */ + USHORT MinorVersion; /* 46 */ + KAFFINITY SetMember; /* 48 */ + ULONG StallScaleFactor; /* 4C */ + UCHAR SpareUnused; /* 50 */ + UCHAR Number; /* 51 */ +} KPCR, *PKPCR; /* 54 */ + +static __inline +ULONG +DDKAPI +KeGetCurrentProcessorNumber(VOID) +{ + ULONG Number; + __asm__ __volatile__ ( + "lwz %0, %c1(12)\n" + : "=r" (Number) + : "i" (FIELD_OFFSET(KPCR, Number)) + ); + return Number; +} + #else #error Unknown architecture #endif diff --git a/reactos/include/ndk/powerpc/ketypes.h b/reactos/include/ndk/powerpc/ketypes.h index 739fb7ae854..4d870b34b8d 100644 --- a/reactos/include/ndk/powerpc/ketypes.h +++ b/reactos/include/ndk/powerpc/ketypes.h @@ -31,81 +31,155 @@ Author: #define IPI_FREEZE 3 #define IPI_PACKET_READY 4 #define IPI_SYNCH_REQUEST 10 +#define MAXIMUM_VECTOR 0x100 + +#define KSEG0_BASE 0x80000000 + +#define PRCB_MAJOR_VERSION 1 +#define PRCB_BUILD_DEBUG 1 + +#ifndef ROUND_UP +#define ROUND_UP(x,y) (((x) + ((y)-1)) & ~((y)-1)) +#endif + +typedef double DOUBLE; + +typedef struct _FX_SAVE_AREA { + ULONG Fr[32]; +} FX_SAVE_AREA; + +typedef struct _LDT_ENTRY { + USHORT LimitLow; + USHORT BaseLow; + union + { + struct + { + UCHAR BaseMid; + UCHAR Flags1; + UCHAR Flags2; + UCHAR BaseHi; + } Bytes; + struct + { + ULONG BaseMid : 8; + ULONG Type : 5; + ULONG Dpl : 2; + ULONG Pres : 1; + ULONG LimitHi : 4; + ULONG Sys : 1; + ULONG Reserved_0 : 1; + ULONG Default_Big : 1; + ULONG Granularity : 1; + ULONG BaseHi : 8; + } Bits; + } HighWord; +} LDT_ENTRY; + +#ifndef CONFIG_SMP +#define SYNCH_LEVEL DISPATCH_LEVEL +#else +#define SYNCH_LEVEL (IPI_LEVEL - 1) +#endif // // Trap Frame Definition // typedef struct _KTRAP_FRAME { - PVOID TrapFrame; - UCHAR OldIrql; - UCHAR PreviousMode; - UCHAR SavedApcStateIndex; - UCHAR SavedKernelApcDisable; - UCHAR ExceptionRecord[ROUND_UP(sizeof(EXCEPTION_RECORD), ULONGLONG]; - ULONG FILL2; - ULONG Gpr0; - ULONG Gpr1; - ULONG Gpr2; - ULONG Gpr3; - ULONG Gpr4; - ULONG Gpr5; - ULONG Gpr6; - ULONG Gpr7; - ULONG Gpr8; - ULONG Gpr9; - ULONG Gpr10; - ULONG Gpr11; - ULONG Gpr12; - DOUBLE Fpr0; - DOUBLE Fpr1; - DOUBLE Fpr2; - DOUBLE Fpr3; - DOUBLE Fpr4; - DOUBLE Fpr5; - DOUBLE Fpr6; - DOUBLE Fpr7; - DOUBLE Fpr8; - DOUBLE Fpr9; - DOUBLE Fpr10; - DOUBLE Fpr11; - DOUBLE Fpr12; - DOUBLE Fpr13; - DOUBLE Fpscr; - ULONG Cr; - ULONG Xer; - ULONG Msr; - ULONG Iar; - ULONG Lr; - ULONG Ctr; - ULONG Dr0; - ULONG Dr1; - ULONG Dr2; - ULONG Dr3; - ULONG Dr4; - ULONG Dr5; - ULONG Dr6; + PVOID TrapFrame; + UCHAR OldIrql; + UCHAR PreviousMode; + UCHAR SavedApcStateIndex; + UCHAR SavedKernelApcDisable; + UCHAR ExceptionRecord[ROUND_UP(sizeof(EXCEPTION_RECORD), sizeof(ULONGLONG))]; + ULONG FILL2; + ULONG Gpr0; + ULONG Gpr1; + ULONG Gpr2; + ULONG Gpr3; + ULONG Gpr4; + ULONG Gpr5; + ULONG Gpr6; + ULONG Gpr7; + ULONG Gpr8; + ULONG Gpr9; + ULONG Gpr10; + ULONG Gpr11; + ULONG Gpr12; + DOUBLE Fpr0; + DOUBLE Fpr1; + DOUBLE Fpr2; + DOUBLE Fpr3; + DOUBLE Fpr4; + DOUBLE Fpr5; + DOUBLE Fpr6; + DOUBLE Fpr7; + DOUBLE Fpr8; + DOUBLE Fpr9; + DOUBLE Fpr10; + DOUBLE Fpr11; + DOUBLE Fpr12; + DOUBLE Fpr13; + DOUBLE Fpscr; + ULONG Cr; + ULONG Xer; + ULONG Msr; + ULONG Iar; + ULONG Lr; + ULONG Ctr; + ULONG Dr0; + ULONG Dr1; + ULONG Dr2; + ULONG Dr3; + ULONG Dr4; + ULONG Dr5; + ULONG Dr6; ULONG Dr7; } KTRAP_FRAME, *PKTRAP_FRAME; // -// Page Table Entry Definition +// GDT Entry Definition // -typedef struct _HARDWARE_PTE_PPC +typedef struct _KGDTENTRY { - ULONG Dirty:2; - ULONG Valid:1; - ULONG GuardedStorage:1; - ULONG MemoryCoherence:1; - ULONG CacheDisable:1; - ULONG WriteThrough:1; - ULONG Change:1; - ULONG Reference:1; - ULONG Write:1; - ULONG CopyOnWrite:1; - ULONG rsvd1:1; - ULONG PageFrameNumber:20; -} HARDWARE_PTE_PPC, *PHARDWARE_PTE_PPC; + USHORT LimitLow; + USHORT BaseLow; + union + { + struct + { + UCHAR BaseMid; + UCHAR Flags1; + UCHAR Flags2; + UCHAR BaseHi; + } Bytes; + struct + { + ULONG BaseMid:8; + ULONG Type:5; + ULONG Dpl:2; + ULONG Pres:1; + ULONG LimitHi:4; + ULONG Sys:1; + ULONG Reserved_0:1; + ULONG Default_Big:1; + ULONG Granularity:1; + ULONG BaseHi:8; + } Bits; + } HighWord; +} KGDTENTRY, *PKGDTENTRY; + +// +// IDT Entry Definition +// +typedef struct _KIDTENTRY +{ + USHORT Offset; + USHORT Selector; + USHORT Access; + USHORT ExtendedOffset; +} KIDTENTRY, *PKIDTENTRY; typedef struct _DESCRIPTOR { @@ -119,49 +193,49 @@ typedef struct _DESCRIPTOR // typedef struct _KSPECIAL_REGISTERS { - ULONG KernelDr0; - ULONG KernelDr1; - ULONG KernelDr2; - ULONG KernelDr3; - ULONG KernelDr4; - ULONG KernelDr5; - ULONG KernelDr6; - ULONG KernelDr7; - ULONG Sprg0; - ULONG Sprg1; - ULONG Sr0; - ULONG Sr1; - ULONG Sr2; - ULONG Sr3; - ULONG Sr4; - ULONG Sr5; - ULONG Sr6; - ULONG Sr7; - ULONG Sr8; - ULONG Sr9; - ULONG Sr10; - ULONG Sr11; - ULONG Sr12; - ULONG Sr13; - ULONG Sr14; - ULONG Sr15; - ULONG DBAT0L; - ULONG DBAT0U; - ULONG DBAT1L; - ULONG DBAT1U; - ULONG DBAT2L; - ULONG DBAT2U; - ULONG DBAT3L; - ULONG DBAT3U; - ULONG IBAT0L; - ULONG IBAT0U; - ULONG IBAT1L; - ULONG IBAT1U; - ULONG IBAT2L; - ULONG IBAT2U; - ULONG IBAT3L; - ULONG IBAT3U; - ULONG Sdr1; + ULONG KernelDr0; + ULONG KernelDr1; + ULONG KernelDr2; + ULONG KernelDr3; + ULONG KernelDr4; + ULONG KernelDr5; + ULONG KernelDr6; + ULONG KernelDr7; + ULONG Sprg0; + ULONG Sprg1; + ULONG Sr0; + ULONG Sr1; + ULONG Sr2; + ULONG Sr3; + ULONG Sr4; + ULONG Sr5; + ULONG Sr6; + ULONG Sr7; + ULONG Sr8; + ULONG Sr9; + ULONG Sr10; + ULONG Sr11; + ULONG Sr12; + ULONG Sr13; + ULONG Sr14; + ULONG Sr15; + ULONG DBAT0L; + ULONG DBAT0U; + ULONG DBAT1L; + ULONG DBAT1U; + ULONG DBAT2L; + ULONG DBAT2U; + ULONG DBAT3L; + ULONG DBAT3U; + ULONG IBAT0L; + ULONG IBAT0U; + ULONG IBAT1L; + ULONG IBAT1U; + ULONG IBAT2L; + ULONG IBAT2U; + ULONG IBAT3L; + ULONG IBAT3U; + ULONG Sdr1; ULONG Reserved[9]; } KSPECIAL_REGISTERS, *PKSPECIAL_REGISTERS; @@ -171,9 +245,9 @@ typedef struct _KSPECIAL_REGISTERS #pragma pack(push,4) typedef struct _KPROCESSOR_STATE { - PCONTEXT ContextFrame; + CONTEXT ContextFrame; KSPECIAL_REGISTERS SpecialRegisters; -} KPROCESSOR_STATE; +} KPROCESSOR_STATE, *PKPROCESSOR_STATE; // // Processor Region Control Block @@ -195,8 +269,13 @@ typedef struct _KPRCB KPROCESSOR_STATE ProcessorState; ULONG KernelReserved[16]; ULONG HalReserved[16]; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + ULONG CFlushSize; + UCHAR PrcbPad0[88]; +#else UCHAR PrcbPad0[92]; - PVOID LockQueue[33]; // Used for Queued Spinlocks +#endif + KSPIN_LOCK_QUEUE LockQueue[LockQueueMaximumLock]; struct _KTHREAD *NpxThread; ULONG InterruptCount; ULONG KernelTime; @@ -208,19 +287,41 @@ typedef struct _KPRCB ULONG PageColor; UCHAR SkipTick; UCHAR DebuggerSavedIRQL; +#if (NTDDI_VERSION >= NTDDI_WS03) + UCHAR NodeColor; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + UCHAR PollSlot; +#else + UCHAR Spare1; +#endif + ULONG NodeShiftedColor; +#else UCHAR Spare1[6]; +#endif struct _KNODE *ParentNode; ULONG MultiThreadProcessorSet; struct _KPRCB *MultiThreadSetMaster; +#if (NTDDI_VERSION >= NTDDI_WS03) + ULONG SecondaryColorMask; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + ULONG DpcTimeLimit; +#else + LONG Sleeping; +#endif +#else ULONG ThreadStartCount[2]; +#endif ULONG CcFastReadNoWait; ULONG CcFastReadWait; ULONG CcFastReadNotPossible; ULONG CcCopyReadNoWait; ULONG CcCopyReadWait; ULONG CcCopyReadNoWaitMiss; +#if (NTDDI_VERSION < NTDDI_LONGHORN) ULONG KeAlignmentFixupCount; - ULONG KeContextSwitches; +#endif + ULONG SpareCounter0; +#if (NTDDI_VERSION < NTDDI_LONGHORN) ULONG KeDcacheFlushCount; ULONG KeExceptionDispatchCount; ULONG KeFirstLevelTbFills; @@ -228,84 +329,170 @@ typedef struct _KPRCB ULONG KeIcacheFlushCount; ULONG KeSecondLevelTbFills; ULONG KeSystemCalls; - ULONG IoReadOperationCount; - ULONG IoWriteOperationCount; - ULONG IoOtherOperationCount; +#endif + volatile ULONG IoReadOperationCount; + volatile ULONG IoWriteOperationCount; + volatile ULONG IoOtherOperationCount; LARGE_INTEGER IoReadTransferCount; LARGE_INTEGER IoWriteTransferCount; LARGE_INTEGER IoOtherTransferCount; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + ULONG CcFastMdlReadNoWait; + ULONG CcFastMdlReadWait; + ULONG CcFastMdlReadNotPossible; + ULONG CcMapDataNoWait; + ULONG CcMapDataWait; + ULONG CcPinMappedDataCount; + ULONG CcPinReadNoWait; + ULONG CcPinReadWait; + ULONG CcMdlReadNoWait; + ULONG CcMdlReadWait; + ULONG CcLazyWriteHotSpots; + ULONG CcLazyWriteIos; + ULONG CcLazyWritePages; + ULONG CcDataFlushes; + ULONG CcDataPages; + ULONG CcLostDelayedWrites; + ULONG CcFastReadResourceMiss; + ULONG CcCopyReadWaitMiss; + ULONG CcFastMdlReadResourceMiss; + ULONG CcMapDataNoWaitMiss; + ULONG CcMapDataWaitMiss; + ULONG CcPinReadNoWaitMiss; + ULONG CcPinReadWaitMiss; + ULONG CcMdlReadNoWaitMiss; + ULONG CcMdlReadWaitMiss; + ULONG CcReadAheadIos; + ULONG KeAlignmentFixupCount; + ULONG KeExceptionDispatchCount; + ULONG KeSystemCalls; + ULONG PrcbPad1[3]; +#else ULONG SpareCounter1[8]; +#endif PP_LOOKASIDE_LIST PPLookasideList[16]; PP_LOOKASIDE_LIST PPNPagedLookasideList[32]; PP_LOOKASIDE_LIST PPPagedLookasideList[32]; - ULONG PacketBarrier; - ULONG ReverseStall; + volatile ULONG PacketBarrier; + volatile ULONG ReverseStall; PVOID IpiFrame; UCHAR PrcbPad2[52]; - PVOID CurrentPacket[3]; - ULONG TargetSet; - ULONG_PTR WorkerRoutine; - ULONG IpiFrozen; + volatile PVOID CurrentPacket[3]; + volatile ULONG TargetSet; + volatile PKIPI_WORKER WorkerRoutine; + volatile ULONG IpiFrozen; UCHAR PrcbPad3[40]; - ULONG RequestSummary; - struct _KPRCB *SignalDone; + volatile ULONG RequestSummary; + volatile struct _KPRCB *SignalDone; UCHAR PrcbPad4[56]; struct _KDPC_DATA DpcData[2]; PVOID DpcStack; ULONG MaximumDpcQueueDepth; ULONG DpcRequestRate; ULONG MinimumDpcRate; - UCHAR DpcInterruptRequested; - UCHAR DpcThreadRequested; - UCHAR DpcRoutineActive; - UCHAR DpcThreadActive; + volatile UCHAR DpcInterruptRequested; + volatile UCHAR DpcThreadRequested; + volatile UCHAR DpcRoutineActive; + volatile UCHAR DpcThreadActive; ULONG PrcbLock; ULONG DpcLastCount; - ULONG TimerHand; - ULONG TimerRequest; + volatile ULONG TimerHand; + volatile ULONG TimerRequest; PVOID DpcThread; - struct _KEVENT *DpcEvent; + KEVENT DpcEvent; UCHAR ThreadDpcEnable; - BOOLEAN QuantumEnd; + volatile BOOLEAN QuantumEnd; UCHAR PrcbPad50; - UCHAR IdleSchedule; - ULONG DpcSetEventRequest; + volatile UCHAR IdleSchedule; + LONG DpcSetEventRequest; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + LONG Sleeping; + ULONG PeriodicCount; + ULONG PeriodicBias; + UCHAR PrcbPad5[6]; +#else UCHAR PrcbPad5[18]; +#endif LONG TickOffset; - struct _KDPC* CallDpc; + KDPC CallDpc; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + LONG ClockKeepAlive; + UCHAR ClockCheckSlot; + UCHAR ClockPollCycle; + UCHAR PrcbPad6[2]; + LONG DpcWatchdogPeriod; + LONG DpcWatchDogCount; + LONG ThreadWatchdogPeriod; + LONG ThreadWatchDogCount; + ULONG PrcbPad70[2]; +#else ULONG PrcbPad7[8]; +#endif LIST_ENTRY WaitListHead; ULONG ReadySummary; - ULONG SelectNextLast; + ULONG QueueIndex; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + SINGLE_LIST_ENTRY DeferredReadyListHead; + ULONGLONG StartCycles; + ULONGLONG CycleTime; + ULONGLONG PrcbPad71[3]; + LIST_ENTRY DispatcherReadyListHead[32]; +#else LIST_ENTRY DispatcherReadyListHead[32]; SINGLE_LIST_ENTRY DeferredReadyListHead; ULONG PrcbPad72[11]; +#endif PVOID ChainedInterruptList; LONG LookasideIrpFloat; - LONG MmPageFaultCount; - LONG MmCopyOnWriteCount; - LONG MmTransitionCount; - LONG MmCacheTransitionCount; - LONG MmDemandZeroCount; - LONG MmPageReadCount; - LONG MmPageReadIoCount; - LONG MmCacheReadCount; - LONG MmCacheIoCount; - LONG MmDirtyPagesWriteCount; - LONG MmDirtyWriteIoCount; - LONG MmMappedPagesWriteCount; - LONG MmMappedWriteIoCount; + volatile LONG MmPageFaultCount; + volatile LONG MmCopyOnWriteCount; + volatile LONG MmTransitionCount; + volatile LONG MmCacheTransitionCount; + volatile LONG MmDemandZeroCount; + volatile LONG MmPageReadCount; + volatile LONG MmPageReadIoCount; + volatile LONG MmCacheReadCount; + volatile LONG MmCacheIoCount; + volatile LONG MmDirtyPagesWriteCount; + volatile LONG MmDirtyWriteIoCount; + volatile LONG MmMappedPagesWriteCount; + volatile LONG MmMappedWriteIoCount; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + ULONG CachedCommit; + ULONG CachedResidentAvailable; + PVOID HyperPte; + UCHAR CpuVendor; + UCHAR PrcbPad9[3]; +#else ULONG SpareFields0[1]; +#endif CHAR VendorString[13]; UCHAR InitialApicId; UCHAR LogicalProcessorsPerPhysicalProcessor; ULONG MHz; ULONG FeatureBits; LARGE_INTEGER UpdateSignature; - LARGE_INTEGER IsrTime; + volatile LARGE_INTEGER IsrTime; LARGE_INTEGER SpareField1; FX_SAVE_AREA NpxSaveArea; PROCESSOR_POWER_STATE PowerState; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + KDPC DpcWatchdogDoc; + KTIMER DpcWatchdogTimer; + PVOID WheaInfo; + PVOID EtwSupport; + SLIST_HEADER InterruptObjectPool; + LARGE_INTEGER HyperCallPagePhysical; + LARGE_INTEGER HyperCallPageVirtual; + PVOID RateControl; + CACHE_DESCRIPTOR Cache[5]; + ULONG CacheCount; + ULONG CacheProcessorMask[5]; + UCHAR LogicalProcessorsPerCore; + UCHAR PrcbPad8[3]; + ULONG PackageProcessorSet; + ULONG CoreProcessorSet; +#endif } KPRCB, *PKPRCB; // @@ -313,89 +500,89 @@ typedef struct _KPRCB // typedef struct _KIPCR { - USHORT MinorVersion; - USHORT MajorVersion; - PKINTERRUPT_ROUTINE InterruptRoutine[MAXIMUM_VECTOR]; - ULONG PcrPage2; - ULONG Kseg0Top; + USHORT MinorVersion; + USHORT MajorVersion; + PKINTERRUPT_ROUTINE InterruptRoutine[MAXIMUM_VECTOR]; + ULONG PcrPage2; + ULONG Kseg0Top; ULONG Spare7[30]; - ULONG FirstLevelDcacheSize; - ULONG FirstLevelDcacheFillSize; - ULONG FirstLevelIcacheSize; - ULONG FirstLevelIcacheFillSize; - ULONG SecondLevelDcacheSize; - ULONG SecondLevelDcacheFillSize; - ULONG SecondLevelIcacheSize; + ULONG FirstLevelDcacheSize; + ULONG FirstLevelDcacheFillSize; + ULONG FirstLevelIcacheSize; + ULONG FirstLevelIcacheFillSize; + ULONG SecondLevelDcacheSize; + ULONG SecondLevelDcacheFillSize; + ULONG SecondLevelIcacheSize; ULONG SecondLevelIcacheFillSize; - struct _KPRCB *Prcb; + struct _KPRCB *PrcbData; PVOID Teb; - ULONG DcacheAlignment; + ULONG DcacheAlignment; ULONG DcacheFillSize; - ULONG IcacheAlignment; + ULONG IcacheAlignment; ULONG IcacheFillSize; - ULONG ProcessorVersion; + ULONG ProcessorVersion; ULONG ProcessorRevision; - ULONG ProfileInterval; - ULONG ProfileCount; - ULONG StallExecutionCount; + ULONG ProfileInterval; + ULONG ProfileCount; + ULONG StallExecutionCount; ULONG StallScaleFactor; ULONG Spare; - union - { - ULONG CachePolicy; - struct - { - UCHAR IcacheMode; - UCHAR DcacheMode; - USHORT ModeSpare; - }; - }; - UCHAR IrqlMask[32]; + union + { + ULONG CachePolicy; + struct + { + UCHAR IcacheMode; + UCHAR DcacheMode; + USHORT ModeSpare; + }; + }; + UCHAR IrqlMask[32]; UCHAR IrqlTable[9]; - UCHAR CurrentIrql; - CCHAR Number; - KAFFINITY SetMember; - ULONG ReservedVectors; - struct _KTHREAD *CurrentThread; - ULONG AlignedCachePolicy; - union - { - ULONG SoftwareInterrupt; - struct - { - UCHAR ApcInterrupt; - UCHAR DispatchInterrupt; - UCHAR Spare4; - UCHAR Spare5; - }; - }; - KAFFINITY NotMember; - ULONG SystemReserved[16]; - ULONG HalReserved[16]; - ULONG FirstLevelActive; - ULONG SystemServiceDispatchStart; - ULONG SystemServiceDispatchEnd; - ULONG InterruptStack; - ULONG QuantumEnd; - PVOID InitialStack; - PVOID PanicStack; - ULONG BadVaddr; - PVOID StackLimit; - PVOID SavedStackLimit; - ULONG SavedV0; - ULONG SavedV1; - UCHAR DebugActive; - UCHAR Spare6[3]; - ULONG GprSave[6]; - ULONG SiR0; - ULONG SiR2; - ULONG SiR3; - ULONG SiR4; - ULONG SiR5; - ULONG Spare0; - ULONG Spare8; - ULONG PgDirRa; - ULONG OnInterruptStack; + UCHAR CurrentIrql; + CCHAR Number; + KAFFINITY SetMember; + ULONG ReservedVectors; + struct _KTHREAD *CurrentThread; + ULONG AlignedCachePolicy; + union + { + ULONG SoftwareInterrupt; + struct + { + UCHAR ApcInterrupt; + UCHAR DispatchInterrupt; + UCHAR Spare4; + UCHAR Spare5; + }; + }; + KAFFINITY NotMember; + ULONG SystemReserved[16]; + ULONG HalReserved[16]; + ULONG FirstLevelActive; + ULONG SystemServiceDispatchStart; + ULONG SystemServiceDispatchEnd; + ULONG InterruptStack; + ULONG QuantumEnd; + PVOID InitialStack; + PVOID PanicStack; + ULONG BadVaddr; + PVOID StackLimit; + PVOID SavedStackLimit; + ULONG SavedV0; + ULONG SavedV1; + UCHAR DebugActive; + UCHAR Spare6[3]; + ULONG GprSave[6]; + ULONG SiR0; + ULONG SiR2; + ULONG SiR3; + ULONG SiR4; + ULONG SiR5; + ULONG Spare0; + ULONG Spare8; + ULONG PgDirRa; + ULONG OnInterruptStack; ULONG SavedInitialStack; } KIPCR, *PKIPCR; #pragma pack(pop) @@ -403,51 +590,59 @@ typedef struct _KIPCR // // TSS Definition // -typedef struct _KTSS, KTSS, *PKTSS; +typedef struct _KTSS { +} KTSS, *PKTSS; // // PowerPC Exception Frame // typedef struct _KEXCEPTION_FRAME { - ULONG Fill1; - ULONG Gpr13; - ULONG Gpr14; - ULONG Gpr15; - ULONG Gpr16; - ULONG Gpr17; - ULONG Gpr18; - ULONG Gpr19; - ULONG Gpr20; - ULONG Gpr21; - ULONG Gpr22; - ULONG Gpr23; - ULONG Gpr24; - ULONG Gpr25; - ULONG Gpr26; - ULONG Gpr27; - ULONG Gpr28; - ULONG Gpr29; - ULONG Gpr30; - ULONG Gpr31; - DOUBLE Fpr14; - DOUBLE Fpr15; - DOUBLE Fpr16; - DOUBLE Fpr17; - DOUBLE Fpr18; - DOUBLE Fpr19; - DOUBLE Fpr20; - DOUBLE Fpr21; - DOUBLE Fpr22; - DOUBLE Fpr23; - DOUBLE Fpr24; - DOUBLE Fpr25; - DOUBLE Fpr26; - DOUBLE Fpr27; - DOUBLE Fpr28; - DOUBLE Fpr29; - DOUBLE Fpr30; + ULONG Fill1; + ULONG Gpr13; + ULONG Gpr14; + ULONG Gpr15; + ULONG Gpr16; + ULONG Gpr17; + ULONG Gpr18; + ULONG Gpr19; + ULONG Gpr20; + ULONG Gpr21; + ULONG Gpr22; + ULONG Gpr23; + ULONG Gpr24; + ULONG Gpr25; + ULONG Gpr26; + ULONG Gpr27; + ULONG Gpr28; + ULONG Gpr29; + ULONG Gpr30; + ULONG Gpr31; + DOUBLE Fpr14; + DOUBLE Fpr15; + DOUBLE Fpr16; + DOUBLE Fpr17; + DOUBLE Fpr18; + DOUBLE Fpr19; + DOUBLE Fpr20; + DOUBLE Fpr21; + DOUBLE Fpr22; + DOUBLE Fpr23; + DOUBLE Fpr24; + DOUBLE Fpr25; + DOUBLE Fpr26; + DOUBLE Fpr27; + DOUBLE Fpr28; + DOUBLE Fpr29; + DOUBLE Fpr30; DOUBLE Fpr31; } KEXCEPTION_FRAME, *PKEXCEPTION_FRAME; +FORCEINLINE +struct _KPRCB * +KeGetCurrentPrcb(VOID) +{ + return (struct _KPRCB *)(ULONG_PTR)__readfsdword(FIELD_OFFSET(KIPCR, PrcbData)); +} + #endif diff --git a/reactos/include/ndk/powerpc/mmtypes.h b/reactos/include/ndk/powerpc/mmtypes.h index c3eb927be71..2dde39f5c27 100644 --- a/reactos/include/ndk/powerpc/mmtypes.h +++ b/reactos/include/ndk/powerpc/mmtypes.h @@ -29,4 +29,35 @@ Author: #define PAGE_SIZE 0x1000 #define PAGE_SHIFT 12L +typedef unsigned long long MMPTE_HARDWARE; +typedef unsigned long long MMPTE_SOFTWARE; +typedef unsigned long long MMPTE_PROTOTYPE; +typedef unsigned long long MMPTE_SUBSECTION; +typedef unsigned long long MMPTE_TRANSITION; +typedef unsigned long long MMPTE_LIST; + +// +// Page Table Entry Definition +// +typedef struct _HARDWARE_PTE_PPC +{ + ULONG Dirty:2; + ULONG Valid:1; + ULONG GuardedStorage:1; + ULONG MemoryCoherence:1; + ULONG CacheDisable:1; + ULONG WriteThrough:1; + ULONG Change:1; + ULONG Reference:1; + ULONG Write:1; + ULONG CopyOnWrite:1; + ULONG rsvd1:1; + ULONG PageFrameNumber:20; +} HARDWARE_PTE_PPC, *PHARDWARE_PTE_PPC; + +#ifndef HARDWARE_PTE +#define HARDWARE_PTE HARDWARE_PTE_PPC +#define PHARDWARE_PTE PHARDWARE_PTE_PPC +#endif + #endif/*_POWERPC_MMTYPES_H*/ diff --git a/reactos/include/psdk/intrin_ppc.h b/reactos/include/psdk/intrin_ppc.h new file mode 100644 index 00000000000..6dd40182e6e --- /dev/null +++ b/reactos/include/psdk/intrin_ppc.h @@ -0,0 +1,969 @@ +/* + Compatibility header for GCC -- GCC equivalents of intrinsic + Microsoft Visual C++ functions. Originally developed for the ReactOS + () and TinyKrnl () + projects. + + Copyright (c) 2006 KJK::Hyperion + + 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 + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ + +#ifndef KJK_INTRIN_PPC_H_ +#define KJK_INTRIN_PPC_H_ + +#ifndef __GNUC__ +#error Unsupported compiler +#endif + +/*** Stack frame juggling ***/ +#define _ReturnAddress() (__builtin_return_address(0)) +#define _AddressOfReturnAddress() (&(((void **)(__builtin_frame_address(0)))[1])) +/* TODO: __getcallerseflags but how??? */ + + +/*** Atomic operations ***/ +/* TODO: _ReadBarrier */ +/* TODO: _WriteBarrier */ + +#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 +#define _ReadWriteBarrier() __sync_synchronize() +#else +/* TODO: _ReadWriteBarrier() */ +#endif + +#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100 + +static __inline__ __attribute__((always_inline)) char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand) +{ + return __sync_val_compare_and_swap(Destination, Comperand, Exchange); +} + +static __inline__ __attribute__((always_inline)) short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand) +{ + return __sync_val_compare_and_swap(Destination, Comperand, Exchange); +} + +static __inline__ __attribute__((always_inline)) long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand) +{ + return __sync_val_compare_and_swap(Destination, Comperand, Exchange); +} + +static __inline__ __attribute__((always_inline)) long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand) +{ + return __sync_val_compare_and_swap(Destination, Comperand, Exchange); +} + +static __inline__ __attribute__((always_inline)) void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand) +{ + return __sync_val_compare_and_swap(Destination, Comperand, Exchange); +} + +static __inline__ __attribute__((always_inline)) long _InterlockedExchange(volatile long * const Target, const long Value) +{ + /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */ + __sync_synchronize(); + return __sync_lock_test_and_set(Target, Value); +} + +static __inline__ __attribute__((always_inline)) void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value) +{ + /* NOTE: ditto */ + __sync_synchronize(); + return __sync_lock_test_and_set(Target, Value); +} + +static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd(volatile long * const Addend, const long Value) +{ + return __sync_fetch_and_add(Addend, Value); +} + +static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask) +{ + return __sync_fetch_and_and(value, mask); +} + +static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask) +{ + return __sync_fetch_and_and(value, mask); +} + +static __inline__ __attribute__((always_inline)) long _InterlockedAnd(volatile long * const value, const long mask) +{ + return __sync_fetch_and_and(value, mask); +} + +static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask) +{ + return __sync_fetch_and_or(value, mask); +} + +static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask) +{ + return __sync_fetch_and_or(value, mask); +} + +static __inline__ __attribute__((always_inline)) long _InterlockedOr(volatile long * const value, const long mask) +{ + return __sync_fetch_and_or(value, mask); +} + +static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask) +{ + return __sync_fetch_and_xor(value, mask); +} + +static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask) +{ + return __sync_fetch_and_xor(value, mask); +} + +static __inline__ __attribute__((always_inline)) long _InterlockedXor(volatile long * const value, const long mask) +{ + return __sync_fetch_and_xor(value, mask); +} + +#else + +static __inline__ __attribute__((always_inline)) char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand) +{ + char retval = Comperand; + __asm__ __volatile__ ( + "sync\n" + "1: lbarx %0,0,%1\n" + " subf. %0,%2,%0\n" + " bne 2f\n" + " stbcx. %3,0,%1\n" + " bne- 1b\n" + "2: isync" + : "=b" (retval) + : "b" (Destination), "r" (Comperand), "r" (Exchange) + : "cr0", "memory"); + return retval; +} + +static __inline__ __attribute__((always_inline)) short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand) +{ + short retval = Comperand; + __asm__ __volatile__ ( + "sync\n" + "1: lharx %0,0,%1\n" + " subf. %0,%2,%0\n" + " bne 2f\n" + " sthcx. %3,0,%1\n" + " bne- 1b\n" + "2: isync" + : "=b" (retval) + : "b" (Destination), "r" (Comperand), "r" (Exchange) + : "cr0", "memory"); + return retval; +} + +static __inline__ __attribute__((always_inline)) long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand) +{ + unsigned long lo32Retval = (unsigned long)((Comperand >> 0) & 0xFFFFFFFF); + long hi32Retval = (unsigned long)((Comperand >> 32) & 0xFFFFFFFF); + + unsigned long lo32Exchange = (unsigned long)((Exchange >> 0) & 0xFFFFFFFF); + long hi32Exchange = (unsigned long)((Exchange >> 32) & 0xFFFFFFFF); + +#if 0 + __asm__ + ( + "cmpxchg8b %[Destination]" : + "a" (lo32Retval), "d" (hi32Retval) : + [Destination] "rm" (Destination), "b" (lo32Exchange), "c" (hi32Exchange) : + "memory" + ); +#endif + { + union u_ + { + long long ll; + struct s_ + { + unsigned long lo32; + long hi32; + } + s; + } + u = { s : { lo32 : lo32Retval, hi32 : hi32Retval } }; + + return u.ll; + } +} + +static __inline__ __attribute__((always_inline)) void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand) +{ + return (void *)_InterlockedCompareExchange + ((long *)Destination, (long) Exchange, (long) Comperand); +} + +static __inline__ __attribute__((always_inline)) long _InterlockedExchange(volatile long * const Target, const long Value) +{ + long retval; + __asm__ __volatile__ ( + "sync\n" + "1: lwarx %0,0,%1\n" + " stwcx. %2,0,%1\n" + " bne- 1b\n" + : "=b" (retval) + : "b" (Target), "b" (Value) + : "cr0", "memory"); + return retval; +} + +static __inline__ __attribute__((always_inline)) void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value) +{ + void * retval; + __asm__ __volatile__ ( + "sync\n" + "1: lwarx %0,0,%1\n" + " stwcx. %2,0,%1\n" + " bne- 1b\n" + : "=b" (retval) + : "b" (Target), "b" (Value) + : "cr0", "memory"); + return retval; +} + +static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd(volatile long * const Addend, const long Value) +{ + long x; + long y = *Addend; + long addend = y; + + do + { + x = y; + y = _InterlockedCompareExchange(Addend, addend + Value, x); + } + while(y != x); + + return y; +} + +static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask) +{ + char x; + char y; + + y = *value; + + do + { + x = y; + y = _InterlockedCompareExchange8(value, x & mask, x); + } + while(y != x); + + return y; +} + +static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask) +{ + short x; + short y; + + y = *value; + + do + { + x = y; + y = _InterlockedCompareExchange16(value, x & mask, x); + } + while(y != x); + + return y; +} + +static __inline__ __attribute__((always_inline)) long _InterlockedAnd(volatile long * const value, const long mask) +{ + long x; + long y; + + y = *value; + + do + { + x = y; + y = _InterlockedCompareExchange(value, x & mask, x); + } + while(y != x); + + return y; +} + +static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask) +{ + char x; + char y; + + y = *value; + + do + { + x = y; + y = _InterlockedCompareExchange8(value, x | mask, x); + } + while(y != x); + + return y; +} + +static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask) +{ + short x; + short y; + + y = *value; + + do + { + x = y; + y = _InterlockedCompareExchange16(value, x | mask, x); + } + while(y != x); + + return y; +} + +static __inline__ __attribute__((always_inline)) long _InterlockedOr(volatile long * const value, const long mask) +{ + long x; + long y; + + y = *value; + + do + { + x = y; + y = _InterlockedCompareExchange(value, x | mask, x); + } + while(y != x); + + return y; +} + +static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask) +{ + char x; + char y; + + y = *value; + + do + { + x = y; + y = _InterlockedCompareExchange8(value, x ^ mask, x); + } + while(y != x); + + return y; +} + +static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask) +{ + short x; + short y; + + y = *value; + + do + { + x = y; + y = _InterlockedCompareExchange16(value, x ^ mask, x); + } + while(y != x); + + return y; +} + +static __inline__ __attribute__((always_inline)) long _InterlockedXor(volatile long * const value, const long mask) +{ + long x; + long y; + + y = *value; + + do + { + x = y; + y = _InterlockedCompareExchange(value, x ^ mask, x); + } + while(y != x); + + return y; +} + +static __inline__ __attribute__((always_inline)) unsigned char _interlockedbittestandreset(volatile long * const a, const long b) +{ + long x; + long y; + long mask = ~(1<>= check; + *Index += check; + } + check >>= 1; + } + return 1; + } +} + +/* NOTE: again, the bizarre implementation follows Visual C++ */ +static __inline__ __attribute__((always_inline)) unsigned char _bittest(const long * const a, const long b) +{ + return ((*a) & (1<> (8-shift)); +} + +static __inline__ __attribute__((always_inline)) unsigned short _rotl16(const unsigned short value, const unsigned char shift) +{ + return (value << shift) | (value >> (16-shift)); +} + +static __inline__ __attribute__((always_inline)) unsigned char _rotr8(const unsigned char value, const unsigned char shift) +{ + return (value >> shift) | (value << (8-shift)); +} + +static __inline__ __attribute__((always_inline)) unsigned short _rotr16(const unsigned short value, const unsigned char shift) +{ + return (value >> shift) | (value << (16-shift)); +} + +static __inline__ __attribute__((always_inline)) unsigned long long __ll_lshift(const unsigned long long Mask, int Bit) +{ + return Mask << Bit; +} + +static __inline__ __attribute__((always_inline)) long long __ll_rshift(const long long Mask, const int Bit) +{ + return Mask >> Bit; +} + +static __inline__ __attribute__((always_inline)) unsigned long long __ull_rshift(const unsigned long long Mask, int Bit) +{ + return Mask >> Bit; +} + + +/*** 64-bit math ***/ +static __inline__ __attribute__((always_inline)) long long __emul(const int a, const int b) +{ + return a * b; +} + +static __inline__ __attribute__((always_inline)) unsigned long long __emulu(const unsigned int a, const unsigned int b) +{ + return a * b; +} + + +/*** Port I/O ***/ +static __inline__ __attribute__((always_inline)) unsigned char __inbyte(const unsigned short Port) +{ + int ret; + __asm__( + "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 %0,0(%1)\n\t" /* Get actual value at phys addr r3 */ + "mtmsr 5\n\t" : "=r" (ret) : "b" (Port) + ); + return ret; +} + +static __inline__ __attribute__((always_inline)) unsigned short __inword(const unsigned short Port) +{ + int ret; + __asm__( + "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 %0,0(%1)\n\t" /* Get actual value at phys addr r3 */ + "mtmsr 5\n\t" : "=r" (ret) : "b" (Port) + ); + return ret; +} + +static __inline__ __attribute__((always_inline)) unsigned long __indword(const unsigned short Port) +{ + int ret; + __asm__( + "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 %0,0(%1)\n\t" /* Get actual value at phys addr r3 */ + "mtmsr 5\n\t" : "=r" (ret) : "b" (Port) + ); + return ret; +} + +static __inline__ __attribute__((always_inline)) void __inbytestring(unsigned short Port, unsigned char * Buffer, unsigned long Count) +{ + while(Count--) { + *Buffer++ = __inbyte(Port); + } +} + +static __inline__ __attribute__((always_inline)) void __inwordstring(unsigned short Port, unsigned short * Buffer, unsigned long Count) +{ + while(Count--) { + *Buffer++ = __inword(Port); + } +} + +static __inline__ __attribute__((always_inline)) void __indwordstring(unsigned short Port, unsigned long * Buffer, unsigned long Count) +{ + while(Count--) { + *Buffer++ = __indword(Port); + } +} + +static __inline__ __attribute__((always_inline)) void __outbyte(unsigned short const Port, const unsigned char Data) +{ + __asm__( + "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 %1,0(%0)\n\t" /* Set actual value at phys addr r3 */ + "dcbst 0,%1\n\t" + "mtmsr 5\n\t" + "sync\n\t" + "eieio\n\t" : : "b" (Port), "r" (Data) + ); +} + +static __inline__ __attribute__((always_inline)) void __outword(unsigned short const Port, const unsigned short Data) +{ + __asm__( + "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 %1,0(%0)\n\t" /* Set actual value at phys addr r3 */ + "dcbst 0,%1\n\t" + "mtmsr 5\n\t" + "sync\n\t" + "eieio\n\t" : : "b" (Port), "b" (Data) + ); +} + +static __inline__ __attribute__((always_inline)) void __outdword(unsigned short const Port, const unsigned long Data) +{ + __asm__( + "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 %1,0(%0)\n\t" /* Set actual value at phys addr r3 */ + "dcbst 0,%1\n\t" + "mtmsr 5\n\t" + "sync\n\t" + "eieio\n\t" : : "b" (Port), "b" (Data) + ); +} + +static __inline__ __attribute__((always_inline)) void __outbytestring(unsigned short const Port, const unsigned char * const Buffer, const unsigned long Count) +{ + unsigned long count = Count; + const unsigned char *buffer = Buffer; + while(count--) { + __outbyte(Port, *buffer++); + } +} + +static __inline__ __attribute__((always_inline)) void __outwordstring(unsigned short const Port, const unsigned short * const Buffer, const unsigned long Count) +{ + unsigned long count = Count; + const unsigned short *buffer = Buffer; + while(count--) { + __outword(Port, *buffer++); + } +} + +static __inline__ __attribute__((always_inline)) void __outdwordstring(unsigned short const Port, const unsigned long * const Buffer, const unsigned long Count) +{ + unsigned long count = Count; + const unsigned long *buffer = Buffer; + while(count--) { + __outdword(Port, *buffer++); + } +} + + +/*** System information ***/ +static __inline__ __attribute__((always_inline)) void __cpuid(int CPUInfo[], const int InfoType) +{ + unsigned long lo32; + __asm__("mfpvr" : "=b" (lo32)); +} + +static __inline__ __attribute__((always_inline)) unsigned long long __rdtsc(void) +{ + unsigned long lo32; + __asm__("mfdec %0" : "=b" (lo32)); + return -lo32; +} + + +/*** Interrupts ***/ +/* Finally decided to do this by enabling single step trap */ +static __inline__ __attribute__((always_inline)) void __debugbreak(void) +{ + +} + +static __inline__ __attribute__((always_inline)) void __int2c(void) +{ + /* Not sure yet */ +} + +#ifndef _ENABLE_DISABLE_DEFINED +#define _ENABLE_DISABLE_DEFINED +static __inline__ __attribute__((always_inline)) void _disable(void) +{ + __asm__ __volatile__("mfmsr 0\n\t" \ + "li 8,0x7fff\n\t" \ + "and 0,8,0\n\t" \ + "mtmsr 0\n\t"); +} + +static __inline__ __attribute__((always_inline)) void _enable(void) +{ + __asm__ __volatile__("mfmsr 0\n\t" \ + "lis 8,0x8000@ha\n\t" \ + "or 0,8,0\n\t" \ + "mtmsr 0\n\t"); +} + +/*** Protected memory management ***/ +static __inline__ __attribute__((always_inline)) unsigned long __readsdr1(void) +{ + unsigned long value; + __asm__("mfsdr1 %0" : "=b" (value)); + return value; +} + +static __inline__ __attribute__((always_inline)) void __writesdr1(const unsigned long long Data) +{ + __asm__("mtsdr1 %0" : : "b" (Data)); +} + +/*** System operations ***/ +/* This likely has a different meaning from the X86 equivalent. We'll keep + * the name cause it fits */ +static __inline__ __attribute__((always_inline)) unsigned long long __readmsr() +{ + unsigned long temp; + __asm__("mfmsr %0" : "=b" (temp)); + return temp; +} + +static __inline__ __attribute__((always_inline)) void __writemsr(const unsigned long Value) +{ + __asm__("mtmsr %0" : : "b" (Value)); +} + +/* We'll make sure of the following: + * IO operations have completed + * Write operations through cache have completed + * We've reloaded anything in the data or instruction cache that might have + * changed in real ram. + */ +static __inline__ __attribute__((always_inline)) void __wbinvd(void) +{ + __asm__("eieio\n\t" + "dcs\n\t" + "sync\n\t" + "isync\n\t"); +} +#endif + +static __inline__ __attribute__((always_inline)) long _InterlockedAddLargeStatistic(volatile long long * const Addend, const long Value) +{ +#if 0 + __asm__ + ( + "lock; add %[Value], %[Lo32];" + "jae LABEL%=;" + "lock; adc $0, %[Hi32];" + "LABEL%=:;" : + [Lo32] "=m" (*((volatile long *)(Addend) + 0)), [Hi32] "=m" (*((volatile long *)(Addend) + 1)) : + [Value] "ir" (Value) + ); +#endif + return Value; +} + +/*** Miscellaneous ***/ +/* BUGBUG: only good for use in macros. Cannot be taken the address of */ +#define __noop(...) ((void)0) + +/* TODO: __assume. GCC only supports the weaker __builtin_expect */ + +#endif +/* EOF */ diff --git a/reactos/include/psdk/rpc.h b/reactos/include/psdk/rpc.h index 58f1983fafb..ca4f8a45092 100644 --- a/reactos/include/psdk/rpc.h +++ b/reactos/include/psdk/rpc.h @@ -22,7 +22,7 @@ extern "C" { #endif -#if defined( MAC ) || defined( _MAC ) || defined(__powerpc__) +#if defined( MAC ) || defined( _MAC ) || defined(__powerpc__) && !defined(_REACTOS_) #define __RPC_MAC__ #define __RPC_WIN32__ #include diff --git a/reactos/include/psdk/winnt.h b/reactos/include/psdk/winnt.h index af8a03249f1..62e4a1bc440 100644 --- a/reactos/include/psdk/winnt.h +++ b/reactos/include/psdk/winnt.h @@ -4039,6 +4039,7 @@ typedef struct _OBJECT_TYPE_LIST { #if defined(__GNUC__) +#ifdef _M_IX86 static __inline__ PVOID GetCurrentFiber(void) { void* ret; @@ -4048,9 +4049,27 @@ static __inline__ PVOID GetCurrentFiber(void) ); return ret; } +#else +static __inline__ __attribute__((always_inline)) unsigned long __readfsdword_winnt(const unsigned long Offset) +{ + unsigned long result; + __asm__("\tadd 7,13,%1\n" + "\tlwz %0,0(7)\n" + : "=r" (result) + : "r" (Offset) + : "r7"); + return result; +} + +static __inline__ PVOID GetCurrentFiber(void) +{ + return __readfsdword_winnt(0x10); +} +#endif /* FIXME: Oh how I wish, I wish the w32api DDK wouldn't include winnt.h... */ #ifndef __NTDDK_H +#ifdef _M_IX86 static __inline__ struct _TEB * NtCurrentTeb(void) { struct _TEB *ret; @@ -4063,6 +4082,12 @@ static __inline__ struct _TEB * NtCurrentTeb(void) return ret; } +#else +static __inline__ struct _TEB * NtCurrentTeb(void) +{ + return __readfsdword_winnt(0x18); +} +#endif #endif #elif defined(__WATCOMC__) @@ -4124,12 +4149,36 @@ InterlockedBitTestAndSet(IN LONG volatile *Base, { LONG OldBit; +#ifdef _M_IX86 __asm__ __volatile__("lock " "btsl %2,%1\n\t" "sbbl %0,%0\n\t" :"=r" (OldBit),"=m" (*Base) :"Ir" (Bit) : "memory"); +#elif defined(_M_PPC) + LONG scratch = 0; + + Bit = 1 << Bit; + /* %0 - OldBit + * %1 - Bit + * %2 - scratch + * %3 - Base + */ + __asm__ __volatile__( + "sync\n" + "0:\n\t" + "lwarx %2,0,%3\n\t" + "mr %0,%2\n\t" + "or %2,%1,%2\n\t" + "stwcx. %2,0,%3\n\t" + "bne- 0b\n\t" : + "=r" (OldBit) : + "r" (Bit), + "r" (scratch), + "r" (Base) + ); +#endif return OldBit; } @@ -4139,12 +4188,36 @@ InterlockedBitTestAndReset(IN LONG volatile *Base, { LONG OldBit; +#ifdef _M_IX86 __asm__ __volatile__("lock " "btrl %2,%1\n\t" "sbbl %0,%0\n\t" :"=r" (OldBit),"=m" (*Base) :"Ir" (Bit) : "memory"); +#elif defined(_M_PPC) + LONG scratch = 0; + + Bit = ~(1 << Bit); + /* %0 - OldBit + * %1 - Bit + * %2 - scratch + * %3 - Base + */ + __asm__ __volatile__( + "sync\n" + "0:\n\t" + "lwarx %2,0,%3\n\t" + "mr %0,%2\n\t" + "and %2,%1,%2\n\t" + "stwcx. %2,0,%3\n\t" + "bne- 0b\n\t" : + "=r" (OldBit) : + "r" (Bit), + "r" (scratch), + "r" (Base) + ); +#endif return OldBit; } @@ -4153,17 +4226,32 @@ BitScanReverse(OUT ULONG *Index, IN ULONG Mask) { BOOLEAN BitPosition = 0; +#ifdef _M_IX86 __asm__ __volatile__("bsrl %2,%0\n\t" "setnz %1\n\t" :"=&r" (*Index), "=r" (BitPosition) :"rm" (Mask) :"memory"); return BitPosition; +#elif defined(_M_PPC) + /* Slow implementation for now */ + for( *Index = 31; *Index; *Index-- ) { + if( (1<<*Index) & Mask ) { + return TRUE; + } + } + + return FALSE; +#endif } #endif +#ifdef _M_IX86 #define YieldProcessor() __asm__ __volatile__("pause"); +#elif defined(_M_PPC) +#define YieldProcessor() __asm__ __volatile__("nop"); +#endif #if defined(_AMD64_) #if defined(_M_AMD64) diff --git a/reactos/include/reactos/arc/arc.h b/reactos/include/reactos/arc/arc.h index 57e2ae05031..43ccdc0e042 100644 --- a/reactos/include/reactos/arc/arc.h +++ b/reactos/include/reactos/arc/arc.h @@ -339,6 +339,11 @@ typedef struct _I386_LOADER_BLOCK ULONG VirtualBias; } I386_LOADER_BLOCK, *PI386_LOADER_BLOCK; +typedef struct _PPC_LOADER_BLOCK +{ + PVOID BootInfo; +} PPC_LOADER_BLOCK, *PPPC_LOADER_BLOCK; + // // Loader Parameter Block // @@ -369,6 +374,7 @@ typedef struct _LOADER_PARAMETER_BLOCK I386_LOADER_BLOCK I386; ALPHA_LOADER_BLOCK Alpha; IA64_LOADER_BLOCK Ia64; + PPC_LOADER_BLOCK PowerPC; } u; } LOADER_PARAMETER_BLOCK, *PLOADER_PARAMETER_BLOCK; diff --git a/reactos/include/reactos/debug.h b/reactos/include/reactos/debug.h index 648d77cd788..637527b6420 100644 --- a/reactos/include/reactos/debug.h +++ b/reactos/include/reactos/debug.h @@ -126,6 +126,8 @@ RtlAssert( #define ASM_BREAKPOINT "\nbreak\n" #elif defined(__x86_64__) #define ASM_BREAKPOINT "\nint $3\n" +#elif defined(_M_PPC) +#define ASM_BREAKPOINT "\ntwi 1\n" #else #error Unsupported architecture. #endif diff --git a/reactos/include/reactos/elf/elf-powerpc.h b/reactos/include/reactos/elf/elf-powerpc.h new file mode 100644 index 00000000000..6365df86fdf --- /dev/null +++ b/reactos/include/reactos/elf/elf-powerpc.h @@ -0,0 +1,158 @@ +/*- + * Copyright (c) 1996-1997 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $ + */ + +#ifndef _MACHINE_ELF_H_ +#define _MACHINE_ELF_H_ 1 + +/* + * ELF definitions for the powerpc architecture. + */ + +#ifdef _REACTOS_ELF_MACHINE_IS_TARGET + +#ifndef __ELF_WORD_SIZE +#define __ELF_WORD_SIZE 32 /* Used by */ +#endif + +#include + +#define ELF_ARCH EM_386 + +#define ELF_MACHINE_OK(x) ((x) == EM_386 || (x) == EM_486) + +/* + * Auxiliary vector entries for passing information to the interpreter. + * + * The powerpc supplement to the SVR4 ABI specification names this "auxv_t", + * but POSIX lays claim to all symbols ending with "_t". + */ + +typedef struct { /* Auxiliary vector entry on initial stack */ + int a_type; /* Entry type. */ + union { + long a_val; /* Integer value. */ + void *a_ptr; /* Address. */ + void (*a_fcn)(void); /* Function pointer (not used). */ + } a_un; +} Elf32_Auxinfo; + +#if __ELF_WORD_SIZE == 64 +/* Fake for amd64 loader support */ +typedef struct { + int fake; +} Elf64_Auxinfo; +#endif + +__ElfType(Auxinfo); + +/* Values for a_type. */ +#define AT_NULL 0 /* Terminates the vector. */ +#define AT_IGNORE 1 /* Ignored entry. */ +#define AT_EXECFD 2 /* File descriptor of program to load. */ +#define AT_PHDR 3 /* Program header of program already loaded. */ +#define AT_PHENT 4 /* Size of each program header entry. */ +#define AT_PHNUM 5 /* Number of program header entries. */ +#define AT_PAGESZ 6 /* Page size in bytes. */ +#define AT_BASE 7 /* Interpreter's base address. */ +#define AT_FLAGS 8 /* Flags (unused for powerpc). */ +#define AT_ENTRY 9 /* Where interpreter should transfer control. */ + +/* + * The following non-standard values are used for passing information + * from John Polstra's testbed program to the dynamic linker. These + * are expected to go away soon. + * + * Unfortunately, these overlap the Linux non-standard values, so they + * must not be used in the same context. + */ +#define AT_BRK 10 /* Starting point for sbrk and brk. */ +#define AT_DEBUG 11 /* Debugging level. */ + +/* + * The following non-standard values are used in Linux ELF binaries. + */ +#define AT_NOTELF 10 /* Program is not ELF ?? */ +#define AT_UID 11 /* Real uid. */ +#define AT_EUID 12 /* Effective uid. */ +#define AT_GID 13 /* Real gid. */ +#define AT_EGID 14 /* Effective gid. */ + +#define AT_COUNT 15 /* Count of defined aux entry types. */ + +/* Define "machine" characteristics */ +#define ELF_TARG_CLASS ELFCLASS32 +#define ELF_TARG_DATA ELFDATA2LSB +#define ELF_TARG_MACH EM_386 +#define ELF_TARG_VER 1 + +#endif /* _REACTOS_ELF_MACHINE_IS_TARGET */ + +/* + * Relocation types. + */ + +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 +#define R_PPC_COUNT 37 + +#endif /* !_MACHINE_ELF_H_ */ diff --git a/reactos/include/reactos/elf/machine.h b/reactos/include/reactos/elf/machine.h index 27d7e494ebd..a570b1c4adf 100644 --- a/reactos/include/reactos/elf/machine.h +++ b/reactos/include/reactos/elf/machine.h @@ -5,6 +5,10 @@ #define _REACTOS_ELF_MACHINE_IS_TARGET #include #undef _REACTOS_ELF_MACHINE_IS_TARGET +#elif defined(_M_PPC) +#define _REACTOS_ELF_MACHINE_IS_TARGET +#include +#undef _REACTOS_ELF_MACHINE_IS_TARGET #else #error Unsupported target architecture #endif diff --git a/reactos/include/reactos/elf/reactos.h b/reactos/include/reactos/elf/reactos.h new file mode 100644 index 00000000000..00743db9fa1 --- /dev/null +++ b/reactos/include/reactos/elf/reactos.h @@ -0,0 +1,7 @@ +#ifndef _SYS_ELF_REACTOS_H_ +#define _SYS_ELF_REACTOS_H_ 1 + +#define TYPE_PEHEADER (SHT_LOOS+1) +#define ADDR24_MASK 0x03fffffc + +#endif/*_SYS_ELF_REACTOS_H_*/ diff --git a/reactos/include/reactos/libs/ppcmmu/mmu.h b/reactos/include/reactos/libs/ppcmmu/mmu.h new file mode 100644 index 00000000000..00e32d5ee0d --- /dev/null +++ b/reactos/include/reactos/libs/ppcmmu/mmu.h @@ -0,0 +1,228 @@ +#ifndef PPCMMU_H +#define PPCMMU_H + +/* PPC MMU object -- + * Always called from kernel mode, maps the first 16 megabytes and uses 16 + * bytes per page between 0x30000 and 16 megs. Maximum memory size is 3 gig. + * + * Physical Memory Map: + * 0x00300 -- Data Miss + * 0x00400 -- Code Miss + * 0x10000 -- MMU ucode + * 0x20000 -- PTEG + * 0x30000 -- Full map + * + * Actions: + * 00 -- Initialize + * -- No arguments + * 01 -- Map page + * r4 -- virtual address + * r5 -- ppc_map_info_t + * 02 -- Erase page + * r4 -- virtual address + * 03 -- Set segment VSID + * r4 -- Start seg + * r5 -- End seg + * r6 -- Vsid + * 04 -- Set page miss callback + * r4 -- Callback address (VA) + * 05 -- Query page + * r4 -- Page addr + * r5 -- Address of info struct + * 06 -- Unit Test + * 07 -- Turn on paging + * 08 -- Unmap process + */ + +#define MMUCODE 0x10000 +#define HTABORG 0x20000 +#define HTABSIZ 0x10000 +#define PAGETAB 0x30000 + +#define PpcHashedPTE ((ppc_pteg_t*)(HTABORG)) +#define PpcPageTable ((ppc_map_t*)(PAGETAB)) + +#define PPC_PAGE_ADDR(x) ((x) << 12) +#define PPC_PAGE_NUMBER(x) ((x) >> 12) +#define PPC_VSID_MASK 0xffffff +#define PPC_PAGE_MASK 0xfff + +#define MMU_NONE 0 +#define MMU_KR 8 +#define MMU_KW 4 +#define MMU_UR 2 +#define MMU_UW 1 +#define MMU_ALL_R 10 +#define MMU_KRW 12 +#define MMU_KRW_UR 14 +#define MMU_ALL_RW 15 + +#define MMU_PAGE_ACCESS 0x40000000 +#define MMU_PAGE_DIRTY 0x80000000 + +#define MMU_KMASK 12 +#define MMU_UMASK 3 + +extern char _binary_mmucode_start[], _binary_mmucode_end[]; + +/* thanks geist */ +typedef unsigned long paddr_t; +typedef unsigned long vaddr_t; + +typedef struct _ppc_pte_t { + unsigned long pteh, ptel; +} ppc_pte_t; + +typedef struct _ppc_pteg_t { + ppc_pte_t block[8]; +} ppc_pteg_t; + +typedef struct _ppc_map_t { + ppc_pte_t pte; + unsigned long proc; + vaddr_t addr; +} ppc_map_t; + +typedef struct _ppc_map_info_t { + unsigned long flags, proc; + vaddr_t addr; + paddr_t phys; +} ppc_map_info_t; + +typedef struct _ppc_trap_frame_t { + unsigned long gpr[32]; + unsigned long lr, cr, ctr, srr0, srr1, dsisr, dar, xer; +} ppc_trap_frame_t; + +typedef int (*MmuPageCallback)(int inst, ppc_trap_frame_t *trap); + +#include "mmuutil.h" + +static inline int PPCMMU(int action, void *arg1, void *arg2, void *arg3) +{ + /* Set Bat0 to mmu object address */ + int i, batu, batl, oldbat[8], usebat[2] = { 0, 1 }, gotbat = 0, pc, mask; + volatile int ret; + int (*mmumain)(int action, void *arg1, void *arg2, void *arg3) = (void *)MMUCODE; + __asm__("bl 1f\n\t" + "\n1:\n\t" + "mflr %0\n\t" : "=r" (pc)); + + for(i = 0, gotbat = 0; i < 4 && gotbat < 2; i++) + { + GetBat(i, 1, &batu, &batl); + if(batu & 0xffc) + { + mask = ~(0x1ffff | ((batu & 0xffc)>>2)<<17); + if(!(batu & 2) || ((batu & mask) != (pc & mask))) + usebat[gotbat++] = i; + } else { + mask = ~(0x1ffff | (batl << 17)); + if(!(batl & 0x40) || ((batu & mask) != (pc & mask))) + usebat[gotbat++] = i; + } + } + + GetBat(usebat[0], 0, &oldbat[0], &oldbat[1]); + GetBat(usebat[0], 1, &oldbat[2], &oldbat[3]); + GetBat(usebat[1], 0, &oldbat[4], &oldbat[5]); + GetBat(usebat[1], 1, &oldbat[6], &oldbat[7]); + + batu = 0xff; + batl = 0x7f; + SetBat(usebat[0], 0, batu, batl); + SetBat(usebat[0], 1, batu, batl); + batu += 8192 * 1024; + batl += 8192 * 1024; + SetBat(usebat[1], 0, batu, batl); + SetBat(usebat[1], 1, batu, batl); + + ret = mmumain(action, arg1, arg2, arg3); + + /* Ok done ... Whatever happened probably worked */ + SetBat(usebat[0], 0, oldbat[0], oldbat[1]); + SetBat(usebat[0], 1, oldbat[2], oldbat[3]); + SetBat(usebat[1], 0, oldbat[4], oldbat[5]); + SetBat(usebat[1], 1, oldbat[6], oldbat[7]); + + return ret; +} + +/* Expand this only if used ... That makes dependence on libmmu_code.a depend + * on whether MmuInit is called in a clean way. + */ +#define MmuInit() _MmuInit(&_binary_mmucode_start, &_binary_mmucode_end) + +/* Copy in the mmu code and call init + * This bootstrap should only be called the first time (i.e. in the bootloader + * or the early boot code). Part of the purpose of this library is to + * eliminate the need to do a complex mmu handoff between boot stages. + */ +static inline void _MmuInit(void *_start, void *_end) +{ + int target = MMUCODE; + int *start = (int *)_start; + while(start < (int *)_end) + { + SetPhys(target, *start++); + target += sizeof(int); + } + PPCMMU(0, 0, 0, 0); +} + +static inline void MmuMapPage(ppc_map_info_t *info, int count) +{ + PPCMMU(1, info, (void *)count, 0); +} + +static inline void MmuUnmapPage(ppc_map_info_t *info, int count) +{ + PPCMMU(2, info, (void *)count, 0); +} + +static inline void MmuSetVsid(int start, int end, int vsid) +{ + PPCMMU(3, (void *)start, (void *)end, (void *)vsid); +} + +static inline MmuPageCallback MmuSetPageCallback(MmuPageCallback cb) +{ + return (MmuPageCallback)PPCMMU(4, (void *)cb, 0, 0); +} + +static inline void MmuInqPage(ppc_map_info_t *info, int count) +{ + PPCMMU(5, info, (void *)count, 0); +} + +static inline int MmuUnitTest() +{ + return PPCMMU(6, 0, 0, 0); +} + +static inline int MmuTurnOn(void *fun, void *arg) +{ + return PPCMMU(7, fun, arg, 0); +} + +static inline void MmuSetMemorySize(paddr_t size) +{ + PPCMMU(8, (void *)size, 0, 0); +} + +static inline paddr_t MmuGetFirstPage() +{ + return (paddr_t)PPCMMU(9, 0, 0, 0); +} + +static inline void *MmuAllocVsid(int vsid, int mask) +{ + return (void *)PPCMMU(10, (void *)vsid, (void *)mask, 0); +} + +static inline void MmuRevokeVsid(int vsid, int mask) +{ + PPCMMU(11, (void *)vsid, (void *)mask, 0); +} + +#endif/*PPCMMU_H*/ diff --git a/reactos/include/reactos/libs/ppcmmu/mmuutil.h b/reactos/include/reactos/libs/ppcmmu/mmuutil.h new file mode 100644 index 00000000000..9528b571fc4 --- /dev/null +++ b/reactos/include/reactos/libs/ppcmmu/mmuutil.h @@ -0,0 +1,23 @@ +#ifndef FREELDR_MMU_H +#define FREELDR_MMU_H + +int GetDEC(); +int GetMSR(); +int GetPhys( paddr_t addr ); +int GetPhysHalf( paddr_t addr ); +int GetPhysByte( paddr_t addr ); +void SetPhys( paddr_t addr, int val ); +void SetPhysHalf( paddr_t addr, int val ); +void SetPhysByte( paddr_t addr, int val ); +int GetSR(int n); +void SetSR(int n, int val); +void GetBat( int bat, int inst, int *batHi, int *batLo ); +void SetBat( int bat, int inst, int batHi, int batLo ); +int GetSDR1(); +void SetSDR1( int newsdr ); +int BatHit( int bath, int batl, int virt ); +int BatTranslate( int bath, int batl, int virt ); +/* translate address */ +int PpcVirt2phys( vaddr_t virt, int inst ); +int PtegNumber( vaddr_t virt, int hfun ); +#endif/*FREELDR_MMU_H*/ diff --git a/reactos/include/reactos/ppcboot.h b/reactos/include/reactos/ppcboot.h new file mode 100644 index 00000000000..8dc39c24bf8 --- /dev/null +++ b/reactos/include/reactos/ppcboot.h @@ -0,0 +1,14 @@ +#ifndef REACTOS_PPCBOOT_H +#define REACTOS_PPCBOOT_H + +typedef char font_char[57]; +typedef struct _boot_infos_t { + void *loaderBlock; + int dispDeviceRect[4]; + int dispDeviceRowBytes; + int dispDeviceDepth; + void *dispDeviceBase; + font_char *dispFont; +} boot_infos_t; + +#endif/*REACTOS_PPCBOOT_H*/ diff --git a/reactos/include/reactos/ppcdebug.h b/reactos/include/reactos/ppcdebug.h new file mode 100644 index 00000000000..0b665a3c158 --- /dev/null +++ b/reactos/include/reactos/ppcdebug.h @@ -0,0 +1,20 @@ +#ifndef _PPCDEBUG_H +#define _PPCDEBUG_H + +#include "ppcboot.h" + +extern struct _boot_infos_t *BootInfo; +extern void DrawNumber(struct _boot_infos_t *, unsigned long, int, int); +extern void DrawString(struct _boot_infos_t *, const char *, int, int); +#define TRACEXY(x,y) do { \ + unsigned long _x_ = (unsigned long)(x), _y_ = (unsigned long)(y); \ + __asm__("ori 0,0,0"); \ + DrawNumber(BootInfo, __LINE__, 10, 160); \ + DrawString(BootInfo, __FILE__, 100, 160); \ + DrawNumber(BootInfo, _x_, 400, 160); \ + DrawNumber(BootInfo, _y_, 490, 160); \ +} while(0) +#define TRACEX(x) TRACEXY(x,0) +#define TRACE TRACEX(0) + +#endif//_PPCDEBUG_H diff --git a/reactos/include/reactos/ppcfont.h b/reactos/include/reactos/ppcfont.h new file mode 100644 index 00000000000..4ea53e74862 --- /dev/null +++ b/reactos/include/reactos/ppcfont.h @@ -0,0 +1,259 @@ +#ifndef _ARCH_POWERPC_FONT_H +#define _ARCH_POWERPC_FONT_H + +font_char BootDigits[37] = { + " XXXXX " + "X X " + "X x X " + "X X X " + "X X " + " XXXXX " + " ", + " XX " + " XXX " + " XX " + " XX " + " XX " + " XX " + " ", + " XXXX " + " X X " + " XX " + " XX " + " XX " + " XXXXXX " + " ", + " XXXX " + " X X " + " XX " + " X " + " X X " + " XXXX " + " ", + " X X " + " X X " + " XXXXXX " + " X " + " X " + " X " + " ", + " XXXXXX " + " X " + " XXXXX " + " X " + " X " + " XXXXX " + " ", + " XXXXX " + " X " + " XXXXX " + " X X " + " X X " + " XXXX " + " ", + " XXXXXX " + " XX " + " XX " + " XXXXX " + " XX " + " XX " + " ", + " XXXX " + " X X " + " XXXX " + " X X " + " X X " + " XXXX " + " ", + " XXXX " + " X X " + " X X " + " XXXXX " + " X " + " XXXX " + " ", + " XXXX " + " X X " + " XXXXXX " + " X X " + " X X " + " X X " + " ", + " XXXXX " + " X X " + " XXXXX " + " X X " + " X X " + " XXXXX " + " ", + " XXXX " + " X X " + " X " + " X " + " X X " + " XXXX " + " ", + " XXXXX " + " X X " + " X X " + " X X " + " X X " + " XXXXX " + " ", + " XXXXXX " + " X " + " XXXX " + " X " + " X " + " XXXXXX " + " ", + " XXXXXX " + " X " + " XXXX " + " X " + " X " + " X " + " ", + " XXXX " + " X X " + " X " + " X XX " + " X X " + " XXXXX " + " ", + " X X " + " X X " + " XXXXXX " + " X X " + " X X " + " X X " + " ", + " XXXX " + " XX " + " XX " + " XX " + " XX " + " XXXX " + " ", + " X " + " X " + " X " + " X " + " X X " + " XXXX " + " ", + " X X " + " X X " + " X X " + " XXXX " + " X X " + " X X " + " ", + " X " + " X " + " X " + " X " + " X " + " XXXXXX " + " ", + " X X " + " X XX X " + " X XX X " + " X X " + " X X " + " X X " + " ", + " X X " + " XX X " + " X X X " + " X X X " + " X XX " + " X X " + " ", + " XXXX " + " X X " + " X X " + " X X " + " X X " + " XXXX " + " ", + " XXXXX " + " X X " + " X X " + " XXXXX " + " X " + " X " + " ", + " XXXX " + " X X " + " X X " + " X X X " + " X XXX " + " XXXXX " + " ", + " XXXXX " + " X X " + " X X " + " XXXXX " + " X X " + " X X " + " ", + " XXXXX " + " X " + " XXXX " + " X " + " X " + " XXXXX " + " ", + " XXXXXX " + " XX " + " XX " + " XX " + " XX " + " XX " + " ", + " X X " + " X X " + " X X " + " X X " + " X X " + " XXXX " + " ", + " X X " + " X X " + " X X " + " X X " + " X X " + " XX " + " ", + " X X " + " X X " + " X X " + " X XX X " + " X XX X " + " X X " + " ", + " X X " + " X X " + " XX " + " X X " + " X X " + " X X " + " ", + " X X " + " X X " + " X X " + " XX " + " XX " + " XX " + " ", + " XXXXXX " + " X " + " X " + " X " + " X " + " XXXXXX " + " " +}; + +#endif/*_ARCH_POWERPC_FONT_H*/ diff --git a/reactos/include/reactos/rosldr.h b/reactos/include/reactos/rosldr.h index 65285698ec0..fbbd187edf3 100644 --- a/reactos/include/reactos/rosldr.h +++ b/reactos/include/reactos/rosldr.h @@ -42,6 +42,7 @@ typedef struct _ROS_LOADER_PARAMETER_BLOCK ULONG PageDirectoryStart; ULONG PageDirectoryEnd; ULONG KernelBase; + ULONG ArchExtra; } ROS_LOADER_PARAMETER_BLOCK, *PROS_LOADER_PARAMETER_BLOCK; extern ULONG MmFreeLdrMemHigher, MmFreeLdrMemLower; diff --git a/reactos/lib/rtl/exception.c b/reactos/lib/rtl/exception.c index 62f5a8c64d5..5a110f93541 100644 --- a/reactos/lib/rtl/exception.c +++ b/reactos/lib/rtl/exception.c @@ -137,6 +137,8 @@ RtlWalkFrameChain(OUT PVOID *Callers, #endif #elif defined(_M_MIPS) __asm__("move $sp, %0" : "=r" (Stack) : ); +#elif defined(_M_PPC) + __asm__("mr %0,1" : "=r" (Stack) : ); #else #error Unknown architecture #endif diff --git a/reactos/lib/rtl/powerpc/debug.c b/reactos/lib/rtl/powerpc/debug.c new file mode 100644 index 00000000000..984f33785a7 --- /dev/null +++ b/reactos/lib/rtl/powerpc/debug.c @@ -0,0 +1,42 @@ +#include +#include + +NTKERNELAPI +VOID +DbgBreakPoint() { __asm__("ti 31,0,0"); } + +NTKERNELAPI +VOID +DbgBreakPointWithStatus(ULONG Status) { __asm__("ti 31,0,0"); } + +NTSTATUS +NTAPI +DebugService +(ULONG Service, const void *Buffer, ULONG Length, PVOID Arg1, PVOID Arg2) +{ + NTSTATUS Result; + __asm__("mr 3,%2\n\t" + "mr 4,%3\n\t" + "mr 5,%4\n\t" + "mr 6,%5\n\t" + "mr 7,%6\n\t" + "mr 8,%1\n\t" + "sc\n\t" + "mr %0,3\n\t" : + "=r" (Result) : + "r" (0x10000), + "r" (Service), + "r" (Buffer), + "r" (Length), + "r" (Arg1), + "r" (Arg2) ); + return Result; +} + +NTSTATUS +NTAPI +DebugService2 +(PVOID Arg1, PVOID Arg2, ULONG Service) +{ + return STATUS_SUCCESS; +} diff --git a/reactos/lib/rtl/powerpc/except.c b/reactos/lib/rtl/powerpc/except.c new file mode 100644 index 00000000000..5b6bce3397d --- /dev/null +++ b/reactos/lib/rtl/powerpc/except.c @@ -0,0 +1,62 @@ +/* COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Runtime Library + * PURPOSE: User-Mode Exception Support + * FILE: lib/rtl/exception.c + * PROGRAMERS: Alex Ionescu (alex@relsoft.net) + * David Welch + * Skywing + * KJK::Hyperion + */ + +/* INCLUDES *****************************************************************/ + +#include +#define NDEBUG +#include + +NTSYSAPI +VOID +NTAPI +RtlCaptureContext +(OUT PCONTEXT ContextRecord) +{ + // XXX arty fixme +} + +NTSYSAPI +BOOLEAN +NTAPI +RtlDispatchException +(IN PEXCEPTION_RECORD ExceptionRecord, + IN PCONTEXT Context) +{ + // XXX arty fixme + return TRUE; +} + +NTSYSAPI +PVOID +RtlpGetExceptionAddress() +{ + // XXX arty fixme + return NULL; +} + +VOID +NTAPI +RtlUnwind(IN PVOID TargetFrame OPTIONAL, + IN PVOID TargetIp OPTIONAL, + IN PEXCEPTION_RECORD ExceptionRecord OPTIONAL, + IN PVOID ReturnValue) +{ + // XXX arty fixme +} + +NTSYSAPI +VOID +NTAPI +RtlGetCallersAddress( + OUT PVOID *CallersAddress, + OUT PVOID *CallersCaller) +{ +} diff --git a/reactos/lib/rtl/powerpc/interlocked.c b/reactos/lib/rtl/powerpc/interlocked.c new file mode 100644 index 00000000000..b681b2e3e4d --- /dev/null +++ b/reactos/lib/rtl/powerpc/interlocked.c @@ -0,0 +1,124 @@ +typedef unsigned int size_t; +#include +#include +#include +#include + +NTKERNELAPI +LONG +FASTCALL +InterlockedExchange(LONG volatile *Target, LONG Value) +{ + return _InterlockedExchange(Target, Value); +} + +NTKERNELAPI +LONG +FASTCALL +InterlockedExchangeAdd(LONG volatile *Target, LONG Value) +{ + return _InterlockedExchangeAdd(Target, Value); +} + +NTKERNELAPI +LONG +WINAPI +InterlockedCompareExchange +(LONG volatile *Destination, LONG Exchange, LONG Comparand) +{ + return _InterlockedCompareExchange(Destination, Exchange, Comparand); +} + +NTKERNELAPI +LONG +FASTCALL +InterlockedIncrement +(IN OUT LONG volatile *Addend) +{ + return _InterlockedIncrement(Addend); +} + +NTKERNELAPI +LONG +FASTCALL +InterlockedDecrement +(IN OUT LONG volatile *Addend) +{ + return _InterlockedDecrement(Addend); +} + +PSLIST_ENTRY WINAPI InterlockedPopEntrySList(PSLIST_HEADER ListHead) +{ + PSLIST_ENTRY Result = NULL; + KIRQL OldIrql; + static BOOLEAN GLLInit = FALSE; + static KSPIN_LOCK GlobalListLock; + + if(!GLLInit) + { + KeInitializeSpinLock(&GlobalListLock); + GLLInit = TRUE; + } + + KeAcquireSpinLock(&GlobalListLock, &OldIrql); + if(ListHead->Next.Next) + { + Result = ListHead->Next.Next; + ListHead->Next.Next = Result->Next; + } + KeReleaseSpinLock(&GlobalListLock, OldIrql); + return Result; +} + +NTKERNELAPI +PSLIST_ENTRY +FASTCALL +InterlockedPushEntrySList +(IN PSLIST_HEADER ListHead, + IN PSLIST_ENTRY ListEntry) +{ + PVOID PrevValue; + + do + { + PrevValue = ListHead->Next.Next; + ListEntry->Next = PrevValue; + } + while + (InterlockedCompareExchangePointer + (&ListHead->Next.Next, + ListEntry, + PrevValue) != PrevValue); + + return (PSLIST_ENTRY)PrevValue; +} + +NTKERNELAPI +VOID +FASTCALL +ExInterlockedAddLargeStatistic +(IN PLARGE_INTEGER Addend, + IN ULONG Increment) +{ + _InterlockedAddLargeStatistic(&Addend->QuadPart, Increment); +} + +NTKERNELAPI +LONGLONG +FASTCALL +ExInterlockedCompareExchange64( + IN OUT PLONGLONG Destination, + IN PLONGLONG Exchange, + IN PLONGLONG Comparand, + IN PKSPIN_LOCK Lock) +{ + KIRQL OldIrql; + LONGLONG Result; + + KeAcquireSpinLock(Lock, &OldIrql); + Result = *Destination; + if(*Destination == Result) + *Destination = *Exchange; + KeReleaseSpinLock(Lock, OldIrql); + return Result; +} diff --git a/reactos/lib/rtl/powerpc/thread.c b/reactos/lib/rtl/powerpc/thread.c new file mode 100644 index 00000000000..b7a3204798e --- /dev/null +++ b/reactos/lib/rtl/powerpc/thread.c @@ -0,0 +1,38 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS system libraries + * PURPOSE: Rtl user thread functions + * FILE: lib/rtl/thread.c + * PROGRAMERS: + * Alex Ionescu (alex@relsoft.net) + * Eric Kohl + * KJK::Hyperion + */ + +/* INCLUDES *****************************************************************/ + +#include +#include "i386/ketypes.h" + +#define NDEBUG +#include + +/* PRIVATE FUNCTIONS *******************************************************/ + +/* + * @implemented + */ +VOID +NTAPI +RtlInitializeContext(IN HANDLE ProcessHandle, + OUT PCONTEXT ThreadContext, + IN PVOID ThreadStartParam OPTIONAL, + IN PTHREAD_START_ROUTINE ThreadStartAddress, + IN PINITIAL_TEB InitialTeb) +{ + DPRINT("RtlInitializeContext: (hProcess: %p, ThreadContext: %p, Teb: %p\n", + ProcessHandle, ThreadContext, InitialTeb); + // XXX arty fixme +} + +/* EOF */ diff --git a/reactos/lib/rtl/rtl.rbuild b/reactos/lib/rtl/rtl.rbuild index ce69b56a61d..9ff60fa5762 100644 --- a/reactos/lib/rtl/rtl.rbuild +++ b/reactos/lib/rtl/rtl.rbuild @@ -18,6 +18,14 @@ thread.c + + + debug.c + except.c + interlocked.c + thread.c + + avl.c tree.c diff --git a/reactos/ntoskrnl/include/internal/powerpc/intrin_i.h b/reactos/ntoskrnl/include/internal/powerpc/intrin_i.h new file mode 100644 index 00000000000..c5ba0381421 --- /dev/null +++ b/reactos/ntoskrnl/include/internal/powerpc/intrin_i.h @@ -0,0 +1,6 @@ +#ifndef _INTRIN_INTERNAL_ +#define _INTRIN_INTERNAL_ + +#endif + +/* EOF */ diff --git a/reactos/tools/rbuild/backend/mingw/modulehandler.cpp b/reactos/tools/rbuild/backend/mingw/modulehandler.cpp index 45db6e03a8e..8ef64ee20cf 100644 --- a/reactos/tools/rbuild/backend/mingw/modulehandler.cpp +++ b/reactos/tools/rbuild/backend/mingw/modulehandler.cpp @@ -146,7 +146,7 @@ MingwModuleHandler::PassThruCacheDirectory (const FileLocation* fileLocation ) MingwModuleHandler::GetTargetDirectoryTree ( const Module& module ) { - if ( module.type == StaticLibrary ) + if ( module.type == StaticLibrary || module.type == BootProgram ) return backend->intermediateDirectory; return backend->outputDirectory; } @@ -267,6 +267,9 @@ MingwModuleHandler::InstanciateHandler ( case EmbeddedTypeLib: handler = new MingwEmbeddedTypeLibModuleHandler ( module ); break; + case ElfExecutable: + handler = new MingwElfExecutableModuleHandler ( module ); + break; default: throw UnknownModuleTypeException ( module.node.location, @@ -3145,20 +3148,24 @@ MingwBootProgramModuleHandler::GenerateBootProgramModuleTarget () fprintf ( fMakefile, "\t$(ECHO_BOOTPROG)\n" ); - fprintf ( fMakefile, "\t$(BOOTPROG_PREPARE) $(OUTPUT)$(SEP)%s %s\n", + fprintf ( fMakefile, "\t$(%s_PREPARE) $(OUTPUT)$(SEP)%s %s\n", + module.buildtype.c_str (), NormalizeFilename( payload->GetPath() ).c_str (), junk_cpy.c_str () ); - fprintf ( fMakefile, "\t${objcopy} $(BOOTPROG_FLATFORMAT) %s %s\n", + fprintf ( fMakefile, "\t${objcopy} $(%s_FLATFORMAT) %s %s\n", + module.buildtype.c_str (), junk_cpy.c_str (), junk_tmp.c_str () ); - fprintf ( fMakefile, "\t${ld} $(BOOTPROG_LINKFORMAT) %s %s -g -o %s\n", + fprintf ( fMakefile, "\t${ld} $(%s_LINKFORMAT) %s %s -g -o %s\n", + module.buildtype.c_str (), linkDepsMacro.c_str (), junk_tmp.c_str (), junk_elf.c_str () ); - fprintf ( fMakefile, "\t${objcopy} $(BOOTPROG_COPYFORMAT) %s %s\n", + fprintf ( fMakefile, "\t${objcopy} $(%s_COPYFORMAT) %s $(INTERMEDIATE)$(SEP)%s\n", + module.buildtype.c_str (), junk_elf.c_str (), module.GetPath().c_str () ); @@ -3690,3 +3697,37 @@ MingwIdlHeaderModuleHandler::Process () { GenerateRules (); } + +MingwElfExecutableModuleHandler::MingwElfExecutableModuleHandler ( + const Module& module_ ) + + : MingwModuleHandler ( module_ ) +{ +} + +void +MingwElfExecutableModuleHandler::Process () +{ + string targetName ( module.GetTargetName () ); + string targetMacro ( GetTargetMacro (module) ); + string workingDirectory = GetWorkingDirectory (); + string objectsMacro = GetObjectsMacro ( module ); + string linkDepsMacro = GetLinkingDependenciesMacro (); + string libsMacro = GetLibsMacro (); + + GenerateRules (); + + fprintf ( fMakefile, "%s: %s %s | %s\n", + targetMacro.c_str (), + objectsMacro.c_str (), + linkDepsMacro.c_str (), + GetDirectory(GetTargetFilename(module,NULL)).c_str () ); + + fprintf ( fMakefile, "\t$(ECHO_BOOTPROG)\n" ); + + fprintf ( fMakefile, "\t${ld} $(%s_LINKFORMAT) %s %s -g -o %s\n", + module.buildtype.c_str(), + objectsMacro.c_str(), + libsMacro.c_str(), + targetMacro.c_str () ); +} diff --git a/reactos/tools/rbuild/backend/mingw/modulehandler.h b/reactos/tools/rbuild/backend/mingw/modulehandler.h index 804c4e26ad4..e68f858b6c5 100644 --- a/reactos/tools/rbuild/backend/mingw/modulehandler.h +++ b/reactos/tools/rbuild/backend/mingw/modulehandler.h @@ -125,6 +125,7 @@ protected: void GenerateRules (); void GenerateImportLibraryTargetIfNeeded (); void GetDefinitionDependencies ( string_list& dependencies ) const; + std::string GetLinkingDependencies () const; static MingwBackend* backend; static FILE* fMakefile; @@ -514,4 +515,12 @@ public: virtual void Process (); }; +class MingwElfExecutableModuleHandler : public MingwModuleHandler +{ +public: + MingwElfExecutableModuleHandler ( const Module& module ); + virtual HostType DefaultHost() { return HostFalse; } + virtual void Process (); +}; + #endif /* MINGW_MODULEHANDLER_H */ diff --git a/reactos/tools/rbuild/bootstrap.cpp b/reactos/tools/rbuild/bootstrap.cpp index 32127a3ab5d..e01303db139 100644 --- a/reactos/tools/rbuild/bootstrap.cpp +++ b/reactos/tools/rbuild/bootstrap.cpp @@ -68,6 +68,7 @@ Bootstrap::IsSupportedModuleType ( ModuleType type ) case Alias: case IdlHeader: case EmbeddedTypeLib: + case ElfExecutable: return false; } throw InvalidOperationException ( __FILE__, diff --git a/reactos/tools/rbuild/module.cpp b/reactos/tools/rbuild/module.cpp index 910c9ef6e48..7cd17984eb9 100644 --- a/reactos/tools/rbuild/module.cpp +++ b/reactos/tools/rbuild/module.cpp @@ -474,6 +474,19 @@ Module::Module ( const Project& project, att = moduleNode.GetAttribute ( "payload", true ); payload = att->value; } + + if ( type == BootProgram || type == ElfExecutable ) + { + att = moduleNode.GetAttribute ( "buildtype", false ); + if ( att != NULL ) + { + buildtype = att->value; + } + else + { + buildtype = "BOOTPROG"; + } + } } Module::~Module () @@ -879,6 +892,8 @@ Module::GetModuleType ( const string& location, const XMLAttribute& attribute ) return IdlHeader; if ( attribute.value == "embeddedtypelib" ) return EmbeddedTypeLib; + if ( attribute.value == "elfexecutable" ) + return ElfExecutable; throw InvalidAttributeValueException ( location, attribute.name, attribute.value ); @@ -891,6 +906,7 @@ Module::GetDefaultModuleExtension () const { case BuildTool: return ExePostfix; + case BootProgram: case StaticLibrary: return ".a"; case ObjectLibrary: @@ -926,7 +942,7 @@ Module::GetDefaultModuleExtension () const case RpcClient: return ".o"; case Alias: - case BootProgram: + case ElfExecutable: case IdlHeader: return ""; case EmbeddedTypeLib: @@ -979,6 +995,7 @@ Module::GetDefaultModuleEntrypoint () const case Alias: case BootProgram: case IdlHeader: + case ElfExecutable: case EmbeddedTypeLib: return ""; } @@ -1007,6 +1024,8 @@ Module::GetDefaultModuleBaseaddress () const case KernelModeDLL: case KernelModeDriver: return "0x00010000"; + case ElfExecutable: + return "0xe00000"; case BuildTool: case StaticLibrary: case ObjectLibrary: @@ -1066,6 +1085,7 @@ Module::IsDLL () const case Alias: case IdlHeader: case EmbeddedTypeLib: + case ElfExecutable: return false; } throw InvalidOperationException ( __FILE__, @@ -1091,18 +1111,19 @@ Module::GenerateInOutputTree () const case BuildTool: case BootLoader: case BootSector: - case BootProgram: case Iso: case LiveIso: case IsoRegTest: case LiveIsoRegTest: case EmbeddedTypeLib: + case ElfExecutable: return true; case StaticLibrary: case ObjectLibrary: case RpcServer: case RpcClient: case Alias: + case BootProgram: case IdlHeader: return false; } @@ -1686,6 +1707,7 @@ AutoRegister::IsSupportedModuleType ( ModuleType type ) case Alias: case IdlHeader: case EmbeddedTypeLib: + case ElfExecutable: return false; } throw InvalidOperationException ( __FILE__, diff --git a/reactos/tools/rbuild/rbuild.h b/reactos/tools/rbuild/rbuild.h index 19cb51cc742..b5d8a13fae8 100644 --- a/reactos/tools/rbuild/rbuild.h +++ b/reactos/tools/rbuild/rbuild.h @@ -274,7 +274,8 @@ enum ModuleType IdlHeader = 23, IsoRegTest = 24, LiveIsoRegTest = 25, - EmbeddedTypeLib = 26 + EmbeddedTypeLib = 26, + ElfExecutable = 27 }; enum HostType @@ -295,6 +296,7 @@ public: std::string extension; std::string baseaddress; std::string payload; + std::string buildtype; std::string path; ModuleType type; ImportLibrary* importLibrary;