source: rtems/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c @ dc0a7df

4.115
Last change on this file since dc0a7df was dc0a7df, checked in by Sebastian Huber <sebastian.huber@…>, on Jul 21, 2011 at 3:18:02 PM

2011-07-21 Sebastian Huber <sebastian.huber@…>

PR 1799/bsps

  • .cvsignore, ChangeLog?, Makefile.am, README, bsp_specs, configure.ac, clock/clock-config.c, console/console-config.c, console/uart-bridge-master.c, console/uart-bridge-slave.c, include/.cvsignore, include/bsp.h, include/hwreg_vals.h, include/intercom.h, include/irq.h, include/mmu.h, include/qoriq.h, include/tm27.h, include/tsec-config.h, include/u-boot-config.h, include/uart-bridge.h, irq/irq.c, make/custom/qoriq.inc, make/custom/qoriq_core_0.cfg, make/custom/qoriq_core_1.cfg, make/custom/qoriq_p1020rdb.cfg, network/if_intercom.c, network/network.c, rtc/rtc-config.c, shmsupp/intercom-mpci.c, shmsupp/intercom.c, shmsupp/lock.S, start/start.S, startup/bsppredriverhook.c, startup/bspreset.c, startup/bspstart.c, startup/linkcmds.base, startup/linkcmds.qoriq_core_0, startup/linkcmds.qoriq_core_1, startup/linkcmds.qoriq_p1020rdb, startup/mmu-config.c, startup/mmu-tlb1.S, startup/mmu.c: New files.
  • Property mode set to 100644
