From: Jérôme Gardou Date: Sat, 27 Mar 2010 23:28:24 +0000 (+0000) Subject: svn will drive me nuts, part 1/x X-Git-Tag: backups/reactos-yarotows@57446~215 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=84b472706478f9ba794d1aa6521f91de89f7cc3a svn will drive me nuts, part 1/x svn path=/branches/reactos-yarotows/; revision=46505 --- diff --git a/drivers/bus/acpi/cmbatt/cmbpnp.c b/drivers/bus/acpi/cmbatt/cmbpnp.c index 55d3ae63d49..bbeee7960d8 100644 --- a/drivers/bus/acpi/cmbatt/cmbpnp.c +++ b/drivers/bus/acpi/cmbatt/cmbpnp.c @@ -567,8 +567,7 @@ CmBattCreateFdo(IN PDRIVER_OBJECT DriverObject, } /* Set FDO flags */ - FdoDeviceObject->Flags |= DO_BUFFERED_IO; - FdoDeviceObject->Flags |= DO_MAP_IO_BUFFER; + FdoDeviceObject->Flags |= (DO_POWER_PAGABLE | DO_BUFFERED_IO); FdoDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; /* Initialize the extension */ diff --git a/drivers/bus/acpi/compbatt/compbatt.c b/drivers/bus/acpi/compbatt/compbatt.c index 03d587c46ad..d8f8920cc0a 100644 --- a/drivers/bus/acpi/compbatt/compbatt.c +++ b/drivers/bus/acpi/compbatt/compbatt.c @@ -21,8 +21,17 @@ NTAPI CompBattOpenClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PAGED_CODE(); + if (CompBattDebug & 0x100) DbgPrint("CompBatt: ENTERING OpenClose\n"); + + /* Complete the IRP with success */ + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IofCompleteRequest(Irp, IO_NO_INCREMENT); + + /* Return success */ + if (CompBattDebug & 0x100) DbgPrint("CompBatt: Exiting OpenClose\n"); + return STATUS_SUCCESS; } NTSTATUS @@ -30,8 +39,28 @@ NTAPI CompBattSystemControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + NTSTATUS Status; + PAGED_CODE(); + if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING System Control\n"); + + /* Are we attached yet? */ + if (DeviceExtension->AttachedDevice) + { + /* Send it up the stack */ + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); + } + else + { + /* We don't support WMI */ + Status = STATUS_NOT_SUPPORTED; + Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + IofCompleteRequest(Irp, IO_NO_INCREMENT); + } + + /* Return status */ + return Status; } NTSTATUS @@ -65,8 +94,23 @@ NTAPI CompBattIoctl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + NTSTATUS Status; + if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING Ioctl\n"); + + /* Let the class driver handle it */ + Status = BatteryClassIoctl(DeviceExtension->ClassData, Irp); + if (Status == STATUS_NOT_SUPPORTED) + { + /* It failed, try the next driver up the stack */ + Irp->IoStatus.Status = Status; + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); + } + + /* Return status */ + if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING Ioctl\n"); + return Status; } NTSTATUS @@ -161,8 +205,18 @@ NTAPI DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + /* Register add device routine */ + DriverObject->DriverExtension->AddDevice = CompBattAddDevice; + + /* Register other handlers */ + DriverObject->MajorFunction[0] = CompBattOpenClose; + DriverObject->MajorFunction[2] = CompBattOpenClose; + DriverObject->MajorFunction[14] = CompBattIoctl; + DriverObject->MajorFunction[22] = CompBattPowerDispatch; + DriverObject->MajorFunction[23] = CompBattSystemControl; + DriverObject->MajorFunction[27] = CompBattPnpDispatch; + + return STATUS_SUCCESS; } /* EOF */ diff --git a/drivers/bus/acpi/compbatt/compbatt.h b/drivers/bus/acpi/compbatt/compbatt.h index 701f1362641..015195bafe2 100644 --- a/drivers/bus/acpi/compbatt/compbatt.h +++ b/drivers/bus/acpi/compbatt/compbatt.h @@ -52,6 +52,68 @@ typedef struct _COMPBATT_DEVICE_EXTENSION PVOID NotificationEntry; } COMPBATT_DEVICE_EXTENSION, *PCOMPBATT_DEVICE_EXTENSION; -extern ULONG CmBattDebug; +NTSTATUS +NTAPI +CompBattAddDevice( + IN PDRIVER_OBJECT DriverObject, + IN PDEVICE_OBJECT PdoDeviceObject +); + +NTSTATUS +NTAPI +CompBattPowerDispatch( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp +); + +NTSTATUS +NTAPI +CompBattPnpDispatch( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp +); + +NTSTATUS +NTAPI +CompBattQueryInformation( + IN PCOMPBATT_DEVICE_EXTENSION FdoExtension, + IN ULONG Tag, + IN BATTERY_QUERY_INFORMATION_LEVEL InfoLevel, + IN OPTIONAL LONG AtRate, + IN PVOID Buffer, + IN ULONG BufferLength, + OUT PULONG ReturnedLength +); + +NTSTATUS +NTAPI +CompBattQueryStatus( + IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG Tag, + IN PBATTERY_STATUS BatteryStatus +); + +NTSTATUS +NTAPI +CompBattSetStatusNotify( + IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension, + IN ULONG BatteryTag, + IN PBATTERY_NOTIFY BatteryNotify +); + +NTSTATUS +NTAPI +CompBattDisableStatusNotify( + IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension +); + +NTSTATUS +NTAPI +CompBattQueryTag( + IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension, + OUT PULONG Tag +); + +extern ULONG CompBattDebug; /* EOF */ diff --git a/drivers/bus/acpi/compbatt/comppnp.c b/drivers/bus/acpi/compbatt/comppnp.c index a767c18ab80..156ee3fd81f 100644 --- a/drivers/bus/acpi/compbatt/comppnp.c +++ b/drivers/bus/acpi/compbatt/comppnp.c @@ -17,8 +17,15 @@ NTAPI CompBattPowerDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + if (CompBattDebug & 1) DbgPrint("CompBatt: PowerDispatch recieved power IRP.\n"); + + /* Start the next IRP */ + PoStartNextPowerIrp(Irp); + + /* Call the next driver in the stack */ + IoSkipCurrentIrpStackLocation(Irp); + return PoCallDriver(DeviceExtension->AttachedDevice, Irp); } PCOMPBATT_BATTERY_ENTRY @@ -79,8 +86,82 @@ NTAPI CompBattAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PdoDeviceObject) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status; + UNICODE_STRING DeviceName; + PCOMPBATT_DEVICE_EXTENSION DeviceExtension; + PDEVICE_OBJECT DeviceObject; + UNICODE_STRING SymbolicLinkName; + BATTERY_MINIPORT_INFO MiniportInfo; + if (CompBattDebug & 2) DbgPrint("CompBatt: Got an AddDevice - %x\n", PdoDeviceObject); + + /* Create the device */ + RtlInitUnicodeString(&DeviceName, L"\\Device\\CompositeBattery"); + Status = IoCreateDevice(DriverObject, + sizeof(COMPBATT_DEVICE_EXTENSION), + &DeviceName, + FILE_DEVICE_BATTERY, + FILE_DEVICE_SECURE_OPEN, + FALSE, + &DeviceObject); + if (!NT_SUCCESS(Status)) return Status; + + /* Setup symbolic link for Win32 access */ + RtlInitUnicodeString(&SymbolicLinkName, L"\\DosDevices\\CompositeBattery"); + IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); + + /* Initialize the device extension */ + DeviceExtension = DeviceObject->DeviceExtension; + RtlZeroMemory(DeviceExtension, 0x1B0u); + + /* Attach to device stack and set DO pointers */ + DeviceExtension->AttachedDevice = IoAttachDeviceToDeviceStack(DeviceObject, + PdoDeviceObject); + DeviceExtension->DeviceObject = DeviceObject; + if (!DeviceExtension->AttachedDevice) + { + /* Fail */ + if (CompBattDebug & 8) + DbgPrint("CompBattAddDevice: Could not attach to LowerDevice.\n"); + IoDeleteDevice(DeviceObject); + return STATUS_UNSUCCESSFUL; + } + + /* Set device object flags */ + DeviceObject->Flags |= (DO_POWER_PAGABLE | DO_BUFFERED_IO); + DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + + /* Setup the device extension */ + ExInitializeFastMutex(&DeviceExtension->Lock); + InitializeListHead(&DeviceExtension->BatteryList); + DeviceExtension->Flags = 0; + DeviceExtension->NextTag = 1; + + /* Setup the miniport data */ + RtlZeroMemory(&MiniportInfo, sizeof(MiniportInfo)); + MiniportInfo.MajorVersion = BATTERY_CLASS_MAJOR_VERSION; + MiniportInfo.MinorVersion = BATTERY_CLASS_MINOR_VERSION; + MiniportInfo.Context = DeviceExtension; + MiniportInfo.DeviceName = &DeviceName; + MiniportInfo.QueryTag = (BCLASS_QUERY_TAG)CompBattQueryTag; + MiniportInfo.QueryInformation = (BCLASS_QUERY_INFORMATION)CompBattQueryInformation; + MiniportInfo.SetInformation = NULL; + MiniportInfo.QueryStatus = (BCLASS_QUERY_STATUS)CompBattQueryStatus; + MiniportInfo.SetStatusNotify = (BCLASS_SET_STATUS_NOTIFY)CompBattSetStatusNotify; + MiniportInfo.DisableStatusNotify = (BCLASS_DISABLE_STATUS_NOTIFY)CompBattDisableStatusNotify; + MiniportInfo.Pdo = NULL; + + /* Register with the class driver */ + Status = BatteryClassInitializeDevice(&MiniportInfo, + &DeviceExtension->ClassData); + if (!NT_SUCCESS(Status)) + { + /* Undo everything */ + IoDetachDevice(DeviceExtension->AttachedDevice); + IoDeleteDevice(DeviceObject); + } + + /* Return status */ + return Status; } NTSTATUS @@ -88,8 +169,94 @@ NTAPI CompBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + PIO_STACK_LOCATION IoStackLocation = IoGetCurrentIrpStackLocation(Irp); + NTSTATUS Status; + PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension; + if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING PnpDispatch\n"); + + /* Set default error */ + Status = STATUS_NOT_SUPPORTED; + + /* Check what kind of PnP function this is */ + switch (IoStackLocation->MinorFunction) + { + case IRP_MN_START_DEVICE: + + /* Device is starting, register for new batteries and pick up current ones */ + Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, + 0, + (PVOID)&GUID_DEVICE_BATTERY, + DeviceObject->DriverObject, + (PDRIVER_NOTIFICATION_CALLBACK_ROUTINE)CompBattPnpEventHandler, + DeviceExtension, + &DeviceExtension->NotificationEntry); + if (NT_SUCCESS(Status)) + { + /* Now go get the batteries */ + if (CompBattDebug & 2) + DbgPrint("CompBatt: Successfully registered for PnP notification\n"); + Status = CompBattGetBatteries(DeviceExtension); + } + else + { + /* We failed */ + if (CompBattDebug & 8) + DbgPrint("CompBatt: Couldn't register for PnP notification - %x\n", + Status); + } + + case IRP_MN_CANCEL_STOP_DEVICE: + + /* Explicitly say ok */ + Status = STATUS_SUCCESS; + break; + + case IRP_MN_CANCEL_REMOVE_DEVICE: + + /* Explicitly say ok */ + Status = STATUS_SUCCESS; + break; + + case IRP_MN_SURPRISE_REMOVAL: + + /* Explicitly say ok */ + Status = STATUS_SUCCESS; + break; + + case IRP_MN_QUERY_PNP_DEVICE_STATE: + + /* Add this in */ + Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE; + Status = STATUS_SUCCESS; + break; + + default: + + /* Not supported */ + Status = STATUS_INVALID_DEVICE_REQUEST; + break; + } + + /* Set IRP status if we have one */ + if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status; + + /* Did someone pick it up? */ + if ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED)) + { + /* Still unsupported, try ACPI */ + IoSkipCurrentIrpStackLocation(Irp); + Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp); + } + else + { + /* Complete the request */ + Status = Irp->IoStatus.Status; + IofCompleteRequest(Irp, IO_NO_INCREMENT); + } + + /* Release the remove lock and return status */ + if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING PnpDispatch\n"); + return Status; } /* EOF */ diff --git a/drivers/bus/acpi/eval.c b/drivers/bus/acpi/eval.c new file mode 100644 index 00000000000..68af8573f42 --- /dev/null +++ b/drivers/bus/acpi/eval.c @@ -0,0 +1,180 @@ +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#define NDEBUG +#include + +NTSTATUS +NTAPI +Bus_PDO_EvalMethod(PPDO_DEVICE_DATA DeviceData, + PIRP Irp) +{ + ULONG Signature; + NTSTATUS Status; + ACPI_OBJECT_LIST ParamList; + PACPI_EVAL_INPUT_BUFFER EvalInputBuff = Irp->AssociatedIrp.SystemBuffer; + ACPI_BUFFER RetBuff = {ACPI_ALLOCATE_BUFFER, NULL}; + PACPI_EVAL_OUTPUT_BUFFER OutputBuf; + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER *SimpleInt; + ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING *SimpleStr; + + if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG)) + return STATUS_INVALID_PARAMETER; + + Signature = *((PULONG)Irp->AssociatedIrp.SystemBuffer); + + switch (Signature) + { + case ACPI_EVAL_INPUT_BUFFER_SIGNATURE: + if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ACPI_EVAL_INPUT_BUFFER)) + return STATUS_INVALID_PARAMETER; + + ParamList.Count = 0; + break; + + case ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE: + SimpleInt = Irp->AssociatedIrp.SystemBuffer; + + if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER)) + return STATUS_INVALID_PARAMETER; + + ParamList.Count = 1; + + ParamList.Pointer = ExAllocatePool(NonPagedPool, sizeof(ACPI_OBJECT)); + if (!ParamList.Pointer) return STATUS_INSUFFICIENT_RESOURCES; + + ParamList.Pointer[0].Type = ACPI_TYPE_INTEGER; + ParamList.Pointer[0].Integer.Value = SimpleInt->IntegerArgument; + break; + + case ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING_SIGNATURE: + SimpleStr = Irp->AssociatedIrp.SystemBuffer; + + if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ACPI_EVAL_INPUT_BUFFER_SIMPLE_STRING)) + return STATUS_INVALID_PARAMETER; + + ParamList.Count = 1; + + ParamList.Pointer = ExAllocatePool(NonPagedPool, sizeof(ACPI_OBJECT)); + if (!ParamList.Pointer) return STATUS_INSUFFICIENT_RESOURCES; + + ParamList.Pointer[0].String.Pointer = (CHAR*)SimpleStr->String; + ParamList.Pointer[0].String.Length = SimpleStr->StringLength; + break; + + default: + DPRINT1("Unsupported input buffer signature: %d\n", Signature); + return STATUS_NOT_IMPLEMENTED; + } + + Status = AcpiEvaluateObject(DeviceData->AcpiHandle, + (CHAR*)EvalInputBuff->MethodName, + &ParamList, + &RetBuff); + + if (ParamList.Count != 0) + ExFreePool(ParamList.Pointer); + + if (ACPI_SUCCESS(Status)) + { + ACPI_OBJECT *Obj = RetBuff.Pointer; + ULONG ExtraParamLength; + + /* If we didn't get anything back then we're done */ + if (!RetBuff.Pointer || RetBuff.Length == 0) + return STATUS_SUCCESS; + + switch (Obj->Type) + { + case ACPI_TYPE_INTEGER: + ExtraParamLength = sizeof(ULONG); + break; + + case ACPI_TYPE_STRING: + ExtraParamLength = Obj->String.Length; + break; + + case ACPI_TYPE_BUFFER: + ExtraParamLength = Obj->Buffer.Length; + break; + + case ACPI_TYPE_PACKAGE: + DPRINT1("ACPI_TYPE_PACKAGE not supported yet!\n"); + return STATUS_UNSUCCESSFUL; + + default: + ASSERT(FALSE); + return STATUS_UNSUCCESSFUL; + } + + /* Enough space for a ULONG is always included */ + if (ExtraParamLength >= sizeof(ULONG)) + ExtraParamLength -= sizeof(ULONG); + else + ExtraParamLength = 0; + + OutputBuf = ExAllocatePool(NonPagedPool, sizeof(ACPI_EVAL_OUTPUT_BUFFER) + + ExtraParamLength); + if (!OutputBuf) return STATUS_INSUFFICIENT_RESOURCES; + + OutputBuf->Signature = ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE; + OutputBuf->Length = ExtraParamLength + sizeof(ACPI_METHOD_ARGUMENT); + OutputBuf->Count = 1; + + switch (Obj->Type) + { + case ACPI_TYPE_INTEGER: + ACPI_METHOD_SET_ARGUMENT_INTEGER(OutputBuf->Argument, Obj->Integer.Value); + break; + + case ACPI_TYPE_STRING: + ACPI_METHOD_SET_ARGUMENT_STRING(OutputBuf->Argument, Obj->String.Pointer); + break; + + case ACPI_TYPE_BUFFER: + ACPI_METHOD_SET_ARGUMENT_BUFFER(OutputBuf->Argument, Obj->Buffer.Pointer, Obj->Buffer.Length); + break; + + case ACPI_TYPE_PACKAGE: + DPRINT1("ACPI_TYPE_PACKAGE not supported yet!\n"); + return STATUS_UNSUCCESSFUL; + + default: + ASSERT(FALSE); + return STATUS_UNSUCCESSFUL; + } + + if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ACPI_EVAL_OUTPUT_BUFFER) + + ExtraParamLength) + { + RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, OutputBuf, sizeof(ACPI_EVAL_OUTPUT_BUFFER) + + ExtraParamLength); + Irp->IoStatus.Information = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + ExtraParamLength; + ExFreePool(OutputBuf); + return STATUS_SUCCESS; + } + else + { + ExFreePool(OutputBuf); + return STATUS_BUFFER_TOO_SMALL; + } + } + else + { + DPRINT1("Query method %s failed on %p\n", EvalInputBuff->MethodName, DeviceData->AcpiHandle); + return STATUS_UNSUCCESSFUL; + } +} diff --git a/drivers/bus/acpi/interface.c b/drivers/bus/acpi/interface.c new file mode 100644 index 00000000000..59717056484 --- /dev/null +++ b/drivers/bus/acpi/interface.c @@ -0,0 +1,138 @@ +#include + +#include + +#include +#include +#include + +#include +#define NDEBUG +#include + +VOID +NTAPI +AcpiInterfaceReference(PVOID Context) +{ + UNIMPLEMENTED +} + +VOID +NTAPI +AcpiInterfaceDereference(PVOID Context) +{ + UNIMPLEMENTED +} + +NTSTATUS +AcpiInterfaceConnectVector(PDEVICE_OBJECT Context, + ULONG GpeNumber, + KINTERRUPT_MODE Mode, + BOOLEAN Shareable, + PGPE_SERVICE_ROUTINE ServiceRoutine, + PVOID ServiceContext, + PVOID *ObjectContext) +{ + UNIMPLEMENTED + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +AcpiInterfaceDisconnectVector(PDEVICE_OBJECT Context, + PVOID ObjectContext) +{ + UNIMPLEMENTED + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +AcpiInterfaceEnableEvent(PDEVICE_OBJECT Context, + PVOID ObjectContext) +{ + UNIMPLEMENTED + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +AcpiInterfaceDisableEvent(PDEVICE_OBJECT Context, + PVOID ObjectContext) +{ + UNIMPLEMENTED + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +AcpiInterfaceClearStatus(PDEVICE_OBJECT Context, + PVOID ObjectContext) +{ + UNIMPLEMENTED + + return STATUS_NOT_IMPLEMENTED; +} + +NTSTATUS +AcpiInterfaceNotificationsRegister(PDEVICE_OBJECT Context, + PDEVICE_NOTIFY_CALLBACK NotificationHandler, + PVOID NotificationContext) +{ + UNIMPLEMENTED + + return STATUS_NOT_IMPLEMENTED; +} + +VOID +AcpiInterfaceNotificationsUnregister(PDEVICE_OBJECT Context, + PDEVICE_NOTIFY_CALLBACK NotificationHandler) +{ + UNIMPLEMENTED +} + +NTSTATUS +Bus_PDO_QueryInterface(PPDO_DEVICE_DATA DeviceData, + PIRP Irp) +{ + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + PACPI_INTERFACE_STANDARD AcpiInterface; + + if (IrpSp->Parameters.QueryInterface.Version != 1) + { + DPRINT1("Invalid version number: %d\n", + IrpSp->Parameters.QueryInterface.Version); + return STATUS_INVALID_PARAMETER; + } + + if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType, + &GUID_ACPI_INTERFACE_STANDARD, sizeof(GUID)) == sizeof(GUID)) + { + DPRINT("GUID_ACPI_INTERFACE_STANDARD\n"); + + if (IrpSp->Parameters.QueryInterface.Size < sizeof(ACPI_INTERFACE_STANDARD)) + { + DPRINT1("Buffer too small! (%d)\n", IrpSp->Parameters.QueryInterface.Size); + return STATUS_BUFFER_TOO_SMALL; + } + + AcpiInterface = (PACPI_INTERFACE_STANDARD)IrpSp->Parameters.QueryInterface.Interface; + + AcpiInterface->InterfaceReference = AcpiInterfaceReference; + AcpiInterface->InterfaceDereference = AcpiInterfaceDereference; + AcpiInterface->GpeConnectVector = AcpiInterfaceConnectVector; + AcpiInterface->GpeDisconnectVector = AcpiInterfaceDisconnectVector; + AcpiInterface->GpeEnableEvent = AcpiInterfaceEnableEvent; + AcpiInterface->GpeDisableEvent = AcpiInterfaceDisableEvent; + AcpiInterface->GpeClearStatus = AcpiInterfaceClearStatus; + AcpiInterface->RegisterForDeviceNotifications = AcpiInterfaceNotificationsRegister; + AcpiInterface->UnregisterForDeviceNotifications = AcpiInterfaceNotificationsUnregister; + + return STATUS_SUCCESS; + } + else + { + DPRINT1("Invalid GUID\n"); + return STATUS_INVALID_PARAMETER; + } +} diff --git a/drivers/storage/scsiport/scsiport.pspec b/drivers/storage/scsiport/scsiport.pspec new file mode 100644 index 00000000000..65c75471c4d --- /dev/null +++ b/drivers/storage/scsiport/scsiport.pspec @@ -0,0 +1,51 @@ +#ifdef __x86_64__ +#define MAYBEFWD(x) +#else +#define MAYBEFWD(x) x +#endif + +@ cdecl ScsiDebugPrint() +@ stdcall ScsiPortCompleteRequest(ptr long long long long) +@ stdcall ScsiPortConvertPhysicalAddressToUlong(long long) +@ stdcall ScsiPortConvertUlongToPhysicalAddress(long) MAYBEFWD(NTOSKRNL.RtlConvertUlongToLargeInteger) +@ stdcall ScsiPortFlushDma(ptr) +@ stdcall ScsiPortFreeDeviceBase(ptr ptr) +@ stdcall ScsiPortGetBusData(ptr long long long ptr long) +@ stdcall ScsiPortGetDeviceBase(ptr long long long long long long) +@ stdcall ScsiPortGetLogicalUnit(ptr long long long) +@ stdcall ScsiPortGetPhysicalAddress(ptr ptr ptr long) +@ stdcall ScsiPortGetSrb(ptr long long long long) +@ stdcall ScsiPortGetUncachedExtension(ptr ptr long) +@ stdcall ScsiPortGetVirtualAddress(ptr long long) +@ stdcall ScsiPortInitialize(ptr ptr ptr ptr) +@ stdcall ScsiPortIoMapTransfer(ptr ptr long long) +@ stdcall ScsiPortLogError(ptr ptr long long long long long) +@ stdcall ScsiPortMoveMemory(ptr ptr long) +@ cdecl ScsiPortNotification() +@ stdcall ScsiPortReadPortBufferUchar(ptr ptr long) MAYBEFWD(HAL.READ_PORT_BUFFER_UCHAR) +@ stdcall ScsiPortReadPortBufferUshort(ptr ptr long) MAYBEFWD(HAL.READ_PORT_BUFFER_USHORT) +@ stdcall ScsiPortReadPortBufferUlong(ptr ptr long) MAYBEFWD(HAL.READ_PORT_BUFFER_ULONG) +@ stdcall ScsiPortReadPortUchar(ptr) MAYBEFWD(HAL.READ_PORT_UCHAR) +@ stdcall ScsiPortReadPortUshort(ptr) MAYBEFWD(HAL.READ_PORT_USHORT) +@ stdcall ScsiPortReadPortUlong(ptr) MAYBEFWD(HAL.READ_PORT_ULONG) +@ stdcall ScsiPortReadRegisterBufferUchar(ptr ptr long) MAYBEFWD(NTOSKRNL.READ_REGISTER_BUFFER_UCHAR) +@ stdcall ScsiPortReadRegisterBufferUshort(ptr ptr long) MAYBEFWD(NTOSKRNL.READ_REGISTER_BUFFER_USHORT) +@ stdcall ScsiPortReadRegisterBufferUlong(ptr ptr long) MAYBEFWD(NTOSKRNL.READ_REGISTER_BUFFER_ULONG) +@ stdcall ScsiPortReadRegisterUchar(ptr) MAYBEFWD(NTOSKRNL.READ_REGISTER_UCHAR) +@ stdcall ScsiPortReadRegisterUshort(ptr) MAYBEFWD(NTOSKRNL.READ_REGISTER_USHORT) +@ stdcall ScsiPortReadRegisterUlong(ptr) MAYBEFWD(NTOSKRNL.READ_REGISTER_ULONG) +@ stdcall ScsiPortSetBusDataByOffset(ptr long long long ptr long long) +@ stdcall ScsiPortStallExecution(long) HAL.KeStallExecutionProcessor +@ stdcall ScsiPortValidateRange(ptr long long long long long long) +@ stdcall ScsiPortWritePortBufferUchar(ptr ptr long) MAYBEFWD(HAL.WRITE_PORT_BUFFER_UCHAR) +@ stdcall ScsiPortWritePortBufferUshort(ptr ptr long) MAYBEFWD(HAL.WRITE_PORT_BUFFER_USHORT) +@ stdcall ScsiPortWritePortBufferUlong(ptr ptr long) MAYBEFWD(HAL.WRITE_PORT_BUFFER_ULONG) +@ stdcall ScsiPortWritePortUchar(ptr long) MAYBEFWD(HAL.WRITE_PORT_UCHAR) +@ stdcall ScsiPortWritePortUshort(ptr long) MAYBEFWD(HAL.WRITE_PORT_USHORT) +@ stdcall ScsiPortWritePortUlong(ptr long) MAYBEFWD(HAL.WRITE_PORT_ULONG) +@ stdcall ScsiPortWriteRegisterBufferUchar(ptr ptr long) MAYBEFWD(NTOSKRNL.WRITE_REGISTER_BUFFER_UCHAR) +@ stdcall ScsiPortWriteRegisterBufferUshort(ptr ptr long) MAYBEFWD(NTOSKRNL.WRITE_REGISTER_BUFFER_USHORT) +@ stdcall ScsiPortWriteRegisterBufferUlong(ptr ptr long) MAYBEFWD(NTOSKRNL.WRITE_REGISTER_BUFFER_ULONG) +@ stdcall ScsiPortWriteRegisterUchar(ptr long) MAYBEFWD(NTOSKRNL.WRITE_REGISTER_UCHAR) +@ stdcall ScsiPortWriteRegisterUshort(ptr long) MAYBEFWD(NTOSKRNL.WRITE_REGISTER_USHORT) +@ stdcall ScsiPortWriteRegisterUlong(ptr long) MAYBEFWD(NTOSKRNL.WRITE_REGISTER_ULONG) diff --git a/drivers/storage/scsiport/stubs.c b/drivers/storage/scsiport/stubs.c new file mode 100644 index 00000000000..9e286d186f4 --- /dev/null +++ b/drivers/storage/scsiport/stubs.c @@ -0,0 +1,250 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Storage Stack + * FILE: drivers/storage/scsiport/stubs.c + * PURPOSE: SCSI port driver + * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) + */ + +/* INCLUDES *****************************************************************/ + +#include +#include + +#define NDEBUG +#include + +#ifdef _MSC_VER + #define DDKAPI +#endif + +SCSI_PHYSICAL_ADDRESS +DDKAPI +ScsiPortConvertUlongToPhysicalAddress( + IN ULONG UlongAddress) +{ + return RtlConvertUlongToLargeInteger(UlongAddress); +} + +VOID +DDKAPI +ScsiPortReadPortBufferUchar( + IN PUCHAR Port, + IN PUCHAR Buffer, + IN ULONG Count) +{ + READ_PORT_BUFFER_UCHAR(Port, Buffer, Count); +} + +VOID +DDKAPI +ScsiPortReadPortBufferUshort( + IN PUSHORT Port, + IN PUSHORT Buffer, + IN ULONG Count) +{ + READ_PORT_BUFFER_USHORT(Port, Buffer, Count); +} + +VOID +DDKAPI +ScsiPortReadPortBufferUlong( + IN PULONG Port, + IN PULONG Buffer, + IN ULONG Count) +{ + READ_PORT_BUFFER_ULONG(Port, Buffer, Count); +} + +UCHAR +DDKAPI +ScsiPortReadPortUchar( + IN PUCHAR Port) +{ + return READ_PORT_UCHAR(Port); +} + +USHORT +DDKAPI +ScsiPortReadPortUshort( + IN PUSHORT Port) +{ + return READ_PORT_USHORT(Port); +} + +ULONG +DDKAPI +ScsiPortReadPortUlong( + IN PULONG Port) +{ + return READ_PORT_ULONG(Port); +} + +VOID +DDKAPI +ScsiPortReadRegisterBufferUchar( + IN PUCHAR Register, + IN PUCHAR Buffer, + IN ULONG Count) +{ + READ_REGISTER_BUFFER_UCHAR(Register, Buffer, Count); +} + +VOID +DDKAPI +ScsiPortReadRegisterBufferUshort( + IN PUSHORT Register, + IN PUSHORT Buffer, + IN ULONG Count) +{ + READ_REGISTER_BUFFER_USHORT(Register, Buffer, Count); +} + +VOID +DDKAPI +ScsiPortReadRegisterBufferUlong( + IN PULONG Register, + IN PULONG Buffer, + IN ULONG Count) +{ + READ_REGISTER_BUFFER_ULONG(Register, Buffer, Count); +} + +UCHAR +DDKAPI +ScsiPortReadRegisterUchar( + IN PUCHAR Register) +{ + return READ_REGISTER_UCHAR(Register); +} + +USHORT +DDKAPI +ScsiPortReadRegisterUshort( + IN PUSHORT Register) +{ + return READ_REGISTER_USHORT(Register); +} + +ULONG +DDKAPI +ScsiPortReadRegisterUlong( + IN PULONG Register) +{ + return READ_REGISTER_ULONG(Register); +} + +VOID +DDKAPI +ScsiPortWritePortBufferUchar( + IN PUCHAR Port, + IN PUCHAR Buffer, + IN ULONG Count) +{ + WRITE_PORT_BUFFER_UCHAR(Port, Buffer, Count); +} + +VOID +DDKAPI +ScsiPortWritePortBufferUshort( + IN PUSHORT Port, + IN PUSHORT Buffer, + IN ULONG Count) +{ + WRITE_PORT_BUFFER_USHORT(Port, Buffer, Count); +} + +VOID +DDKAPI +ScsiPortWritePortBufferUlong( + IN PULONG Port, + IN PULONG Buffer, + IN ULONG Count) +{ + WRITE_PORT_BUFFER_ULONG(Port, Buffer, Count); +} + +VOID +DDKAPI +ScsiPortWritePortUchar( + IN PUCHAR Port, + IN UCHAR Value) +{ + WRITE_PORT_UCHAR(Port, Value); +} + +VOID +DDKAPI +ScsiPortWritePortUshort( + IN PUSHORT Port, + IN USHORT Value) +{ + WRITE_PORT_USHORT(Port, Value); +} + +VOID +DDKAPI +ScsiPortWritePortUlong( + IN PULONG Port, + IN ULONG Value) +{ + WRITE_PORT_ULONG(Port, Value); +} + +VOID +DDKAPI +ScsiPortWriteRegisterBufferUchar( + IN PUCHAR Register, + IN PUCHAR Buffer, + IN ULONG Count) +{ + WRITE_REGISTER_BUFFER_UCHAR(Register, Buffer, Count); +} + +VOID +DDKAPI +ScsiPortWriteRegisterBufferUshort( + IN PUSHORT Register, + IN PUSHORT Buffer, + IN ULONG Count) +{ + WRITE_REGISTER_BUFFER_USHORT(Register, Buffer, Count); +} + +VOID +DDKAPI +ScsiPortWriteRegisterBufferUlong( + IN PULONG Register, + IN PULONG Buffer, + IN ULONG Count) +{ + WRITE_REGISTER_BUFFER_ULONG(Register, Buffer, Count); +} + +VOID +DDKAPI +ScsiPortWriteRegisterUchar( + IN PUCHAR Register, + IN ULONG Value) +{ + WRITE_REGISTER_UCHAR(Register, Value); +} + +VOID +DDKAPI +ScsiPortWriteRegisterUshort( + IN PUSHORT Register, + IN USHORT Value) +{ + WRITE_REGISTER_USHORT(Register, Value); +} + +VOID +DDKAPI +ScsiPortWriteRegisterUlong( + IN PULONG Register, + IN ULONG Value) +{ + WRITE_REGISTER_ULONG(Register, Value); +} + diff --git a/hal/halx86/up/pic.c b/hal/halx86/up/pic.c new file mode 100644 index 00000000000..a710d862567 --- /dev/null +++ b/hal/halx86/up/pic.c @@ -0,0 +1,1363 @@ +/* + * PROJECT: ReactOS HAL + * LICENSE: BSD - See COPYING.ARM in the top level directory + * FILE: hal/halx86/generic/pic.c + * PURPOSE: HAL PIC Management and Control Code + * PROGRAMMERS: ReactOS Portable Systems Group + */ + +/* INCLUDES *******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS ********************************************************************/ + +#ifndef _MINIHAL_ +/* + * This table basically keeps track of level vs edge triggered interrupts. + * Windows has 250+ entries, but it seems stupid to replicate that since the PIC + * can't actually have that many. + * + * When a level interrupt is registered, the respective pointer in this table is + * modified to point to a dimiss routine for level interrupts instead. + * + * The other thing this table does is special case IRQ7, IRQ13 and IRQ15: + * + * - If an IRQ line is deasserted before it is acknowledged due to a noise spike + * generated by an expansion device (since the IRQ line is low during the 1st + * acknowledge bus cycle), the i8259 will keep the line low for at least 100ns + * When the spike passes, a pull-up resistor will return the IRQ line to high. + * Since the PIC requires the input be high until the first acknowledge, the + * i8259 knows that this was a spurious interrupt, and on the second interrupt + * acknowledge cycle, it reports this to the CPU. Since no valid interrupt has + * actually happened Intel hardcoded the chip to report IRQ7 on the master PIC + * and IRQ15 on the slave PIC (IR7 either way). + * + * "ISA System Architecture", 3rd Edition, states that these cases should be + * handled by reading the respective Interrupt Service Request (ISR) bits from + * the affected PIC, and validate whether or not IR7 is set. If it isn't, then + * the interrupt is spurious and should be ignored. + * + * Note that for a spurious IRQ15, we DO have to send an EOI to the master for + * IRQ2 since the line was asserted by the slave when it received the spurious + * IRQ15! + * + * - When the 80287/80387 math co-processor generates an FPU/NPX trap, this is + * connected to IRQ13, so we have to clear the busy latch on the NPX port. + */ +PHAL_DISMISS_INTERRUPT HalpSpecialDismissTable[16] = +{ + HalpDismissIrqGeneric, + HalpDismissIrqGeneric, + HalpDismissIrqGeneric, + HalpDismissIrqGeneric, + HalpDismissIrqGeneric, + HalpDismissIrqGeneric, + HalpDismissIrqGeneric, + HalpDismissIrq07, + HalpDismissIrqGeneric, + HalpDismissIrqGeneric, + HalpDismissIrqGeneric, + HalpDismissIrqGeneric, + HalpDismissIrqGeneric, + HalpDismissIrq13, + HalpDismissIrqGeneric, + HalpDismissIrq15 +}; + +/* + * These are the level IRQ dismissal functions that get copied in the table + * above if the given IRQ is actually level triggered. + */ +PHAL_DISMISS_INTERRUPT HalpSpecialDismissLevelTable[16] = +{ + HalpDismissIrqLevel, + HalpDismissIrqLevel, + HalpDismissIrqLevel, + HalpDismissIrqLevel, + HalpDismissIrqLevel, + HalpDismissIrqLevel, + HalpDismissIrqLevel, + HalpDismissIrq07Level, + HalpDismissIrqLevel, + HalpDismissIrqLevel, + HalpDismissIrqLevel, + HalpDismissIrqLevel, + HalpDismissIrqLevel, + HalpDismissIrq13Level, + HalpDismissIrqLevel, + HalpDismissIrq15Level +}; + +/* This table contains the static x86 PIC mapping between IRQLs and IRQs */ +ULONG KiI8259MaskTable[32] = +{ +#ifdef __GNUC__ +#if __GNUC__ * 100 + __GNUC_MINOR__ >= 404 + /* + * It Device IRQLs only start at 4 or higher, so these are just software + * IRQLs that don't really change anything on the hardware + */ + 0b00000000000000000000000000000000, /* IRQL 0 */ + 0b00000000000000000000000000000000, /* IRQL 1 */ + 0b00000000000000000000000000000000, /* IRQL 2 */ + 0b00000000000000000000000000000000, /* IRQL 3 */ + + /* + * These next IRQLs are actually useless from the PIC perspective, because + * with only 2 PICs, the mask you can send them is only 8 bits each, for 16 + * bits total, so these IRQLs are masking off a phantom PIC. + */ + 0b11111111100000000000000000000000, /* IRQL 4 */ + 0b11111111110000000000000000000000, /* IRQL 5 */ + 0b11111111111000000000000000000000, /* IRQL 6 */ + 0b11111111111100000000000000000000, /* IRQL 7 */ + 0b11111111111110000000000000000000, /* IRQL 8 */ + 0b11111111111111000000000000000000, /* IRQL 9 */ + 0b11111111111111100000000000000000, /* IRQL 10 */ + 0b11111111111111110000000000000000, /* IRQL 11 */ + + /* + * Okay, now we're finally starting to mask off IRQs on the slave PIC, from + * IRQ15 to IRQ8. This means the higher-level IRQs get less priority in the + * IRQL sense. + */ + 0b11111111111111111000000000000000, /* IRQL 12 */ + 0b11111111111111111100000000000000, /* IRQL 13 */ + 0b11111111111111111110000000000000, /* IRQL 14 */ + 0b11111111111111111111000000000000, /* IRQL 15 */ + 0b11111111111111111111100000000000, /* IRQL 16 */ + 0b11111111111111111111110000000000, /* IRQL 17 */ + 0b11111111111111111111111000000000, /* IRQL 18 */ + 0b11111111111111111111111000000000, /* IRQL 19 */ + + /* + * Now we mask off the IRQs on the master. Notice the 0 "droplet"? You might + * have also seen that IRQL 18 and 19 are essentially equal as far as the + * PIC is concerned. That bit is actually IRQ8, which happens to be the RTC. + * The RTC will keep firing as long as we don't reach PROFILE_LEVEL which + * actually kills it. The RTC clock (unlike the system clock) is used by the + * profiling APIs in the HAL, so that explains the logic. + */ + 0b11111111111111111111111010000000, /* IRQL 20 */ + 0b11111111111111111111111011000000, /* IRQL 21 */ + 0b11111111111111111111111011100000, /* IRQL 22 */ + 0b11111111111111111111111011110000, /* IRQL 23 */ + 0b11111111111111111111111011111000, /* IRQL 24 */ + 0b11111111111111111111111011111000, /* IRQL 25 */ + 0b11111111111111111111111011111010, /* IRQL 26 */ + 0b11111111111111111111111111111010, /* IRQL 27 */ + + /* + * IRQL 24 and 25 are actually identical, so IRQL 28 is actually the last + * IRQL to modify a bit on the master PIC. It happens to modify the very + * last of the IRQs, IRQ0, which corresponds to the system clock interval + * timer that keeps track of time (the Windows heartbeat). We only want to + * turn this off at a high-enough IRQL, which is why IRQLs 24 and 25 are the + * same to give this guy a chance to come up higher. Note that IRQL 28 is + * called CLOCK2_LEVEL, which explains the usage we just explained. + */ + 0b11111111111111111111111111111011, /* IRQL 28 */ + + /* + * We have finished off with the PIC so there's nothing left to mask at the + * level of these IRQLs, making them only logical IRQLs on x86 machines. + * Note that we have another 0 "droplet" you might've caught since IRQL 26. + * In this case, it's the 2nd bit that never gets turned off, which is IRQ2, + * the cascade IRQ that we use to bridge the slave PIC with the master PIC. + * We never want to turn it off, so no matter the IRQL, it will be set to 0. + */ + 0b11111111111111111111111111111011, /* IRQL 29 */ + 0b11111111111111111111111111111011, /* IRQL 30 */ + 0b11111111111111111111111111111011 /* IRQL 31 */ +#else + 0, /* IRQL 0 */ + 0, /* IRQL 1 */ + 0, /* IRQL 2 */ + 0, /* IRQL 3 */ + 0xFF800000, /* IRQL 4 */ + 0xFFC00000, /* IRQL 5 */ + 0xFFE00000, /* IRQL 6 */ + 0xFFF00000, /* IRQL 7 */ + 0xFFF80000, /* IRQL 8 */ + 0xFFFC0000, /* IRQL 9 */ + 0xFFFE0000, /* IRQL 10 */ + 0xFFFF0000, /* IRQL 11 */ + 0xFFFF8000, /* IRQL 12 */ + 0xFFFFC000, /* IRQL 13 */ + 0xFFFFE000, /* IRQL 14 */ + 0xFFFFF000, /* IRQL 15 */ + 0xFFFFF800, /* IRQL 16 */ + 0xFFFFFC00, /* IRQL 17 */ + 0xFFFFFE00, /* IRQL 18 */ + 0xFFFFFE00, /* IRQL 19 */ + 0xFFFFFE80, /* IRQL 20 */ + 0xFFFFFEC0, /* IRQL 21 */ + 0xFFFFFEE0, /* IRQL 22 */ + 0xFFFFFEF0, /* IRQL 23 */ + 0xFFFFFEF8, /* IRQL 24 */ + 0xFFFFFEF8, /* IRQL 25 */ + 0xFFFFFEFA, /* IRQL 26 */ + 0xFFFFFFFA, /* IRQL 27 */ + 0xFFFFFFFB, /* IRQL 28 */ + 0xFFFFFFFB, /* IRQL 29 */ + 0xFFFFFFFB, /* IRQL 30 */ + 0xFFFFFFFB /* IRQL 31 */ +#endif +#endif +}; + +/* This table indicates which IRQs, if pending, can preempt a given IRQL level */ +ULONG FindHigherIrqlMask[32] = +{ +#ifdef __GNUC__ +#if __GNUC__ * 100 + __GNUC_MINOR__ >= 404 + /* + * Software IRQLs, at these levels all hardware interrupts can preempt. + * Each higher IRQL simply enables which software IRQL can preempt the + * current level. + */ + 0b11111111111111111111111111111110, /* IRQL 0 */ + 0b11111111111111111111111111111100, /* IRQL 1 */ + 0b11111111111111111111111111111000, /* IRQL 2 */ + + /* + * IRQL3 means only hardware IRQLs can now preempt. These last 4 zeros will + * then continue throughout the rest of the list, trickling down. + */ + 0b11111111111111111111111111110000, /* IRQL 3 */ + + /* + * Just like in the previous list, these masks don't really mean anything + * since we've only got two PICs with 16 possible IRQs total + */ + 0b00000111111111111111111111110000, /* IRQL 4 */ + 0b00000011111111111111111111110000, /* IRQL 5 */ + 0b00000001111111111111111111110000, /* IRQL 6 */ + 0b00000000111111111111111111110000, /* IRQL 7 */ + 0b00000000011111111111111111110000, /* IRQL 8 */ + 0b00000000001111111111111111110000, /* IRQL 9 */ + 0b00000000000111111111111111110000, /* IRQL 10 */ + + /* + * Now we start progressivly limiting which slave PIC interrupts have the + * right to preempt us at each level. + */ + 0b00000000000011111111111111110000, /* IRQL 11 */ + 0b00000000000001111111111111110000, /* IRQL 12 */ + 0b00000000000000111111111111110000, /* IRQL 13 */ + 0b00000000000000011111111111110000, /* IRQL 14 */ + 0b00000000000000001111111111110000, /* IRQL 15 */ + 0b00000000000000000111111111110000, /* IRQL 16 */ + 0b00000000000000000011111111110000, /* IRQL 17 */ + 0b00000000000000000001111111110000, /* IRQL 18 */ + 0b00000000000000000001111111110000, /* IRQL 19 */ + + /* + * Also recall from the earlier table that IRQL 18/19 are treated the same + * in order to spread the masks better thoughout the 32 IRQLs and to reflect + * the fact that some bits will always stay on until much higher IRQLs since + * they are system-critical. One such example is the 1 bit that you start to + * see trickling down here. This is IRQ8, the RTC timer used for profiling, + * so it will always preempt until we reach PROFILE_LEVEL. + */ + 0b00000000000000000001011111110000, /* IRQL 20 */ + 0b00000000000000000001001111110000, /* IRQL 20 */ + 0b00000000000000000001000111110000, /* IRQL 22 */ + 0b00000000000000000001000011110000, /* IRQL 23 */ + 0b00000000000000000001000001110000, /* IRQL 24 */ + 0b00000000000000000001000000110000, /* IRQL 25 */ + 0b00000000000000000001000000010000, /* IRQL 26 */ + + /* At this point, only the clock (IRQ0) can still preempt... */ + 0b00000000000000000000000000010000, /* IRQL 27 */ + + /* And any higher than that there's no relation with hardware PICs anymore */ + 0b00000000000000000000000000000000, /* IRQL 28 */ + 0b00000000000000000000000000000000, /* IRQL 29 */ + 0b00000000000000000000000000000000, /* IRQL 30 */ + 0b00000000000000000000000000000000, /* IRQL 31 */ +#else + 0xFFFFFFFE, /* IRQL 0 */ + 0xFFFFFFFC, /* IRQL 1 */ + 0xFFFFFFF8, /* IRQL 2 */ + 0xFFFFFFF0, /* IRQL 3 */ + 0x7FFFFF0, /* IRQL 4 */ + 0x3FFFFF0, /* IRQL 5 */ + 0x1FFFFF0, /* IRQL 6 */ + 0x0FFFFF0, /* IRQL 7 */ + 0x7FFFF0, /* IRQL 8 */ + 0x3FFFF0, /* IRQL 9 */ + 0x1FFFF0, /* IRQL 10 */ + 0x0FFFF0, /* IRQL 11 */ + 0x7FFF0, /* IRQL 12 */ + 0x3FFF0, /* IRQL 13 */ + 0x1FFF0, /* IRQL 14 */ + 0x0FFF0, /* IRQL 15 */ + 0x7FF0, /* IRQL 16 */ + 0x3FF0, /* IRQL 17 */ + 0x1FF0, /* IRQL 18 */ + 0x1FF0, /* IRQL 19 */ + 0x17F0, /* IRQL 20 */ + 0x13F0, /* IRQL 21 */ + 0x11F0, /* IRQL 22 */ + 0x10F0, /* IRQL 23 */ + 0x1070, /* IRQL 24 */ + 0x1030, /* IRQL 25 */ + 0x1010, /* IRQL 26 */ + 0x10, /* IRQL 27 */ + 0, /* IRQL 28 */ + 0, /* IRQL 29 */ + 0, /* IRQL 30 */ + 0 /* IRQL 31 */ +#endif +#endif +}; + +/* Denotes minimum required IRQL before we can process pending SW interrupts */ +KIRQL SWInterruptLookUpTable[8] = +{ + PASSIVE_LEVEL, /* IRR 0 */ + PASSIVE_LEVEL, /* IRR 1 */ + APC_LEVEL, /* IRR 2 */ + APC_LEVEL, /* IRR 3 */ + DISPATCH_LEVEL, /* IRR 4 */ + DISPATCH_LEVEL, /* IRR 5 */ + DISPATCH_LEVEL, /* IRR 6 */ + DISPATCH_LEVEL /* IRR 7 */ +}; + +#define HalpDelayedHardwareInterrupt(x) \ + VOID HalpHardwareInterrupt##x(VOID); \ + VOID \ + HalpHardwareInterrupt##x(VOID) \ + { \ + asm volatile ("int $%c0\n"::"i"(PRIMARY_VECTOR_BASE + x)); \ + } + +/* Pending/delayed hardware interrupt handlers */ +HalpDelayedHardwareInterrupt(0); +HalpDelayedHardwareInterrupt(1); +HalpDelayedHardwareInterrupt(2); +HalpDelayedHardwareInterrupt(3); +HalpDelayedHardwareInterrupt(4); +HalpDelayedHardwareInterrupt(5); +HalpDelayedHardwareInterrupt(6); +HalpDelayedHardwareInterrupt(7); +HalpDelayedHardwareInterrupt(8); +HalpDelayedHardwareInterrupt(9); +HalpDelayedHardwareInterrupt(10); +HalpDelayedHardwareInterrupt(11); +HalpDelayedHardwareInterrupt(12); +HalpDelayedHardwareInterrupt(13); +HalpDelayedHardwareInterrupt(14); +HalpDelayedHardwareInterrupt(15); + +/* Handlers for pending interrupts */ +PHAL_SW_INTERRUPT_HANDLER SWInterruptHandlerTable[20] = +{ + KiUnexpectedInterrupt, + HalpApcInterrupt, + HalpDispatchInterrupt2, + KiUnexpectedInterrupt, + HalpHardwareInterrupt0, + HalpHardwareInterrupt1, + HalpHardwareInterrupt2, + HalpHardwareInterrupt3, + HalpHardwareInterrupt4, + HalpHardwareInterrupt5, + HalpHardwareInterrupt6, + HalpHardwareInterrupt7, + HalpHardwareInterrupt8, + HalpHardwareInterrupt9, + HalpHardwareInterrupt10, + HalpHardwareInterrupt11, + HalpHardwareInterrupt12, + HalpHardwareInterrupt13, + HalpHardwareInterrupt14, + HalpHardwareInterrupt15 +}; + +/* Handlers for pending software interrupts when we already have a trap frame*/ +PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY SWInterruptHandlerTable2[3] = +{ + (PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY)KiUnexpectedInterrupt, + HalpApcInterrupt2ndEntry, + HalpDispatchInterrupt2ndEntry +}; + +LONG HalpEisaELCR; + +/* FUNCTIONS ******************************************************************/ + +VOID +NTAPI +HalpInitializePICs(IN BOOLEAN EnableInterrupts) +{ + ULONG EFlags; + I8259_ICW1 Icw1; + I8259_ICW2 Icw2; + I8259_ICW3 Icw3; + I8259_ICW4 Icw4; + EISA_ELCR Elcr; + ULONG i, j; + + /* Save EFlags and disable interrupts */ + EFlags = __readeflags(); + _disable(); + + /* Initialize ICW1 for master, interval 8, edge-triggered mode with ICW4 */ + Icw1.NeedIcw4 = TRUE; + Icw1.InterruptMode = EdgeTriggered; + Icw1.OperatingMode = Cascade; + Icw1.Interval = Interval8; + Icw1.Init = TRUE; + Icw1.InterruptVectorAddress = 0; /* This is only used in MCS80/85 mode */ + __outbyte(PIC1_CONTROL_PORT, Icw1.Bits); + + /* Set interrupt vector base */ + Icw2.Bits = PRIMARY_VECTOR_BASE; + __outbyte(PIC1_DATA_PORT, Icw2.Bits); + + /* Connect slave to IRQ 2 */ + Icw3.Bits = 0; + Icw3.SlaveIrq2 = TRUE; + __outbyte(PIC1_DATA_PORT, Icw3.Bits); + + /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */ + Icw4.Reserved = 0; + Icw4.SystemMode = New8086Mode; + Icw4.EoiMode = NormalEoi; + Icw4.BufferedMode = NonBuffered; + Icw4.SpecialFullyNestedMode = FALSE; + __outbyte(PIC1_DATA_PORT, Icw4.Bits); + + /* Mask all interrupts */ + __outbyte(PIC1_DATA_PORT, 0xFF); + + /* Initialize ICW1 for master, interval 8, edge-triggered mode with ICW4 */ + Icw1.NeedIcw4 = TRUE; + Icw1.InterruptMode = EdgeTriggered; + Icw1.OperatingMode = Cascade; + Icw1.Interval = Interval8; + Icw1.Init = TRUE; + Icw1.InterruptVectorAddress = 0; /* This is only used in MCS80/85 mode */ + __outbyte(PIC2_CONTROL_PORT, Icw1.Bits); + + /* Set interrupt vector base */ + Icw2.Bits = PRIMARY_VECTOR_BASE + 8; + __outbyte(PIC2_DATA_PORT, Icw2.Bits); + + /* Slave ID */ + Icw3.Bits = 0; + Icw3.SlaveId = 2; + __outbyte(PIC2_DATA_PORT, Icw3.Bits); + + /* Enable 8086 mode, non-automatic EOI, non-buffered mode, non special fully nested mode */ + Icw4.Reserved = 0; + Icw4.SystemMode = New8086Mode; + Icw4.EoiMode = NormalEoi; + Icw4.BufferedMode = NonBuffered; + Icw4.SpecialFullyNestedMode = FALSE; + __outbyte(PIC2_DATA_PORT, Icw4.Bits); + + /* Mask all interrupts */ + __outbyte(PIC2_DATA_PORT, 0xFF); + + /* Read EISA Edge/Level Register for master and slave */ + Elcr.Bits = (__inbyte(EISA_ELCR_SLAVE) << 8) | __inbyte(EISA_ELCR_MASTER); + + /* IRQs 0, 1, 2, 8, and 13 are system-reserved and must be edge */ + if (!(Elcr.Master.Irq0Level) && !(Elcr.Master.Irq1Level) && !(Elcr.Master.Irq2Level) && + !(Elcr.Slave.Irq8Level) && !(Elcr.Slave.Irq13Level)) + { + /* ELCR is as it's supposed to be, save it */ + HalpEisaELCR = Elcr.Bits; + + /* Scan for level interrupts */ + for (i = 1, j = 0; j < 16; i <<= 1, j++) + { + if (HalpEisaELCR & i) + { + /* Switch handler to level */ + SWInterruptHandlerTable[j + 4] = HalpHardwareInterruptLevel; + + /* Switch dismiss to level */ + HalpSpecialDismissTable[j] = HalpSpecialDismissLevelTable[j]; + } + } + } + + /* Restore interrupt state */ + if (EnableInterrupts) EFlags |= EFLAGS_INTERRUPT_MASK; + __writeeflags(EFlags); +} + +/* IRQL MANAGEMENT ************************************************************/ + +/* + * @implemented + */ +KIRQL +NTAPI +KeGetCurrentIrql(VOID) +{ + /* Return the IRQL */ + return KeGetPcr()->Irql; +} + +/* + * @implemented + */ +KIRQL +NTAPI +KeRaiseIrqlToDpcLevel(VOID) +{ + PKPCR Pcr = KeGetPcr(); + KIRQL CurrentIrql; + + /* Save and update IRQL */ + CurrentIrql = Pcr->Irql; + Pcr->Irql = DISPATCH_LEVEL; + +#ifdef IRQL_DEBUG + /* Validate correct raise */ + if (CurrentIrql > DISPATCH_LEVEL) KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL); +#endif + + /* Return the previous value */ + return CurrentIrql; +} + +/* + * @implemented + */ +KIRQL +NTAPI +KeRaiseIrqlToSynchLevel(VOID) +{ + PKPCR Pcr = KeGetPcr(); + KIRQL CurrentIrql; + + /* Save and update IRQL */ + CurrentIrql = Pcr->Irql; + Pcr->Irql = SYNCH_LEVEL; + +#ifdef IRQL_DEBUG + /* Validate correct raise */ + if (CurrentIrql > SYNCH_LEVEL) + { + /* Crash system */ + KeBugCheckEx(IRQL_NOT_GREATER_OR_EQUAL, + CurrentIrql, + SYNCH_LEVEL, + 0, + 1); + } +#endif + + /* Return the previous value */ + return CurrentIrql; +} + +/* + * @implemented + */ +KIRQL +FASTCALL +KfRaiseIrql(IN KIRQL NewIrql) +{ + PKPCR Pcr = KeGetPcr(); + KIRQL CurrentIrql; + + /* Read current IRQL */ + CurrentIrql = Pcr->Irql; + +#ifdef IRQL_DEBUG + /* Validate correct raise */ + if (CurrentIrql > NewIrql) + { + /* Crash system */ + Pcr->Irql = PASSIVE_LEVEL; + KeBugCheck(IRQL_NOT_GREATER_OR_EQUAL); + } +#endif + + /* Set new IRQL */ + Pcr->Irql = NewIrql; + + /* Return old IRQL */ + return CurrentIrql; +} + + +/* + * @implemented + */ +VOID +FASTCALL +KfLowerIrql(IN KIRQL OldIrql) +{ + ULONG EFlags; + ULONG PendingIrql, PendingIrqlMask; + PKPCR Pcr = KeGetPcr(); + PIC_MASK Mask; + +#ifdef IRQL_DEBUG + /* Validate correct lower */ + if (OldIrql > Pcr->Irql) + { + /* Crash system */ + Pcr->Irql = HIGH_LEVEL; + KeBugCheck(IRQL_NOT_LESS_OR_EQUAL); + } +#endif + + /* Save EFlags and disable interrupts */ + EFlags = __readeflags(); + _disable(); + + /* Set old IRQL */ + Pcr->Irql = OldIrql; + + /* Check for pending software interrupts and compare with current IRQL */ + PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql]; + if (PendingIrqlMask) + { + /* Check if pending IRQL affects hardware state */ + BitScanReverse(&PendingIrql, PendingIrqlMask); + if (PendingIrql > DISPATCH_LEVEL) + { + /* Set new PIC mask */ + Mask.Both = Pcr->IDR; + __outbyte(PIC1_DATA_PORT, Mask.Master); + __outbyte(PIC2_DATA_PORT, Mask.Slave); + + /* Clear IRR bit */ + Pcr->IRR ^= (1 << PendingIrql); + } + + /* Now handle pending interrupt */ + SWInterruptHandlerTable[PendingIrql](); + } + + /* Restore interrupt state */ + __writeeflags(EFlags); +} + +/* SOFTWARE INTERRUPTS ********************************************************/ + +/* + * @implemented + */ +VOID +FASTCALL +HalRequestSoftwareInterrupt(IN KIRQL Irql) +{ + ULONG EFlags; + PKPCR Pcr = KeGetPcr(); + KIRQL PendingIrql; + + /* Save EFlags and disable interrupts */ + EFlags = __readeflags(); + _disable(); + + /* Mask out the requested bit */ + Pcr->IRR |= (1 << Irql); + + /* Check for pending software interrupts and compare with current IRQL */ + PendingIrql = SWInterruptLookUpTable[Pcr->IRR & 3]; + if (PendingIrql > Pcr->Irql) SWInterruptHandlerTable[PendingIrql](); + + /* Restore interrupt state */ + __writeeflags(EFlags); +} + +/* + * @implemented + */ +VOID +FASTCALL +HalClearSoftwareInterrupt(IN KIRQL Irql) +{ + /* Mask out the requested bit */ + KeGetPcr()->IRR &= ~(1 << Irql); +} + +VOID +NTAPI +HalpEndSoftwareInterrupt(IN KIRQL OldIrql, + IN PKTRAP_FRAME TrapFrame) +{ + ULONG PendingIrql, PendingIrqlMask, PendingIrqMask; + PKPCR Pcr = KeGetPcr(); + PIC_MASK Mask; + + /* Set old IRQL */ + Pcr->Irql = OldIrql; + + /* Loop checking for pending interrupts */ + while (TRUE) + { + /* Check for pending software interrupts and compare with current IRQL */ + PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql]; + if (!PendingIrqlMask) return; + + /* Check for in-service delayed interrupt */ + if (Pcr->IrrActive & 0xFFFFFFF0) return; + + /* Check if pending IRQL affects hardware state */ + BitScanReverse(&PendingIrql, PendingIrqlMask); + if (PendingIrql > DISPATCH_LEVEL) + { + /* Set new PIC mask */ + Mask.Both = Pcr->IDR; + __outbyte(PIC1_DATA_PORT, Mask.Master); + __outbyte(PIC2_DATA_PORT, Mask.Slave); + + /* Set active bit otherwise, and clear it from IRR */ + PendingIrqMask = (1 << PendingIrql); + Pcr->IrrActive |= PendingIrqMask; + Pcr->IRR ^= PendingIrqMask; + + /* Handle delayed hardware interrupt */ + SWInterruptHandlerTable[PendingIrql](); + + /* Handling complete */ + Pcr->IrrActive ^= PendingIrqMask; + } + else + { + /* No need to loop checking for hardware interrupts */ + SWInterruptHandlerTable2[PendingIrql](TrapFrame); + } + } +} + +/* EDGE INTERRUPT DISMISSAL FUNCTIONS *****************************************/ + +BOOLEAN +FORCEINLINE +_HalpDismissIrqGeneric(IN KIRQL Irql, + IN ULONG Irq, + OUT PKIRQL OldIrql) +{ + PIC_MASK Mask; + KIRQL CurrentIrql; + I8259_OCW2 Ocw2; + PKPCR Pcr = KeGetPcr(); + + /* First save current IRQL and compare it to the requested one */ + CurrentIrql = Pcr->Irql; + + /* Check if this interrupt is really allowed to happen */ + if (Irql > CurrentIrql) + { + /* Set the new IRQL and return the current one */ + Pcr->Irql = Irql; + *OldIrql = CurrentIrql; + + /* Prepare OCW2 for EOI */ + Ocw2.Bits = 0; + Ocw2.EoiMode = SpecificEoi; + + /* Check which PIC needs the EOI */ + if (Irq > 8) + { + /* Send the EOI for the IRQ */ + __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | (Irq - 8)); + + /* Send the EOI for IRQ2 on the master because this was cascaded */ + __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2); + } + else + { + /* Send the EOI for the IRQ */ + __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | Irq); + } + + /* Enable interrupts and return success */ + _enable(); + return TRUE; + } + + /* Update the IRR so that we deliver this interrupt when the IRQL is proper */ + Pcr->IRR |= (1 << (Irq + 4)); + + /* Set new PIC mask to real IRQL level, since the optimization is lost now */ + Mask.Both = KiI8259MaskTable[CurrentIrql] | Pcr->IDR; + __outbyte(PIC1_DATA_PORT, Mask.Master); + __outbyte(PIC2_DATA_PORT, Mask.Slave); + + /* Now lie and say this was spurious */ + return FALSE; +} + +BOOLEAN +__attribute__((regparm(3))) +HalpDismissIrqGeneric(IN KIRQL Irql, + IN ULONG Irq, + OUT PKIRQL OldIrql) +{ + /* Run the inline code */ + return _HalpDismissIrqGeneric(Irql, Irq, OldIrql); +} + +BOOLEAN +__attribute__((regparm(3))) +HalpDismissIrq15(IN KIRQL Irql, + IN ULONG Irq, + OUT PKIRQL OldIrql) +{ + I8259_OCW3 Ocw3; + I8259_OCW2 Ocw2; + I8259_ISR Isr; + + /* Request the ISR */ + Ocw3.Bits = 0; + Ocw3.Sbo = 1; /* This encodes an OCW3 vs. an OCW2 */ + Ocw3.ReadRequest = ReadIsr; + __outbyte(PIC2_CONTROL_PORT, Ocw3.Bits); + + /* Read the ISR */ + Isr.Bits = __inbyte(PIC2_CONTROL_PORT); + + /* Is IRQ15 really active (this is IR7) */ + if (Isr.Irq7 == FALSE) + { + /* It isn't, so we have to EOI IRQ2 because this was cascaded */ + Ocw2.Bits = 0; + Ocw2.EoiMode = SpecificEoi; + __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2); + + /* And now fail since this was spurious */ + return FALSE; + } + + /* Do normal interrupt dismiss */ + return _HalpDismissIrqGeneric(Irql, Irq, OldIrql); +} + + +BOOLEAN +__attribute__((regparm(3))) +HalpDismissIrq13(IN KIRQL Irql, + IN ULONG Irq, + OUT PKIRQL OldIrql) +{ + /* Clear the FPU busy latch */ + __outbyte(0xF0, 0); + + /* Do normal interrupt dismiss */ + return _HalpDismissIrqGeneric(Irql, Irq, OldIrql); +} + +BOOLEAN +__attribute__((regparm(3))) +HalpDismissIrq07(IN KIRQL Irql, + IN ULONG Irq, + OUT PKIRQL OldIrql) +{ + I8259_OCW3 Ocw3; + I8259_ISR Isr; + + /* Request the ISR */ + Ocw3.Bits = 0; + Ocw3.Sbo = 1; + Ocw3.ReadRequest = ReadIsr; + __outbyte(PIC1_CONTROL_PORT, Ocw3.Bits); + + /* Read the ISR */ + Isr.Bits = __inbyte(PIC1_CONTROL_PORT); + + /* Is IRQ 7 really active? If it isn't, this is spurious so fail */ + if (Isr.Irq7 == FALSE) return FALSE; + + /* Do normal interrupt dismiss */ + return _HalpDismissIrqGeneric(Irql, Irq, OldIrql); +} + +/* LEVEL INTERRUPT DISMISSAL FUNCTIONS ****************************************/ + +BOOLEAN +FORCEINLINE +_HalpDismissIrqLevel(IN KIRQL Irql, + IN ULONG Irq, + OUT PKIRQL OldIrql) +{ + PIC_MASK Mask; + KIRQL CurrentIrql; + I8259_OCW2 Ocw2; + PKPCR Pcr = KeGetPcr(); + + /* Update the PIC */ + Mask.Both = KiI8259MaskTable[Irql] | Pcr->IDR; + __outbyte(PIC1_DATA_PORT, Mask.Master); + __outbyte(PIC2_DATA_PORT, Mask.Slave); + + /* Update the IRR so that we clear this interrupt when the IRQL is proper */ + Pcr->IRR |= (1 << (Irq + 4)); + + /* Save current IRQL */ + CurrentIrql = Pcr->Irql; + + /* Prepare OCW2 for EOI */ + Ocw2.Bits = 0; + Ocw2.EoiMode = SpecificEoi; + + /* Check which PIC needs the EOI */ + if (Irq > 8) + { + /* Send the EOI for the IRQ */ + __outbyte(PIC2_CONTROL_PORT, Ocw2.Bits | (Irq - 8)); + + /* Send the EOI for IRQ2 on the master because this was cascaded */ + __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2); + } + else + { + /* Send the EOI for the IRQ */ + __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | Irq); + } + + /* Check if this interrupt should be allowed to happen */ + if (Irql > CurrentIrql) + { + /* Set the new IRQL and return the current one */ + Pcr->Irql = Irql; + *OldIrql = CurrentIrql; + + /* Enable interrupts and return success */ + _enable(); + return TRUE; + } + + /* Now lie and say this was spurious */ + return FALSE; +} + +BOOLEAN +__attribute__((regparm(3))) +HalpDismissIrqLevel(IN KIRQL Irql, + IN ULONG Irq, + OUT PKIRQL OldIrql) +{ + /* Run the inline code */ + return _HalpDismissIrqLevel(Irql, Irq, OldIrql); +} + +BOOLEAN +__attribute__((regparm(3))) +HalpDismissIrq15Level(IN KIRQL Irql, + IN ULONG Irq, + OUT PKIRQL OldIrql) +{ + I8259_OCW3 Ocw3; + I8259_OCW2 Ocw2; + I8259_ISR Isr; + + /* Request the ISR */ + Ocw3.Bits = 0; + Ocw3.Sbo = 1; /* This encodes an OCW3 vs. an OCW2 */ + Ocw3.ReadRequest = ReadIsr; + __outbyte(PIC2_CONTROL_PORT, Ocw3.Bits); + + /* Read the ISR */ + Isr.Bits = __inbyte(PIC2_CONTROL_PORT); + + /* Is IRQ15 really active (this is IR7) */ + if (Isr.Irq7 == FALSE) + { + /* It isn't, so we have to EOI IRQ2 because this was cascaded */ + Ocw2.Bits = 0; + Ocw2.EoiMode = SpecificEoi; + __outbyte(PIC1_CONTROL_PORT, Ocw2.Bits | 2); + + /* And now fail since this was spurious */ + return FALSE; + } + + /* Do normal interrupt dismiss */ + return _HalpDismissIrqLevel(Irql, Irq, OldIrql); +} + +BOOLEAN +__attribute__((regparm(3))) +HalpDismissIrq13Level(IN KIRQL Irql, + IN ULONG Irq, + OUT PKIRQL OldIrql) +{ + /* Clear the FPU busy latch */ + __outbyte(0xF0, 0); + + /* Do normal interrupt dismiss */ + return _HalpDismissIrqLevel(Irql, Irq, OldIrql); +} + +BOOLEAN +__attribute__((regparm(3))) +HalpDismissIrq07Level(IN KIRQL Irql, + IN ULONG Irq, + OUT PKIRQL OldIrql) +{ + I8259_OCW3 Ocw3; + I8259_ISR Isr; + + /* Request the ISR */ + Ocw3.Bits = 0; + Ocw3.Sbo = 1; + Ocw3.ReadRequest = ReadIsr; + __outbyte(PIC1_CONTROL_PORT, Ocw3.Bits); + + /* Read the ISR */ + Isr.Bits = __inbyte(PIC1_CONTROL_PORT); + + /* Is IRQ 7 really active? If it isn't, this is spurious so fail */ + if (Isr.Irq7 == FALSE) return FALSE; + + /* Do normal interrupt dismiss */ + return _HalpDismissIrqLevel(Irql, Irq, OldIrql); +} + +VOID +HalpHardwareInterruptLevel(VOID) +{ + PKPCR Pcr = KeGetPcr(); + ULONG PendingIrqlMask, PendingIrql; + + /* Check for pending software interrupts and compare with current IRQL */ + PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[Pcr->Irql]; + if (PendingIrqlMask) + { + /* Check for in-service delayed interrupt */ + if (Pcr->IrrActive & 0xFFFFFFF0) return; + + /* Check if pending IRQL affects hardware state */ + BitScanReverse(&PendingIrql, PendingIrqlMask); + + /* Clear IRR bit */ + Pcr->IRR ^= (1 << PendingIrql); + + /* Now handle pending interrupt */ + SWInterruptHandlerTable[PendingIrql](); + } +} + +/* SYSTEM INTERRUPTS **********************************************************/ + +/* + * @implemented + */ +BOOLEAN +NTAPI +HalEnableSystemInterrupt(IN UCHAR Vector, + IN KIRQL Irql, + IN KINTERRUPT_MODE InterruptMode) +{ + ULONG Irq; + PKPCR Pcr = KeGetPcr(); + PIC_MASK PicMask; + + /* Validate the IRQ */ + Irq = Vector - PRIMARY_VECTOR_BASE; + if (Irq >= CLOCK2_LEVEL) return FALSE; + + /* Check for level interrupt */ + if (InterruptMode == LevelSensitive) + { + /* Switch handler to level */ + SWInterruptHandlerTable[Irq + 4] = HalpHardwareInterruptLevel; + + /* Switch dismiss to level */ + HalpSpecialDismissTable[Irq] = HalpSpecialDismissLevelTable[Irq]; + } + + /* Disable interrupts */ + _disable(); + + /* Update software IDR */ + Pcr->IDR &= ~(1 << Irq); + + /* Set new PIC mask */ + PicMask.Both = KiI8259MaskTable[Pcr->Irql] | Pcr->IDR; + __outbyte(PIC1_DATA_PORT, PicMask.Master); + __outbyte(PIC2_DATA_PORT, PicMask.Slave); + + /* Enable interrupts and exit */ + _enable(); + return TRUE; +} + +/* + * @implemented + */ +VOID +NTAPI +HalDisableSystemInterrupt(IN UCHAR Vector, + IN KIRQL Irql) +{ + ULONG IrqMask; + PIC_MASK PicMask; + + /* Compute new combined IRQ mask */ + IrqMask = 1 << (Vector - PRIMARY_VECTOR_BASE); + + /* Disable interrupts */ + _disable(); + + /* Update software IDR */ + KeGetPcr()->IDR |= IrqMask; + + /* Read current interrupt mask */ + PicMask.Master = __inbyte(PIC1_DATA_PORT); + PicMask.Slave = __inbyte(PIC2_DATA_PORT); + + /* Add the new disabled interrupt */ + PicMask.Both |= IrqMask; + + /* Write new interrupt mask */ + __outbyte(PIC1_DATA_PORT, PicMask.Master); + __outbyte(PIC2_DATA_PORT, PicMask.Slave); + + /* Bring interrupts back */ + _enable(); +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +HalBeginSystemInterrupt(IN KIRQL Irql, + IN UCHAR Vector, + OUT PKIRQL OldIrql) +{ + ULONG Irq; + + /* Get the IRQ and call the proper routine to handle it */ + Irq = Vector - PRIMARY_VECTOR_BASE; + return HalpSpecialDismissTable[Irq](Irql, Irq, OldIrql); +} + +/* + * @implemented + */ +VOID +NTAPI +HalEndSystemInterrupt(IN KIRQL OldIrql, + IN PKTRAP_FRAME TrapFrame) +{ + ULONG PendingIrql, PendingIrqlMask, PendingIrqMask; + PKPCR Pcr = KeGetPcr(); + PIC_MASK Mask; + + /* Set old IRQL */ + Pcr->Irql = OldIrql; + + /* Check for pending software interrupts and compare with current IRQL */ + PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql]; + if (PendingIrqlMask) + { + /* Check for in-service delayed interrupt */ + if (Pcr->IrrActive & 0xFFFFFFF0) return; + + /* Loop checking for pending interrupts */ + while (TRUE) + { + /* Check if pending IRQL affects hardware state */ + BitScanReverse(&PendingIrql, PendingIrqlMask); + if (PendingIrql > DISPATCH_LEVEL) + { + /* Set new PIC mask */ + Mask.Both = Pcr->IDR; + __outbyte(PIC1_DATA_PORT, Mask.Master); + __outbyte(PIC2_DATA_PORT, Mask.Slave); + + /* Now check if this specific interrupt is already in-service */ + PendingIrqMask = (1 << PendingIrql); + if (Pcr->IrrActive & PendingIrqMask) return; + + /* Set active bit otherwise, and clear it from IRR */ + Pcr->IrrActive |= PendingIrqMask; + Pcr->IRR ^= PendingIrqMask; + + /* Handle delayed hardware interrupt */ + SWInterruptHandlerTable[PendingIrql](); + + /* Handling complete */ + Pcr->IrrActive ^= PendingIrqMask; + + /* Check if there's still interrupts pending */ + PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[Pcr->Irql]; + if (!PendingIrqlMask) break; + } + else + { + /* Now handle pending software interrupt */ + SWInterruptHandlerTable2[PendingIrql](TrapFrame); + } + } + } +} + +/* SOFTWARE INTERRUPT TRAPS ***************************************************/ + +VOID +FORCEINLINE +DECLSPEC_NORETURN +_HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame) +{ + KIRQL CurrentIrql; + PKPCR Pcr = KeGetPcr(); + + /* Save the current IRQL and update it */ + CurrentIrql = Pcr->Irql; + Pcr->Irql = APC_LEVEL; + + /* Remove DPC from IRR */ + Pcr->IRR &= ~(1 << APC_LEVEL); + + /* Enable interrupts and call the kernel's APC interrupt handler */ + _enable(); + KiDeliverApc(((KiUserTrap(TrapFrame)) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) ? + UserMode : KernelMode, + NULL, + TrapFrame); + + /* Disable interrupts and end the interrupt */ + _disable(); + HalpEndSoftwareInterrupt(CurrentIrql, TrapFrame); + + /* Exit the interrupt */ + KiEoiHelper(TrapFrame); +} + +VOID +FASTCALL +DECLSPEC_NORETURN +HalpApcInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame) +{ + /* Do the work */ + _HalpApcInterruptHandler(TrapFrame); +} + +VOID +FASTCALL +DECLSPEC_NORETURN +HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame) +{ + /* Set up a fake INT Stack */ + TrapFrame->EFlags = __readeflags(); + TrapFrame->SegCs = KGDT_R0_CODE; + TrapFrame->Eip = TrapFrame->Eax; + + /* Build the trap frame */ + KiEnterInterruptTrap(TrapFrame); + + /* Do the work */ + _HalpApcInterruptHandler(TrapFrame); +} + +KIRQL +FORCEINLINE +_HalpDispatchInterruptHandler(VOID) +{ + KIRQL CurrentIrql; + PKPCR Pcr = KeGetPcr(); + + /* Save the current IRQL and update it */ + CurrentIrql = Pcr->Irql; + Pcr->Irql = DISPATCH_LEVEL; + + /* Remove DPC from IRR */ + Pcr->IRR &= ~(1 << DISPATCH_LEVEL); + + /* Enable interrupts and call the kernel's DPC interrupt handler */ + _enable(); + KiDispatchInterrupt(); + _disable(); + + /* Return IRQL */ + return CurrentIrql; +} + +VOID +FASTCALL +DECLSPEC_NORETURN +HalpDispatchInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame) +{ + KIRQL CurrentIrql; + + /* Do the work */ + CurrentIrql = _HalpDispatchInterruptHandler(); + + /* End the interrupt */ + HalpEndSoftwareInterrupt(CurrentIrql, TrapFrame); + + /* Exit the interrupt */ + KiEoiHelper(TrapFrame); +} + +VOID +HalpDispatchInterrupt2(VOID) +{ + ULONG PendingIrqlMask, PendingIrql; + KIRQL OldIrql; + PIC_MASK Mask; + PKPCR Pcr = KeGetPcr(); + + /* Do the work */ + OldIrql = _HalpDispatchInterruptHandler(); + + /* Restore IRQL */ + Pcr->Irql = OldIrql; + + /* Check for pending software interrupts and compare with current IRQL */ + PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql]; + if (PendingIrqlMask) + { + /* Check if pending IRQL affects hardware state */ + BitScanReverse(&PendingIrql, PendingIrqlMask); + if (PendingIrql > DISPATCH_LEVEL) + { + /* Set new PIC mask */ + Mask.Both = Pcr->IDR; + __outbyte(PIC1_DATA_PORT, Mask.Master); + __outbyte(PIC2_DATA_PORT, Mask.Slave); + + /* Clear IRR bit */ + Pcr->IRR ^= (1 << PendingIrql); + } + + /* Now handle pending interrupt */ + SWInterruptHandlerTable[PendingIrql](); + } +} + +#else + +KIRQL +NTAPI +KeGetCurrentIrql(VOID) +{ + return PASSIVE_LEVEL; +} + +VOID +FASTCALL +KfLowerIrql( + IN KIRQL OldIrql) +{ +} + +KIRQL +FASTCALL +KfRaiseIrql( + IN KIRQL NewIrql) +{ + return NewIrql; +} + +#endif diff --git a/hal/halx86/up/processor.c b/hal/halx86/up/processor.c new file mode 100644 index 00000000000..662514b19cf --- /dev/null +++ b/hal/halx86/up/processor.c @@ -0,0 +1,98 @@ +/* + * PROJECT: ReactOS HAL + * LICENSE: GPL - See COPYING in the top level directory + * FILE: hal/halx86/up/processor.c + * PURPOSE: HAL Processor Routines + * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +LONG HalpActiveProcessors; +KAFFINITY HalpDefaultInterruptAffinity; + +/* PRIVATE FUNCTIONS *********************************************************/ + +VOID +NTAPI +HaliHaltSystem(VOID) +{ + /* Disable interrupts and halt the CPU */ + _disable(); + __halt(); +} + +/* FUNCTIONS *****************************************************************/ + +/* + * @implemented + */ +VOID +NTAPI +HalInitializeProcessor(IN ULONG ProcessorNumber, + IN PLOADER_PARAMETER_BLOCK LoaderBlock) +{ + /* Set default IDR and stall count */ + KeGetPcr()->IDR = 0xFFFFFFFB; + KeGetPcr()->StallScaleFactor = INITIAL_STALL_COUNT; + + /* Update the interrupt affinity and processor mask */ + InterlockedBitTestAndSet(&HalpActiveProcessors, ProcessorNumber); + InterlockedBitTestAndSet((PLONG)&HalpDefaultInterruptAffinity, + ProcessorNumber); + + /* Register routines for KDCOM */ + HalpRegisterKdSupportFunctions(); +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +HalAllProcessorsStarted(VOID) +{ + /* Do nothing */ + return TRUE; +} + +/* + * @implemented + */ +BOOLEAN +NTAPI +HalStartNextProcessor(IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN PKPROCESSOR_STATE ProcessorState) +{ + /* Ready to start */ + return FALSE; +} + +/* + * @implemented + */ +VOID +NTAPI +HalProcessorIdle(VOID) +{ + /* Enable interrupts and halt the processor */ + _enable(); + __halt(); +} + +/* + * @implemented + */ +VOID +NTAPI +HalRequestIpi(KAFFINITY TargetProcessors) +{ + /* Not implemented on UP */ + __debugbreak(); +} + +/* EOF */ diff --git a/include/dxsdk/bdatif.idl b/include/dxsdk/bdatif.idl new file mode 100644 index 00000000000..6c8887eb7cf --- /dev/null +++ b/include/dxsdk/bdatif.idl @@ -0,0 +1,270 @@ +#ifndef DO_NO_IMPORTS +import "unknwn.idl"; +import "strmif.idl"; +import "tuner.idl"; +import "bdaiface.idl"; +#endif + +interface IMPEG2_TIF_CONTROL; +interface IATSCChannelInfo; +interface IMPEG2PIDMap; + +[ + object, + uuid(DFEF4A68-EE61-415f-9CCB-CD95F2F98A3A), + pointer_default(unique) +] +interface IBDA_TIF_REGISTRATION : IUnknown +{ + HRESULT + RegisterTIFEx( + [in] IPin * pTIFInputPin, + [in, out] ULONG * ppvRegistrationContext, + [in, out] IUnknown ** ppMpeg2DataControl); + + HRESULT + UnregisterTIF( + [in] ULONG pvRegistrationContext); +} + +[ + object, + uuid(F9BAC2F9-4149-4916-B2EF-FAA202326862), + pointer_default(unique) +] +interface IMPEG2_TIF_CONTROL : IUnknown +{ + HRESULT + RegisterTIF( + [in] IUnknown * pUnkTIF, + [in, out] ULONG * ppvRegistrationContext); + + HRESULT + UnregisterTIF( + [in] ULONG pvRegistrationContext); + + HRESULT + AddPIDs( + [in] ULONG ulcPIDs, + [in] ULONG * pulPIDs); + + HRESULT + DeletePIDs( + [in] ULONG ulcPIDs, + [in] ULONG * pulPIDs); + + HRESULT + GetPIDCount( + [out] ULONG * pulcPIDs); + + HRESULT + GetPIDs( + [out] ULONG * pulcPIDs, + [out] ULONG * pulPIDs); +} + +[ + object, + uuid(A3B152DF-7A90-4218-AC54-9830BEE8C0B6), + pointer_default(unique) +] +interface ITuneRequestInfo : IUnknown +{ + HRESULT + GetLocatorData( + [in] ITuneRequest *Request); + + HRESULT + GetComponentData( + [in] ITuneRequest *CurrentRequest); + + HRESULT + CreateComponentList( + [in] ITuneRequest *CurrentRequest); + + HRESULT + GetNextProgram ( + [in] ITuneRequest *CurrentRequest, + [out, retval] ITuneRequest **TuneRequest); + + HRESULT + GetPreviousProgram( + [in] ITuneRequest *CurrentRequest, + [out, retval] ITuneRequest **TuneRequest); + + HRESULT + GetNextLocator( + [in] ITuneRequest *CurrentRequest, + [out, retval] ITuneRequest **TuneRequest); + + HRESULT + GetPreviousLocator( + [in] ITuneRequest *CurrentRequest, + [out, retval] ITuneRequest **TuneRequest); +} + +[ + object, + uuid(EFDA0C80-F395-42c3-9B3C-56B37DEC7BB7), + pointer_default(unique) +] +interface IGuideDataEvent : IUnknown +{ + HRESULT + GuideDataAcquired(); + + HRESULT ProgramChanged( + [in] VARIANT varProgramDescriptionID); + + HRESULT ServiceChanged( + [in] VARIANT varServiceDescriptionID); + + HRESULT ScheduleEntryChanged( + [in] VARIANT varScheduleEntryDescriptionID); + + HRESULT ProgramDeleted( + [in] VARIANT varProgramDescriptionID); + + HRESULT ServiceDeleted( + [in] VARIANT varServiceDescriptionID); + + HRESULT ScheduleDeleted( + [in] VARIANT varScheduleEntryDescriptionID); +} + +[ + object, + uuid(88EC5E58-BB73-41d6-99CE-66C524B8B591), + pointer_default(unique) +] +interface IGuideDataProperty : IUnknown +{ + HRESULT + get_Name( + [out] BSTR *pbstrName); + + HRESULT + get_Language( + [out] long *idLang); + + HRESULT + get_Value( + [out] VARIANT *pvar); +} + +[ + object, + uuid(AE44423B-4571-475c-AD2C-F40A771D80EF), + pointer_default(unique) +] +interface IEnumGuideDataProperties : IUnknown +{ + HRESULT + Next( + [in] unsigned long celt, + [out] IGuideDataProperty **ppprop, + [out] unsigned long *pcelt); + + HRESULT + Skip( + [in] unsigned long celt); + + HRESULT + Reset(); + + HRESULT + Clone( + [out] IEnumGuideDataProperties **ppenum); +} + +[ + object, + uuid(1993299C-CED6-4788-87A3-420067DCE0C7), + pointer_default(unique) +] +interface IEnumTuneRequests : IUnknown +{ + HRESULT + Next( + [in] unsigned long celt, + [out] ITuneRequest **ppprop, + [out] unsigned long *pcelt); + + HRESULT + Skip( + [in] unsigned long celt); + + HRESULT + Reset(); + + HRESULT + Clone( + [out] IEnumTuneRequests **ppenum); +} + +[ + object, + uuid(61571138-5B01-43cd-AEAF-60B784A0BF93), + pointer_default(unique) +] +interface IGuideData : IUnknown +{ + HRESULT + GetServices( + [out, retval] IEnumTuneRequests ** ppEnumTuneRequests); + + HRESULT + GetServiceProperties( + [in] ITuneRequest * pTuneRequest, + [out, retval] IEnumGuideDataProperties ** ppEnumProperties); + + HRESULT + GetGuideProgramIDs( + [out, retval] IEnumVARIANT ** pEnumPrograms); + + HRESULT + GetProgramProperties( + [in] VARIANT varProgramDescriptionID, + [out, retval] IEnumGuideDataProperties ** ppEnumProperties); + + HRESULT + GetScheduleEntryIDs( + [out, retval] IEnumVARIANT ** pEnumScheduleEntries); + + HRESULT + GetScheduleEntryProperties( + [in] VARIANT varScheduleEntryDescriptionID, + [out, retval] IEnumGuideDataProperties ** ppEnumProperties); +} + +[ + object, + uuid(4764ff7c-fa95-4525-af4d-d32236db9e38), + pointer_default(unique) +] +interface IGuideDataLoader : IUnknown +{ + HRESULT Init([in] IGuideData *pGuideStore); + HRESULT Terminate(); +}; + +[ + uuid(8224A083-7F8C-432D-B83E-3C5E9BDE3528), + version(1.0), +] +library PSISLOADLib +{ + importlib("stdole32.tlb"); + importlib("stdole2.tlb"); + + [ + uuid(14EB8748-1753-4393-95AE-4F7E7A87AAD6), + helpstring("TIFLoad Class") + ] + coclass TIFLoad + { + interface IGuideDataLoader; + interface IGuideDataEvent; + }; +}; + diff --git a/include/ndk/peb_teb.h b/include/ndk/peb_teb.h new file mode 100644 index 00000000000..38791b31a21 --- /dev/null +++ b/include/ndk/peb_teb.h @@ -0,0 +1,389 @@ + +#define PASTE2(x,y) x##y +#define PASTE(x,y) PASTE2(x,y) + +#ifdef EXPLICIT_32BIT + #define STRUCT(x) PASTE(x,32) + #define PTR(x) ULONG +#elif defined(EXPLICIT_64BIT) + #define STRUCT(x) PASTE(x,64) + #define PTR(x) ULONG64 +#else + #define STRUCT(x) x + #define PTR(x) x +#endif + +#if defined(_WIN64) && !defined(EXPLICIT_32BIT) + #define GDI_HANDLE_BUFFER_SIZE 60 +#else + #define GDI_HANDLE_BUFFER_SIZE 34 +#endif + +typedef struct STRUCT(_PEB) +{ + BOOLEAN InheritedAddressSpace; + BOOLEAN ReadImageFileExecOptions; + BOOLEAN BeingDebugged; +#if (NTDDI_VERSION >= NTDDI_WS03) + union + { + BOOLEAN BitField; + struct + { + BOOLEAN ImageUsesLargePages:1; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + BOOLEAN IsProtectedProcess:1; + BOOLEAN IsLegacyProcess:1; + BOOLEAN IsImageDynamicallyRelocated:1; + BOOLEAN SkipPatchingUser32Forwarders:1; + BOOLEAN SpareBits:3; +#else + BOOLEAN SpareBits:7; +#endif + }; + }; +#else + BOOLEAN SpareBool; +#endif + PTR(HANDLE) Mutant; + PTR(PVOID) ImageBaseAddress; + PTR(PPEB_LDR_DATA) Ldr; + PTR(struct _RTL_USER_PROCESS_PARAMETERS*) ProcessParameters; + PTR(PVOID) SubSystemData; + PTR(PVOID) ProcessHeap; + PTR(struct _RTL_CRITICAL_SECTION*) FastPebLock; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PTR(PVOID) AltThunkSListPtr; + PTR(PVOID) IFEOKey; + union + { + ULONG CrossProcessFlags; + struct + { + ULONG ProcessInJob:1; + ULONG ProcessInitializing:1; + ULONG ProcessUsingVEH:1; + ULONG ProcessUsingVCH:1; + ULONG ReservedBits0:28; + }; + }; + union + { + PTR(PVOID) KernelCallbackTable; + PTR(PVOID) UserSharedInfoPtr; + }; +#elif (NTDDI_VERSION >= NTDDI_WS03) + PTR(PVOID) AltThunkSListPtr; + PTR(PVOID) SparePtr2; + ULONG EnvironmentUpdateCount; + PTR(PVOID) KernelCallbackTable; +#else + PTR(PPEBLOCKROUTINE) FastPebLockRoutine; + PTR(PPEBLOCKROUTINE) FastPebUnlockRoutine; + ULONG EnvironmentUpdateCount; + PTR(PVOID) KernelCallbackTable; +#endif + ULONG SystemReserved[1]; + ULONG SpareUlong; // AtlThunkSListPtr32 + PTR(PPEB_FREE_BLOCK) FreeList; + ULONG TlsExpansionCounter; + PTR(PVOID) TlsBitmap; + ULONG TlsBitmapBits[2]; + PTR(PVOID) ReadOnlySharedMemoryBase; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PTR(PVOID) HotpatchInformation; +#else + PTR(PVOID) ReadOnlySharedMemoryHeap; +#endif + PTR(PVOID*) ReadOnlyStaticServerData; + PTR(PVOID) AnsiCodePageData; + PTR(PVOID) OemCodePageData; + PTR(PVOID) UnicodeCaseTableData; + ULONG NumberOfProcessors; + ULONG NtGlobalFlag; + LARGE_INTEGER CriticalSectionTimeout; + PTR(ULONG_PTR) HeapSegmentReserve; + PTR(ULONG_PTR) HeapSegmentCommit; + PTR(ULONG_PTR) HeapDeCommitTotalFreeThreshold; + PTR(ULONG_PTR) HeapDeCommitFreeBlockThreshold; + ULONG NumberOfHeaps; + ULONG MaximumNumberOfHeaps; + PTR(PVOID*) ProcessHeaps; + PTR(PVOID) GdiSharedHandleTable; + PTR(PVOID) ProcessStarterHelper; + ULONG GdiDCAttributeList; + PTR(struct _RTL_CRITICAL_SECTION*) LoaderLock; + ULONG OSMajorVersion; + ULONG OSMinorVersion; + USHORT OSBuildNumber; + USHORT OSCSDVersion; + ULONG OSPlatformId; + ULONG ImageSubsystem; + ULONG ImageSubsystemMajorVersion; + ULONG ImageSubsystemMinorVersion; + PTR(ULONG_PTR) ImageProcessAffinityMask; + ULONG GdiHandleBuffer[GDI_HANDLE_BUFFER_SIZE]; + PTR(PPOST_PROCESS_INIT_ROUTINE) PostProcessInitRoutine; + PTR(PVOID) TlsExpansionBitmap; + ULONG TlsExpansionBitmapBits[32]; + ULONG SessionId; +#if (NTDDI_VERSION >= NTDDI_WINXP) + ULARGE_INTEGER AppCompatFlags; + ULARGE_INTEGER AppCompatFlagsUser; + PTR(PVOID) pShimData; + PTR(PVOID) AppCompatInfo; + STRUCT(UNICODE_STRING) CSDVersion; + PTR(struct _ACTIVATION_CONTEXT_DATA*) ActivationContextData; + PTR(struct _ASSEMBLY_STORAGE_MAP*) ProcessAssemblyStorageMap; + PTR(struct _ACTIVATION_CONTEXT_DATA*) SystemDefaultActivationContextData; + PTR(struct _ASSEMBLY_STORAGE_MAP*) SystemAssemblyStorageMap; + PTR(ULONG_PTR) MinimumStackCommit; +#endif +#if (NTDDI_VERSION >= NTDDI_WS03) + PTR(PVOID*) FlsCallback; + STRUCT(LIST_ENTRY) FlsListHead; + PTR(PVOID) FlsBitmap; + ULONG FlsBitmapBits[4]; + ULONG FlsHighIndex; +#endif +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PTR(PVOID) WerRegistrationData; + PTR(PVOID) WerShipAssertPtr; +#endif +} STRUCT(PEB), *STRUCT(PPEB); + + +#if defined(_WIN64) && !defined(EXPLICIT_32BIT) +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), Mutant) == 0x08); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), Ldr) == 0x18); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), FastPebLock) == 0x038); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), TlsExpansionCounter) == 0x070); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), NtGlobalFlag) == 0x0BC); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), GdiSharedHandleTable) == 0x0F8); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), LoaderLock) == 0x110); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), ImageSubsystem) == 0x128); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), ImageProcessAffinityMask) == 0x138); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), PostProcessInitRoutine) == 0x230); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), SessionId) == 0x2C0); +#if (NTDDI_VERSION >= NTDDI_WS03) +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), FlsHighIndex) == 0x350); +#endif +#else +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), Mutant) == 0x04); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), Ldr) == 0x0C); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), FastPebLock) == 0x01C); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), TlsExpansionCounter) == 0x03C); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), NtGlobalFlag) == 0x068); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), GdiSharedHandleTable) == 0x094); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), LoaderLock) == 0x0A0); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), ImageSubsystem) == 0x0B4); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), ImageProcessAffinityMask) == 0x0C0); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), PostProcessInitRoutine) == 0x14C); +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), SessionId) == 0x1D4); +#if (NTDDI_VERSION >= NTDDI_WS03) +C_ASSERT(FIELD_OFFSET(STRUCT(PEB), FlsHighIndex) == 0x22C); +#endif +#endif + +// +// GDI Batch Descriptor +// +typedef struct STRUCT(_GDI_TEB_BATCH) +{ + ULONG Offset; + PTR(HANDLE) HDC; + ULONG Buffer[0x136]; +} STRUCT(GDI_TEB_BATCH), *STRUCT(PGDI_TEB_BATCH); + +// +// Thread Environment Block (TEB) +// +typedef struct STRUCT(_TEB) +{ + STRUCT(NT_TIB) NtTib; + PTR(PVOID) EnvironmentPointer; + STRUCT(CLIENT_ID) ClientId; + PTR(PVOID) ActiveRpcHandle; + PTR(PVOID) ThreadLocalStoragePointer; + PTR(STRUCT(PPEB)) ProcessEnvironmentBlock; + ULONG LastErrorValue; + ULONG CountOfOwnedCriticalSections; + PTR(PVOID) CsrClientThread; + PTR(PVOID) Win32ThreadInfo; + ULONG User32Reserved[26]; + ULONG UserReserved[5]; + PTR(PVOID) WOW32Reserved; + LCID CurrentLocale; + ULONG FpSoftwareStatusRegister; + PTR(PVOID) SystemReserved1[54]; + LONG ExceptionCode; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PTR(struct _ACTIVATION_CONTEXT_STACK*) ActivationContextStackPointer; + UCHAR SpareBytes1[0x30 - 3 * sizeof(PTR(PVOID))]; + ULONG TxFsContext; +#elif (NTDDI_VERSION >= NTDDI_WS03) + PTR(struct _ACTIVATION_CONTEXT_STACK*) ActivationContextStackPointer; + UCHAR SpareBytes1[0x34 - 3 * sizeof(PTR(PVOID))]; +#else + ACTIVATION_CONTEXT_STACK ActivationContextStack; + UCHAR SpareBytes1[24]; +#endif + STRUCT(GDI_TEB_BATCH) GdiTebBatch; + STRUCT(CLIENT_ID) RealClientId; + PTR(PVOID) GdiCachedProcessHandle; + ULONG GdiClientPID; + ULONG GdiClientTID; + PTR(PVOID) GdiThreadLocalInfo; + PTR(SIZE_T) Win32ClientInfo[62]; + PTR(PVOID) glDispatchTable[233]; + PTR(SIZE_T) glReserved1[29]; + PTR(PVOID) glReserved2; + PTR(PVOID) glSectionInfo; + PTR(PVOID) glSection; + PTR(PVOID) glTable; + PTR(PVOID) glCurrentRC; + PTR(PVOID) glContext; + NTSTATUS LastStatusValue; + STRUCT(UNICODE_STRING) StaticUnicodeString; + WCHAR StaticUnicodeBuffer[261]; + PTR(PVOID) DeallocationStack; + PTR(PVOID) TlsSlots[64]; + STRUCT(LIST_ENTRY) TlsLinks; + PTR(PVOID) Vdm; + PTR(PVOID) ReservedForNtRpc; + PTR(PVOID) DbgSsReserved[2]; +#if (NTDDI_VERSION >= NTDDI_WS03) + ULONG HardErrorMode; +#else + ULONG HardErrorsAreDisabled; +#endif +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PTR(PVOID) Instrumentation[13 - sizeof(GUID)/sizeof(PTR(PVOID))]; + GUID ActivityId; + PTR(PVOID) SubProcessTag; + PTR(PVOID) EtwLocalData; + PTR(PVOID) EtwTraceData; +#elif (NTDDI_VERSION >= NTDDI_WS03) + PTR(PVOID) Instrumentation[14]; + PTR(PVOID) SubProcessTag; + PTR(PVOID) EtwLocalData; +#else + PTR(PVOID) Instrumentation[16]; +#endif + PTR(PVOID) WinSockData; + ULONG GdiBatchCount; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + BOOLEAN SpareBool0; + BOOLEAN SpareBool1; + BOOLEAN SpareBool2; +#else + BOOLEAN InDbgPrint; + BOOLEAN FreeStackOnTermination; + BOOLEAN HasFiberData; +#endif + UCHAR IdealProcessor; +#if (NTDDI_VERSION >= NTDDI_WS03) + ULONG GuaranteedStackBytes; +#else + ULONG Spare3; +#endif + PTR(PVOID) ReservedForPerf; + PTR(PVOID) ReservedForOle; + ULONG WaitingOnLoaderLock; +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PTR(PVOID) SavedPriorityState; + PTR(ULONG_PTR) SoftPatchPtr1; + PTR(ULONG_PTR) ThreadPoolData; +#elif (NTDDI_VERSION >= NTDDI_WS03) + PTR(ULONG_PTR) SparePointer1; + PTR(ULONG_PTR) SoftPatchPtr1; + PTR(ULONG_PTR) SoftPatchPtr2; +#else + Wx86ThreadState Wx86Thread; +#endif + PTR(PVOID*) TlsExpansionSlots; +#if defined(_WIN64) && !defined(EXPLICIT_32BIT) + PTR(PVOID) DeallocationBStore; + PTR(PVOID) BStoreLimit; +#endif + ULONG ImpersonationLocale; + ULONG IsImpersonating; + PTR(PVOID) NlsCache; + PTR(PVOID) pShimData; + ULONG HeapVirtualAffinity; + PTR(HANDLE) CurrentTransactionHandle; + PTR(PTEB_ACTIVE_FRAME) ActiveFrame; +#if (NTDDI_VERSION >= NTDDI_WS03) + PVOID FlsData; +#endif +#if (NTDDI_VERSION >= NTDDI_LONGHORN) + PVOID PreferredLangauges; + PVOID UserPrefLanguages; + PVOID MergedPrefLanguages; + ULONG MuiImpersonation; + union + { + struct + { + USHORT SpareCrossTebFlags:16; + }; + USHORT CrossTebFlags; + }; + union + { + struct + { + USHORT DbgSafeThunkCall:1; + USHORT DbgInDebugPrint:1; + USHORT DbgHasFiberData:1; + USHORT DbgSkipThreadAttach:1; + USHORT DbgWerInShipAssertCode:1; + USHORT DbgIssuedInitialBp:1; + USHORT DbgClonedThread:1; + USHORT SpareSameTebBits:9; + }; + USHORT SameTebFlags; + }; + PTR(PVOID) TxnScopeEntercallback; + PTR(PVOID) TxnScopeExitCAllback; + PTR(PVOID) TxnScopeContext; + ULONG LockCount; + ULONG ProcessRundown; + ULONG64 LastSwitchTime; + ULONG64 TotalSwitchOutTime; + LARGE_INTEGER WaitReasonBitMap; +#else + BOOLEAN SafeThunkCall; + BOOLEAN BooleanSpare[3]; +#endif +} STRUCT(TEB), *STRUCT(PTEB); + +#if defined(_WIN64) && !defined(EXPLICIT_32BIT) +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), EnvironmentPointer) == 0x038); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), ExceptionCode) == 0x2C0); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), GdiTebBatch) == 0x2F0); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), LastStatusValue) == 0x1250); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), Vdm) == 0x1690); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), HardErrorMode) == 0x16B0); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), GdiBatchCount) == 0x1740); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), IdealProcessor) == 0x1747); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), WaitingOnLoaderLock) == 0x1760); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), TlsExpansionSlots) == 0x1780); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), WaitingOnLoaderLock) == 0x1760); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), ActiveFrame) == 0x17C0); +#else +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), EnvironmentPointer) == 0x01C); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), ExceptionCode) == 0x1A4); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), GdiTebBatch) == 0x1D4); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), LastStatusValue) == 0xBF4); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), Vdm) == 0xF18); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), GdiBatchCount) == 0xF70); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), TlsExpansionSlots) == 0xF94); +C_ASSERT(FIELD_OFFSET(STRUCT(TEB), ActiveFrame) == 0xFB0); +#endif + +#undef PTR +#undef STRUCT +#undef PASTE +#undef PASTE2 +#undef GDI_HANDLE_BUFFER_SIZE diff --git a/media/inf/machine.inf b/media/inf/machine.inf index 7b7e0a9d302..ecc90375e8d 100644 Binary files a/media/inf/machine.inf and b/media/inf/machine.inf differ diff --git a/ntoskrnl/io/pnpmgr/pnpmgr.c b/ntoskrnl/io/pnpmgr/pnpmgr.c index 9cd6347e957..cd0859b261b 100644 --- a/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -2180,9 +2180,19 @@ IopEnumerateDetectedDevices( const UNICODE_STRING IdentifierMouse = RTL_CONSTANT_STRING(L"PointerController"); UNICODE_STRING HardwareIdMouse = RTL_CONSTANT_STRING(L"*PNP0F13\0"); static ULONG DeviceIndexMouse = 0; + const UNICODE_STRING IdentifierParallel = RTL_CONSTANT_STRING(L"PARALLEL"); + UNICODE_STRING HardwareIdParallel = RTL_CONSTANT_STRING(L"*PNP0400\0"); + static ULONG DeviceIndexParallel = 0; + const UNICODE_STRING IdentifierFloppy = RTL_CONSTANT_STRING(L"FLOPPY"); + UNICODE_STRING HardwareIdFloppy = RTL_CONSTANT_STRING(L"*PNP0700\0"); + static ULONG DeviceIndexFloppy = 0; + const UNICODE_STRING IdentifierIsa = RTL_CONSTANT_STRING(L"ISA"); + UNICODE_STRING HardwareIdIsa = RTL_CONSTANT_STRING(L"*PNP0A00\0"); + static ULONG DeviceIndexIsa = 0; UNICODE_STRING HardwareIdKey; PUNICODE_STRING pHardwareId; ULONG DeviceIndex = 0; + BOOLEAN IsDeviceDesc; if (RelativePath) { @@ -2409,16 +2419,19 @@ IopEnumerateDetectedDevices( { pHardwareId = &HardwareIdSerial; DeviceIndex = DeviceIndexSerial++; + IsDeviceDesc = TRUE; } else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierKeyboard, FALSE) == 0) { pHardwareId = &HardwareIdKeyboard; DeviceIndex = DeviceIndexKeyboard++; + IsDeviceDesc = FALSE; } else if (RelativePath && RtlCompareUnicodeString(RelativePath, &IdentifierMouse, FALSE) == 0) { pHardwareId = &HardwareIdMouse; DeviceIndex = DeviceIndexMouse++; + IsDeviceDesc = FALSE; } else if (NT_SUCCESS(Status)) { @@ -2427,19 +2440,51 @@ IopEnumerateDetectedDevices( { pHardwareId = &HardwareIdPci; DeviceIndex = DeviceIndexPci++; + IsDeviceDesc = FALSE; + } + else if (RtlCompareUnicodeString(&ValueName, &IdentifierIsa, FALSE) == 0) + { + pHardwareId = &HardwareIdIsa; + DeviceIndex = DeviceIndexIsa++; + IsDeviceDesc = FALSE; } #ifdef ENABLE_ACPI else if (RtlCompareUnicodeString(&ValueName, &IdentifierAcpi, FALSE) == 0) { pHardwareId = &HardwareIdAcpi; DeviceIndex = DeviceIndexAcpi++; + IsDeviceDesc = FALSE; } #endif - else + else /* Now let's detect devices with a device number at the end */ { - /* Unknown device */ - DPRINT("Unknown device '%wZ'\n", &ValueName); - goto nextdevice; + /* First, we remove the number */ + ValueName.Length -= sizeof(WCHAR); + + /* Let's see if it is a floppy device */ + if (RtlCompareUnicodeString(&ValueName, &IdentifierFloppy, FALSE) == 0) + { + pHardwareId = &HardwareIdFloppy; + DeviceIndex = DeviceIndexFloppy++; + IsDeviceDesc = FALSE; + } + /* Nope, is it a parallel port? */ + else if (RtlCompareUnicodeString(&ValueName, &IdentifierParallel, FALSE) == 0) + { + pHardwareId = &HardwareIdParallel; + DeviceIndex = DeviceIndexParallel++; + IsDeviceDesc = FALSE; + } + /* Nope, out of ideas so let's skip this one */ + else + { + ValueName.Length += sizeof(WCHAR); + DPRINT("Unknown device '%wZ'\n", &ValueName); + goto nextdevice; + } + + /* Add the number back */ + ValueName.Length += sizeof(WCHAR); } } else @@ -2486,12 +2531,15 @@ IopEnumerateDetectedDevices( goto nextdevice; } DPRINT("Found %wZ #%lu (%wZ)\n", &ValueName, DeviceIndex, &HardwareIdKey); - Status = ZwSetValueKey(hLevel2Key, &DeviceDescU, 0, REG_SZ, ValueName.Buffer, ValueName.MaximumLength); - if (!NT_SUCCESS(Status)) + if (IsDeviceDesc) { - DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); - ZwDeleteKey(hLevel2Key); - goto nextdevice; + Status = ZwSetValueKey(hLevel2Key, &DeviceDescU, 0, REG_SZ, ValueName.Buffer, ValueName.MaximumLength); + if (!NT_SUCCESS(Status)) + { + DPRINT("ZwSetValueKey() failed with status 0x%08lx\n", Status); + ZwDeleteKey(hLevel2Key); + goto nextdevice; + } } Status = ZwSetValueKey(hLevel2Key, &HardwareIDU, 0, REG_MULTI_SZ, pHardwareId->Buffer, pHardwareId->MaximumLength); if (!NT_SUCCESS(Status))