2 * PROJECT: ReactOS i8042 (ps/2 keyboard-mouse controller) driver
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: drivers/input/i8042prt/readwrite.c
5 * PURPOSE: Read/write port functions
6 * PROGRAMMERS: Copyright Victor Kirhenshtein (sauros@iname.com)
7 Copyright Jason Filby (jasonfilby@yahoo.com)
8 Copyright Martijn Vernooij (o112w8r02@sneakemail.com)
9 Copyright 2006-2007 Hervé Poussineau (hpoussin@reactos.org)
12 /* INCLUDES ******************************************************************/
16 /* FUNCTIONS *****************************************************************/
20 IN PPORT_DEVICE_EXTENSION DeviceExtension
)
24 /* Flush output buffer */
25 while (NT_SUCCESS(i8042ReadData(DeviceExtension
, KBD_OBF
/* | MOU_OBF*/, &Ignore
))) {
26 KeStallExecutionProcessor(50);
27 TRACE_(I8042PRT
, "Output data flushed\n");
30 /* Flush input buffer */
31 while (NT_SUCCESS(i8042ReadData(DeviceExtension
, KBD_IBF
, &Ignore
))) {
32 KeStallExecutionProcessor(50);
33 TRACE_(I8042PRT
, "Input data flushed\n");
39 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
41 IN UCHAR SelectCmd OPTIONAL
)
44 if (!i8042Write(DeviceExtension
, DeviceExtension
->ControlPort
, SelectCmd
))
47 return i8042Write(DeviceExtension
, DeviceExtension
->DataPort
, Value
);
51 * FUNCTION: Read data from port 0x60
55 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
62 Status
= i8042ReadStatus(DeviceExtension
, &PortStatus
);
63 if (!NT_SUCCESS(Status
))
66 // If data is available
67 if (PortStatus
& StatusFlags
)
69 *Data
= READ_PORT_UCHAR(DeviceExtension
->DataPort
);
70 INFO_(I8042PRT
, "Read: 0x%02x (status: 0x%x)\n", Data
[0], PortStatus
);
72 // If the data is valid (not timeout, not parity error)
73 if ((PortStatus
& KBD_PERR
) == 0)
74 return STATUS_SUCCESS
;
76 return STATUS_UNSUCCESSFUL
;
81 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
84 ASSERT(DeviceExtension
->ControlPort
!= NULL
);
85 *Status
= READ_PORT_UCHAR(DeviceExtension
->ControlPort
);
86 return STATUS_SUCCESS
;
90 * FUNCTION: Read data from data port
94 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
100 Counter
= DeviceExtension
->Settings
.PollingIterations
;
104 Status
= i8042ReadKeyboardData(DeviceExtension
, Data
);
106 if (NT_SUCCESS(Status
))
109 KeStallExecutionProcessor(50);
113 return STATUS_IO_TIMEOUT
;
117 * This one reads a value from the port; You don't have to specify
118 * which one, it'll always be from the one you talked to, so one function
119 * is enough this time. Note how MSDN specifies the
120 * WaitForAck parameter to be ignored.
126 IN BOOLEAN WaitForAck
)
128 PPORT_DEVICE_EXTENSION DeviceExtension
;
130 UNREFERENCED_PARAMETER(WaitForAck
);
132 DeviceExtension
= (PPORT_DEVICE_EXTENSION
)Context
;
134 return i8042ReadDataWait(DeviceExtension
, Value
);
138 * These functions are callbacks for filter driver custom
139 * initialization routines.
143 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
146 IN BOOLEAN WaitForAck
)
150 ULONG ResendIterations
;
152 ResendIterations
= DeviceExtension
->Settings
.ResendIterations
+ 1;
157 if (!i8042Write(DeviceExtension
, DeviceExtension
->DataPort
, Port
))
159 WARN_(I8042PRT
, "Failed to write Port\n");
160 return STATUS_IO_TIMEOUT
;
163 if (!i8042Write(DeviceExtension
, DeviceExtension
->DataPort
, Value
))
165 WARN_(I8042PRT
, "Failed to write Value\n");
166 return STATUS_IO_TIMEOUT
;
171 Status
= i8042ReadDataWait(DeviceExtension
, &Ack
);
172 if (!NT_SUCCESS(Status
))
174 WARN_(I8042PRT
, "Failed to read Ack\n");
178 return STATUS_SUCCESS
;
179 else if (Ack
== KBD_RESEND
)
180 INFO_(I8042PRT
, "i8042 asks for a data resend\n");
184 return STATUS_SUCCESS
;
186 TRACE_(I8042PRT
, "Reiterating\n");
188 } while (ResendIterations
);
190 return STATUS_IO_TIMEOUT
;
194 * FUNCTION: Write data to a port, waiting first for it to become ready
198 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
205 ASSERT(DeviceExtension
->ControlPort
!= NULL
);
207 Counter
= DeviceExtension
->Settings
.PollingIterations
;
209 while ((KBD_IBF
& READ_PORT_UCHAR(DeviceExtension
->ControlPort
)) &&
212 KeStallExecutionProcessor(50);
217 WRITE_PORT_UCHAR(addr
, data
);
218 INFO_(I8042PRT
, "Sent 0x%x to port %p\n", data
, addr
);