source: rtems/c/src/lib/libbsp/sparc/erc32/console/erc32_console.c @ 9f058fb

4.115
Last change on this file since 9f058fb was 9f058fb, checked in by Daniel Cederman <cederman@…>, on 05/08/14 at 15:08:04

bsps/sparc: Change tabs to spaces.

  • Property mode set to 100644
File size: 9.0 KB
Line 
1/**
2 * @file
3 *
4 * @brief Driver for serial ports on the ERC32.
5 */
6
7/*
8 * Copyright (c) 2010 Tiemen Schut <T.Schut@sron.nl>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#include <unistd.h>
16#include <termios.h>
17#include <stdlib.h>
18
19#include <rtems.h>
20#include <rtems/libio.h>
21#include <rtems/console.h>
22#include <rtems/termiostypes.h>
23
24#include <libchip/serial.h>
25#include <libchip/sersupp.h>
26
27#include <bsp.h>
28#include <bspopts.h>
29
30#define CONSOLE_BUF_SIZE (16)
31
32#define CONSOLE_UART_A_TRAP  ERC32_TRAP_TYPE(ERC32_INTERRUPT_UART_A_RX_TX)
33#define CONSOLE_UART_B_TRAP  ERC32_TRAP_TYPE(ERC32_INTERRUPT_UART_B_RX_TX)
34
35static uint8_t erc32_console_get_register(uintptr_t addr, uint8_t i)
36{
37  volatile uint32_t *reg = (volatile uint32_t *)addr;
38  return (uint8_t) reg [i];
39}
40
41static void erc32_console_set_register(uintptr_t addr, uint8_t i, uint8_t val)
42{
43  volatile uint32_t *reg = (volatile uint32_t *)addr;
44  reg [i] = val;
45}
46
47static int erc32_console_first_open(int major, int minor, void *arg);
48
49#if (CONSOLE_USE_INTERRUPTS)
50  static ssize_t erc32_console_write_support_int(
51    int minor, const char *buf, size_t len);
52#else
53  int console_inbyte_nonblocking( int port );
54  static ssize_t erc32_console_write_support_polled(
55      int minor, const char *buf, size_t len);
56#endif
57static void erc32_console_initialize(int minor);
58
59#if (CONSOLE_USE_INTERRUPTS)
60  const console_fns erc32_fns = {
61    libchip_serial_default_probe,           /* deviceProbe */
62    erc32_console_first_open,               /* deviceFirstOpen */
63    NULL,                                   /* deviceLastClose */
64    NULL,                                   /* deviceRead */
65    erc32_console_write_support_int,        /* deviceWrite */
66    erc32_console_initialize,               /* deviceInitialize */
67    NULL,                                   /* deviceWritePolled */
68    NULL,                                   /* deviceSetAttributes */
69    TERMIOS_IRQ_DRIVEN                      /* deviceOutputUsesInterrupts */
70  };
71#else
72  const console_fns erc32_fns = {
73    libchip_serial_default_probe,           /* deviceProbe */
74    erc32_console_first_open,               /* deviceFirstOpen */
75    NULL,                                   /* deviceLastClose */
76    console_inbyte_nonblocking,             /* deviceRead */
77    erc32_console_write_support_polled,     /* deviceWrite */
78    erc32_console_initialize,               /* deviceInitialize */
79    NULL,                                   /* deviceWritePolled */
80    NULL,                                   /* deviceSetAttributes */
81    TERMIOS_POLLED                          /* deviceOutputUsesInterrupts */
82  };
83#endif
84
85console_tbl Console_Configuration_Ports [] = {
86  {
87    .sDeviceName = "/dev/console_a",
88    .deviceType = SERIAL_CUSTOM,
89    .pDeviceFns = &erc32_fns,
90    .deviceProbe = NULL,
91    .pDeviceFlow = NULL,
92    .ulMargin = 16,
93    .ulHysteresis = 8,
94    .pDeviceParams = (void *) -1,  /* could be baud rate */
95    .ulCtrlPort1 = 0,
96    .ulCtrlPort2 = 0,
97    .ulDataPort = 0,
98    .getRegister = erc32_console_get_register,
99    .setRegister = erc32_console_set_register,
100    .getData = NULL,
101    .setData = NULL,
102    .ulClock = 16,
103    .ulIntVector = ERC32_INTERRUPT_UART_A_RX_TX
104  },
105  {
106    .sDeviceName = "/dev/console_b",
107    .deviceType = SERIAL_CUSTOM,
108    .pDeviceFns = &erc32_fns,
109    .deviceProbe = NULL,
110    .pDeviceFlow = NULL,
111    .ulMargin = 16,
112    .ulHysteresis = 8,
113    .pDeviceParams = (void *) -1,  /* could be baud rate */
114    .ulCtrlPort1 = 0,
115    .ulCtrlPort2 = 0,
116    .ulDataPort = 0,
117    .getRegister = erc32_console_get_register,
118    .setRegister = erc32_console_set_register,
119    .getData = NULL,
120    .setData = NULL,
121    .ulClock = 16,
122    .ulIntVector = ERC32_INTERRUPT_UART_B_RX_TX
123  },
124};
125
126/* always exactly two uarts for erc32 */
127#define ERC32_UART_COUNT (2)
128
129unsigned long Console_Configuration_Count = ERC32_UART_COUNT;
130
131static int erc32_console_first_open(int major, int minor, void *arg)
132{
133  /* Check minor number */
134  if (minor < 0 || minor > 1) {
135    return -1;
136  }
137 
138  rtems_libio_open_close_args_t *oca = arg;
139  struct rtems_termios_tty *tty = oca->iop->data1;
140  console_tbl *ct = Console_Port_Tbl [minor];
141  console_data *cd = &Console_Port_Data [minor];
142 
143  cd->termios_data = tty;
144  rtems_termios_set_initial_baud(tty, (int32_t)ct->pDeviceParams);
145 
146  return 0;
147}
148
149#if (CONSOLE_USE_INTERRUPTS)
150static ssize_t erc32_console_write_support_int(
151    int minor, const char *buf, size_t len)
152{
153  if (len > 0) {
154    console_data *cd = &Console_Port_Data[minor];
155    int k = 0;
156
157    if (minor == 0) { /* uart a */
158      for (k = 0;
159           k < len && (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA);
160           k ++) {
161        ERC32_MEC.UART_Channel_A = (unsigned char)buf[k];
162      }
163      ERC32_Force_interrupt(ERC32_INTERRUPT_UART_A_RX_TX);
164    } else { /* uart b */
165      for (k = 0;
166           k < len && (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB);
167           k ++) {
168        ERC32_MEC.UART_Channel_B = (unsigned char)buf[k];
169      }
170      ERC32_Force_interrupt(ERC32_INTERRUPT_UART_B_RX_TX);
171    }
172
173    cd->pDeviceContext = (void *)k;
174    cd->bActive = true;
175  }
176
177  return 0;
178}
179
180static void erc32_console_isr_error(
181  rtems_vector_number vector
182)
183{
184  int UStat;
185
186  UStat = ERC32_MEC.UART_Status;
187
188  if (UStat & ERC32_MEC_UART_STATUS_ERRA) {
189    ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRA;
190    ERC32_MEC.Control = ERC32_MEC.Control;
191  }
192
193  if (UStat & ERC32_MEC_UART_STATUS_ERRB) {
194    ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB;
195    ERC32_MEC.Control = ERC32_MEC.Control;
196  }
197
198  ERC32_Clear_interrupt( ERC32_INTERRUPT_UART_ERROR );
199}
200
201static void erc32_console_isr_a(
202  rtems_vector_number vector
203)
204{
205  console_data *cd = &Console_Port_Data[0];
206
207  /* check for error */
208  if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_ERRA) {
209    ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRA;
210    ERC32_MEC.Control = ERC32_MEC.Control;
211  }
212
213  do {
214    int chars_to_dequeue = (int)cd->pDeviceContext;
215    int rv = 0;
216    int i = 0;
217    char buf[CONSOLE_BUF_SIZE];
218       
219    /* enqueue received chars */
220    while (i < CONSOLE_BUF_SIZE) {
221      if (!(ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRA))
222        break;
223      buf[i] = ERC32_MEC.UART_Channel_A;
224      ++i;
225    }
226    if ( i )
227      rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i);
228
229    /* dequeue transmitted chars */
230    if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA) {
231      rv = rtems_termios_dequeue_characters(
232         cd->termios_data, chars_to_dequeue);
233      if ( !rv ) {
234        cd->pDeviceContext = 0;
235        cd->bActive = false;
236      }
237      ERC32_Clear_interrupt (ERC32_INTERRUPT_UART_A_RX_TX);
238    }
239  } while (ERC32_Is_interrupt_pending (ERC32_INTERRUPT_UART_A_RX_TX));
240}
241
242static void erc32_console_isr_b(
243  rtems_vector_number vector
244)
245{
246  console_data *cd = &Console_Port_Data[1];
247
248  /* check for error */
249  if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_ERRB) {
250      ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB;
251      ERC32_MEC.Control = ERC32_MEC.Control;
252  }
253
254  do {
255    int chars_to_dequeue = (int)cd->pDeviceContext;
256    int rv = 0;
257    int i = 0;
258    char buf[CONSOLE_BUF_SIZE];
259       
260    /* enqueue received chars */
261    while (i < CONSOLE_BUF_SIZE) {
262      if (!(ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRB))
263        break;
264      buf[i] = ERC32_MEC.UART_Channel_B;
265      ++i;
266    }
267    if ( i )
268      rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i);
269
270    /* dequeue transmitted chars */
271    if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB) {
272      rv = rtems_termios_dequeue_characters(
273         cd->termios_data, chars_to_dequeue);
274      if ( !rv ) {
275        cd->pDeviceContext = 0;
276        cd->bActive = false;
277      }
278      ERC32_Clear_interrupt (ERC32_INTERRUPT_UART_B_RX_TX);
279    }
280  } while (ERC32_Is_interrupt_pending (ERC32_INTERRUPT_UART_B_RX_TX));
281}
282#else
283
284extern void console_outbyte_polled( int  port, unsigned char ch );
285
286static ssize_t erc32_console_write_support_polled(
287  int         minor,
288  const char *buf,
289  size_t      len
290)
291{
292  int nwrite = 0;
293
294  while (nwrite < len) {
295    console_outbyte_polled( minor, *buf++ );
296    nwrite++;
297  }
298  return nwrite;
299}
300
301#endif
302
303
304/*
305 *  Console Device Driver Entry Points
306 *
307 */
308
309static void erc32_console_initialize(
310    int minor
311)
312{
313  console_data *cd = &Console_Port_Data [minor];
314
315  cd->bActive = false;
316  cd->pDeviceContext = 0;
317
318 /*
319  * Initialize the Termios infrastructure.  If Termios has already
320  * been initialized by another device driver, then this call will
321  * have no effect.
322  */
323  rtems_termios_initialize();
324
325 /*
326  *  Initialize Hardware
327  */
328  #if (CONSOLE_USE_INTERRUPTS)
329    set_vector(erc32_console_isr_a, CONSOLE_UART_A_TRAP, 1);
330    set_vector(erc32_console_isr_b, CONSOLE_UART_B_TRAP, 1);
331    set_vector(erc32_console_isr_error, CONSOLE_UART_ERROR_TRAP, 1);
332  #endif
333
334   /* Clear any previous error flags */
335   ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRA;
336   ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB;
337}
Note: See TracBrowser for help on using the repository browser.