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_ioctl (void *arg);
|
||||
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 */
|
||||
|
||||
@@ -23,13 +23,17 @@
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <ringbuf.h>
|
||||
|
||||
/*
|
||||
* The size of the cooked buffer
|
||||
*/
|
||||
#define CBUFSIZE 256
|
||||
|
||||
/*
|
||||
* The size of the raw input message queue
|
||||
*/
|
||||
#define RAW_BUFFER_SIZE 128
|
||||
|
||||
/*
|
||||
* Variables associated with each termios instance.
|
||||
* One structure for each hardware I/O device.
|
||||
@@ -80,18 +84,20 @@ struct rtems_termios_tty {
|
||||
/*
|
||||
* Raw character buffer
|
||||
*/
|
||||
rtems_id rawInputSem;
|
||||
Ring_buffer_t rawInputBuffer;
|
||||
|
||||
rtems_unsigned32 rawMessageOptions;
|
||||
rtems_interval rawMessageTimeout;
|
||||
rtems_interval rawMessageFirstTimeout;
|
||||
volatile char rawBuf[RAW_BUFFER_SIZE];
|
||||
volatile unsigned int rawBufHead;
|
||||
volatile unsigned int rawBufTail;
|
||||
rtems_id rawBufSemaphore;
|
||||
rtems_unsigned32 rawBufSemaphoreOptions;
|
||||
rtems_interval rawBufSemaphoreTimeout;
|
||||
rtems_interval rawBufSemaphoreFirstTimeout;
|
||||
unsigned int rawBufDropped; /* Statistics */
|
||||
|
||||
/*
|
||||
* Callbacks to device-specific routines
|
||||
*/
|
||||
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);
|
||||
};
|
||||
static struct rtems_termios_tty *ttyHead, *ttyTail;
|
||||
@@ -127,7 +133,7 @@ rtems_termios_open (
|
||||
void *arg,
|
||||
int (*deviceFirstOpen)(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)
|
||||
)
|
||||
{
|
||||
@@ -191,11 +197,13 @@ rtems_termios_open (
|
||||
sc = rtems_semaphore_create (
|
||||
rtems_build_name ('T', 'R', 'r', c),
|
||||
0,
|
||||
RTEMS_COUNTING_SEMAPHORE | RTEMS_FIFO | RTEMS_LOCAL,
|
||||
RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
|
||||
RTEMS_NO_PRIORITY,
|
||||
&tty->rawInputSem);
|
||||
&tty->rawBufSemaphore);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
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->osem);
|
||||
if (tty->read == NULL)
|
||||
rtems_semaphore_delete (tty->rawInputSem);
|
||||
rtems_semaphore_delete (tty->rawBufSemaphore);
|
||||
free (tty);
|
||||
}
|
||||
rtems_semaphore_release (ttyMutex);
|
||||
@@ -297,30 +305,30 @@ rtems_termios_ioctl (void *arg)
|
||||
case RTEMS_IO_SET_ATTRIBUTES:
|
||||
tty->termios = *(struct termios *)args->buffer;
|
||||
if (tty->termios.c_lflag & ICANON) {
|
||||
tty->rawMessageOptions = RTEMS_WAIT;
|
||||
tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||
tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
}
|
||||
else {
|
||||
rtems_interval ticksPerSecond;
|
||||
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
|
||||
tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
|
||||
if (tty->termios.c_cc[VTIME]) {
|
||||
tty->rawMessageOptions = RTEMS_WAIT;
|
||||
tty->rawMessageTimeout = tty->vtimeTicks;
|
||||
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||
tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
|
||||
if (tty->termios.c_cc[VMIN])
|
||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
else
|
||||
tty->rawMessageFirstTimeout = tty->vtimeTicks;
|
||||
tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
|
||||
}
|
||||
else {
|
||||
if (tty->termios.c_cc[VMIN]) {
|
||||
tty->rawMessageOptions = RTEMS_WAIT;
|
||||
tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||
tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
}
|
||||
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
|
||||
fillBufferQueue (struct rtems_termios_tty *tty)
|
||||
{
|
||||
rtems_interval timeout = tty->rawMessageFirstTimeout;
|
||||
rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
|
||||
rtems_status_code sc;
|
||||
rtems_unsigned8 c;
|
||||
|
||||
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
|
||||
*/
|
||||
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 (siproc (c, tty))
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@@ -687,8 +690,17 @@ fillBufferQueue (struct rtems_termios_tty *tty)
|
||||
if (tty->ccount >= tty->termios.c_cc[VMIN])
|
||||
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;
|
||||
}
|
||||
@@ -732,15 +744,44 @@ void
|
||||
rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
|
||||
{
|
||||
struct rtems_termios_tty *tty = ttyp;
|
||||
unsigned int newTail;
|
||||
|
||||
while (len) {
|
||||
if (Ring_buffer_Is_full(&tty->rawInputBuffer))
|
||||
newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
|
||||
if (newTail == tty->rawBufHead) {
|
||||
tty->rawBufDropped += len;
|
||||
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_ioctl (void *arg);
|
||||
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 */
|
||||
|
||||
@@ -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_ioctl (void *arg);
|
||||
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 */
|
||||
|
||||
@@ -23,13 +23,17 @@
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <ringbuf.h>
|
||||
|
||||
/*
|
||||
* The size of the cooked buffer
|
||||
*/
|
||||
#define CBUFSIZE 256
|
||||
|
||||
/*
|
||||
* The size of the raw input message queue
|
||||
*/
|
||||
#define RAW_BUFFER_SIZE 128
|
||||
|
||||
/*
|
||||
* Variables associated with each termios instance.
|
||||
* One structure for each hardware I/O device.
|
||||
@@ -80,18 +84,20 @@ struct rtems_termios_tty {
|
||||
/*
|
||||
* Raw character buffer
|
||||
*/
|
||||
rtems_id rawInputSem;
|
||||
Ring_buffer_t rawInputBuffer;
|
||||
|
||||
rtems_unsigned32 rawMessageOptions;
|
||||
rtems_interval rawMessageTimeout;
|
||||
rtems_interval rawMessageFirstTimeout;
|
||||
volatile char rawBuf[RAW_BUFFER_SIZE];
|
||||
volatile unsigned int rawBufHead;
|
||||
volatile unsigned int rawBufTail;
|
||||
rtems_id rawBufSemaphore;
|
||||
rtems_unsigned32 rawBufSemaphoreOptions;
|
||||
rtems_interval rawBufSemaphoreTimeout;
|
||||
rtems_interval rawBufSemaphoreFirstTimeout;
|
||||
unsigned int rawBufDropped; /* Statistics */
|
||||
|
||||
/*
|
||||
* Callbacks to device-specific routines
|
||||
*/
|
||||
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);
|
||||
};
|
||||
static struct rtems_termios_tty *ttyHead, *ttyTail;
|
||||
@@ -127,7 +133,7 @@ rtems_termios_open (
|
||||
void *arg,
|
||||
int (*deviceFirstOpen)(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)
|
||||
)
|
||||
{
|
||||
@@ -191,11 +197,13 @@ rtems_termios_open (
|
||||
sc = rtems_semaphore_create (
|
||||
rtems_build_name ('T', 'R', 'r', c),
|
||||
0,
|
||||
RTEMS_COUNTING_SEMAPHORE | RTEMS_FIFO | RTEMS_LOCAL,
|
||||
RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
|
||||
RTEMS_NO_PRIORITY,
|
||||
&tty->rawInputSem);
|
||||
&tty->rawBufSemaphore);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
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->osem);
|
||||
if (tty->read == NULL)
|
||||
rtems_semaphore_delete (tty->rawInputSem);
|
||||
rtems_semaphore_delete (tty->rawBufSemaphore);
|
||||
free (tty);
|
||||
}
|
||||
rtems_semaphore_release (ttyMutex);
|
||||
@@ -297,30 +305,30 @@ rtems_termios_ioctl (void *arg)
|
||||
case RTEMS_IO_SET_ATTRIBUTES:
|
||||
tty->termios = *(struct termios *)args->buffer;
|
||||
if (tty->termios.c_lflag & ICANON) {
|
||||
tty->rawMessageOptions = RTEMS_WAIT;
|
||||
tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||
tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
}
|
||||
else {
|
||||
rtems_interval ticksPerSecond;
|
||||
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
|
||||
tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
|
||||
if (tty->termios.c_cc[VTIME]) {
|
||||
tty->rawMessageOptions = RTEMS_WAIT;
|
||||
tty->rawMessageTimeout = tty->vtimeTicks;
|
||||
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||
tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
|
||||
if (tty->termios.c_cc[VMIN])
|
||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
else
|
||||
tty->rawMessageFirstTimeout = tty->vtimeTicks;
|
||||
tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
|
||||
}
|
||||
else {
|
||||
if (tty->termios.c_cc[VMIN]) {
|
||||
tty->rawMessageOptions = RTEMS_WAIT;
|
||||
tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||
tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
}
|
||||
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
|
||||
fillBufferQueue (struct rtems_termios_tty *tty)
|
||||
{
|
||||
rtems_interval timeout = tty->rawMessageFirstTimeout;
|
||||
rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
|
||||
rtems_status_code sc;
|
||||
rtems_unsigned8 c;
|
||||
|
||||
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
|
||||
*/
|
||||
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 (siproc (c, tty))
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@@ -687,8 +690,17 @@ fillBufferQueue (struct rtems_termios_tty *tty)
|
||||
if (tty->ccount >= tty->termios.c_cc[VMIN])
|
||||
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;
|
||||
}
|
||||
@@ -732,15 +744,44 @@ void
|
||||
rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
|
||||
{
|
||||
struct rtems_termios_tty *tty = ttyp;
|
||||
unsigned int newTail;
|
||||
|
||||
while (len) {
|
||||
if (Ring_buffer_Is_full(&tty->rawInputBuffer))
|
||||
newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
|
||||
if (newTail == tty->rawBufHead) {
|
||||
tty->rawBufDropped += len;
|
||||
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_ioctl (void *arg);
|
||||
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 */
|
||||
|
||||
@@ -23,13 +23,17 @@
|
||||
#include <stdlib.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <ringbuf.h>
|
||||
|
||||
/*
|
||||
* The size of the cooked buffer
|
||||
*/
|
||||
#define CBUFSIZE 256
|
||||
|
||||
/*
|
||||
* The size of the raw input message queue
|
||||
*/
|
||||
#define RAW_BUFFER_SIZE 128
|
||||
|
||||
/*
|
||||
* Variables associated with each termios instance.
|
||||
* One structure for each hardware I/O device.
|
||||
@@ -80,18 +84,20 @@ struct rtems_termios_tty {
|
||||
/*
|
||||
* Raw character buffer
|
||||
*/
|
||||
rtems_id rawInputSem;
|
||||
Ring_buffer_t rawInputBuffer;
|
||||
|
||||
rtems_unsigned32 rawMessageOptions;
|
||||
rtems_interval rawMessageTimeout;
|
||||
rtems_interval rawMessageFirstTimeout;
|
||||
volatile char rawBuf[RAW_BUFFER_SIZE];
|
||||
volatile unsigned int rawBufHead;
|
||||
volatile unsigned int rawBufTail;
|
||||
rtems_id rawBufSemaphore;
|
||||
rtems_unsigned32 rawBufSemaphoreOptions;
|
||||
rtems_interval rawBufSemaphoreTimeout;
|
||||
rtems_interval rawBufSemaphoreFirstTimeout;
|
||||
unsigned int rawBufDropped; /* Statistics */
|
||||
|
||||
/*
|
||||
* Callbacks to device-specific routines
|
||||
*/
|
||||
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);
|
||||
};
|
||||
static struct rtems_termios_tty *ttyHead, *ttyTail;
|
||||
@@ -127,7 +133,7 @@ rtems_termios_open (
|
||||
void *arg,
|
||||
int (*deviceFirstOpen)(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)
|
||||
)
|
||||
{
|
||||
@@ -191,11 +197,13 @@ rtems_termios_open (
|
||||
sc = rtems_semaphore_create (
|
||||
rtems_build_name ('T', 'R', 'r', c),
|
||||
0,
|
||||
RTEMS_COUNTING_SEMAPHORE | RTEMS_FIFO | RTEMS_LOCAL,
|
||||
RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
|
||||
RTEMS_NO_PRIORITY,
|
||||
&tty->rawInputSem);
|
||||
&tty->rawBufSemaphore);
|
||||
if (sc != RTEMS_SUCCESSFUL)
|
||||
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->osem);
|
||||
if (tty->read == NULL)
|
||||
rtems_semaphore_delete (tty->rawInputSem);
|
||||
rtems_semaphore_delete (tty->rawBufSemaphore);
|
||||
free (tty);
|
||||
}
|
||||
rtems_semaphore_release (ttyMutex);
|
||||
@@ -297,30 +305,30 @@ rtems_termios_ioctl (void *arg)
|
||||
case RTEMS_IO_SET_ATTRIBUTES:
|
||||
tty->termios = *(struct termios *)args->buffer;
|
||||
if (tty->termios.c_lflag & ICANON) {
|
||||
tty->rawMessageOptions = RTEMS_WAIT;
|
||||
tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||
tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
}
|
||||
else {
|
||||
rtems_interval ticksPerSecond;
|
||||
rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
|
||||
tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
|
||||
if (tty->termios.c_cc[VTIME]) {
|
||||
tty->rawMessageOptions = RTEMS_WAIT;
|
||||
tty->rawMessageTimeout = tty->vtimeTicks;
|
||||
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||
tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
|
||||
if (tty->termios.c_cc[VMIN])
|
||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
else
|
||||
tty->rawMessageFirstTimeout = tty->vtimeTicks;
|
||||
tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
|
||||
}
|
||||
else {
|
||||
if (tty->termios.c_cc[VMIN]) {
|
||||
tty->rawMessageOptions = RTEMS_WAIT;
|
||||
tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreOptions = RTEMS_WAIT;
|
||||
tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
|
||||
tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
|
||||
}
|
||||
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
|
||||
fillBufferQueue (struct rtems_termios_tty *tty)
|
||||
{
|
||||
rtems_interval timeout = tty->rawMessageFirstTimeout;
|
||||
rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
|
||||
rtems_status_code sc;
|
||||
rtems_unsigned8 c;
|
||||
|
||||
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
|
||||
*/
|
||||
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 (siproc (c, tty))
|
||||
return RTEMS_SUCCESSFUL;
|
||||
@@ -687,8 +690,17 @@ fillBufferQueue (struct rtems_termios_tty *tty)
|
||||
if (tty->ccount >= tty->termios.c_cc[VMIN])
|
||||
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;
|
||||
}
|
||||
@@ -732,15 +744,44 @@ void
|
||||
rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
|
||||
{
|
||||
struct rtems_termios_tty *tty = ttyp;
|
||||
unsigned int newTail;
|
||||
|
||||
while (len) {
|
||||
if (Ring_buffer_Is_full(&tty->rawInputBuffer))
|
||||
newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
|
||||
if (newTail == tty->rawBufHead) {
|
||||
tty->rawBufDropped += len;
|
||||
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