diff --git a/ChangeLog b/ChangeLog index 2c47f8aa0..261623b2b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,18 @@ +2000-08-12 OKUJI Yoshinori + + Add a serial device driver (but only the driver). + + * stage2/serial.c: New file. + * stage2/serial.h: Likewise. + * stage2/shared.h (serial_getkey): Moved to stage2/serial.h. + (serial_checkkey): Likewise. + (serial_putchar): Likewise. + * stage2/Makefile.am (noinst_HEADERS): Added serial.h. + (pre_stage2_exec_SOURCES): Added serial.c. + 2000-08-10 Pavel Roskin - * docs/tutorial.texi: minor fixes + * docs/tutorial.texi: Minor fixes. 2000-08-10 OKUJI Yoshinori diff --git a/stage2/Makefile.am b/stage2/Makefile.am index 1be8ecc75..25f64732f 100644 --- a/stage2/Makefile.am +++ b/stage2/Makefile.am @@ -5,7 +5,8 @@ noinst_SCRIPTS = $(TESTS) # For dist target. noinst_HEADERS = apic.h defs.h dir.h disk_inode.h disk_inode_ffs.h \ fat.h filesys.h freebsd.h fs.h i386-elf.h imgact_aout.h \ - mb_header.h mb_info.h pc_slice.h shared.h smp-imps.h nbi.h + mb_header.h mb_info.h pc_slice.h serial.h shared.h smp-imps.h \ + nbi.h EXTRA_DIST = $(noinst_SCRIPTS) # For . @@ -59,8 +60,8 @@ STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1 # For stage2 target. pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c common.c \ char_io.c cmdline.c disk_io.c gunzip.c fsys_ext2fs.c \ - fsys_fat.c fsys_ffs.c fsys_minix.c fsys_reiserfs.c smp-imps.c \ - stage2.c + fsys_fat.c fsys_ffs.c fsys_minix.c fsys_reiserfs.c serial.c \ + smp-imps.c stage2.c pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK) diff --git a/stage2/Makefile.in b/stage2/Makefile.in index 932ca5206..4bbcf4da5 100644 --- a/stage2/Makefile.in +++ b/stage2/Makefile.in @@ -93,7 +93,8 @@ noinst_SCRIPTS = $(TESTS) # For dist target. noinst_HEADERS = apic.h defs.h dir.h disk_inode.h disk_inode_ffs.h \ fat.h filesys.h freebsd.h fs.h i386-elf.h imgact_aout.h \ - mb_header.h mb_info.h pc_slice.h shared.h smp-imps.h nbi.h + mb_header.h mb_info.h pc_slice.h serial.h shared.h smp-imps.h \ + nbi.h EXTRA_DIST = $(noinst_SCRIPTS) @@ -143,8 +144,8 @@ STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1 # For stage2 target. pre_stage2_exec_SOURCES = asm.S bios.c boot.c builtins.c common.c \ char_io.c cmdline.c disk_io.c gunzip.c fsys_ext2fs.c \ - fsys_fat.c fsys_ffs.c fsys_minix.c fsys_reiserfs.c smp-imps.c \ - stage2.c + fsys_fat.c fsys_ffs.c fsys_minix.c fsys_reiserfs.c serial.c \ + smp-imps.c stage2.c pre_stage2_exec_CFLAGS = $(STAGE2_COMPILE) $(FSYS_CFLAGS) pre_stage2_exec_LDFLAGS = $(PRE_STAGE2_LINK) @@ -250,7 +251,7 @@ diskless_exec-char_io.o diskless_exec-cmdline.o diskless_exec-disk_io.o \ diskless_exec-gunzip.o diskless_exec-fsys_ext2fs.o \ diskless_exec-fsys_fat.o diskless_exec-fsys_ffs.o \ diskless_exec-fsys_minix.o diskless_exec-fsys_reiserfs.o \ -diskless_exec-smp-imps.o diskless_exec-stage2.o +diskless_exec-serial.o diskless_exec-smp-imps.o diskless_exec-stage2.o diskless_exec_OBJECTS = $(am_diskless_exec_OBJECTS) diskless_exec_DEPENDENCIES = ../netboot/libdrivers.a am_e2fs_stage1_5_exec_OBJECTS = e2fs_stage1_5_exec-start.o \ @@ -296,8 +297,8 @@ pre_stage2_exec-char_io.o pre_stage2_exec-cmdline.o \ pre_stage2_exec-disk_io.o pre_stage2_exec-gunzip.o \ pre_stage2_exec-fsys_ext2fs.o pre_stage2_exec-fsys_fat.o \ pre_stage2_exec-fsys_ffs.o pre_stage2_exec-fsys_minix.o \ -pre_stage2_exec-fsys_reiserfs.o pre_stage2_exec-smp-imps.o \ -pre_stage2_exec-stage2.o +pre_stage2_exec-fsys_reiserfs.o pre_stage2_exec-serial.o \ +pre_stage2_exec-smp-imps.o pre_stage2_exec-stage2.o pre_stage2_exec_OBJECTS = $(am_pre_stage2_exec_OBJECTS) @NETBOOT_SUPPORT_TRUE@pre_stage2_exec_DEPENDENCIES = \ @NETBOOT_SUPPORT_TRUE@../netboot/libdrivers.a @@ -343,8 +344,9 @@ $(DEPDIR)/diskless_exec-fsys_ext2fs.Po \ $(DEPDIR)/diskless_exec-fsys_fat.Po $(DEPDIR)/diskless_exec-fsys_ffs.Po \ $(DEPDIR)/diskless_exec-fsys_minix.Po \ $(DEPDIR)/diskless_exec-fsys_reiserfs.Po \ -$(DEPDIR)/diskless_exec-gunzip.Po $(DEPDIR)/diskless_exec-smp-imps.Po \ -$(DEPDIR)/diskless_exec-stage2.Po $(DEPDIR)/e2fs_stage1_5_exec-asm.Po \ +$(DEPDIR)/diskless_exec-gunzip.Po $(DEPDIR)/diskless_exec-serial.Po \ +$(DEPDIR)/diskless_exec-smp-imps.Po $(DEPDIR)/diskless_exec-stage2.Po \ +$(DEPDIR)/e2fs_stage1_5_exec-asm.Po \ $(DEPDIR)/e2fs_stage1_5_exec-bios.Po \ $(DEPDIR)/e2fs_stage1_5_exec-char_io.Po \ $(DEPDIR)/e2fs_stage1_5_exec-common.Po \ @@ -392,7 +394,7 @@ $(DEPDIR)/pre_stage2_exec-fsys_fat.Po \ $(DEPDIR)/pre_stage2_exec-fsys_ffs.Po \ $(DEPDIR)/pre_stage2_exec-fsys_minix.Po \ $(DEPDIR)/pre_stage2_exec-fsys_reiserfs.Po \ -$(DEPDIR)/pre_stage2_exec-gunzip.Po \ +$(DEPDIR)/pre_stage2_exec-gunzip.Po $(DEPDIR)/pre_stage2_exec-serial.Po \ $(DEPDIR)/pre_stage2_exec-smp-imps.Po \ $(DEPDIR)/pre_stage2_exec-stage2.Po \ $(DEPDIR)/pxeloader_exec-pxeloader.Po \ @@ -484,6 +486,7 @@ diskless_exec-fsys_fat.o: fsys_fat.c diskless_exec-fsys_ffs.o: fsys_ffs.c diskless_exec-fsys_minix.o: fsys_minix.c diskless_exec-fsys_reiserfs.o: fsys_reiserfs.c +diskless_exec-serial.o: serial.c diskless_exec-smp-imps.o: smp-imps.c diskless_exec-stage2.o: stage2.c @@ -567,6 +570,7 @@ pre_stage2_exec-fsys_fat.o: fsys_fat.c pre_stage2_exec-fsys_ffs.o: fsys_ffs.c pre_stage2_exec-fsys_minix.o: fsys_minix.c pre_stage2_exec-fsys_reiserfs.o: fsys_reiserfs.c +pre_stage2_exec-serial.o: serial.c pre_stage2_exec-smp-imps.o: smp-imps.c pre_stage2_exec-stage2.o: stage2.c @@ -667,6 +671,7 @@ maintainer-clean-tags: @AMDEP@include $(DEPDIR)/diskless_exec-fsys_minix.Po @AMDEP@include $(DEPDIR)/diskless_exec-fsys_reiserfs.Po @AMDEP@include $(DEPDIR)/diskless_exec-gunzip.Po +@AMDEP@include $(DEPDIR)/diskless_exec-serial.Po @AMDEP@include $(DEPDIR)/diskless_exec-smp-imps.Po @AMDEP@include $(DEPDIR)/diskless_exec-stage2.Po @AMDEP@include $(DEPDIR)/e2fs_stage1_5_exec-asm.Po @@ -729,6 +734,7 @@ maintainer-clean-tags: @AMDEP@include $(DEPDIR)/pre_stage2_exec-fsys_minix.Po @AMDEP@include $(DEPDIR)/pre_stage2_exec-fsys_reiserfs.Po @AMDEP@include $(DEPDIR)/pre_stage2_exec-gunzip.Po +@AMDEP@include $(DEPDIR)/pre_stage2_exec-serial.Po @AMDEP@include $(DEPDIR)/pre_stage2_exec-smp-imps.Po @AMDEP@include $(DEPDIR)/pre_stage2_exec-stage2.Po @AMDEP@include $(DEPDIR)/pxeloader_exec-pxeloader.Po @@ -970,6 +976,14 @@ diskless_exec-fsys_reiserfs.o: fsys_reiserfs.c @AMDEP@CCDEPMODE = @CCDEPMODE@ +diskless_exec-serial.o: serial.c +@AMDEP@ source='serial.c' object='diskless_exec-serial.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP@ depfile='$(DEPDIR)/diskless_exec-serial.Po' tmpdepfile='$(DEPDIR)/diskless_exec-serial.TPo' @AMDEPBACKSLASH@ +@AMDEP@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(diskless_exec_CFLAGS) $(CFLAGS) -c -o diskless_exec-serial.o `test -f serial.c || echo '$(srcdir)/'`serial.c + +@AMDEP@CCDEPMODE = @CCDEPMODE@ + diskless_exec-smp-imps.o: smp-imps.c @AMDEP@ source='smp-imps.c' object='diskless_exec-smp-imps.o' libtool=no @AMDEPBACKSLASH@ @AMDEP@ depfile='$(DEPDIR)/diskless_exec-smp-imps.Po' tmpdepfile='$(DEPDIR)/diskless_exec-smp-imps.TPo' @AMDEPBACKSLASH@ @@ -1282,6 +1296,14 @@ pre_stage2_exec-fsys_reiserfs.o: fsys_reiserfs.c @AMDEP@CCDEPMODE = @CCDEPMODE@ +pre_stage2_exec-serial.o: serial.c +@AMDEP@ source='serial.c' object='pre_stage2_exec-serial.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP@ depfile='$(DEPDIR)/pre_stage2_exec-serial.Po' tmpdepfile='$(DEPDIR)/pre_stage2_exec-serial.TPo' @AMDEPBACKSLASH@ +@AMDEP@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(pre_stage2_exec_CFLAGS) $(CFLAGS) -c -o pre_stage2_exec-serial.o `test -f serial.c || echo '$(srcdir)/'`serial.c + +@AMDEP@CCDEPMODE = @CCDEPMODE@ + pre_stage2_exec-smp-imps.o: smp-imps.c @AMDEP@ source='smp-imps.c' object='pre_stage2_exec-smp-imps.o' libtool=no @AMDEPBACKSLASH@ @AMDEP@ depfile='$(DEPDIR)/pre_stage2_exec-smp-imps.Po' tmpdepfile='$(DEPDIR)/pre_stage2_exec-smp-imps.TPo' @AMDEPBACKSLASH@ diff --git a/stage2/serial.c b/stage2/serial.c new file mode 100644 index 000000000..99b4ddb01 --- /dev/null +++ b/stage2/serial.c @@ -0,0 +1,170 @@ +/* serial.c - serial device interface */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef SUPPORT_SERIAL + +#include +#include + +/* The structure for speed vs. divisor. */ +struct divisor +{ + int speed; + unsigned short div; +}; + +/* Store the port number of a serial unit. */ +static unsigned short serial_port; + +/* The table which lists common configurations. */ +static struct divisor divisor_tab[] = +{ + { 2400, 0x0030 }, + { 4800, 0x0018 }, + { 9600, 0x000C }, + { 19200, 0x0006 }, + { 38400, 0x0003 }, + { 57600, 0x0002 }, + { 115200, 0x0001 } +}; + + +/* Read a byte from a port. */ +static inline unsigned char +inb (unsigned short port) +{ + unsigned char value; + + asm volatile ("inb %w1, %0" : "=a" (value) : "Nd" (port)); + return value; +} + +/* Write a byte to a port. */ +static inline void +outb (unsigned short port, unsigned char value) +{ + asm volatile ("outb %b0, %w1" : : "a" (value), "Nd" (port)); +} + +/* The serial version of getkey. */ +int +serial_getkey (void) +{ + /* Wait until data is ready. */ + while ((inb (serial_port + UART_LSR) & UART_DATA_READY) == 0) + ; + + /* Read and return the data. */ + return inb (serial_port + UART_RX); +} + +/* The serial version of checkkey. This doesn't return a character code, + but that doesn't matter actually. */ +int +serial_checkkey (void) +{ + unsigned char status; + + status = inb (serial_port + UART_LSR); + return status & UART_DATA_READY ? : -1; +} + +/* The serial version of grub_putchar. */ +void +serial_putchar (int c) +{ + /* Perhaps a timeout is necessary. */ + int timeout = 10000; + + /* Wait until the transmitter holding register is empty. */ + while ((inb (serial_port + UART_LSR) & UART_EMPTY_TRANSMITTER) == 0) + if (--timeout == 0) + /* There is something wrong. But what can I do? */ + return; + + outb (serial_port + UART_TX, c); +} + +/* Return the port number for the UNITth serial device. */ +unsigned short +serial_get_port (int unit) +{ + /* The BIOS data area. */ + const unsigned short *addr = (const unsigned short *) 0x0400; + + return addr[unit]; +} + +/* Initialize a serial device. PORT is the port number for a serial device. + SPEED is a DTE-DTE speed which must be one of these: 2400, 4800, 9600, + 19200, 38400, 57600 and 115200. WORD_LEN is the word length to be used + for the device. Likewise, PARITY is the type of the parity and + STOP_BIT_LEN is the length of the stop bit. The possible values for + WORD_LEN, PARITY and STOP_BIT_LEN are defined in the header file as + macros. */ +int +serial_init (unsigned short port, unsigned int speed, + int word_len, int parity, int stop_bit_len) +{ + int i; + unsigned short div = 0; + unsigned char status = 0; + + /* Turn off the interrupt. */ + outb (port + UART_IER, 0); + + /* Set DLAB. */ + outb (port + UART_LCR, UART_DLAB); + + /* Set the baud rate. */ + for (i = 0; i < sizeof (divisor_tab) / sizeof (divisor_tab[0]); i++) + if (divisor_tab[i].speed == speed) + { + div = divisor_tab[i].div; + break; + } + + if (div == 0) + return 0; + + outb (port + UART_DLL, div & 0xFF); + outb (port + UART_DLH, div >> 8); + + /* Set the line status. */ + status |= parity | word_len | stop_bit_len; + outb (port + UART_LCR, status); + + /* Enable the FIFO. */ + outb (port + UART_FCR, UART_ENABLE_FIFO); + + /* Turn on DTR, RTS, and OUT2. */ + outb (port + UART_MCR, UART_ENABLE_MODEM); + + /* Store the port number. */ + serial_port = port; + + /* Drain the input buffer. */ + while (serial_checkkey () != -1) + (void) serial_getkey (); + + return 1; +} + +#endif /* SUPPORT_SERIAL */ diff --git a/stage2/serial.h b/stage2/serial.h new file mode 100644 index 000000000..9e6bd1f00 --- /dev/null +++ b/stage2/serial.h @@ -0,0 +1,87 @@ +/* serial.h - serial device interface */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef GRUB_SERIAL_HEADER +#define GRUB_SERIAL_HEADER 1 + +/* Macros. */ + +/* The offsets of UART registers. */ +#define UART_TX 0 +#define UART_RX 0 +#define UART_DLL 0 +#define UART_IER 1 +#define UART_DLH 1 +#define UART_IIR 2 +#define UART_FCR 2 +#define UART_LCR 3 +#define UART_MCR 4 +#define UART_LSR 5 +#define UART_MSR 6 +#define UART_SR 7 + +/* For LSR bits. */ +#define UART_DATA_READY 0x01 +#define UART_EMPTY_TRANSMITTER 0x20 + +/* The type of parity. */ +#define UART_NO_PARITY 0x00 +#define UART_ODD_PARITY 0x08 +#define UART_EVEN_PARITY 0x18 + +/* The type of word length. */ +#define UART_5BITS_WORD 0x00 +#define UART_6BITS_WORD 0x01 +#define UART_7BITS_WORD 0x02 +#define UART_8BITS_WORD 0x03 + +/* The type of the length of stop bit. */ +#define UART_1_STOP_BIT 0x00 +#define UART_2_STOP_BITS 0x04 + +/* the switch of DLAB. */ +#define UART_DLAB 0x80 + +/* Enable the FIFO. */ +#define UART_ENABLE_FIFO 0xC7 + +/* Turn on DTR, RTS, and OUT2. */ +#define UART_ENABLE_MODEM 0x0B + + +/* Function prototypes. */ + +/* The serial part of grub_putchar. */ +void serial_putchar (int c); + +/* The serial part of getkey. */ +int serial_getkey (void); + +/* The serial part of checkkey. */ +int serial_checkkey (void); + +/* Return the port number for the UNITth serial device. */ +unsigned short serial_get_port (int unit); + +/* Initialize a serial device. */ +int serial_init (unsigned short port, unsigned int speed, + int word_len, int parity, int stop_bit_len); + +#endif /* ! GRUB_SERIAL_HEADER */ diff --git a/stage2/shared.h b/stage2/shared.h index 6f2e7ecf4..5cf64c25a 100644 --- a/stage2/shared.h +++ b/stage2/shared.h @@ -659,9 +659,6 @@ void grub_putchar (int c); /* The console part of grub_putchar. */ void console_putchar (int c); -/* The serial part of grub_putchar. */ -void serial_putchar (int c); - /* Wait for a keypress, and return its packed BIOS/ASCII key code. Use ASCII_CHAR(ret) to extract the ASCII code. */ int getkey (void); @@ -669,9 +666,6 @@ int getkey (void); /* The console part of getkey. */ int console_getkey (void); -/* The serial part of getkey. */ -int serial_getkey (void); - /* Like GETKEY, but doesn't block, and returns -1 if no keystroke is available. */ int checkkey (void); @@ -679,9 +673,6 @@ int checkkey (void); /* The console part of checkkey. */ int console_checkkey (void); -/* The serial part of checkkey. */ -int serial_checkkey (void); - /* Sets text mode character attribute at the cursor position. See A_* constants defined above. */ void set_attrib (int attr);