source: rtems/c/src/lib/libbsp/sparc/erc32/console/console.c @ 7f96eef

4.104.114.84.95
Last change on this file since 7f96eef was 7f96eef, checked in by Joel Sherrill <joel.sherrill@…>, on Dec 2, 1996 at 10:36:28 PM

Replacement for the sis bsp which supports the simulator and real
hardware. From Jiri Gaisler <jgais@…>. Supports sis
2.6 and later.

  • Property mode set to 100644
File size: 14.3 KB
Line 
1/*
2 *  console.c
3 *
4 *  This file contains the Sparc Instruction Simulator Console driver.
5 *
6 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
7 *  On-Line Applications Research Corporation (OAR).
8 *  All rights assigned to U.S. Government, 1994.
9 *
10 *  This material may be reproduced by or for the U.S. Government pursuant
11 *  to the copyright license under the clause at DFARS 252.227-7013.  This
12 *  notice must appear in all copies of this file and its derivatives.
13 *
14 *  Ported to ERC32 implementation of the SPARC by On-Line Applications
15 *  Research Corporation (OAR) under contract to the European Space
16 *  Agency (ESA).
17 *
18 *  ERC32 modifications of respective RTEMS file: COPYRIGHT (c) 1995.
19 *  European Space Agency.
20 *
21 *  $Id$
22 */
23
24#include <bsp.h>
25#include <rtems/libio.h>
26#include <stdlib.h>
27
28/*
29 *  Define RDB_BREAK_IN if you need to be able to break in to the
30 *  program with a ctrl-c during remote target debugging. If so,
31 *  UART B will not be accessible from rtems during remote debugging
32 *  if interrupt driven console is used. Does not affect UART A, polled
33 *  mode or when the program runs without remote debugging.
34 */
35
36#define RDB_BREAK_IN
37
38/*
39 *  This is a kludge so the tests run without stopping to ask for input.
40 *  It makes it possible to run the RTEMS tests without human intervention.
41 */
42
43/*
44#define CONSOLE_FAKE_INPUT
45*/
46
47/*
48 *  Should we use a polled or interrupt drived console?
49 * 
50 *  NOTE: Define only one of these by default.
51 *
52 *  WARNING:  As of sis 1.6, it did not appear that the UART interrupts
53 *            worked in a desirable fashion.  Immediately upon writing
54 *            a character into the TX buffer, an interrupt was generated.
55 *            This did not allow enough time for the program to put more
56 *            characters in the buffer.  So every character resulted in
57 *            "priming" the transmitter.   This effectively results in
58 *            in a polled console with a useless interrupt per character
59 *            on output.  It is reasonable to assume that input does not
60 *            share this problem although it was not investigated.
61 */
62
63#define CONSOLE_USE_INTERRUPTS
64
65/*
66#define CONSOLE_USE_POLLED
67*/
68
69#ifdef CONSOLE_USE_POLLED
70#define OUTBYTE console_outbyte_polled
71#define INBYTE  console_inbyte_polled
72#else
73#define OUTBYTE console_outbyte_interrupts
74#define INBYTE  console_inbyte_interrupts
75#endif
76
77void console_initialize_interrupts( void );
78
79/*  console_initialize
80 *
81 *  This routine initializes the console IO driver.
82 *
83 *  Input parameters:
84 *    major - console device major number
85 *    minor - console device minor number
86 *    arg   - pointer to optional device driver arguments
87 *
88 *  Output parameters:  NONE
89 *
90 *  Return values:
91 *    rtems_device_driver status code
92 */
93 
94rtems_device_driver console_initialize(
95  rtems_device_major_number  major,
96  rtems_device_minor_number  minor,
97  void                      *arg
98)
99{
100  rtems_status_code status;
101 
102  status = rtems_io_register_name(
103    "/dev/console",
104    major,
105    (rtems_device_minor_number) 0
106  );
107 
108  if (status != RTEMS_SUCCESSFUL)
109    rtems_fatal_error_occurred(status);
110
111#ifdef CONSOLE_USE_INTERRUPTS
112  console_initialize_interrupts();
113#endif
114 
115  return RTEMS_SUCCESSFUL;
116}
117
118/*  console_inbyte_polled
119 *
120 *  This routine reads a character from the UART.
121 *
122 *  Input parameters:
123 *    port - port to read character from
124 *
125 *  Output parameters:  NONE
126 *
127 *  Return values:
128 *    character read from UART
129 */
130
131char console_inbyte_polled( int port )
132{
133  int UStat;
134
135  if ( port == 0 ) {
136    while (((UStat = ERC32_MEC.UART_Status) & ERC32_MEC_UART_STATUS_DRA) == 0 )
137        if (UStat & ERC32_MEC_UART_STATUS_ERRA) {
138            ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRA;
139            ERC32_MEC.Control = ERC32_MEC.Control;
140        }
141    return (int) ERC32_MEC.UART_Channel_A;
142  } 
143
144  while (((UStat = ERC32_MEC.UART_Status) & ERC32_MEC_UART_STATUS_DRB) == 0 )
145        if (UStat & ERC32_MEC_UART_STATUS_ERRB) {
146            ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB;
147            ERC32_MEC.Control = ERC32_MEC.Control;
148        }
149  return (int) ERC32_MEC.UART_Channel_B;
150}
151
152
153/*  console_outbyte_polled
154 *
155 *  This routine transmits a character out.
156 *
157 *  Input parameters:
158 *    port - port to transmit character to
159 *    ch  - character to be transmitted
160 *
161 *  Output parameters:  NONE
162 *
163 *  Return values: NONE
164 */
165
166void console_outbyte_polled(
167  int  port,
168  char ch
169)
170{
171  if ( port == 0 ) {
172    while ( (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA) == 0 );
173    ERC32_MEC.UART_Channel_A = (int) ch;
174    return;
175  }
176
177  while ( (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB) == 0 );
178  ERC32_MEC.UART_Channel_B = (int) ch;
179}
180
181/*
182 *  Interrupt driven console IO
183 */
184
185#ifdef CONSOLE_USE_INTERRUPTS
186
187/*
188 *  Buffers between task and ISRs
189 */
190
191#include <ringbuf.h>
192 
193Ring_buffer_t  TX_Buffer[ 2 ];
194Ring_buffer_t  RX_Buffer[ 2 ];
195boolean        Is_TX_active[ 2 ];
196 
197/*
198 *  console_isr_a
199 *
200 *  This routine is the console interrupt handler for Channel A.
201 *
202 *  Input parameters:
203 *    vector - vector number
204 *
205 *  Output parameters: NONE
206 *
207 *  Return values:     NONE
208 */
209
210rtems_isr console_isr_a(
211  rtems_vector_number vector
212)
213{ 
214  char ch;
215  int UStat;
216 
217  if ( (UStat = ERC32_MEC.UART_Status) & ERC32_MEC_UART_STATUS_DRA ) {
218    if (UStat & ERC32_MEC_UART_STATUS_ERRA) {
219      ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRA;
220      ERC32_MEC.Control = ERC32_MEC.Control;
221    }
222    ch = ERC32_MEC.UART_Channel_A;
223    if ( !Ring_buffer_Is_full( &RX_Buffer[ 0 ] ) )
224      Ring_buffer_Add_character( &RX_Buffer[ 0 ], ch );
225    /* else toss it */
226  }
227 
228  if ( ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA ) {
229    if ( !Ring_buffer_Is_empty( &TX_Buffer[ 0 ] ) ) {
230      Ring_buffer_Remove_character( &TX_Buffer[ 0 ], ch );
231      ERC32_MEC.UART_Channel_A = (unsigned32) ch;
232    } else
233     Is_TX_active[ 0 ] = FALSE;
234  }
235 
236  ERC32_Clear_interrupt( ERC32_INTERRUPT_UART_A_RX_TX );
237}
238
239/*
240 *  console_isr_b
241 *
242 *  This routine is the console interrupt handler for Channel B.
243 *
244 *  Input parameters:
245 *    vector - vector number
246 *
247 *  Output parameters: NONE
248 *
249 *  Return values:     NONE
250 */
251 
252rtems_isr console_isr_b(
253  rtems_vector_number vector
254)
255{
256  char ch;
257  int UStat;
258
259  if ( (UStat = ERC32_MEC.UART_Status) & ERC32_MEC_UART_STATUS_DRB ) {
260    if (UStat & ERC32_MEC_UART_STATUS_ERRB) {
261      ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB;
262      ERC32_MEC.Control = ERC32_MEC.Control;
263    }
264    ch = ERC32_MEC.UART_Channel_B;
265    if ( !Ring_buffer_Is_full( &RX_Buffer[ 1 ] ) )
266      Ring_buffer_Add_character( &RX_Buffer[ 1 ], ch );
267    /* else toss it */
268  }
269
270  if ( ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB ) {
271    if ( !Ring_buffer_Is_empty( &TX_Buffer[ 1 ] ) ) {
272      Ring_buffer_Remove_character( &TX_Buffer[ 1 ], ch );
273      ERC32_MEC.UART_Channel_B = (unsigned32) ch;
274    } else
275     Is_TX_active[ 1 ] = FALSE;
276  }
277
278  ERC32_Clear_interrupt( ERC32_INTERRUPT_UART_B_RX_TX );
279}
280
281/*
282 *  console_exit
283 *
284 *  This routine allows the console to exit by masking its associated interrupt
285 *  vectors.
286 *
287 *  Input parameters:  NONE
288 *
289 *  Output parameters: NONE
290 *
291 *  Return values:     NONE
292 */
293
294void console_exit()
295{
296  rtems_unsigned32 port;
297  rtems_unsigned32 ch;
298
299  /*
300   *  Although the interrupts for the UART are unmasked, the PIL is set to
301   *  disable all external interrupts.  So we might as well do this first.
302   */
303
304  ERC32_Mask_interrupt( ERC32_INTERRUPT_UART_A_RX_TX );
305  ERC32_Mask_interrupt( ERC32_INTERRUPT_UART_B_RX_TX );
306
307  for ( port=0 ; port <= 1 ; port++ ) {
308    while ( !Ring_buffer_Is_empty( &TX_Buffer[ port ] ) ) {
309      Ring_buffer_Remove_character( &TX_Buffer[ port ], ch );
310      console_outbyte_polled( port, ch );
311    }
312  }
313
314  /*
315   *  Now wait for all the data to actually get out ... the send register
316   *  should be empty.
317   */
318 
319  while ( (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA) != 
320          ERC32_MEC_UART_STATUS_THEA );
321
322  while ( (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB) != 
323          ERC32_MEC_UART_STATUS_THEB );
324
325}
326
327#define CONSOLE_UART_A_TRAP  ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_A_RX_TX )
328#define CONSOLE_UART_B_TRAP  ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_B_RX_TX )
329
330/*
331 *  console_initialize_interrupts
332 *
333 *  This routine initializes the console's receive and transmit
334 *  ring buffers and loads the appropriate vectors to handle the interrupts.
335 *
336 *  Input parameters:  NONE
337 *
338 *  Output parameters: NONE
339 *
340 *  Return values:     NONE
341 */
342
343#ifdef RDB_BREAK_IN
344  extern int trap_table[];
345#endif
346
347void console_initialize_interrupts()
348{
349  Ring_buffer_Initialize( &RX_Buffer[ 0 ] );
350  Ring_buffer_Initialize( &RX_Buffer[ 1 ] );
351
352  Ring_buffer_Initialize( &TX_Buffer[ 0 ] );
353  Ring_buffer_Initialize( &TX_Buffer[ 1 ] );
354
355  Is_TX_active[ 0 ] = FALSE;
356  Is_TX_active[ 1 ] = FALSE;
357
358  atexit( console_exit );
359
360  set_vector( console_isr_a, CONSOLE_UART_A_TRAP, 1 );
361#ifdef RDB_BREAK_IN
362  if (trap_table[0x150/4] == 0x91d02000)
363#endif
364  set_vector( console_isr_b, CONSOLE_UART_B_TRAP, 1 );
365}
366
367/*
368 *  console_inbyte_interrupts
369 *
370 *  This routine reads a character from the UART.
371 *
372 *  Input parameters: NONE
373 *
374 *  Output parameters:  NONE
375 *
376 *  Return values:
377 *    character read from UART
378 */
379 
380char console_inbyte_interrupts( int port )
381{
382  char ch;
383
384  while ( Ring_buffer_Is_empty( &RX_Buffer[ port ] ) );
385 
386  Ring_buffer_Remove_character( &RX_Buffer[ port ], ch );
387  return ch;
388}
389 
390/*
391 *  console_outbyte_interrupts
392 *
393 *  This routine transmits a character out.
394 *
395 *  Input parameters:
396 *    port - port to transmit character to
397 *    ch  - character to be transmitted
398 *
399 *  Output parameters:  NONE
400 *
401 *  Return values:      NONE
402 */
403 
404void console_outbyte_interrupts(
405  int  port,
406  char ch
407)
408{
409  /*
410   *  If this is the first character then we need to prime the pump
411   */
412
413  if ( Is_TX_active[ port ] == FALSE ) {
414    Is_TX_active[ port ] = TRUE;
415    console_outbyte_polled( port, ch );
416    return;
417  }
418
419  while ( Ring_buffer_Is_full( &TX_Buffer[ port ] ) );
420 
421  Ring_buffer_Add_character( &TX_Buffer[ port ], ch );
422}
423
424#endif /* CONSOLE_USE_INTERRUPTS */
425
426/*
427 *  DEBUG_puts
428 *
429 *  This should be safe in the event of an error.  It attempts to insure
430 *  that no TX empty interrupts occur while it is doing polled IO.  Then
431 *  it restores the state of that external interrupt.
432 *
433 *  Input parameters:
434 *    string  - pointer to debug output string
435 *
436 *  Output parameters:  NONE
437 *
438 *  Return values:      NONE
439 */
440
441void DEBUG_puts(
442  char *string
443)
444{
445  char *s;
446  unsigned32 old_level;
447
448  ERC32_Disable_interrupt( ERC32_INTERRUPT_UART_A_RX_TX, old_level );
449    for ( s = string ; *s ; s++ ) 
450      console_outbyte_polled( 0, *s );
451
452    console_outbyte_polled( 0, '\r' );
453    console_outbyte_polled( 0, '\n' );
454  ERC32_Restore_interrupt( ERC32_INTERRUPT_UART_A_RX_TX, old_level );
455}
456
457
458/*
459 *  console_open
460 *
461 *  This routine is the console device driver open entry point.
462 *
463 *  Input parameters:
464 *    major - console device major number
465 *    minor - console device minor number
466 *    arg   - pointer to optional device driver arguments
467 *
468 *  Output parameters:  NONE
469 *
470 *  Return values:
471 *    rtems_device_driver status code
472 */
473 
474rtems_device_driver console_open(
475  rtems_device_major_number major,
476  rtems_device_minor_number minor,
477  void                    * arg
478)
479{
480  return RTEMS_SUCCESSFUL;
481}
482 
483/*
484 *  console_close
485 *
486 *  This routine is the console device driver close entry point.
487 *
488 *  Input parameters:
489 *    major - console device major number
490 *    minor - console device minor number
491 *    arg   - pointer to optional device driver arguments
492 *
493 *  Output parameters:  NONE
494 *
495 *  Return values:
496 *    rtems_device_driver status code
497 */
498 
499rtems_device_driver console_close(
500  rtems_device_major_number major,
501  rtems_device_minor_number minor,
502  void                    * arg
503)
504{
505  return RTEMS_SUCCESSFUL;
506}
507 
508/*
509 *  console_read
510 *
511 *  This routine is the console device driver read entry point.
512 *
513 *  Input parameters:
514 *    major - console device major number
515 *    minor - console device minor number
516 *    arg   - pointer to optional device driver arguments
517 *
518 *  Output parameters:  NONE
519 *
520 *  Return values:
521 *    rtems_device_driver status code
522 *
523 *  NOTE:  Read bytes from the serial port. We only have stdin.
524 */
525 
526rtems_device_driver console_read(
527  rtems_device_major_number major,
528  rtems_device_minor_number minor,
529  void                    * arg
530)
531{
532  rtems_libio_rw_args_t *rw_args;
533  char *buffer;
534  int maximum;
535  int count = 0;
536 
537  rw_args = (rtems_libio_rw_args_t *) arg;
538 
539  buffer = rw_args->buffer;
540  maximum = rw_args->count;
541 
542#ifdef CONSOLE_FAKE_INPUT
543    count = 0;
544    buffer[ count++ ]  = '\n';
545    buffer[ count ]  = 0;
546#else
547  for (count = 0; count < maximum; count++) {
548    buffer[ count ] = INBYTE( minor );
549    if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
550      buffer[ count++ ]  = '\n';
551      buffer[ count ]  = 0;
552      break;
553    }
554  }
555#endif
556 
557  rw_args->bytes_moved = count;
558  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
559}
560 
561/*
562 *  console_write
563 *
564 *  This routine is the console device driver write entry point.
565 *
566 *  Input parameters:
567 *    major - console device major number
568 *    minor - console device minor number
569 *    arg   - pointer to optional device driver arguments
570 *
571 *  Output parameters:  NONE
572 *
573 *  Return values:
574 *    rtems_device_driver status code
575 *
576 *  NOTE:  Write bytes to the serial port. Stdout and stderr are the same.
577 */
578 
579rtems_device_driver console_write(
580  rtems_device_major_number major,
581  rtems_device_minor_number minor,
582  void                    * arg
583)
584{
585  int count;
586  int maximum;
587  rtems_libio_rw_args_t *rw_args;
588  char *buffer;
589 
590  rw_args = (rtems_libio_rw_args_t *) arg;
591 
592  buffer = rw_args->buffer;
593  maximum = rw_args->count;
594 
595  for (count = 0; count < maximum; count++) {
596    OUTBYTE( minor, buffer[ count ] );
597    if ( buffer[ count ] == '\n') {
598      OUTBYTE( minor, '\r');
599    }
600  }
601 
602  rw_args->bytes_moved = maximum;
603  return RTEMS_SUCCESSFUL;
604}
605 
606/*
607 *  console_control
608 *
609 *  This routine is the console device driver control entry point.
610 *
611 *  Input parameters:
612 *    major - console device major number
613 *    minor - console device minor number
614 *    arg   - pointer to optional device driver arguments
615 *
616 *  Output parameters:  NONE
617 *
618 *  Return values:
619 *    rtems_device_driver status code
620 */
621 
622rtems_device_driver console_control(
623  rtems_device_major_number major,
624  rtems_device_minor_number minor,
625  void                    * arg
626)
627{
628  return RTEMS_SUCCESSFUL;
629}
630
Note: See TracBrowser for help on using the repository browser.