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

4.104.114.84.9
Last change on this file since e4f62d9 was e4f62d9, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 28, 2007 at 6:08:38 PM

2007-03-28 Joel Sherrill <joel@…>

PR 1233/bsps

  • Makefile.am, console/console.c, console/debugputs.c: Move printk support code into debug IO file so you do not get the entire console driver when you do not want it.
  • Property mode set to 100644
File size: 9.5 KB
Line 
1/*
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.rtems.com/license/LICENSE.
12 *
13 *  $Id$
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
44void 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
57int 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 <rtems/ringbuf.h>
72
73Ring_buffer_t  TX_Buffer[ 2 ];
74boolean        Is_TX_active[ 2 ];
75
76void *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
91rtems_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 = (uint32_t) 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
132rtems_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 = (uint32_t) 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
173void console_exit()
174{
175  uint32_t         port;
176  uint32_t         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 uint32_t   trap_table[];
224#endif
225
226void 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
257void 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
284int 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
304rtems_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
337rtems_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    0                            /* outputUsesInterrupts */
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    0                            /* outputUsesInterrupts */
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
384rtems_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
393rtems_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
402rtems_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
411rtems_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}
Note: See TracBrowser for help on using the repository browser.