/*
 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
 *
 * 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_OR_UBDL );

/** @file
 *
 * Serial console
 *
 */

#include <stddef.h>
#include <string.h>
#include <ipxe/init.h>
#include <ipxe/uart.h>
#include <ipxe/console.h>
#include <ipxe/serial.h>
#include <ipxe/ns16550.h>
#include <config/console.h>
#include <config/serial.h>

/* 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

#ifdef SERIAL_FIXED
#define SERIAL_PREFIX_fixed
#else
#define SERIAL_PREFIX_fixed __fixed_
#endif

/* Serial console UART */
#ifndef COMCONSOLE
#define COMCONSOLE NULL
#endif

/* Serial console baud rate */
#ifndef COMSPEED
#define COMSPEED 0
#endif

/** Active serial console UART
 *
 * Explicitly initialised to @c NULL since this variable may be
 * accessed before .bss has been zeroed.
 */
struct uart *serial_console = NULL;

/**
 * Get fixed serial console UART
 *
 * @ret uart		Serial console UART, or NULL
 */
struct uart * fixed_serial_console ( void ) {
	struct uart *uart = COMCONSOLE;
	unsigned int baud = COMSPEED;

	/* Set default baud rate, if applicable */
	if ( uart && baud )
		uart->baud = baud;

	return uart;
}

/**
 * Print a character to serial console
 *
 * @v character		Character to be printed
 */
static void serial_putchar ( int character ) {

	/* Do nothing if we have no UART */
	if ( ! serial_console )
		return;

	/* Transmit character */
	uart_transmit ( serial_console, character );
}

/**
 * Get character from serial console
 *
 * @ret character	Character read from console
 */
static int serial_getchar ( void ) {
	uint8_t data;

	/* Do nothing if we have no UART */
	if ( ! serial_console )
		return 0;

	/* Wait for data to be ready */
	while ( ! uart_data_ready ( serial_console ) ) {}

	/* Receive data */
	data = uart_receive ( serial_console );

	/* Strip any high bit and convert DEL to backspace */
	data &= 0x7f;
	if ( data == 0x7f )
		data = 0x08;

	return data;
}

/**
 * Check for character ready to read from serial console
 *
 * @ret True		Character available to read
 * @ret False		No character available to read
 */
static int serial_iskey ( void ) {

	/* Do nothing if we have no UART */
	if ( ! serial_console )
		return 0;

	/* Check UART */
	return uart_data_ready ( serial_console );
}

/** 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 ) {
	struct uart *uart;
	int rc;

	/* Get default serial console, if any */
	uart = default_serial_console();
	if ( ! uart )
		return;

	/* Initialise UART */
	if ( ( rc = uart_init ( uart ) ) != 0 ) {
		DBGC ( uart, "SERIAL could not initialise %s: %s\n",
		       uart->name, strerror ( rc ) );
		return;
	}

	/* Record UART as serial console */
	serial_console = uart;
	DBGC ( uart, "SERIAL using %s\n", uart->name );
}

/**
 * Shut down serial console
 *
 * @v flags		Shutdown flags
 */
static void serial_shutdown ( int flags __unused ) {

	/* Do nothing if we have no UART */
	if ( ! serial_console )
		return;

	/* Flush any pending output */
	uart_flush ( serial_console );

	/* Leave console enabled; it's still usable */
}

/** Serial console initialisation function */
struct init_fn serial_console_init_fn __init_fn ( INIT_CONSOLE ) = {
	.name = "serial",
	.initialise = serial_init,
};

/** Serial console startup function */
struct startup_fn serial_startup_fn __startup_fn ( STARTUP_EARLY ) = {
	.name = "serial",
	.shutdown = serial_shutdown,
};

PROVIDE_SERIAL_INLINE ( null, default_serial_console );
PROVIDE_SERIAL ( fixed, default_serial_console, fixed_serial_console );
