source: rtems/c/src/lib/libbsp/sparc/erc32/console/console.c @ 2f93371

4.104.114.84.95
Last change on this file since 2f93371 was 2f93371, checked in by Joel Sherrill <joel.sherrill@…>, on Jan 29, 1997 at 12:28:30 AM

The CONSOLE_USE_INTERRUPTS and CONSOLE_USE_POLLED macros are now
defined in the targopts.h file.

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