Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225/* * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver * LICENSE: GPL - See COPYING in the top level directory * FILE: drivers/input/i8042prt/readwrite.c * PURPOSE: Read/write port functions * PROGRAMMERS: Copyright Victor Kirhenshtein (sauros@iname.com) Copyright Jason Filby (jasonfilby@yahoo.com) Copyright Martijn Vernooij (o112w8r02@sneakemail.com) Copyright 2006-2007 Herv� Poussineau (hpoussin@reactos.org) */
/* INCLUDES ******************************************************************/
#include "i8042prt.h"
#include <debug.h>
/* FUNCTIONS *****************************************************************/
VOIDi8042Flush( IN PPORT_DEVICE_EXTENSION DeviceExtension){ UCHAR Ignore;
/* Flush output buffer */ while (NT_SUCCESS(i8042ReadData(DeviceExtension, KBD_OBF /* | MOU_OBF*/, &Ignore))) { KeStallExecutionProcessor(50); TRACE_(I8042PRT, "Output data flushed\n"); }
/* Flush input buffer */ while (NT_SUCCESS(i8042ReadData(DeviceExtension, KBD_IBF, &Ignore))) { KeStallExecutionProcessor(50); TRACE_(I8042PRT, "Input data flushed\n"); }}
BOOLEANi8042IsrWritePort( IN PPORT_DEVICE_EXTENSION DeviceExtension, IN UCHAR Value, IN UCHAR SelectCmd OPTIONAL){ if (SelectCmd) if (!i8042Write(DeviceExtension, DeviceExtension->ControlPort, SelectCmd)) return FALSE;
return i8042Write(DeviceExtension, DeviceExtension->DataPort, Value);}
/* * FUNCTION: Read data from port 0x60 */NTSTATUSi8042ReadData( IN PPORT_DEVICE_EXTENSION DeviceExtension, IN UCHAR StatusFlags, OUT PUCHAR Data){ UCHAR PortStatus; NTSTATUS Status;
Status = i8042ReadStatus(DeviceExtension, &PortStatus); if (!NT_SUCCESS(Status)) return Status;
// If data is available if (PortStatus & StatusFlags) { *Data = READ_PORT_UCHAR(DeviceExtension->DataPort); INFO_(I8042PRT, "Read: 0x%02x (status: 0x%x)\n", Data[0], PortStatus);
// If the data is valid (not timeout, not parity error) if ((PortStatus & KBD_PERR) == 0) return STATUS_SUCCESS; } return STATUS_UNSUCCESSFUL;}
NTSTATUSi8042ReadStatus( IN PPORT_DEVICE_EXTENSION DeviceExtension, OUT PUCHAR Status){ ASSERT(DeviceExtension->ControlPort != NULL); *Status = READ_PORT_UCHAR(DeviceExtension->ControlPort); return STATUS_SUCCESS;}
/* * FUNCTION: Read data from data port */NTSTATUSi8042ReadDataWait( IN PPORT_DEVICE_EXTENSION DeviceExtension, OUT PUCHAR Data){ ULONG Counter; NTSTATUS Status;
Counter = DeviceExtension->Settings.PollingIterations;
while (Counter--) { Status = i8042ReadKeyboardData(DeviceExtension, Data);
if (NT_SUCCESS(Status)) return Status;
KeStallExecutionProcessor(50); }
/* Timed out */ return STATUS_IO_TIMEOUT;}
/* * This one reads a value from the port; You don't have to specify * which one, it'll always be from the one you talked to, so one function * is enough this time. Note how MSDN specifies the * WaitForAck parameter to be ignored. */NTSTATUS NTAPIi8042SynchReadPort( IN PVOID Context, OUT PUCHAR Value, IN BOOLEAN WaitForAck){ PPORT_DEVICE_EXTENSION DeviceExtension;
UNREFERENCED_PARAMETER(WaitForAck);
DeviceExtension = (PPORT_DEVICE_EXTENSION)Context;
return i8042ReadDataWait(DeviceExtension, Value);}
/* * These functions are callbacks for filter driver custom * initialization routines. */NTSTATUS NTAPIi8042SynchWritePort( IN PPORT_DEVICE_EXTENSION DeviceExtension, IN UCHAR Port, IN UCHAR Value, IN BOOLEAN WaitForAck){ NTSTATUS Status; UCHAR Ack; ULONG ResendIterations;
ResendIterations = DeviceExtension->Settings.ResendIterations + 1;
do { if (Port) if (!i8042Write(DeviceExtension, DeviceExtension->DataPort, Port)) { WARN_(I8042PRT, "Failed to write Port\n"); return STATUS_IO_TIMEOUT; }
if (!i8042Write(DeviceExtension, DeviceExtension->DataPort, Value)) { WARN_(I8042PRT, "Failed to write Value\n"); return STATUS_IO_TIMEOUT; }
if (WaitForAck) { Status = i8042ReadDataWait(DeviceExtension, &Ack); if (!NT_SUCCESS(Status)) { WARN_(I8042PRT, "Failed to read Ack\n"); return Status; } if (Ack == KBD_ACK) return STATUS_SUCCESS; else if (Ack == KBD_RESEND) INFO_(I8042PRT, "i8042 asks for a data resend\n"); } else { return STATUS_SUCCESS; } TRACE_(I8042PRT, "Reiterating\n"); ResendIterations--; } while (ResendIterations);
return STATUS_IO_TIMEOUT;}
/* * FUNCTION: Write data to a port, waiting first for it to become ready */BOOLEANi8042Write( IN PPORT_DEVICE_EXTENSION DeviceExtension, IN PUCHAR addr, IN UCHAR data){ ULONG Counter;
ASSERT(addr); ASSERT(DeviceExtension->ControlPort != NULL);
Counter = DeviceExtension->Settings.PollingIterations;
while ((KBD_IBF & READ_PORT_UCHAR(DeviceExtension->ControlPort)) && (Counter--)) { KeStallExecutionProcessor(50); }
if (Counter) { WRITE_PORT_UCHAR(addr, data); INFO_(I8042PRT, "Sent 0x%x to port %p\n", data, addr); return TRUE; } return FALSE;}