summaryrefslogblamecommitdiffstats
path: root/c/src/lib/libbsp/sparc/shared/uart/cons.c
blob: f0af1f9c52da8d7d3cda66ece71859e8aed2e9ce (plain) (tree)









































                                                                             
                                                                 

















































































































































                                                                                
/*  This file contains the TTY driver for the serial ports. The driver
 *  is layered so that different UART hardware can be used. It is implemented
 *  using the Driver Manager.
 *
 *  This driver uses the termios pseudo driver.
 *
 *  COPYRIGHT (c) 2010.
 *  Cobham Gaisler AB.
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.com/license/LICENSE.
 */

#include <bsp.h>
#include <stdlib.h>
#include <rtems/libio.h>
#include <rtems/bspIo.h>
#include <cons.h>

#ifdef RTEMS_DRVMGR_STARTUP

/* Note that it is not possible to use the interrupt mode of the driver
 * together with the "old" APBUART and -u to GRMON. However the new
 * APBUART core (from 1.0.17-b2710) has the GRMON debug bit and can 
 * handle interrupts.
 */

int console_initialized = 0;
rtems_device_major_number console_major = 0;

#define FLAG_SYSCON 0x01
struct console_priv {
	unsigned char flags; /* 0x1=SystemConsole */
	unsigned char minor;
	struct console_dev *dev;
};

#define CONSOLE_MAX BSP_NUMBER_OF_TERMIOS_PORTS
struct console_priv cons[CONSOLE_MAX] = {{0,0},};

/* Register Console to TERMIOS layer and initialize it */
static void console_dev_init(struct console_priv *con, int minor)
{
	char name[16], *fsname;
	rtems_status_code status;

	if (!con->dev->fsname) {
		strcpy(name, "/dev/console_a");
		/* Special console name and MINOR for SYSTEM CONSOLE */
		if (minor == 0)
			name[12] = '\0'; /* /dev/console */
		name[13] += minor; /* when minor=0, this has no effect... */
		fsname = name;
	} else {
		fsname = con->dev->fsname;
	}
	status = rtems_io_register_name(fsname, console_major, minor);
	if ((minor == 0) && (status != RTEMS_SUCCESSFUL))
		rtems_fatal_error_occurred(status);
}

void console_dev_register(struct console_dev *dev)
{
	int i, minor = 0;
	struct console_priv *con = NULL;

	if ((dev->flags & CONSOLE_FLAG_SYSCON) && !cons[0].dev) {
		con = &cons[0];
		con->flags = FLAG_SYSCON;
	} else {
		for (i=1; i<CONSOLE_MAX; i++) {
			if (!cons[i].dev) {
				con = &cons[i];
				con->flags = 0;
				minor = i;
				break;
			}
		}
	}
	if (con == NULL) {
		/* Not enough console structures */
		return;
	}

	/* Assign Console */
	con->dev = dev;
	con->minor = minor;

	/* Console layer is already initialized, that means that we can
	 * register termios interface directly.
	 */
	if (console_initialized)
		console_dev_init(con, minor);
}

#if 0
void console_dev_unregister(struct console_dev *dev)
{

}
#endif

rtems_device_driver console_initialize(
	rtems_device_major_number	major,
	rtems_device_minor_number	minor,
	void				*arg)
{
	int i;

	console_major = major;

	rtems_termios_initialize();

	/* Register all Console a file system device node */
	for (i=0; i<CONSOLE_MAX; i++) {
		if (cons[i].dev)
			console_dev_init(&cons[i], i);
	}

	console_initialized = 1;

	return RTEMS_SUCCESSFUL;
}

rtems_device_driver console_open(
	rtems_device_major_number	major,
	rtems_device_minor_number	minor,
	void				*arg)
{
	rtems_status_code status;
	struct termios term;

	if ((minor >= CONSOLE_MAX) || !cons[minor].dev)
		return RTEMS_INVALID_NUMBER;

	status = rtems_termios_open(
			major,
			(int)cons[minor].dev,
			arg,
			cons[minor].dev->callbacks);

	/* Inherit UART hardware parameters from bootloader on system console */
	if ((status == RTEMS_SUCCESSFUL) && (cons[minor].flags & FLAG_SYSCON) &&
	    (cons[minor].dev->ops.get_uart_attrs != NULL)) {
		if (tcgetattr(STDIN_FILENO, &term) >= 0) {
			cons[minor].dev->ops.get_uart_attrs(cons[minor].dev,
								&term);
			term.c_oflag |= ONLCR;
			tcsetattr(STDIN_FILENO, TCSANOW, &term);
		}
	}

	return status;
}

rtems_device_driver console_close(
	rtems_device_major_number	major,
	rtems_device_minor_number	minor,
	void				*arg)
{
	return rtems_termios_close(arg);
}

rtems_device_driver console_read(
	rtems_device_major_number	major,
	rtems_device_minor_number	minor,
	void				*arg)
{
	return rtems_termios_read(arg);
}

rtems_device_driver console_write(
	rtems_device_major_number	major,
	rtems_device_minor_number	minor,
	void				*arg)
{
	return rtems_termios_write(arg);
}

rtems_device_driver console_control(
	rtems_device_major_number	major,
	rtems_device_minor_number	minor,
	void				*arg)
{
	return rtems_termios_ioctl(arg);
}

#endif