New termios.c from Eric Norum.

Added new entry point to add in per physical port resource requirements.
This commit is contained in:
Joel Sherrill
1997-10-23 13:13:46 +00:00
parent 3dbcece75a
commit 118a81295d
7 changed files with 1825 additions and 1686 deletions

View File

@@ -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 */

View File

@@ -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,12 +84,14 @@ 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
@@ -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);
}

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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,12 +84,14 @@ 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
@@ -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);
}

View File

@@ -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 */

View File

@@ -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,12 +84,14 @@ 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
@@ -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);
}