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

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

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