OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [sparc/] [erc32/] [console/] [console.c] - Blame information for rev 173

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 30 unneback
/*
2
 *  This file contains the TTY driver for the serial ports on the erc32.
3
 *
4
 *  This driver uses the termios pseudo driver.
5
 *
6
 *  COPYRIGHT (c) 1989-1999.
7
 *  On-Line Applications Research Corporation (OAR).
8
 *
9
 *  The license and distribution terms for this file may be
10
 *  found in the file LICENSE in this distribution or at
11
 *  http://www.OARcorp.com/rtems/license.html.
12
 *
13
 *  $Id: console.c,v 1.2 2001-09-27 12:01:13 chris Exp $
14
 */
15
 
16
#include <bsp.h>
17
#include <rtems/libio.h>
18
#include <stdlib.h>
19
#include <assert.h>
20
 
21
/*
22
 *  Should we use a polled or interrupt drived console?
23
 *
24
 *  NOTE: This is defined in the custom/erc32.cfg file.
25
 *
26
 *  WARNING:  In sis 1.6, it did not appear that the UART interrupts
27
 *            worked in a desirable fashion.  Immediately upon writing
28
 *            a character into the TX buffer, an interrupt was generated.
29
 *            This did not allow enough time for the program to put more
30
 *            characters in the buffer.  So every character resulted in
31
 *            "priming" the transmitter.   This effectively results in
32
 *            in a polled console with a useless interrupt per character
33
 *            on output.  It is reasonable to assume that input does not
34
 *            share this problem although it was not investigated.
35
 *
36
 */
37
 
38
/*
39
 *  console_outbyte_polled
40
 *
41
 *  This routine transmits a character using polling.
42
 */
43
 
44
void console_outbyte_polled(
45
  int  port,
46
  char ch
47
);
48
 
49
/* body is in debugputs.c */
50
 
51
/*
52
 *  console_inbyte_nonblocking
53
 *
54
 *  This routine polls for a character.
55
 */
56
 
57
int console_inbyte_nonblocking( int port );
58
 
59
/* body is in debugputs.c */
60
 
61
/*
62
 *  Interrupt driven console IO
63
 */
64
 
65
#if (CONSOLE_USE_INTERRUPTS)
66
 
67
/*
68
 *  Buffers between task and ISRs
69
 */
70
 
71
#include <ringbuf.h>
72
 
73
Ring_buffer_t  TX_Buffer[ 2 ];
74
boolean        Is_TX_active[ 2 ];
75
 
76
void *console_termios_data[ 2 ];
77
 
78
/*
79
 *  console_isr_a
80
 *
81
 *  This routine is the console interrupt handler for Channel A.
82
 *
83
 *  Input parameters:
84
 *    vector - vector number
85
 *
86
 *  Output parameters: NONE
87
 *
88
 *  Return values:     NONE
89
 */
90
 
91
rtems_isr console_isr_a(
92
  rtems_vector_number vector
93
)
94
{
95
  char ch;
96
  int UStat;
97
 
98
  if ( (UStat = ERC32_MEC.UART_Status) & ERC32_MEC_UART_STATUS_DRA ) {
99
    if (UStat & ERC32_MEC_UART_STATUS_ERRA) {
100
      ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRA;
101
      ERC32_MEC.Control = ERC32_MEC.Control;
102
    }
103
    ch = ERC32_MEC.UART_Channel_A;
104
 
105
    rtems_termios_enqueue_raw_characters( console_termios_data[ 0 ], &ch, 1 );
106
  }
107
 
108
  if ( ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA ) {
109
    if ( !Ring_buffer_Is_empty( &TX_Buffer[ 0 ] ) ) {
110
      Ring_buffer_Remove_character( &TX_Buffer[ 0 ], ch );
111
      ERC32_MEC.UART_Channel_A = (unsigned32) ch;
112
    } else
113
     Is_TX_active[ 0 ] = FALSE;
114
  }
115
 
116
  ERC32_Clear_interrupt( ERC32_INTERRUPT_UART_A_RX_TX );
117
}
118
 
119
/*
120
 *  console_isr_b
121
 *
122
 *  This routine is the console interrupt handler for Channel B.
123
 *
124
 *  Input parameters:
125
 *    vector - vector number
126
 *
127
 *  Output parameters: NONE
128
 *
129
 *  Return values:     NONE
130
 */
131
 
