From 36402e5aa41c01d578a492546c1f224ebf2e7389 Mon Sep 17 00:00:00 2001 From: Casper Hornstrup Date: Tue, 21 Aug 2001 20:18:27 +0000 Subject: [PATCH] Module wide .cvsignore for: *.sys, *.exe, *.dll, *.a, *.o, *.coff Seperated the HALs from ntoskrnl.exe Added template HAL svn path=/trunk/; revision=2186 --- reactos/hal/hal/Makefile | 23 + reactos/hal/hal/hal.c | 925 ++++++++++++ reactos/hal/hal/hal.def | 94 ++ reactos/hal/hal/hal.edf | 94 ++ reactos/hal/hal/hal.rc | 37 + reactos/hal/halx86/.cvsignore | 1 + reactos/hal/halx86/Makefile | 97 ++ reactos/hal/halx86/adapter.c | 154 ++ reactos/hal/halx86/beep.c | 77 + reactos/hal/halx86/bios32.c | 144 ++ reactos/hal/halx86/bus.c | 515 +++++++ reactos/hal/halx86/display.c | 293 ++++ reactos/hal/halx86/dma.c | 115 ++ reactos/hal/halx86/drive.c | 31 + reactos/hal/halx86/enum.c | 34 + reactos/hal/halx86/fmutex.c | 60 + reactos/hal/halx86/halinit.c | 71 + reactos/hal/halx86/halx86mp.rc | 37 + reactos/hal/halx86/halx86up.rc | 37 + reactos/hal/halx86/include/bus.h | 121 ++ reactos/hal/halx86/include/hal.h | 48 + reactos/hal/halx86/include/mps.h | 435 ++++++ reactos/hal/halx86/irql.c | 451 ++++++ reactos/hal/halx86/isa.c | 62 + reactos/hal/halx86/kdbg.c | 336 +++++ reactos/hal/halx86/mbr.c | 25 + reactos/hal/halx86/misc.c | 105 ++ reactos/hal/halx86/mp.c | 2367 ++++++++++++++++++++++++++++++ reactos/hal/halx86/mps.S | 76 + reactos/hal/halx86/mpsboot.asm | 106 ++ reactos/hal/halx86/mpsirql.c | 417 ++++++ reactos/hal/halx86/pci.c | 494 +++++++ reactos/hal/halx86/perfcnt.c | 62 + reactos/hal/halx86/portio.c | 182 +++ reactos/hal/halx86/pwroff.c | 114 ++ reactos/hal/halx86/reboot.c | 74 + reactos/hal/halx86/spinlock.c | 95 ++ reactos/hal/halx86/sysbus.c | 64 + reactos/hal/halx86/sysinfo.c | 23 + reactos/hal/halx86/time.c | 307 ++++ reactos/hal/halx86/udelay.c | 223 +++ 41 files changed, 9026 insertions(+) create mode 100644 reactos/hal/hal/Makefile create mode 100644 reactos/hal/hal/hal.c create mode 100644 reactos/hal/hal/hal.def create mode 100644 reactos/hal/hal/hal.edf create mode 100644 reactos/hal/hal/hal.rc create mode 100644 reactos/hal/halx86/.cvsignore create mode 100644 reactos/hal/halx86/Makefile create mode 100644 reactos/hal/halx86/adapter.c create mode 100644 reactos/hal/halx86/beep.c create mode 100644 reactos/hal/halx86/bios32.c create mode 100644 reactos/hal/halx86/bus.c create mode 100644 reactos/hal/halx86/display.c create mode 100644 reactos/hal/halx86/dma.c create mode 100644 reactos/hal/halx86/drive.c create mode 100644 reactos/hal/halx86/enum.c create mode 100644 reactos/hal/halx86/fmutex.c create mode 100644 reactos/hal/halx86/halinit.c create mode 100644 reactos/hal/halx86/halx86mp.rc create mode 100644 reactos/hal/halx86/halx86up.rc create mode 100644 reactos/hal/halx86/include/bus.h create mode 100644 reactos/hal/halx86/include/hal.h create mode 100644 reactos/hal/halx86/include/mps.h create mode 100644 reactos/hal/halx86/irql.c create mode 100644 reactos/hal/halx86/isa.c create mode 100644 reactos/hal/halx86/kdbg.c create mode 100644 reactos/hal/halx86/mbr.c create mode 100644 reactos/hal/halx86/misc.c create mode 100644 reactos/hal/halx86/mp.c create mode 100644 reactos/hal/halx86/mps.S create mode 100644 reactos/hal/halx86/mpsboot.asm create mode 100644 reactos/hal/halx86/mpsirql.c create mode 100644 reactos/hal/halx86/pci.c create mode 100644 reactos/hal/halx86/perfcnt.c create mode 100644 reactos/hal/halx86/portio.c create mode 100644 reactos/hal/halx86/pwroff.c create mode 100644 reactos/hal/halx86/reboot.c create mode 100644 reactos/hal/halx86/spinlock.c create mode 100644 reactos/hal/halx86/sysbus.c create mode 100644 reactos/hal/halx86/sysinfo.c create mode 100644 reactos/hal/halx86/time.c create mode 100644 reactos/hal/halx86/udelay.c diff --git a/reactos/hal/hal/Makefile b/reactos/hal/hal/Makefile new file mode 100644 index 00000000000..b98f9d11bc3 --- /dev/null +++ b/reactos/hal/hal/Makefile @@ -0,0 +1,23 @@ +# $Id: Makefile,v 1.1 2001/08/21 20:18:26 chorns Exp $ + +PATH_TO_TOP = ../.. + +TARGET_TYPE = driver_library + +TARGET_ASFLAGS = -D__NTHAL__ -I$(PATH_TO_TOP)/ntoskrnl/include + +TARGET_CFLAGS = -D__NTHAL__ -I$(PATH_TO_TOP)/ntoskrnl/include + +TARGET_NAME = hal + +HEADER_FILES = $(PATH_TO_TOP)/include/roscfg.h + +TARGET_OBJECTS := $(TARGET_NAME).o $(HEADER_FILES) + +include $(PATH_TO_TOP)/rules.mak + +include $(TOOLS_PATH)/helper.mk + +include $(TOOLS_PATH)/config.mk + +# EOF diff --git a/reactos/hal/hal/hal.c b/reactos/hal/hal/hal.c new file mode 100644 index 00000000000..d1d107cf8b2 --- /dev/null +++ b/reactos/hal/hal/hal.c @@ -0,0 +1,925 @@ +/* $Id: hal.c,v 1.1 2001/08/21 20:18:26 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: hal/hal.c + * PURPOSE: Hardware Abstraction Layer DLL + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * REVISION HISTORY: + * 01-08-2001 CSH Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include + +#define NDEBUG +#include + +/* DATA **********************************************************************/ + +ULONG EXPORTED KdComPortInUse = 0; + +/* FUNCTIONS *****************************************************************/ + +NTSTATUS +STDCALL +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +{ + UNIMPLEMENTED; + + return STATUS_SUCCESS; +} + + +VOID +FASTCALL +ExAcquireFastMutex( + PFAST_MUTEX FastMutex) +{ + UNIMPLEMENTED; +} + + +VOID +FASTCALL +ExReleaseFastMutex( + PFAST_MUTEX FastMutex) +{ + UNIMPLEMENTED; +} + + +BOOLEAN FASTCALL +ExTryToAcquireFastMutex( + PFAST_MUTEX FastMutex) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalAcquireDisplayOwnership( + PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters) +{ + UNIMPLEMENTED; +} + + +NTSTATUS +STDCALL +HalAdjustResourceList( + PCM_RESOURCE_LIST Resources) +{ + UNIMPLEMENTED; + + return STATUS_SUCCESS; +} + + +BOOLEAN +STDCALL +HalAllProcessorsStarted(VOID) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +NTSTATUS +STDCALL +HalAllocateAdapterChannel( + PADAPTER_OBJECT AdapterObject, + PDEVICE_OBJECT DeviceObject, + ULONG NumberOfMapRegisters, + PDRIVER_CONTROL ExecutionRoutine, + PVOID Context) +{ + UNIMPLEMENTED; + + return STATUS_SUCCESS; +} + + +PVOID +STDCALL +HalAllocateCommonBuffer( + PADAPTER_OBJECT AdapterObject, + ULONG Length, + PPHYSICAL_ADDRESS LogicalAddress, + BOOLEAN CacheEnabled) +{ + UNIMPLEMENTED; + + return NULL; +} + + +NTSTATUS +STDCALL +HalAssignSlotResources( + PUNICODE_STRING RegistryPath, + PUNICODE_STRING DriverClassName, + PDRIVER_OBJECT DriverObject, + PDEVICE_OBJECT DeviceObject, + INTERFACE_TYPE BusType, + ULONG BusNumber, + ULONG SlotNumber, + PCM_RESOURCE_LIST *AllocatedResources) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +BOOLEAN +STDCALL +HalBeginSystemInterrupt( + ULONG Vector, + KIRQL Irql, + PKIRQL OldIrql) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalCalibratePerformanceCounter( + ULONG Count) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalDisableSystemInterrupt( + ULONG Vector, + ULONG Unknown2) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalDisplayString( + PCH String) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalEnableSystemInterrupt( + ULONG Vector, + ULONG Unknown2, + ULONG Unknown3) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalEndSystemInterrupt( + KIRQL Irql, + ULONG Unknown2) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalFlushCommonBuffer( + ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3, + ULONG Unknown4, + ULONG Unknown5, + ULONG Unknown6, + ULONG Unknown7, + ULONG Unknown8) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalFreeCommonBuffer( + PADAPTER_OBJECT AdapterObject, + ULONG Length, + PHYSICAL_ADDRESS LogicalAddress, + PVOID VirtualAddress, + BOOLEAN CacheEnabled) +{ + UNIMPLEMENTED; +} + + +PADAPTER_OBJECT +STDCALL +HalGetAdapter( + PDEVICE_DESCRIPTION DeviceDescription, + PULONG NumberOfMapRegisters) +{ + UNIMPLEMENTED; + + return (PADAPTER_OBJECT)NULL; +} + + +ULONG +STDCALL +HalGetBusData( + BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Length) +{ + UNIMPLEMENTED; + + return 0; +} + + +ULONG +STDCALL +HalGetBusDataByOffset( + BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + UNIMPLEMENTED; + + return 0; +} + + +BOOLEAN +STDCALL +HalGetEnvironmentVariable( + PCH Name, + PCH Value, + USHORT ValueLength) +{ + UNIMPLEMENTED; + + return FALSE; +} + + +ULONG +STDCALL +HalGetInterruptVector( + INTERFACE_TYPE InterfaceType, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity) +{ + UNIMPLEMENTED; + + return 0; +} + + +VOID +STDCALL +HalHandleNMI( + ULONG Unused) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalInitSystem( + ULONG BootPhase, + PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalInitializeProcessor( + ULONG ProcessorNumber, + PVOID ProcessorStack) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalMakeBeep( + ULONG Frequency) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalProcessorIdle(VOID) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +HalQueryDisplayParameters( + PULONG DispSizeX, + PULONG DispSizeY, + PULONG CursorPosX, + PULONG CursorPosY) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +HalQueryRealTimeClock( + PTIME_FIELDS Time) +{ + UNIMPLEMENTED; +} + + +ULONG +STDCALL +HalReadDmaCounter( + PADAPTER_OBJECT AdapterObject) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +HalReportResourceUsage(VOID) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +HalRequestIpi( + ULONG Unknown) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +HalReturnToFirmware( + ULONG Action) +{ + UNIMPLEMENTED; +} + + +ULONG +STDCALL +HalSetBusData( + BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Length) +{ + UNIMPLEMENTED; + + return 0; +} + + +ULONG +STDCALL +HalSetBusDataByOffset( + BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + UNIMPLEMENTED; + + return 0; +} + + +VOID +STDCALL +HalSetDisplayParameters( + ULONG CursorPosX, + ULONG CursorPosY) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalSetEnvironmentVariable( + PCH Name, + PCH Value) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +HalSetRealTimeClock( + PTIME_FIELDS Time) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +HalStartNextProcessor( + ULONG Unknown1, + ULONG Unknown2) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +ULONG +FASTCALL +HalSystemVectorDispatchEntry( + ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3) +{ + UNIMPLEMENTED; + + return 0; +} + + +BOOLEAN +STDCALL +HalTranslateBusAddress( + INTERFACE_TYPE InterfaceType, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +IoAssignDriveLetters( + PLOADER_PARAMETER_BLOCK LoaderBlock, + PSTRING NtDeviceName, + PUCHAR NtSystemPath, + PSTRING NtSystemPathString) +{ + UNIMPLEMENTED; +} + + +BOOLEAN +STDCALL +IoFlushAdapterBuffers( + PADAPTER_OBJECT AdapterObject, + PMDL Mdl, + PVOID MapRegisterBase, + PVOID CurrentVa, + ULONG Length, + BOOLEAN WriteToDevice) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +IoFreeAdapterChannel( + PADAPTER_OBJECT AdapterObject) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +IoFreeMapRegisters( + PADAPTER_OBJECT AdapterObject, + PVOID MapRegisterBase, + ULONG NumberOfMapRegisters) +{ + UNIMPLEMENTED; +} + + +PHYSICAL_ADDRESS +STDCALL +IoMapTransfer( + PADAPTER_OBJECT AdapterObject, + PMDL Mdl, + PVOID MapRegisterBase, + PVOID CurrentVa, + PULONG Length, + BOOLEAN WriteToDevice) +{ + PHYSICAL_ADDRESS Address; + + UNIMPLEMENTED; + + Address.QuadPart = 0; + + return Address; +} + + +BOOLEAN +STDCALL +KdPortGetByte( + PUCHAR ByteRecieved) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +BOOLEAN +STDCALL +KdPortInitialize( + PKD_PORT_INFORMATION PortInformation, + DWORD Unknown1, + DWORD Unknown2) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +BOOLEAN +STDCALL +KdPortPollByte( + PUCHAR ByteRecieved) +{ + UNIMPLEMENTED; + + return TRUE; +} + + +VOID +STDCALL +KdPortPutByte( + UCHAR ByteToSend) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +KdPortRestore(VOID) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +KdPortSave(VOID) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +KeAcquireSpinLock( + PKSPIN_LOCK SpinLock, + PKIRQL OldIrql) +{ + UNIMPLEMENTED; +} + + +KIRQL +FASTCALL +KeAcquireSpinLockRaiseToSynch( + PKSPIN_LOCK SpinLock) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +KeFlushWriteBuffer(VOID) +{ + UNIMPLEMENTED; +} + + +KIRQL +STDCALL +KeGetCurrentIrql(VOID) +{ + UNIMPLEMENTED; + + return (KIRQL)0; +} + + +VOID +STDCALL +KeLowerIrql( + KIRQL NewIrql) +{ + UNIMPLEMENTED; +} + + +LARGE_INTEGER +STDCALL +KeQueryPerformanceCounter( + PLARGE_INTEGER PerformanceFreq) +{ + LARGE_INTEGER Value; + + UNIMPLEMENTED; + + Value.QuadPart = 0; + + return Value; +} + + +VOID +STDCALL +KeRaiseIrql( + KIRQL NewIrql, + PKIRQL OldIrql) +{ + UNIMPLEMENTED; +} + + +KIRQL +STDCALL +KeRaiseIrqlToDpcLevel(VOID) +{ + UNIMPLEMENTED; + + return (KIRQL)0; +} + + +KIRQL +STDCALL +KeRaiseIrqlToSynchLevel(VOID) +{ + UNIMPLEMENTED; + + return (KIRQL)0; +} + + +VOID +STDCALL +KeReleaseSpinLock( + PKSPIN_LOCK SpinLock, + KIRQL NewIrql) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +KeStallExecutionProcessor( + ULONG Microseconds) +{ + UNIMPLEMENTED; +} + + +KIRQL +FASTCALL +KfAcquireSpinLock( + PKSPIN_LOCK SpinLock) +{ + UNIMPLEMENTED; + + return (KIRQL)0; +} + + +VOID +FASTCALL +KfLowerIrql( + KIRQL NewIrql) +{ + UNIMPLEMENTED; +} + + +KIRQL +FASTCALL +KfRaiseIrql( + KIRQL NewIrql) +{ + UNIMPLEMENTED; + + return (KIRQL)0; +} + + +VOID +FASTCALL +KfReleaseSpinLock( + PKSPIN_LOCK SpinLock, + KIRQL NewIrql) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +READ_PORT_BUFFER_UCHAR( + PUCHAR Port, + PUCHAR Buffer, + ULONG Count) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +READ_PORT_BUFFER_ULONG( + PULONG Port, + PULONG Buffer, + ULONG Count) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +READ_PORT_BUFFER_USHORT( + PUSHORT Port, + PUSHORT Buffer, + ULONG Count) +{ + UNIMPLEMENTED; +} + + +UCHAR +STDCALL +READ_PORT_UCHAR( + PUCHAR Port) +{ + UNIMPLEMENTED; + + return 0; +} + + +ULONG +STDCALL +READ_PORT_ULONG( + PULONG Port) +{ + UNIMPLEMENTED; + + return 0; +} + + +USHORT +STDCALL +READ_PORT_USHORT( + PUSHORT Port) +{ + UNIMPLEMENTED; + + return 0; +} + + +VOID +STDCALL +WRITE_PORT_BUFFER_UCHAR( + PUCHAR Port, + PUCHAR Buffer, + ULONG Count) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +WRITE_PORT_BUFFER_USHORT( + PUSHORT Port, + PUSHORT Buffer, + ULONG Count) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +WRITE_PORT_BUFFER_ULONG( + PULONG Port, + PULONG Buffer, + ULONG Count) +{ + UNIMPLEMENTED; +} + + +VOID +STDCALL +WRITE_PORT_UCHAR( + PUCHAR Port, + UCHAR Value) +{ + UNIMPLEMENTED; +} + +VOID +STDCALL +WRITE_PORT_ULONG( + PULONG Port, + ULONG Value) +{ + UNIMPLEMENTED; +} + +VOID +STDCALL +WRITE_PORT_USHORT( + PUSHORT Port, + USHORT Value) +{ + UNIMPLEMENTED; +} + +/* EOF */ diff --git a/reactos/hal/hal/hal.def b/reactos/hal/hal/hal.def new file mode 100644 index 00000000000..4a2109327c3 --- /dev/null +++ b/reactos/hal/hal/hal.def @@ -0,0 +1,94 @@ +; Hardware Abstraction Layer - ReactOS Operating System + +LIBRARY hal.dll + +EXPORTS +@ExAcquireFastMutex@4 +@ExReleaseFastMutex@4 +@ExTryToAcquireFastMutex@4 +HalAcquireDisplayOwnership@4 +HalAdjustResourceList@4 +HalAllProcessorsStarted@0 +HalAllocateAdapterChannel@20 +HalAllocateCommonBuffer@16 +;HalAllocateCrashDumpRegisters@8 +HalAssignSlotResources@32 +HalBeginSystemInterrupt@12 +HalCalibratePerformanceCounter@4 +;@HalClearSoftwareInterrupt@4 +;HalClearSoftwareInterrupt@4 +HalDisableSystemInterrupt@8 +HalDisplayString@4 +HalEnableSystemInterrupt@12 +HalEndSystemInterrupt@8 +HalFlushCommonBuffer@32 +HalFreeCommonBuffer@24 +HalGetAdapter@8 +HalGetBusData@20 +HalGetBusDataByOffset@24 +HalGetEnvironmentVariable@12 +HalGetInterruptVector@24 +HalHandleNMI@4 +HalInitSystem@8 +HalInitializeProcessor@8 +HalMakeBeep@4 +HalProcessorIdle@0 +HalQueryDisplayParameters@16 +HalQueryRealTimeClock@4 +HalReadDmaCounter@4 +HalReportResourceUsage@0 +HalRequestIpi@4 +;@HalRequestSoftwareInterrupt@4 +;HalRequestSoftwareInterrupt@4 +HalReturnToFirmware@4 +HalSetBusData@20 +HalSetBusDataByOffset@24 +HalSetDisplayParameters@8 +HalSetEnvironmentVariable@8 +;HalSetProfileInterval@4 +HalSetRealTimeClock@4 +;HalSetTimeIncrement@4 +HalStartNextProcessor@8 +;HalStartProfileInterrupt@4 +;HalStopProfileInterrupt@4 +@HalSystemVectorDispatchEntry@12 +HalTranslateBusAddress@24 +IoAssignDriveLetters@16 +IoFlushAdapterBuffers@24 +IoFreeAdapterChannel@4 +IoFreeMapRegisters@12 +IoMapTransfer@24 +KdComPortInUse DATA +KdPortGetByte@4 +KdPortInitialize@12 +KdPortPollByte@4 +KdPortPutByte@4 +KdPortRestore@0 +KdPortSave@0 +KeAcquireSpinLock@8 +@KeAcquireSpinLockRaiseToSynch@4 +KeFlushWriteBuffer@0 +KeGetCurrentIrql@0 +KeLowerIrql@4 +KeQueryPerformanceCounter@4 +KeRaiseIrql@8 +KeRaiseIrqlToDpcLevel@0 +KeRaiseIrqlToSynchLevel@0 +KeReleaseSpinLock@8 +KeStallExecutionProcessor@4 +@KfAcquireSpinLock@4 +@KfLowerIrql@4 +@KfRaiseIrql@4 +@KfReleaseSpinLock@8 +READ_PORT_BUFFER_UCHAR@12 +READ_PORT_BUFFER_ULONG@12 +READ_PORT_BUFFER_USHORT@12 +READ_PORT_UCHAR@4 +READ_PORT_ULONG@4 +READ_PORT_USHORT@4 +WRITE_PORT_BUFFER_UCHAR@12 +WRITE_PORT_BUFFER_ULONG@12 +WRITE_PORT_BUFFER_USHORT@12 +WRITE_PORT_UCHAR@8 +WRITE_PORT_ULONG@8 +WRITE_PORT_USHORT@8 diff --git a/reactos/hal/hal/hal.edf b/reactos/hal/hal/hal.edf new file mode 100644 index 00000000000..1a7a19de470 --- /dev/null +++ b/reactos/hal/hal/hal.edf @@ -0,0 +1,94 @@ +; Hardware Abstraction Layer - ReactOS Operating System + +LIBRARY hal.dll + +EXPORTS +ExAcquireFastMutex=@ExAcquireFastMutex@4 +ExReleaseFastMutex=@ExReleaseFastMutex@4 +ExTryToAcquireFastMutex=@ExTryToAcquireFastMutex@4 +HalAcquireDisplayOwnership=HalAcquireDisplayOwnership@4 +HalAdjustResourceList=HalAdjustResourceList@4 +HalAllProcessorsStarted=HalAllProcessorsStarted@0 +HalAllocateAdapterChannel=HalAllocateAdapterChannel@20 +HalAllocateCommonBuffer=HalAllocateCommonBuffer@16 +;HalAllocateCrashDumpRegisters@8 +HalAssignSlotResources=HalAssignSlotResources@32 +HalBeginSystemInterrupt=HalBeginSystemInterrupt@12 +HalCalibratePerformanceCounter=HalCalibratePerformanceCounter@4 +;@HalClearSoftwareInterrupt@4 +;HalClearSoftwareInterrupt@4 +HalDisableSystemInterrupt=HalDisableSystemInterrupt@8 +HalDisplayString=HalDisplayString@4 +HalEnableSystemInterrupt=HalEnableSystemInterrupt@12 +HalEndSystemInterrupt=HalEndSystemInterrupt@8 +HalFlushCommonBuffer=HalFlushCommonBuffer@32 +HalFreeCommonBuffer=HalFreeCommonBuffer@24 +HalGetAdapter=HalGetAdapter@8 +HalGetBusData=HalGetBusData@20 +HalGetBusDataByOffset=HalGetBusDataByOffset@24 +HalGetEnvironmentVariable=HalGetEnvironmentVariable@12 +HalGetInterruptVector=HalGetInterruptVector@24 +HalHandleNMI=HalHandleNMI@4 +HalInitSystem=HalInitSystem@8 +HalInitializeProcessor=HalInitializeProcessor@8 +HalMakeBeep=HalMakeBeep@4 +HalProcessorIdle=HalProcessorIdle@0 +HalQueryDisplayParameters=HalQueryDisplayParameters@16 +HalQueryRealTimeClock=HalQueryRealTimeClock@4 +HalReadDmaCounter=HalReadDmaCounter@4 +HalReportResourceUsage=HalReportResourceUsage@0 +HalRequestIpi=HalRequestIpi@4 +;@HalRequestSoftwareInterrupt@4 +;HalRequestSoftwareInterrupt@4 +HalReturnToFirmware=HalReturnToFirmware@4 +HalSetBusData=HalSetBusData@20 +HalSetBusDataByOffset=HalSetBusDataByOffset@24 +HalSetDisplayParameters=HalSetDisplayParameters@8 +HalSetEnvironmentVariable=HalSetEnvironmentVariable@8 +;HalSetProfileInterval@4 +HalSetRealTimeClock=HalSetRealTimeClock@4 +;HalSetTimeIncrement@4 +HalStartNextProcessor=HalStartNextProcessor@8 +;HalStartProfileInterrupt@4 +;HalStopProfileInterrupt@4 +HalSystemVectorDispatchEntry=@HalSystemVectorDispatchEntry@12 +HalTranslateBusAddress=HalTranslateBusAddress@24 +IoAssignDriveLetters=IoAssignDriveLetters@16 +IoFlushAdapterBuffers=IoFlushAdapterBuffers@24 +IoFreeAdapterChannel=IoFreeAdapterChannel@4 +IoFreeMapRegisters=IoFreeMapRegisters@12 +IoMapTransfer=IoMapTransfer@24 +KdComPortInUse DATA +KdPortGetByte=KdPortGetByte@4 +KdPortInitialize=KdPortInitialize@12 +KdPortPollByte=KdPortPollByte@4 +KdPortPutByte=KdPortPutByte@4 +KdPortRestore=KdPortRestore@0 +KdPortSave=KdPortSave@0 +KeAcquireSpinLock=KeAcquireSpinLock@8 +KeAcquireSpinLockRaiseToSynch=@KeAcquireSpinLockRaiseToSynch@4 +KeFlushWriteBuffer=KeFlushWriteBuffer@0 +KeGetCurrentIrql=KeGetCurrentIrql@0 +KeLowerIrql=KeLowerIrql@4 +KeQueryPerformanceCounter=KeQueryPerformanceCounter@4 +KeRaiseIrql=KeRaiseIrql@8 +KeRaiseIrqlToDpcLevel=KeRaiseIrqlToDpcLevel@0 +KeRaiseIrqlToSynchLevel=KeRaiseIrqlToSynchLevel@0 +KeReleaseSpinLock=KeReleaseSpinLock@8 +KeStallExecutionProcessor=KeStallExecutionProcessor@4 +KfAcquireSpinLock=@KfAcquireSpinLock@4 +KfLowerIrql=@KfLowerIrql@4 +KfRaiseIrql=@KfRaiseIrql@4 +KfReleaseSpinLock=@KfReleaseSpinLock@8 +READ_PORT_BUFFER_UCHAR=READ_PORT_BUFFER_UCHAR@12 +READ_PORT_BUFFER_ULONG=READ_PORT_BUFFER_ULONG@12 +READ_PORT_BUFFER_USHORT=READ_PORT_BUFFER_USHORT@12 +READ_PORT_UCHAR=READ_PORT_UCHAR@4 +READ_PORT_ULONG=READ_PORT_ULONG@4 +READ_PORT_USHORT=READ_PORT_USHORT@4 +WRITE_PORT_BUFFER_UCHAR=WRITE_PORT_BUFFER_UCHAR@12 +WRITE_PORT_BUFFER_ULONG=WRITE_PORT_BUFFER_ULONG@12 +WRITE_PORT_BUFFER_USHORT=WRITE_PORT_BUFFER_USHORT@12 +WRITE_PORT_UCHAR=WRITE_PORT_UCHAR@8 +WRITE_PORT_ULONG=WRITE_PORT_ULONG@8 +WRITE_PORT_USHORT=WRITE_PORT_USHORT@8 diff --git a/reactos/hal/hal/hal.rc b/reactos/hal/hal/hal.rc new file mode 100644 index 00000000000..2d3e9ffa137 --- /dev/null +++ b/reactos/hal/hal/hal.rc @@ -0,0 +1,37 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "Template Hardware Abstraction Layer\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "hal\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "hal.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END \ No newline at end of file diff --git a/reactos/hal/halx86/.cvsignore b/reactos/hal/halx86/.cvsignore new file mode 100644 index 00000000000..36de49a073e --- /dev/null +++ b/reactos/hal/halx86/.cvsignore @@ -0,0 +1 @@ +*.d \ No newline at end of file diff --git a/reactos/hal/halx86/Makefile b/reactos/hal/halx86/Makefile new file mode 100644 index 00000000000..3711ba416c3 --- /dev/null +++ b/reactos/hal/halx86/Makefile @@ -0,0 +1,97 @@ +# $Id: Makefile,v 1.1 2001/08/21 20:18:26 chorns Exp $ + +PATH_TO_TOP = ../.. + +# +# Build configuration +# +include $(PATH_TO_TOP)/rules.mak + +# +# Global configuration +# +include $(TOOLS_PATH)/config.mk + +TARGET_TYPE = hal + +TARGET_BASENAME = hal + +TARGET_DEFNAME = ../hal/hal + +TARGET_LIBPATH = . + +TARGET_ASFLAGS = -I$(PATH_TO_TOP)/include -I$(PATH_TO_TOP)/ntoskrnl/include -D__ASM__ + +TARGET_CFLAGS = -I./include -I$(PATH_TO_TOP)/ntoskrnl/include + + +TARGET_NAME_UP = halx86up + +TARGET_NAME_MP = halx86mp + +ifeq ($(MP), 1) +TARGET_NAME = $(TARGET_NAME_MP) +else +TARGET_NAME = $(TARGET_NAME_UP) +endif + +HAL_OBJECTS = \ + adapter.o \ + beep.o \ + bios32.o \ + bus.o \ + display.o \ + dma.o \ + drive.o \ + enum.o \ + fmutex.o \ + halinit.o \ + isa.o \ + kdbg.o \ + mbr.o \ + misc.o \ + mp.o \ + pci.o \ + perfcnt.o \ + portio.o \ + reboot.o \ + spinlock.o \ + sysbus.o \ + sysinfo.o \ + time.o \ + udelay.o + + #pwroff.o + +HAL_UP = \ + $(HAL_OBJECTS) \ + irql.o + +HAL_MP = \ + $(HAL_OBJECTS) \ + mpsirql.o \ + mpsboot.o \ + mps.o + +ifeq ($(MP), 1) +DEP_OBJECTS := $(HAL_MP) +else +DEP_OBJECTS := $(HAL_UP) +endif + +TARGET_OBJECTS := $(DEP_OBJECTS) $(PATH_TO_TOP)/include/roscfg.h + +# Note: Must be = and not := since $(DEP_FILES) is assigned a value below +TARGET_CLEAN = $(DEP_FILES) *.o *.dll + +# +# Helper makefile +# +include $(TOOLS_PATH)/helper.mk + +# +# Include automatic dependancy tracking +# +include $(TOOLS_PATH)/depend.mk + +# EOF diff --git a/reactos/hal/halx86/adapter.c b/reactos/hal/halx86/adapter.c new file mode 100644 index 00000000000..ab2dacee093 --- /dev/null +++ b/reactos/hal/halx86/adapter.c @@ -0,0 +1,154 @@ +/* $Id: adapter.c,v 1.1 2001/08/21 20:18:26 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: hal/x86/adapter.c (from ntoskrnl/io/adapter.c) + * PURPOSE: DMA handling + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include + +/* FUNCTIONS *****************************************************************/ + +/* NOTE: IoAllocateAdapterChannel in NTOSKRNL.EXE */ + +NTSTATUS STDCALL +HalAllocateAdapterChannel(PADAPTER_OBJECT AdapterObject, + PDEVICE_OBJECT DeviceObject, + ULONG NumberOfMapRegisters, + PDRIVER_CONTROL ExecutionRoutine, + PVOID Context ) +{ + KIRQL OldIrql; + PVOID Buffer; + int ret; + LARGE_INTEGER MaxAddress; + + MaxAddress.QuadPart = 0x1000000; + Buffer = MmAllocateContiguousAlignedMemory( NumberOfMapRegisters * PAGESIZE, + MaxAddress, + 0x10000 ); + if( !Buffer ) + return STATUS_INSUFFICIENT_RESOURCES; + KeAcquireSpinLock( &AdapterObject->SpinLock, &OldIrql ); + if( AdapterObject->Inuse ) + { + // someone is already using it, we need to wait + // create a wait block, and add it to the chain + UNIMPLEMENTED; + } + else { + AdapterObject->Inuse = TRUE; + KeReleaseSpinLock( &AdapterObject->SpinLock, OldIrql ); + ret = ExecutionRoutine( DeviceObject, + NULL, + Buffer, + Context ); + KeAcquireSpinLock( &AdapterObject->SpinLock, &OldIrql ); + if( ret == DeallocateObject ) + { + MmFreeContiguousMemory( Buffer ); + AdapterObject->Inuse = FALSE; + } + else AdapterObject->Buffer = Buffer; + } + KeReleaseSpinLock( &AdapterObject->SpinLock, OldIrql ); + return STATUS_SUCCESS; +} + + +BOOLEAN STDCALL +IoFlushAdapterBuffers (PADAPTER_OBJECT AdapterObject, + PMDL Mdl, + PVOID MapRegisterBase, + PVOID CurrentVa, + ULONG Length, + BOOLEAN WriteToDevice) +{ + // if this was a read from device, copy data back to caller buffer, otherwise, do nothing + if( !WriteToDevice ) + memcpy( (PVOID)((DWORD)MmGetSystemAddressForMdl( Mdl ) + (DWORD)CurrentVa - (DWORD)MmGetMdlVirtualAddress( Mdl )), MapRegisterBase, Length ); + return TRUE; +} + + +VOID STDCALL +IoFreeAdapterChannel (PADAPTER_OBJECT AdapterObject) +{ + KIRQL OldIrql; + + KeAcquireSpinLock( &AdapterObject->SpinLock, &OldIrql ); + if( AdapterObject->Inuse == FALSE ) + { + DbgPrint( "Attempting to IoFreeAdapterChannel on a channel not in use\n" ); + KeBugCheck(0); + } + AdapterObject->Inuse = FALSE; + if( AdapterObject->Buffer ) + { + MmFreeContiguousMemory( AdapterObject->Buffer ); + AdapterObject->Buffer = 0; + } + KeReleaseSpinLock( &AdapterObject->SpinLock, OldIrql ); +} + + +VOID STDCALL +IoFreeMapRegisters (PADAPTER_OBJECT AdapterObject, + PVOID MapRegisterBase, + ULONG NumberOfMapRegisters) +{ + UNIMPLEMENTED; +} + + +PHYSICAL_ADDRESS STDCALL +IoMapTransfer (PADAPTER_OBJECT AdapterObject, + PMDL Mdl, + PVOID MapRegisterBase, + PVOID CurrentVa, + PULONG Length, + BOOLEAN WriteToDevice) +{ + PHYSICAL_ADDRESS Address; + // program up the dma controller, and return + // if it is a write to the device, copy the caller buffer to the low buffer + if( WriteToDevice ) + memcpy( MapRegisterBase, + MmGetSystemAddressForMdl( Mdl ) + ( (DWORD)CurrentVa - (DWORD)MmGetMdlVirtualAddress( Mdl ) ), + *Length ); + Address = MmGetPhysicalAddress( MapRegisterBase ); + // port 0xA is the dma mask register, or a 0x10 on to the channel number to mask it + WRITE_PORT_UCHAR( (PVOID)0x0A, AdapterObject->Channel | 0x10 ); + // write zero to the reset register + WRITE_PORT_UCHAR( (PVOID)0x0C, 0 ); + // mode register, or channel with 0x4 for write memory, 0x8 for read memory, 0x10 for non auto initialize + WRITE_PORT_UCHAR( (PVOID)0x0B, AdapterObject->Channel | ( WriteToDevice ? 0x8 : 0x4 ) ); + // set the 64k page register for the channel + WRITE_PORT_UCHAR( AdapterObject->PagePort, (UCHAR)(((ULONG)Address.QuadPart)>>16) ); + // low, then high address byte, which is always 0 for us, because we have a 64k alligned address + WRITE_PORT_UCHAR( AdapterObject->OffsetPort, 0 ); + WRITE_PORT_UCHAR( AdapterObject->OffsetPort, 0 ); + // count is 1 less than length, low then high + WRITE_PORT_UCHAR( AdapterObject->CountPort, (UCHAR)(*Length - 1) ); + WRITE_PORT_UCHAR( AdapterObject->CountPort, (UCHAR)((*Length - 1)>>8) ); + // unmask the channel to let it rip + WRITE_PORT_UCHAR( (PVOID)0x0A, AdapterObject->Channel ); + Address.QuadPart = (DWORD)MapRegisterBase; + return Address; +} + + +/* EOF */ + + + + diff --git a/reactos/hal/halx86/beep.c b/reactos/hal/halx86/beep.c new file mode 100644 index 00000000000..a0d8bfc1c01 --- /dev/null +++ b/reactos/hal/halx86/beep.c @@ -0,0 +1,77 @@ +/* + * 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 + ) +{ + UCHAR b; + + /* save flags and disable interrupts */ + __asm__("pushf\n\t" \ + "cli\n\t"); + + /* speaker off */ + b = READ_PORT_UCHAR((PUCHAR)PORT_B); + WRITE_PORT_UCHAR((PUCHAR)PORT_B, b & 0xFC); + + if (Frequency) + { + DWORD Divider = CLOCKFREQ / Frequency; + + if (Divider > 0x10000) + { + /* restore flags */ + __asm__("popf\n\t"); + + return FALSE; + } + + /* set timer divider */ + WRITE_PORT_UCHAR((PUCHAR)TIMER3, 0xB6); + WRITE_PORT_UCHAR((PUCHAR)TIMER2, (UCHAR)(Divider & 0xFF)); + WRITE_PORT_UCHAR((PUCHAR)TIMER2, (UCHAR)((Divider>>8) & 0xFF)); + + /* speaker on */ + WRITE_PORT_UCHAR((PUCHAR)PORT_B, READ_PORT_UCHAR((PUCHAR)PORT_B) | 0x03); + } + + /* restore flags */ + __asm__("popf\n\t"); + + return TRUE; +} + diff --git a/reactos/hal/halx86/bios32.c b/reactos/hal/halx86/bios32.c new file mode 100644 index 00000000000..4668367610b --- /dev/null +++ b/reactos/hal/halx86/bios32.c @@ -0,0 +1,144 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/pci + * PURPOSE: Interfaces to BIOS32 interface + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * 05/06/98: Created + */ + +/* + * NOTES: Sections copied from the Linux pci support + */ + +/* INCLUDES ***************************************************************/ + +#include +#include +#include + + +/* TYPES ******************************************************************/ + +typedef struct +{ + /* + * "_32_" if present + */ + unsigned int signature; + + /* + * Entry point (physical address) + */ + unsigned long int entry; + + /* + * Revision level + */ + unsigned char revision; + + /* + * Length in paragraphs + */ + unsigned char length; + + /* + * Checksum (so all bytes add up to zero) + */ + unsigned char checksum; + + unsigned char reserved[5]; +} bios32; + +BOOLEAN bios32_detected = FALSE; + +static struct +{ + unsigned long address; + unsigned short segment; +} bios32_indirect = {0,KERNEL_CS}; + +/* FUNCTIONS **************************************************************/ + +#define BIOS32_SIGNATURE (('_' << 0)+('3'<<8)+('2'<<16)+('_'<<24)) + +#if 0 +BOOL static checksum(bios32* service_entry) +/* + * FUNCTION: Checks the checksum of a bios32 service entry + * ARGUMENTS: + * service_entry = Pointer to the service entry + * RETURNS: True if the sum of the bytes in the entry was zero + * False otherwise + */ +{ + unsigned char* p = (unsigned char *)service_entry; + int i; + unsigned char sum=0; + + for (i=0; i<(service_entry->length*16); i++) + { + sum=sum+p[i]; + } +// DbgPrint("sum = %d\n",sum); + if (sum==0) + { + return(TRUE); + } + return(FALSE); +} +#endif + +BOOLEAN Hal_bios32_is_service_present(ULONG service) +{ + unsigned char return_code; + unsigned int address; + unsigned int length; + unsigned int entry; + + __asm__("lcall *(%%edi)" + : "=a" (return_code), + "=b" (address), + "=c" (length), + "=d" (entry) + : "0" (service), + "1" (0), + "D" (&bios32_indirect)); + if (return_code==0) + { + return(address+entry); + } + return(0); +} + +VOID Hal_bios32_probe() +/* + * FUNCTION: Probes for an BIOS32 extension + * RETURNS: True if detected + */ +{ + DbgPrint ("Hal_bios32_probe()\n"); + + return; +#if 0 + int i; + + for (i=0xe0000;i<=0xffff0;i++) + { + bios32* service_entry = (bios32 *)physical_to_linear(i); + if ( service_entry->signature != BIOS32_SIGNATURE ) + { + continue; + } + DbgPrint("Signature detected at %x\n",i); + if (!checksum(service_entry)) + { + continue; + } + DbgPrint("ReactOS: BIOS32 detected at %x\n",i); + bios32_indirect.address = service_entry->entry; + bios32_detected=TRUE; + } +#endif +} diff --git a/reactos/hal/halx86/bus.c b/reactos/hal/halx86/bus.c new file mode 100644 index 00000000000..8f6b4446999 --- /dev/null +++ b/reactos/hal/halx86/bus.c @@ -0,0 +1,515 @@ +/* $Id: bus.c,v 1.1 2001/08/21 20:18:26 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/bus.c + * PURPOSE: Bus functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + * + * + * TODO: + * - Add bus handler functions for all busses + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define TAG_BUS TAG('B', 'U', 'S', 'H') + +KSPIN_LOCK HalpBusHandlerSpinLock = {0,}; +LIST_ENTRY HalpBusHandlerList; + + +/* FUNCTIONS *****************************************************************/ + +static NTSTATUS STDCALL +HalpNoAdjustResourceList(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PCM_RESOURCE_LIST Resources) +{ + return STATUS_UNSUCCESSFUL; +} + +static NTSTATUS STDCALL +HalpNoAssignSlotResources(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PUNICODE_STRING RegistryPath, + PUNICODE_STRING DriverClassName, + PDRIVER_OBJECT DriverObject, + PDEVICE_OBJECT DeviceObject, + ULONG SlotNumber, + PCM_RESOURCE_LIST *AllocatedResources) +{ + return STATUS_NOT_SUPPORTED; +} + +static ULONG STDCALL +HalpNoBusData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + return 0; +} + +static ULONG STDCALL +HalpNoGetInterruptVector(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity) +{ + return 0; +} + +static ULONG STDCALL +HalpNoTranslateBusAddress(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress) +{ + return 0; +} + + +PBUS_HANDLER +HalpAllocateBusHandler(INTERFACE_TYPE InterfaceType, + BUS_DATA_TYPE BusDataType, + ULONG BusNumber) +{ + PBUS_HANDLER BusHandler = NULL; + + DPRINT("HalpAllocateBusHandler()\n"); + + BusHandler = ExAllocatePoolWithTag(NonPagedPool, + sizeof(BUS_HANDLER), + TAG_BUS); + if (BusHandler == NULL) + return NULL; + + RtlZeroMemory(BusHandler, + sizeof(BUS_HANDLER)); + + InsertTailList(&HalpBusHandlerList, + &BusHandler->Entry); + + BusHandler->InterfaceType = InterfaceType; + BusHandler->BusDataType = BusDataType; + BusHandler->BusNumber = BusNumber; + + /* initialize default bus handler functions */ + BusHandler->GetBusData = HalpNoBusData; + BusHandler->SetBusData = HalpNoBusData; + BusHandler->AdjustResourceList = HalpNoAdjustResourceList; + BusHandler->AssignSlotResources = HalpNoAssignSlotResources; + BusHandler->GetInterruptVector = HalpNoGetInterruptVector; + BusHandler->TranslateBusAddress = HalpNoTranslateBusAddress; + + /* any more ?? */ + + DPRINT("HalpAllocateBusHandler() done\n"); + + return BusHandler; +} + + +VOID +HalpInitBusHandlers(VOID) +{ + PBUS_HANDLER BusHandler; + + /* general preparations */ + KeInitializeSpinLock(&HalpBusHandlerSpinLock); + InitializeListHead(&HalpBusHandlerList); + + /* initialize hal dispatch tables */ +#if 0 + + + HalDispatchTable->HalQueryBusSlots = HaliQueryBusSlots; +#endif + + /* add system bus handler */ + BusHandler = HalpAllocateBusHandler(Internal, + ConfigurationSpaceUndefined, + 0); + if (BusHandler == NULL) + return; + BusHandler->GetInterruptVector = + (pGetInterruptVector)HalpGetSystemInterruptVector; + BusHandler->TranslateBusAddress = + (pTranslateBusAddress)HalpTranslateSystemBusAddress; + + /* add cmos bus handler */ + BusHandler = HalpAllocateBusHandler(InterfaceTypeUndefined, + Cmos, + 0); + if (BusHandler == NULL) + return; + BusHandler->GetBusData = (pGetSetBusData)HalpGetCmosData; + BusHandler->SetBusData = (pGetSetBusData)HalpSetCmosData; + + /* add isa bus handler */ + BusHandler = HalpAllocateBusHandler(Isa, + ConfigurationSpaceUndefined, + 0); + if (BusHandler == NULL) + return; + + BusHandler->TranslateBusAddress = + (pTranslateBusAddress)HalpTranslateIsaBusAddress; +} + + +PBUS_HANDLER FASTCALL +HaliHandlerForBus(INTERFACE_TYPE InterfaceType, + ULONG BusNumber) +{ + PBUS_HANDLER BusHandler; + PLIST_ENTRY CurrentEntry; + KIRQL OldIrql; + + KeAcquireSpinLock(&HalpBusHandlerSpinLock, + &OldIrql); + + CurrentEntry = HalpBusHandlerList.Flink; + while (CurrentEntry != &HalpBusHandlerList) + { + BusHandler = (PBUS_HANDLER)CurrentEntry; + if (BusHandler->InterfaceType == InterfaceType && + BusHandler->BusNumber == BusNumber) + { + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + return BusHandler; + } + CurrentEntry = CurrentEntry->Flink; + } + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + + return NULL; +} + + +PBUS_HANDLER FASTCALL +HaliHandlerForConfigSpace(BUS_DATA_TYPE BusDataType, + ULONG BusNumber) +{ + PBUS_HANDLER BusHandler; + PLIST_ENTRY CurrentEntry; + KIRQL OldIrql; + + KeAcquireSpinLock(&HalpBusHandlerSpinLock, + &OldIrql); + + CurrentEntry = HalpBusHandlerList.Flink; + while (CurrentEntry != &HalpBusHandlerList) + { + BusHandler = (PBUS_HANDLER)CurrentEntry; + if (BusHandler->BusDataType == BusDataType && + BusHandler->BusNumber == BusNumber) + { + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + return BusHandler; + } + CurrentEntry = CurrentEntry->Flink; + } + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + + return NULL; +} + + +PBUS_HANDLER FASTCALL +HaliReferenceHandlerForBus(INTERFACE_TYPE InterfaceType, + ULONG BusNumber) +{ + PBUS_HANDLER BusHandler; + PLIST_ENTRY CurrentEntry; + KIRQL OldIrql; + + KeAcquireSpinLock(&HalpBusHandlerSpinLock, + &OldIrql); + + CurrentEntry = HalpBusHandlerList.Flink; + while (CurrentEntry != &HalpBusHandlerList) + { + BusHandler = (PBUS_HANDLER)CurrentEntry; + if (BusHandler->InterfaceType == InterfaceType && + BusHandler->BusNumber == BusNumber) + { + BusHandler->RefCount++; + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + return BusHandler; + } + CurrentEntry = CurrentEntry->Flink; + } + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + + return NULL; +} + + +PBUS_HANDLER FASTCALL +HaliReferenceHandlerForConfigSpace(BUS_DATA_TYPE BusDataType, + ULONG BusNumber) +{ + PBUS_HANDLER BusHandler; + PLIST_ENTRY CurrentEntry; + KIRQL OldIrql; + + KeAcquireSpinLock(&HalpBusHandlerSpinLock, + &OldIrql); + + CurrentEntry = HalpBusHandlerList.Flink; + while (CurrentEntry != &HalpBusHandlerList) + { + BusHandler = (PBUS_HANDLER)CurrentEntry; + if (BusHandler->BusDataType == BusDataType && + BusHandler->BusNumber == BusNumber) + { + BusHandler->RefCount++; + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + return BusHandler; + } + CurrentEntry = CurrentEntry->Flink; + } + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); + + return NULL; +} + + +VOID FASTCALL +HaliDereferenceBusHandler(PBUS_HANDLER BusHandler) +{ + KIRQL OldIrql; + + KeAcquireSpinLock(&HalpBusHandlerSpinLock, + &OldIrql); + BusHandler->RefCount--; + KeReleaseSpinLock(&HalpBusHandlerSpinLock, + OldIrql); +} + + +NTSTATUS STDCALL +HalAdjustResourceList(PCM_RESOURCE_LIST Resources) +{ + PBUS_HANDLER BusHandler; + NTSTATUS Status; + + BusHandler = HaliReferenceHandlerForBus(Resources->List[0].InterfaceType, + Resources->List[0].BusNumber); + if (BusHandler == NULL) + return STATUS_SUCCESS; + + Status = BusHandler->AdjustResourceList(BusHandler, + Resources->List[0].BusNumber, + Resources); + HaliDereferenceBusHandler (BusHandler); + + return Status; +} + + +NTSTATUS STDCALL +HalAssignSlotResources(PUNICODE_STRING RegistryPath, + PUNICODE_STRING DriverClassName, + PDRIVER_OBJECT DriverObject, + PDEVICE_OBJECT DeviceObject, + INTERFACE_TYPE BusType, + ULONG BusNumber, + ULONG SlotNumber, + PCM_RESOURCE_LIST *AllocatedResources) +{ + PBUS_HANDLER BusHandler; + NTSTATUS Status; + + BusHandler = HaliReferenceHandlerForBus(BusType, + BusNumber); + if (BusHandler == NULL) + return STATUS_NOT_FOUND; + + Status = BusHandler->AssignSlotResources(BusHandler, + BusNumber, + RegistryPath, + DriverClassName, + DriverObject, + DeviceObject, + SlotNumber, + AllocatedResources); + + HaliDereferenceBusHandler(BusHandler); + + return Status; +} + + +ULONG STDCALL +HalGetBusData(BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Length) +{ + return (HalGetBusDataByOffset(BusDataType, + BusNumber, + SlotNumber, + Buffer, + 0, + Length)); +} + + +ULONG STDCALL +HalGetBusDataByOffset(BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PBUS_HANDLER BusHandler; + ULONG Result; + + BusHandler = HaliReferenceHandlerForConfigSpace(BusDataType, + BusNumber); + if (BusHandler == NULL) + return 0; + + Result = BusHandler->GetBusData(BusHandler, + BusNumber, + SlotNumber, + Buffer, + Offset, + Length); + + HaliDereferenceBusHandler (BusHandler); + + return Result; +} + + +ULONG STDCALL +HalGetInterruptVector(INTERFACE_TYPE InterfaceType, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity) +{ + PBUS_HANDLER BusHandler; + ULONG Result; + + BusHandler = HaliReferenceHandlerForBus(InterfaceType, + BusNumber); + if (BusHandler == NULL) + return 0; + + Result = BusHandler->GetInterruptVector(BusHandler, + BusNumber, + BusInterruptLevel, + BusInterruptVector, + Irql, + Affinity); + + HaliDereferenceBusHandler(BusHandler); + + return Result; +} + + +ULONG STDCALL +HalSetBusData(BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Length) +{ + return (HalSetBusDataByOffset(BusDataType, + BusNumber, + SlotNumber, + Buffer, + 0, + Length)); +} + + +ULONG STDCALL +HalSetBusDataByOffset(BUS_DATA_TYPE BusDataType, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PBUS_HANDLER BusHandler; + ULONG Result; + + BusHandler = HaliReferenceHandlerForConfigSpace(BusDataType, + BusNumber); + if (BusHandler == NULL) + return 0; + + Result = BusHandler->SetBusData(BusHandler, + BusNumber, + SlotNumber, + Buffer, + Offset, + Length); + + HaliDereferenceBusHandler(BusHandler); + + return Result; +} + + +BOOLEAN STDCALL +HalTranslateBusAddress(INTERFACE_TYPE InterfaceType, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress) +{ + PBUS_HANDLER BusHandler; + BOOLEAN Result; + + BusHandler = HaliReferenceHandlerForBus(InterfaceType, + BusNumber); + if (BusHandler == NULL) + return FALSE; + + Result = BusHandler->TranslateBusAddress(BusHandler, + BusNumber, + BusAddress, + AddressSpace, + TranslatedAddress); + + HaliDereferenceBusHandler(BusHandler); + + return Result; +} + +/* EOF */ diff --git a/reactos/hal/halx86/display.c b/reactos/hal/halx86/display.c new file mode 100644 index 00000000000..ce070d968a1 --- /dev/null +++ b/reactos/hal/halx86/display.c @@ -0,0 +1,293 @@ +/* $Id: display.c,v 1.1 2001/08/21 20:18:26 chorns Exp $ + * + * 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@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * Created 08/10/99 + */ + +#include +#include + +#define SCREEN_SYNCHRONIZATION + + +#define CRTC_COMMAND 0x3d4 +#define CRTC_DATA 0x3d5 + +#define CRTC_COLUMNS 0x01 +#define CRTC_OVERFLOW 0x07 +#define CRTC_ROWS 0x12 +#define CRTC_SCANLINES 0x09 + +#define CRTC_CURHI 0x0e +#define CRTC_CURLO 0x0f + + +#define CHAR_ATTRIBUTE 0x17 /* grey on blue */ + + +/* 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 WORD *VideoBuffer = NULL; + +static PHAL_RESET_DISPLAY_PARAMETERS HalResetDisplayParameters = NULL; + + +/* STATIC FUNCTIONS *********************************************************/ + +static VOID +HalClearDisplay (VOID) +{ + WORD *ptr = (WORD*)VideoBuffer; + ULONG i; + + for (i = 0; i < SizeX * SizeY; i++, ptr++) + *ptr = ((CHAR_ATTRIBUTE << 8) + ' '); + + CursorX = 0; + CursorY = 0; +} + + +VOID +HalScrollDisplay (VOID) +{ + WORD *ptr; + int i; + + ptr = VideoBuffer + SizeX; + RtlMoveMemory (VideoBuffer, + ptr, + SizeX * (SizeY - 1) * 2); + + ptr = VideoBuffer + (SizeX * (SizeY - 1)); + for (i = 0; i < SizeX; i++, ptr++) + { + *ptr = (CHAR_ATTRIBUTE << 8) + ' '; + } +} + + +static VOID +HalPutCharacter (CHAR Character) +{ + WORD *ptr; + + ptr = VideoBuffer + ((CursorY * SizeX) + CursorX); + *ptr = (CHAR_ATTRIBUTE << 8) + Character; +} + + +/* PRIVATE FUNCTIONS ********************************************************/ + +VOID +HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock) +/* + * FUNCTION: Initalize the display + * ARGUMENTS: + * InitParameters = Parameters setup by the boot loader + */ +{ + if (DisplayInitialized == FALSE) + { + ULONG ScanLines; + ULONG Data; + + VideoBuffer = (WORD *)(0xd0000000 + 0xb8000); +// VideoBuffer = HalMapPhysicalMemory (0xb8000, 2); + + /* Set cursor position */ +// CursorX = LoaderBlock->cursorx; +// CursorY = LoaderBlock->cursory; + CursorX = 0; + CursorY = 0; + + /* read screen size from the crtc */ + /* FIXME: screen size should be read from the boot parameters */ + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_COLUMNS); + SizeX = READ_PORT_UCHAR((PUCHAR)CRTC_DATA) + 1; + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_ROWS); + SizeY = READ_PORT_UCHAR((PUCHAR)CRTC_DATA); + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_OVERFLOW); + Data = READ_PORT_UCHAR((PUCHAR)CRTC_DATA); + SizeY |= (((Data & 0x02) << 7) | ((Data & 0x40) << 3)); + SizeY++; + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_SCANLINES); + ScanLines = (READ_PORT_UCHAR((PUCHAR)CRTC_DATA) & 0x1F) + 1; + SizeY = SizeY / ScanLines; + +#ifdef BOCHS_30ROWS +SizeY=30; +#endif + HalClearDisplay (); + + DisplayInitialized = TRUE; + } +} + + +VOID +HalResetDisplay (VOID) +/* + * FUNCTION: Reset the display + * ARGUMENTS: + * None + */ +{ + if (HalResetDisplayParameters == NULL) + return; + + if (HalOwnsDisplay == TRUE) + return; + + if (HalResetDisplayParameters(SizeX, SizeY) == TRUE) + { + HalOwnsDisplay = TRUE; + HalClearDisplay (); + } +} + + +/* PUBLIC FUNCTIONS *********************************************************/ + +VOID +STDCALL +HalAcquireDisplayOwnership ( + IN PHAL_RESET_DISPLAY_PARAMETERS ResetDisplayParameters + ) +/* + * FUNCTION: + * ARGUMENTS: + * ResetDisplayParameters = Pointer to a driver specific + * reset routine. + */ +{ + HalOwnsDisplay = FALSE; + HalResetDisplayParameters = ResetDisplayParameters; +} + + +VOID STDCALL +HalDisplayString (IN PCH String) +/* + * FUNCTION: Switches the screen to HAL console mode (BSOD) if not there + * already and displays a string + * ARGUMENT: + * string = ASCII string to display + * NOTE: Use with care because there is no support for returning from BSOD + * mode + */ +{ + PCH pch; +#ifdef SCREEN_SYNCHRONIZATION + int offset; +#endif + static KSPIN_LOCK Lock; + ULONG Flags; + + pch = String; + + pushfl(Flags); + __asm__ ("cli\n\t"); + KeAcquireSpinLockAtDpcLevel(&Lock); + + if (HalOwnsDisplay == FALSE) + { + HalResetDisplay (); + } + +#ifdef SCREEN_SYNCHRONIZATION + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURHI); + offset = READ_PORT_UCHAR((PUCHAR)CRTC_DATA)<<8; + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURLO); + offset += READ_PORT_UCHAR((PUCHAR)CRTC_DATA); + + CursorY = offset / SizeX; + CursorX = offset % SizeX; +#endif + + while (*pch != 0) + { + if (*pch == '\n') + { + CursorY++; + CursorX = 0; + } + else + { + HalPutCharacter (*pch); + CursorX++; + + if (CursorX >= SizeX) + { + CursorY++; + CursorX = 0; + } + } + + if (CursorY >= SizeY) + { + HalScrollDisplay (); + CursorY = SizeY - 1; + } + + pch++; + } + +#ifdef SCREEN_SYNCHRONIZATION + offset = (CursorY * SizeX) + CursorX; + + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURLO); + WRITE_PORT_UCHAR((PUCHAR)CRTC_DATA, offset & 0xff); + WRITE_PORT_UCHAR((PUCHAR)CRTC_COMMAND, CRTC_CURHI); + WRITE_PORT_UCHAR((PUCHAR)CRTC_DATA, (offset >> 8) & 0xff); +#endif + KeReleaseSpinLockFromDpcLevel(&Lock); + popfl(Flags); +} + + +VOID +STDCALL +HalQueryDisplayParameters ( + PULONG DispSizeX, + PULONG DispSizeY, + PULONG CursorPosX, + PULONG CursorPosY + ) +{ + if (DispSizeX) + *DispSizeX = SizeX; + if (DispSizeY) + *DispSizeY = SizeY; + if (CursorPosX) + *CursorPosX = CursorX; + if (CursorPosY) + *CursorPosY = CursorY; +} + + +VOID +STDCALL +HalSetDisplayParameters ( + ULONG CursorPosX, + ULONG CursorPosY + ) +{ + CursorX = (CursorPosX < SizeX) ? CursorPosX : SizeX - 1; + CursorY = (CursorPosY < SizeY) ? CursorPosY : SizeY - 1; +} + +/* EOF */ diff --git a/reactos/hal/halx86/dma.c b/reactos/hal/halx86/dma.c new file mode 100644 index 00000000000..4fdc6c4b203 --- /dev/null +++ b/reactos/hal/halx86/dma.c @@ -0,0 +1,115 @@ +/* $Id: dma.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/dma.c + * PURPOSE: DMA functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include +#include + +ADAPTER_OBJECT AdapterObjects[] = { + { 0, (PVOID)0x87, (PVOID)0x1, (PVOID)0x0, { 0 }, NULL }, + { 1, (PVOID)0x83, (PVOID)0x3, (PVOID)0x2, { 0 }, NULL }, + { 2, (PVOID)0x81, (PVOID)0x5, (PVOID)0x4, { 0 }, NULL }, + { 3, (PVOID)0x82, (PVOID)0x7, (PVOID)0x6, { 0 }, NULL } }; + + +/* FUNCTIONS *****************************************************************/ + +PVOID STDCALL +HalAllocateCommonBuffer (PADAPTER_OBJECT AdapterObject, + ULONG Length, + PPHYSICAL_ADDRESS LogicalAddress, + BOOLEAN CacheEnabled) +/* + * FUNCTION: Allocates memory that is visible to both the processor(s) and + * a dma device + * ARGUMENTS: + * AdapterObject = Adapter object representing the bus master or + * system dma controller + * Length = Number of bytes to allocate + * LogicalAddress = Logical address the driver can use to access the + * buffer + * CacheEnabled = Specifies if the memory can be cached + * RETURNS: The base virtual address of the memory allocated + * NULL on failure + */ +{ + UNIMPLEMENTED; +} + +BOOLEAN STDCALL +HalFlushCommonBuffer (ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3, + ULONG Unknown4, + ULONG Unknown5, + ULONG Unknown6, + ULONG Unknown7, + ULONG Unknown8) +{ + return TRUE; +} + +VOID STDCALL +HalFreeCommonBuffer (PADAPTER_OBJECT AdapterObject, + ULONG Length, + PHYSICAL_ADDRESS LogicalAddress, + PVOID VirtualAddress, + BOOLEAN CacheEnabled) +{ + MmFreeContiguousMemory(VirtualAddress); +} + +PADAPTER_OBJECT STDCALL +HalGetAdapter (PDEVICE_DESCRIPTION DeviceDescription, + PULONG NumberOfMapRegisters) +/* + * FUNCTION: Returns a pointer to an adapter object for the DMA device + * defined in the device description structure + * ARGUMENTS: + * DeviceDescription = Structure describing the attributes of the device + * NumberOfMapRegisters (OUT) = Returns the maximum number of map + * registers the device driver can + * allocate for DMA transfer operations + * RETURNS: The allocated adapter object on success + * NULL on failure + */ +{ + /* Validate parameters in device description, and return a pointer to + the adapter object for the requested dma channel */ + if( DeviceDescription->Version != DEVICE_DESCRIPTION_VERSION ) + return NULL; + if( DeviceDescription->Master ) + return NULL; + if( DeviceDescription->ScatterGather ) + return NULL; + if( DeviceDescription->AutoInitialize ) + return NULL; + if( DeviceDescription->Dma32BitAddress ) + return NULL; + if( DeviceDescription->InterfaceType != Isa ) + return NULL; + /* if( DeviceDescription->DmaWidth != Width8Bits ) + return NULL;*/ + *NumberOfMapRegisters = 0x10; + AdapterObjects[DeviceDescription->DmaChannel].Buffer = 0; + return &AdapterObjects[DeviceDescription->DmaChannel]; +} + +ULONG STDCALL +HalReadDmaCounter (PADAPTER_OBJECT AdapterObject) +{ + UNIMPLEMENTED; +} + +/* EOF */ diff --git a/reactos/hal/halx86/drive.c b/reactos/hal/halx86/drive.c new file mode 100644 index 00000000000..17287fefcba --- /dev/null +++ b/reactos/hal/halx86/drive.c @@ -0,0 +1,31 @@ +/* $Id: drive.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: hal/x86/drive.c + * PURPOSE: Drive letter assignment + * PROGRAMMER: + * UPDATE HISTORY: + * 2000-03-25 + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +/* FUNCTIONS *****************************************************************/ + +VOID STDCALL +IoAssignDriveLetters(IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN PSTRING NtDeviceName, + OUT PUCHAR NtSystemPath, + OUT PSTRING NtSystemPathString) +{ + HalDispatchTable.HalIoAssignDriveLetters(LoaderBlock, + NtDeviceName, + NtSystemPath, + NtSystemPathString); +} + +/* EOF */ diff --git a/reactos/hal/halx86/enum.c b/reactos/hal/halx86/enum.c new file mode 100644 index 00000000000..e2a75abeefd --- /dev/null +++ b/reactos/hal/halx86/enum.c @@ -0,0 +1,34 @@ +/* $Id: enum.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * 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 +#include + +#define NDEBUG +#include + +VOID +HalpStartEnumerator (VOID) +{ +#ifdef ACPI + + UNICODE_STRING DriverName; + + RtlInitUnicodeString(&DriverName, + L"\\SystemRoot\\system32\\drivers\\acpi.sys"); + NtLoadDriver(&DriverName); + +#endif /* ACPI */ +} + +/* EOF */ diff --git a/reactos/hal/halx86/fmutex.c b/reactos/hal/halx86/fmutex.c new file mode 100644 index 00000000000..c840382d30e --- /dev/null +++ b/reactos/hal/halx86/fmutex.c @@ -0,0 +1,60 @@ +/* $Id: fmutex.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/fmutex.c + * PURPOSE: Implements fast mutexes + * PROGRAMMER: David Welch (welch@cwcom.net) + * Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * Created 09/06/2000 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID FASTCALL +ExAcquireFastMutex (PFAST_MUTEX FastMutex) +{ + KeEnterCriticalRegion(); + if (InterlockedDecrement(&(FastMutex->Count))==0) + { + return; + } + FastMutex->Contention++; + KeWaitForSingleObject(&(FastMutex->Event), + Executive, + KernelMode, + FALSE, + NULL); + FastMutex->Owner=KeGetCurrentThread(); +} + + +VOID FASTCALL +ExReleaseFastMutex (PFAST_MUTEX FastMutex) +{ + assert(FastMutex->Owner == KeGetCurrentThread()); + FastMutex->Owner=NULL; + if (InterlockedIncrement(&(FastMutex->Count))<=0) + { + return; + } + KeSetEvent(&(FastMutex->Event),0,FALSE); + + KeLeaveCriticalRegion(); +} + + +BOOLEAN FASTCALL +ExTryToAcquireFastMutex (PFAST_MUTEX FastMutex) +{ + UNIMPLEMENTED; +} + +/* EOF */ diff --git a/reactos/hal/halx86/halinit.c b/reactos/hal/halx86/halinit.c new file mode 100644 index 00000000000..24f871ab7d6 --- /dev/null +++ b/reactos/hal/halx86/halinit.c @@ -0,0 +1,71 @@ +/* $Id: halinit.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * 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 +#include +#include +#include + +#ifdef MP +#include +#endif /* MP */ + +#define NDEBUG +#include + +/* FUNCTIONS ***************************************************************/ + +NTSTATUS +STDCALL +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +{ + return STATUS_SUCCESS; +} + +BOOLEAN STDCALL +HalInitSystem (ULONG BootPhase, + PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + if (BootPhase == 0) + { + HalInitializeDisplay (LoaderBlock); + +#ifdef MP + + HalpInitMPS(); + +#else + + HalpInitPICs(); + + /* Setup busy waiting */ + HalpCalibrateStallExecution(); + +#endif /* MP */ + + } + else if (BootPhase == 1) + { + HalpInitBusHandlers (); + HalpCalibrateStallExecution (); + + /* Enumerate the devices on the motherboard */ + HalpStartEnumerator(); + } + + return TRUE; +} + +/* EOF */ diff --git a/reactos/hal/halx86/halx86mp.rc b/reactos/hal/halx86/halx86mp.rc new file mode 100644 index 00000000000..9f302cdbfe8 --- /dev/null +++ b/reactos/hal/halx86/halx86mp.rc @@ -0,0 +1,37 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "X86 Multiprocessor Hardware Abstraction Layer\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "halx86mp\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "halx86mp.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END \ No newline at end of file diff --git a/reactos/hal/halx86/halx86up.rc b/reactos/hal/halx86/halx86up.rc new file mode 100644 index 00000000000..b2566b85695 --- /dev/null +++ b/reactos/hal/halx86/halx86up.rc @@ -0,0 +1,37 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "X86 Uniprocessor Hardware Abstraction Layer\0" + VALUE "FileVersion", "0.0.0\0" + VALUE "InternalName", "halx86up\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "halx86up.dll\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END \ No newline at end of file diff --git a/reactos/hal/halx86/include/bus.h b/reactos/hal/halx86/include/bus.h new file mode 100644 index 00000000000..5fb87c56bac --- /dev/null +++ b/reactos/hal/halx86/include/bus.h @@ -0,0 +1,121 @@ +/* + + */ + +#ifndef __INTERNAL_HAL_BUS_H +#define __INTERNAL_HAL_BUS_H + +struct _BUS_HANDLER; + +typedef NTSTATUS (STDCALL *pAdjustResourceList) ( + IN struct _BUS_HANDLER *BusHandler, + IN ULONG BusNumber, + IN OUT PCM_RESOURCE_LIST Resources + ); + +typedef NTSTATUS (STDCALL *pAssignSlotResources) ( + IN struct _BUS_HANDLER *BusHandler, + IN ULONG BusNumber, + IN PUNICODE_STRING RegistryPath, + IN PUNICODE_STRING DriverClassName, + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT DeviceObject, + IN ULONG SlotNumber, + IN OUT PCM_RESOURCE_LIST *AllocatedResources + ); + +typedef ULONG (STDCALL *pGetSetBusData) ( + IN struct _BUS_HANDLER *BusHandler, + IN ULONG BusNumber, + IN ULONG SlotNumber, + OUT PVOID Buffer, + IN ULONG Offset, + IN ULONG Length + ); + +typedef ULONG (STDCALL *pGetInterruptVector) ( + IN struct _BUS_HANDLER *BusHandler, + IN ULONG BusNumber, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +typedef ULONG (STDCALL *pTranslateBusAddress) ( + IN struct _BUS_HANDLER *BusHandler, + IN ULONG BusNumber, + IN PHYSICAL_ADDRESS BusAddress, + IN OUT PULONG AddressSpace, + OUT PPHYSICAL_ADDRESS TranslatedAddress + ); + +typedef struct _BUS_HANDLER +{ + LIST_ENTRY Entry; + INTERFACE_TYPE InterfaceType; + BUS_DATA_TYPE BusDataType; + ULONG BusNumber; + ULONG RefCount; + + pGetSetBusData GetBusData; + pGetSetBusData SetBusData; + pAdjustResourceList AdjustResourceList; + pAssignSlotResources AssignSlotResources; + pGetInterruptVector GetInterruptVector; + pTranslateBusAddress TranslateBusAddress; +} BUS_HANDLER, *PBUS_HANDLER; + + +/* FUNCTIONS *****************************************************************/ + +/* bus.c */ +PBUS_HANDLER +HalpAllocateBusHandler(INTERFACE_TYPE InterfaceType, + BUS_DATA_TYPE BusDataType, + ULONG BusNumber); + +/* sysbus.h */ +ULONG STDCALL +HalpGetSystemInterruptVector(PVOID BusHandler, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity); + +BOOLEAN STDCALL +HalpTranslateSystemBusAddress(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress); + +/* isa.c */ +BOOLEAN STDCALL +HalpTranslateIsaBusAddress(PBUS_HANDLER BusHandler, + ULONG BusNumber, + PHYSICAL_ADDRESS BusAddress, + PULONG AddressSpace, + PPHYSICAL_ADDRESS TranslatedAddress); + +/* time.c */ +ULONG STDCALL +HalpGetCmosData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length); + +ULONG STDCALL +HalpSetCmosData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length); + +#endif /* __INTERNAL_HAL_BUS_H */ + +/* EOF */ \ No newline at end of file diff --git a/reactos/hal/halx86/include/hal.h b/reactos/hal/halx86/include/hal.h new file mode 100644 index 00000000000..704c2b3cf10 --- /dev/null +++ b/reactos/hal/halx86/include/hal.h @@ -0,0 +1,48 @@ +/* + * + */ + +#ifndef __INTERNAL_HAL_HAL_H +#define __INTERNAL_HAL_HAL_H + +//#include +//#include + +/* + * FUNCTION: Probes for a BIOS32 extension + */ +VOID Hal_bios32_probe(VOID); + +/* + * FUNCTION: Determines if a a bios32 service is present + */ +BOOLEAN Hal_bios32_is_service_present(ULONG service); + +VOID HalInitializeDisplay (PLOADER_PARAMETER_BLOCK LoaderBlock); +VOID HalResetDisplay (VOID); + +VOID HalpInitBusHandlers (VOID); + +/* irql.c */ +VOID HalpInitPICs(VOID); + +/* udelay.c */ +VOID HalpCalibrateStallExecution(VOID); + +/* pci.c */ +VOID HalpInitPciBus (VOID); + +/* enum.c */ +VOID HalpStartEnumerator (VOID); + +struct _ADAPTER_OBJECT { + int Channel; + PVOID PagePort; + PVOID CountPort; + PVOID OffsetPort; + KSPIN_LOCK SpinLock; + PVOID Buffer; + BOOLEAN Inuse; +}; + +#endif /* __INTERNAL_HAL_HAL_H */ diff --git a/reactos/hal/halx86/include/mps.h b/reactos/hal/halx86/include/mps.h new file mode 100644 index 00000000000..6fc8e47ccb2 --- /dev/null +++ b/reactos/hal/halx86/include/mps.h @@ -0,0 +1,435 @@ +#ifndef __INCLUDE_HAL_MPS +#define __INCLUDE_HAL_MPS + +#define APIC_DEFAULT_BASE 0xFEE00000 /* Default Local APIC Base Register Address */ +#define IOAPIC_DEFAULT_BASE 0xFEC00000 /* Default I/O 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_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 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_TARGET_SELF 0x100 +#define APIC_TARGET_ALL 0x200 +#define APIC_TARGET_ALL_BUT_SELF 0x300 + +#define IPI_CACHE_FLUSH 0x40 +#define IPI_INV_TLB 0x41 +#define IPI_INV_PTE 0x42 +#define IPI_INV_RESCHED 0x43 +#define IPI_STOP 0x44 + + +#define APIC_INTEGRATED(version) (version & 0xF0) + + +/* 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) */ + +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; +} __attribute__ ((packed)) IOAPIC_ROUTE_ENTRY, *PIOAPIC_ROUTE_ENTRY; + +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; + + +/* + * 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 CALL_FUNCTION_VECTOR 0xFB +#define RESCHEDULE_VECTOR 0xFC +#define INVALIDATE_TLB_VECTOR 0xFD +#define ERROR_VECTOR 0xFE +#define SPURIOUS_VECTOR 0xFF /* Must be 0xXF */ + +/* + * First APIC vector available to drivers: (vectors 0x30-0xEE) + * we start at 0x31 to spread out vectors evenly between priority + * levels. + */ +#define FIRST_DEVICE_VECTOR 0x31 +#define FIRST_SYSTEM_VECTOR 0xEF +#define NUMBER_DEVICE_VECTORS (FIRST_SYSTEM_VECTOR - FIRST_DEVICE_VECTOR) + + +/* MP Floating Pointer Structure */ +#define MPF_SIGNATURE (('_' << 24) | ('P' << 16) | ('M' << 8) | '_') + +typedef struct __attribute__((packed)) _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) */ +} __attribute__((packed)) 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 __attribute__((packed)) _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 */ +} __attribute__((packed)) 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 __attribute__((packed)) _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) */ +} __attribute__((packed)) MP_CONFIGURATION_PROCESSOR, + *PMP_CONFIGURATION_PROCESSOR; + +#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 + + +typedef struct __attribute__((packed)) _MP_CONFIGURATION_BUS +{ + UCHAR Type; /* 1 */ + UCHAR BusId; /* Bus ID */ + UCHAR BusType[6]; /* Bus type */ +} __attribute__((packed)) 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 __attribute__((packed)) _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 */ +} __attribute__((packed)) MP_CONFIGURATION_IOAPIC, *PMP_CONFIGURATION_IOAPIC; + +#define MAX_IOAPIC 2 + +#define MP_IOAPIC_USABLE 0x01 + + +typedef struct __attribute__((packed)) _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 */ +} __attribute__((packed)) 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 __attribute__((packed)) _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; + +#define MP_APIC_ALL 0xFF + + +static inline VOID ReadPentiumClock(PULARGE_INTEGER Count) +{ + register ULONG nLow; + register ULONG nHigh; + + __asm__ __volatile__ ("rdtsc" : "=a" (nLow), "=d" (nHigh)); + + Count->u.LowPart = nLow; + Count->u.HighPart = nHigh; +} + + +#define MAX_CPU 32 + + +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; + +/* 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 */ + + +typedef enum { + amPIC = 0, /* IMCR and PIC compatibility mode */ + amVWIRE /* Virtual Wire compatibility mode */ +} APIC_MODE; + + +#define pushfl(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */) +#define popfl(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory") + + +#define PIC_IRQS 16 + +/* Prototypes */ + +VOID HalpInitMPS(VOID); +volatile ULONG IOAPICRead(ULONG Apic, ULONG Offset); +VOID IOAPICWrite(ULONG Apic, ULONG Offset, ULONG Value); +VOID IOAPICMaskIrq(ULONG Apic, ULONG Irq); +VOID IOAPICUnmaskIrq(ULONG Apic, ULONG Irq); +volatile inline ULONG APICRead(ULONG Offset); +inline VOID APICWrite(ULONG Offset, ULONG Value); +inline VOID APICSendEOI(VOID); +inline ULONG ThisCPU(VOID); +VOID APICSendIPI(ULONG Target, + ULONG DeliveryMode, + ULONG IntNum, + ULONG Level); +/* For debugging */ +VOID IOAPICDump(VOID); +VOID APICDump(VOID); + +#endif /* __INCLUDE_HAL_MPS */ + +/* EOF */ diff --git a/reactos/hal/halx86/irql.c b/reactos/hal/halx86/irql.c new file mode 100644 index 00000000000..328a8eba822 --- /dev/null +++ b/reactos/hal/halx86/irql.c @@ -0,0 +1,451 @@ +/* + * 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 +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +/* FIXME: this should be in a header file */ +#define NR_IRQS (16) +#define IRQ_BASE (0x40) + +/* + * PURPOSE: Current irq level + */ +static KIRQL CurrentIrql = HIGH_LEVEL; + +extern IMPORTED ULONG DpcQueueSize; + +static VOID KeSetCurrentIrql(KIRQL newlvl); + +#define DIRQL_TO_IRQ(x) (PROFILE_LEVEL - x) +#define IRQ_TO_DIRQL(x) (PROFILE_LEVEL - x) + +/* FUNCTIONS ****************************************************************/ + +VOID HalpInitPICs(VOID) +{ + /* Initialization sequence */ + WRITE_PORT_UCHAR((PUCHAR)0x20, 0x11); + WRITE_PORT_UCHAR((PUCHAR)0xa0, 0x11); + /* Start of hardware irqs (0x24) */ + WRITE_PORT_UCHAR((PUCHAR)0x21, 0x40); + WRITE_PORT_UCHAR((PUCHAR)0xa1, 0x48); + /* 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); + /* Mask off all interrupts from PICs */ + WRITE_PORT_UCHAR((PUCHAR)0x21, 0xff); + WRITE_PORT_UCHAR((PUCHAR)0xa1, 0xff); + + /* We can know enable interrupts */ + __asm__ __volatile__ ("sti\n\t"); +} + +static ULONG +HiSetCurrentPICMask(unsigned int mask) +{ + WRITE_PORT_UCHAR((PUCHAR)0x21,mask & 0xff); + WRITE_PORT_UCHAR((PUCHAR)0xa1,(mask >> 8) & 0xff); + + return mask; +} + +static VOID HiSwitchIrql(KIRQL oldIrql) +/* + * FUNCTION: Switches to the current irql + * NOTE: Must be called with interrupt disabled + */ +{ + unsigned int i; + PKTHREAD CurrentThread; + + CurrentThread = KeGetCurrentThread(); + + /* + * Disable all interrupts + */ + if (CurrentIrql >= IPI_LEVEL) + { + HiSetCurrentPICMask(0xFFFF); + __asm__("sti\n\t"); + return; + } + + /* + * Disable all interrupts but the timer + */ + if (CurrentIrql == PROFILE_LEVEL || + CurrentIrql == CLOCK1_LEVEL || + CurrentIrql == CLOCK2_LEVEL) + { + HiSetCurrentPICMask(0xFFFE); + __asm__("sti\n\t"); + return; + } + + /* + * Disable all interrupts of lesser priority + */ + if (CurrentIrql > DISPATCH_LEVEL) + { + unsigned int current_mask = 0; + + for (i = CurrentIrql; i > (PROFILE_LEVEL - 15); i--) + { + current_mask = current_mask | (1 << (PROFILE_LEVEL - i)); + } + + HiSetCurrentPICMask(current_mask); + __asm__("sti\n\t"); + return; + } + + /* + * Enable all interrupts + */ + if (CurrentIrql == DISPATCH_LEVEL) + { + HiSetCurrentPICMask(0); + __asm__("sti\n\t"); + return; + } + + /* + * APCs are disabled but execute any pending DPCs + */ + if (CurrentIrql == APC_LEVEL) + { + HiSetCurrentPICMask(0); + __asm__("sti\n\t"); + if (DpcQueueSize > 0) + { + CurrentIrql = DISPATCH_LEVEL; + KiDispatchInterrupt(); + CurrentIrql = APC_LEVEL; + } + return; + } + + /* + * Execute any pending DPCs or APCs + */ + if (CurrentIrql == PASSIVE_LEVEL) + { + if (DpcQueueSize > 0) + { + CurrentIrql = DISPATCH_LEVEL; + KiDispatchInterrupt(); + CurrentIrql = PASSIVE_LEVEL; + } + if (CurrentThread != NULL && + CurrentThread->ApcState.KernelApcPending) + { + CurrentIrql = APC_LEVEL; + KiDeliverApc(0, 0, 0); + CurrentIrql = PASSIVE_LEVEL; + } + } +} + + +KIRQL STDCALL +KeGetCurrentIrql (VOID) +/* + * PURPOSE: Returns the current irq level + * RETURNS: The current irq level + */ +{ + return(CurrentIrql); +} + + +STATIC VOID +KeSetCurrentIrql(KIRQL newlvl) +/* + * PURPOSE: Sets the current irq level without taking any action + */ +{ + CurrentIrql = newlvl; +} + + +/********************************************************************** + * 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) +{ + KIRQL OldIrql; + + __asm__("cli\n\t"); + + DPRINT("KfLowerIrql(NewIrql %d)\n", NewIrql); + + if (NewIrql > CurrentIrql) + { + DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n", + __FILE__, __LINE__, NewIrql, CurrentIrql); + KeBugCheck(0); + for(;;); + } + + OldIrql = CurrentIrql; + CurrentIrql = NewIrql; + HiSwitchIrql(OldIrql); +} + + +/********************************************************************** + * NAME EXPORTED + * KeLowerIrql + * + * DESCRIPTION + * Restores the irq level on the current processor + * + * ARGUMENTS + * NewIrql = Irql to lower to + * + * RETURN VALUE + * None + * + * NOTES + */ + +VOID STDCALL +KeLowerIrql (KIRQL NewIrql) +{ + KfLowerIrql (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 < CurrentIrql) + { + DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n", + __FILE__,__LINE__,CurrentIrql,NewIrql); + KeBugCheck (0); + for(;;); + } + + __asm__("cli\n\t"); + OldIrql = CurrentIrql; + CurrentIrql = NewIrql; + + DPRINT ("NewIrql %x OldIrql %x CurrentIrql %x\n", + NewIrql, OldIrql, CurrentIrql); + HiSwitchIrql(OldIrql); + + return OldIrql; +} + + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrql + * + * DESCRIPTION + * Raises the hardware priority (irql) + * + * ARGUMENTS + * NewIrql = Irql to raise to + * OldIrql (OUT) = Caller supplied storage for the previous irql + * + * RETURN VALUE + * None + * + * NOTES + * Calls KfRaiseIrql + */ +VOID STDCALL +KeRaiseIrql (KIRQL NewIrql, + PKIRQL OldIrql) +{ + *OldIrql = KfRaiseIrql (NewIrql); +} + + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrqlToDpcLevel + * + * DESCRIPTION + * Raises the hardware priority (irql) to DISPATCH level + * + * ARGUMENTS + * None + * + * RETURN VALUE + * Previous irq level + * + * NOTES + * Calls KfRaiseIrql + */ + +KIRQL STDCALL +KeRaiseIrqlToDpcLevel (VOID) +{ + return KfRaiseIrql (DISPATCH_LEVEL); +} + + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrqlToSynchLevel + * + * DESCRIPTION + * Raises the hardware priority (irql) to CLOCK2 level + * + * ARGUMENTS + * None + * + * RETURN VALUE + * Previous irq level + * + * NOTES + * Calls KfRaiseIrql + */ + +KIRQL STDCALL +KeRaiseIrqlToSynchLevel (VOID) +{ + return KfRaiseIrql (CLOCK2_LEVEL); +} + + +BOOLEAN STDCALL +HalBeginSystemInterrupt (ULONG Vector, + KIRQL Irql, + PKIRQL OldIrql) +{ + if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS) + return FALSE; + + /* Send EOI to the PICs */ + WRITE_PORT_UCHAR((PUCHAR)0x20,0x20); + if ((Vector-IRQ_BASE)>=8) + { + WRITE_PORT_UCHAR((PUCHAR)0xa0,0x20); + } + + *OldIrql = KeGetCurrentIrql(); + if (Vector-IRQ_BASE != 0) + { + DPRINT("old_level %d\n",*OldIrql); + } + KeSetCurrentIrql(Irql); + + return TRUE; +} + + +VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, + ULONG Unknown2) +{ + KeSetCurrentIrql(Irql); +} + + +BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector, + ULONG Unknown2) +{ + ULONG irq; + + if (Vector < IRQ_BASE || Vector > IRQ_BASE + NR_IRQS) + return FALSE; + + irq = Vector - IRQ_BASE; + if (irq < 8) + { + WRITE_PORT_UCHAR((PUCHAR)0x21, + READ_PORT_UCHAR((PUCHAR)0x21)|(1< IRQ_BASE + NR_IRQS) + return FALSE; + + irq = Vector - IRQ_BASE; + if (irq < 8) + { + WRITE_PORT_UCHAR((PUCHAR)0x21, + READ_PORT_UCHAR((PUCHAR)0x21)&(~(1< +#include + + +/* FUNCTIONS *****************************************************************/ + +BOOL 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; +} + +/* EOF */ diff --git a/reactos/hal/halx86/kdbg.c b/reactos/hal/halx86/kdbg.c new file mode 100644 index 00000000000..bcb0bc71120 --- /dev/null +++ b/reactos/hal/halx86/kdbg.c @@ -0,0 +1,336 @@ +/* $Id: kdbg.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * 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 SER_DLM(x) ((x)+1) +#define SER_IIR(x) ((x)+2) +#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 SER_LSR(x) ((x)+5) +#define SR_LSR_DR 0x01 +#define SR_LSR_TBE 0x20 +#define SER_MSR(x) ((x)+6) +#define SR_MSR_CTS 0x10 +#define SR_MSR_DSR 0x20 +#define SER_SCR(x) ((x)+7) + + +/* GLOBAL VARIABLES *********************************************************/ + +ULONG +__declspec(dllexport) +KdComPortInUse = 0; /* EXPORTED */ + + +/* 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; + BYTE mcr; + BYTE 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) + found = TRUE; + } + + /* restore MCR */ + WRITE_PORT_UCHAR (SER_MCR(BaseAddress), mcr); + + return (found); +} + + +/* FUNCTIONS ****************************************************************/ + +/* HAL.KdPortInitialize */ +BOOLEAN +STDCALL +KdPortInitialize ( + PKD_PORT_INFORMATION PortInformation, + DWORD Unknown1, + DWORD Unknown2 + ) +{ + ULONG BaseArray[5] = {0, 0x3F8, 0x2F8, 0x3E8, 0x2E8}; + char buffer[80]; + ULONG divisor; + BYTE 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), divisor & 0xff); + WRITE_PORT_UCHAR (SER_DLM(PortBase), (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.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.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.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.KdPortRestore */ +VOID +STDCALL +KdPortRestore ( + VOID + ) +{ +} + + +/* HAL.KdPortSave */ +VOID +STDCALL +KdPortSave ( + VOID + ) +{ +} + + +/* EOF */ diff --git a/reactos/hal/halx86/mbr.c b/reactos/hal/halx86/mbr.c new file mode 100644 index 00000000000..5dc30a9e203 --- /dev/null +++ b/reactos/hal/halx86/mbr.c @@ -0,0 +1,25 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/mbr.c + * PURPOSE: Functions for reading the master boot record (MBR) + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID HalExamineMBR(PDEVICE_OBJECT DeviceObject, + ULONG SectorSize, + ULONG MBRTypeIdentifier, + PVOID Buffer) +{ + UNIMPLEMENTED; +} diff --git a/reactos/hal/halx86/misc.c b/reactos/hal/halx86/misc.c new file mode 100644 index 00000000000..f6049acdf13 --- /dev/null +++ b/reactos/hal/halx86/misc.c @@ -0,0 +1,105 @@ +/* $Id: misc.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/misc.c + * PURPOSE: Miscellaneous hardware functions + * PROGRAMMER: Eric Kohl (ekohl@rz-online.de) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +/* FUNCTIONS ****************************************************************/ + +VOID STDCALL +HalHandleNMI (ULONG Unused) +{ + UCHAR ucStatus; + + ucStatus = READ_PORT_UCHAR((PUCHAR) 0x61); + + HalDisplayString ("\n*** Hardware Malfunction\n\n"); + HalDisplayString ("Call your hardware vendor for support\n\n"); + + if (ucStatus & 0x80) + HalDisplayString ("NMI: Parity Check / Memory Parity Error\n"); + + if (ucStatus & 0x40) + HalDisplayString ("NMI: Channel Check / IOCHK\n"); + + HalDisplayString ("\n*** The system has halted ***\n"); + KeEnterKernelDebugger (); +} + +VOID STDCALL +HalProcessorIdle (VOID) +{ +#if 1 + __asm__("sti\n\t" \ + "hlt\n\t"); +#else + +#endif +} + +VOID STDCALL +HalRequestIpi(ULONG Unknown) +{ + return; +} + +ULONG FASTCALL +HalSystemVectorDispatchEntry ( + ULONG Unknown1, + ULONG Unknown2, + ULONG Unknown3 + ) +{ + return 0; +} + +VOID STDCALL +KeFlushWriteBuffer ( + VOID + ) +{ + return; +} + +VOID STDCALL +HalReportResourceUsage ( + VOID + ) +{ + /* + * FIXME: Report all resources used by hal. + * Calls IoReportHalResourceUsage() + */ + + /* + * Initialize PCI bus. + */ + HalpInitPciBus (); +#if 0 + /* + * Initialize IsaPnP bus. + */ + HalpInitIsaPnpBus (); + + /* + * Initialize other busses??? + */ + + /* + * Probe for a BIOS32 extension + */ + Hal_bios32_probe(); +#endif + + return; +} + +/* EOF */ diff --git a/reactos/hal/halx86/mp.c b/reactos/hal/halx86/mp.c new file mode 100644 index 00000000000..c8fddb1d197 --- /dev/null +++ b/reactos/hal/halx86/mp.c @@ -0,0 +1,2367 @@ +/* $Id: mp.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/mp.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 +#include + +#define NDEBUG +#include + +#ifdef MP + +#include +#include + +#include +#include +#include +#include + +/* + Address of area to be used for communication between Application + Processors (APs) and the BootStrap Processor (BSP) + */ +#define COMMON_AREA 0x2000 + +#define BIOS_AREA 0x0 + +typedef struct __attribute__((packed)) _COMMON_AREA_INFO +{ + ULONG Stack; /* Location of AP stack */ + ULONG Debug[16]; /* For debugging */ +} COMMON_AREA_INFO, *PCOMMON_AREA_INFO; + +CPU_INFO CPUMap[MAX_CPU]; /* Map of all CPUs in the system */ +ULONG CPUCount; /* Total number of CPUs */ +ULONG OnlineCPUs; /* Bitmask of online CPUs */ + +UCHAR BUSMap[MAX_BUS]; /* Map of all buses in the system */ +UCHAR PCIBUSMap[MAX_BUS]; /* Map of all PCI buses in the system */ + +IOAPIC_INFO IOAPICMap[MAX_IOAPIC]; /* Map of all I/O APICs in the system */ +ULONG IOAPICCount; /* Number of I/O APICs in the system */ + +MP_CONFIGURATION_INTSRC IRQMap[MAX_IRQ_SOURCE]; /* Map of all IRQs */ +ULONG IRQVectorMap[MAX_IRQ_SOURCE]; /* IRQ to vector map */ +ULONG IRQCount; /* Number of IRQs */ + +ULONG APICMode; /* APIC mode at startup */ +ULONG BootCPU; /* Bootstrap processor */ +ULONG NextCPU; /* Next CPU to start */ +PULONG BIOSBase; /* Virtual address of BIOS data segment */ +PULONG APICBase; /* Virtual address of local APIC */ +PULONG CommonBase; /* Virtual address of common area */ + +extern CHAR *APstart, *APend; +extern VOID (*APflush)(VOID); + +extern VOID MpsTimerInterrupt(VOID); +extern VOID MpsErrorInterrupt(VOID); +extern VOID MpsSpuriousInterrupt(VOID); + +#define CMOS_READ(address) ({ \ + WRITE_PORT_UCHAR((PUCHAR)0x70, address)); \ + READ_PORT_UCHAR((PUCHAR)0x71)); \ +}) + +#define CMOS_WRITE(address, value) ({ \ + WRITE_PORT_UCHAR((PUCHAR)0x70, address); \ + WRITE_PORT_UCHAR((PUCHAR)0x71, value); \ +}) + +BOOLEAN MPSInitialized = FALSE; /* Is the MP system initialized? */ + +VOID APICDisable(VOID); +static VOID APICSyncArbIDs(VOID); + +/* For debugging */ +ULONG lastregr = 0; +ULONG lastvalr = 0; +ULONG lastregw = 0; +ULONG lastvalw = 0; + +#endif /* MP */ + + +BOOLEAN BSPInitialized = FALSE; /* Is the BSP initialized? */ + + +/* FUNCTIONS *****************************************************************/ + +#ifdef MP + +/* Functions for handling 8259A PICs */ + +VOID Disable8259AIrq( + ULONG irq) +{ + ULONG tmp; + + if (irq & 8) { + tmp = READ_PORT_UCHAR((PUCHAR)0xA1); + tmp |= (1 << irq); + WRITE_PORT_UCHAR((PUCHAR)0xA1, tmp); + } else { + tmp = READ_PORT_UCHAR((PUCHAR)0x21); + tmp |= (1 << irq); + WRITE_PORT_UCHAR((PUCHAR)0x21, tmp); + } +} + + +VOID Enable8259AIrq( + ULONG irq) +{ + ULONG tmp; + + if (irq & 8) { + tmp = READ_PORT_UCHAR((PUCHAR)0xA1); + tmp &= ~(1 << irq); + WRITE_PORT_UCHAR((PUCHAR)0xA1, tmp); + } else { + tmp = READ_PORT_UCHAR((PUCHAR)0x21); + tmp &= ~(1 << irq); + WRITE_PORT_UCHAR((PUCHAR)0x21, tmp); + } +} + + +/* Functions for handling I/O APICs */ + +volatile ULONG IOAPICRead( + ULONG Apic, + ULONG Offset) +{ + PULONG Base; + + Base = (PULONG)IOAPICMap[Apic].ApicAddress; + + *Base = Offset; + return *((PULONG)((ULONG)Base + IOAPIC_IOWIN)); +} + + +VOID IOAPICWrite( + ULONG Apic, + ULONG Offset, + ULONG Value) +{ + PULONG Base; + + Base = (PULONG)IOAPICMap[Apic].ApicAddress; + + *Base = Offset; + *((PULONG)((ULONG)Base + IOAPIC_IOWIN)) = Value; +} + + +VOID IOAPICClearPin( + ULONG Apic, + ULONG Pin) +{ + IOAPIC_ROUTE_ENTRY Entry; + + /* + * Disable it in the IO-APIC irq-routing table + */ + memset(&Entry, 0, sizeof(Entry)); + Entry.mask = 1; + IOAPICWrite(Apic, IOAPIC_REDTBL + 2 * Pin, *(((PULONG)&Entry) + 0)); + IOAPICWrite(Apic, IOAPIC_REDTBL + 1 + 2 * Pin, *(((PULONG)&Entry) + 1)); +} + +static VOID IOAPICClear( + ULONG Apic) +{ + ULONG Pin; + + for (Pin = 0; Pin < IOAPICMap[Apic].EntryCount; Pin++) + IOAPICClearPin(Apic, Pin); +} + +static VOID IOAPICClearAll( + VOID) +{ + ULONG Apic; + + for (Apic = 0; Apic < IOAPICCount; Apic++) + IOAPICClear(Apic); +} + +/* This is performance critical and should probably be done in assembler */ +VOID IOAPICMaskIrq( + ULONG Apic, + ULONG Irq) +{ + IOAPIC_ROUTE_ENTRY Entry; + + *((PULONG)&Entry) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq); + Entry.mask = 1; + IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq, *((PULONG)&Entry)); +} + + +/* This is performance critical and should probably be done in assembler */ +VOID IOAPICUnmaskIrq( + ULONG Apic, + ULONG Irq) +{ + IOAPIC_ROUTE_ENTRY Entry; + + *((PULONG)&Entry) = IOAPICRead(Apic, IOAPIC_REDTBL+2*Irq); + Entry.mask = 0; + IOAPICWrite(Apic, IOAPIC_REDTBL+2*Irq, *((PULONG)&Entry)); +} + +static VOID +IOAPICSetupIds(VOID) +{ + ULONG tmp, apic, i; + UCHAR old_id; + + /* + * Set the IOAPIC ID to the value stored in the MPC table. + */ + for (apic = 0; apic < IOAPICCount; apic++) { + + /* Read the register 0 value */ + tmp = IOAPICRead(apic, IOAPIC_ID); + + old_id = IOAPICMap[apic].ApicId; + + if (IOAPICMap[apic].ApicId >= 0xf) { + DPRINT1("BIOS bug, IO-APIC#%d ID is %d in the MPC table!...\n", + apic, IOAPICMap[apic].ApicId); + DPRINT1("... fixing up to %d. (tell your hw vendor)\n", + GET_IOAPIC_ID(tmp)); + IOAPICMap[apic].ApicId = GET_IOAPIC_ID(tmp); + } + + /* + * We need to adjust the IRQ routing table + * if the ID changed. + */ + if (old_id != IOAPICMap[apic].ApicId) + for (i = 0; i < IRQCount; i++) + if (IRQMap[i].DstApicId == old_id) + IRQMap[i].DstApicId = IOAPICMap[apic].ApicId; + + /* + * Read the right value from the MPC table and + * write it into the ID register. + */ + DPRINT("Changing IO-APIC physical APIC ID to %d\n", + IOAPICMap[apic].ApicId); + + tmp &= ~IOAPIC_ID_MASK; + tmp |= SET_IOAPIC_ID(IOAPICMap[apic].ApicId); + + IOAPICWrite(apic, IOAPIC_ID, tmp); + + /* + * Sanity check + */ + tmp = IOAPICRead(apic, 0); + if (GET_IOAPIC_ID(tmp) != IOAPICMap[apic].ApicId) { + DPRINT1("Could not set I/O APIC ID!\n"); + KeBugCheck(0); + } + } +} + + +/* + * EISA Edge/Level control register, ELCR + */ +static ULONG EISA_ELCR( + ULONG irq) +{ + if (irq < 16) { + PUCHAR port = (PUCHAR)(0x4d0 + (irq >> 3)); + return (READ_PORT_UCHAR(port) >> (irq & 7)) & 1; + } + DPRINT("Broken MPtable reports ISA irq %d\n", irq); + return 0; +} + +/* EISA interrupts are always polarity zero and can be edge or level + * trigger depending on the ELCR value. If an interrupt is listed as + * EISA conforming in the MP table, that means its trigger type must + * be read in from the ELCR */ + +#define default_EISA_trigger(idx) (EISA_ELCR(IRQMap[idx].SrcBusIrq)) +#define default_EISA_polarity(idx) (0) + +/* ISA interrupts are always polarity zero edge triggered, + * when listed as conforming in the MP table. */ + +#define default_ISA_trigger(idx) (0) +#define default_ISA_polarity(idx) (0) + +/* PCI interrupts are always polarity one level triggered, + * when listed as conforming in the MP table. */ + +#define default_PCI_trigger(idx) (1) +#define default_PCI_polarity(idx) (1) + +/* MCA interrupts are always polarity zero level triggered, + * when listed as conforming in the MP table. */ + +#define default_MCA_trigger(idx) (1) +#define default_MCA_polarity(idx) (0) + +static ULONG IRQPolarity( + ULONG idx) +{ + ULONG bus = IRQMap[idx].SrcBusId; + ULONG polarity; + + /* + * Determine IRQ line polarity (high active or low active): + */ + switch (IRQMap[idx].IrqFlag & 3) + { + case 0: /* conforms, ie. bus-type dependent polarity */ + { + switch (BUSMap[bus]) + { + case MP_BUS_ISA: /* ISA pin */ + { + polarity = default_ISA_polarity(idx); + break; + } + case MP_BUS_EISA: /* EISA pin */ + { + polarity = default_EISA_polarity(idx); + break; + } + case MP_BUS_PCI: /* PCI pin */ + { + polarity = default_PCI_polarity(idx); + break; + } + case MP_BUS_MCA: /* MCA pin */ + { + polarity = default_MCA_polarity(idx); + break; + } + default: + { + DPRINT("Broken BIOS!!\n"); + polarity = 1; + break; + } + } + break; + } + case 1: /* high active */ + { + polarity = 0; + break; + } + case 2: /* reserved */ + { + DPRINT("Broken BIOS!!\n"); + polarity = 1; + break; + } + case 3: /* low active */ + { + polarity = 1; + break; + } + default: /* invalid */ + { + DPRINT("Broken BIOS!!\n"); + polarity = 1; + break; + } + } + return polarity; +} + +static ULONG IRQTrigger( + ULONG idx) +{ + ULONG bus = IRQMap[idx].SrcBusId; + ULONG trigger; + + /* + * Determine IRQ trigger mode (edge or level sensitive): + */ + switch ((IRQMap[idx].IrqFlag >> 2) & 3) + { + case 0: /* conforms, ie. bus-type dependent */ + { + switch (BUSMap[bus]) + { + case MP_BUS_ISA: /* ISA pin */ + { + trigger = default_ISA_trigger(idx); + break; + } + case MP_BUS_EISA: /* EISA pin */ + { + trigger = default_EISA_trigger(idx); + break; + } + case MP_BUS_PCI: /* PCI pin */ + { + trigger = default_PCI_trigger(idx); + break; + } + case MP_BUS_MCA: /* MCA pin */ + { + trigger = default_MCA_trigger(idx); + break; + } + default: + { + DPRINT("Broken BIOS!!\n"); + trigger = 1; + break; + } + } + break; + } + case 1: /* edge */ + { + trigger = 0; + break; + } + case 2: /* reserved */ + { + DPRINT("Broken BIOS!!\n"); + trigger = 1; + break; + } + case 3: /* level */ + { + trigger = 1; + break; + } + default: /* invalid */ + { + DPRINT("Broken BIOS!!\n"); + trigger = 0; + break; + } + } + return trigger; +} + + +static ULONG Pin2Irq( + ULONG idx, + ULONG apic, + ULONG pin) +{ + ULONG irq, i; + ULONG bus = IRQMap[idx].SrcBusId; + + /* + * Debugging check, we are in big trouble if this message pops up! + */ + if (IRQMap[idx].DstApicInt != pin) { + DPRINT("broken BIOS or MPTABLE parser, ayiee!!\n"); + } + + switch (BUSMap[bus]) + { + case MP_BUS_ISA: /* ISA pin */ + case MP_BUS_EISA: + case MP_BUS_MCA: + { + irq = IRQMap[idx].SrcBusIrq; + break; + } + case MP_BUS_PCI: /* PCI pin */ + { + /* + * PCI IRQs are mapped in order + */ + i = irq = 0; + while (i < apic) + irq += IOAPICMap[i++].EntryCount; + irq += pin; + break; + } + default: + { + DPRINT("Unknown bus type %d.\n",bus); + irq = 0; + break; + } + } + + return irq; +} + + +/* + * Rough estimation of how many shared IRQs there are, can + * be changed anytime. + */ +#define MAX_PLUS_SHARED_IRQS PIC_IRQS +#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + PIC_IRQS) + +/* + * This is performance-critical, we want to do it O(1) + * + * the indexing order of this array favors 1:1 mappings + * between pins and IRQs. + */ + +static struct irq_pin_list { + ULONG apic, pin, next; +} irq_2_pin[PIN_MAP_SIZE]; + +/* + * The common case is 1:1 IRQ<->pin mappings. Sometimes there are + * shared ISA-space IRQs, so we have to support them. We are super + * fast in the common case, and fast for shared ISA-space IRQs. + */ +static VOID AddPinToIrq( + ULONG irq, + ULONG apic, + ULONG pin) +{ + static ULONG first_free_entry = PIC_IRQS; + struct irq_pin_list *entry = irq_2_pin + irq; + + while (entry->next) + entry = irq_2_pin + entry->next; + + if (entry->pin != -1) { + entry->next = first_free_entry; + entry = irq_2_pin + entry->next; + if (++first_free_entry >= PIN_MAP_SIZE) { + DPRINT1("Ohh no!"); + KeBugCheck(0); + } + } + entry->apic = apic; + entry->pin = pin; +} + + +/* + * Find the IRQ entry number of a certain pin. + */ +static ULONG IOAPICGetIrqEntry( + ULONG apic, + ULONG pin, + ULONG type) +{ + ULONG i; + + for (i = 0; i < IRQCount; i++) + if (IRQMap[i].IrqType == type && + (IRQMap[i].DstApicId == IOAPICMap[apic].ApicId || + IRQMap[i].DstApicId == MP_APIC_ALL) && + IRQMap[i].DstApicInt == pin) + return i; + + return -1; +} + + +static ULONG AssignIrqVector( + ULONG irq) +{ + static ULONG current_vector = FIRST_DEVICE_VECTOR, vector_offset = 0; + ULONG vector; + + /* There may already have been assigned a vector for this IRQ */ + vector = IRQVectorMap[irq]; + if (vector > 0) + return vector; + + current_vector += 8; + if (current_vector > FIRST_SYSTEM_VECTOR) { + vector_offset++; + current_vector = FIRST_DEVICE_VECTOR + vector_offset; + } else if (current_vector == FIRST_SYSTEM_VECTOR) { + DPRINT1("Ran out of interrupt sources!"); + KeBugCheck(0); + } + + IRQVectorMap[irq] = current_vector; + return current_vector; +} + + +VOID IOAPICSetupIrqs( + VOID) +{ + IOAPIC_ROUTE_ENTRY entry; + ULONG apic, pin, idx, irq, first_notcon = 1, vector; + + DPRINT("Init IO_APIC IRQs\n"); + + for (apic = 0; apic < IOAPICCount; apic++) { + for (pin = 0; pin < IOAPICMap[apic].EntryCount; pin++) { + + /* + * add it to the IO-APIC irq-routing table + */ + memset(&entry,0,sizeof(entry)); + + entry.delivery_mode = APIC_DM_LOWEST; + entry.dest_mode = 1; /* logical delivery */ + entry.mask = 0; /* enable IRQ */ + entry.dest.logical.logical_dest = OnlineCPUs; + + idx = IOAPICGetIrqEntry(apic,pin,INT_VECTORED); + if (idx == -1) { + if (first_notcon) { + DPRINT(" IO-APIC (apicid-pin) %d-%d\n", IOAPICMap[apic].ApicId, pin); + first_notcon = 0; + } else { + DPRINT(", %d-%d\n", IOAPICMap[apic].ApicId, pin); + } + continue; + } + + entry.trigger = IRQTrigger(idx); + entry.polarity = IRQPolarity(idx); + + if (entry.trigger) { + entry.trigger = 1; + entry.mask = 1; + entry.dest.logical.logical_dest = OnlineCPUs; + } + + irq = Pin2Irq(idx, apic, pin); + AddPinToIrq(irq, apic, pin); + + vector = AssignIrqVector(irq); + entry.vector = vector; + + if (irq == 0) + { + /* Mask timer IRQ */ + entry.mask = 1; + } + + if ((apic == 0) && (irq < 16)) + Disable8259AIrq(irq); + + IOAPICWrite(apic, IOAPIC_REDTBL+2*pin+1, *(((PULONG)&entry)+1)); + IOAPICWrite(apic, IOAPIC_REDTBL+2*pin, *(((PULONG)&entry)+0)); + } + } +} + + +static VOID IOAPICEnable( + VOID) +{ + ULONG i, tmp; + + for (i = 0; i < PIN_MAP_SIZE; i++) { + irq_2_pin[i].pin = -1; + irq_2_pin[i].next = 0; + } + + /* + * The number of IO-APIC IRQ registers (== #pins): + */ + for (i = 0; i < IOAPICCount; i++) { + tmp = IOAPICRead(i, IOAPIC_VER); + IOAPICMap[i].EntryCount = GET_IOAPIC_MRE(tmp) + 1; + } + + /* + * Do not trust the IO-APIC being empty at bootup + */ + IOAPICClearAll(); +} + +#if 0 +static VOID IOAPICDisable( + VOID) +{ + /* + * Clear the IO-APIC before rebooting + */ + IOAPICClearAll(); + + APICDisable(); +} +#endif + + +static VOID IOAPICSetup( + VOID) +{ + IOAPICEnable(); + IOAPICSetupIds(); + if (0) { + // FIXME: This causes application processors to not boot if asked to + APICSyncArbIDs(); + } + IOAPICSetupIrqs(); +} + + +VOID IOAPICDump(VOID) +{ + ULONG apic, i; + ULONG reg0, reg1, reg2; + + DbgPrint("Number of MP IRQ sources: %d.\n", IRQCount); + for (i = 0; i < IOAPICCount; i++) { + DbgPrint("Number of IO-APIC #%d registers: %d.\n", + IOAPICMap[i].ApicId, + IOAPICMap[i].EntryCount); + } + + /* + * We are a bit conservative about what we expect. We have to + * know about every hardware change ASAP. + */ + DbgPrint("Testing the IO APIC.......................\n"); + + for (apic = 0; apic < IOAPICCount; apic++) { + + reg0 = IOAPICRead(apic, IOAPIC_ID); + reg1 = IOAPICRead(apic, IOAPIC_VER); + if (GET_IOAPIC_VERSION(reg1) >= 0x10) { + reg2 = IOAPICRead(apic, IOAPIC_ARB); + } + + DbgPrint("\n"); + DbgPrint("IO APIC #%d......\n", IOAPICMap[apic].ApicId); + DbgPrint(".... register #00: %08X\n", reg0); + DbgPrint("....... : physical APIC id: %02X\n", GET_IOAPIC_ID(reg0)); + if (reg0 & 0xF0FFFFFF) { + DbgPrint(" WARNING: Unexpected IO-APIC\n"); + } + + DbgPrint(".... register #01: %08X\n", reg1); + i = GET_IOAPIC_MRE(reg1); + + DbgPrint("....... : max redirection entries: %04X\n", i); + if ((i != 0x0f) && /* older (Neptune) boards */ + (i != 0x17) && /* typical ISA+PCI boards */ + (i != 0x1b) && /* Compaq Proliant boards */ + (i != 0x1f) && /* dual Xeon boards */ + (i != 0x22) && /* bigger Xeon boards */ + (i != 0x2E) && + (i != 0x3F)) { + DbgPrint(" WARNING: Unexpected IO-APIC\n"); + } + + i = GET_IOAPIC_VERSION(reg1); + DbgPrint("....... : IO APIC version: %04X\n", i); + if ((i != 0x01) && /* 82489DX IO-APICs */ + (i != 0x10) && /* oldest IO-APICs */ + (i != 0x11) && /* Pentium/Pro IO-APICs */ + (i != 0x13)) { /* Xeon IO-APICs */ + DbgPrint(" WARNING: Unexpected IO-APIC\n"); + } + + if (reg1 & 0xFF00FF00) { + DbgPrint(" WARNING: Unexpected IO-APIC\n"); + } + + if (GET_IOAPIC_VERSION(reg1) >= 0x10) { + DbgPrint(".... register #02: %08X\n", reg2); + DbgPrint("....... : arbitration: %02X\n", + GET_IOAPIC_ARB(reg2)); + if (reg2 & 0xF0FFFFFF) { + DbgPrint(" WARNING: Unexpected IO-APIC\n"); + } + } + + DbgPrint(".... IRQ redirection table:\n"); + DbgPrint(" NR Log Phy Mask Trig IRR Pol" + " Stat Dest Deli Vect: \n"); + + for (i = 0; i <= GET_IOAPIC_MRE(reg1); i++) { + IOAPIC_ROUTE_ENTRY entry; + + *(((PULONG)&entry)+0) = IOAPICRead(apic, 0x10+i*2); + *(((PULONG)&entry)+1) = IOAPICRead(apic, 0x11+i*2); + + DbgPrint(" %02x %03X %02X ", + i, + entry.dest.logical.logical_dest, + entry.dest.physical.physical_dest + ); + + DbgPrint("%C %C %1d %C %C %C %03X %02X\n", + (entry.mask == 0) ? 'U' : 'M', // Unmasked/masked + (entry.trigger == 0) ? 'E' : 'L', // Edge/level sensitive + entry.irr, + (entry.polarity == 0) ? 'H' : 'L', // Active high/active low + (entry.delivery_status == 0) ? 'I' : 'S', // Idle / send pending + (entry.dest_mode == 0) ? 'P' : 'L', // Physical logical + entry.delivery_mode, + entry.vector + ); + } + } + DbgPrint("IRQ to pin mappings:\n"); + for (i = 0; i < PIC_IRQS; i++) { + struct irq_pin_list *entry = irq_2_pin + i; + if (entry->pin < 0) + continue; + DbgPrint("IRQ%d ", i); + for (;;) { + DbgPrint("-> %d", entry->pin); + if (!entry->next) + break; + entry = irq_2_pin + entry->next; + } + if (i % 2) { + DbgPrint("\n"); + } else { + DbgPrint(" "); + } + } + + DbgPrint(".................................... done.\n"); +} + + + +/* Functions for handling local APICs */ + +#if 0 +volatile inline ULONG APICRead( + ULONG Offset) +{ + PULONG p; + + p = (PULONG)((ULONG)APICBase + Offset); + return *p; +} +#else +volatile inline ULONG APICRead( + ULONG Offset) +{ + PULONG p; + + lastregr = Offset; + lastvalr = 0; + + //DPRINT1("R(0x%X)", Offset); + p = (PULONG)((ULONG)APICBase + Offset); + lastvalr = *p; + //DPRINT1("(0x%08X)\n", *p); + + return lastvalr; +} +#endif + +#if 0 +inline VOID APICWrite( + ULONG Offset, + ULONG Value) +{ + PULONG p; + + p = (PULONG)((ULONG)APICBase + Offset); + + *p = Value; +} +#else +inline VOID APICWrite( + ULONG Offset, + ULONG Value) +{ + PULONG p; + + lastregw = Offset; + lastvalw = Value; + + //DPRINT1("W(0x%X, 0x%08X)\n", Offset, Value); + p = (PULONG)((ULONG)APICBase + Offset); + + *p = Value; +} +#endif + + +inline VOID APICSendEOI(VOID) +{ + // Dummy read + APICRead(APIC_SIVR); + // Send the EOI + APICWrite(APIC_EOI, 0); +} + + +VOID DumpESR(VOID) +{ + ULONG tmp; + + if (CPUMap[ThisCPU()].MaxLVT > 3) + APICWrite(APIC_ESR, 0); + tmp = APICRead(APIC_ESR); + DbgPrint("ESR %08x\n", tmp); +} + + +ULONG APICGetMaxLVT(VOID) +{ + ULONG tmp, ver, maxlvt; + + tmp = APICRead(APIC_VER); + ver = GET_APIC_VERSION(tmp); + /* 82489DXs do not report # of LVT entries. */ + maxlvt = APIC_INTEGRATED(ver) ? GET_APIC_MAXLVT(tmp) : 2; + + return maxlvt; +} + + +static VOID APICClear( + VOID) +{ + ULONG tmp, maxlvt; + + maxlvt = CPUMap[ThisCPU()].MaxLVT; + + /* + * Careful: we have to set masks only first to deassert + * any level-triggered sources. + */ + tmp = APICRead(APIC_LVTT); + APICWrite(APIC_LVTT, tmp | APIC_LVT_MASKED); + + tmp = APICRead(APIC_LINT0); + APICWrite(APIC_LINT0, tmp | APIC_LVT_MASKED); + + tmp = APICRead(APIC_LINT1); + APICWrite(APIC_LINT1, tmp | APIC_LVT_MASKED); + + if (maxlvt >= 3) { + tmp = APICRead(APIC_LVT3); + APICWrite(APIC_LVT3, tmp | APIC_LVT3_MASKED); + } + + if (maxlvt >= 4) { + tmp = APICRead(APIC_LVTPC); + APICWrite(APIC_LVTPC, tmp | APIC_LVT_MASKED); + } + + /* + * Clean APIC state for other OSs: + */ + APICRead(APIC_SIVR); // Dummy read + APICWrite(APIC_LVTT, APIC_LVT_MASKED); + + APICRead(APIC_SIVR); // Dummy read + APICWrite(APIC_LINT0, APIC_LVT_MASKED); + + APICRead(APIC_SIVR); // Dummy read + APICWrite(APIC_LINT1, APIC_LVT_MASKED); + + if (maxlvt >= 3) { + APICRead(APIC_SIVR); // Dummy read + APICWrite(APIC_LVT3, APIC_LVT3_MASKED); + } + + if (maxlvt >= 4) { + APICRead(APIC_SIVR); // Dummy read + APICWrite(APIC_LVTPC, APIC_LVT_MASKED); + } +} + +/* Enable symetric I/O mode ie. connect the BSP's + local APIC to INT and NMI lines */ +inline VOID EnableSMPMode( + VOID) +{ + /* + * Do not trust the local APIC being empty at bootup. + */ + APICClear(); + + WRITE_PORT_UCHAR((PUCHAR)0x22, 0x70); + WRITE_PORT_UCHAR((PUCHAR)0x23, 0x01); +} + + +/* Disable symetric I/O mode ie. go to PIC mode */ +inline VOID DisableSMPMode( + VOID) +{ + /* + * Put the board back into PIC mode (has an effect + * only on certain older boards). Note that APIC + * interrupts, including IPIs, won't work beyond + * this point! The only exception are INIT IPIs. + */ + WRITE_PORT_UCHAR((PUCHAR)0x22, 0x70); + WRITE_PORT_UCHAR((PUCHAR)0x23, 0x00); +} + + +VOID APICDisable( + VOID) +{ + ULONG tmp; + + APICClear(); + + /* + * Disable APIC (implies clearing of registers for 82489DX!). + */ + tmp = APICRead(APIC_SIVR); + tmp &= ~APIC_SIVR_ENABLE; + APICWrite(APIC_SIVR, tmp); +} + + +inline ULONG ThisCPU( + VOID) +{ + return (APICRead(APIC_ID) & APIC_ID_MASK) >> 24; +} + + +static VOID APICDumpBit(ULONG base) +{ + ULONG v, i, j; + + DbgPrint("0123456789abcdef0123456789abcdef\n"); + for (i = 0; i < 8; i++) { + APICRead(base + i*0x10); + for (j = 0; j < 32; j++) { + if (v & (1< 3) /* Due to the Pentium erratum 3AP. */ + APICWrite(APIC_ESR, 0); + v = APICRead(APIC_ESR); + DbgPrint("... ESR : %08x\n", v); + } + + v = APICRead(APIC_ICR0); + DbgPrint("... ICR0 : %08x ! ", v); + v = APICRead(APIC_ICR1); + DbgPrint("... ICR1 : %08x ! ", v); + + v = APICRead(APIC_LVTT); + DbgPrint("... LVTT : %08x\n", v); + + if (maxlvt > 3) { /* PC is LVT#4. */ + v = APICRead(APIC_LVTPC); + DbgPrint("... LVTPC : %08x ! ", v); + } + v = APICRead(APIC_LINT0); + DbgPrint("... LINT0 : %08x ! ", v); + v = APICRead(APIC_LINT1); + DbgPrint("... LINT1 : %08x\n", v); + + if (maxlvt > 2) { + v = APICRead(APIC_LVT3); + DbgPrint("... LVT3 : %08x\n", v); + } + + v = APICRead(APIC_ICRT); + DbgPrint("... ICRT : %08x ! ", v); + v = APICRead(APIC_CCRT); + DbgPrint("... CCCT : %08x ! ", v); + v = APICRead(APIC_TDCR); + DbgPrint("... TDCR : %08x\n", v); + DbgPrint("\n"); + DbgPrint("Last register read (offset): 0x%08X\n", r1); + DbgPrint("Last register read (value): 0x%08X\n", r2); + DbgPrint("Last register written (offset): 0x%08X\n", w1); + DbgPrint("Last register written (value): 0x%08X\n", w2); + DbgPrint("\n"); +} + + +ULONG Read8254Timer(VOID) +{ + ULONG Count; + + WRITE_PORT_UCHAR((PUCHAR)0x43, 0x00); + Count = READ_PORT_UCHAR((PUCHAR)0x40); + Count |= READ_PORT_UCHAR((PUCHAR)0x40) << 8; + + return Count; +} + + +VOID WaitFor8254Wraparound(VOID) +{ + ULONG CurCount, PrevCount = ~0; + LONG Delta; + + CurCount = Read8254Timer(); + + do { + PrevCount = CurCount; + CurCount = Read8254Timer(); + Delta = CurCount - PrevCount; + + /* + * This limit for delta seems arbitrary, but it isn't, it's + * slightly above the level of error a buggy Mercury/Neptune + * chipset timer can cause. + */ + + } while (Delta < 300); +} + +#define HZ (100) +#define APIC_DIVISOR (16) + +VOID APICSetupLVTT( + ULONG ClockTicks) +{ + ULONG tmp; + + /* Periodic timer */ + tmp = SET_APIC_TIMER_BASE(APIC_TIMER_BASE_DIV) | + APIC_LVT_PERIODIC | LOCAL_TIMER_VECTOR; + APICWrite(APIC_LVTT, tmp); + + tmp = APICRead(APIC_TDCR); + tmp &= ~(APIC_TDCR_1 | APIC_TDCR_TMBASE | APIC_TDCR_16); + APICWrite(APIC_TDCR, tmp); + APICWrite(APIC_ICRT, ClockTicks / APIC_DIVISOR); +} + + +VOID APICCalibrateTimer( + ULONG CPU) +{ + ULARGE_INTEGER t1, t2; + LONG tt1, tt2; + + DPRINT("Calibrating APIC timer...\n"); + + APICSetupLVTT(~0); + + /* + * The timer chip counts down to zero. Let's wait + * for a wraparound to start exact measurement: + * (the current tick might have been already half done) + */ + WaitFor8254Wraparound(); + + /* + * We wrapped around just now. Let's start + */ + ReadPentiumClock(&t1); + tt1 = APICRead(APIC_CCRT); + + WaitFor8254Wraparound(); + + tt2 = APICRead(APIC_CCRT); + ReadPentiumClock(&t2); + + CPUMap[CPU].BusSpeed = (HZ * (tt2 - tt1) * APIC_DIVISOR); + CPUMap[CPU].CoreSpeed = (HZ * (t2.QuadPart - t1.QuadPart)); + + /* Setup timer for normal operation */ + //APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 100); // 100ns + APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 15000); // 15ms + //APICSetupLVTT((CPUMap[CPU].BusSpeed / 1000000) * 100000); // 100ms + + DPRINT("CPU clock speed is %ld.%04ld MHz.\n", + CPUMap[CPU].CoreSpeed/1000000, + CPUMap[CPU].CoreSpeed%1000000); + + DPRINT("Host bus clock speed is %ld.%04ld MHz.\n", + CPUMap[CPU].BusSpeed/1000000, + CPUMap[CPU].BusSpeed%1000000); +} + + +static VOID APICSleep( + ULONG Count) +/* + PARAMETERS: + Count = Number of microseconds to busy wait + */ +{ + KeStallExecutionProcessor(Count); +} + + +static VOID APICSyncArbIDs( + VOID) +{ + ULONG i, tmp; + + /* Wait up to 100ms for the APIC to become ready */ + for (i = 0; i < 10000; i++) { + tmp = APICRead(APIC_ICR0); + /* Check Delivery Status */ + if ((tmp & APIC_ICR0_DS) == 0) + break; + APICSleep(10); + } + + if (i == 10000) { + DPRINT("CPU(%d) APIC busy for 100ms.\n", ThisCPU()); + } + + DPRINT("Synchronizing Arb IDs.\n"); + APICWrite(APIC_ICR0, APIC_ICR0_DESTS_ALL | APIC_ICR0_LEVEL | APIC_DM_INIT); +} + + +VOID APICSendIPI( + ULONG Target, + ULONG DeliveryMode, + ULONG IntNum, + ULONG Level) +{ + ULONG tmp, i, flags; + + pushfl(flags); + __asm__ ("\n\tcli\n\t"); + + /* Wait up to 100ms for the APIC to become ready */ + for (i = 0; i < 10000; i++) { + tmp = APICRead(APIC_ICR0); + /* Check Delivery Status */ + if ((tmp & APIC_ICR0_DS) == 0) + break; + APICSleep(10); + } + + if (i == 10000) { + DPRINT("CPU(%d) Previous IPI was not delivered after 100ms.\n", ThisCPU()); + } + + /* Setup the APIC to deliver the IPI */ + tmp = APICRead(APIC_ICR1); + tmp &= 0x00FFFFFF; + APICWrite(APIC_ICR1, tmp | SET_APIC_DEST_FIELD(Target)); + + tmp = APICRead(APIC_ICR0); + tmp &= ~(APIC_ICR0_LEVEL | APIC_ICR0_DESTM | APIC_ICR0_DM | APIC_ICR0_VECTOR); + tmp |= (DeliveryMode | IntNum | Level); + + if (Target == APIC_TARGET_SELF) { + tmp |= APIC_ICR0_DESTS_SELF; + } else if (Target == APIC_TARGET_ALL) { + tmp |= APIC_ICR0_DESTS_ALL; + } else if (Target == APIC_TARGET_ALL_BUT_SELF) { + tmp |= APIC_ICR0_DESTS_ALL_BUT_SELF; + } else { + tmp |= APIC_ICR0_DESTS_FIELD; + } + + /* Now, fire off the IPI */ + APICWrite(APIC_ICR0, tmp); + + popfl(flags); +} + + +BOOLEAN VerifyLocalAPIC( + VOID) +{ + UINT reg0, reg1; + + /* The version register is read-only in a real APIC */ + reg0 = APICRead(APIC_VER); + APICWrite(APIC_VER, reg0 ^ APIC_VER_MASK); + reg1 = APICRead(APIC_VER); + + if (reg1 != reg0) + return FALSE; + + /* The ID register is read/write in a real APIC */ + reg0 = APICRead(APIC_ID); + APICWrite(APIC_ID, reg0 ^ APIC_ID_MASK); + reg1 = APICRead(APIC_ID); + APICWrite(APIC_ID, reg0); + if (reg1 != (reg0 ^ APIC_ID_MASK)) + return FALSE; + + return TRUE; +} + + +static VOID SetInterruptGate( + ULONG index, + ULONG address) +{ + IDT_DESCRIPTOR *idt; + + idt = (IDT_DESCRIPTOR*)((ULONG)KeGetCurrentKPCR()->IDT + index * sizeof(IDT_DESCRIPTOR)); + idt->a = (((ULONG)address)&0xffff) + (KERNEL_CS << 16); + idt->b = 0x8f00 + (((ULONG)address)&0xffff0000); +} + + +VOID MpsTimerHandler( + VOID) +{ +#if 0 + KIRQL OldIrql; +#endif + + DPRINT("T1"); + + /* + * Acknowledge the interrupt + */ + APICSendEOI(); +#if 0 + /* + * Notify the rest of the kernel of the raised irq level + */ + OldIrql = KeRaiseIrqlToSynchLevel(); +#endif + __asm__("sti\n\t"); + + /* + * Call the dispatcher + */ + PsDispatchThread(THREAD_STATE_RUNNABLE); + +#if 0 + /* + * Lower irq level + */ + KeLowerIrql(OldIrql); +#endif +} + + +VOID MpsErrorHandler( + VOID) +{ + ULONG tmp1, tmp2; + + APICDump(); + + tmp1 = APICRead(APIC_ESR); + APICWrite(APIC_ESR, 0); + tmp2 = APICRead(APIC_ESR); + + /* + * Acknowledge the interrupt + */ + APICSendEOI(); + + /* Here is what the APIC error bits mean: + 0: Send CS error + 1: Receive CS error + 2: Send accept error + 3: Receive accept error + 4: Reserved + 5: Send illegal vector + 6: Received illegal vector + 7: Illegal register address + */ + DPRINT1("APIC error on CPU(%d) ESR(%x)(%x)\n", ThisCPU(), tmp1, tmp2); + for (;;); +} + + +VOID MpsSpuriousHandler( + VOID) +{ + DPRINT1("Spurious interrupt on CPU(%d)\n", ThisCPU()); + + /* + * Acknowledge the interrupt + */ + APICSendEOI(); + APICDump(); + for (;;); +} + + +VOID APICSetup( + VOID) +{ + ULONG CPU, tmp; + + CPU = ThisCPU(); + + /* + * Intel recommends to set DFR, LDR and TPR before enabling + * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel + * document number 292116). So here it goes... + */ + + /* + * Put the APIC into flat delivery mode. + * Must be "all ones" explicitly for 82489DX. + */ + APICWrite(APIC_DFR, 0xFFFFFFFF); + + /* + * Set up the logical destination ID. + */ + tmp = APICRead(APIC_LDR); + tmp &= ~APIC_LDR_MASK; + tmp |= (1 << (CPU + 24)); + APICWrite(APIC_LDR, tmp); + + /* Accept all interrupts */ + tmp = (APICRead(APIC_TPR) & ~APIC_TPR_PRI); + APICWrite(APIC_TPR, tmp); + + /* Enable local APIC */ + tmp = APICRead(APIC_SIVR) | APIC_SIVR_ENABLE | APIC_SIVR_FOCUS; // No focus processor + + /* Set spurious interrupt vector */ + tmp |= SPURIOUS_VECTOR; + + APICWrite(APIC_SIVR, tmp); + + /* + * Only the BP should see the LINT1 NMI signal, obviously. + */ + if (CPU == 0) + tmp = APIC_DM_NMI; + else + tmp = APIC_DM_NMI | APIC_LVT_MASKED; + if (!APIC_INTEGRATED(CPUMap[CPU].APICVersion)) /* 82489DX */ + tmp |= APIC_LVT_LEVEL_TRIGGER; + APICWrite(APIC_LINT1, tmp); + + if (APIC_INTEGRATED(CPUMap[CPU].APICVersion)) { /* !82489DX */ + if (CPUMap[CPU].MaxLVT > 3) { /* Due to the Pentium erratum 3AP */ + APICWrite(APIC_ESR, 0); + } + + tmp = APICRead(APIC_ESR); + DPRINT("ESR value before enabling vector: 0x%X\n", tmp); + + /* Enable sending errors */ + tmp = ERROR_VECTOR; + APICWrite(APIC_LVT3, tmp); + + /* + * Spec says clear errors after enabling vector + */ + if (CPUMap[CPU].MaxLVT > 3) + APICWrite(APIC_ESR, 0); + tmp = APICRead(APIC_ESR); + DPRINT("ESR value after enabling vector: 0x%X\n", tmp); + } +} + +VOID +HaliInitBSP( + VOID) +{ + PUSHORT ps; + + /* Only initialize the BSP once */ + if (BSPInitialized) + return; + + BSPInitialized = TRUE; + + DPRINT("APIC is mapped at 0x%X\n", APICBase); + + if (VerifyLocalAPIC()) { + DPRINT("APIC found\n"); + } else { + DPRINT1("No APIC found\n"); + KeBugCheck(0); + } + + CPUMap[BootCPU].MaxLVT = APICGetMaxLVT(); + + SetInterruptGate(LOCAL_TIMER_VECTOR, (ULONG)MpsTimerInterrupt); + SetInterruptGate(ERROR_VECTOR, (ULONG)MpsErrorInterrupt); + SetInterruptGate(SPURIOUS_VECTOR, (ULONG)MpsSpuriousInterrupt); + + if (APICMode == amPIC) { + EnableSMPMode(); + } + + APICSetup(); + + /* BIOS data segment */ + BIOSBase = (PULONG)BIOS_AREA; + + /* Area for communicating with the APs */ + CommonBase = (PULONG)COMMON_AREA; + + /* Copy bootstrap code to common area */ + memcpy((PVOID)((ULONG)CommonBase + PAGESIZE), + &APstart, + (ULONG)&APend - (ULONG)&APstart + 1); + + /* Set shutdown code */ + CMOS_WRITE(0xF, 0xA); + + /* Set warm reset vector */ + ps = (PUSHORT)((ULONG)BIOSBase + 0x467); + *ps = (COMMON_AREA + PAGESIZE) & 0xF; + + ps = (PUSHORT)((ULONG)BIOSBase + 0x469); + *ps = (COMMON_AREA + PAGESIZE) >> 4; + + /* Calibrate APIC timer */ + APICCalibrateTimer(0); + + /* The boot processor is online */ + OnlineCPUs = (1 << 0); +} + +#endif /* MP */ + +VOID +STDCALL +HalInitializeProcessor ( + ULONG ProcessorNumber, + PVOID ProcessorStack) +{ + +#ifdef MP + + PCOMMON_AREA_INFO Common; + ULONG StartupCount; + ULONG DeliveryStatus; + ULONG AcceptStatus; + ULONG CPU, i, j; + ULONG tmp, maxlvt; + + if (ProcessorNumber == 0) { + /* Boot processor is already initialized */ + NextCPU = 1; + return; + } + + if (NextCPU < CPUCount) { + CPU = NextCPU; + + DPRINT("Attempting to boot CPU %d\n", CPU); + + /* Send INIT IPI */ + APICSendIPI(CPUMap[CPU].APICId, APIC_DM_INIT, 0, APIC_ICR0_LEVEL_ASSERT); + + APICSleep(200); + + /* Deassert INIT */ + APICSendIPI(CPUMap[CPU].APICId, APIC_DM_INIT, 0, APIC_ICR0_LEVEL_DEASSERT); + + if (APIC_INTEGRATED(CPUMap[CPU].APICVersion)) { + /* Clear APIC errors */ + APICWrite(APIC_ESR, 0); + tmp = (APICRead(APIC_ESR) & APIC_ESR_MASK); + } + + Common = (PCOMMON_AREA_INFO)CommonBase; + + /* Write the location of the AP stack */ + Common->Stack = (ULONG)ProcessorStack; + + DPRINT("CPU %d got stack at 0x%X\n", CPU, Common->Stack); +#if 0 + for (j = 0; j < 16; j++) { + Common->Debug[j] = 0; + } +#endif + + maxlvt = APICGetMaxLVT(); + + /* Is this a local APIC or an 82489DX? */ + StartupCount = (APIC_INTEGRATED(CPUMap[CPU].APICVersion)) ? 2 : 0; + + for (i = 1; i <= StartupCount; i++) + { + /* It's a local APIC, so send STARTUP IPI */ + DPRINT("Sending startup signal %d\n", i); + /* Clear errors */ + APICWrite(APIC_ESR, 0); + APICRead(APIC_ESR); + + APICSendIPI(CPUMap[CPU].APICId, + 0, + APIC_DM_STARTUP | ((COMMON_AREA + PAGESIZE) >> 12), + APIC_ICR0_LEVEL_DEASSERT); + + /* Wait up to 10ms for IPI to be delivered */ + j = 0; + do { + APICSleep(10); + + /* Check Delivery Status */ + DeliveryStatus = APICRead(APIC_ICR0) & APIC_ICR0_DS; + + j++; + } while ((DeliveryStatus) && (j < 1000)); + + APICSleep(200); + + /* + * Due to the Pentium erratum 3AP. + */ + if (maxlvt > 3) { + APICRead(APIC_SIVR); + APICWrite(APIC_ESR, 0); + } + + AcceptStatus = APICRead(APIC_ESR) & APIC_ESR_MASK; + + if (DeliveryStatus || AcceptStatus) { + break; + } + } + + if (DeliveryStatus) { + DPRINT("STARTUP IPI for CPU %d was never delivered.\n", CPU); + } + + if (AcceptStatus) { + DPRINT("STARTUP IPI for CPU %d was never accepted.\n", CPU); + } + + if (!(DeliveryStatus || AcceptStatus)) { + + /* Wait no more than 5 seconds for processor to boot */ + DPRINT("Waiting for 5 seconds for CPU %d to boot\n", CPU); + + /* Wait no more than 5 seconds */ + for (j = 0; j < 50000; j++) { + + if (CPUMap[CPU].Flags & CPU_ENABLED) + break; + + APICSleep(100); + } + } + + if (CPUMap[CPU].Flags & CPU_ENABLED) { + DbgPrint("CPU %d is now running\n", CPU); + } else { + DbgPrint("Initialization of CPU %d failed\n", CPU); + } + +#if 0 + DPRINT("Debug bytes are:\n"); + + for (j = 0; j < 4; j++) { + DPRINT("0x%08X 0x%08X 0x%08X 0x%08X.\n", + Common->Debug[j*4+0], + Common->Debug[j*4+1], + Common->Debug[j*4+2], + Common->Debug[j*4+3]); + } +#endif + NextCPU++; + } + +#endif /* MP */ + +} + +BOOLEAN +STDCALL +HalAllProcessorsStarted ( + VOID + ) +{ + +#ifdef MP + + return (NextCPU >= CPUCount); + +#else /* MP */ + + if (BSPInitialized) { + return TRUE; + } else { + BSPInitialized = TRUE; + return FALSE; + } + +#endif /* MP */ + +} + +BOOLEAN +STDCALL +HalStartNextProcessor ( + ULONG Unknown1, + ULONG Unknown2 + ) +{ +#ifdef MP + + /* Display the APIC registers for debugging */ + switch (Unknown1) { + case 0: + APICDump(); + break; + case 1: + IOAPICDump(); + } + for(;;); + + return (NextCPU >= CPUCount); + +#endif /* MP */ + + return FALSE; +} + + +#ifdef MP + +ULONG MPChecksum( + PUCHAR Base, + ULONG Size) +/* + * Checksum an MP configuration block + */ +{ + ULONG Sum = 0; + + while (Size--) + Sum += *Base++; + + return((UCHAR)Sum); +} + + +PCHAR HaliMPFamily( + ULONG Family, + ULONG Model) +{ + static CHAR str[32]; + static PCHAR CPUs[] = + { + "80486DX", "80486DX", + "80486SX", "80486DX/2 or 80487", + "80486SL", "Intel5X2(tm)", + "Unknown", "Unknown", + "80486DX/4" + }; + if (Family == 0x6) + return ("Pentium(tm) Pro"); + if (Family == 0x5) + return ("Pentium(tm)"); + if (Family == 0x0F && Model == 0x0F) + return("Special controller"); + if (Family == 0x0F && Model == 0x00) + return("Pentium 4(tm)"); + if (Family == 0x04 && Model < 9) + return CPUs[Model]; + sprintf(str, "Unknown CPU with family ID %ld and model ID %ld", Family, Model); + return str; +} + + +static VOID HaliMPProcessorInfo(PMP_CONFIGURATION_PROCESSOR m) +{ + ULONG ver; + + if (!(m->CpuFlags & CPU_FLAG_ENABLED)) + return; + + DPRINT("Processor #%d %s APIC version %d\n", + m->ApicId, + HaliMPFamily((m->FeatureFlags & CPU_FAMILY_MASK) >> 8, + (m->FeatureFlags & CPU_MODEL_MASK) >> 4), + m->ApicVersion); + + if (m->FeatureFlags & (1 << 0)) + DPRINT(" Floating point unit present.\n"); + if (m->FeatureFlags & (1 << 7)) + DPRINT(" Machine Exception supported.\n"); + if (m->FeatureFlags & (1 << 8)) + DPRINT(" 64 bit compare & exchange supported.\n"); + if (m->FeatureFlags & (1 << 9)) + DPRINT(" Internal APIC present.\n"); + if (m->FeatureFlags & (1 << 11)) + DPRINT(" SEP present.\n"); + if (m->FeatureFlags & (1 << 12)) + DPRINT(" MTRR present.\n"); + if (m->FeatureFlags & (1 << 13)) + DPRINT(" PGE present.\n"); + if (m->FeatureFlags & (1 << 14)) + DPRINT(" MCA present.\n"); + if (m->FeatureFlags & (1 << 15)) + DPRINT(" CMOV present.\n"); + if (m->FeatureFlags & (1 << 16)) + DPRINT(" PAT present.\n"); + if (m->FeatureFlags & (1 << 17)) + DPRINT(" PSE present.\n"); + if (m->FeatureFlags & (1 << 18)) + DPRINT(" PSN present.\n"); + if (m->FeatureFlags & (1 << 19)) + DPRINT(" Cache Line Flush Instruction present.\n"); + /* 20 Reserved */ + if (m->FeatureFlags & (1 << 21)) + DPRINT(" Debug Trace and EMON Store present.\n"); + if (m->FeatureFlags & (1 << 22)) + DPRINT(" ACPI Thermal Throttle Registers present.\n"); + if (m->FeatureFlags & (1 << 23)) + DPRINT(" MMX present.\n"); + if (m->FeatureFlags & (1 << 24)) + DPRINT(" FXSR present.\n"); + if (m->FeatureFlags & (1 << 25)) + DPRINT(" XMM present.\n"); + if (m->FeatureFlags & (1 << 26)) + DPRINT(" Willamette New Instructions present.\n"); + if (m->FeatureFlags & (1 << 27)) + DPRINT(" Self Snoop present.\n"); + /* 28 Reserved */ + if (m->FeatureFlags & (1 << 29)) + DPRINT(" Thermal Monitor present.\n"); + /* 30, 31 Reserved */ + + CPUMap[CPUCount].APICId = m->ApicId; + + CPUMap[CPUCount].Flags = CPU_USABLE; + + if (m->CpuFlags & CPU_FLAG_BSP) { + DPRINT(" Bootup CPU\n"); + CPUMap[CPUCount].Flags |= CPU_BSP; + BootCPU = m->ApicId; + } + + if (m->ApicId > MAX_CPU) { + DPRINT("Processor #%d INVALID. (Max ID: %d).\n", m->ApicId, MAX_CPU); + return; + } + ver = m->ApicVersion; + + /* + * Validate version + */ + if (ver == 0x0) { + DPRINT("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->ApicId); + ver = 0x10; + } + CPUMap[CPUCount].APICVersion = ver; + + CPUCount++; +} + +static VOID HaliMPBusInfo(PMP_CONFIGURATION_BUS m) +{ + static ULONG CurrentPCIBusId = 0; + CHAR str[7]; + + memcpy(str, m->BusType, 6); + str[6] = 0; + DPRINT("Bus #%d is %s\n", m->BusId, str); + + if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) { + BUSMap[m->BusId] = MP_BUS_ISA; + } else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) { + BUSMap[m->BusId] = MP_BUS_EISA; + } else if (strncmp(str, BUSTYPE_PCI, sizeof(BUSTYPE_PCI)-1) == 0) { + BUSMap[m->BusId] = MP_BUS_PCI; + PCIBUSMap[m->BusId] = CurrentPCIBusId; + CurrentPCIBusId++; + } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) { + BUSMap[m->BusId] = MP_BUS_MCA; + } else { + DPRINT("Unknown bustype %s - ignoring\n", str); + } +} + +static VOID HaliMPIOApicInfo(PMP_CONFIGURATION_IOAPIC m) +{ + if (!(m->ApicFlags & CPU_FLAG_ENABLED)) + return; + + DPRINT("I/O APIC #%d Version %d at 0x%lX.\n", + m->ApicId, m->ApicVersion, m->ApicAddress); + if (IOAPICCount > MAX_IOAPIC) { + DPRINT("Max # of I/O APICs (%d) exceeded (found %d).\n", + MAX_IOAPIC, IOAPICCount); + DPRINT1("Recompile with bigger MAX_IOAPIC!.\n"); + KeBugCheck(0); + } + IOAPICMap[IOAPICCount].ApicId = m->ApicId; + IOAPICMap[IOAPICCount].ApicVersion = m->ApicVersion; + IOAPICMap[IOAPICCount].ApicAddress = m->ApicAddress; + IOAPICCount++; +} + +static VOID HaliMPIntSrcInfo(PMP_CONFIGURATION_INTSRC m) +{ + DPRINT("Int: type %d, pol %d, trig %d, bus %d," + " IRQ %02x, APIC ID %x, APIC INT %02x\n", + m->IrqType, m->IrqFlag & 3, + (m->IrqFlag >> 2) & 3, m->SrcBusId, + m->SrcBusIrq, m->DstApicId, m->DstApicInt); + if (IRQCount > MAX_IRQ_SOURCE) { + DPRINT1("Max # of irq sources exceeded!!\n"); + KeBugCheck(0); + } + + IRQMap[IRQCount] = *m; + IRQCount++; +} + +static VOID HaliMPIntLocalInfo(PMP_CONFIGURATION_INTLOCAL m) +{ + DPRINT("Lint: type %d, pol %d, trig %d, bus %d," + " IRQ %02x, APIC ID %x, APIC LINT %02x\n", + m->IrqType, m->IrqFlag & 3, + (m->IrqFlag >> 2) & 3, m->SrcBusId, + m->SrcBusIrq, m->DstApicId, m->DstApicLInt); + /* + * Well it seems all SMP boards in existence + * use ExtINT/LVT1 == LINT0 and + * NMI/LVT2 == LINT1 - the following check + * will show us if this assumptions is false. + * Until then we do not have to add baggage. + */ + if ((m->IrqType == INT_EXTINT) && (m->DstApicLInt != 0)) { + DPRINT1("Invalid MP table!\n"); + KeBugCheck(0); + } + if ((m->IrqType == INT_NMI) && (m->DstApicLInt != 1)) { + DPRINT1("Invalid MP table!\n"); + KeBugCheck(0); + } +} + + +VOID +HaliReadMPConfigTable( + PMP_CONFIGURATION_TABLE Table) +/* + PARAMETERS: + Table = Pointer to MP configuration table + */ +{ + PUCHAR Entry; + ULONG Count; + + if (Table->Signature != MPC_SIGNATURE) + { + PUCHAR pc = (PUCHAR)&Table->Signature; + + DbgPrint("Bad MP configuration block signature: %c%c%c%c\n", + pc[0], pc[1], pc[2], pc[3]); + KeBugCheck(0); + return; + } + + if (MPChecksum((PUCHAR)Table, Table->Length)) + { + DbgPrint("Bad MP configuration block checksum\n"); + KeBugCheck(0); + return; + } + + if (Table->Specification < 0x04) + { + DbgPrint("Bad MP configuration table version (%d)\n", + Table->Specification); + KeBugCheck(0); + return; + } + + APICBase = (PULONG)Table->LocalAPICAddress; + if (APICBase != (PULONG)APIC_DEFAULT_BASE) + { + DbgPrint("APIC base address is at 0x%X. " \ + "I cannot handle non-standard adresses\n", APICBase); + KeBugCheck(0); + } + + Entry = (PUCHAR)((PVOID)Table + sizeof(MP_CONFIGURATION_TABLE)); + Count = 0; + while (Count < (Table->Length - sizeof(MP_CONFIGURATION_TABLE))) + { + /* Switch on type */ + switch (*Entry) + { + case MPCTE_PROCESSOR: + { + HaliMPProcessorInfo((PMP_CONFIGURATION_PROCESSOR)Entry); + Entry += sizeof(MP_CONFIGURATION_PROCESSOR); + Count += sizeof(MP_CONFIGURATION_PROCESSOR); + break; + } + case MPCTE_BUS: + { + HaliMPBusInfo((PMP_CONFIGURATION_BUS)Entry); + Entry += sizeof(MP_CONFIGURATION_BUS); + Count += sizeof(MP_CONFIGURATION_BUS); + break; + } + case MPCTE_IOAPIC: + { + HaliMPIOApicInfo((PMP_CONFIGURATION_IOAPIC)Entry); + Entry += sizeof(MP_CONFIGURATION_IOAPIC); + Count += sizeof(MP_CONFIGURATION_IOAPIC); + break; + } + case MPCTE_INTSRC: + { + HaliMPIntSrcInfo((PMP_CONFIGURATION_INTSRC)Entry); + Entry += sizeof(MP_CONFIGURATION_INTSRC); + Count += sizeof(MP_CONFIGURATION_INTSRC); + break; + } + case MPCTE_LINTSRC: + { + HaliMPIntLocalInfo((PMP_CONFIGURATION_INTLOCAL)Entry); + Entry += sizeof(MP_CONFIGURATION_INTLOCAL); + Count += sizeof(MP_CONFIGURATION_INTLOCAL); + break; + } + default: + DbgPrint("Unknown entry in MPC table\n"); + KeBugCheck(0); + } + } +} + + +static VOID HaliConstructDefaultIOIrqMPTable( + ULONG Type) +{ + MP_CONFIGURATION_INTSRC intsrc; + ULONG i; + + intsrc.Type = MPCTE_INTSRC; + intsrc.IrqFlag = 0; /* conforming */ + intsrc.SrcBusId = 0; + intsrc.DstApicId = IOAPICMap[0].ApicId; + + intsrc.IrqType = INT_VECTORED; + for (i = 0; i < 16; i++) { + switch (Type) { + case 2: + if (i == 0 || i == 13) + continue; /* IRQ0 & IRQ13 not connected */ + /* Fall through */ + default: + if (i == 2) + continue; /* IRQ2 is never connected */ + } + + intsrc.SrcBusIrq = i; + intsrc.DstApicInt = i ? i : 2; /* IRQ0 to INTIN2 */ + HaliMPIntSrcInfo(&intsrc); + } + + intsrc.IrqType = INT_EXTINT; + intsrc.SrcBusIrq = 0; + intsrc.DstApicInt = 0; /* 8259A to INTIN0 */ + HaliMPIntSrcInfo(&intsrc); +} + + +static VOID HaliConstructDefaultISAMPTable( + ULONG Type) +{ + MP_CONFIGURATION_PROCESSOR processor; + MP_CONFIGURATION_BUS bus; + MP_CONFIGURATION_IOAPIC ioapic; + MP_CONFIGURATION_INTLOCAL lintsrc; + ULONG linttypes[2] = { INT_EXTINT, INT_NMI }; + ULONG i; + + APICBase = (PULONG)APIC_DEFAULT_BASE; + + /* + * 2 CPUs, numbered 0 & 1. + */ + processor.Type = MPCTE_PROCESSOR; + /* Either an integrated APIC or a discrete 82489DX. */ + processor.ApicVersion = Type > 4 ? 0x10 : 0x01; + processor.CpuFlags = CPU_FLAG_ENABLED | CPU_FLAG_BSP; + /* FIXME: Get this from the bootstrap processor */ + processor.CpuSignature = 0; + processor.FeatureFlags = 0; + processor.Reserved[0] = 0; + processor.Reserved[1] = 0; + for (i = 0; i < 2; i++) { + processor.ApicId = i; + HaliMPProcessorInfo(&processor); + processor.CpuFlags &= ~CPU_FLAG_BSP; + } + + bus.Type = MPCTE_BUS; + bus.BusId = 0; + switch (Type) { + default: + DPRINT("Unknown standard configuration %d\n", Type); + /* Fall through */ + case 1: + case 5: + memcpy(bus.BusType, "ISA ", 6); + break; + case 2: + case 6: + case 3: + memcpy(bus.BusType, "EISA ", 6); + break; + case 4: + case 7: + memcpy(bus.BusType, "MCA ", 6); + } + HaliMPBusInfo(&bus); + if (Type > 4) { + bus.Type = MPCTE_BUS; + bus.BusId = 1; + memcpy(bus.BusType, "PCI ", 6); + HaliMPBusInfo(&bus); + } + + ioapic.Type = MPCTE_IOAPIC; + ioapic.ApicId = 2; + ioapic.ApicVersion = Type > 4 ? 0x10 : 0x01; + ioapic.ApicFlags = MP_IOAPIC_USABLE; + ioapic.ApicAddress = IOAPIC_DEFAULT_BASE; + HaliMPIOApicInfo(&ioapic); + + /* + * We set up most of the low 16 IO-APIC pins according to MPS rules. + */ + HaliConstructDefaultIOIrqMPTable(Type); + + lintsrc.Type = MPCTE_LINTSRC; + lintsrc.IrqType = 0; + lintsrc.IrqFlag = 0; /* conforming */ + lintsrc.SrcBusId = 0; + lintsrc.SrcBusIrq = 0; + lintsrc.DstApicId = MP_APIC_ALL; + for (i = 0; i < 2; i++) { + lintsrc.IrqType = linttypes[i]; + lintsrc.DstApicLInt = i; + HaliMPIntLocalInfo(&lintsrc); + } +} + +BOOLEAN +HaliScanForMPConfigTable( + ULONG Base, + ULONG Size) +/* + PARAMETERS: + Base = Base address of region + Size = Length of region to check + RETURNS: + TRUE if a valid MP configuration table was found + */ +{ + PULONG bp = (PULONG)Base; + MP_FLOATING_POINTER* mpf; + + while (Size > 0) + { + if (*bp == MPF_SIGNATURE) + { + DbgPrint("Found MPF signature at %x, checksum %x\n", bp, + MPChecksum((PUCHAR)bp, 16)); + if (MPChecksum((PUCHAR)bp, 16) == 0) + { + mpf = (MP_FLOATING_POINTER*)bp; + + DbgPrint("Intel MultiProcessor Specification v1.%d compliant system.\n", + mpf->Specification); + + if (mpf->Feature2 & FEATURE2_IMCRP) { + APICMode = amPIC; + DPRINT("Running in IMCR and PIC compatibility mode.\n") + } else { + APICMode = amVWIRE; + DPRINT("Running in Virtual Wire compatibility mode.\n"); + } + + switch (mpf->Feature1) + { + case 0: + /* Non standard configuration */ + break; + case 1: + DPRINT("ISA\n"); + break; + case 2: + DPRINT("EISA with no IRQ8 chaining\n"); + break; + case 3: + DPRINT("EISA\n"); + break; + case 4: + DPRINT("MCA\n"); + break; + case 5: + DPRINT("ISA and PCI\n"); + break; + case 6: + DPRINT("EISA and PCI\n"); + break; + case 7: + DPRINT("MCA and PCI\n"); + break; + default: + DbgPrint("Unknown standard configuration %d\n", mpf->Feature1); + return FALSE; + } + + CPUCount = 0; + IOAPICCount = 0; + IRQCount = 0; + + if ((mpf->Feature1 == 0) && (mpf->Address)) { + HaliReadMPConfigTable((PMP_CONFIGURATION_TABLE)mpf->Address); + } else { + HaliConstructDefaultISAMPTable(mpf->Feature1); + } + + return TRUE; + } + } + bp += 4; + Size -= 16; + } + return FALSE; +} + + +VOID +HalpInitMPS( + VOID) +{ + USHORT EBDA; + ULONG CPU; + + /* Only initialize MP system once. Once called the first time, + each subsequent call is part of the initialization sequence + for an application processor. */ + if (MPSInitialized) { + CPU = ThisCPU(); + + DPRINT("CPU %d says it is now booted.\n", CPU); + + APICSetup(); + APICCalibrateTimer(CPU); + + /* This processor is now booted */ + CPUMap[CPU].Flags |= CPU_ENABLED; + OnlineCPUs |= (1 << CPU); + + return; + } + + MPSInitialized = TRUE; + + /* + Scan the system memory for an MP configuration table + 1) Scan the first KB of system base memory + 2) Scan the last KB of system base memory + 3) Scan the BIOS ROM address space between 0F0000h and 0FFFFFh + 4) Scan the Extended BIOS Data Area + */ + + if (!HaliScanForMPConfigTable(0x0, 0x400)) { + if (!HaliScanForMPConfigTable(0x9FC00, 0x400)) { + if (!HaliScanForMPConfigTable(0xF0000, 0x10000)) { + EBDA = *((PUSHORT)0x040E); + EBDA <<= 4; + if (!HaliScanForMPConfigTable((ULONG)EBDA, 0x1000)) { + DbgPrint("No multiprocessor compliant system found.\n"); + KeBugCheck(0); + } + } + } + } + + /* Setup IRQ to vector translation map */ + memset(&IRQVectorMap, sizeof(IRQVectorMap), 0); + + /* Initialize the bootstrap processor */ + HaliInitBSP(); + + /* Setup I/O APIC */ + IOAPICSetup(); + + /* Setup busy waiting */ + HalpCalibrateStallExecution(); + + /* We can now enable interrupts */ + __asm__ __volatile__ ("sti\n\t"); + + NextCPU = 0; +} + +#endif /* MP */ + +/* EOF */ diff --git a/reactos/hal/halx86/mps.S b/reactos/hal/halx86/mps.S new file mode 100644 index 00000000000..e89087c3d83 --- /dev/null +++ b/reactos/hal/halx86/mps.S @@ -0,0 +1,76 @@ +/* $Id: mps.S,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/mps.S + * PURPOSE: Intel MultiProcessor specification support + * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * Created 12/04/2001 + */ + +/* INCLUDES ******************************************************************/ + +#include + +/* FUNCTIONS *****************************************************************/ + +#define BEFORE \ + pusha; \ + pushl %ds; \ + pushl %es; \ + pushl %fs; \ + pushl %gs; \ + movl $(KERNEL_DS), %eax; \ + movl %eax, %ds; \ + movl %eax, %es; \ + movl %eax, %gs; \ + movl $(PCR_SELECTOR), %eax; \ + movl %eax, %fs; + +#define AFTER \ + popl %gs; \ + popl %fs; \ + popl %es; \ + popl %ds; \ + popa; + +.globl _MpsTimerInterrupt +_MpsTimerInterrupt: + /* Save registers */ + BEFORE + + /* Call the C handler */ + call _MpsTimerHandler + + /* Return to the caller */ + AFTER + iret + + +.globl _MpsErrorInterrupt +_MpsErrorInterrupt: + /* Save registers */ + BEFORE + + /* Call the C handler */ + call _MpsErrorHandler + + /* Return to the caller */ + AFTER + iret + + +.globl _MpsSpuriousInterrupt +_MpsSpuriousInterrupt: + /* Save registers */ + BEFORE + + /* Call the C handler */ + call _MpsSpuriousHandler + + /* Return to the caller */ + AFTER + iret + +/* EOF */ diff --git a/reactos/hal/halx86/mpsboot.asm b/reactos/hal/halx86/mpsboot.asm new file mode 100644 index 00000000000..684b69ab823 --- /dev/null +++ b/reactos/hal/halx86/mpsboot.asm @@ -0,0 +1,106 @@ +; +; COPYRIGHT: See COPYING in the top level directory +; PROJECT: ReactOS kernel +; FILE: ntoskrnl/hal/x86/mpsboot.c +; PURPOSE: Bootstrap code for application processors +; PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) +; UPDATE HISTORY: +; Created 12/04/2001 +; + +; +; Memory map at this stage is: +; 0x2000 Location of our stack +; 0x3000 Startup code for the APs (this code) +; + +; +; Base address of common area for BSP and APs +; +LOAD_BASE equ 00200000h + +; +; Magic value to be put in EAX when multiboot.S is called as part of the +; application processor initialization process +; +AP_MAGIC equ 12481020h + +; +; Segment selectors +; +%define KERNEL_CS (0x8) +%define KERNEL_DS (0x10) + +section .text + +global _APstart +global _APend + +; 16 bit code +BITS 16 + +_APstart: + cli ; Just in case + + xor ax, ax + mov ds, ax + mov ss, ax + + mov eax, 3000h + APgdt - _APstart + lgdt [eax] + + mov eax, cr0 + or eax, 00010001h ; Turn on protected mode and write protection + mov cr0, eax + + db 0eah + dw 3000h + flush - _APstart, KERNEL_CS + +; 32 bit code +BITS 32 + +flush: + mov ax, KERNEL_DS + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + ; Setup a stack for the AP + mov eax, 2000h + mov eax, [eax] + mov esp, eax + + ; Jump to start of the kernel with AP magic in eax + mov eax, AP_MAGIC + jmp dword KERNEL_CS:(LOAD_BASE + 0x1000) + + ; Never get here + + +; Temporary GDT descriptor for the APs + +APgdt: +; Limit + dw (3*8)-1 +; Base + dd 3000h + gdt - _APstart + +gdt: + dw 0x0 ; Null descriptor + dw 0x0 + dw 0x0 + dw 0x0 + + dw 0xffff ; Kernel code descriptor + dw 0x0000 + dw 0x9a00 + dw 0x00cf + + dw 0xffff ; Kernel data descriptor + dw 0x0000 + dw 0x9200 + dw 0x00cf + +_APend: diff --git a/reactos/hal/halx86/mpsirql.c b/reactos/hal/halx86/mpsirql.c new file mode 100644 index 00000000000..392d1d2486d --- /dev/null +++ b/reactos/hal/halx86/mpsirql.c @@ -0,0 +1,417 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/mpsirql.c + * PURPOSE: Implements IRQLs for multiprocessor systems + * PROGRAMMERS: David Welch (welch@cwcom.net) + * Casper S. Hornstrup (chorns@users.sourceforge.net) + * UPDATE HISTORY: + * 12/04/2001 CSH Created + */ + +/* INCLUDES *****************************************************************/ + +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/; + +extern IMPORTED ULONG DpcQueueSize; + +static VOID KeSetCurrentIrql(KIRQL newlvl); + +/* FUNCTIONS ****************************************************************/ + +#define IRQL2TPR(irql) (APIC_TPR_MIN + ((irql - DISPATCH_LEVEL - 1) * 8)) + +static VOID HiSetCurrentPriority( + ULONG Priority) +{ + //DbgPrint(" P(0x%X)\n", Priority); + APICWrite(APIC_TPR, Priority & APIC_TPR_PRI); +} + + +static VOID HiSwitchIrql(KIRQL OldIrql, ULONG Flags) +/* + * FUNCTION: Switches to the current irql + * NOTE: Must be called with interrupt disabled + */ +{ + PKTHREAD CurrentThread; + KIRQL CurrentIrql; + + //DbgPrint("HiSwitchIrql(OldIrql %d)\n", OldIrql); + + CurrentIrql = KeGetCurrentKPCR()->Irql; + + if (CurrentIrql >= IPI_LEVEL) + { + /* Block all interrupts */ + HiSetCurrentPriority(APIC_TPR_MAX); + return; + } + + if (CurrentIrql == CLOCK2_LEVEL) + { + HiSetCurrentPriority(APIC_TPR_MAX - 16); + popfl(Flags); + return; + } + + if (CurrentIrql > DISPATCH_LEVEL) + { + HiSetCurrentPriority(IRQL2TPR(CurrentIrql)); + popfl(Flags); + return; + } + + /* Pass all interrupts */ + HiSetCurrentPriority(0); + + if (CurrentIrql == DISPATCH_LEVEL) + { + popfl(Flags); + return; + } + + if (CurrentIrql == APC_LEVEL) + { + if (DpcQueueSize > 0 ) + { + KeSetCurrentIrql(DISPATCH_LEVEL); + __asm__("sti\n\t"); + KiDispatchInterrupt(); + __asm__("cli\n\t"); + KeSetCurrentIrql(PASSIVE_LEVEL); + } + popfl(Flags); + return; + } + + CurrentThread = KeGetCurrentThread(); + + if (CurrentIrql == PASSIVE_LEVEL && + CurrentThread != NULL && + CurrentThread->ApcState.KernelApcPending) + { + KeSetCurrentIrql(APC_LEVEL); + __asm__("sti\n\t"); + KiDeliverApc(0, 0, 0); + __asm__("cli\n\t"); + KeSetCurrentIrql(PASSIVE_LEVEL); + popfl(Flags); + } + else + { + popfl(Flags); + } +} + + +KIRQL STDCALL KeGetCurrentIrql (VOID) +/* + * PURPOSE: Returns the current irq level + * RETURNS: The current irq level + */ +{ + return(KeGetCurrentKPCR()->Irql); +} + + +static VOID KeSetCurrentIrql(KIRQL newlvl) +/* + * PURPOSE: Sets the current irq level without taking any action + */ +{ +// DPRINT("KeSetCurrentIrql(newlvl %x)\n",newlvl); + + KeGetCurrentKPCR()->Irql = newlvl; +} + + +/********************************************************************** + * 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 + ) +{ + KIRQL CurrentIrql; + KIRQL OldIrql; + ULONG Flags; + + //DbgPrint("KfLowerIrql(NewIrql %d)\n", NewIrql); + + pushfl(Flags); + __asm__ ("\n\tcli\n\t"); + + CurrentIrql = KeGetCurrentKPCR()->Irql; + + if (NewIrql > CurrentIrql) + { + DbgPrint ("(%s:%d) NewIrql %x CurrentIrql %x\n", + __FILE__, __LINE__, NewIrql, CurrentIrql); + KeBugCheck(0); + for(;;); + } + + OldIrql = CurrentIrql; + KeGetCurrentKPCR()->Irql = NewIrql; + HiSwitchIrql(OldIrql, Flags); +} + + +/********************************************************************** + * NAME EXPORTED + * KeLowerIrql + * + * DESCRIPTION + * Restores the irq level on the current processor + * + * ARGUMENTS + * NewIrql = Irql to lower to + * + * RETURN VALUE + * None + * + * NOTES + */ + +VOID +STDCALL +KeLowerIrql ( + KIRQL NewIrql + ) +{ + KfLowerIrql (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 CurrentIrql; + KIRQL OldIrql; + ULONG Flags; + + //DbgPrint("KfRaiseIrql(NewIrql %d)\n", NewIrql); + + pushfl(Flags); + __asm__ ("\n\tcli\n\t"); + + CurrentIrql = KeGetCurrentKPCR()->Irql; + + if (NewIrql < CurrentIrql) + { + DbgPrint ("%s:%d CurrentIrql %x NewIrql %x\n", + __FILE__,__LINE__,CurrentIrql,NewIrql); + KeBugCheck (0); + for(;;); + } + + OldIrql = CurrentIrql; + KeGetCurrentKPCR()->Irql = NewIrql; + + //DPRINT("NewIrql %x OldIrql %x\n", NewIrql, OldIrql); + HiSwitchIrql(OldIrql, Flags); + return OldIrql; +} + + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrql + * + * DESCRIPTION + * Raises the hardware priority (irql) + * + * ARGUMENTS + * NewIrql = Irql to raise to + * OldIrql (OUT) = Caller supplied storage for the previous irql + * + * RETURN VALUE + * None + * + * NOTES + * Calls KfRaiseIrql + */ + +VOID +STDCALL +KeRaiseIrql ( + KIRQL NewIrql, + PKIRQL OldIrql + ) +{ + *OldIrql = KfRaiseIrql (NewIrql); +} + + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrqlToDpcLevel + * + * DESCRIPTION + * Raises the hardware priority (irql) to DISPATCH level + * + * ARGUMENTS + * None + * + * RETURN VALUE + * Previous irq level + * + * NOTES + * Calls KfRaiseIrql + */ + +KIRQL +STDCALL +KeRaiseIrqlToDpcLevel (VOID) +{ + return KfRaiseIrql (DISPATCH_LEVEL); +} + + +/********************************************************************** + * NAME EXPORTED + * KeRaiseIrqlToSynchLevel + * + * DESCRIPTION + * Raises the hardware priority (irql) to CLOCK2 level + * + * ARGUMENTS + * None + * + * RETURN VALUE + * Previous irq level + * + * NOTES + * Calls KfRaiseIrql + */ + +KIRQL +STDCALL +KeRaiseIrqlToSynchLevel (VOID) +{ + return KfRaiseIrql (CLOCK2_LEVEL); +} + + +BOOLEAN STDCALL HalBeginSystemInterrupt (ULONG Vector, + KIRQL Irql, + PKIRQL OldIrql) +{ + DPRINT("Vector (0x%X) Irql (0x%X)\n", + Vector, Irql); + + if (Vector < FIRST_DEVICE_VECTOR || + Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) { + DPRINT("Not a device interrupt\n"); + return FALSE; + } + + /* + * Acknowledge the interrupt + */ + APICSendEOI(); + + *OldIrql = KeGetCurrentIrql(); + + KeSetCurrentIrql(Irql); + + return TRUE; +} + + +VOID STDCALL HalEndSystemInterrupt (KIRQL Irql, + ULONG Unknown2) +{ + KeSetCurrentIrql(Irql); +} + + +BOOLEAN STDCALL HalDisableSystemInterrupt (ULONG Vector, + ULONG Unknown2) +{ + ULONG irq; + + DPRINT("Vector (0x%X)\n", Vector); + + if (Vector < FIRST_DEVICE_VECTOR || + Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) { + DPRINT("Not a device interrupt\n"); + return FALSE; + } + + irq = VECTOR2IRQ(Vector); + + IOAPICMaskIrq(0, irq); + + return TRUE; +} + + +BOOLEAN STDCALL HalEnableSystemInterrupt (ULONG Vector, + ULONG Unknown2, + ULONG Unknown3) +{ + ULONG irq; + + DPRINT("Vector (0x%X)\n", Vector); + + if (Vector < FIRST_DEVICE_VECTOR || + Vector > FIRST_DEVICE_VECTOR + NUMBER_DEVICE_VECTORS) { + DPRINT("Not a device interrupt\n"); + return FALSE; + } + + irq = VECTOR2IRQ(Vector); + + IOAPICUnmaskIrq(0, irq); + + return TRUE; +} + +/* EOF */ diff --git a/reactos/hal/halx86/pci.c b/reactos/hal/halx86/pci.c new file mode 100644 index 00000000000..ca538432ad7 --- /dev/null +++ b/reactos/hal/halx86/pci.c @@ -0,0 +1,494 @@ +/* $Id: pci.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/pci.c + * PURPOSE: Interfaces to the PCI bus + * PROGRAMMER: David Welch (welch@mcmail.com) + * Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * 05/06/1998: Created + * 17/08/2000: Added preliminary pci bus scanner + * 13/06/2001: Implemented access to pci configuration space + */ + +/* + * NOTES: Sections copied from the Linux pci support + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + + +/* MACROS ******************************************************************/ + +/* access type 1 macros */ +#define PCI_FUNC(devfn) \ + ((devfn) & 0x07) +#define CONFIG_CMD(bus, device_fn, where) \ + (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3)) + +/* access type 2 macros */ +#define IOADDR(devfn, where) \ + ((0xC000 | ((devfn & 0x78) << 5)) + where) +#define FUNC(devfn) \ + (((devfn & 7) << 1) | 0xf0) + + +#define PCIBIOS_SUCCESSFUL 0x00 +#define PCIBIOS_DEVICE_NOT_FOUND 0x86 +#define PCIBIOS_BAD_REGISTER_NUMBER 0x87 + + +/* GLOBALS ******************************************************************/ + +static ULONG BusConfigType = 0; /* undetermined config type */ + + +/* FUNCTIONS ****************************************************************/ + +static NTSTATUS +ReadPciConfigUchar(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + PUCHAR Value) +{ + switch (BusConfigType) + { + case 1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + *Value = READ_PORT_UCHAR((PUCHAR)0xCFC + (Offset & 3)); + return STATUS_SUCCESS; + + case 2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + *Value = READ_PORT_UCHAR((PUCHAR)(IOADDR(Slot, Offset))); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +ReadPciConfigUshort(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + PUSHORT Value) +{ + if ((Offset & 1) != 0) + { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + switch (BusConfigType) + { + case 1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + *Value = READ_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1)); + return STATUS_SUCCESS; + + case 2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + *Value = READ_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset))); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +ReadPciConfigUlong(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + PULONG Value) +{ + if ((Offset & 3) != 0) + { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + switch (BusConfigType) + { + case 1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + *Value = READ_PORT_ULONG((PULONG)0xCFC); + return STATUS_SUCCESS; + + case 2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + *Value = READ_PORT_ULONG((PULONG)(IOADDR(Slot, Offset))); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +WritePciConfigUchar(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + UCHAR Value) +{ + switch (BusConfigType) + { + case 1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + WRITE_PORT_UCHAR((PUCHAR)0xCFC + (Offset&3), Value); + return STATUS_SUCCESS; + + case 2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + WRITE_PORT_UCHAR((PUCHAR)(IOADDR(Slot,Offset)), Value); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +WritePciConfigUshort(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + USHORT Value) +{ + if ((Offset & 1) != 0) + { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + switch (BusConfigType) + { + case 1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + WRITE_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1), Value); + return STATUS_SUCCESS; + + case 2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + WRITE_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)), Value); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static NTSTATUS +WritePciConfigUlong(UCHAR Bus, + UCHAR Slot, + UCHAR Offset, + ULONG Value) +{ + if ((Offset & 3) != 0) + { + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + switch (BusConfigType) + { + case 1: + WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset)); + WRITE_PORT_ULONG((PULONG)0xCFC, Value); + return STATUS_SUCCESS; + + case 2: + WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot)); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus); + WRITE_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)), Value); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0); + return STATUS_SUCCESS; + } + return STATUS_UNSUCCESSFUL; +} + + +static ULONG STDCALL +HalpGetPciData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PVOID Ptr = Buffer; + ULONG Address = Offset; + ULONG Len = Length; + ULONG Vendor; + UCHAR HeaderType; + + DPRINT("HalpGetPciData() called.\n"); + DPRINT(" BusNumber %lu\n", BusNumber); + DPRINT(" SlotNumber %lu\n", SlotNumber); + DPRINT(" Offset 0x%lx\n", Offset); + DPRINT(" Length 0x%lx\n", Length); + + if ((Length == 0) || (BusConfigType == 0)) + return 0; + + /* 0E=PCI_HEADER_TYPE */ + ReadPciConfigUchar(BusNumber, + SlotNumber & 0xF8, + 0x0E, + &HeaderType); + if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0)) + return 0; + + ReadPciConfigUlong(BusNumber, + SlotNumber, + 0x00, + &Vendor); + /* some broken boards return 0 if a slot is empty: */ + if (Vendor == 0xFFFFFFFF || Vendor == 0) + return 0; + + if ((Address & 1) && (Len >= 1)) + { + ReadPciConfigUchar(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + + if ((Address & 2) && (Len >= 2)) + { + ReadPciConfigUshort(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 2; + Address += 2; + Len -= 2; + } + + while (Len >= 4) + { + ReadPciConfigUlong(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 4; + Address += 4; + Len -= 4; + } + + if (Len >= 2) + { + ReadPciConfigUshort(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 2; + Address += 2; + Len -= 2; + } + + if (Len >= 1) + { + ReadPciConfigUchar(BusNumber, + SlotNumber, + Address, + Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + + return Length - Len; +} + + +static ULONG STDCALL +HalpSetPciData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PVOID Ptr = Buffer; + ULONG Address = Offset; + ULONG Len = Length; + ULONG Vendor; + UCHAR HeaderType; + + DPRINT("HalpSetPciData() called.\n"); + DPRINT(" BusNumber %lu\n", BusNumber); + DPRINT(" SlotNumber %lu\n", SlotNumber); + DPRINT(" Offset 0x%lx\n", Offset); + DPRINT(" Length 0x%lx\n", Length); + + if ((Length == 0) || (BusConfigType == 0)) + return 0; + + /* 0E=PCI_HEADER_TYPE */ + ReadPciConfigUchar(BusNumber, + SlotNumber & 0xF8, + 0x0E, + &HeaderType); + if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0)) + return 0; + + ReadPciConfigUlong(BusNumber, + SlotNumber, + 0x00, + &Vendor); + /* some broken boards return 0 if a slot is empty: */ + if (Vendor == 0xFFFFFFFF || Vendor == 0) + return 0; + + if ((Address & 1) && (Len >= 1)) + { + WritePciConfigUchar(BusNumber, + SlotNumber, + Address, + *(PUCHAR)Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + + if ((Address & 2) && (Len >= 2)) + { + WritePciConfigUshort(BusNumber, + SlotNumber, + Address, + *(PUSHORT)Ptr); + Ptr = Ptr + 2; + Address += 2; + Len -= 2; + } + + while (Len >= 4) + { + WritePciConfigUlong(BusNumber, + SlotNumber, + Address, + *(PULONG)Ptr); + Ptr = Ptr + 4; + Address += 4; + Len -= 4; + } + + if (Len >= 2) + { + WritePciConfigUshort(BusNumber, + SlotNumber, + Address, + *(PUSHORT)Ptr); + Ptr = Ptr + 2; + Address += 2; + Len -= 2; + } + + if (Len >= 1) + { + WritePciConfigUchar(BusNumber, + SlotNumber, + Address, + *(PUCHAR)Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + + return Length - Len; +} + + +static ULONG +GetBusConfigType(VOID) +{ + ULONG Value; + + DPRINT("GetBusConfigType() called\n"); + + DPRINT("Checking configuration type 1:"); + WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x01); + Value = READ_PORT_ULONG((PULONG)0xCF8); + WRITE_PORT_ULONG((PULONG)0xCF8, 0x80000000); + if (READ_PORT_ULONG((PULONG)0xCF8) == 0x80000000) + { + WRITE_PORT_ULONG((PULONG)0xCF8, Value); + DPRINT(" Success!\n"); + return 1; + } + WRITE_PORT_ULONG((PULONG)0xCF8, Value); + DPRINT(" Unsuccessful!\n"); + + DPRINT("Checking configuration type 2:"); + WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x00); + WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0x00); + WRITE_PORT_UCHAR((PUCHAR)0xCFA, 0x00); + if (READ_PORT_UCHAR((PUCHAR)0xCF8) == 0x00 && + READ_PORT_UCHAR((PUCHAR)0xCFB) == 0x00) + { + DPRINT(" Success!\n"); + return 2; + } + DPRINT(" Unsuccessful!\n"); + + DPRINT("No pci bus found!\n"); + return 0; +} + + +VOID HalpInitPciBus (VOID) +{ + PBUS_HANDLER BusHandler; + + DPRINT("HalpInitPciBus() called.\n"); + + BusConfigType = GetBusConfigType(); + if (BusConfigType == 0) + return; + + DPRINT("Bus configuration %lu used\n", BusConfigType); + + /* pci bus (bus 0) handler */ + BusHandler = HalpAllocateBusHandler(PCIBus, + PCIConfiguration, + 0); + BusHandler->GetBusData = (pGetSetBusData)HalpGetPciData; + BusHandler->SetBusData = (pGetSetBusData)HalpSetPciData; +// BusHandler->GetInterruptVector = +// (pGetInterruptVector)HalpGetPciInterruptVector; +// BusHandler->AdjustResourceList = +// (pGetSetBusData)HalpAdjustPciResourceList; +// BusHandler->AssignSlotResources = +// (pGetSetBusData)HalpAssignPciSlotResources; + + + /* agp bus (bus 1) handler */ + BusHandler = HalpAllocateBusHandler(PCIBus, + PCIConfiguration, + 1); + BusHandler->GetBusData = (pGetSetBusData)HalpGetPciData; + BusHandler->SetBusData = (pGetSetBusData)HalpSetPciData; +// BusHandler->GetInterruptVector = +// (pGetInterruptVector)HalpGetPciInterruptVector; +// BusHandler->AdjustResourceList = +// (pGetSetBusData)HalpAdjustPciResourceList; +// BusHandler->AssignSlotResources = +// (pGetSetBusData)HalpAssignPciSlotResources; + + DPRINT("HalpInitPciBus() finished.\n"); +} + +/* EOF */ diff --git a/reactos/hal/halx86/perfcnt.c b/reactos/hal/halx86/perfcnt.c new file mode 100644 index 00000000000..49dd83c39bb --- /dev/null +++ b/reactos/hal/halx86/perfcnt.c @@ -0,0 +1,62 @@ +/* $Id: perfcnt.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/perfcnt.c + * PURPOSE: Performance counter functions + * PROGRAMMER: David Welch (welch@mcmail.com) + * Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * 09/06/2000: Created + */ + + +/* INCLUDES ***************************************************************/ + +#include + +/* FUNCTIONS **************************************************************/ + + +VOID STDCALL +HalCalibratePerformanceCounter(ULONG Count) +{ + ULONG i; + + /* save flags and disable interrupts */ + __asm__("pushf\n\t" \ + "cli\n\t"); + + for (i = 0; i < Count; i++); + + /* restore flags */ + __asm__("popf\n\t"); +} + + +LARGE_INTEGER STDCALL +KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFreq) +/* + * FUNCTION: Queries the finest grained running count avaiable in the system + * ARGUMENTS: + * PerformanceFreq (OUT) = The routine stores the number of + * performance counters tick per second here + * RETURNS: The performance counter value in HERTZ + * NOTE: Returns the system tick count or the time-stamp on the pentium + */ +{ + if (PerformanceFreq != NULL) + { + PerformanceFreq->QuadPart = 0; + return *PerformanceFreq; + } + else + { + LARGE_INTEGER Value; + + Value.QuadPart = 0; + return Value; + } +} + +/* EOF */ diff --git a/reactos/hal/halx86/portio.c b/reactos/hal/halx86/portio.c new file mode 100644 index 00000000000..a897443fa26 --- /dev/null +++ b/reactos/hal/halx86/portio.c @@ -0,0 +1,182 @@ +/* $Id: portio.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * 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 + + +/* 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 + */ + +#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 + +#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 + +VOID STDCALL +READ_PORT_BUFFER_UCHAR (PUCHAR Port, + PUCHAR Buffer, + ULONG Count) +{ + __asm__ __volatile__ ("cld ; rep ; insb\n\t" + : "=D" (Buffer), "=c" (Count) + : "d" (Port),"0" (Buffer),"1" (Count)); +} + +VOID STDCALL +READ_PORT_BUFFER_USHORT (PUSHORT Port, + PUSHORT Buffer, + ULONG Count) +{ + __asm__ __volatile__ ("cld ; rep ; insw" + : "=D" (Buffer), "=c" (Count) + : "d" (Port),"0" (Buffer),"1" (Count)); +} + +VOID STDCALL +READ_PORT_BUFFER_ULONG (PULONG Port, + PULONG Buffer, + ULONG Count) +{ + __asm__ __volatile__ ("cld ; rep ; insl" + : "=D" (Buffer), "=c" (Count) + : "d" (Port),"0" (Buffer),"1" (Count)); +} + +UCHAR STDCALL +READ_PORT_UCHAR (PUCHAR Port) +{ + UCHAR Value; + + __asm__("inb %w1, %0\n\t" + : "=a" (Value) + : "d" (Port)); + SLOW_DOWN_IO; + return(Value); +} + +USHORT STDCALL +READ_PORT_USHORT (PUSHORT Port) +{ + USHORT Value; + + __asm__("inw %w1, %0\n\t" + : "=a" (Value) + : "d" (Port)); + SLOW_DOWN_IO; + return(Value); +} + +ULONG STDCALL +READ_PORT_ULONG (PULONG Port) +{ + ULONG Value; + + __asm__("inl %w1, %0\n\t" + : "=a" (Value) + : "d" (Port)); + SLOW_DOWN_IO; + return(Value); +} + +VOID STDCALL +WRITE_PORT_BUFFER_UCHAR (PUCHAR Port, + PUCHAR Buffer, + ULONG Count) +{ + __asm__ __volatile__ ("cld ; rep ; outsb" + : "=S" (Buffer), "=c" (Count) + : "d" (Port),"0" (Buffer),"1" (Count)); +} + +VOID STDCALL +WRITE_PORT_BUFFER_USHORT (PUSHORT Port, + PUSHORT Buffer, + ULONG Count) +{ + __asm__ __volatile__ ("cld ; rep ; outsw" + : "=S" (Buffer), "=c" (Count) + : "d" (Port),"0" (Buffer),"1" (Count)); +} + +VOID STDCALL +WRITE_PORT_BUFFER_ULONG (PULONG Port, + PULONG Buffer, + ULONG Count) +{ + __asm__ __volatile__ ("cld ; rep ; outsl" + : "=S" (Buffer), "=c" (Count) + : "d" (Port),"0" (Buffer),"1" (Count)); +} + +VOID STDCALL +WRITE_PORT_UCHAR (PUCHAR Port, + UCHAR Value) +{ + __asm__("outb %0, %w1\n\t" + : + : "a" (Value), + "d" (Port)); + SLOW_DOWN_IO; +} + +VOID STDCALL +WRITE_PORT_USHORT (PUSHORT Port, + USHORT Value) +{ + __asm__("outw %0, %w1\n\t" + : + : "a" (Value), + "d" (Port)); + SLOW_DOWN_IO; +} + +VOID STDCALL +WRITE_PORT_ULONG (PULONG Port, + ULONG Value) +{ + __asm__("outl %0, %w1\n\t" + : + : "a" (Value), + "d" (Port)); + SLOW_DOWN_IO; +} + +/* EOF */ diff --git a/reactos/hal/halx86/pwroff.c b/reactos/hal/halx86/pwroff.c new file mode 100644 index 00000000000..94696c77f8a --- /dev/null +++ b/reactos/hal/halx86/pwroff.c @@ -0,0 +1,114 @@ +/* $Id: pwroff.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * 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 + + + +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 */ +} + + +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/halx86/reboot.c b/reactos/hal/halx86/reboot.c new file mode 100644 index 00000000000..151b1248ab2 --- /dev/null +++ b/reactos/hal/halx86/reboot.c @@ -0,0 +1,74 @@ +/* $Id: reboot.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * 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 +#include + + +static VOID +HalReboot (VOID) +{ + char data; + BYTE *mem; + + /* enable warm reboot */ + mem = (BYTE *)(0xd0000000 + 0x0000); +// mem = HalMapPhysicalMemory (0, 1); + mem[0x472] = 0x34; + mem[0x473] = 0x12; + + /* disable interrupts */ + __asm__("cli\n"); + + /* disable periodic interrupt (RTC) */ + WRITE_PORT_UCHAR((PUCHAR)0x70, 0x0b); + data = READ_PORT_UCHAR((PUCHAR)0x71); + WRITE_PORT_UCHAR((PUCHAR)0x71, data & 0xbf); + + /* */ + WRITE_PORT_UCHAR((PUCHAR)0x70, 0x0a); + data = READ_PORT_UCHAR((PUCHAR)0x71); + WRITE_PORT_UCHAR((PUCHAR)0x71, (data & 0xf0) | 0x06); + + /* */ + WRITE_PORT_UCHAR((PUCHAR)0x70, 0x15); + + /* generate RESET signal via keyboard controller */ + WRITE_PORT_UCHAR((PUCHAR)0x64, 0xfe); + + /* stop the processor */ +#if 1 + __asm__("hlt\n"); +#else + for(;;); +#endif +} + + +VOID STDCALL +HalReturnToFirmware ( + ULONG Action + ) +{ + if (Action == FIRMWARE_HALT) + { + DbgPrint ("HalReturnToFirmware called!\n"); + DbgBreakPoint (); + } + else if (Action == FIRMWARE_REBOOT) + { + HalResetDisplay (); + HalReboot (); + } +} + +/* EOF */ diff --git a/reactos/hal/halx86/spinlock.c b/reactos/hal/halx86/spinlock.c new file mode 100644 index 00000000000..012cab061ae --- /dev/null +++ b/reactos/hal/halx86/spinlock.c @@ -0,0 +1,95 @@ +/* $Id: spinlock.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/spinlock.c + * PURPOSE: Implements spinlocks + * PROGRAMMER: David Welch (welch@cwcom.net) + * Eric Kohl (ekohl@rz-online.de) + * UPDATE HISTORY: + * 09/06/2000 Created + */ + +/* + * NOTE: On a uniprocessor machine spinlocks are implemented by raising + * the irq level + */ + +/* INCLUDES ****************************************************************/ + +#include + +#include + +/* FUNCTIONS ***************************************************************/ + +VOID STDCALL +KeAcquireSpinLock ( + PKSPIN_LOCK SpinLock, + PKIRQL OldIrql + ) +/* + * FUNCTION: Acquires a spinlock + * ARGUMENTS: + * SpinLock = Spinlock to acquire + * OldIrql (OUT) = Caller supplied storage for the previous irql + */ +{ + KeRaiseIrql(DISPATCH_LEVEL,OldIrql); + KeAcquireSpinLockAtDpcLevel(SpinLock); +} + +KIRQL FASTCALL +KeAcquireSpinLockRaiseToSynch ( + PKSPIN_LOCK SpinLock + ) +{ + UNIMPLEMENTED; +} + +VOID STDCALL +KeReleaseSpinLock ( + PKSPIN_LOCK SpinLock, + KIRQL NewIrql + ) +/* + * FUNCTION: Releases a spinlock + * ARGUMENTS: + * SpinLock = Spinlock to release + * NewIrql = Irql level before acquiring the spinlock + */ +{ + KeReleaseSpinLockFromDpcLevel(SpinLock); + KeLowerIrql(NewIrql); +} + +KIRQL FASTCALL +KfAcquireSpinLock ( + PKSPIN_LOCK SpinLock + ) +{ + KIRQL OldIrql; + + KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); + KeAcquireSpinLockAtDpcLevel(SpinLock); + + return OldIrql; +} + +VOID FASTCALL +KfReleaseSpinLock ( + PKSPIN_LOCK SpinLock, + KIRQL NewIrql + ) +/* + * FUNCTION: Releases a spinlock + * ARGUMENTS: + * SpinLock = Spinlock to release + * NewIrql = Irql level before acquiring the spinlock + */ +{ + KeReleaseSpinLockFromDpcLevel(SpinLock); + KeLowerIrql(NewIrql); +} + +/* EOF */ diff --git a/reactos/hal/halx86/sysbus.c b/reactos/hal/halx86/sysbus.c new file mode 100644 index 00000000000..be7b27511bd --- /dev/null +++ b/reactos/hal/halx86/sysbus.c @@ -0,0 +1,64 @@ +/* $Id: sysbus.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * 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 +#include + + +/* FUNCTIONS ****************************************************************/ + +ULONG STDCALL +HalpGetSystemInterruptVector(PVOID BusHandler, + ULONG BusNumber, + ULONG BusInterruptLevel, + ULONG BusInterruptVector, + PKIRQL Irql, + PKAFFINITY Affinity) +{ + *Irql = HIGH_LEVEL - BusInterruptVector; + *Affinity = 0xFFFFFFFF; + return BusInterruptVector; +} + + +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/halx86/sysinfo.c b/reactos/hal/halx86/sysinfo.c new file mode 100644 index 00000000000..5d04be8449c --- /dev/null +++ b/reactos/hal/halx86/sysinfo.c @@ -0,0 +1,23 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/sysinfo.c + * PURPOSE: Getting system information + * PROGRAMMER: David Welch (welch@mcmail.com) + * UPDATE HISTORY: + * Created 22/05/98 + */ + +/* INCLUDES *****************************************************************/ + +#include + +#include + +/* FUNCTIONS *****************************************************************/ + +VOID HalQuerySystemInformation() +{ + UNIMPLEMENTED; +} + diff --git a/reactos/hal/halx86/time.c b/reactos/hal/halx86/time.c new file mode 100644 index 00000000000..57a4015a955 --- /dev/null +++ b/reactos/hal/halx86/time.c @@ -0,0 +1,307 @@ +/* + * 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 +#include +#include +#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 + + +/* FUNCTIONS *****************************************************************/ + + +static UCHAR +HalpQueryCMOS(UCHAR Reg) +{ + UCHAR Val; + ULONG Flags; + + Reg |= 0x80; + pushfl(Flags); + __asm__("cli\n"); // AP unsure as to whether to do this here + WRITE_PORT_UCHAR((PUCHAR)0x70, Reg); + Val = READ_PORT_UCHAR((PUCHAR)0x71); + WRITE_PORT_UCHAR((PUCHAR)0x70, 0); + popfl(Flags); + + return(Val); +} + + +static VOID +HalpSetCMOS(UCHAR Reg, + UCHAR Val) +{ + ULONG Flags; + + Reg |= 0x80; + pushfl(Flags); + __asm__("cli\n"); // AP unsure as to whether to do this here + WRITE_PORT_UCHAR((PUCHAR)0x70, Reg); + WRITE_PORT_UCHAR((PUCHAR)0x71, Val); + WRITE_PORT_UCHAR((PUCHAR)0x70, 0); + popfl(Flags); +} + + +static UCHAR +HalpQueryECMOS(USHORT Reg) +{ + UCHAR Val; + ULONG Flags; + + pushfl(Flags); + __asm__("cli\n"); // AP unsure as to whether to do this here + WRITE_PORT_UCHAR((PUCHAR)0x74, (UCHAR)(Reg & 0x00FF)); + WRITE_PORT_UCHAR((PUCHAR)0x75, (UCHAR)(Reg>>8)); + Val = READ_PORT_UCHAR((PUCHAR)0x76); + popfl(Flags); + + return(Val); +} + + +static VOID +HalpSetECMOS(USHORT Reg, + UCHAR Val) +{ + ULONG Flags; + + pushfl(Flags); + __asm__("cli\n"); // AP unsure as to whether to do this here + WRITE_PORT_UCHAR((PUCHAR)0x74, (UCHAR)(Reg & 0x00FF)); + WRITE_PORT_UCHAR((PUCHAR)0x75, (UCHAR)(Reg>>8)); + WRITE_PORT_UCHAR((PUCHAR)0x76, Val); + popfl(Flags); +} + + +VOID STDCALL +HalQueryRealTimeClock(PTIME_FIELDS Time) +{ + /* check 'Update In Progress' bit */ + while (HalpQueryCMOS (RTC_REGISTER_A) & RTC_REG_A_UIP) + ; + + Time->Second = BCD_INT(HalpQueryCMOS (0)); + Time->Minute = BCD_INT(HalpQueryCMOS (2)); + Time->Hour = BCD_INT(HalpQueryCMOS (4)); + Time->Weekday = BCD_INT(HalpQueryCMOS (6)); + Time->Day = BCD_INT(HalpQueryCMOS (7)); + Time->Month = BCD_INT(HalpQueryCMOS (8)); + Time->Year = BCD_INT(HalpQueryCMOS (9)); + + if (Time->Year > 80) + Time->Year += 1900; + else + Time->Year += 2000; + +#if 0 + /* Century */ + Time->Year += BCD_INT(HalpQueryCMOS (RTC_REGISTER_CENTURY)) * 100; +#endif + +#ifndef NDEBUG + DbgPrint ("HalQueryRealTimeClock() %d:%d:%d %d/%d/%d\n", + Time->Hour, + Time->Minute, + Time->Second, + Time->Day, + Time->Month, + Time->Year + ); +#endif + + Time->Milliseconds = 0; +} + + +VOID STDCALL +HalSetRealTimeClock(PTIME_FIELDS Time) +{ + /* check 'Update In Progress' bit */ + while (HalpQueryCMOS (RTC_REGISTER_A) & RTC_REG_A_UIP) + ; + + HalpSetCMOS (0, INT_BCD(Time->Second)); + HalpSetCMOS (2, INT_BCD(Time->Minute)); + HalpSetCMOS (4, INT_BCD(Time->Hour)); + HalpSetCMOS (6, INT_BCD(Time->Weekday)); + HalpSetCMOS (7, INT_BCD(Time->Day)); + HalpSetCMOS (8, INT_BCD(Time->Month)); + HalpSetCMOS (9, INT_BCD(Time->Year % 100)); + +#if 0 + /* Century */ + HalpSetCMOS (RTC_REGISTER_CENTURY, INT_BCD(Time->Year / 100)); +#endif +} + + +BOOLEAN STDCALL +HalGetEnvironmentVariable(PCH Name, + PCH Value, + USHORT ValueLength) +{ + if (_stricmp(Name, "LastKnownGood") != 0) + { + return FALSE; + } + + if (HalpQueryCMOS(RTC_REGISTER_B) & 0x01) + { + strncpy(Value, "FALSE", ValueLength); + } + else + { + strncpy(Value, "TRUE", ValueLength); + } + + return TRUE; +} + + +BOOLEAN STDCALL +HalSetEnvironmentVariable(PCH Name, + PCH Value) +{ + UCHAR Val; + + if (_stricmp(Name, "LastKnownGood") != 0) + return FALSE; + + Val = HalpQueryCMOS(RTC_REGISTER_B); + + if (_stricmp(Value, "TRUE") == 0) + HalpSetCMOS(RTC_REGISTER_B, Val | 0x01); + else if (_stricmp(Value, "FALSE") == 0) + HalpSetCMOS(RTC_REGISTER_B, Val & ~0x01); + else + return FALSE; + + return TRUE; +} + + +ULONG STDCALL +HalpGetCmosData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PUCHAR Ptr = Buffer; + ULONG Address = SlotNumber; + ULONG Len = 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); + + if (Length == 0) + return 0; + + if (BusNumber == 0) + { + /* CMOS */ + while ((Len > 0) && (Address < 0x100)) + { + *Ptr = HalpQueryCMOS((UCHAR)Address); + Ptr = Ptr + 1; + Address++; + Len--; + } + } + else if (BusNumber == 1) + { + /* Extended CMOS */ + while ((Len > 0) && (Address < 0x1000)) + { + *Ptr = HalpQueryECMOS((USHORT)Address); + Ptr = Ptr + 1; + Address++; + Len--; + } + } + + return(Length - Len); +} + + +ULONG STDCALL +HalpSetCmosData(PBUS_HANDLER BusHandler, + ULONG BusNumber, + ULONG SlotNumber, + PVOID Buffer, + ULONG Offset, + ULONG Length) +{ + PUCHAR Ptr = (PUCHAR)Buffer; + ULONG Address = SlotNumber; + ULONG Len = 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); + + if (Length == 0) + return 0; + + if (BusNumber == 0) + { + /* CMOS */ + while ((Len > 0) && (Address < 0x100)) + { + HalpSetCMOS((UCHAR)Address, *Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + } + else if (BusNumber == 1) + { + /* Extended CMOS */ + while ((Len > 0) && (Address < 0x1000)) + { + HalpSetECMOS((USHORT)Address, *Ptr); + Ptr = Ptr + 1; + Address++; + Len--; + } + } + + return(Length - Len); +} + +/* EOF */ diff --git a/reactos/hal/halx86/udelay.c b/reactos/hal/halx86/udelay.c new file mode 100644 index 00000000000..10146ab60b4 --- /dev/null +++ b/reactos/hal/halx86/udelay.c @@ -0,0 +1,223 @@ +/* + * ReactOS kernel + * Copyright (C) 2000 David Welch + * Copyright (C) 1999 Gareth Owen , Ramon von Handel + * Copyright (C) 1991, 1992 Linus Torvalds + * + * This software is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write + * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, + * MA 02139, USA. + * + */ +/* $Id: udelay.c,v 1.1 2001/08/21 20:18:27 chorns Exp $ + * + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/hal/x86/udelay.c + * PURPOSE: Busy waiting + * PROGRAMMER: David Welch (david.welch@seh.ox.ac.uk) + * UPDATE HISTORY: + * 06/11/99 Created + */ + +/* INCLUDES ***************************************************************/ + +#include + +#define NDEBUG +#include + +/* GLOBALS ******************************************************************/ + +static unsigned int delay_count = 1; + +#define MILLISEC (10) +#define FREQ (1000/MILLISEC) + +#define PRECISION (8) + +#define TMR_CTRL 0x43 /* I/O for control */ +#define TMR_CNT0 0x40 /* I/O for counter 0 */ +#define TMR_CNT1 0x41 /* I/O for counter 1 */ +#define TMR_CNT2 0x42 /* I/O for counter 2 */ + +#define TMR_SC0 0 /* Select channel 0 */ +#define TMR_SC1 0x40 /* Select channel 1 */ +#define TMR_SC2 0x80 /* Select channel 2 */ + +#define TMR_LOW 0x10 /* RW low byte only */ +#define TMR_HIGH 0x20 /* RW high byte only */ +#define TMR_BOTH 0x30 /* RW both bytes */ + +#define TMR_MD0 0 /* Mode 0 */ +#define TMR_MD1 0x2 /* Mode 1 */ +#define TMR_MD2 0x4 /* Mode 2 */ +#define TMR_MD3 0x6 /* Mode 3 */ +#define TMR_MD4 0x8 /* Mode 4 */ +#define TMR_MD5 0xA /* Mode 5 */ + +#define TMR_BCD 1 /* BCD mode */ + +#define TMR_LATCH 0 /* Latch command */ + +#define TMR_READ 0xF0 /* Read command */ +#define TMR_CNT 0x20 /* CNT bit (Active low, subtract it) */ +#define TMR_STAT 0x10 /* Status bit (Active low, subtract it) */ +#define TMR_CH2 0x8 /* Channel 2 bit */ +#define TMR_CH1 0x4 /* Channel 1 bit */ +#define TMR_CH0 0x2 /* Channel 0 bit */ + +static BOOLEAN UdelayCalibrated = FALSE; + +/* FUNCTIONS **************************************************************/ + +void init_pit(float h, unsigned char channel) +{ + unsigned int temp=0; + + temp = 1193180/h; + +// WRITE_PORT_UCHAR((PUCHAR)TMR_CTRL, +// (channel*0x40) + TMR_BOTH + TMR_MD3); + WRITE_PORT_UCHAR((PUCHAR)TMR_CTRL, + (channel*0x40) + TMR_BOTH + TMR_MD2); + WRITE_PORT_UCHAR((PUCHAR)(0x40+channel), + (unsigned char) temp); + WRITE_PORT_UCHAR((PUCHAR)(0x40+channel), + (unsigned char) (temp>>8)); +} + +VOID STDCALL +__KeStallExecutionProcessor(ULONG Loops) +{ + register unsigned int i; + for (i=0; i> 8); /* MSB */ + + /* Stage 1: Coarse calibration */ + + WaitFor8254Wraparound(); + + delay_count = 1; + + do { + delay_count <<= 1; /* Next delay count to try */ + + WaitFor8254Wraparound(); + + __KeStallExecutionProcessor(delay_count); /* Do the delay */ + + CurCount = Read8254Timer(); + } while (CurCount > LATCH / 2); + + delay_count >>= 1; /* Get bottom value for delay */ + + /* Stage 2: Fine calibration */ + DbgPrint("delay_count: %d", delay_count); + + calib_bit = delay_count; /* Which bit are we going to test */ + + for(i=0;i>= 1; /* Next bit to calibrate */ + if(!calib_bit) break; /* If we have done all bits, stop */ + + delay_count |= calib_bit; /* Set the bit in delay_count */ + + WaitFor8254Wraparound(); + + __KeStallExecutionProcessor(delay_count); /* Do the delay */ + + CurCount = Read8254Timer(); + if (CurCount <= LATCH / 2) /* If a tick has passed, turn the */ + delay_count &= ~calib_bit; /* calibrated bit back off */ + } + + /* We're finished: Do the finishing touches */ + + delay_count /= (MILLISEC / 2); /* Calculate delay_count for 1ms */ + + DbgPrint("]\n"); + DbgPrint("delay_count: %d\n", delay_count); + DbgPrint("CPU speed: %d\n", delay_count/250); +#if 0 + DbgPrint("About to start delay loop test\n"); + DbgPrint("Waiting for five minutes..."); + for (i = 0; i < (5*60*1000*20); i++) + { + KeStallExecutionProcessor(50); + } + DbgPrint("finished\n"); + for(;;); +#endif +} + +/* EOF */