source: rtems/c/src/lib/libbsp/sparc/leon2/console/console.c @ b46a31e

4.115
Last change on this file since b46a31e was b46a31e, checked in by Joel Sherrill <joel.sherrill@…>, on 11/23/14 at 15:48:17

leon2: include <rtems/ringbuf.h> not <ringbuf.h>

close #2113

  • Property mode set to 100644
File size: 9.7 KB
Line 
1/**
2 * @file
3 * @ingroup sparc_leon2
4 * @brief TTY driver driver for the serial ports on the LEON console
5 *
6 *  This file contains the TTY driver for the serial ports on the LEON.
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2014.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#include <bsp.h>
19#include <rtems/libio.h>
20#include <stdlib.h>
21#include <assert.h>
22#include <rtems/bspIo.h>
23
24/*
25 *  console_outbyte_polled
26 *
27 *  This routine transmits a character using polling.
28 */
29void console_outbyte_polled(
30  int           port,
31  unsigned char ch
32);
33
34/* body is in debugputs.c */
35
36/*
37 *  console_inbyte_nonblocking
38 *
39 *  This routine polls for a character.
40 */
41
42int console_inbyte_nonblocking( int port );
43
44/* body is in debugputs.c */
45
46/*
47 *  Interrupt driven console IO
48 */
49
50#if (CONSOLE_USE_INTERRUPTS)
51
52/*
53 *  Buffers between task and ISRs
54 */
55
56#include <rtems/ringbuf.h>
57
58Ring_buffer_t  TX_Buffer[ 2 ];
59bool           Is_TX_active[ 2 ];
60
61void *console_termios_data[ 2 ];
62
63/*
64 *  console_isr_a
65 *
66 *  This routine is the console interrupt handler for Channel 1.
67 *
68 *  Input parameters:
69 *    vector - vector number
70 *
71 *  Output parameters: NONE
72 *
73 *  Return values:     NONE
74 */
75
76rtems_isr console_isr_a(
77  rtems_vector_number vector
78)
79{
80  char ch;
81  int UStat;
82
83  if ( (UStat = LEON_REG.UART_Status_1) & LEON_REG_UART_STATUS_DR ) {
84    if (UStat & LEON_REG_UART_STATUS_ERR) {
85      LEON_REG.UART_Status_1 = LEON_REG_UART_STATUS_CLR;
86    }
87    ch = LEON_REG.UART_Channel_1;
88
89    rtems_termios_enqueue_raw_characters( console_termios_data[ 0 ], &ch, 1 );
90  }
91
92  if ( LEON_REG.UART_Status_1 & LEON_REG_UART_STATUS_THE ) {
93    if ( !Ring_buffer_Is_empty( &TX_Buffer[ 0 ] ) ) {
94      Ring_buffer_Remove_character( &TX_Buffer[ 0 ], ch );
95      LEON_REG.UART_Channel_1 = (uint32_t) ch;
96    } else
97     Is_TX_active[ 0 ] = false;
98  }
99
100  LEON_Clear_interrupt( LEON_INTERRUPT_UART_1_RX_TX );
101}
102
103/*
104 *  console_isr_b
105 *
106 *  This routine is the console interrupt handler for Channel 2.
107 *
108 *  Input parameters:
109 *    vector - vector number
110 *
111 *  Output parameters: NONE
112 *
113 *  Return values:     NONE
114 */
115
116rtems_isr console_isr_b(
117  rtems_vector_number vector
118)
119{
120  char ch;
121  int UStat;
122
123  if ( (UStat = LEON_REG.UART_Status_2) & LEON_REG_UART_STATUS_DR ) {
124    if (UStat & LEON_REG_UART_STATUS_ERR) {
125      LEON_REG.UART_Status_2 = LEON_REG_UART_STATUS_CLR;
126    }
127    ch = LEON_REG.UART_Channel_2;
128    rtems_termios_enqueue_raw_characters( console_termios_data[ 1 ], &ch, 1 );
129
130  }
131
132  if ( LEON_REG.UART_Status_2 & LEON_REG_UART_STATUS_THE ) {
133    if ( !Ring_buffer_Is_empty( &TX_Buffer[ 1 ] ) ) {
134      Ring_buffer_Remove_character( &TX_Buffer[ 1 ], ch );
135      LEON_REG.UART_Channel_2 = (uint32_t) ch;
136    } else
137     Is_TX_active[ 1 ] = false;
138  }
139
140  LEON_Clear_interrupt( LEON_INTERRUPT_UART_2_RX_TX );
141}
142
143/*
144 *  console_exit
145 *
146 *  This routine allows the console to exit by masking its associated interrupt
147 *  vectors.
148 *
149 *  Input parameters:  NONE
150 *
151 *  Output parameters: NONE
152 *
153 *  Return values:     NONE
154 */
155
156void console_exit()
157{
158  uint32_t port;
159  uint32_t ch;
160
161  /*
162   *  Although the interrupts for the UART are unmasked, the PIL is set to
163   *  disable all external interrupts.  So we might as well do this first.
164   */
165
166  LEON_Mask_interrupt( LEON_INTERRUPT_UART_1_RX_TX );
167  LEON_Mask_interrupt( LEON_INTERRUPT_UART_2_RX_TX );
168
169  for ( port=0 ; port <= 1 ; port++ ) {
170    while ( !Ring_buffer_Is_empty( &TX_Buffer[ port ] ) ) {
171      Ring_buffer_Remove_character( &TX_Buffer[ port ], ch );
172      console_outbyte_polled( port, ch );
173    }
174  }
175
176  /*
177   *  Now wait for all the data to actually get out ... the send register
178   *  should be empty.
179   */
180
181  while ( (LEON_REG.UART_Status_1 & LEON_REG_UART_STATUS_THE) !=
182          LEON_REG_UART_STATUS_THE );
183
184  while ( (LEON_REG.UART_Status_2 & LEON_REG_UART_STATUS_THE) !=
185          LEON_REG_UART_STATUS_THE );
186
187  LEON_REG.UART_Control_1 = 0;
188  LEON_REG.UART_Control_2 = 0;
189  LEON_REG.UART_Status_1 = 0;
190  LEON_REG.UART_Status_2 = 0;
191
192
193}
194
195#define CONSOLE_UART_1_TRAP  LEON_TRAP_TYPE( LEON_INTERRUPT_UART_1_RX_TX )
196#define CONSOLE_UART_2_TRAP  LEON_TRAP_TYPE( LEON_INTERRUPT_UART_2_RX_TX )
197
198/*
199 *  console_initialize_interrupts
200 *
201 *  This routine initializes the console's receive and transmit
202 *  ring buffers and loads the appropriate vectors to handle the interrupts.
203 *
204 *  Input parameters:  NONE
205 *
206 *  Output parameters: NONE
207 *
208 *  Return values:     NONE
209 */
210
211#ifdef RDB_BREAK_IN
212  extern uint32_t trap_table[];
213#endif
214
215void console_initialize_interrupts( void )
216{
217  Ring_buffer_Initialize( &TX_Buffer[ 0 ] );
218  Ring_buffer_Initialize( &TX_Buffer[ 1 ] );
219
220  Is_TX_active[ 0 ] = false;
221  Is_TX_active[ 1 ] = false;
222
223  atexit( console_exit );
224
225  LEON_REG.UART_Control_1 |= LEON_REG_UART_CTRL_RI | LEON_REG_UART_CTRL_TI;
226  LEON_REG.UART_Control_2 |= LEON_REG_UART_CTRL_RI | LEON_REG_UART_CTRL_TI;
227
228  set_vector( console_isr_a, CONSOLE_UART_1_TRAP, 1 );
229#ifdef RDB_BREAK_IN
230  if (trap_table[0x150/4] == 0x91d02000)
231#endif
232  set_vector( console_isr_b, CONSOLE_UART_2_TRAP, 1 );
233}
234
235/*
236 *  console_outbyte_interrupt
237 *
238 *  This routine transmits a character out.
239 *
240 *  Input parameters:
241 *    port - port to transmit character to
242 *    ch  - character to be transmitted
243 *
244 *  Output parameters:  NONE
245 *
246 *  Return values:      NONE
247 */
248
249void console_outbyte_interrupt(
250  int   port,
251  char  ch
252)
253{
254  /*
255   *  If this is the first character then we need to prime the pump
256   */
257
258  if ( Is_TX_active[ port ] == false ) {
259    Is_TX_active[ port ] = true;
260    console_outbyte_polled( port, ch );
261    return;
262  }
263
264  while ( Ring_buffer_Is_full( &TX_Buffer[ port ] ) );
265
266  Ring_buffer_Add_character( &TX_Buffer[ port ], ch );
267}
268
269#endif /* CONSOLE_USE_INTERRUPTS */
270
271/*
272 *  Console Termios Support Entry Points
273 *
274 */
275
276static ssize_t console_write_support (int minor, const char *buf, size_t len)
277{
278  int nwrite = 0;
279
280  while (nwrite < len) {
281#if (CONSOLE_USE_INTERRUPTS)
282    console_outbyte_interrupt( minor, *buf++ );
283#else
284    console_outbyte_polled( minor, *buf++ );
285#endif
286    nwrite++;
287  }
288  return nwrite;
289}
290
291/*
292 *  Console Device Driver Entry Points
293 *
294 */
295
296rtems_device_driver console_initialize(
297  rtems_device_major_number  major,
298  rtems_device_minor_number  minor,
299  void                      *arg
300)
301{
302  rtems_status_code status;
303
304  rtems_termios_initialize();
305
306  /*
307   *  Register Device Names
308   */
309
310  status = rtems_io_register_name( "/dev/console", major, 0 );
311  if (status != RTEMS_SUCCESSFUL)
312    rtems_fatal_error_occurred(status);
313
314  status = rtems_io_register_name( "/dev/console_b", major, 1 );
315  if (status != RTEMS_SUCCESSFUL)
316    rtems_fatal_error_occurred(status);
317
318  /*
319   *  Initialize Hardware
320   */
321
322  LEON_REG.UART_Control_1 |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
323  LEON_REG.UART_Control_2 |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE |
324      LEON_REG_UART_CTRL_RI;  /* rx irq default enable for remote debugger */
325  LEON_REG.UART_Status_1 = 0;
326  LEON_REG.UART_Status_2 = 0;
327#if (CONSOLE_USE_INTERRUPTS)
328  console_initialize_interrupts();
329#endif
330
331  return RTEMS_SUCCESSFUL;
332}
333
334rtems_device_driver console_open(
335  rtems_device_major_number major,
336  rtems_device_minor_number minor,
337  void                    * arg
338)
339{
340  rtems_status_code sc;
341#if (CONSOLE_USE_INTERRUPTS)
342  rtems_libio_open_close_args_t *args = arg;
343  static const rtems_termios_callbacks intrCallbacks = {
344    NULL,                        /* firstOpen */
345    NULL,                        /* lastClose */
346    NULL,                        /* pollRead */
347    console_write_support,       /* write */
348    NULL,                        /* setAttributes */
349    NULL,                        /* stopRemoteTx */
350    NULL,                        /* startRemoteTx */
351    0                            /* outputUsesInterrupts */
352  };
353#else
354  static const rtems_termios_callbacks pollCallbacks = {
355    NULL,                        /* firstOpen */
356    NULL,                        /* lastClose */
357    console_inbyte_nonblocking,  /* pollRead */
358    console_write_support,       /* write */
359    NULL,                        /* setAttributes */
360    NULL,                        /* stopRemoteTx */
361    NULL,                        /* startRemoteTx */
362    0                            /* outputUsesInterrupts */
363  };
364#endif
365
366  assert( minor <= 1 );
367  if ( minor > 2 )
368    return RTEMS_INVALID_NUMBER;
369
370#if (CONSOLE_USE_INTERRUPTS)
371  sc = rtems_termios_open (major, minor, arg, &intrCallbacks);
372
373  console_termios_data[ minor ] = args->iop->data1;
374#else
375  sc = rtems_termios_open (major, minor, arg, &pollCallbacks);
376#endif
377  (void) sc; /* avoid set but not used warning */
378
379  return RTEMS_SUCCESSFUL;
380}
381
382rtems_device_driver console_close(
383  rtems_device_major_number major,
384  rtems_device_minor_number minor,
385  void                    * arg
386)
387{
388  return rtems_termios_close (arg);
389}
390
391rtems_device_driver console_read(
392  rtems_device_major_number major,
393  rtems_device_minor_number minor,
394  void                    * arg
395)
396{
397  return rtems_termios_read (arg);
398}
399
400rtems_device_driver console_write(
401  rtems_device_major_number major,
402  rtems_device_minor_number minor,
403  void                    * arg
404)
405{
406  return rtems_termios_write (arg);
407}
408
409rtems_device_driver console_control(
410  rtems_device_major_number major,
411  rtems_device_minor_number minor,
412  void                    * arg
413)
414{
415  return rtems_termios_ioctl (arg);
416}
417
418/* putchar/getchar for printk */
419
420static void bsp_out_char (char c)
421{
422  console_outbyte_polled(0, c);
423}
424
425BSP_output_char_function_type BSP_output_char = bsp_out_char;
426
427static int bsp_in_char(void)
428{
429  int tmp;
430
431  while ((tmp = console_inbyte_nonblocking(0)) < 0);
432  return tmp;
433}
434
435BSP_polling_getchar_function_type BSP_poll_char = bsp_in_char;
Note: See TracBrowser for help on using the repository browser.