summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>1995-01-20 07:48:27 +0000
committerwpaul <wpaul@FreeBSD.org>1995-01-20 07:48:27 +0000
commit1875d75ad14b7e1e30810e2caa90e11f404fd9f2 (patch)
treea551b89627e6c0f432e7ce4339805e8d158a7ec7 /sys
parent7a6a5253caf293944cabff9f7679f6bf2d51b9dd (diff)
downloadFreeBSD-src-1875d75ad14b7e1e30810e2caa90e11f404fd9f2.zip
FreeBSD-src-1875d75ad14b7e1e30810e2caa90e11f404fd9f2.tar.gz
Submitted by: Bill Paul (wpaul@ctr.columbia.edu)
Obtained from: bios boot block changed to allow booting from both the attached graphics display and from a serial port. (A specially compiled serial boot block is no longer necessary.) The boot block should detect the presence or absence of a keyboard: if there is no keyboard, COM1 is turned into the console. This simulates the behavior of the Sun boot PROMs. Unplug your keyboard, attach a terminal to COM1 and you should be ready to go. :)
Diffstat (limited to 'sys')
-rw-r--r--sys/i386/boot/biosboot/Makefile9
-rw-r--r--sys/i386/boot/biosboot/README.serial132
-rw-r--r--sys/i386/boot/biosboot/boot.c63
-rw-r--r--sys/i386/boot/biosboot/io.c42
-rw-r--r--sys/i386/boot/biosboot/probe_keyboard.c82
-rw-r--r--sys/i386/boot/biosboot/serial.S198
6 files changed, 472 insertions, 54 deletions
diff --git a/sys/i386/boot/biosboot/Makefile b/sys/i386/boot/biosboot/Makefile
index d147e75..ed1ab3a 100644
--- a/sys/i386/boot/biosboot/Makefile
+++ b/sys/i386/boot/biosboot/Makefile
@@ -1,15 +1,16 @@
-# $Id: Makefile,v 1.22 1994/11/05 21:06:16 ache Exp $
+# $Id: Makefile,v 1.23 1994/12/18 19:14:08 bde Exp $
#
PROG= boot
# Order is very important on the SRCS line for this prog
-SRCS= start.S table.c boot2.S boot.c asm.S bios.S io.c disk.c sys.c
+SRCS= start.S table.c boot2.S boot.c asm.S bios.S serial.S
+SRCS+= probe_keyboard.c io.c disk.c sys.c
BINDIR= /usr/mdec
BINMODE= 444
-CFLAGS= -O -DDO_BAD144 -DBOOTWAIT=${BOOTWAIT}
+CFLAGS= -O2 -DDO_BAD144 -DBOOTWAIT=${BOOTWAIT} -DCOMCONSOLE=0x3F8
CFLAGS+= -DBOOTSEG=${BOOTSEG} -DBOOTSTACK=${BOOTSTACK}
-CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../..
+CFLAGS+= -I${.CURDIR} -I${.CURDIR}/../.. -DRB_SERIAL=0x1000
CLEANFILES+= boot.nohdr boot.strip boot1 boot2
DPADD= ${LIBC}
LDFLAGS+= -N -T 0 -nostdlib
diff --git a/sys/i386/boot/biosboot/README.serial b/sys/i386/boot/biosboot/README.serial
new file mode 100644
index 0000000..c4c34dc
--- /dev/null
+++ b/sys/i386/boot/biosboot/README.serial
@@ -0,0 +1,132 @@
+ $Id$
+ SERIAL CONSOLE USAGE NOTES
+ Bill Paul (wpaul@ctr.columbia.edu)
+
+The FreeBSD boot block can now be used to boot FreeBSD on a system with
+only a dumb terminal on a serial port (COM1) as a console. This feature
+is provided for the benefit of people who wish to install FreeBSD on
+dedicated file/compute/terminal server machines that have no keyboard
+(or monitor) attached, just as is possible with Sun workstations and
+servers. People who don't need this extra functionality shouldn't notice
+the changes at all (unless I've screwed something up horribly).
+
+Note that 'options COMCONSOLE' can still be used to force the kernel to
+boot in 'serial console' mode regardless of what boot options you use.
+
+To boot FreeBSD in serial console mode, you must to the following:
+
+- Unplug your keyboard. Most PC systems probe for the keyboard during the
+ Power-On Self-Test (POST) and will generate an error if the keyboard
+ isn't detected. Additionally, many machines will pause the boot process
+ and wait for you to reattach the keyboard and press a key before
+ proceeding any further. If your computer complains about the lack of a
+ keyboard but boots anyway, then you don't have to do anything special.
+ (One machine with a PHOENIX BIOS that I have here merely says 'Keyboard
+ failed' then continues to boot normally.) If your machine complains
+ loudly about the lack of a keyboard and won't continue to boot until you
+ plug it back in, you'll have to go into your CMOS configuration menu and
+ change the 'Keyboard' setting to 'Not installed' in order to bypass the
+ keyboard probe.
+
+ NOTE: Setting the keyboard to 'Not installed' in the CMOS configuration
+ does *NOT* mean that you won't be able to use your keyboard. All this
+ does is tell the BIOS not to probe for a keyboard at power-on so that
+ it won't bitch and moan if the keyboard isn't plugged in. You can leave the
+ keyboard plugged in even with this flag set to 'Not installed' and the
+ keyboard will still work. I repeat: changing the CMOS 'keyboard' setting
+ to 'Not installed' only disables the BIOS's keyboard probe; it does
+ *NOT* actually disable the keyboard.
+
+- Plug a dumb terminal into COM1. If you don't have a dumb terminal, you
+ can use an old PC/XT with a modem program, or the serial port on
+ another UNIX box. If you don't have a COM1, get one. At this time,
+ there is no way to select a port other than COM1 without recompiling
+ both the kernel and the boot blocks. If you're already using COM1 for
+ another device, you'll have to temporarily remove that device and
+ install a new boot block and kernel once you get FreeBSD up and running.
+ (It is assumed that COM1 will be available on a file/compute/terminal
+ server anyway; if you really need COM1 for something else (and you can't
+ switch it to COM2), then you probably shouldn't even be bothering with
+ all this.)
+
+ The serial port settings are hardcoded to 9600 baud, 8 bits, no parity,
+ 1 stop bit.
+
+ NOTE: in addition to a serial cable, you will need a null modem adapter
+ in order to connect the terminal to the PC's serial port. If you don't
+ have one, go to Radio Shack and buy one: they're cheap.
+
+- Boot the machine. The boot block will probe for a keyboard on your
+ system. If it fails to find one, you'll see a prompt appear on the
+ terminal that looks like this:
+
+ No keyboard found.
+
+ >> FreeBSD BOOT @ 0x10000: 640/7168 k of memory
+ Use hd(1,a)/kernel to boot sd0 when wd0 is also installed.
+ Usage: [[[fd(0,a)]/kernel][-s][-r][-a][-c][-d][-b][-v][-h]]
+ Use ? for file list or simply press Return for defaults
+ Boot:
+
+ This is identical to the prompt that normally appears on the VGA console,
+ except for the 'No keyboard found' message that indicates a keyboard
+ couldn't be detected. (If a keyboard is detected, the boot prompt will
+ appear on the VGA display as usual.)
+
+ From here you can boot the system (or let it autoboot by itself) just
+ like you can from the VGA console and the kernel will automatically
+ use COM1 as the console device. No recompilation or 'options COMCONSOLE'
+ is required. This is done by passing a special flag to the kernel in
+ the 'boothowto' word. (The curious can refer to <sys/reboot.h> and the
+ sio driver sources for details.)
+
+- You will notice that there's a new boot flag: -h. You can use this to
+ force the kernel to switch console devices. For instance, if you boot
+ from the VGA console, you can use -h to force the kernel to use the
+ serial port as its console device. Alternatively, if you boot from
+ the serial port, using -h will force the kernel to use the VGA display
+ as the console instead. (Can you say 'toggle' boys and girls? I knew
+ you could. Now try saying 'XOR.')
+
+CAVEATS:
+
+- The idea here is to allow people to set up dedicated servers that require
+ no graphics hardware or attached keyboards. Unfortunately, while (most?)
+ every system will let you boot without a keyboard, there are quite a few
+ that will not let you boot without a graphics adapter. Machines with
+ AMI BIOSes can be configured to boot with no graphics adapter installed
+ simply by changing the 'graphics adapter' setting in the CMOS configuration
+ to 'Not installed.' However, many machines do not support this option
+ and will refuse to boot if you have no display hardware installed. With
+ these machines, you'll have to leave some kind of graphics card installed,
+ (even if it's just a junky mono board) although you won't have to plug a
+ monitor into it. You might also try installing an AMI BIOS. :)
+
+- Using a port other than COM1 as the console requires some recompiling.
+ Again, it's usually assumed that COM1 will be available for use as a
+ console device on a dedicated file/compute/terminal server, so hopefully
+ you'll never have to do this. But if you feel you must change the console
+ to a different port, here's how:
+
+ o Get the kerndist kernel source package.
+ o Edit /sys/i386/boot/biosboot/Makefile and set COMCONSOLE to the
+ address of the port you want to use (0x3F8, 0x2E8, 0x3E8 or
+ 0x2E8). Only COM1 through COM4 can be used; multiport serial
+ cards will not work. No interrupt setting is needed.
+ o Create a custom kernel configuration file and add the following
+ lines:
+
+ options "CONADDR=0x3F8"
+ options "CONUNIT=0"
+
+ Set CONADDR to the same address that you selected for COMCONSOLE
+ in the bootbios Makefile. Set CONUNIT to the unit number of the
+ serial port that this address corresponds to (0 = sio0, 1 = sio1,
+ etc). This implies that the serial port you want to use must be
+ configured into the kernel in the normal way first. I'm not
+ going to list all the possible combinations here; just use your
+ head and you should be okay.
+ o Recompile both the boot blocks and the kernel.
+ o Install the boot blocks with the disklabel command and boot
+ from the new kernel.
+
diff --git a/sys/i386/boot/biosboot/boot.c b/sys/i386/boot/biosboot/boot.c
index 290ec31..a9a31ee 100644
--- a/sys/i386/boot/biosboot/boot.c
+++ b/sys/i386/boot/biosboot/boot.c
@@ -24,7 +24,7 @@
* the rights to redistribute these changes.
*
* from: Mach, [92/04/03 16:51:14 rvb]
- * $Id: boot.c,v 1.28 1994/12/18 19:14:13 bde Exp $
+ * $Id: boot.c,v 1.29 1994/12/18 20:30:10 joerg Exp $
*/
@@ -59,52 +59,47 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
struct exec head;
struct bootinfo_t bootinfo;
-char *name;
-char *names[] = {
- "/kernel"
-};
-#define NUMNAMES (sizeof(names)/sizeof(char *))
+char *name = { "/kernel" };
-#ifdef COMCONSOLE
extern void init_serial(void);
-#endif
+extern int probe_keyboard(void);
+int loadflags = 0;
extern int end;
boot(drive)
int drive;
{
- int loadflags, currname = 0, ret;
+ int ret;
char *t;
-#ifdef COMCONSOLE
- init_serial();
-#endif
-
+ if (probe_keyboard()) {
+ init_serial();
+ loadflags |= RB_SERIAL;
+ printf ("\nNo keyboard found.\n");
+ }
+
/* Pick up the story from the Bios on geometry of disks */
for(ret = 0; ret < N_BIOS_GEOM; ret ++)
bootinfo.bios_geom[ret] = get_diskinfo(ret + 0x80);
- printf("\n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory\n",
- ouraddr, memsize(0), memsize(1));
- printf("Use hd(1,a)/kernel to boot sd0 when wd0 is also installed.\n");
- printf("Usage: [[[%s(0,a)]%s][-s][-r][-a][-c][-d][-b][-v]]\n",
- devs[(drive & 0x80) ? 0 : 2], names[0]);
- printf("Use ? for file list or simply press Return for defaults\n");
+ /* This is nasty, but why use 4 printf()s when 1 will do. */
+
+ printf("\n>> FreeBSD BOOT @ 0x%x: %d/%d k of memory\nUse hd(1,a)/kernel to boot sd0 when wd0 is also installed.\nUsage: [[[%s(%d,a)]%s][-s][-r][-a][-c][-d][-b][-v][-h]]\nUse ? for file list or simply press Return for defaults\n", ouraddr, memsize(0), memsize(1), devs[(drive & 0x80) ? 0 : 2],
+ (unit = (drive & 0x7f)), name);
+
gateA20();
+
loadstart:
/***************************************************************\
* As a default set it to the first partition of the first *
* floppy or hard drive *
\***************************************************************/
- part = unit = 0;
+
+ part = 0;
maj = (drive&0x80 ? 0 : 2); /* a good first bet */
- name = names[currname++];
- loadflags = 0;
- if (currname == NUMNAMES)
- currname = 0;
- printf("Boot: ");
+ printf ("Boot: ");
getbootdev(&loadflags);
ret = openrd();
if (ret != 0) {
@@ -147,6 +142,12 @@ loadprog(howto)
, 'a'+part
, name
, addr);
+/*
+ * With the current scheme of things, addr can never be less than ouraddr,
+ * so this next bit of code is largely irrelevant. Taking it out saves lots
+ * of space.
+ */
+#ifdef REDUNDANT
if(addr < ouraddr)
{
if((addr + head.a_text + head.a_data) > ouraddr)
@@ -160,6 +161,7 @@ loadprog(howto)
return;
}
}
+#endif
printf("text=0x%x ", head.a_text);
/********************************************************/
/* LOAD THE TEXT SEGMENT */
@@ -185,6 +187,11 @@ loadprog(howto)
/* (but clear it) */
/********************************************************/
printf("bss=0x%x ", head.a_bss);
+
+/*
+ * This doesn't do us any good anymore either.
+ */
+#ifdef REDUNDANT
if( (addr < ouraddr) && ((addr + head.a_bss) > ouraddr))
{
pbzero(addr,ouraddr - (int)addr);
@@ -194,7 +201,9 @@ loadprog(howto)
pbzero(addr,head.a_bss);
}
addr += head.a_bss;
-
+#else
+ pbzero(addr,head.a_bss);
+#endif
#ifdef LOADSYMS /* not yet, haven't worked this out yet */
if (addr > 0x100000)
{
@@ -286,6 +295,8 @@ getbootdev(howto)
*howto |= RB_HALT; continue;
case 'v':
*howto |= RB_VERBOSE; continue;
+ case 'h':
+ *howto ^= RB_SERIAL; continue;
}
else {
name = ptr;
diff --git a/sys/i386/boot/biosboot/io.c b/sys/i386/boot/biosboot/io.c
index 25dc322..7932385 100644
--- a/sys/i386/boot/biosboot/io.c
+++ b/sys/i386/boot/biosboot/io.c
@@ -1,4 +1,3 @@
-
/*
* Mach Operating System
* Copyright (c) 1992, 1991 Carnegie Mellon University
@@ -25,10 +24,11 @@
* the rights to redistribute these changes.
*
* from: Mach, Revision 2.2 92/04/04 11:35:57 rpd
- * $Id: io.c,v 1.9 1994/09/20 22:24:59 adam Exp $
+ * $Id: io.c,v 1.10 1994/11/07 11:26:29 davidg Exp $
*/
#include <machine/cpufunc.h>
+#include <sys/reboot.h>
#define K_RDWR 0x60 /* keyboard data & cmds (read/write) */
#define K_STATUS 0x64 /* keyboard status */
@@ -44,6 +44,8 @@
enable data line
enable clock line */
+extern int loadflags;
+
/*
* Gate A20 for high memory
*/
@@ -73,7 +75,6 @@ printf(format,data)
int *dataptr = &data;
char c;
- reset_twiddle();
while (c = *format++)
if (c != '%')
putchar(c);
@@ -119,9 +120,12 @@ printf(format,data)
putchar(c)
{
- if (c == '\n')
- putc('\r');
- putc(c);
+ if (c == '\n') {
+ if (loadflags & RB_SERIAL) serial_putc('\r');
+ else putc('\r');
+ }
+ if (loadflags & RB_SERIAL) serial_putc(c);
+ else putc(c);
}
getchar(in_buf)
@@ -130,7 +134,7 @@ getchar(in_buf)
int c;
loop:
- if ((c=getc()) == '\r')
+ if ((c = ((loadflags & RB_SERIAL) ? serial_getc(c) : getc(c))) == '\r')
c = '\n';
if (c == '\b') {
if (in_buf != 0) {
@@ -173,7 +177,7 @@ char *buf;
#if BOOTWAIT
for (i = BOOTWAIT; i>0; delay1ms(),i--)
#endif
- if (ischar())
+ if ((loadflags & RB_SERIAL) ? serial_ischar() : ischar())
for (;;)
switch(*ptr = getchar(ptr - buf) & 0xff) {
case '\n':
@@ -186,6 +190,7 @@ char *buf;
default:
ptr++;
}
+
return 0;
}
@@ -208,24 +213,13 @@ int len;
*to++ = *from++;
}
-static int tw_on;
-static int tw_pos;
-static char tw_chars[] = "|/-\\";
+/* To quote Ken: "You are not expected to understand this." :) */
-reset_twiddle()
-{
- if (tw_on)
- putchar('\b');
- tw_on = 0;
- tw_pos = 0;
-}
+static unsigned long tw_chars = 0x5C2D2F7C; /* "\-/|" */
twiddle()
{
- if (tw_on)
- putchar('\b');
- else
- tw_on = 1;
- putchar(tw_chars[tw_pos++]);
- tw_pos %= (sizeof(tw_chars) - 1);
+ putchar((char)tw_chars);
+ tw_chars = (tw_chars >> 8) | ((tw_chars & (unsigned long)0xFF) << 24);
+ putchar('\b');
}
diff --git a/sys/i386/boot/biosboot/probe_keyboard.c b/sys/i386/boot/biosboot/probe_keyboard.c
new file mode 100644
index 0000000..694db14
--- /dev/null
+++ b/sys/i386/boot/biosboot/probe_keyboard.c
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 1992-1995 Søren Schmidt
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz and Don Ahn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in this position and unchanged.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This is a modified version of the keyboard reset code used in syscons.
+ * If the keyboard reset fails, we assume that the keyboard has been
+ * unplugged and we use a serial port (COM1) as the console instead.
+ * Returns 1 on failure (no keyboard), 0 on success (keyboard attached).
+ *
+ * This grody hack brought to you by Bill Paul (wpaul@ctr.columbia.edu)
+ *
+ * $Id$
+ */
+
+#include <machine/console.h>
+#include <machine/cpufunc.h>
+
+#ifdef BOOTWAIT
+extern int delay1ms(void);
+#else
+int delay1ms()
+{
+ int i = 800;
+ while (--i >= 0)
+ (void)inb(0x84);
+}
+#endif
+
+int
+probe_keyboard(void)
+{
+ int i, retries = 5;
+ unsigned char val;
+
+ /* Try to reset keyboard hardware */
+ while (retries--) {
+ outb(KB_DATA, KB_RESET);
+ for (i=0; i<100000; i++) {
+ delay1ms();
+ val = inb(KB_DATA);
+ if (val == KB_ACK || val == KB_ECHO)
+ return(0);
+ if (val == KB_RESEND)
+ return (1);
+ }
+ }
+
+ return (0);
+}
diff --git a/sys/i386/boot/biosboot/serial.S b/sys/i386/boot/biosboot/serial.S
new file mode 100644
index 0000000..34d0528
--- /dev/null
+++ b/sys/i386/boot/biosboot/serial.S
@@ -0,0 +1,198 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ *
+ * from: Mach, Revision 2.2 92/04/04 11:34:26 rpd
+ * $Id: bios.S,v 1.1 1994/12/18 20:12:08 joerg Exp $
+ */
+
+/*
+ Copyright 1988, 1989, 1990, 1991, 1992
+ by Intel Corporation, Santa Clara, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+ * Serial bootblock interface routines
+ * Copyright (c) 1994, J"org Wunsch
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. THE AUTHOR DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ */
+
+ .file "serial.s"
+
+#include "asm.h"
+ .text
+
+/*
+ * The serial port interface routines implement a simple polled i/o
+ * interface to a standard serial port. Due to the space restrictions
+ * for the boot blocks, no BIOS support is used (since BIOS requires
+ * expensive real/protected mode switches), instead the rudimentary
+ * BIOS support is duplicated here.
+ *
+ * The base address for the i/o port is passed from the Makefile in
+ * the COMCONSOLE preprocessor macro. Console parameters are currently
+ * hard-coded to 9600 Bd, 8 bit. This can be changed in the
+ * init_serial() function.
+ */
+
+/*
+ * void serial_putc(char ch)
+ * send ch to serial port
+ *
+ */
+
+ENTRY(serial_putc)
+ push %ebp
+ mov %esp, %ebp
+ push %edx
+
+ mov $COMCONSOLE + 5, %edx # line status reg
+1: inb %dx, %al
+ test $0x20, %al
+ jz 1b # TX buffer not empty
+
+ movb 0x8(%ebp), %al
+
+ sub $5, %edx # TX output reg
+ outb %al, %dx # send this one
+
+ pop %edx
+ pop %ebp
+ ret
+
+/*
+ * int serial_getc(void)
+ * read a character from serial port
+ */
+
+ENTRY(serial_getc)
+ push %ebp
+ mov %esp, %ebp
+ push %edx
+
+ mov $COMCONSOLE + 5, %edx # line status reg
+1:
+ inb %dx, %al
+ testb $0x01, %al
+ jz 1b # no RX char available
+
+ xor %eax, %eax
+ sub $5, %edx # RX buffer reg
+ inb %dx, %al # fetch (first) character
+
+ cmp $0x7F, %eax # make DEL...
+ jne 2f
+ mov $0x08, %eax # look like BS
+2:
+ pop %edx
+ pop %ebp
+ ret
+
+/*
+ * int serial_ischar(void)
+ * if there is a character pending, return true; otherwise return 0
+ */
+ENTRY(serial_ischar)
+ push %ebp
+ mov %esp, %ebp
+ push %edx
+
+ xorl %eax, %eax
+ mov $COMCONSOLE + 5, %edx # line status reg
+ inb %dx, %al
+ andb $0x01, %al # RX char available?
+
+ pop %edx
+ pop %ebp
+ ret
+
+/*
+ * void init_serial(void)
+ * initialize the serial console port to 9600 Bd, 8 bpc
+ */
+ENTRY(init_serial)
+ push %ebp
+ mov %esp, %ebp
+ push %edx
+
+ mov $COMCONSOLE + 3, %edx # line control reg
+ movb $0x80, %al
+ outb %al, %dx # enable DLAB
+
+ sub $3, %edx # divisor latch, low byte
+ mov $12, %ax # divisor 12: 9600 Bd
+ outb %al, %dx
+ inc %edx # divisor latch, high byte
+ movb %ah, %al
+ outb %al, %dx
+
+ add $2, %edx # line control reg
+ movb $0x13, %al
+ outb %al, %dx # 8 bit, no parity, 1 stop bit
+
+ inc %edx # modem control reg
+ mov $3, %al
+ outb %al, %dx # enable DTR/RTS
+
+ /* now finally, flush the input buffer */
+ inc %edx # line status reg
+1:
+ inb %dx, %al
+ testb $0x01, %al
+ jz 2f # no more characters buffered
+ sub $5, %edx # rx buffer reg
+ inb %dx, %al # throw away
+ add $5, %edx
+ jmp 1b
+2:
+ pop %edx
+ pop %ebp
+ ret
OpenPOWER on IntegriCloud