132
rtems_isr console_isr_b(
133
  rtems_vector_number vector
134
)
135
{
136
  char ch;
137
  int UStat;
138
 
139
  if ( (UStat = ERC32_MEC.UART_Status) & ERC32_MEC_UART_STATUS_DRB ) {
140
    if (UStat & ERC32_MEC_UART_STATUS_ERRB) {
141
      ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB;
142
      ERC32_MEC.Control = ERC32_MEC.Control;
143
    }
144
    ch = ERC32_MEC.UART_Channel_B;
145
    rtems_termios_enqueue_raw_characters( console_termios_data[ 1 ], &ch, 1 );
146
 
147
  }
148
 
149
  if ( ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB ) {
150
    if ( !Ring_buffer_Is_empty( &TX_Buffer[ 1 ] ) ) {
151
      Ring_buffer_Remove_character( &TX_Buffer[ 1 ], ch );
152
      ERC32_MEC.UART_Channel_B = (unsigned32) ch;
153
    } else
154
     Is_TX_active[ 1 ] = FALSE;
155
  }
156
 
157
  ERC32_Clear_interrupt( ERC32_INTERRUPT_UART_B_RX_TX );
158
}
159
 
160
/*
161
 *  console_exit
162
 *
163
 *  This routine allows the console to exit by masking its associated interrupt
164
 *  vectors.
165
 *
166
 *  Input parameters:  NONE
167
 *
168
 *  Output parameters: NONE
169
 *
170
 *  Return values:     NONE
171
 */
172
 
173
void console_exit()
174
{
175
  rtems_unsigned32 port;
176
  rtems_unsigned32 ch;
177
 
178
  /*
179
   *  Although the interrupts for the UART are unmasked, the PIL is set to
180
   *  disable all external interrupts.  So we might as well do this first.
181
   */
182
 
183
  ERC32_Mask_interrupt( ERC32_INTERRUPT_UART_A_RX_TX );
184
  ERC32_Mask_interrupt( ERC32_INTERRUPT_UART_B_RX_TX );
185
 
186
  for ( port=0 ; port <= 1 ; port++ ) {
187
    while ( !Ring_buffer_Is_empty( &TX_Buffer[ port ] ) ) {
188
      Ring_buffer_Remove_character( &TX_Buffer[ port ], ch );
189
      console_outbyte_polled( port, ch );
190
    }
191
  }
192
 
193
  /*
194
   *  Now wait for all the data to actually get out ... the send register
195
   *  should be empty.
196
   */
197
 
198
  while ( (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA) !=
199
          ERC32_MEC_UART_STATUS_THEA );
200
 
201
  while ( (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB) !=
202
          ERC32_MEC_UART_STATUS_THEB );
203
 
204
}
205
 
206
#define CONSOLE_UART_A_TRAP  ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_A_RX_TX )
207
#define CONSOLE_UART_B_TRAP  ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_B_RX_TX )
208
 
209
/*
210
 *  console_initialize_interrupts
211
 *
212
 *  This routine initializes the console's receive and transmit
213
 *  ring buffers and loads the appropriate vectors to handle the interrupts.
214
 *
215
 *  Input parameters:  NONE
216
 *
217
 *  Output parameters: NONE
218
 *
219
 *  Return values:     NONE
220
 */
221
 
222
#ifdef RDB_BREAK_IN
223
  extern unsigned32 trap_table[];
224
#endif
225
 
226
void console_initialize_interrupts( void )
227
{
228
  Ring_buffer_Initialize( &TX_Buffer[ 0 ] );
229
  Ring_buffer_Initialize( &TX_Buffer[ 1 ] );
230
 
231
  Is_TX_active[ 0 ] = FALSE;
232
  Is_TX_active[ 1 ] = FALSE;
233
 
234
  atexit( console_exit );
235
 
236
  set_vector( console_isr_a, CONSOLE_UART_A_TRAP, 1 );
237
#ifdef RDB_BREAK_IN
238
  if (trap_table[0x150/4] == 0x91d02000)
239
#endif
240
  set_vector( console_isr_b, CONSOLE_UART_B_TRAP, 1 );
241
}
242
 
243
/*
244
 *  console_outbyte_interrupt
245
 *
246
 *  This routine transmits a character out.
247
 *
248
 *  Input parameters:
249
 *    port - port to transmit character to
250
 *    ch  - character to be transmitted
251
 *
252
 *  Output parameters:  NONE
253
 *
254
 *  Return values:      NONE
255
 */
256
 
257
void console_outbyte_interrupt(
258
  int   port,
259
  char  ch
260
)
261
{
262
  /*
263
   *  If this is the first character then we need to prime the pump
264
   */
265
 
266
  if ( Is_TX_active[ port ] == FALSE ) {
267
    Is_TX_active[ port ] = TRUE;
268
    console_outbyte_polled( port, ch );
269
    return;
270
  }
271
 
272
  while ( Ring_buffer_Is_full( &TX_Buffer[ port ] ) );
273
 
274
  Ring_buffer_Add_character( &TX_Buffer[ port ], ch );
275
}
276
 
