X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=qemu%2Froms%2Fipxe%2Fsrc%2Fcore%2Fserial.c;h=4ce025519d90ce0fed24823e389a6ee82ba6450a;hb=437fd90c0250dee670290f9b714253671a990160;hp=7e4460ab95819100cfe206d0e173d3909b30bfcf;hpb=e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb;p=kvmfornfv.git diff --git a/qemu/roms/ipxe/src/core/serial.c b/qemu/roms/ipxe/src/core/serial.c index 7e4460ab9..4ce025519 100644 --- a/qemu/roms/ipxe/src/core/serial.c +++ b/qemu/roms/ipxe/src/core/serial.c @@ -1,259 +1,184 @@ /* - * 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. + * Copyright (C) 2014 Michael Brown . * - * The base address and speed for the i/o port are passed from the - * Makefile in the COMCONSOLE and CONSPEED preprocessor macros. The - * line control parameters are currently hard-coded to 8 bits, no - * parity, 1 stop bit (8N1). This can be changed in init_serial(). + * 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 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. */ -FILE_LICENCE ( GPL2_OR_LATER ); +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +/** @file + * + * Serial console + * + */ -#include "stddef.h" +#include #include -#include -#include +#include +#include #include -#include "config/serial.h" - -/* Set default values if none specified */ +#include +#include -#ifndef COMCONSOLE -#define COMCONSOLE 0x3f8 +/* Set default console usage if applicable */ +#if ! ( defined ( CONSOLE_SERIAL ) && CONSOLE_EXPLICIT ( CONSOLE_SERIAL ) ) +#undef CONSOLE_SERIAL +#define CONSOLE_SERIAL ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG ) #endif -#ifndef COMSPEED -#define COMSPEED 9600 -#endif - -#ifndef COMDATA -#define COMDATA 8 +/* UART port number */ +#ifdef COMCONSOLE +#define CONSOLE_PORT COMCONSOLE +#else +#define CONSOLE_PORT 0 #endif -#ifndef COMPARITY -#define COMPARITY 0 +/* UART baud rate */ +#ifdef COMPRESERVE +#define CONSOLE_BAUD 0 +#else +#define CONSOLE_BAUD COMSPEED #endif -#ifndef COMSTOP -#define COMSTOP 1 +/* UART line control register value */ +#ifdef COMPRESERVE +#define CONSOLE_LCR 0 +#else +#define CONSOLE_LCR UART_LCR_WPS ( COMDATA, COMPARITY, COMSTOP ) #endif -#undef UART_BASE -#define UART_BASE ( COMCONSOLE ) - -#undef UART_BAUD -#define UART_BAUD ( COMSPEED ) +/** Serial console UART */ +struct uart serial_console; -#if ((115200%UART_BAUD) != 0) -#error Bad ttys0 baud rate -#endif - -#define COMBRD (115200/UART_BAUD) +/** + * Print a character to serial console + * + * @v character Character to be printed + */ +static void serial_putchar ( int character ) { -/* Line Control Settings */ -#define UART_LCS ( ( ( (COMDATA) - 5 ) << 0 ) | \ - ( ( (COMPARITY) ) << 3 ) | \ - ( ( (COMSTOP) - 1 ) << 2 ) ) + /* Do nothing if we have no UART */ + if ( ! serial_console.base ) + return; -/* Data */ -#define UART_RBR 0x00 -#define UART_TBR 0x00 + /* Transmit character */ + uart_transmit ( &serial_console, character ); +} -/* Control */ -#define UART_IER 0x01 -#define UART_IIR 0x02 -#define UART_FCR 0x02 -#define UART_LCR 0x03 -#define UART_MCR 0x04 -#define UART_DLL 0x00 -#define UART_DLM 0x01 +/** + * Get character from serial console + * + * @ret character Character read from console + */ +static int serial_getchar ( void ) { + uint8_t data; -/* Status */ -#define UART_LSR 0x05 -#define UART_LSR_TEMPT 0x40 /* Transmitter empty */ -#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ -#define UART_LSR_BI 0x10 /* Break interrupt indicator */ -#define UART_LSR_FE 0x08 /* Frame error indicator */ -#define UART_LSR_PE 0x04 /* Parity error indicator */ -#define UART_LSR_OE 0x02 /* Overrun error indicator */ -#define UART_LSR_DR 0x01 /* Receiver data ready */ + /* Do nothing if we have no UART */ + if ( ! serial_console.base ) + return 0; -#define UART_MSR 0x06 -#define UART_SCR 0x07 + /* Wait for data to be ready */ + while ( ! uart_data_ready ( &serial_console ) ) {} -#if defined(UART_MEM) -#define uart_readb(addr) readb((addr)) -#define uart_writeb(val,addr) writeb((val),(addr)) -#else -#define uart_readb(addr) inb((addr)) -#define uart_writeb(val,addr) outb((val),(addr)) -#endif + /* Receive data */ + data = uart_receive ( &serial_console ); -/* Boolean for the state of serial driver initialization */ -int serial_initialized = 0; + /* Strip any high bit and convert DEL to backspace */ + data &= 0x7f; + if ( data == 0x7f ) + data = 0x08; -/* - * void serial_putc(int ch); - * Write character `ch' to port UART_BASE. - */ -void serial_putc ( int ch ) { - int i; - int status; - i = 1000; /* timeout */ - while(--i > 0) { - status = uart_readb(UART_BASE + UART_LSR); - if (status & UART_LSR_THRE) { - /* TX buffer emtpy */ - uart_writeb(ch, UART_BASE + UART_TBR); - break; - } - mdelay(2); - } + return data; } -/* - * int serial_getc(void); - * Read a character from port UART_BASE. - */ -int serial_getc ( void ) { - int status; - int ch; - do { - status = uart_readb(UART_BASE + UART_LSR); - } while((status & 1) == 0); - ch = uart_readb(UART_BASE + UART_RBR); /* fetch (first) character */ - ch &= 0x7f; /* remove any parity bits we get */ - if (ch == 0x7f) { /* Make DEL... look like BS */ - ch = 0x08; - } - return ch; -} - -/* - * int serial_ischar(void); - * If there is a character in the input buffer of port UART_BASE, - * return nonzero; otherwise return 0. +/** + * Check for character ready to read from serial console + * + * @ret True Character available to read + * @ret False No character available to read */ -int serial_ischar ( void ) { - int status; - status = uart_readb(UART_BASE + UART_LSR); /* line status reg; */ - return status & 1; /* rx char available */ -} +static int serial_iskey ( void ) { -/* - * int serial_init(void); - * Initialize port UART_BASE to speed COMSPEED, line settings 8N1. - */ -static void serial_init ( void ) { - int status; - int divisor, lcs; + /* Do nothing if we have no UART */ + if ( ! serial_console.base ) + return 0; - DBG ( "Serial port %#x initialising\n", UART_BASE ); + /* Check UART */ + return uart_data_ready ( &serial_console ); +} - divisor = COMBRD; - lcs = UART_LCS; +/** Serial console */ +struct console_driver serial_console_driver __console_driver = { + .putchar = serial_putchar, + .getchar = serial_getchar, + .iskey = serial_iskey, + .usage = CONSOLE_SERIAL, +}; +/** Initialise serial console */ +static void serial_init ( void ) { + int rc; -#ifdef COMPRESERVE - lcs = uart_readb(UART_BASE + UART_LCR) & 0x7f; - uart_writeb(0x80 | lcs, UART_BASE + UART_LCR); - divisor = (uart_readb(UART_BASE + UART_DLM) << 8) | uart_readb(UART_BASE + UART_DLL); - uart_writeb(lcs, UART_BASE + UART_LCR); -#endif + /* Do nothing if we have no default port */ + if ( ! CONSOLE_PORT ) + return; - /* Set Baud Rate Divisor to COMSPEED, and test to see if the - * serial port appears to be present. - */ - uart_writeb(0x80 | lcs, UART_BASE + UART_LCR); - uart_writeb(0xaa, UART_BASE + UART_DLL); - if (uart_readb(UART_BASE + UART_DLL) != 0xaa) { - DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE ); - goto out; - } - uart_writeb(0x55, UART_BASE + UART_DLL); - if (uart_readb(UART_BASE + UART_DLL) != 0x55) { - DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE ); - goto out; + /* Select UART */ + if ( ( rc = uart_select ( &serial_console, CONSOLE_PORT ) ) != 0 ) { + DBG ( "Could not select UART %d: %s\n", + CONSOLE_PORT, strerror ( rc ) ); + return; } - uart_writeb(divisor & 0xff, UART_BASE + UART_DLL); - if (uart_readb(UART_BASE + UART_DLL) != (divisor & 0xff)) { - DBG ( "Serial port %#x UART_DLL failed\n", UART_BASE ); - goto out; - } - uart_writeb(0xaa, UART_BASE + UART_DLM); - if (uart_readb(UART_BASE + UART_DLM) != 0xaa) { - DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE ); - goto out; - } - uart_writeb(0x55, UART_BASE + UART_DLM); - if (uart_readb(UART_BASE + UART_DLM) != 0x55) { - DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE ); - goto out; - } - uart_writeb((divisor >> 8) & 0xff, UART_BASE + UART_DLM); - if (uart_readb(UART_BASE + UART_DLM) != ((divisor >> 8) & 0xff)) { - DBG ( "Serial port %#x UART_DLM failed\n", UART_BASE ); - goto out; - } - uart_writeb(lcs, UART_BASE + UART_LCR); - - /* disable interrupts */ - uart_writeb(0x0, UART_BASE + UART_IER); - /* enable fifos */ - uart_writeb(0x01, UART_BASE + UART_FCR); + /* Initialise UART */ + if ( ( rc = uart_init ( &serial_console, CONSOLE_BAUD, + CONSOLE_LCR ) ) != 0 ) { + DBG ( "Could not initialise UART %d baud %d LCR %#02x: %s\n", + CONSOLE_PORT, CONSOLE_BAUD, CONSOLE_LCR, strerror ( rc )); + return; + } +} - /* Set clear to send, so flow control works... */ - uart_writeb((1<<1), UART_BASE + UART_MCR); +/** + * Shut down serial console + * + * @v flags Shutdown flags + */ +static void serial_shutdown ( int flags __unused ) { - /* Flush the input buffer. */ - do { - /* rx buffer reg - * throw away (unconditionally the first time) - */ - (void) uart_readb(UART_BASE + UART_RBR); - /* line status reg */ - status = uart_readb(UART_BASE + UART_LSR); - } while(status & UART_LSR_DR); + /* Do nothing if we have no UART */ + if ( ! serial_console.base ) + return; - /* Note that serial support has been initialized */ - serial_initialized = 1; - out: - return; -} + /* Flush any pending output */ + uart_flush ( &serial_console ); -/* - * void serial_fini(void); - * Cleanup our use of the serial port, in particular flush the - * output buffer so we don't accidentially lose characters. - */ -static void serial_fini ( int flags __unused ) { - int i, status; - /* Flush the output buffer to avoid dropping characters, - * if we are reinitializing the serial port. - */ - i = 10000; /* timeout */ - do { - status = uart_readb(UART_BASE + UART_LSR); - } while((--i > 0) && !(status & UART_LSR_TEMPT)); - /* Don't mark it as disabled; it's still usable */ + /* Leave console enabled; it's still usable */ } -/** - * Serial driver initialisation function - * - * Initialise serial port early on so that it is available to capture - * early debug messages. - */ -struct init_fn serial_init_fn __init_fn ( INIT_SERIAL ) = { +/** Serial console initialisation function */ +struct init_fn serial_console_init_fn __init_fn ( INIT_CONSOLE ) = { .initialise = serial_init, }; -/** Serial driver startup function */ +/** Serial console startup function */ struct startup_fn serial_startup_fn __startup_fn ( STARTUP_EARLY ) = { - .shutdown = serial_fini, + .shutdown = serial_shutdown, };