diff options
-rw-r--r-- | usr/src/grub/grub-0.97/stage2/builtins.c | 92 | ||||
-rw-r--r-- | usr/src/grub/grub-0.97/stage2/serial.c | 14 | ||||
-rw-r--r-- | usr/src/grub/grub-0.97/stage2/serial.h | 6 |
3 files changed, 89 insertions, 23 deletions
diff --git a/usr/src/grub/grub-0.97/stage2/builtins.c b/usr/src/grub/grub-0.97/stage2/builtins.c index 17eb542a1e..c67ed4bc9b 100644 --- a/usr/src/grub/grub-0.97/stage2/builtins.c +++ b/usr/src/grub/grub-0.97/stage2/builtins.c @@ -4045,12 +4045,20 @@ static struct builtin builtin_savedefault = static int serial_func (char *arg, int flags) { - unsigned short port = serial_hw_get_port (0); + int i; + int units[SERIAL_MAX_PORTS]; + unsigned short ports[SERIAL_MAX_PORTS]; unsigned int speed = 9600; int word_len = UART_8BITS_WORD; int parity = UART_NO_PARITY; int stop_bit_len = UART_1_STOP_BIT; + for (i = 0; i < SERIAL_MAX_PORTS; ++i) + { + units[i] = -1; + ports[i] = 0; + } + /* Process GNU-style long options. FIXME: We should implement a getopt-like function, to avoid duplications. */ @@ -4060,17 +4068,28 @@ serial_func (char *arg, int flags) { char *p = arg + sizeof ("--unit=") - 1; int unit; - - if (! safe_parse_maxint (&p, &unit)) - return 1; - - if (unit < 0 || unit > 3) + + i = 0; + do { - errnum = ERR_DEV_VALUES; - return 1; - } + if (i >= SERIAL_MAX_PORTS) + { + errnum = ERR_DEV_FORMAT; + return 1; + } + + if (! safe_parse_maxint (&p, &unit)) + return 1; + + if (unit < 0 || unit > 3) + { + errnum = ERR_DEV_VALUES; + return 1; + } - port = serial_hw_get_port (unit); + units[i++] = unit; + } + while (*p++ == ','); } else if (grub_memcmp (arg, "--speed=", sizeof ("--speed=") - 1) == 0) { @@ -4086,11 +4105,28 @@ serial_func (char *arg, int flags) { char *p = arg + sizeof ("--port=") - 1; int num; - - if (! safe_parse_maxint (&p, &num)) - return 1; - port = (unsigned short) num; + i = 0; + do + { + if (i >= SERIAL_MAX_PORTS) + { + errnum = ERR_DEV_FORMAT; + return 1; + } + + if (! safe_parse_maxint (&p, &num)) + return 1; + + if (num > 0xffff || num <= 0) + { + errnum = ERR_DEV_VALUES; + return 1; + } + + ports[i++] = (unsigned short) num; + } + while (*p++ == ','); } else if (grub_memcmp (arg, "--word=", sizeof ("--word=") - 1) == 0) { @@ -4166,8 +4202,21 @@ serial_func (char *arg, int flags) arg = skip_to (0, arg); } - /* Initialize the serial unit. */ - if (! serial_hw_init (port, speed, word_len, parity, stop_bit_len)) + if (units[0] == -1 && ports[0] == 0) + units[0] = 0; + + for (i = 0; i < SERIAL_MAX_PORTS; ++i) + { + if (units[i] != -1) + ports[i] = serial_hw_get_port (units[i]); + if (ports[i] == 0) + continue; + + if (serial_hw_init (ports[i], speed, word_len, parity, stop_bit_len)) + break; + } + + if (i >= SERIAL_MAX_PORTS) { errnum = ERR_BAD_ARGUMENT; return 1; @@ -4181,14 +4230,17 @@ static struct builtin builtin_serial = "serial", serial_func, BUILTIN_MENU | BUILTIN_CMDLINE | BUILTIN_HELP_LIST, - "serial [--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] [--parity=PARITY] [--stop=STOP] [--device=DEV]", + "serial [[--unit=UNIT[,UNIT...]] | [--port=PORT[,PORT...]]] [--speed=SPEED] [--word=WORD] [--parity=PARITY] [--stop=STOP] [--device=DEV]", "Initialize a serial device. UNIT is a digit that specifies which serial" - " device is used (e.g. 0 == COM1). If you need to specify the port number," - " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length," + " device is used (e.g. 0 == ttya (aka COM1)). If you need to specify the port" + " number, set it by --port. Either but not both of --unit and --port is" + " permitted; --unit takes precedence. Multiple devices may be specified," + " separated by commas; the first working device in the list will be used" + " and the rest ignored. SPEED is the DTE-DTE speed. WORD is the word length," " PARITY is the type of parity, which is one of `no', `odd' and `even'." " STOP is the length of stop bit(s). The option --device can be used only" " in the grub shell, which specifies the file name of a tty device. The" - " default values are COM1, 9600, 8N1." + " default values are ttya, 9600, 8N1." }; #endif /* SUPPORT_SERIAL */ diff --git a/usr/src/grub/grub-0.97/stage2/serial.c b/usr/src/grub/grub-0.97/stage2/serial.c index 4e120e000d..b9f27bc581 100644 --- a/usr/src/grub/grub-0.97/stage2/serial.c +++ b/usr/src/grub/grub-0.97/stage2/serial.c @@ -141,6 +141,16 @@ serial_hw_init (unsigned short port, unsigned int speed, int i; unsigned short div = 0; unsigned char status = 0; + + if (port == 0) + return 0; + + /* Make sure the port actually exists. */ + outb (port + UART_SR, UART_SR_TEST); + outb (port + UART_FCR, 0); + status = inb (port + UART_SR); + if (status != UART_SR_TEST) + return 0; /* Turn off the interrupt. */ outb (port + UART_IER, 0); @@ -163,7 +173,7 @@ serial_hw_init (unsigned short port, unsigned int speed, outb (port + UART_DLH, div >> 8); /* Set the line status. */ - status |= parity | word_len | stop_bit_len; + status = parity | word_len | stop_bit_len; outb (port + UART_LCR, status); /* Enable the FIFO. */ @@ -186,8 +196,6 @@ serial_hw_init (unsigned short port, unsigned int speed, { term_table[i].flags &= ~TERM_NEED_INIT; } - - /* FIXME: should check if the serial terminal was found. */ return 1; } diff --git a/usr/src/grub/grub-0.97/stage2/serial.h b/usr/src/grub/grub-0.97/stage2/serial.h index 76c222720d..19f7be6e63 100644 --- a/usr/src/grub/grub-0.97/stage2/serial.h +++ b/usr/src/grub/grub-0.97/stage2/serial.h @@ -23,6 +23,9 @@ /* Macros. */ +/* The maximum number of ports we ever try to use. */ +#define SERIAL_MAX_PORTS 4 + /* The offsets of UART registers. */ #define UART_TX 0 #define UART_RX 0 @@ -65,6 +68,9 @@ /* Turn on DTR, RTS, and OUT2. */ #define UART_ENABLE_MODEM 0x0B +/* Arbitrary pattern to write during existence testing. */ +#define UART_SR_TEST 0x4F + /* Function prototypes. */ |