277
#endif /* CONSOLE_USE_INTERRUPTS */
278
 
279
/*
280
 *  Console Termios Support Entry Points
281
 *
282
 */
283
 
284
int console_write_support (int minor, const char *buf, int len)
285
{
286
  int nwrite = 0;
287
 
288
  while (nwrite < len) {
289
#if (CONSOLE_USE_INTERRUPTS)
290
    console_outbyte_interrupt( minor, *buf++ );
291
#else
292
    console_outbyte_polled( minor, *buf++ );
293
#endif
294
    nwrite++;
295
  }
296
  return nwrite;
297
}
298
 
299
/*
300
 *  Console Device Driver Entry Points
301
 *
302
 */
303
 
304
rtems_device_driver console_initialize(
305
  rtems_device_major_number  major,
306
  rtems_device_minor_number  minor,
307
  void                      *arg
308
)
309
{
310
  rtems_status_code status;
311
 
312
  rtems_termios_initialize();
313
 
314
  /*
315
   *  Register Device Names
316
   */
317
 
318
  status = rtems_io_register_name( "/dev/console", major, 0 );
319
  if (status != RTEMS_SUCCESSFUL)
320
    rtems_fatal_error_occurred(status);
321
 
322
  status = rtems_io_register_name( "/dev/console_b", major, 1 );
323
  if (status != RTEMS_SUCCESSFUL)
324
    rtems_fatal_error_occurred(status);
325
 
326
  /*
327
   *  Initialize Hardware
328
   */
329
 
330
#if (CONSOLE_USE_INTERRUPTS)
331
  console_initialize_interrupts();
332
#endif
333
 
334
  return RTEMS_SUCCESSFUL;
335
}
336
 
337
rtems_device_driver console_open(
338
  rtems_device_major_number major,
339
  rtems_device_minor_number minor,
340
  void                    * arg
341
)
342
{
343
  rtems_status_code sc;
344
#if (CONSOLE_USE_INTERRUPTS)
345
  rtems_libio_open_close_args_t *args = arg;
346
  static const rtems_termios_callbacks intrCallbacks = {
347
    NULL,                        /* firstOpen */
348
    NULL,                        /* lastClose */
349
    NULL,                        /* pollRead */
350
    console_write_support,       /* write */
351
    NULL,                        /* setAttributes */
352
    NULL,                        /* stopRemoteTx */
353
    NULL,                        /* startRemoteTx */
354
 
355
  };
356
#else
357
  static const rtems_termios_callbacks pollCallbacks = {
358
    NULL,                        /* firstOpen */
359
    NULL,                        /* lastClose */
360
    console_inbyte_nonblocking,  /* pollRead */
361
    console_write_support,       /* write */
362
    NULL,                        /* setAttributes */
363
    NULL,                        /* stopRemoteTx */
364
    NULL,                        /* startRemoteTx */
365
 
366
  };
367
#endif
368
 
369
  assert( minor <= 1 );
370
  if ( minor > 2 )
371
    return RTEMS_INVALID_NUMBER;
372
 
373
#if (CONSOLE_USE_INTERRUPTS)
374
  sc = rtems_termios_open (major, minor, arg, &intrCallbacks);
375
 
376
  console_termios_data[ minor ] = args->iop->data1;
377
#else
378
  sc = rtems_termios_open (major, minor, arg, &pollCallbacks);
379
#endif
380
 
381
  return RTEMS_SUCCESSFUL;
382
}
383
 
384
rtems_device_driver console_close(
385
  rtems_device_major_number major,
386
  rtems_device_minor_number minor,
387
  void                    * arg
388
)
389
{
390
  return rtems_termios_close (arg);
391
}
392
 
393
rtems_device_driver console_read(
394
  rtems_device_major_number major,
395
  rtems_device_minor_number minor,
396
  void                    * arg
397
)
398
{
399
  return rtems_termios_read (arg);
400
}
401
 
402
rtems_device_driver console_write(
403
  rtems_device_major_number major,
404
  rtems_device_minor_number minor,
405
  void                    * arg
406
)
407
{
408
  return rtems_termios_write (arg);
409
}
410
 
411
rtems_device_driver console_control(
412
  rtems_device_major_number major,
413
  rtems_device_minor_number minor,
414
  void                    * arg
415
)
416
{
417
  return rtems_termios_ioctl (arg);
418
}
419
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.