ps2_drv: back down after unsucessful AUX access

The driver might end up in an endless loop on systems that do not
contain an i8042 controller when probing the AUX interface. This
leads to busy looping and in the end to not annoucing the Input
service. Components that wait for the announcement of the service
will therefore hang as well.

Normally a service gets announced only if it is usable but in this
case this is inconvient because it renders all scenarios that use
the input_merger non working on x86 systems that only provide USB
input and do not have PS/2 at all.

Ideally, the PS/2 driver should only be started if the system needs it.
That is currently not feasible and for the time being we post-pone the
inevitable and back down after several unsucessful attempts to read
from the AUX interface while initializing the driver.

Fixes #1871.
This commit is contained in:
Josef Söntgen 2016-02-01 14:50:29 +01:00 committed by Christian Helmuth
parent f572cf8a05
commit c10ad4ff01
1 changed files with 30 additions and 2 deletions

View File

@ -75,11 +75,17 @@ class I8042
enum Return
{
RET_INVALID = 0x23, /* arbitrary value */
RET_TEST_OK = 0x55,
RET_KBD_TEST_OK = 0x00,
RET_AUX_TEST_OK = 0x00,
};
/*
* Maximal number of attempts to read from port
*/
enum { MAX_ATTEMPTS = 4096 };
class _Channel : public Serial_interface,
public Genode::Ring_buffer<unsigned char, 1024>
{
@ -115,8 +121,21 @@ class I8042
unsigned char read()
{
while (empty())
unsigned attempts = MAX_ATTEMPTS;
while (empty() && attempts > 0) {
flush_read();
attempts--;
}
/*
* We can savely return zero at this point because it only
* matters while the driver is initializing (see various reset()
* functions).
*/
if (attempts == 0) {
PERR("Failed to read from port");
return 0;
}
return get();
}
@ -184,7 +203,16 @@ class I8042
*/
unsigned char _wait_data()
{
while (!_output_buffer_full());
unsigned attempts = MAX_ATTEMPTS;
while (!_output_buffer_full() && attempts > 0)
attempts--;
if (attempts == 0) {
PERR("No data available");
return RET_INVALID;
}
return _data();
}