forked from Imagelibrary/rtems
New termios.c from Eric Norum.
Added new entry point to add in per physical port resource requirements.
This commit is contained in:
@@ -147,5 +147,9 @@ rtems_status_code rtems_termios_read (void *arg);
|
|||||||
rtems_status_code rtems_termios_write (void *arg);
|
rtems_status_code rtems_termios_write (void *arg);
|
||||||
rtems_status_code rtems_termios_ioctl (void *arg);
|
rtems_status_code rtems_termios_ioctl (void *arg);
|
||||||
void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
|
void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
|
||||||
|
void rtems_termios_reserve_resources(
|
||||||
|
rtems_configuration_table *configuration,
|
||||||
|
rtems_unsigned32 number_of_devices
|
||||||
|
);
|
||||||
|
|
||||||
#endif /* _RTEMS_LIBIO_H */
|
#endif /* _RTEMS_LIBIO_H */
|
||||||
|
|||||||
@@ -23,13 +23,17 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <ringbuf.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The size of the cooked buffer
|
* The size of the cooked buffer
|
||||||
*/
|
*/
|
||||||
#define CBUFSIZE 256
|
#define CBUFSIZE 256
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The size of the raw input message queue
|
||||||
|
*/
|
||||||
|
#define RAW_BUFFER_SIZE 128
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Variables associated with each termios instance.
|
* Variables associated with each termios instance.
|
||||||
* One structure for each hardware I/O device.
|
* One structure for each hardware I/O device.
|
||||||
@@ -80,18 +84,20 @@ struct rtems_termios_tty {
|
|||||||
/*
|
/*
|
||||||
* Raw character buffer
|
* Raw character buffer
|
||||||
*/
|
*/
|
||||||
rtems_id rawInputSem;
|
volatile char rawBuf[RAW_BUFFER_SIZE];
|
||||||
Ring_buffer_t rawInputBuffer;
|
volatile unsigned int rawBufHead;
|
||||||
|
volatile unsigned int rawBufTail;
|
||||||
rtems_unsigned32 rawMessageOptions;
|
rtems_id rawBufSemaphore;
|
||||||
rtems_interval rawMessageTimeout;
|
rtems_unsigned32 rawBufSemaphoreOptions;
|
||||||
rtems_interval rawMessageFirstTimeout;
|
rtems_interval rawBufSemaphoreTimeout;
|
||||||
|
rtems_interval rawBufSemaphoreFirstTimeout;
|
||||||
|
unsigned int rawBufDropped; /* Statistics */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Callbacks to device-specific routines
|
* Callbacks to device-specific routines
|
||||||
*/
|
*/
|
||||||
int (*lastClose)(int major, int minor, void *arg);
|
int (*lastClose)(int major, int minor, void *arg);
|
||||||
int (*read)(int minor, char *buf );
|
int (*read)(int minor, char *buf);
|
||||||
int (*write)(int minor, char *buf, int len);
|
int (*write)(int minor, char *buf, int len);
|
||||||
};
|
};
|
||||||
static struct rtems_termios_tty *ttyHead, *ttyTail;
|
static struct rtems_termios_tty *ttyHead, *ttyTail;
|
||||||
@@ -127,7 +133,7 @@ rtems_termios_open (
|
|||||||
void *arg,
|
void *arg,
|
||||||
int (*deviceFirstOpen)(int major, int minor, void *arg),
|
int (*deviceFirstOpen)(int major, int minor, void *arg),
|
||||||
int (*deviceLastClose)(int major, int minor, void *arg),
|
int (*deviceLastClose)(int major, int minor, void *arg),
|
||||||
int (*deviceRead)(int minor, char *buf/*, int len*/),
|
int (*deviceRead)(int minor, char *buf),
|
||||||
int (*deviceWrite)(int minor, char *buf, int len)
|
int (*deviceWrite)(int minor, char *buf, int len)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -191,11 +197,13 @@ rtems_termios_open (
|
|||||||
sc = rtems_semaphore_create (
|
sc = rtems_semaphore_create (
|
||||||
rtems_build_name ('T', 'R', 'r', c),
|
rtems_build_name ('T', 'R', 'r', c),
|
||||||
0,
|
0,
|
||||||
RTEMS_COUNTING_SEMAPHORE | RTEMS_FIFO | RTEMS_LOCAL,
|
RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
|
||||||
RTEMS_NO_PRIORITY,
|
RTEMS_NO_PRIORITY,
|
||||||
&tty->rawInputSem);
|
&tty->rawBufSemaphore);
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
rtems_fatal_error_occurred (sc);
|
rtems_fatal_error_occurred (sc);
|
||||||
|
tty->rawBufHead = 0;
|
||||||
|
tty->rawBufTail = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -268,7 +276,7 @@ rtems_termios_close (void *arg)
|
|||||||
rtems_semaphore_delete (tty->isem);
|
rtems_semaphore_delete (tty->isem);
|
||||||
rtems_semaphore_delete (tty->osem);
|
rtems_semaphore_delete (tty->osem);
|
||||||
if (tty->read == NULL)
|
if (tty->read == NULL)
|
||||||
rtems_semaphore_delete (tty->rawInputSem);
|
rtems_semaphore_delete (tty->rawBufSemaphore);
|
||||||
free (tty);
|
free (tty);
|
||||||
}
|
}
|
||||||
rtems_semaphore_release (ttyMutex);
|
rtems_semaphore_release (ttyMutex);
|
||||||
@@ -297,30 +305,30 @@ rtems_termios_ioctl (void *arg)
|
|||||||
case RTEMS_IO_SET_ATTRIBUTES:
|
case RTEMS_IO_SET_ATTRIBUTES:
|
||||||
tty->termios = *(struct termios *)args->buffer;
|
tty->termios = *(struct termios *)args->buffer;
|
||||||
if (tty->termios.c_lflag & ICANON) {
|
if (tty->termios.c_lflag & ICANON) {
|
||||||
tty->rawMessageOptions = RTEMS_WAIT;
|
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||||
tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
|
||||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rtems_interval ticksPerSecond;
|
rtems_interval ticksPerSecond;
|
||||||
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
|
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
|
||||||
tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
|
tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
|
||||||
if (tty->termios.c_cc[VTIME]) {
|
if (tty->termios.c_cc[VTIME]) {
|
||||||
tty->rawMessageOptions = RTEMS_WAIT;
|
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||||
tty->rawMessageTimeout = tty->vtimeTicks;
|
tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
|
||||||
if (tty->termios.c_cc[VMIN])
|
if (tty->termios.c_cc[VMIN])
|
||||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||||
else
|
else
|
||||||
tty->rawMessageFirstTimeout = tty->vtimeTicks;
|
tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (tty->termios.c_cc[VMIN]) {
|
if (tty->termios.c_cc[VMIN]) {
|
||||||
tty->rawMessageOptions = RTEMS_WAIT;
|
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||||
tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
|
||||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tty->rawMessageOptions = RTEMS_NO_WAIT;
|
tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -659,25 +667,20 @@ fillBufferPoll (struct rtems_termios_tty *tty)
|
|||||||
static rtems_status_code
|
static rtems_status_code
|
||||||
fillBufferQueue (struct rtems_termios_tty *tty)
|
fillBufferQueue (struct rtems_termios_tty *tty)
|
||||||
{
|
{
|
||||||
rtems_interval timeout = tty->rawMessageFirstTimeout;
|
rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
rtems_unsigned8 c;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
/*
|
|
||||||
* Read characters from raw queue
|
|
||||||
*/
|
|
||||||
sc = rtems_semaphore_obtain (tty->rawInputSem,
|
|
||||||
tty->rawMessageOptions,
|
|
||||||
timeout);
|
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
|
||||||
break;
|
|
||||||
Ring_buffer_Remove_character( &tty->rawInputBuffer, c );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process characters read from raw queue
|
* Process characters read from raw queue
|
||||||
*/
|
*/
|
||||||
|
while (tty->rawBufHead != tty->rawBufTail) {
|
||||||
|
unsigned char c;
|
||||||
|
unsigned int newHead;
|
||||||
|
|
||||||
|
newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE;
|
||||||
|
c = tty->rawBuf[newHead];
|
||||||
|
tty->rawBufHead = newHead;
|
||||||
if (tty->termios.c_lflag & ICANON) {
|
if (tty->termios.c_lflag & ICANON) {
|
||||||
if (siproc (c, tty))
|
if (siproc (c, tty))
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
@@ -687,8 +690,17 @@ fillBufferQueue (struct rtems_termios_tty *tty)
|
|||||||
if (tty->ccount >= tty->termios.c_cc[VMIN])
|
if (tty->ccount >= tty->termios.c_cc[VMIN])
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
timeout = tty->rawBufSemaphoreTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
timeout = tty->rawMessageTimeout;
|
/*
|
||||||
|
* Wait for characters
|
||||||
|
*/
|
||||||
|
sc = rtems_semaphore_obtain (tty->rawBufSemaphore,
|
||||||
|
tty->rawBufSemaphoreOptions,
|
||||||
|
timeout);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
@@ -732,15 +744,44 @@ void
|
|||||||
rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
|
rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
|
||||||
{
|
{
|
||||||
struct rtems_termios_tty *tty = ttyp;
|
struct rtems_termios_tty *tty = ttyp;
|
||||||
|
unsigned int newTail;
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
if (Ring_buffer_Is_full(&tty->rawInputBuffer))
|
newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
|
||||||
|
if (newTail == tty->rawBufHead) {
|
||||||
|
tty->rawBufDropped += len;
|
||||||
break;
|
break;
|
||||||
Ring_buffer_Add_character(&tty->rawInputBuffer, *buf);
|
|
||||||
if (rtems_semaphore_release(tty->rawInputSem) != RTEMS_SUCCESSFUL)
|
|
||||||
break;
|
|
||||||
len -= 1;
|
|
||||||
buf += 1;
|
|
||||||
}
|
}
|
||||||
|
tty->rawBuf[newTail] = *buf++;
|
||||||
|
len--;
|
||||||
|
tty->rawBufTail = newTail;
|
||||||
|
}
|
||||||
|
rtems_semaphore_release (tty->rawBufSemaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reserve enough resources to at least open every physical device
|
||||||
|
* once.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void rtems_termios_reserve_resources(
|
||||||
|
rtems_configuration_table *configuration,
|
||||||
|
rtems_unsigned32 number_of_devices
|
||||||
|
)
|
||||||
|
{
|
||||||
|
static int first_time = 1;
|
||||||
|
rtems_api_configuration_table *rtems_config;
|
||||||
|
|
||||||
|
if (!configuration)
|
||||||
|
rtems_fatal_error_occurred (0xFFF0F001);
|
||||||
|
|
||||||
|
rtems_config = configuration->RTEMS_api_configuration;
|
||||||
|
if (!rtems_config)
|
||||||
|
rtems_fatal_error_occurred (0xFFF0F002);
|
||||||
|
|
||||||
|
if (first_time)
|
||||||
|
rtems_config->maximum_semaphores += 1;
|
||||||
|
|
||||||
|
first_time = 0;
|
||||||
|
rtems_config->maximum_semaphores += (3 * number_of_devices);
|
||||||
|
}
|
||||||
|
|||||||
@@ -147,5 +147,9 @@ rtems_status_code rtems_termios_read (void *arg);
|
|||||||
rtems_status_code rtems_termios_write (void *arg);
|
rtems_status_code rtems_termios_write (void *arg);
|
||||||
rtems_status_code rtems_termios_ioctl (void *arg);
|
rtems_status_code rtems_termios_ioctl (void *arg);
|
||||||
void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
|
void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
|
||||||
|
void rtems_termios_reserve_resources(
|
||||||
|
rtems_configuration_table *configuration,
|
||||||
|
rtems_unsigned32 number_of_devices
|
||||||
|
);
|
||||||
|
|
||||||
#endif /* _RTEMS_LIBIO_H */
|
#endif /* _RTEMS_LIBIO_H */
|
||||||
|
|||||||
@@ -147,5 +147,9 @@ rtems_status_code rtems_termios_read (void *arg);
|
|||||||
rtems_status_code rtems_termios_write (void *arg);
|
rtems_status_code rtems_termios_write (void *arg);
|
||||||
rtems_status_code rtems_termios_ioctl (void *arg);
|
rtems_status_code rtems_termios_ioctl (void *arg);
|
||||||
void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
|
void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
|
||||||
|
void rtems_termios_reserve_resources(
|
||||||
|
rtems_configuration_table *configuration,
|
||||||
|
rtems_unsigned32 number_of_devices
|
||||||
|
);
|
||||||
|
|
||||||
#endif /* _RTEMS_LIBIO_H */
|
#endif /* _RTEMS_LIBIO_H */
|
||||||
|
|||||||
@@ -23,13 +23,17 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <ringbuf.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The size of the cooked buffer
|
* The size of the cooked buffer
|
||||||
*/
|
*/
|
||||||
#define CBUFSIZE 256
|
#define CBUFSIZE 256
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The size of the raw input message queue
|
||||||
|
*/
|
||||||
|
#define RAW_BUFFER_SIZE 128
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Variables associated with each termios instance.
|
* Variables associated with each termios instance.
|
||||||
* One structure for each hardware I/O device.
|
* One structure for each hardware I/O device.
|
||||||
@@ -80,18 +84,20 @@ struct rtems_termios_tty {
|
|||||||
/*
|
/*
|
||||||
* Raw character buffer
|
* Raw character buffer
|
||||||
*/
|
*/
|
||||||
rtems_id rawInputSem;
|
volatile char rawBuf[RAW_BUFFER_SIZE];
|
||||||
Ring_buffer_t rawInputBuffer;
|
volatile unsigned int rawBufHead;
|
||||||
|
volatile unsigned int rawBufTail;
|
||||||
rtems_unsigned32 rawMessageOptions;
|
rtems_id rawBufSemaphore;
|
||||||
rtems_interval rawMessageTimeout;
|
rtems_unsigned32 rawBufSemaphoreOptions;
|
||||||
rtems_interval rawMessageFirstTimeout;
|
rtems_interval rawBufSemaphoreTimeout;
|
||||||
|
rtems_interval rawBufSemaphoreFirstTimeout;
|
||||||
|
unsigned int rawBufDropped; /* Statistics */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Callbacks to device-specific routines
|
* Callbacks to device-specific routines
|
||||||
*/
|
*/
|
||||||
int (*lastClose)(int major, int minor, void *arg);
|
int (*lastClose)(int major, int minor, void *arg);
|
||||||
int (*read)(int minor, char *buf );
|
int (*read)(int minor, char *buf);
|
||||||
int (*write)(int minor, char *buf, int len);
|
int (*write)(int minor, char *buf, int len);
|
||||||
};
|
};
|
||||||
static struct rtems_termios_tty *ttyHead, *ttyTail;
|
static struct rtems_termios_tty *ttyHead, *ttyTail;
|
||||||
@@ -127,7 +133,7 @@ rtems_termios_open (
|
|||||||
void *arg,
|
void *arg,
|
||||||
int (*deviceFirstOpen)(int major, int minor, void *arg),
|
int (*deviceFirstOpen)(int major, int minor, void *arg),
|
||||||
int (*deviceLastClose)(int major, int minor, void *arg),
|
int (*deviceLastClose)(int major, int minor, void *arg),
|
||||||
int (*deviceRead)(int minor, char *buf/*, int len*/),
|
int (*deviceRead)(int minor, char *buf),
|
||||||
int (*deviceWrite)(int minor, char *buf, int len)
|
int (*deviceWrite)(int minor, char *buf, int len)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -191,11 +197,13 @@ rtems_termios_open (
|
|||||||
sc = rtems_semaphore_create (
|
sc = rtems_semaphore_create (
|
||||||
rtems_build_name ('T', 'R', 'r', c),
|
rtems_build_name ('T', 'R', 'r', c),
|
||||||
0,
|
0,
|
||||||
RTEMS_COUNTING_SEMAPHORE | RTEMS_FIFO | RTEMS_LOCAL,
|
RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
|
||||||
RTEMS_NO_PRIORITY,
|
RTEMS_NO_PRIORITY,
|
||||||
&tty->rawInputSem);
|
&tty->rawBufSemaphore);
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
rtems_fatal_error_occurred (sc);
|
rtems_fatal_error_occurred (sc);
|
||||||
|
tty->rawBufHead = 0;
|
||||||
|
tty->rawBufTail = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -268,7 +276,7 @@ rtems_termios_close (void *arg)
|
|||||||
rtems_semaphore_delete (tty->isem);
|
rtems_semaphore_delete (tty->isem);
|
||||||
rtems_semaphore_delete (tty->osem);
|
rtems_semaphore_delete (tty->osem);
|
||||||
if (tty->read == NULL)
|
if (tty->read == NULL)
|
||||||
rtems_semaphore_delete (tty->rawInputSem);
|
rtems_semaphore_delete (tty->rawBufSemaphore);
|
||||||
free (tty);
|
free (tty);
|
||||||
}
|
}
|
||||||
rtems_semaphore_release (ttyMutex);
|
rtems_semaphore_release (ttyMutex);
|
||||||
@@ -297,30 +305,30 @@ rtems_termios_ioctl (void *arg)
|
|||||||
case RTEMS_IO_SET_ATTRIBUTES:
|
case RTEMS_IO_SET_ATTRIBUTES:
|
||||||
tty->termios = *(struct termios *)args->buffer;
|
tty->termios = *(struct termios *)args->buffer;
|
||||||
if (tty->termios.c_lflag & ICANON) {
|
if (tty->termios.c_lflag & ICANON) {
|
||||||
tty->rawMessageOptions = RTEMS_WAIT;
|
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||||
tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
|
||||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rtems_interval ticksPerSecond;
|
rtems_interval ticksPerSecond;
|
||||||
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
|
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
|
||||||
tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
|
tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
|
||||||
if (tty->termios.c_cc[VTIME]) {
|
if (tty->termios.c_cc[VTIME]) {
|
||||||
tty->rawMessageOptions = RTEMS_WAIT;
|
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||||
tty->rawMessageTimeout = tty->vtimeTicks;
|
tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
|
||||||
if (tty->termios.c_cc[VMIN])
|
if (tty->termios.c_cc[VMIN])
|
||||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||||
else
|
else
|
||||||
tty->rawMessageFirstTimeout = tty->vtimeTicks;
|
tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (tty->termios.c_cc[VMIN]) {
|
if (tty->termios.c_cc[VMIN]) {
|
||||||
tty->rawMessageOptions = RTEMS_WAIT;
|
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||||
tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
|
||||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tty->rawMessageOptions = RTEMS_NO_WAIT;
|
tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -659,25 +667,20 @@ fillBufferPoll (struct rtems_termios_tty *tty)
|
|||||||
static rtems_status_code
|
static rtems_status_code
|
||||||
fillBufferQueue (struct rtems_termios_tty *tty)
|
fillBufferQueue (struct rtems_termios_tty *tty)
|
||||||
{
|
{
|
||||||
rtems_interval timeout = tty->rawMessageFirstTimeout;
|
rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
rtems_unsigned8 c;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
/*
|
|
||||||
* Read characters from raw queue
|
|
||||||
*/
|
|
||||||
sc = rtems_semaphore_obtain (tty->rawInputSem,
|
|
||||||
tty->rawMessageOptions,
|
|
||||||
timeout);
|
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
|
||||||
break;
|
|
||||||
Ring_buffer_Remove_character( &tty->rawInputBuffer, c );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process characters read from raw queue
|
* Process characters read from raw queue
|
||||||
*/
|
*/
|
||||||
|
while (tty->rawBufHead != tty->rawBufTail) {
|
||||||
|
unsigned char c;
|
||||||
|
unsigned int newHead;
|
||||||
|
|
||||||
|
newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE;
|
||||||
|
c = tty->rawBuf[newHead];
|
||||||
|
tty->rawBufHead = newHead;
|
||||||
if (tty->termios.c_lflag & ICANON) {
|
if (tty->termios.c_lflag & ICANON) {
|
||||||
if (siproc (c, tty))
|
if (siproc (c, tty))
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
@@ -687,8 +690,17 @@ fillBufferQueue (struct rtems_termios_tty *tty)
|
|||||||
if (tty->ccount >= tty->termios.c_cc[VMIN])
|
if (tty->ccount >= tty->termios.c_cc[VMIN])
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
timeout = tty->rawBufSemaphoreTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
timeout = tty->rawMessageTimeout;
|
/*
|
||||||
|
* Wait for characters
|
||||||
|
*/
|
||||||
|
sc = rtems_semaphore_obtain (tty->rawBufSemaphore,
|
||||||
|
tty->rawBufSemaphoreOptions,
|
||||||
|
timeout);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
@@ -732,15 +744,44 @@ void
|
|||||||
rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
|
rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
|
||||||
{
|
{
|
||||||
struct rtems_termios_tty *tty = ttyp;
|
struct rtems_termios_tty *tty = ttyp;
|
||||||
|
unsigned int newTail;
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
if (Ring_buffer_Is_full(&tty->rawInputBuffer))
|
newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
|
||||||
|
if (newTail == tty->rawBufHead) {
|
||||||
|
tty->rawBufDropped += len;
|
||||||
break;
|
break;
|
||||||
Ring_buffer_Add_character(&tty->rawInputBuffer, *buf);
|
|
||||||
if (rtems_semaphore_release(tty->rawInputSem) != RTEMS_SUCCESSFUL)
|
|
||||||
break;
|
|
||||||
len -= 1;
|
|
||||||
buf += 1;
|
|
||||||
}
|
}
|
||||||
|
tty->rawBuf[newTail] = *buf++;
|
||||||
|
len--;
|
||||||
|
tty->rawBufTail = newTail;
|
||||||
|
}
|
||||||
|
rtems_semaphore_release (tty->rawBufSemaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reserve enough resources to at least open every physical device
|
||||||
|
* once.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void rtems_termios_reserve_resources(
|
||||||
|
rtems_configuration_table *configuration,
|
||||||
|
rtems_unsigned32 number_of_devices
|
||||||
|
)
|
||||||
|
{
|
||||||
|
static int first_time = 1;
|
||||||
|
rtems_api_configuration_table *rtems_config;
|
||||||
|
|
||||||
|
if (!configuration)
|
||||||
|
rtems_fatal_error_occurred (0xFFF0F001);
|
||||||
|
|
||||||
|
rtems_config = configuration->RTEMS_api_configuration;
|
||||||
|
if (!rtems_config)
|
||||||
|
rtems_fatal_error_occurred (0xFFF0F002);
|
||||||
|
|
||||||
|
if (first_time)
|
||||||
|
rtems_config->maximum_semaphores += 1;
|
||||||
|
|
||||||
|
first_time = 0;
|
||||||
|
rtems_config->maximum_semaphores += (3 * number_of_devices);
|
||||||
|
}
|
||||||
|
|||||||
@@ -147,5 +147,9 @@ rtems_status_code rtems_termios_read (void *arg);
|
|||||||
rtems_status_code rtems_termios_write (void *arg);
|
rtems_status_code rtems_termios_write (void *arg);
|
||||||
rtems_status_code rtems_termios_ioctl (void *arg);
|
rtems_status_code rtems_termios_ioctl (void *arg);
|
||||||
void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
|
void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
|
||||||
|
void rtems_termios_reserve_resources(
|
||||||
|
rtems_configuration_table *configuration,
|
||||||
|
rtems_unsigned32 number_of_devices
|
||||||
|
);
|
||||||
|
|
||||||
#endif /* _RTEMS_LIBIO_H */
|
#endif /* _RTEMS_LIBIO_H */
|
||||||
|
|||||||
@@ -23,13 +23,17 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <ringbuf.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The size of the cooked buffer
|
* The size of the cooked buffer
|
||||||
*/
|
*/
|
||||||
#define CBUFSIZE 256
|
#define CBUFSIZE 256
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The size of the raw input message queue
|
||||||
|
*/
|
||||||
|
#define RAW_BUFFER_SIZE 128
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Variables associated with each termios instance.
|
* Variables associated with each termios instance.
|
||||||
* One structure for each hardware I/O device.
|
* One structure for each hardware I/O device.
|
||||||
@@ -80,18 +84,20 @@ struct rtems_termios_tty {
|
|||||||
/*
|
/*
|
||||||
* Raw character buffer
|
* Raw character buffer
|
||||||
*/
|
*/
|
||||||
rtems_id rawInputSem;
|
volatile char rawBuf[RAW_BUFFER_SIZE];
|
||||||
Ring_buffer_t rawInputBuffer;
|
volatile unsigned int rawBufHead;
|
||||||
|
volatile unsigned int rawBufTail;
|
||||||
rtems_unsigned32 rawMessageOptions;
|
rtems_id rawBufSemaphore;
|
||||||
rtems_interval rawMessageTimeout;
|
rtems_unsigned32 rawBufSemaphoreOptions;
|
||||||
rtems_interval rawMessageFirstTimeout;
|
rtems_interval rawBufSemaphoreTimeout;
|
||||||
|
rtems_interval rawBufSemaphoreFirstTimeout;
|
||||||
|
unsigned int rawBufDropped; /* Statistics */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Callbacks to device-specific routines
|
* Callbacks to device-specific routines
|
||||||
*/
|
*/
|
||||||
int (*lastClose)(int major, int minor, void *arg);
|
int (*lastClose)(int major, int minor, void *arg);
|
||||||
int (*read)(int minor, char *buf );
|
int (*read)(int minor, char *buf);
|
||||||
int (*write)(int minor, char *buf, int len);
|
int (*write)(int minor, char *buf, int len);
|
||||||
};
|
};
|
||||||
static struct rtems_termios_tty *ttyHead, *ttyTail;
|
static struct rtems_termios_tty *ttyHead, *ttyTail;
|
||||||
@@ -127,7 +133,7 @@ rtems_termios_open (
|
|||||||
void *arg,
|
void *arg,
|
||||||
int (*deviceFirstOpen)(int major, int minor, void *arg),
|
int (*deviceFirstOpen)(int major, int minor, void *arg),
|
||||||
int (*deviceLastClose)(int major, int minor, void *arg),
|
int (*deviceLastClose)(int major, int minor, void *arg),
|
||||||
int (*deviceRead)(int minor, char *buf/*, int len*/),
|
int (*deviceRead)(int minor, char *buf),
|
||||||
int (*deviceWrite)(int minor, char *buf, int len)
|
int (*deviceWrite)(int minor, char *buf, int len)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -191,11 +197,13 @@ rtems_termios_open (
|
|||||||
sc = rtems_semaphore_create (
|
sc = rtems_semaphore_create (
|
||||||
rtems_build_name ('T', 'R', 'r', c),
|
rtems_build_name ('T', 'R', 'r', c),
|
||||||
0,
|
0,
|
||||||
RTEMS_COUNTING_SEMAPHORE | RTEMS_FIFO | RTEMS_LOCAL,
|
RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
|
||||||
RTEMS_NO_PRIORITY,
|
RTEMS_NO_PRIORITY,
|
||||||
&tty->rawInputSem);
|
&tty->rawBufSemaphore);
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
rtems_fatal_error_occurred (sc);
|
rtems_fatal_error_occurred (sc);
|
||||||
|
tty->rawBufHead = 0;
|
||||||
|
tty->rawBufTail = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -268,7 +276,7 @@ rtems_termios_close (void *arg)
|
|||||||
rtems_semaphore_delete (tty->isem);
|
rtems_semaphore_delete (tty->isem);
|
||||||
rtems_semaphore_delete (tty->osem);
|
rtems_semaphore_delete (tty->osem);
|
||||||
if (tty->read == NULL)
|
if (tty->read == NULL)
|
||||||
rtems_semaphore_delete (tty->rawInputSem);
|
rtems_semaphore_delete (tty->rawBufSemaphore);
|
||||||
free (tty);
|
free (tty);
|
||||||
}
|
}
|
||||||
rtems_semaphore_release (ttyMutex);
|
rtems_semaphore_release (ttyMutex);
|
||||||
@@ -297,30 +305,30 @@ rtems_termios_ioctl (void *arg)
|
|||||||
case RTEMS_IO_SET_ATTRIBUTES:
|
case RTEMS_IO_SET_ATTRIBUTES:
|
||||||
tty->termios = *(struct termios *)args->buffer;
|
tty->termios = *(struct termios *)args->buffer;
|
||||||
if (tty->termios.c_lflag & ICANON) {
|
if (tty->termios.c_lflag & ICANON) {
|
||||||
tty->rawMessageOptions = RTEMS_WAIT;
|
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||||
tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
|
||||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rtems_interval ticksPerSecond;
|
rtems_interval ticksPerSecond;
|
||||||
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
|
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
|
||||||
tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
|
tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
|
||||||
if (tty->termios.c_cc[VTIME]) {
|
if (tty->termios.c_cc[VTIME]) {
|
||||||
tty->rawMessageOptions = RTEMS_WAIT;
|
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||||
tty->rawMessageTimeout = tty->vtimeTicks;
|
tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
|
||||||
if (tty->termios.c_cc[VMIN])
|
if (tty->termios.c_cc[VMIN])
|
||||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||||
else
|
else
|
||||||
tty->rawMessageFirstTimeout = tty->vtimeTicks;
|
tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (tty->termios.c_cc[VMIN]) {
|
if (tty->termios.c_cc[VMIN]) {
|
||||||
tty->rawMessageOptions = RTEMS_WAIT;
|
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||||
tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
|
||||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tty->rawMessageOptions = RTEMS_NO_WAIT;
|
tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -659,25 +667,20 @@ fillBufferPoll (struct rtems_termios_tty *tty)
|
|||||||
static rtems_status_code
|
static rtems_status_code
|
||||||
fillBufferQueue (struct rtems_termios_tty *tty)
|
fillBufferQueue (struct rtems_termios_tty *tty)
|
||||||
{
|
{
|
||||||
rtems_interval timeout = tty->rawMessageFirstTimeout;
|
rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
|
||||||
rtems_status_code sc;
|
rtems_status_code sc;
|
||||||
rtems_unsigned8 c;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
||||||
/*
|
|
||||||
* Read characters from raw queue
|
|
||||||
*/
|
|
||||||
sc = rtems_semaphore_obtain (tty->rawInputSem,
|
|
||||||
tty->rawMessageOptions,
|
|
||||||
timeout);
|
|
||||||
if (sc != RTEMS_SUCCESSFUL)
|
|
||||||
break;
|
|
||||||
Ring_buffer_Remove_character( &tty->rawInputBuffer, c );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Process characters read from raw queue
|
* Process characters read from raw queue
|
||||||
*/
|
*/
|
||||||
|
while (tty->rawBufHead != tty->rawBufTail) {
|
||||||
|
unsigned char c;
|
||||||
|
unsigned int newHead;
|
||||||
|
|
||||||
|
newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE;
|
||||||
|
c = tty->rawBuf[newHead];
|
||||||
|
tty->rawBufHead = newHead;
|
||||||
if (tty->termios.c_lflag & ICANON) {
|
if (tty->termios.c_lflag & ICANON) {
|
||||||
if (siproc (c, tty))
|
if (siproc (c, tty))
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
@@ -687,8 +690,17 @@ fillBufferQueue (struct rtems_termios_tty *tty)
|
|||||||
if (tty->ccount >= tty->termios.c_cc[VMIN])
|
if (tty->ccount >= tty->termios.c_cc[VMIN])
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
timeout = tty->rawBufSemaphoreTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
timeout = tty->rawMessageTimeout;
|
/*
|
||||||
|
* Wait for characters
|
||||||
|
*/
|
||||||
|
sc = rtems_semaphore_obtain (tty->rawBufSemaphore,
|
||||||
|
tty->rawBufSemaphoreOptions,
|
||||||
|
timeout);
|
||||||
|
if (sc != RTEMS_SUCCESSFUL)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
@@ -732,15 +744,44 @@ void
|
|||||||
rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
|
rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
|
||||||
{
|
{
|
||||||
struct rtems_termios_tty *tty = ttyp;
|
struct rtems_termios_tty *tty = ttyp;
|
||||||
|
unsigned int newTail;
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
if (Ring_buffer_Is_full(&tty->rawInputBuffer))
|
newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
|
||||||
|
if (newTail == tty->rawBufHead) {
|
||||||
|
tty->rawBufDropped += len;
|
||||||
break;
|
break;
|
||||||
Ring_buffer_Add_character(&tty->rawInputBuffer, *buf);
|
|
||||||
if (rtems_semaphore_release(tty->rawInputSem) != RTEMS_SUCCESSFUL)
|
|
||||||
break;
|
|
||||||
len -= 1;
|
|
||||||
buf += 1;
|
|
||||||
}
|
}
|
||||||
|
tty->rawBuf[newTail] = *buf++;
|
||||||
|
len--;
|
||||||
|
tty->rawBufTail = newTail;
|
||||||
|
}
|
||||||
|
rtems_semaphore_release (tty->rawBufSemaphore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reserve enough resources to at least open every physical device
|
||||||
|
* once.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void rtems_termios_reserve_resources(
|
||||||
|
rtems_configuration_table *configuration,
|
||||||
|
rtems_unsigned32 number_of_devices
|
||||||
|
)
|
||||||
|
{
|
||||||
|
static int first_time = 1;
|
||||||
|
rtems_api_configuration_table *rtems_config;
|
||||||
|
|
||||||
|
if (!configuration)
|
||||||
|
rtems_fatal_error_occurred (0xFFF0F001);
|
||||||
|
|
||||||
|
rtems_config = configuration->RTEMS_api_configuration;
|
||||||
|
if (!rtems_config)
|
||||||
|
rtems_fatal_error_occurred (0xFFF0F002);
|
||||||
|
|
||||||
|
if (first_time)
|
||||||
|
rtems_config->maximum_semaphores += 1;
|
||||||
|
|
||||||
|
first_time = 0;
|
||||||
|
rtems_config->maximum_semaphores += (3 * number_of_devices);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user