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

4.115
Last change on this file since 59766586 was 59766586, checked in by Jennifer Averett <Jennifer.Averett@…>, on Oct 18, 2011 at 6:30:22 PM

2011-10-18 Jennifer Averett <Jennifer.Averett@…>

PR 1917/bsps

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