forked from Imagelibrary/rtems
217 lines
4.4 KiB
C
217 lines
4.4 KiB
C
/*
|
|
* Console driver for Milkymist
|
|
*
|
|
* The license and distribution terms for this file may be
|
|
* found in the file LICENSE in this distribution or at
|
|
* http://www.rtems.org/license/LICENSE.
|
|
*
|
|
* COPYRIGHT (c) 2010 Sebastien Bourdeauducq
|
|
*/
|
|
|
|
#include <unistd.h>
|
|
#include <termios.h>
|
|
|
|
#include <rtems.h>
|
|
#include <rtems/bspIo.h>
|
|
#include <rtems/libio.h>
|
|
#include <rtems/console.h>
|
|
#include <rtems/termiostypes.h>
|
|
#include <bsp/irq-generic.h>
|
|
|
|
#include "../include/system_conf.h"
|
|
#include "uart.h"
|
|
|
|
BSP_output_char_function_type BSP_output_char = BSP_uart_polled_write;
|
|
BSP_polling_getchar_function_type BSP_poll_char = BSP_uart_polled_read;
|
|
|
|
static struct rtems_termios_tty *tty;
|
|
|
|
static int mmconsole_first_open(int major, int minor, void *arg)
|
|
{
|
|
tty = ((rtems_libio_open_close_args_t *) arg)->iop->data1;
|
|
return rtems_termios_set_initial_baud(tty, UART_BAUD_RATE);
|
|
}
|
|
|
|
static int mmconsole_last_close(int major, int minor, void *arg)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int mmconsole_set_attributes(int minor, const struct termios *t)
|
|
{
|
|
int baud;
|
|
|
|
switch (t->c_ospeed) {
|
|
case B0:
|
|
baud = 0;
|
|
break;
|
|
case B50:
|
|
baud = 50;
|
|
break;
|
|
case B75:
|
|
baud = 75;
|
|
break;
|
|
case B110:
|
|
baud = 110;
|
|
break;
|
|
case B134:
|
|
baud = 134;
|
|
break;
|
|
case B150:
|
|
baud = 150;
|
|
break;
|
|
case B200:
|
|
baud = 200;
|
|
break;
|
|
case B300:
|
|
baud = 300;
|
|
break;
|
|
case B600:
|
|
baud = 600;
|
|
break;
|
|
case B1200:
|
|
baud = 1200;
|
|
break;
|
|
case B1800:
|
|
baud = 1800;
|
|
break;
|
|
case B2400:
|
|
baud = 2400;
|
|
break;
|
|
case B4800:
|
|
baud = 4800;
|
|
break;
|
|
case B9600:
|
|
baud = 9600;
|
|
break;
|
|
case B19200:
|
|
baud = 19200;
|
|
break;
|
|
case B38400:
|
|
baud = 38400;
|
|
break;
|
|
case B57600:
|
|
baud = 57600;
|
|
break;
|
|
case B115200:
|
|
baud = 115200;
|
|
break;
|
|
case B230400:
|
|
baud = 230400;
|
|
break;
|
|
case B460800:
|
|
baud = 460800;
|
|
break;
|
|
default:
|
|
baud = -1;
|
|
break;
|
|
}
|
|
|
|
if (baud > 0)
|
|
MM_WRITE(MM_UART_DIV, MM_READ(MM_FREQUENCY)/baud/16);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static ssize_t mmconsole_write(int minor, const char *buf, size_t n)
|
|
{
|
|
if (n > 0) {
|
|
MM_WRITE(MM_UART_RXTX, *buf);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static rtems_isr mmconsole_interrupt(rtems_vector_number n)
|
|
{
|
|
char c;
|
|
while (MM_READ(MM_UART_STAT) & UART_STAT_RX_EVT) {
|
|
c = MM_READ(MM_UART_RXTX);
|
|
MM_WRITE(MM_UART_STAT, UART_STAT_RX_EVT);
|
|
rtems_termios_enqueue_raw_characters(tty, &c, 1);
|
|
}
|
|
if (MM_READ(MM_UART_STAT) & UART_STAT_TX_EVT) {
|
|
MM_WRITE(MM_UART_STAT, UART_STAT_TX_EVT);
|
|
rtems_termios_dequeue_characters(tty, 1);
|
|
}
|
|
lm32_interrupt_ack(1 << MM_IRQ_UART);
|
|
}
|
|
|
|
static const rtems_termios_callbacks mmconsole_callbacks = {
|
|
.firstOpen = mmconsole_first_open,
|
|
.lastClose = mmconsole_last_close,
|
|
.pollRead = NULL,
|
|
.write = mmconsole_write,
|
|
.setAttributes = mmconsole_set_attributes,
|
|
.stopRemoteTx = NULL,
|
|
.startRemoteTx = NULL,
|
|
.outputUsesInterrupts = TERMIOS_IRQ_DRIVEN
|
|
};
|
|
|
|
rtems_device_driver console_initialize(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void *arg
|
|
)
|
|
{
|
|
rtems_status_code status;
|
|
rtems_isr_entry dummy;
|
|
|
|
rtems_termios_initialize();
|
|
|
|
status = rtems_io_register_name("/dev/console", major, 0);
|
|
if (status != RTEMS_SUCCESSFUL)
|
|
rtems_fatal_error_occurred(status);
|
|
|
|
rtems_interrupt_catch(mmconsole_interrupt, MM_IRQ_UART, &dummy);
|
|
bsp_interrupt_vector_enable(MM_IRQ_UART);
|
|
MM_WRITE(MM_UART_CTRL, UART_CTRL_RX_INT|UART_CTRL_TX_INT);
|
|
|
|
return RTEMS_SUCCESSFUL;
|
|
}
|
|
|
|
rtems_device_driver console_open(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void *arg
|
|
)
|
|
{
|
|
return rtems_termios_open(major, minor, arg, &mmconsole_callbacks);
|
|
}
|
|
|
|
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);
|
|
}
|