File indexing completed on 2025-05-11 08:24:15
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifdef HAVE_CONFIG_H
0029 #include "config.h"
0030 #endif
0031
0032 #include <rtems/console.h>
0033 #include <rtems/bspIo.h>
0034 #include <rtems/imfs.h>
0035 #include <rtems/thread.h>
0036
0037 #include "consolesimple.h"
0038
0039 #define CONSOLE_SIMPLE_TASK_BUFFER_SIZE 2048
0040
0041 #define CONSOLE_SIMPLE_TASK_MAX_JUNK_SIZE 80
0042
0043 typedef struct {
0044 IMFS_jnode_t Node;
0045 RTEMS_INTERRUPT_LOCK_MEMBER( buf_lock )
0046 rtems_mutex output_mutex;
0047 rtems_id task;
0048 size_t head;
0049 size_t tail;
0050 char buf[ CONSOLE_SIMPLE_TASK_BUFFER_SIZE ];
0051 } Console_simple_task_Control;
0052
0053 static Console_simple_task_Control _Console_simple_task_Instance;
0054
0055 static size_t _Console_simple_task_Capacity(
0056 const Console_simple_task_Control *cons
0057 )
0058 {
0059 return ( cons->tail - cons->head - 1 ) % CONSOLE_SIMPLE_TASK_BUFFER_SIZE;
0060 }
0061
0062 static size_t _Console_simple_task_Available(
0063 const Console_simple_task_Control *cons
0064 )
0065 {
0066 return ( cons->head - cons->tail ) % CONSOLE_SIMPLE_TASK_BUFFER_SIZE;
0067 }
0068
0069 static Console_simple_task_Control *_Console_simple_task_Iop_to_control(
0070 const rtems_libio_t *iop
0071 )
0072 {
0073 return (Console_simple_task_Control *) IMFS_iop_to_node( iop );
0074 }
0075
0076 static ssize_t _Console_simple_task_Write(
0077 rtems_libio_t *iop,
0078 const void *buffer,
0079 size_t count
0080 )
0081 {
0082 Console_simple_task_Control *cons;
0083 const char *buf;
0084 size_t todo;
0085
0086 cons = _Console_simple_task_Iop_to_control( iop );
0087 buf = buffer;
0088 todo = count;
0089
0090 while ( todo > 0 ) {
0091 rtems_interrupt_lock_context lock_context;
0092 size_t junk;
0093 size_t head;
0094 size_t i;
0095
0096 rtems_interrupt_lock_acquire( &cons->buf_lock, &lock_context );
0097
0098 junk = _Console_simple_task_Capacity( cons );
0099
0100 if ( junk > todo ) {
0101 junk = todo;
0102 }
0103
0104 if ( junk > CONSOLE_SIMPLE_TASK_MAX_JUNK_SIZE ) {
0105 junk = CONSOLE_SIMPLE_TASK_MAX_JUNK_SIZE;
0106 }
0107
0108 head = cons->head;
0109
0110 for ( i = 0; i < junk; ++i ) {
0111 cons->buf[ head ] = *buf;
0112 head = ( head + 1 ) % CONSOLE_SIMPLE_TASK_BUFFER_SIZE;
0113 --todo;
0114 ++buf;
0115 }
0116
0117 cons->head = head;
0118
0119 rtems_interrupt_lock_release( &cons->buf_lock, &lock_context );
0120
0121 if ( junk == 0 ) {
0122 break;
0123 }
0124 }
0125
0126 rtems_event_system_send( cons->task, RTEMS_EVENT_SYSTEM_SERVER );
0127
0128 return (ssize_t) ( count - todo );
0129 }
0130
0131 static void _Console_simple_task_Put_chars( Console_simple_task_Control *cons )
0132 {
0133 rtems_interrupt_lock_context lock_context;
0134 size_t available;
0135 size_t tail;
0136 size_t i;
0137
0138 rtems_mutex_lock( &cons->output_mutex );
0139
0140 rtems_interrupt_lock_acquire( &cons->buf_lock, &lock_context );
0141
0142 available = _Console_simple_task_Available( cons );
0143 tail = cons->tail;
0144
0145 rtems_interrupt_lock_release( &cons->buf_lock, &lock_context );
0146
0147 for ( i = 0; i < available; ++i) {
0148 rtems_putc( cons->buf[ tail ] );
0149 tail = ( tail + 1 ) % CONSOLE_SIMPLE_TASK_BUFFER_SIZE;
0150 }
0151
0152 rtems_interrupt_lock_acquire( &cons->buf_lock, &lock_context );
0153
0154 cons->tail = tail;
0155
0156 rtems_interrupt_lock_release( &cons->buf_lock, &lock_context );
0157
0158 rtems_mutex_unlock( &cons->output_mutex );
0159 }
0160
0161 static int _Console_simple_task_Fsync( rtems_libio_t *iop )
0162 {
0163 Console_simple_task_Control *cons;
0164
0165 cons = _Console_simple_task_Iop_to_control( iop );
0166 _Console_simple_task_Put_chars( cons );
0167
0168 return 0;
0169 }
0170
0171 static const rtems_filesystem_file_handlers_r _Console_simple_task_Handlers = {
0172 .open_h = rtems_filesystem_default_open,
0173 .close_h = rtems_filesystem_default_close,
0174 .read_h = _Console_simple_Read,
0175 .write_h = _Console_simple_task_Write,
0176 .ioctl_h = rtems_filesystem_default_ioctl,
0177 .lseek_h = rtems_filesystem_default_lseek,
0178 .fstat_h = IMFS_stat,
0179 .ftruncate_h = rtems_filesystem_default_ftruncate,
0180 .fsync_h = _Console_simple_task_Fsync,
0181 .fdatasync_h = _Console_simple_task_Fsync,
0182 .fcntl_h = rtems_filesystem_default_fcntl,
0183 .readv_h = rtems_filesystem_default_readv,
0184 .writev_h = rtems_filesystem_default_writev,
0185 .mmap_h = rtems_filesystem_default_mmap
0186 };
0187
0188 static const IMFS_node_control
0189 _Console_simple_task_Node_control = IMFS_NODE_CONTROL_INITIALIZER(
0190 &_Console_simple_task_Handlers,
0191 IMFS_node_initialize_default,
0192 IMFS_do_nothing_destroy
0193 );
0194
0195 static void _Console_simple_task_Task( rtems_task_argument arg )
0196 {
0197 Console_simple_task_Control *cons;
0198
0199 cons = (Console_simple_task_Control *) arg;
0200
0201 while ( true ) {
0202 rtems_event_set events;
0203
0204 rtems_event_system_receive(
0205 RTEMS_EVENT_SYSTEM_SERVER,
0206 RTEMS_WAIT | RTEMS_EVENT_ALL,
0207 RTEMS_NO_TIMEOUT,
0208 &events
0209 );
0210
0211 _Console_simple_task_Put_chars( cons );
0212 }
0213 }
0214
0215 static const char _Console_simple_task_Name[] = "console";
0216
0217 void _Console_simple_task_Initialize( void )
0218 {
0219 Console_simple_task_Control *cons;
0220 rtems_status_code status;
0221
0222 cons = &_Console_simple_task_Instance;
0223
0224 IMFS_node_preinitialize(
0225 &cons->Node,
0226 &_Console_simple_task_Node_control,
0227 _Console_simple_task_Name,
0228 sizeof( _Console_simple_task_Name ) - 1,
0229 S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO
0230 );
0231
0232 rtems_interrupt_lock_initialize( &cons->buf_lock, "Console" );
0233 rtems_mutex_init( &cons->output_mutex, "Console" );
0234
0235 IMFS_add_node( "/dev", &cons->Node, NULL );
0236
0237 status = rtems_task_create(
0238 rtems_build_name('C', 'O', 'N', 'S'),
0239 RTEMS_MAXIMUM_PRIORITY - 1,
0240 RTEMS_MINIMUM_STACK_SIZE,
0241 RTEMS_DEFAULT_ATTRIBUTES,
0242 RTEMS_DEFAULT_MODES,
0243 &cons->task
0244 );
0245 _Assert_Unused_variable_equals(status, RTEMS_SUCCESSFUL);
0246
0247 status = rtems_task_start(
0248 cons->task,
0249 _Console_simple_task_Task,
0250 (rtems_task_argument) cons
0251 );
0252 _Assert_Unused_variable_equals(status, RTEMS_SUCCESSFUL);
0253 }