Use the same method for detecting actual presence of AT-style keyboard

controller as we use in boot blocks (querying status register until
bit 1 goes off). If that doesn't happed during reasonable period assume
that the hardware doesn't have AT-style keyboard controller. This makes
FreeBSD working almost OOB on MacBook Pro (still there are issues with
putting second CPU core on-line, but since installation CD comes with
UP kernel with this change one should be able to install FreeBSD without
playing tricks with hints). Other legacy-free hardware (e.g. IBM NetVista
S40) should benefit from this as well, but since I don't have any I can't
verify.

It should make no difference on the ordinary i386 hardware (since in
that case that hardware already would be having an issues with A20
routines in boot blocks). I don't know much about AT-style keyboard
controller on other platforms (and don't have dedicated access to one),
therefore, the code is restricted to i386 for now. I suspect that amd64
may need this as well, but I would rather leave this decision to someone
who knows better about the platform(s) in question.

I have tested this change on as many "ordinary i386 boxes" as I can get
my hands on, and it doesn't create any false negatives on hardware with
AT-style keyboard present.

MFC after:	1 month
This commit is contained in:
Maxim Sobolev 2006-04-26 06:05:16 +00:00
parent 7c5a8ab212
commit 6621aa5cc7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=158041
3 changed files with 61 additions and 5 deletions

View File

@ -282,11 +282,12 @@ atkbd_configure(int flags)
int arg[2];
int i;
/* probe the keyboard controller */
atkbdc_configure();
/* if the driver is disabled, unregister the keyboard if any */
if (resource_disabled("atkbd", ATKBD_DEFAULT)) {
/*
* Probe the keyboard controller, if not present or if the driver
* is disabled, unregister the keyboard if any.
*/
if (atkbdc_configure() != 0 ||
resource_disabled("atkbd", ATKBD_DEFAULT)) {
i = kbd_find_keyboard(ATKBD_DRIVER_NAME, ATKBD_DEFAULT);
if (i >= 0) {
kbd = kbd_get_keyboard(i);

View File

@ -153,6 +153,10 @@ atkbdc_configure(void)
bus_space_tag_t tag;
bus_space_handle_t h0;
bus_space_handle_t h1;
#if defined(__i386__)
volatile int i;
register_t flags;
#endif
#ifdef __sparc64__
char name[32];
phandle_t chosen, node;
@ -219,6 +223,26 @@ atkbdc_configure(void)
h1 = (bus_space_handle_t)port1;
#endif
#endif
#if defined(__i386__)
/*
* Check if we really have AT keyboard controller. Poll status
* register until we get "all clear" indication. If no such
* indication comes, it probably means that there is no AT
* keyboard controller present. Give up in such case. Check relies
* on the fact that reading from non-existing in/out port returns
* 0xff on i386. May or may not be true on other platforms.
*/
flags = intr_disable();
for (i = 0; i != 65535; i++) {
if ((bus_space_read_1(tag, h1, 0) & 0x2) == 0)
break;
}
intr_restore(flags);
if (i == 65535)
return ENXIO;
#endif
return atkbdc_setup(atkbdc_softc[0], tag, h0, h1);
}

View File

@ -93,6 +93,12 @@ atkbdc_isa_probe(device_t dev)
u_long count;
int error;
int rid;
#if defined(__i386__)
bus_space_tag_t tag;
bus_space_handle_t ioh1;
volatile int i;
register_t flags;
#endif
/* check PnP IDs */
if (ISA_PNP_PROBE(device_get_parent(dev), dev, atkbdc_ids) == ENXIO)
@ -127,6 +133,31 @@ atkbdc_isa_probe(device_t dev)
bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
return ENXIO;
}
#if defined(__i386__)
/*
* Check if we really have AT keyboard controller. Poll status
* register until we get "all clear" indication. If no such
* indication comes, it probably means that there is no AT
* keyboard controller present. Give up in such case. Check relies
* on the fact that reading from non-existing in/out port returns
* 0xff on i386. May or may not be true on other platforms.
*/
tag = rman_get_bustag(port0);
ioh1 = rman_get_bushandle(port1);
flags = intr_disable();
for (i = 0; i != 65535; i++) {
if ((bus_space_read_1(tag, ioh1, 0) & 0x2) == 0)
break;
}
intr_restore(flags);
if (i == 65535) {
bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
bus_release_resource(dev, SYS_RES_IOPORT, 1, port1);
return ENXIO;
}
#endif
device_verbose(dev);
error = atkbdc_probe_unit(device_get_unit(dev), port0, port1);