forked from Imagelibrary/rtems
bsps: Move console drivers to bsps
This patch is a part of the BSP source reorganization. Update #3285.
This commit is contained in:
314
bsps/powerpc/shared/console/console.c
Normal file
314
bsps/powerpc/shared/console/console.c
Normal file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* console.c -- console I/O package
|
||||
*
|
||||
* Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
|
||||
*
|
||||
* This code is based on the pc386 BSP console.c so the following
|
||||
* copyright also applies :
|
||||
*
|
||||
* (C) Copyright 1997 -
|
||||
* - NavIST Group - Real-Time Distributed Systems and Industrial Automation
|
||||
*
|
||||
* Till Straumann, <strauman@slac.stanford.edu>, 12/20/2001
|
||||
* separate BSP specific stuff from generics...
|
||||
*
|
||||
* http://pandora.ist.utl.pt
|
||||
*
|
||||
* Instituto Superior Tecnico * Lisboa * PORTUGAL
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <bsp.h>
|
||||
#include <bsp/irq.h>
|
||||
#include <rtems/bspIo.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/console.h>
|
||||
#include <rtems/termiostypes.h>
|
||||
#include <termios.h>
|
||||
#include <bsp/uart.h>
|
||||
#include <rtems/bspIo.h> /* printk */
|
||||
|
||||
/* Definitions for BSPConsolePort */
|
||||
/*
|
||||
* Possible value for console input/output :
|
||||
* BSP_CONSOLE_PORT_CONSOLE
|
||||
* BSP_UART_COM1
|
||||
* BSP_UART_COM2
|
||||
*/
|
||||
int BSPConsolePort = BSP_CONSOLE_PORT;
|
||||
|
||||
int BSPBaseBaud = BSP_UART_BAUD_BASE;
|
||||
|
||||
/*
|
||||
* TERMIOS_OUTPUT_MODE should be a 'bspopts.h/configure'-able option;
|
||||
* we could even make it a link-time option (but that would require
|
||||
* small changes)...
|
||||
*/
|
||||
#if defined(USE_POLLED_IO)
|
||||
#define TERMIOS_OUTPUT_MODE TERMIOS_POLLED
|
||||
#elif defined(USE_TASK_DRIVEN_IO)
|
||||
#define TERMIOS_OUTPUT_MODE TERMIOS_TASK_DRIVEN
|
||||
#else
|
||||
#define TERMIOS_OUTPUT_MODE TERMIOS_IRQ_DRIVEN
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------+
|
||||
| External Prototypes
|
||||
+--------------------------------------------------------------------------*/
|
||||
|
||||
static int conSetAttr(int minor, const struct termios *);
|
||||
|
||||
typedef struct TtySTblRec_ {
|
||||
char *name;
|
||||
rtems_irq_hdl isr;
|
||||
} TtySTblRec, *TtySTbl;
|
||||
|
||||
static TtySTblRec ttyS[]={
|
||||
{ "/dev/ttyS0",
|
||||
#ifdef BSP_UART_IOBASE_COM1
|
||||
BSP_uart_termios_isr_com1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
{ "/dev/ttyS1",
|
||||
#ifdef BSP_UART_IOBASE_COM2
|
||||
BSP_uart_termios_isr_com2
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------+
|
||||
| Console device driver INITIALIZE entry point.
|
||||
+--------------------------------------------------------------------------+
|
||||
| Initilizes the I/O console (keyboard + VGA display) driver.
|
||||
+--------------------------------------------------------------------------*/
|
||||
rtems_device_driver console_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
rtems_status_code status;
|
||||
|
||||
/*
|
||||
* The video was initialized in the start.s code and does not need
|
||||
* to be reinitialized.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Set up TERMIOS
|
||||
*/
|
||||
rtems_termios_initialize();
|
||||
|
||||
/*
|
||||
* Do device-specific initialization
|
||||
*/
|
||||
|
||||
/* RTEMS calls this routine once with 'minor'==0; loop through
|
||||
* all known instances...
|
||||
*/
|
||||
|
||||
for (minor=0; minor < sizeof(ttyS)/sizeof(ttyS[0]); minor++) {
|
||||
char *nm;
|
||||
/*
|
||||
* Skip ports (possibly not supported by BSP...) we have no ISR for
|
||||
*/
|
||||
if ( ! ttyS[minor].isr )
|
||||
continue;
|
||||
/*
|
||||
* Register the device
|
||||
*/
|
||||
status = rtems_io_register_name ((nm=ttyS[minor].name), major, minor);
|
||||
if ( RTEMS_SUCCESSFUL==status && BSPConsolePort == minor) {
|
||||
printk("Registering /dev/console as minor %" PRIu32 " (==%s)\n",
|
||||
minor,
|
||||
ttyS[minor].name);
|
||||
/* also register an alias */
|
||||
status = rtems_io_register_name ( (nm="/dev/console"), major, minor);
|
||||
}
|
||||
|
||||
if (status != RTEMS_SUCCESSFUL) {
|
||||
printk("Error registering %s!\n",nm);
|
||||
rtems_fatal_error_occurred (status);
|
||||
}
|
||||
}
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
} /* console_initialize */
|
||||
|
||||
#if !defined(USE_POLLED_IO)
|
||||
static int console_first_open(int major, int minor, void *arg)
|
||||
{
|
||||
rtems_status_code status;
|
||||
|
||||
/* must not open a minor device we have no ISR for */
|
||||
assert( minor>=0 && minor < sizeof(ttyS)/sizeof(ttyS[0]) && ttyS[minor].isr );
|
||||
|
||||
/* 9600-8-N-1 */
|
||||
BSP_uart_init(minor, 9600, 0);
|
||||
status = BSP_uart_install_isr(minor, ttyS[minor].isr);
|
||||
if (!status) {
|
||||
printk("Error installing serial console interrupt handler for '%s'!\n",
|
||||
ttyS[minor].name);
|
||||
rtems_fatal_error_occurred(status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass data area info down to driver
|
||||
*/
|
||||
BSP_uart_termios_set(minor, ((rtems_libio_open_close_args_t *)arg)->iop->data1);
|
||||
|
||||
/* Enable interrupts on channel */
|
||||
BSP_uart_intr_ctrl(minor, BSP_UART_INTR_CTRL_TERMIOS);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(USE_POLLED_IO)
|
||||
static int console_last_close(int major, int minor, void *arg)
|
||||
{
|
||||
BSP_uart_remove_isr(minor, ttyS[minor].isr);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------+
|
||||
| Console device driver OPEN entry point
|
||||
+--------------------------------------------------------------------------*/
|
||||
rtems_device_driver console_open(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
rtems_status_code status;
|
||||
static rtems_termios_callbacks cb =
|
||||
#if defined(USE_POLLED_IO)
|
||||
{
|
||||
NULL, /* firstOpen */
|
||||
NULL, /* lastClose */
|
||||
NULL, /* pollRead */
|
||||
BSP_uart_termios_write_polled, /* write */
|
||||
conSetAttr, /* setAttributes */
|
||||
NULL, /* stopRemoteTx */
|
||||
NULL, /* startRemoteTx */
|
||||
TERMIOS_POLLED /* outputUsesInterrupts */
|
||||
};
|
||||
#else
|
||||
{
|
||||
console_first_open, /* firstOpen */
|
||||
console_last_close, /* lastClose */
|
||||
#ifdef USE_TASK_DRIVEN_IO
|
||||
BSP_uart_termios_read_com, /* pollRead */
|
||||
#else
|
||||
NULL, /* pollRead */
|
||||
#endif
|
||||
BSP_uart_termios_write_com, /* write */
|
||||
conSetAttr, /* setAttributes */
|
||||
NULL, /* stopRemoteTx */
|
||||
NULL, /* startRemoteTx */
|
||||
TERMIOS_OUTPUT_MODE /* outputUsesInterrupts */
|
||||
};
|
||||
#endif
|
||||
|
||||
status = rtems_termios_open (major, minor, arg, &cb);
|
||||
|
||||
if (status != RTEMS_SUCCESSFUL) {
|
||||
printk("Error opening console device\n");
|
||||
return status;
|
||||
}
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------+
|
||||
| Console device driver CLOSE entry point
|
||||
+--------------------------------------------------------------------------*/
|
||||
rtems_device_driver
|
||||
console_close(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
rtems_device_driver res = RTEMS_SUCCESSFUL;
|
||||
|
||||
res = rtems_termios_close (arg);
|
||||
|
||||
return res;
|
||||
} /* console_close */
|
||||
|
||||
/*-------------------------------------------------------------------------+
|
||||
| Console device driver READ entry point.
|
||||
+--------------------------------------------------------------------------+
|
||||
| Read characters from the I/O console. We only have stdin.
|
||||
+--------------------------------------------------------------------------*/
|
||||
rtems_device_driver console_read(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
return rtems_termios_read (arg);
|
||||
} /* console_read */
|
||||
|
||||
/*-------------------------------------------------------------------------+
|
||||
| Console device driver WRITE entry point.
|
||||
+--------------------------------------------------------------------------+
|
||||
| Write characters to the I/O console. Stderr and stdout are the same.
|
||||
+--------------------------------------------------------------------------*/
|
||||
rtems_device_driver console_write(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
return rtems_termios_write (arg);
|
||||
} /* console_write */
|
||||
|
||||
/*
|
||||
* Handle ioctl request.
|
||||
*/
|
||||
rtems_device_driver console_control(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
/* does the BSP support break callbacks ? */
|
||||
#if defined(BIOCSETBREAKCB) && defined(BIOCGETBREAKCB)
|
||||
rtems_libio_ioctl_args_t *ioa=arg;
|
||||
switch (ioa->command) {
|
||||
case BIOCSETBREAKCB: return BSP_uart_set_break_cb(minor, ioa);
|
||||
case BIOCGETBREAKCB: return BSP_uart_get_break_cb(minor, ioa);
|
||||
default: break;
|
||||
}
|
||||
#endif
|
||||
return rtems_termios_ioctl (arg);
|
||||
}
|
||||
|
||||
static int conSetAttr(
|
||||
int minor,
|
||||
const struct termios *t
|
||||
)
|
||||
{
|
||||
rtems_termios_baud_t baud;
|
||||
|
||||
baud = rtems_termios_baud_to_number(t->c_ospeed);
|
||||
if ( baud > 115200 )
|
||||
rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR);
|
||||
|
||||
BSP_uart_set_baud(minor, baud);
|
||||
|
||||
return 0;
|
||||
}
|
||||
781
bsps/powerpc/shared/console/uart.c
Normal file
781
bsps/powerpc/shared/console/uart.c
Normal file
@@ -0,0 +1,781 @@
|
||||
/*
|
||||
* This software is Copyright (C) 1998 by T.sqware - all rights limited
|
||||
* It is provided in to the public domain "as is", can be freely modified
|
||||
* as far as this copyight notice is kept unchanged, but does not imply
|
||||
* an endorsement by T.sqware of the product in which it is included.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <bsp.h>
|
||||
#include <bsp/irq.h>
|
||||
#include <bsp/uart.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <rtems/bspIo.h>
|
||||
#include <rtems/termiostypes.h>
|
||||
#include <termios.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* Basic 16552 driver
|
||||
*/
|
||||
|
||||
struct uart_data
|
||||
{
|
||||
unsigned long ioBase;
|
||||
int irq;
|
||||
int hwFlow;
|
||||
int baud;
|
||||
BSP_UartBreakCbRec breakCallback;
|
||||
int ioMode;
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialization of BSP specific data.
|
||||
* The constants are pulled in from a BSP
|
||||
* specific file, whereas all of the code
|
||||
* in this file is generic and makes no
|
||||
* assumptions about addresses, irq vectors
|
||||
* etc...
|
||||
*/
|
||||
|
||||
#define UART_UNSUPP ((unsigned long)(-1))
|
||||
|
||||
static struct uart_data uart_data[2] = {
|
||||
{
|
||||
#ifdef BSP_UART_IOBASE_COM1
|
||||
BSP_UART_IOBASE_COM1,
|
||||
BSP_UART_COM1_IRQ,
|
||||
#else
|
||||
UART_UNSUPP,
|
||||
-1,
|
||||
#endif
|
||||
},
|
||||
{
|
||||
#ifdef BSP_UART_IOBASE_COM2
|
||||
BSP_UART_IOBASE_COM2,
|
||||
BSP_UART_COM2_IRQ,
|
||||
#else
|
||||
UART_UNSUPP,
|
||||
-1,
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
#define MAX_UARTS (sizeof(uart_data)/sizeof(uart_data[0]))
|
||||
#define SANITY_CHECK(uart) \
|
||||
assert( MAX_UARTS > (unsigned)(uart) && uart_data[(uart)].ioBase != UART_UNSUPP )
|
||||
/*
|
||||
* Macros to read/write register of uart, if configuration is
|
||||
* different just rewrite these macros
|
||||
*/
|
||||
|
||||
static inline unsigned char
|
||||
uread(int uart, unsigned int reg)
|
||||
{
|
||||
return in_8((uint8_t*)(uart_data[uart].ioBase + reg));
|
||||
}
|
||||
|
||||
static inline void
|
||||
uwrite(int uart, int reg, unsigned int val)
|
||||
{
|
||||
out_8((uint8_t*)(uart_data[uart].ioBase + reg), val);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
uartError(int uart, void *termiosPrivate)
|
||||
{
|
||||
unsigned char uartStatus, dummy;
|
||||
BSP_UartBreakCbProc h;
|
||||
|
||||
uartStatus = uread(uart, LSR);
|
||||
dummy = uread(uart, RBR);
|
||||
|
||||
#ifdef UARTDEBUG
|
||||
if (uartStatus & OE)
|
||||
printk("********* Over run Error **********\n");
|
||||
if (uartStatus & PE)
|
||||
printk("********* Parity Error **********\n");
|
||||
if (uartStatus & FE)
|
||||
printk("********* Framing Error **********\n");
|
||||
if (uartStatus & BI) {
|
||||
printk("********* BREAK INTERRUPT *********\n");
|
||||
#endif
|
||||
if ((h=uart_data[uart].breakCallback.handler)) {
|
||||
h(uart,
|
||||
(dummy<<8)|uartStatus,
|
||||
termiosPrivate,
|
||||
uart_data[uart].breakCallback.private);
|
||||
}
|
||||
#ifdef UARTDEBUG
|
||||
if (uartStatus & ERFIFO)
|
||||
printk("********* Error receive Fifo **********\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Uart initialization, it is hardcoded to 8 bit, no parity,
|
||||
* one stop bit, FIFO, things to be changed
|
||||
* are baud rate and nad hw flow control,
|
||||
* and longest rx fifo setting
|
||||
*/
|
||||
void
|
||||
BSP_uart_init(int uart, int baud, int hwFlow)
|
||||
{
|
||||
unsigned char tmp;
|
||||
|
||||
/* Sanity check */
|
||||
SANITY_CHECK(uart);
|
||||
|
||||
/* Make sure any printk activity drains before
|
||||
* re-initializing.
|
||||
*/
|
||||
while ( ! (uread(uart, LSR) & TEMT) )
|
||||
;
|
||||
|
||||
switch(baud)
|
||||
{
|
||||
case 50:
|
||||
case 75:
|
||||
case 110:
|
||||
case 134:
|
||||
case 300:
|
||||
case 600:
|
||||
case 1200:
|
||||
case 2400:
|
||||
case 9600:
|
||||
case 19200:
|
||||
case 38400:
|
||||
case 57600:
|
||||
case 115200:
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set DLAB bit to 1 */
|
||||
uwrite(uart, LCR, DLAB);
|
||||
|
||||
if ( (int)BSPBaseBaud <= 0 ) {
|
||||
/* Use current divisor assuming BSPBaseBaud gives us the current speed */
|
||||
BSPBaseBaud = BSPBaseBaud ? -BSPBaseBaud : 9600;
|
||||
BSPBaseBaud *= ((uread(uart, DLM) << 8) | uread(uart, DLL));
|
||||
}
|
||||
|
||||
/* Set baud rate */
|
||||
uwrite(uart, DLL, (BSPBaseBaud/baud) & 0xff);
|
||||
uwrite(uart, DLM, ((BSPBaseBaud/baud) >> 8) & 0xff);
|
||||
|
||||
/* 8-bit, no parity , 1 stop */
|
||||
uwrite(uart, LCR, CHR_8_BITS);
|
||||
|
||||
/* Set DTR, RTS and OUT2 high */
|
||||
uwrite(uart, MCR, DTR | RTS | OUT_2);
|
||||
|
||||
/* Enable FIFO */
|
||||
uwrite(uart, FCR, FIFO_EN | XMIT_RESET | RCV_RESET | RECEIVE_FIFO_TRIGGER12);
|
||||
|
||||
/* Disable Interrupts */
|
||||
uwrite(uart, IER, 0);
|
||||
|
||||
/* Read status to clear them */
|
||||
tmp = uread(uart, LSR);
|
||||
tmp = uread(uart, RBR);
|
||||
tmp = uread(uart, MSR);
|
||||
(void) tmp; /* avoid set but not used warning */
|
||||
|
||||
/* Remember state */
|
||||
uart_data[uart].hwFlow = hwFlow;
|
||||
uart_data[uart].baud = baud;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set baud
|
||||
*/
|
||||
void
|
||||
BSP_uart_set_baud(int uart, int baud)
|
||||
{
|
||||
unsigned char mcr, ier;
|
||||
|
||||
/* Sanity check */
|
||||
SANITY_CHECK(uart);
|
||||
|
||||
/*
|
||||
* This function may be called whenever TERMIOS parameters
|
||||
* are changed, so we have to make sure that baud change is
|
||||
* indeed required.
|
||||
*/
|
||||
|
||||
if(baud == uart_data[uart].baud)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mcr = uread(uart, MCR);
|
||||
ier = uread(uart, IER);
|
||||
|
||||
BSP_uart_init(uart, baud, uart_data[uart].hwFlow);
|
||||
|
||||
uwrite(uart, MCR, mcr);
|
||||
uwrite(uart, IER, ier);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable/disable interrupts
|
||||
*/
|
||||
void
|
||||
BSP_uart_intr_ctrl(int uart, int cmd)
|
||||
{
|
||||
|
||||
SANITY_CHECK(uart);
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case BSP_UART_INTR_CTRL_DISABLE:
|
||||
uwrite(uart, IER, INTERRUPT_DISABLE);
|
||||
break;
|
||||
case BSP_UART_INTR_CTRL_ENABLE:
|
||||
if(uart_data[uart].hwFlow)
|
||||
{
|
||||
uwrite(uart, IER,
|
||||
(RECEIVE_ENABLE |
|
||||
TRANSMIT_ENABLE |
|
||||
RECEIVER_LINE_ST_ENABLE |
|
||||
MODEM_ENABLE
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
uwrite(uart, IER,
|
||||
(RECEIVE_ENABLE |
|
||||
TRANSMIT_ENABLE |
|
||||
RECEIVER_LINE_ST_ENABLE
|
||||
)
|
||||
);
|
||||
}
|
||||
break;
|
||||
case BSP_UART_INTR_CTRL_TERMIOS:
|
||||
if(uart_data[uart].hwFlow)
|
||||
{
|
||||
uwrite(uart, IER,
|
||||
(RECEIVE_ENABLE |
|
||||
RECEIVER_LINE_ST_ENABLE |
|
||||
MODEM_ENABLE
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
uwrite(uart, IER,
|
||||
(RECEIVE_ENABLE |
|
||||
RECEIVER_LINE_ST_ENABLE
|
||||
)
|
||||
);
|
||||
}
|
||||
break;
|
||||
case BSP_UART_INTR_CTRL_GDB:
|
||||
uwrite(uart, IER, RECEIVE_ENABLE);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
BSP_uart_throttle(int uart)
|
||||
{
|
||||
unsigned int mcr;
|
||||
|
||||
SANITY_CHECK(uart);
|
||||
|
||||
if(!uart_data[uart].hwFlow)
|
||||
{
|
||||
/* Should not happen */
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
mcr = uread (uart, MCR);
|
||||
/* RTS down */
|
||||
mcr &= ~RTS;
|
||||
uwrite(uart, MCR, mcr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
BSP_uart_unthrottle(int uart)
|
||||
{
|
||||
unsigned int mcr;
|
||||
|
||||
SANITY_CHECK(uart);
|
||||
|
||||
if(!uart_data[uart].hwFlow)
|
||||
{
|
||||
/* Should not happen */
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
mcr = uread (uart, MCR);
|
||||
/* RTS up */
|
||||
mcr |= RTS;
|
||||
uwrite(uart, MCR, mcr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Status function, -1 if error
|
||||
* detected, 0 if no received chars available,
|
||||
* 1 if received char available, 2 if break
|
||||
* is detected, it will eat break and error
|
||||
* chars. It ignores overruns - we cannot do
|
||||
* anything about - it execpt count statistics
|
||||
* and we are not counting it.
|
||||
*/
|
||||
int
|
||||
BSP_uart_polled_status(int uart)
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
SANITY_CHECK(uart);
|
||||
|
||||
val = uread(uart, LSR);
|
||||
|
||||
if(val & BI)
|
||||
{
|
||||
/* BREAK found, eat character */
|
||||
uread(uart, RBR);
|
||||
return BSP_UART_STATUS_BREAK;
|
||||
}
|
||||
|
||||
if((val & (DR | OE | FE)) == 1)
|
||||
{
|
||||
/* No error, character present */
|
||||
return BSP_UART_STATUS_CHAR;
|
||||
}
|
||||
|
||||
if((val & (DR | OE | FE)) == 0)
|
||||
{
|
||||
/* Nothing */
|
||||
return BSP_UART_STATUS_NOCHAR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Framing or parity error
|
||||
* eat character
|
||||
*/
|
||||
uread(uart, RBR);
|
||||
|
||||
return BSP_UART_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Polled mode write function
|
||||
*/
|
||||
void
|
||||
BSP_uart_polled_write(int uart, int val)
|
||||
{
|
||||
unsigned char val1;
|
||||
|
||||
/* Sanity check */
|
||||
SANITY_CHECK(uart);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if((val1=uread(uart, LSR)) & THRE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(uart_data[uart].hwFlow)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
if(uread(uart, MSR) & CTS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uwrite(uart, THR, val & 0xff);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
BSP_output_char_via_serial(const char val)
|
||||
{
|
||||
BSP_uart_polled_write(BSPConsolePort, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Polled mode read function
|
||||
*/
|
||||
int
|
||||
BSP_uart_polled_read(int uart)
|
||||
{
|
||||
unsigned char val;
|
||||
|
||||
SANITY_CHECK(uart);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(uread(uart, LSR) & DR)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
val = uread(uart, RBR);
|
||||
|
||||
return (int)(val & 0xff);
|
||||
}
|
||||
|
||||
unsigned
|
||||
BSP_poll_char_via_serial()
|
||||
{
|
||||
return BSP_uart_polled_read(BSPConsolePort);
|
||||
}
|
||||
|
||||
static void
|
||||
uart_noop(const rtems_irq_connect_data *unused)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* note that the IRQ names contain _ISA_ for legacy
|
||||
* reasons. They can be any interrupt, depending
|
||||
* on the particular BSP...
|
||||
*/
|
||||
|
||||
static int
|
||||
uart_isr_is_on(const rtems_irq_connect_data *irq)
|
||||
{
|
||||
int uart;
|
||||
|
||||
uart = (irq->name == BSP_UART_COM1_IRQ) ?
|
||||
BSP_UART_COM1 : BSP_UART_COM2;
|
||||
|
||||
return uread(uart,IER);
|
||||
}
|
||||
|
||||
static int
|
||||
doit(int uart, rtems_irq_hdl handler, int (*p)(const rtems_irq_connect_data*))
|
||||
{
|
||||
rtems_irq_connect_data d={0};
|
||||
d.name = uart_data[uart].irq;
|
||||
d.off = d.on = uart_noop;
|
||||
d.isOn = uart_isr_is_on;
|
||||
d.hdl = handler;
|
||||
return p(&d);
|
||||
}
|
||||
|
||||
int
|
||||
BSP_uart_install_isr(int uart, rtems_irq_hdl handler)
|
||||
{
|
||||
/* Using shared interrupts by default might break things.. the
|
||||
* shared IRQ installer uses malloc() and if a BSP had called this
|
||||
* during early init it might not work...
|
||||
*/
|
||||
#ifdef BSP_UART_USE_SHARED_IRQS
|
||||
return doit(uart, handler, BSP_install_rtems_shared_irq_handler);
|
||||
#else
|
||||
return doit(uart, handler, BSP_install_rtems_irq_handler);
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
BSP_uart_remove_isr(int uart, rtems_irq_hdl handler)
|
||||
{
|
||||
return doit(uart, handler, BSP_remove_rtems_irq_handler);
|
||||
}
|
||||
|
||||
/* ================ Termios support =================*/
|
||||
|
||||
static volatile int termios_stopped_com[2] = {0,0};
|
||||
static volatile int termios_tx_active_com[2] = {0,0};
|
||||
static void* termios_ttyp_com[2] = {NULL,NULL};
|
||||
static char termios_tx_hold_com[2] = {0,0};
|
||||
static volatile char termios_tx_hold_valid_com[2] = {0,0};
|
||||
|
||||
/*
|
||||
* Set channel parameters
|
||||
*/
|
||||
void
|
||||
BSP_uart_termios_set(int uart, void *p)
|
||||
{
|
||||
struct rtems_termios_tty *ttyp = p;
|
||||
unsigned char val;
|
||||
SANITY_CHECK(uart);
|
||||
|
||||
if(uart_data[uart].hwFlow)
|
||||
{
|
||||
val = uread(uart, MSR);
|
||||
|
||||
termios_stopped_com[uart] = (val & CTS) ? 0 : 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
termios_stopped_com[uart] = 0;
|
||||
}
|
||||
termios_tx_active_com[uart] = 0;
|
||||
termios_ttyp_com[uart] = ttyp;
|
||||
termios_tx_hold_com[uart] = 0;
|
||||
termios_tx_hold_valid_com[uart] = 0;
|
||||
|
||||
uart_data[uart].ioMode = ttyp->device.outputUsesInterrupts;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
BSP_uart_termios_write_polled(int minor, const char *buf, size_t len)
|
||||
{
|
||||
int uart=minor; /* could differ, theoretically */
|
||||
int nwrite;
|
||||
const char *b = buf;
|
||||
|
||||
for (nwrite=0 ; nwrite < len ; nwrite++) {
|
||||
BSP_uart_polled_write(uart, *b++);
|
||||
}
|
||||
return nwrite;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
BSP_uart_termios_write_com(int minor, const char *buf, size_t len)
|
||||
{
|
||||
int uart=minor; /* could differ, theoretically */
|
||||
|
||||
if(len <= 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the TX buffer is busy - something is royally screwed up */
|
||||
/* assert((uread(BSP_UART_COM1, LSR) & THRE) != 0); */
|
||||
|
||||
if(termios_stopped_com[uart])
|
||||
{
|
||||
/* CTS low */
|
||||
termios_tx_hold_com[uart] = *buf;
|
||||
termios_tx_hold_valid_com[uart] = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write character */
|
||||
uwrite(uart, THR, *buf & 0xff);
|
||||
|
||||
/* Enable interrupts if necessary */
|
||||
if(!termios_tx_active_com[uart] && uart_data[uart].hwFlow)
|
||||
{
|
||||
termios_tx_active_com[uart] = 1;
|
||||
uwrite(uart, IER,
|
||||
(RECEIVE_ENABLE |
|
||||
TRANSMIT_ENABLE |
|
||||
RECEIVER_LINE_ST_ENABLE |
|
||||
MODEM_ENABLE
|
||||
)
|
||||
);
|
||||
}
|
||||
else if(!termios_tx_active_com[uart])
|
||||
{
|
||||
termios_tx_active_com[uart] = 1;
|
||||
uwrite(uart, IER,
|
||||
(RECEIVE_ENABLE |
|
||||
TRANSMIT_ENABLE |
|
||||
RECEIVER_LINE_ST_ENABLE
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
BSP_uart_termios_read_com(int uart)
|
||||
{
|
||||
int off = (int)0;
|
||||
char buf[40];
|
||||
rtems_interrupt_level l;
|
||||
|
||||
/* read bytes */
|
||||
while (( off < sizeof(buf) ) && ( uread(uart, LSR) & DR )) {
|
||||
buf[off++] = uread(uart, RBR);
|
||||
}
|
||||
|
||||
/* write out data */
|
||||
if ( off > 0 ) {
|
||||
rtems_termios_enqueue_raw_characters(termios_ttyp_com[uart], buf, off);
|
||||
}
|
||||
|
||||
/* enable receive interrupts */
|
||||
rtems_interrupt_disable(l);
|
||||
uwrite(uart, IER, uread(uart, IER) | (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE));
|
||||
rtems_interrupt_enable(l);
|
||||
|
||||
return ( EOF );
|
||||
}
|
||||
|
||||
static void
|
||||
BSP_uart_termios_isr_com(int uart)
|
||||
{
|
||||
unsigned char buf[40];
|
||||
unsigned char val, ier;
|
||||
int off, ret, vect;
|
||||
|
||||
off = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
vect = uread(uart, IIR) & 0xf;
|
||||
|
||||
switch(vect)
|
||||
{
|
||||
case MODEM_STATUS :
|
||||
val = uread(uart, MSR);
|
||||
if(uart_data[uart].hwFlow)
|
||||
{
|
||||
if(val & CTS)
|
||||
{
|
||||
/* CTS high */
|
||||
termios_stopped_com[uart] = 0;
|
||||
if(termios_tx_hold_valid_com[uart])
|
||||
{
|
||||
termios_tx_hold_valid_com[uart] = 0;
|
||||
BSP_uart_termios_write_com(uart, &termios_tx_hold_com[uart],
|
||||
1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* CTS low */
|
||||
termios_stopped_com[uart] = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NO_MORE_INTR :
|
||||
/* No more interrupts */
|
||||
if(off != 0)
|
||||
{
|
||||
/* Update rx buffer */
|
||||
rtems_termios_enqueue_raw_characters(termios_ttyp_com[uart],
|
||||
(char *)buf,
|
||||
off);
|
||||
}
|
||||
return;
|
||||
case TRANSMITTER_HODING_REGISTER_EMPTY :
|
||||
/*
|
||||
* TX holding empty: we have to disable these interrupts
|
||||
* if there is nothing more to send.
|
||||
*/
|
||||
|
||||
ret = rtems_termios_dequeue_characters(termios_ttyp_com[uart], 1);
|
||||
|
||||
/* If nothing else to send disable interrupts */
|
||||
if(ret == 0 && uart_data[uart].hwFlow)
|
||||
{
|
||||
uwrite(uart, IER,
|
||||
(RECEIVE_ENABLE |
|
||||
RECEIVER_LINE_ST_ENABLE |
|
||||
MODEM_ENABLE
|
||||
)
|
||||
);
|
||||
termios_tx_active_com[uart] = 0;
|
||||
}
|
||||
else if(ret == 0)
|
||||
{
|
||||
uwrite(uart, IER,
|
||||
(RECEIVE_ENABLE |
|
||||
RECEIVER_LINE_ST_ENABLE
|
||||
)
|
||||
);
|
||||
termios_tx_active_com[uart] = 0;
|
||||
}
|
||||
break;
|
||||
case RECEIVER_DATA_AVAIL :
|
||||
case CHARACTER_TIMEOUT_INDICATION:
|
||||
if ( uart_data[uart].ioMode == TERMIOS_TASK_DRIVEN )
|
||||
{
|
||||
/* ensure interrupts are enabled */
|
||||
if ( (ier = uread(uart,IER)) & RECEIVE_ENABLE )
|
||||
{
|
||||
/* disable interrupts and notify termios */
|
||||
ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
|
||||
uwrite(uart, IER, ier);
|
||||
rtems_termios_rxirq_occured(termios_ttyp_com[uart]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* RX data ready */
|
||||
assert(off < sizeof(buf));
|
||||
while ( off < sizeof(buf) && ( DR & uread(uart, LSR) ) )
|
||||
buf[off++] = uread(uart, RBR);
|
||||
}
|
||||
break;
|
||||
case RECEIVER_ERROR:
|
||||
/* RX error: eat character */
|
||||
uartError(uart, termios_ttyp_com[uart]);
|
||||
break;
|
||||
default:
|
||||
/* Should not happen */
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX - Note that this can now be one isr with the uart
|
||||
* passed as the parameter.
|
||||
*/
|
||||
void
|
||||
BSP_uart_termios_isr_com1(void *unused)
|
||||
{
|
||||
BSP_uart_termios_isr_com(BSP_UART_COM1);
|
||||
}
|
||||
|
||||
void
|
||||
BSP_uart_termios_isr_com2(void *unused)
|
||||
{
|
||||
BSP_uart_termios_isr_com(BSP_UART_COM2);
|
||||
}
|
||||
|
||||
/* retrieve 'break' handler info */
|
||||
int
|
||||
BSP_uart_get_break_cb(int uart, rtems_libio_ioctl_args_t *arg)
|
||||
{
|
||||
BSP_UartBreakCb cb=arg->buffer;
|
||||
unsigned long flags;
|
||||
SANITY_CHECK(uart);
|
||||
rtems_interrupt_disable(flags);
|
||||
*cb = uart_data[uart].breakCallback;
|
||||
rtems_interrupt_enable(flags);
|
||||
arg->ioctl_return=0;
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
/* install 'break' handler */
|
||||
int
|
||||
BSP_uart_set_break_cb(int uart, rtems_libio_ioctl_args_t *arg)
|
||||
{
|
||||
BSP_UartBreakCb cb=arg->buffer;
|
||||
unsigned long flags;
|
||||
SANITY_CHECK(uart);
|
||||
rtems_interrupt_disable(flags);
|
||||
uart_data[uart].breakCallback = *cb;
|
||||
rtems_interrupt_enable(flags);
|
||||
arg->ioctl_return=0;
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
Reference in New Issue
Block a user