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>