source: rtems/c/src/lib/libbsp/sparc/leon/console/console.c @ 206e590

4.104.114.84.95
Last change on this file since 206e590 was 206e590, checked in by Ralf Corsepius <ralf.corsepius@…>, on Apr 1, 2004 at 10:11:58 AM

2004-04-01 Ralf Corsepius <ralf_corsepius@…>

  • startup/boardinit.S: Include <rtems/asm.h> instead of <asm.h>.
  • include/bsp.h: Include <rtems/clockdrv.h> instead of <clockdrv.h>.
  • include/bsp.h: Include <rtems/console.h> instead of <console.h>.
  • include/bsp.h: Include <rtems/iosupp.h> instead of <iosupp.h>.
  • console/console.c: Include <rtems/ringbuf.h> instead of <ringbuf.h>.
  • Property mode set to 100644
File size: 10.0 KB
Line 
1/*
2 *  This file contains the TTY driver for the serial ports on the LEON.
3 *
4 *  This driver uses the termios pseudo driver.
5 *
6 *  COPYRIGHT (c) 1989-1998.
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/leon.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 1.
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 = LEON_REG.UART_Status_1) & LEON_REG_UART_STATUS_DR ) {
99    if (UStat & LEON_REG_UART_STATUS_ERR) {
100      LEON_REG.UART_Status_1 = LEON_REG_UART_STATUS_CLR;
101    }
102    ch = LEON_REG.UART_Channel_1;
103
104    rtems_termios_enqueue_raw_characters( console_termios_data[ 0 ], &ch, 1 );
105  }
106 
107  if ( LEON_REG.UART_Status_1 & LEON_REG_UART_STATUS_THE ) {
108    if ( !Ring_buffer_Is_empty( &TX_Buffer[ 0 ] ) ) {
109      Ring_buffer_Remove_character( &TX_Buffer[ 0 ], ch );
110      LEON_REG.UART_Channel_1 = (uint32_t) ch;
111    } else
112     Is_TX_active[ 0 ] = FALSE;
113  }
114 
115  LEON_Clear_interrupt( LEON_INTERRUPT_UART_1_RX_TX );
116}
117
118/*
119 *  console_isr_b
120 *
121 *  This routine is the console interrupt handler for Channel 2.
122 *
123 *  Input parameters:
124 *    vector - vector number
125 *
126 *  Output parameters: NONE
127 *
128 *  Return values:     NONE
129 */
130 
131rtems_isr console_isr_b(
132  rtems_vector_number vector
133)
134{
135  char ch;
136  int UStat;
137
138  if ( (UStat = LEON_REG.UART_Status_2) & LEON_REG_UART_STATUS_DR ) {
139    if (UStat & LEON_REG_UART_STATUS_ERR) {
140      LEON_REG.UART_Status_2 = LEON_REG_UART_STATUS_CLR;
141    }
142    ch = LEON_REG.UART_Channel_2;
143    rtems_termios_enqueue_raw_characters( console_termios_data[ 1 ], &ch, 1 );
144
145  }
146
147  if ( LEON_REG.UART_Status_2 & LEON_REG_UART_STATUS_THE ) {
148    if ( !Ring_buffer_Is_empty( &TX_Buffer[ 1 ] ) ) {
149      Ring_buffer_Remove_character( &TX_Buffer[ 1 ], ch );
150      LEON_REG.UART_Channel_2 = (uint32_t) ch;
151    } else
152     Is_TX_active[ 1 ] = FALSE;
153  }
154
155  LEON_Clear_interrupt( LEON_INTERRUPT_UART_2_RX_TX );
156}
157
158/*
159 *  console_exit
160 *
161 *  This routine allows the console to exit by masking its associated interrupt
162 *  vectors.
163 *
164 *  Input parameters:  NONE
165 *
166 *  Output parameters: NONE
167 *
168 *  Return values:     NONE
169 */
170
171void console_exit()
172{
173  uint32_t         port;
174  uint32_t         ch;
175
176  /*
177   *  Although the interrupts for the UART are unmasked, the PIL is set to
178   *  disable all external interrupts.  So we might as well do this first.
179   */
180
181  LEON_Mask_interrupt( LEON_INTERRUPT_UART_1_RX_TX );
182  LEON_Mask_interrupt( LEON_INTERRUPT_UART_2_RX_TX );
183
184  for ( port=0 ; port <= 1 ; port++ ) {
185    while ( !Ring_buffer_Is_empty( &TX_Buffer[ port ] ) ) {
186      Ring_buffer_Remove_character( &TX_Buffer[ port ], ch );
187      console_outbyte_polled( port, ch );
188    }
189  }
190
191  /*
192   *  Now wait for all the data to actually get out ... the send register
193   *  should be empty.
194   */
195 
196  while ( (LEON_REG.UART_Status_1 & LEON_REG_UART_STATUS_THE) != 
197          LEON_REG_UART_STATUS_THE );
198
199  while ( (LEON_REG.UART_Status_2 & LEON_REG_UART_STATUS_THE) != 
200          LEON_REG_UART_STATUS_THE );
201
202  LEON_REG.UART_Control_1 = 0;
203  LEON_REG.UART_Control_2 = 0;
204  LEON_REG.UART_Status_1 = 0;
205  LEON_REG.UART_Status_2 = 0;
206
207
208}
209
210#define CONSOLE_UART_1_TRAP  LEON_TRAP_TYPE( LEON_INTERRUPT_UART_1_RX_TX )
211#define CONSOLE_UART_2_TRAP  LEON_TRAP_TYPE( LEON_INTERRUPT_UART_2_RX_TX )
212
213/*
214 *  console_initialize_interrupts
215 *
216 *  This routine initializes the console's receive and transmit
217 *  ring buffers and loads the appropriate vectors to handle the interrupts.
218 *
219 *  Input parameters:  NONE
220 *
221 *  Output parameters: NONE
222 *
223 *  Return values:     NONE
224 */
225
226#ifdef RDB_BREAK_IN
227  extern uint32_t   trap_table[];
228#endif
229
230void console_initialize_interrupts( void )
231{
232  Ring_buffer_Initialize( &TX_Buffer[ 0 ] );
233  Ring_buffer_Initialize( &TX_Buffer[ 1 ] );
234
235  Is_TX_active[ 0 ] = FALSE;
236  Is_TX_active[ 1 ] = FALSE;
237
238  atexit( console_exit );
239
240  LEON_REG.UART_Control_1 |= LEON_REG_UART_CTRL_RI | LEON_REG_UART_CTRL_TI;
241  LEON_REG.UART_Control_2 |= LEON_REG_UART_CTRL_RI | LEON_REG_UART_CTRL_TI;
242
243  set_vector( console_isr_a, CONSOLE_UART_1_TRAP, 1 );
244#ifdef RDB_BREAK_IN
245  if (trap_table[0x150/4] == 0x91d02000)
246#endif
247  set_vector( console_isr_b, CONSOLE_UART_2_TRAP, 1 );
248}
249
250/*
251 *  console_outbyte_interrupt
252 *
253 *  This routine transmits a character out.
254 *
255 *  Input parameters:
256 *    port - port to transmit character to
257 *    ch  - character to be transmitted
258 *
259 *  Output parameters:  NONE
260 *
261 *  Return values:      NONE
262 */
263 
264void console_outbyte_interrupt(
265  int   port,
266  char  ch
267)
268{
269  /*
270   *  If this is the first character then we need to prime the pump
271   */
272
273  if ( Is_TX_active[ port ] == FALSE ) {
274    Is_TX_active[ port ] = TRUE;
275    console_outbyte_polled( port, ch );
276    return;
277  }
278
279  while ( Ring_buffer_Is_full( &TX_Buffer[ port ] ) );
280
281  Ring_buffer_Add_character( &TX_Buffer[ port ], ch );
282}
283
284#endif /* CONSOLE_USE_INTERRUPTS */
285
286/*
287 *  Console Termios Support Entry Points
288 *
289 */
290
291int console_write_support (int minor, const char *buf, int len)
292{
293  int nwrite = 0;
294
295  while (nwrite < len) {
296#if (CONSOLE_USE_INTERRUPTS)
297    console_outbyte_interrupt( minor, *buf++ );
298#else
299    console_outbyte_polled( minor, *buf++ );
300#endif
301    nwrite++;
302  }
303  return nwrite;
304}
305
306/*
307 *  Console Device Driver Entry Points
308 *
309 */
310 
311rtems_device_driver console_initialize(
312  rtems_device_major_number  major,
313  rtems_device_minor_number  minor,
314  void                      *arg
315)
316{
317  rtems_status_code status;
318
319  rtems_termios_initialize();
320
321  /*
322   *  Register Device Names
323   */
324
325  status = rtems_io_register_name( "/dev/console", major, 0 );
326  if (status != RTEMS_SUCCESSFUL)
327    rtems_fatal_error_occurred(status);
328
329  status = rtems_io_register_name( "/dev/console_b", major, 1 );
330  if (status != RTEMS_SUCCESSFUL)
331    rtems_fatal_error_occurred(status);
332
333  /*
334   *  Initialize Hardware
335   */
336 
337  LEON_REG.UART_Control_1 |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
338  LEON_REG.UART_Control_2 |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE |
339        LEON_REG_UART_CTRL_RI;  /* rx irq default enable for remote debugger */
340  LEON_REG.UART_Status_1 = 0;
341  LEON_REG.UART_Status_2 = 0;
342#if (CONSOLE_USE_INTERRUPTS)
343  console_initialize_interrupts();
344#endif
345
346  return RTEMS_SUCCESSFUL;
347}
348
349rtems_device_driver console_open(
350  rtems_device_major_number major,
351  rtems_device_minor_number minor,
352  void                    * arg
353)
354{
355  rtems_status_code sc;
356#if (CONSOLE_USE_INTERRUPTS)
357  rtems_libio_open_close_args_t *args = arg;
358  static const rtems_termios_callbacks intrCallbacks = {
359    NULL,                        /* firstOpen */
360    NULL,                        /* lastClose */
361    NULL,                        /* pollRead */
362    console_write_support,       /* write */
363    NULL,                        /* setAttributes */
364    NULL,                        /* stopRemoteTx */
365    NULL,                        /* startRemoteTx */
366    0                            /* outputUsesInterrupts */
367  };
368#else
369  static const rtems_termios_callbacks pollCallbacks = {
370    NULL,                        /* firstOpen */
371    NULL,                        /* lastClose */
372    console_inbyte_nonblocking,  /* pollRead */
373    console_write_support,       /* write */
374    NULL,                        /* setAttributes */
375    NULL,                        /* stopRemoteTx */
376    NULL,                        /* startRemoteTx */
377    0                            /* outputUsesInterrupts */
378  };
379#endif
380
381  assert( minor <= 1 );
382  if ( minor > 2 )
383    return RTEMS_INVALID_NUMBER;
384 
385#if (CONSOLE_USE_INTERRUPTS)
386  sc = rtems_termios_open (major, minor, arg, &intrCallbacks);
387
388  console_termios_data[ minor ] = args->iop->data1;
389#else
390  sc = rtems_termios_open (major, minor, arg, &pollCallbacks);
391#endif
392
393  return RTEMS_SUCCESSFUL;
394}
395 
396rtems_device_driver console_close(
397  rtems_device_major_number major,
398  rtems_device_minor_number minor,
399  void                    * arg
400)
401{
402  return rtems_termios_close (arg);
403}
404 
405rtems_device_driver console_read(
406  rtems_device_major_number major,
407  rtems_device_minor_number minor,
408  void                    * arg
409)
410{
411  return rtems_termios_read (arg);
412}
413 
414rtems_device_driver console_write(
415  rtems_device_major_number major,
416  rtems_device_minor_number minor,
417  void                    * arg
418)
419{
420  return rtems_termios_write (arg);
421}
422 
423rtems_device_driver console_control(
424  rtems_device_major_number major,
425  rtems_device_minor_number minor,
426  void                    * arg
427)
428{
429  return rtems_termios_ioctl (arg);
430}
431
Note: See TracBrowser for help on using the repository browser.