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

4.115
Last change on this file since c8bd3cd was c8bd3cd, checked in by Sebastian Huber <sebastian.huber@…>, on 02/08/13 at 12:39:59

libchip/serial: Add const qualifier

  • Property mode set to 100644
File size: 8.2 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.com/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(int minor, const char *buf, size_t len)
151{
152  console_data *cd = &Console_Port_Data[minor];
153  int k = 0;
154
155  if (minor == 0) { /* uart a */
156    for (k = 0;
157         k < len && (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA); k ++) {
158      ERC32_MEC.UART_Channel_A = (unsigned char)buf[k];
159    }
160    ERC32_Force_interrupt(ERC32_INTERRUPT_UART_A_RX_TX);
161  } else { /* uart b */
162    for (k = 0;
163         k < len && (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB); k ++) {
164      ERC32_MEC.UART_Channel_B = (unsigned char)buf[k];
165    }
166    ERC32_Force_interrupt(ERC32_INTERRUPT_UART_B_RX_TX);
167  }
168 
169  if (len > 0) {
170    cd->pDeviceContext = (void *)k;
171    cd->bActive = true;
172  }
173 
174  return 0;
175}
176
177static void erc32_console_isr_a(
178  rtems_vector_number vector
179)
180{
181  console_data *cd = &Console_Port_Data[0];
182
183  /* check for error */
184  if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_ERRA) {
185    ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRA;
186    ERC32_MEC.Control = ERC32_MEC.Control;
187  }
188
189  do {
190    int chars_to_dequeue = (int)cd->pDeviceContext;
191    int rv = 0;
192    int i = 0;
193    char buf[CONSOLE_BUF_SIZE];
194       
195    /* enqueue received chars */
196    while (i < CONSOLE_BUF_SIZE) {
197      if (!(ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRA))
198        break;
199      buf[i] = ERC32_MEC.UART_Channel_A;
200      ++i;
201    }
202    if ( i )
203      rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i);
204
205    /* dequeue transmitted chars */
206    if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEA) {
207      rv = rtems_termios_dequeue_characters(
208         cd->termios_data, chars_to_dequeue);
209      if ( !rv ) {
210        cd->pDeviceContext = 0;
211        cd->bActive = false;
212      }
213      ERC32_Clear_interrupt (ERC32_INTERRUPT_UART_A_RX_TX);
214    }
215  } while (ERC32_Is_interrupt_pending (ERC32_INTERRUPT_UART_A_RX_TX));
216}
217
218static void erc32_console_isr_b(
219  rtems_vector_number vector
220)
221{
222  console_data *cd = &Console_Port_Data[1];
223
224  /* check for error */
225  if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_ERRB) {
226      ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB;
227      ERC32_MEC.Control = ERC32_MEC.Control;
228  }
229
230  do {
231    int chars_to_dequeue = (int)cd->pDeviceContext;
232    int rv = 0;
233    int i = 0;
234    char buf[CONSOLE_BUF_SIZE];
235       
236    /* enqueue received chars */
237    while (i < CONSOLE_BUF_SIZE) {
238      if (!(ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRB))
239        break;
240      buf[i] = ERC32_MEC.UART_Channel_B;
241      ++i;
242    }
243    if ( i )
244      rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i);
245
246    /* dequeue transmitted chars */
247    if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB) {
248      rv = rtems_termios_dequeue_characters(
249         cd->termios_data, chars_to_dequeue);
250      if ( !rv ) {
251        cd->pDeviceContext = 0;
252        cd->bActive = false;
253      }
254      ERC32_Clear_interrupt (ERC32_INTERRUPT_UART_B_RX_TX);
255    }
256  } while (ERC32_Is_interrupt_pending (ERC32_INTERRUPT_UART_B_RX_TX));
257}
258#else
259
260extern void console_outbyte_polled( int  port, unsigned char ch );
261
262static ssize_t erc32_console_write_support_polled(
263  int         minor,
264  const char *buf,
265  size_t      len
266)
267{
268  int nwrite = 0;
269
270  while (nwrite < len) {
271    console_outbyte_polled( minor, *buf++ );
272    nwrite++;
273  }
274  return nwrite;
275}
276
277#endif
278
279
280/*
281 *  Console Device Driver Entry Points
282 *
283 */
284
285static void erc32_console_initialize(
286    int minor
287)
288{
289  console_data *cd = &Console_Port_Data [minor];
290
291  cd->bActive = false;
292  cd->pDeviceContext = 0;
293
294 /*
295  * Initialize the Termios infrastructure.  If Termios has already
296  * been initialized by another device driver, then this call will
297  * have no effect.
298  */
299  rtems_termios_initialize();
300
301 /*
302  *  Initialize Hardware
303  */
304  #if (CONSOLE_USE_INTERRUPTS)
305    set_vector(erc32_console_isr_a, CONSOLE_UART_A_TRAP, 1);
306    set_vector(erc32_console_isr_b, CONSOLE_UART_B_TRAP, 1);
307  #endif
308}
Note: See TracBrowser for help on using the repository browser.