/* serial.c - serial device interface */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2000,2001,2002 Free Software Foundation, Inc.
*
* 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 <shared.h>
#include <serial.h>
#include <term.h>
#include <terminfo.h>
/* An input buffer. */
static int npending = 0;
static int serial_x;
static int serial_y;
/* Hardware-dependent definitions. */
#ifndef GRUB_UTIL
/* 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_hw_port = 0;
/* The table which lists common configurations. */
{
{ 2400, 0x0030 },
{ 4800, 0x0018 },
{ 9600, 0x000C },
{ 19200, 0x0006 },
{ 38400, 0x0003 },
{ 57600, 0x0002 },
{ 115200, 0x0001 }
};
/* Read a byte from a port. */
static inline unsigned char
{
unsigned char value;
asm volatile ("outb %%al, $0x80" : : );
return value;
}
/* Write a byte to a port. */
static inline void
{
asm volatile ("outb %%al, $0x80" : : );
}
/* Fetch a key. */
int
serial_hw_fetch (void)
{
return -1;
}
/* Put a chararacter. */
void
serial_hw_put (int c)
{
/* Wait until the transmitter holding register is empty. */
{
if (--timeout == 0)
/* There is something wrong. But what can I do? */
return;
}
}
void
serial_hw_delay (void)
{
outb (0x80, 0);
}
/* Return the port number for the UNITth serial device. */
unsigned short
{
/* The BIOS data area. */
}
/* 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
{
int i;
unsigned short div = 0;
unsigned char status = 0;
/* Turn off the interrupt. */
/* Set DLAB. */
/* Set the baud rate. */
for (i = 0; i < sizeof (divisor_tab) / sizeof (divisor_tab[0]); i++)
{
break;
}
if (div == 0)
return 0;
/* Set the line status. */
/* Enable the FIFO. */
/* Turn on DTR, RTS, and OUT2. */
/* Store the port number. */
/* Drain the input buffer. */
while (serial_checkkey () != -1)
(void) serial_getkey ();
/* Get rid of TERM_NEED_INIT from the serial terminal. */
for (i = 0; term_table[i].name; i++)
{
break;
}
/* FIXME: should check if the serial terminal was found. */
return 1;
}
#endif /* ! GRUB_UTIL */
/* Generic definitions. */
static void
{
const struct
{
char key;
char ascii;
}
three_code_table[] =
{
{'A', 16},
{'B', 14},
{'C', 6},
{'D', 2},
{'F', 5},
{'H', 1},
{'4', 4}
};
const struct
{
short key;
char ascii;
}
four_code_table[] =
{
{('1' | ('~' << 8)), 1},
{('3' | ('~' << 8)), 4},
{('5' | ('~' << 8)), 7},
{('6' | ('~' << 8)), 3},
};
/* The buffer must start with ``ESC [''. */
return;
if (npending >= 3)
{
int i;
for (i = 0;
i < sizeof (three_code_table) / sizeof (three_code_table[0]);
i++)
{
npending -= 2;
return;
}
}
if (npending >= 4)
{
int i;
for (i = 0;
i < sizeof (four_code_table) / sizeof (four_code_table[0]);
i++)
{
npending -= 3;
return;
}
}
}
static
{
int i;
{
int c;
c = serial_hw_fetch ();
if (c >= 0)
{
/* Reset the counter to zero, to wait for the same interval. */
i = 0;
}
if (nowait)
break;
}
/* Translate some key sequences. */
return npending;
}
/* The serial version of getkey. */
int
serial_getkey (void)
{
int c;
while (! fill_input_buf (0))
;
c = input_buf[0];
npending--;
return c;
}
/* The serial version of checkkey. */
int
serial_checkkey (void)
{
if (fill_input_buf (1))
return input_buf[0];
return -1;
}
/* The serial version of grub_putchar. */
void
serial_putchar (int c)
{
/* Keep track of the cursor. */
if (keep_track)
{
/* The serial terminal doesn't have VGA fonts. */
switch (c)
{
case DISP_UL:
c = ACS_ULCORNER;
break;
case DISP_UR:
c = ACS_URCORNER;
break;
case DISP_LL:
c = ACS_LLCORNER;
break;
case DISP_LR:
c = ACS_LRCORNER;
break;
case DISP_HORIZ:
c = ACS_HLINE;
break;
case DISP_VERT:
c = ACS_VLINE;
break;
case DISP_LEFT:
c = ACS_LARROW;
break;
case DISP_RIGHT:
c = ACS_RARROW;
break;
case DISP_UP:
c = ACS_UARROW;
break;
case DISP_DOWN:
c = ACS_DARROW;
break;
default:
break;
}
switch (c)
{
case '\r':
serial_x = 0;
break;
case '\n':
serial_y++;
break;
case '\b':
case 127:
if (serial_x > 0)
serial_x--;
break;
case '\a':
break;
default:
if (serial_x >= 79)
{
serial_putchar ('\r');
serial_putchar ('\n');
}
serial_x++;
break;
}
}
serial_hw_put (c);
}
int
serial_getxy (void)
{
}
void
serial_gotoxy (int x, int y)
{
keep_track = 0;
ti_cursor_address (x, y);
keep_track = 1;
serial_x = x;
serial_y = y;
}
void
serial_cls (void)
{
keep_track = 0;
ti_clear_screen ();
keep_track = 1;
}
void
{
keep_track = 0;
if (state == COLOR_STATE_HIGHLIGHT)
else
keep_track = 1;
}
#endif /* SUPPORT_SERIAL */