Date: Thu, 08 May 1997 19:40:53 +0900 From: Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> To: Bruce Evans <bde@zeta.org.au> Cc: hackers@freebsd.org, j@uriah.heep.sax.de, yokota@zodiac.mech.utsunomiya-u.ac.jp Subject: Re: alternative probe_keyboard.c (was: Re: i386/3124: BOOT_PROBE_KEYBOARD hangs system in bootblocks) Message-ID: <199705081040.TAA00480@zodiac.mech.utsunomiya-u.ac.jp> In-Reply-To: Your message of "Sat, 26 Apr 1997 03:10:05 %2B1000." <199704251710.DAA05121@godzilla.zeta.org.au> References: <199704251710.DAA05121@godzilla.zeta.org.au>
next in thread | previous in thread | raw e-mail | index | archive | help
Ooops. I thought I had sent this reply days ago...
Kazu
>There is little need for it in -current. It could be controlled by an
>option in /boot.config:
>
>-S: force a serial console. Don't bother probing the keyboard. To use
> a keyboard after all, either start booting with a serial console and
> toggle -S, or if you don't have access to a serial console after all,
> boot from another disk without -S. Simplest.
>-K: enable the keyboard probe. Same as now except there is no danger
> from buggy keyboard probes except for people who enable the probe.
> If you use this in a SNAP, don't expect adequate test coverage of
> the probe :-).
>-D: enable dual normal/serial console. Do all i/o to both the normal
> and the serial console without much probing.
>-D -S: as above, except -S just gives preference to the serial console.
> You can toggle it easily by typing on either console.
>
>I implemented a non-optional ugly version -D. It's simple except for
>the timeout stuff. The timeout stuff could be skipped if there were
>a -D flag (users should only use -D if serial hardware exists). Output
>at 9600 bps is a bit slow to use all the time (twiddle() takes longer
>than disk i/o :-).
>
>Bruce
Based on your code and suggestions, I added some quick hack to your
code (see attached shar file). But I have not tested the code because
we are now hitting the size limit... We need to
reorganize/rearrange the boot code in order to pursue this hack.
Some notes:
* Space problem
We are seriously running out of space in the boot block. Whether we
use the existing probe_keyboard.c or the new one, we cannot turn on
all the options (PROBE_KEYBOARD_LOCK, BOOT_HD_BIAS, NAMEBLOCK,
NAMEBLOCK_WRITEBACK) together with -K -S -D options you have
suggested.
I managed to tweak some bytes and was able to compile the boot block
with PROBE_KEYBOARD_LOCK and BOOT_HD_BIAS. But, enabling NAMEBLOCK
and NAMEBLOCK_WRITEBACK in addition to these will make the boot block
exceed its limit.
* Symbols
RB_DUAL and RB_PROBEKBD are newly defined, temporarily in boot.h.
They should be in sys/reboot.h, but, I wonder if RB_PROBEKBD belongs
there; it might have been better to define it something rather than a
reboot() flag...
* Compile-time options
PROBE_KEYBOARD_LOCK
Same as before. Check if the key lock is on. If it is, the serial
console is forced.
FORCE_COMCONSOLE, PROBE_KEYBOARD
These options are now gone. probe_keyboard() is always compiled in,
but will be executed only if -K option takes effect (see below).
FORCE_COMCONSOLE is superseded by -S option (see below).
* /boot.config and "Boot:" options
-S
The serial console is forced. The keyboard is not probed.
-D
Console output will go to both the normal and the serial console. The
keyboard is not probed.
If neither -S nor -D is specified, the systems behaves in the same way
as the current boot block. The normal console is assumed (unless -K
option takes effect, see below).
-K
If neither -S nor -D is specified but -K is specified, the keyboard is
probed and if it is not found, the serial console is assumed. If it is
found, the normal console is assumed.
-D -S
I didn't quite follow your intention and didn't implement this
combination. I have run out of space anyway.
Examples:
-S
The serial console is forced.
-S -K
The serial console is forced. -K is ignored and the keyboard is not
probed.
-K
The keyboard is probed.
-D
Console output will go to both the normal and the serial console.
-D -S
-D -K
-D -S -K
Console output will go to both the normal and the serial console.
-S and -K are ignored.
Looking forward to hearing your comments.
Kazu
# This is a shell archive. Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file". Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
# biosboot.diff
# probe_keyboard.c-echo
#
echo x - biosboot.diff
sed 's/^X//' >biosboot.diff << 'END-of-biosboot.diff'
Xdiff -c2 ../biosboot/boot.c ./boot.c
X*** ../biosboot/boot.c Thu Apr 10 23:42:23 1997
X--- ./boot.c Tue Apr 29 10:16:31 1997
X***************
X*** 85,99 ****
X int ret;
X
X! #ifdef PROBE_KEYBOARD
X! if (probe_keyboard()) {
X! init_serial();
X! loadflags |= RB_SERIAL;
X! printf("\nNo keyboard found.");
X! }
X! #endif
X
X #ifdef PROBE_KEYBOARD_LOCK
X if (!(inb(0x64) & 0x10)) {
X- init_serial();
X loadflags |= RB_SERIAL;
X printf("\nKeyboard locked.");
X--- 85,92 ----
X int ret;
X
X! init_serial();
X
X #ifdef PROBE_KEYBOARD_LOCK
X if (!(inb(0x64) & 0x10)) {
X loadflags |= RB_SERIAL;
X printf("\nKeyboard locked.");
X***************
X*** 101,110 ****
X #endif
X
X- #ifdef FORCE_COMCONSOLE
X- init_serial();
X- loadflags |= RB_SERIAL;
X- printf("\nSerial console forced.");
X- #endif
X-
X /* Pick up the story from the Bios on geometry of disks */
X
X--- 94,97 ----
X***************
X*** 156,163 ****
X #endif /*NAMEBLOCK*/
X readfile("boot.config", boot_config, BOOT_CONFIG_SIZE);
X if (namebuf[0] != '\0')
X printf("boot.config: %s", boot_config);
X name = "kernel";
X- getbootdev(boot_config, &loadflags);
X /*
X * XXX parsing of `name' is in openrd(), so the defaults aren't
X--- 143,150 ----
X #endif /*NAMEBLOCK*/
X readfile("boot.config", boot_config, BOOT_CONFIG_SIZE);
X+ getbootdev(boot_config, &loadflags);
X if (namebuf[0] != '\0')
X printf("boot.config: %s", boot_config);
X name = "kernel";
X /*
X * XXX parsing of `name' is in openrd(), so the defaults aren't
X***************
X*** 168,172 ****
X /* If we have looped, use the previous entries as defaults */
X printf("\n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory\n"
X! "Usage: [[[%d:][%s](%d,a)]%s][-abcCdghrsv]\n"
X "Use 1:sd(0,a)kernel to boot sd0 if it is BIOS drive 1\n"
X "Use ? for file list or press Enter for defaults\n\nBoot: ",
X--- 155,159 ----
X /* If we have looped, use the previous entries as defaults */
X printf("\n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory\n"
X! "Usage: [[[%d:][%s](%d,a)]%s][-abcCdDghKrsSv]\n"
X "Use 1:sd(0,a)kernel to boot sd0 if it is BIOS drive 1\n"
X "Use ? for file list or press Enter for defaults\n\nBoot: ",
X***************
X*** 174,183 ****
X dosdev & 0x7f, devs[maj], unit, name);
X
X! loadflags &= RB_SERIAL; /* clear all, but leave serial console */
X
X /*
X * Be paranoid and make doubly sure that the input buffer is empty.
X */
X! if (loadflags & RB_SERIAL)
X init_serial();
X
X--- 161,170 ----
X dosdev & 0x7f, devs[maj], unit, name);
X
X! loadflags &= (RB_SERIAL | RB_DUAL);
X
X /*
X * Be paranoid and make doubly sure that the input buffer is empty.
X */
X! if (loadflags & (RB_SERIAL | RB_DUAL))
X init_serial();
X
X***************
X*** 352,355 ****
X--- 339,343 ----
X getbootdev(char *ptr, int *howto)
X {
X+ int f = *howto; /* save some bytes */
X char c;
X
X***************
X*** 363,392 ****
X goto nextarg;
X if (c == 'C')
X! *howto |= RB_CDROM;
X if (c == 'a')
X! *howto |= RB_ASKNAME;
X if (c == 'b')
X! *howto |= RB_HALT;
X if (c == 'c')
X! *howto |= RB_CONFIG;
X if (c == 'd')
X! *howto |= RB_KDB;
X! if (c == 'h') {
X! *howto ^= RB_SERIAL;
X! if (*howto & RB_SERIAL)
X! init_serial();
X! continue;
X! }
X if (c == 'g')
X! *howto |= RB_GDB;
X if (c == 'r')
X! *howto |= RB_DFLTROOT;
X if (c == 's')
X! *howto |= RB_SINGLE;
X if (c == 'v')
X! *howto |= RB_VERBOSE;
X }
X if (c == '\0')
X! return;
X name = ptr;
X while (*++ptr != '\0') {
X--- 351,382 ----
X goto nextarg;
X if (c == 'C')
X! f |= RB_CDROM;
X if (c == 'a')
X! f |= RB_ASKNAME;
X if (c == 'b')
X! f |= RB_HALT;
X if (c == 'c')
X! f |= RB_CONFIG;
X if (c == 'd')
X! f |= RB_KDB;
X! if (c == 'h')
X! f ^= RB_SERIAL;
X if (c == 'g')
X! f |= RB_GDB;
X if (c == 'r')
X! f |= RB_DFLTROOT;
X if (c == 's')
X! f |= RB_SINGLE;
X if (c == 'v')
X! f |= RB_VERBOSE;
X! if (c == 'S')
X! f |= RB_SERIAL;
X! if (c == 'D')
X! f |= (RB_DUAL | RB_SERIAL);
X! if (c == 'K')
X! f |= RB_PROBEKBD;
X }
X if (c == '\0')
X! break;
X name = ptr;
X while (*++ptr != '\0') {
X***************
X*** 397,399 ****
X--- 387,398 ----
X }
X }
X+
X+ if (((f & (RB_SERIAL | RB_DUAL | RB_PROBEKBD)) == RB_PROBEKBD)
X+ && probe_keyboard()) {
X+ f |= RB_SERIAL;
X+ printf("\nNo keyboard found.");
X+ }
X+ if (f & (RB_SERIAL | RB_DUAL))
X+ init_serial();
X+ *howto = f;
X }
Xdiff -c2 ../biosboot/boot.h ./boot.h
X*** ../biosboot/boot.h Thu Apr 10 23:42:24 1997
X--- ./boot.h Mon Apr 28 18:03:51 1997
X***************
X*** 36,39 ****
X--- 36,42 ----
X #include <ufs/ufs/inode.h>
X
X+ #define RB_DUAL 0x40000 /* XXX */
X+ #define RB_PROBEKBD 0x80000 /* XXX */
X+
X extern char *devs[];
X extern char *name;
Xdiff -c2 ../biosboot/io.c ./io.c
X*** ../biosboot/io.c Thu Apr 10 23:42:24 1997
X--- ./io.c Mon Apr 28 18:07:45 1997
X***************
X*** 122,132 ****
X putchar(int c)
X {
X! if (c == '\n') {
X! if (loadflags & RB_SERIAL)
X! serial_putc('\r');
X! else
X! putc('\r');
X! }
X! if (loadflags & RB_SERIAL)
X serial_putc(c);
X else
X--- 122,131 ----
X putchar(int c)
X {
X! if (c == '\n')
X! putchar('\r');
X! if (loadflags & RB_DUAL) {
X! putc(c);
X! serial_putc(c);
X! } else if (loadflags & RB_SERIAL)
X serial_putc(c);
X else
X***************
X*** 140,144 ****
X
X loop:
X! if ((c = ((loadflags & RB_SERIAL) ? serial_getc() : getc())) == '\r')
X c = '\n';
X if (c == '\b') {
X--- 139,155 ----
X
X loop:
X! if (loadflags & RB_DUAL) {
X! if (ischar())
X! c = getc();
X! else if (serial_ischar())
X! c = serial_getc();
X! else
X! goto loop;
X! } else if (loadflags & RB_SERIAL) {
X! c = serial_getc();
X! } else {
X! c = getc();
X! }
X! if (c == '\r')
X c = '\n';
X if (c == '\b') {
X***************
X*** 154,158 ****
X }
X
X- #ifdef PROBE_KEYBOARD
X /*
X * This routine uses an inb to an unused port, the time to execute that
X--- 165,168 ----
X***************
X*** 172,176 ****
X (void)inb(0x84);
X }
X- #endif /* PROBE_KEYBOARD */
X
X static __inline int
X--- 182,185 ----
X***************
X*** 186,191 ****
X isc = ischar();
X
X! if (!(loadflags & RB_SERIAL))
X return (isc);
X return (serial_ischar());
X
X--- 195,204 ----
X isc = ischar();
X
X! if (loadflags & RB_DUAL) {
X! if (isc != 0)
X! return (isc);
X! } else if (!(loadflags & RB_SERIAL)) {
X return (isc);
X+ }
X return (serial_ischar());
X
Xdiff -c2 ../biosboot/serial.S ./serial.S
X*** ../biosboot/serial.S Thu Apr 10 23:42:24 1997
X--- ./serial.S Mon Apr 28 11:25:35 1997
X***************
X*** 96,101 ****
X push %edx
X
X mov $COMCONSOLE + 5, %edx # line status reg
X! 1: inb %dx, %al
X test $0x20, %al
X jz 1b # TX buffer not empty
X--- 96,105 ----
X push %edx
X
X+ movl $10000, %ecx # timeout
X mov $COMCONSOLE + 5, %edx # line status reg
X! 1:
X! decl %ecx
X! je 2f
X! inb %dx, %al
X test $0x20, %al
X jz 1b # TX buffer not empty
X***************
X*** 106,109 ****
X--- 110,114 ----
X outb %al, %dx # send this one
X
X+ 2:
X pop %edx
X pop %ebp
X***************
X*** 177,181 ****
X outb %al, %dx
X
X! add $2, %edx # line control reg
X movb $0x13, %al
X outb %al, %dx # 8 bit, no parity, 1 stop bit
X--- 182,190 ----
X outb %al, %dx
X
X! incl %edx # fifo control register (if any)
X! xorl %eax,%eax
X! outb %al, %dx # disable fifo to reduce worst-case busy-wait
X!
X! incl %edx # line control reg
X movb $0x13, %al
X outb %al, %dx # 8 bit, no parity, 1 stop bit
END-of-biosboot.diff
echo x - probe_keyboard.c-echo
sed 's/^X//' >probe_keyboard.c-echo << 'END-of-probe_keyboard.c-echo'
X/*-
X * Copyright (c) 1997 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms, with or without
X * modification, are permitted provided that the following conditions
X * are met:
X * 1. Redistributions of source code must retain the above copyright
X * notice, this list of conditions and the following disclaimer.
X * 2. Redistributions in binary form must reproduce the above copyright
X * notice, this list of conditions and the following disclaimer in the
X * documentation and/or other materials provided with the distribution.
X *
X * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
X * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
X * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
X * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
X * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
X * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
X * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
X * SUCH DAMAGE.
X *
X * $Id:$
X */
X
X#include <i386/include/cpufunc.h>
X#include <i386/isa/isa.h>
X#include <i386/isa/ic/i8042.h>
X#include <i386/isa/kbdio.h>
X
X#include "boot.h"
X
X#define PROBE_MAXRETRY 5
X#define PROBE_MAXWAIT 400
X
X#define IO_DUMMY 0x84
X
X/* 7 microsec delay necessary for some keyboard controllers */
Xstatic void
Xdelay7(void)
X{
X /*
X * I know this is broken, but no timer is avaiable yet at this stage...
X * See also comments in `delay1ms()' in `io.c'.
X */
X inb(IO_DUMMY); inb(IO_DUMMY);
X inb(IO_DUMMY); inb(IO_DUMMY);
X inb(IO_DUMMY); inb(IO_DUMMY);
X}
X
X/*
X * Perform a simple test on the keyboard; issue the ECHO command and see
X * if the right answer is returned. We don't do anything as drastic as
X * full keyboard reset; it will be too troublesome and take too much time.
X */
Xint
Xprobe_keyboard(void)
X{
X int retry = PROBE_MAXRETRY;
X int wait;
X int i;
X
X while (--retry >= 0) {
X /* flush any noise */
X while (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) {
X delay7();
X inb(IO_KBD + KBD_DATA_PORT);
X delay1ms();
X }
X
X /* wait until the controller can accept a command */
X for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
X if (((i = inb(IO_KBD + KBD_STATUS_PORT))
X & (KBDS_INPUT_BUFFER_FULL | KBDS_ANY_BUFFER_FULL)) == 0)
X break;
X if (i & KBDS_ANY_BUFFER_FULL) {
X delay7();
X inb(IO_KBD + KBD_DATA_PORT);
X }
X delay1ms();
X }
X if (wait <= 0)
X continue;
X
X /* send the ECHO command */
X outb(IO_KBD + KBD_DATA_PORT, KBDC_ECHO);
X
X /* wait for a response */
X for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
X if (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL)
X break;
X delay1ms();
X }
X if (wait <= 0)
X continue;
X
X delay7();
X i = inb(IO_KBD + KBD_DATA_PORT);
X#ifdef PROBE_KBD_BEBUG
X printf("probe_keyboard: got 0x%x.\n", i);
X#endif
X if (i == KBD_ECHO) {
X /* got the right answer */
X return (0);
X }
X }
X
X return (1);
X}
X
END-of-probe_keyboard.c-echo
exit
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199705081040.TAA00480>
