static VOID NTAPI i8042KbdDpcRoutine( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2) { PI8042_KEYBOARD_EXTENSION DeviceExtension; PPORT_DEVICE_EXTENSION PortDeviceExtension; ULONG KeysTransferred = 0; ULONG KeysInBufferCopy; KIRQL Irql; UNREFERENCED_PARAMETER(Dpc); UNREFERENCED_PARAMETER(SystemArgument1); UNREFERENCED_PARAMETER(SystemArgument2); __analysis_assume(DeferredContext != NULL); DeviceExtension = DeferredContext; PortDeviceExtension = DeviceExtension->Common.PortDeviceExtension; if (HandlePowerKeys(DeviceExtension)) { DeviceExtension->KeyComplete = FALSE; return; } i8042PacketDpc(PortDeviceExtension); if (!DeviceExtension->KeyComplete) return; /* We got the interrupt as it was being enabled, too bad */ if (!PortDeviceExtension->HighestDIRQLInterrupt) return; Irql = KeAcquireInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt); DeviceExtension->KeyComplete = FALSE; KeysInBufferCopy = DeviceExtension->KeysInBuffer; KeReleaseInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt, Irql); TRACE_(I8042PRT, "Send a key\n"); if (!DeviceExtension->KeyboardData.ClassService) return; INFO_(I8042PRT, "Sending %lu key(s)\n", KeysInBufferCopy); (*(PSERVICE_CALLBACK_ROUTINE)DeviceExtension->KeyboardData.ClassService)( DeviceExtension->KeyboardData.ClassDeviceObject, DeviceExtension->KeyboardBuffer, DeviceExtension->KeyboardBuffer + KeysInBufferCopy, &KeysTransferred); KeAcquireInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt); DeviceExtension->KeysInBuffer -= KeysTransferred; KeReleaseInterruptSpinLock(PortDeviceExtension->HighestDIRQLInterrupt, Irql); }
static VOID PortAcquireSpinLock( PFDO_DEVICE_EXTENSION DeviceExtension, STOR_SPINLOCK SpinLock, PVOID LockContext, PSTOR_LOCK_HANDLE LockHandle) { DPRINT1("PortAcquireSpinLock(%p %lu %p %p)\n", DeviceExtension, SpinLock, LockContext, LockHandle); LockHandle->Lock = SpinLock; switch (SpinLock) { case DpcLock: /* 1, */ DPRINT1("DpcLock\n"); break; case StartIoLock: /* 2 */ DPRINT1("StartIoLock\n"); break; case InterruptLock: /* 3 */ DPRINT1("InterruptLock\n"); if (DeviceExtension->Interrupt == NULL) LockHandle->Context.OldIrql = 0; else LockHandle->Context.OldIrql = KeAcquireInterruptSpinLock(DeviceExtension->Interrupt); break; } }
/* * This function starts a packet. It must be called with the * correct DIRQL. */ NTSTATUS i8042StartPacket( IN PPORT_DEVICE_EXTENSION DeviceExtension, IN PFDO_DEVICE_EXTENSION FdoDeviceExtension, IN PUCHAR Bytes, IN ULONG ByteCount, IN PIRP Irp) { KIRQL Irql; NTSTATUS Status; Irql = KeAcquireInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt); if (DeviceExtension->Packet.State != Idle) { Status = STATUS_DEVICE_BUSY; goto done; } switch (FdoDeviceExtension->Type) { case Keyboard: DeviceExtension->PacketPort = 0; break; case Mouse: DeviceExtension->PacketPort = CTRL_WRITE_MOUSE; break; default: ERR_(I8042PRT, "Unknown FDO type %u\n", FdoDeviceExtension->Type); ASSERT(FALSE); Status = STATUS_INTERNAL_ERROR; goto done; } DeviceExtension->Packet.Bytes = Bytes; DeviceExtension->Packet.CurrentByte = 0; DeviceExtension->Packet.ByteCount = ByteCount; DeviceExtension->Packet.State = SendingBytes; DeviceExtension->PacketResult = Status = STATUS_PENDING; DeviceExtension->CurrentIrp = Irp; DeviceExtension->CurrentIrpDevice = FdoDeviceExtension->Fdo; if (!i8042PacketWrite(DeviceExtension)) { Status = STATUS_IO_TIMEOUT; DeviceExtension->Packet.State = Idle; DeviceExtension->PacketResult = STATUS_ABANDONED; goto done; } DeviceExtension->Packet.CurrentByte++; done: KeReleaseInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt, Irql); if (Status != STATUS_PENDING) { DeviceExtension->CurrentIrp = NULL; DeviceExtension->CurrentIrpDevice = NULL; Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); } return Status; }
static VOID i8042PacketDpc( IN PPORT_DEVICE_EXTENSION DeviceExtension) { BOOLEAN FinishIrp = FALSE; KIRQL Irql; NTSTATUS Result = STATUS_INTERNAL_ERROR; /* Shouldn't happen */ /* If the interrupt happens before this is setup, the key * was already in the buffer. Too bad! */ if (!DeviceExtension->HighestDIRQLInterrupt) return; Irql = KeAcquireInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt); if (DeviceExtension->Packet.State == Idle && DeviceExtension->PacketComplete) { FinishIrp = TRUE; Result = DeviceExtension->PacketResult; DeviceExtension->PacketComplete = FALSE; } KeReleaseInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt, Irql); if (!FinishIrp) return; if (DeviceExtension->CurrentIrp) { DeviceExtension->CurrentIrp->IoStatus.Status = Result; IoCompleteRequest(DeviceExtension->CurrentIrp, IO_NO_INCREMENT); IoStartNextPacket(DeviceExtension->CurrentIrpDevice, FALSE); DeviceExtension->CurrentIrp = NULL; DeviceExtension->CurrentIrpDevice = NULL; } }
static NTSTATUS StartProcedure( IN PPORT_DEVICE_EXTENSION DeviceExtension) { NTSTATUS Status; UCHAR FlagsToDisable = 0; UCHAR FlagsToEnable = 0; KIRQL Irql; if (DeviceExtension->DataPort == 0) { /* Unable to do something at the moment */ return STATUS_SUCCESS; } if (!(DeviceExtension->Flags & (KEYBOARD_PRESENT | MOUSE_PRESENT))) { /* Try to detect them */ TRACE_(I8042PRT, "Check if the controller is really a i8042\n"); Status = i8042BasicDetect(DeviceExtension); if (!NT_SUCCESS(Status)) { WARN_(I8042PRT, "i8042BasicDetect() failed with status 0x%08lx\n", Status); return STATUS_UNSUCCESSFUL; } /* First detect the mouse and then the keyboard! If we do it the other way round, some systems throw away settings like the keyboard translation, when detecting the mouse. */ TRACE_(I8042PRT, "Detecting mouse\n"); i8042DetectMouse(DeviceExtension); TRACE_(I8042PRT, "Detecting keyboard\n"); i8042DetectKeyboard(DeviceExtension); INFO_(I8042PRT, "Keyboard present: %s\n", DeviceExtension->Flags & KEYBOARD_PRESENT ? "YES" : "NO"); INFO_(I8042PRT, "Mouse present : %s\n", DeviceExtension->Flags & MOUSE_PRESENT ? "YES" : "NO"); TRACE_(I8042PRT, "Enabling i8042 interrupts\n"); if (DeviceExtension->Flags & KEYBOARD_PRESENT) { FlagsToDisable |= CCB_KBD_DISAB; FlagsToEnable |= CCB_KBD_INT_ENAB; } if (DeviceExtension->Flags & MOUSE_PRESENT) { FlagsToDisable |= CCB_MOUSE_DISAB; FlagsToEnable |= CCB_MOUSE_INT_ENAB; } Status = EnableInterrupts(DeviceExtension, FlagsToDisable, FlagsToEnable); if (!NT_SUCCESS(Status)) { DeviceExtension->Flags &= ~(KEYBOARD_PRESENT | MOUSE_PRESENT); return Status; } } /* Connect interrupts */ if (DeviceExtension->Flags & KEYBOARD_PRESENT && DeviceExtension->Flags & KEYBOARD_CONNECTED && DeviceExtension->Flags & KEYBOARD_STARTED && !(DeviceExtension->Flags & KEYBOARD_INITIALIZED)) { /* Keyboard is ready to be initialized */ Status = i8042ConnectKeyboardInterrupt(DeviceExtension->KeyboardExtension); if (NT_SUCCESS(Status)) { DeviceExtension->Flags |= KEYBOARD_INITIALIZED; } } if (DeviceExtension->Flags & MOUSE_PRESENT && DeviceExtension->Flags & MOUSE_CONNECTED && DeviceExtension->Flags & MOUSE_STARTED && !(DeviceExtension->Flags & MOUSE_INITIALIZED)) { /* Mouse is ready to be initialized */ Status = i8042ConnectMouseInterrupt(DeviceExtension->MouseExtension); if (NT_SUCCESS(Status)) { DeviceExtension->Flags |= MOUSE_INITIALIZED; } /* Start the mouse */ Irql = KeAcquireInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt); i8042IsrWritePort(DeviceExtension, MOU_CMD_RESET, CTRL_WRITE_MOUSE); KeReleaseInterruptSpinLock(DeviceExtension->HighestDIRQLInterrupt, Irql); } return Status; }