File size: 5.2 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup QorIQUartBridge
5 *
6 * @brief UART bridge slave implementation.
7 */
8
9/*
10 * Copyright (c) 2011 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Obere Lagerstr. 30
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.com/license/LICENSE.
21 *
22 * $Id$
23 */
24
25#include <assert.h>
26
27#include <libchip/sersupp.h>
28
29#include <bspopts.h>
30#include <bsp/uart-bridge.h>
31
32#define TRANSMIT_EVENT RTEMS_EVENT_13
33
34static rtems_mode disable_preemption(void)
35{
36  rtems_status_code sc = RTEMS_SUCCESSFUL;
37  rtems_mode prev_mode = 0;
38
39  sc = rtems_task_mode (RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &prev_mode);
40  assert(sc == RTEMS_SUCCESSFUL);
41
42  return prev_mode;
43}
44
45static void restore_preemption(rtems_mode prev_mode)
46{
47  rtems_status_code sc = RTEMS_SUCCESSFUL;
48
49  sc = rtems_task_mode (prev_mode, RTEMS_PREEMPT_MASK, &prev_mode);
50  assert(sc == RTEMS_SUCCESSFUL);
51}
52
53static void uart_bridge_slave_service(intercom_packet *packet, void *arg)
54{
55  uart_bridge_slave_control *control = arg;
56  struct rtems_termios_tty *tty = control->tty;
57
58  /* Workaround for https://www.rtems.org/bugzilla/show_bug.cgi?id=1736 */
59  rtems_mode prev_mode = disable_preemption();
60
61  rtems_termios_enqueue_raw_characters(tty, packet->data, (int) packet->size);
62  qoriq_intercom_free_packet(packet);
63
64  restore_preemption(prev_mode);
65}
66
67static void transmit_task(rtems_task_argument arg)
68{
69  rtems_status_code sc = RTEMS_SUCCESSFUL;
70  uart_bridge_slave_control *control = (uart_bridge_slave_control *) arg;
71  rtems_chain_control *fifo = &control->transmit_fifo;
72  struct rtems_termios_tty *tty = control->tty;
73
74  while (true) {
75    intercom_packet *packet = NULL;
76    sc = rtems_chain_get_with_wait(
77      fifo,
78      TRANSMIT_EVENT,
79      RTEMS_NO_TIMEOUT,
80      (rtems_chain_node **) &packet
81    );
82    assert(sc == RTEMS_SUCCESSFUL);
83
84    /* Workaround for https://www.rtems.org/bugzilla/show_bug.cgi?id=1736 */
85    rtems_mode prev_mode = disable_preemption();
86
87    size_t size = packet->size;
88    qoriq_intercom_send_packet(QORIQ_UART_BRIDGE_MASTER_CORE, packet);
89    rtems_termios_dequeue_characters(tty, (int) size);
90
91    restore_preemption(prev_mode);
92  }
93}
94
95static void create_transmit_task(
96  uart_bridge_slave_control *control
97)
98{
99  rtems_status_code sc = RTEMS_SUCCESSFUL;
100  rtems_id task = RTEMS_ID_NONE;
101  char index = (char) ('0' + control->type - INTERCOM_TYPE_UART_0);
102
103  sc = rtems_task_create(
104    rtems_build_name('U', 'B', 'T', index),
105    QORIQ_UART_BRIDGE_TASK_PRIORITY,
106    0,
107    RTEMS_DEFAULT_MODES,
108    RTEMS_DEFAULT_ATTRIBUTES,
109    &task
110  );
111  assert(sc == RTEMS_SUCCESSFUL);
112
113  sc = rtems_task_start(
114    task,
115    transmit_task,
116    (rtems_task_argument) control
117  );
118  assert(sc == RTEMS_SUCCESSFUL);
119
120  control->transmit_task = task;
121}
122
123static void initialize(int minor)
124{
125  /* Do nothing */
126}
127
128static int first_open(int major, int minor, void *arg)
129{
130  rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg;
131  struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1;
132  console_tbl *ct = &Console_Port_Tbl [minor];
133  console_data *cd = &Console_Port_Data [minor];
134  uart_bridge_slave_control *control = ct->pDeviceParams;
135  intercom_type type = control->type;
136
137  control->tty = tty;
138  cd->termios_data = tty;
139  rtems_termios_set_initial_baud(tty, 115200);
140  create_transmit_task(control);
141  qoriq_intercom_service_install(type, uart_bridge_slave_service, control);
142
143  return 0;
144}
145
146static int last_close(int major, int minor, void *arg)
147{
148  console_tbl *ct = &Console_Port_Tbl [minor];
149  uart_bridge_slave_control *control = ct->pDeviceParams;
150
151  qoriq_intercom_service_remove(control->type);
152
153  return 0;
154}
155
156static ssize_t write_with_interrupts(int minor, const char *buf, size_t len)
157{
158  rtems_status_code sc = RTEMS_SUCCESSFUL;
159  console_tbl *ct = &Console_Port_Tbl [minor];
160  uart_bridge_slave_control *control = ct->pDeviceParams;
161  intercom_packet *packet = qoriq_intercom_allocate_packet(
162    control->type,
163    INTERCOM_SIZE_64
164  );
165
166  packet->size = len;
167  memcpy(packet->data, buf, len);
168
169  /*
170   * Due to the lovely Termios implementation we have to hand this over to
171   * another context.
172   */
173  sc = rtems_chain_append_with_notification(
174    &control->transmit_fifo,
175    &packet->glue.node,
176    control->transmit_task,
177    TRANSMIT_EVENT
178  );
179  assert(sc == RTEMS_SUCCESSFUL);
180
181  return 0;
182}
183
184static void write_polled(int minor, char c)
185{
186  console_tbl *ct = &Console_Port_Tbl [minor];
187  uart_bridge_slave_control *control = ct->pDeviceParams;
188  intercom_packet *packet = qoriq_intercom_allocate_packet(
189    control->type,
190    INTERCOM_SIZE_64
191  );
192  char *data = packet->data;
193  data [0] = c;
194  packet->size = 1;
195  qoriq_intercom_send_packet(QORIQ_UART_BRIDGE_MASTER_CORE, packet);
196}
197
198static int set_attribues(int minor, const struct termios *term)
199{
200  return -1;
201}
202
203console_fns qoriq_uart_bridge_slave = {
204  .deviceProbe = libchip_serial_default_probe,
205  .deviceFirstOpen = first_open,
206  .deviceLastClose = last_close,
207  .deviceRead = NULL,
208  .deviceWrite = write_with_interrupts,
209  .deviceInitialize = initialize,
210  .deviceWritePolled = write_polled,
211  .deviceSetAttributes = set_attribues,
212  .deviceOutputUsesInterrupts = true
213};
Note: See TracBrowser for help on using the repository browser.