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 ******************************************************************/
18 /* FUNCTIONS *****************************************************************/
22 IN PPORT_DEVICE_EXTENSION DeviceExtension
)
26 /* Flush output buffer */
27 while (NT_SUCCESS(i8042ReadData(DeviceExtension
, KBD_OBF
/* | MOU_OBF*/, &Ignore
))) {
28 KeStallExecutionProcessor(50);
29 TRACE_(I8042PRT
, "Output data flushed\n");
32 /* Flush input buffer */
33 while (NT_SUCCESS(i8042ReadData(DeviceExtension
, KBD_IBF
, &Ignore
))) {
34 KeStallExecutionProcessor(50);
35 TRACE_(I8042PRT
, "Input data flushed\n");
41 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
43 IN UCHAR SelectCmd OPTIONAL
)
46 if (!i8042Write(DeviceExtension
, DeviceExtension
->ControlPort
, SelectCmd
))
49 return i8042Write(DeviceExtension
, DeviceExtension
->DataPort
, Value
);
53 * FUNCTION: Read data from port 0x60
57 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
64 Status
= i8042ReadStatus(DeviceExtension
, &PortStatus
);
65 if (!NT_SUCCESS(Status
))
68 // If data is available
69 if (PortStatus
& StatusFlags
)
71 *Data
= READ_PORT_UCHAR(DeviceExtension
->DataPort
);
72 INFO_(I8042PRT
, "Read: 0x%02x (status: 0x%x)\n", Data
[0], PortStatus
);
74 // If the data is valid (not timeout, not parity error)
75 if ((PortStatus
& KBD_PERR
) == 0)
76 return STATUS_SUCCESS
;
78 return STATUS_UNSUCCESSFUL
;
83 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
86 ASSERT(DeviceExtension
->ControlPort
!= NULL
);
87 *Status
= READ_PORT_UCHAR(DeviceExtension
->ControlPort
);
88 return STATUS_SUCCESS
;
92 * FUNCTION: Read data from data port
96 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
102 Counter
= DeviceExtension
->Settings
.PollingIterations
;
106 Status
= i8042ReadKeyboardData(DeviceExtension
, Data
);
108 if (NT_SUCCESS(Status
))
111 KeStallExecutionProcessor(50);
115 return STATUS_IO_TIMEOUT
;
119 * This one reads a value from the port; You don't have to specify
120 * which one, it'll always be from the one you talked to, so one function
121 * is enough this time. Note how MSDN specifies the
122 * WaitForAck parameter to be ignored.
128 IN BOOLEAN WaitForAck
)
130 PPORT_DEVICE_EXTENSION DeviceExtension
;
132 UNREFERENCED_PARAMETER(WaitForAck
);
134 DeviceExtension
= (PPORT_DEVICE_EXTENSION
)Context
;
136 return i8042ReadDataWait(DeviceExtension
, Value
);
140 * These functions are callbacks for filter driver custom
141 * initialization routines.
145 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
148 IN BOOLEAN WaitForAck
)
152 ULONG ResendIterations
;
154 ResendIterations
= DeviceExtension
->Settings
.ResendIterations
+ 1;
159 if (!i8042Write(DeviceExtension
, DeviceExtension
->DataPort
, Port
))
161 WARN_(I8042PRT
, "Failed to write Port\n");
162 return STATUS_IO_TIMEOUT
;
165 if (!i8042Write(DeviceExtension
, DeviceExtension
->DataPort
, Value
))
167 WARN_(I8042PRT
, "Failed to write Value\n");
168 return STATUS_IO_TIMEOUT
;
173 Status
= i8042ReadDataWait(DeviceExtension
, &Ack
);
174 if (!NT_SUCCESS(Status
))
176 WARN_(I8042PRT
, "Failed to read Ack\n");
180 return STATUS_SUCCESS
;
181 else if (Ack
== KBD_RESEND
)
182 INFO_(I8042PRT
, "i8042 asks for a data resend\n");
186 return STATUS_SUCCESS
;
188 TRACE_(I8042PRT
, "Reiterating\n");
190 } while (ResendIterations
);
192 return STATUS_IO_TIMEOUT
;
196 * FUNCTION: Write data to a port, waiting first for it to become ready
200 IN PPORT_DEVICE_EXTENSION DeviceExtension
,
207 ASSERT(DeviceExtension
->ControlPort
!= NULL
);
209 Counter
= DeviceExtension
->Settings
.PollingIterations
;
211 while ((KBD_IBF
& READ_PORT_UCHAR(DeviceExtension
->ControlPort
)) &&
214 KeStallExecutionProcessor(50);
219 WRITE_PORT_UCHAR(addr
, data
);
220 INFO_(I8042PRT
, "Sent 0x%x to port %p\n", data
, addr
);