2005-03-08 19:53:11 +01:00
|
|
|
/*
|
2015-06-29 09:43:16 +02:00
|
|
|
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
|
2005-03-08 19:53:11 +01:00
|
|
|
*
|
2015-06-29 09:43:16 +02:00
|
|
|
* 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.
|
2005-03-08 19:53:11 +01:00
|
|
|
*/
|
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|
|
|
|
|
|
|
/** @file
|
|
|
|
*
|
|
|
|
* Serial console
|
|
|
|
*
|
|
|
|
*/
|
2009-05-01 16:41:06 +02:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
#include <stddef.h>
|
2016-03-12 19:02:20 +01:00
|
|
|
#include <string.h>
|
2010-04-19 21:16:01 +02:00
|
|
|
#include <ipxe/init.h>
|
2015-06-29 09:43:16 +02:00
|
|
|
#include <ipxe/uart.h>
|
|
|
|
#include <ipxe/console.h>
|
2010-04-19 21:16:01 +02:00
|
|
|
#include <ipxe/serial.h>
|
2015-06-29 09:43:16 +02:00
|
|
|
#include <config/console.h>
|
|
|
|
#include <config/serial.h>
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* 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 )
|
2005-03-08 19:53:11 +01:00
|
|
|
#endif
|
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* UART port number */
|
|
|
|
#ifdef COMCONSOLE
|
|
|
|
#define CONSOLE_PORT COMCONSOLE
|
|
|
|
#else
|
|
|
|
#define CONSOLE_PORT 0
|
2005-04-17 18:15:46 +02:00
|
|
|
#endif
|
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* UART baud rate */
|
|
|
|
#ifdef COMPRESERVE
|
|
|
|
#define CONSOLE_BAUD 0
|
|
|
|
#else
|
|
|
|
#define CONSOLE_BAUD COMSPEED
|
2005-04-17 18:15:46 +02:00
|
|
|
#endif
|
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* UART line control register value */
|
|
|
|
#ifdef COMPRESERVE
|
|
|
|
#define CONSOLE_LCR 0
|
|
|
|
#else
|
|
|
|
#define CONSOLE_LCR UART_LCR_WPS ( COMDATA, COMPARITY, COMSTOP )
|
2005-03-08 19:53:11 +01:00
|
|
|
#endif
|
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/** Serial console UART */
|
|
|
|
struct uart serial_console;
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/**
|
|
|
|
* Print a character to serial console
|
|
|
|
*
|
|
|
|
* @v character Character to be printed
|
|
|
|
*/
|
|
|
|
static void serial_putchar ( int character ) {
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* Do nothing if we have no UART */
|
|
|
|
if ( ! serial_console.base )
|
|
|
|
return;
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* Transmit character */
|
|
|
|
uart_transmit ( &serial_console, character );
|
|
|
|
}
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/**
|
|
|
|
* Get character from serial console
|
|
|
|
*
|
|
|
|
* @ret character Character read from console
|
|
|
|
*/
|
|
|
|
static int serial_getchar ( void ) {
|
|
|
|
uint8_t data;
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* Do nothing if we have no UART */
|
|
|
|
if ( ! serial_console.base )
|
|
|
|
return 0;
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* Wait for data to be ready */
|
|
|
|
while ( ! uart_data_ready ( &serial_console ) ) {}
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* Receive data */
|
|
|
|
data = uart_receive ( &serial_console );
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* Strip any high bit and convert DEL to backspace */
|
|
|
|
data &= 0x7f;
|
|
|
|
if ( data == 0x7f )
|
|
|
|
data = 0x08;
|
2012-10-05 16:14:12 +02:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
return data;
|
2005-03-08 19:53:11 +01:00
|
|
|
}
|
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/**
|
|
|
|
* Check for character ready to read from serial console
|
|
|
|
*
|
|
|
|
* @ret True Character available to read
|
|
|
|
* @ret False No character available to read
|
2005-03-08 19:53:11 +01:00
|
|
|
*/
|
2015-06-29 09:43:16 +02:00
|
|
|
static int serial_iskey ( void ) {
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* Do nothing if we have no UART */
|
|
|
|
if ( ! serial_console.base )
|
|
|
|
return 0;
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* Check UART */
|
|
|
|
return uart_data_ready ( &serial_console );
|
|
|
|
}
|
2006-09-01 02:26:32 +02:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/** Serial console */
|
|
|
|
struct console_driver serial_console_driver __console_driver = {
|
|
|
|
.putchar = serial_putchar,
|
|
|
|
.getchar = serial_getchar,
|
|
|
|
.iskey = serial_iskey,
|
|
|
|
.usage = CONSOLE_SERIAL,
|
|
|
|
};
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/** Initialise serial console */
|
|
|
|
static void serial_init ( void ) {
|
|
|
|
int rc;
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* Do nothing if we have no default port */
|
|
|
|
if ( ! CONSOLE_PORT )
|
|
|
|
return;
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* Select UART */
|
|
|
|
if ( ( rc = uart_select ( &serial_console, CONSOLE_PORT ) ) != 0 ) {
|
|
|
|
DBG ( "Could not select UART %d: %s\n",
|
|
|
|
CONSOLE_PORT, strerror ( rc ) );
|
|
|
|
return;
|
2006-09-01 02:19:09 +02:00
|
|
|
}
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* 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;
|
|
|
|
}
|
|
|
|
}
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/**
|
|
|
|
* Shut down serial console
|
|
|
|
*
|
|
|
|
* @v flags Shutdown flags
|
|
|
|
*/
|
|
|
|
static void serial_shutdown ( int flags __unused ) {
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* Do nothing if we have no UART */
|
|
|
|
if ( ! serial_console.base )
|
|
|
|
return;
|
2012-10-05 16:14:12 +02:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* Flush any pending output */
|
|
|
|
uart_flush ( &serial_console );
|
2005-03-08 19:53:11 +01:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/* Leave console enabled; it's still usable */
|
2005-03-08 19:53:11 +01:00
|
|
|
}
|
2005-04-08 17:01:17 +02:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/** Serial console initialisation function */
|
|
|
|
struct init_fn serial_console_init_fn __init_fn ( INIT_CONSOLE ) = {
|
2007-07-04 00:09:56 +02:00
|
|
|
.initialise = serial_init,
|
|
|
|
};
|
2008-06-04 22:00:46 +02:00
|
|
|
|
2015-06-29 09:43:16 +02:00
|
|
|
/** Serial console startup function */
|
2008-07-17 18:45:17 +02:00
|
|
|
struct startup_fn serial_startup_fn __startup_fn ( STARTUP_EARLY ) = {
|
2015-06-29 09:43:16 +02:00
|
|
|
.shutdown = serial_shutdown,
|
2008-06-04 22:00:46 +02:00
|
|
|
};
|