diff options
author | wpaul <wpaul@FreeBSD.org> | 1995-01-20 07:48:27 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 1995-01-20 07:48:27 +0000 |
commit | 1875d75ad14b7e1e30810e2caa90e11f404fd9f2 (patch) | |
tree | a551b89627e6c0f432e7ce4339805e8d158a7ec7 /sys | |
parent | 7a6a5253caf293944cabff9f7679f6bf2d51b9dd (diff) | |
download | FreeBSD-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/Makefile | 9 | ||||
-rw-r--r-- | sys/i386/boot/biosboot/README.serial | 132 | ||||
-rw-r--r-- | sys/i386/boot/biosboot/boot.c | 63 | ||||
-rw-r--r-- | sys/i386/boot/biosboot/io.c | 42 | ||||
-rw-r--r-- | sys/i386/boot/biosboot/probe_keyboard.c | 82 | ||||
-rw-r--r-- | sys/i386/boot/biosboot/serial.S | 198 |
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 |