source: rtems/c/src/lib/libcpu/powerpc/mpc5xx/console-generic/console-generic.c @ 1c6926c1

Last change on this file since 1c6926c1 was 1c6926c1, checked in by Kevin Kirspel <kevin-kirspel@…>, on Mar 21, 2017 at 7:39:48 PM

termios: Synchronize with latest FreeBSD headers

Adding modified FreeBSD headers to synchronize RTEMS termios with
FreeBSD. Modify termios to support dedicated input and output baud for
termios structure. Updated BSPs to use dedicated input and output baud
in termios structure. Updated tools to use dedicated input and output
baud in termios structure. Updated termios testsuites to use dedicated
input and output baud in termios structure.

Close #2897.

  • Property mode set to 100644
File size: 7.0 KB
Line 
1/*
2 *  General Serial I/O functions.
3 *
4 *  This file contains the functions for performing serial I/O.  The actual
5 *  system calls (console_*) should be in the BSP part of the source tree.
6 *  That way different BSPs can use whichever SCI they wish for /dev/console.
7 *
8 *  On-chip resources used:
9 *   resource   minor                note
10 *      SCI1      0
11 *      SCI2      1
12 */
13
14/*
15 *  MPC5xx port sponsored by Defence Research and Development Canada - Suffield
16 *  Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
17 *
18 *  Derived from
19 *    c/src/lib/libcpu/powerpc/mpc8xx/console_generic/console_generic.c:
20 *  Author: Jay Monkman (jmonkman@frasca.com)
21 *  Copyright (C) 1998 by Frasca International, Inc.
22 *
23 *  Derived from c/src/lib/libbsp/m68k/gen360/console/console.c written by:
24 *    W. Eric Norum
25 *    Saskatchewan Accelerator Laboratory
26 *    University of Saskatchewan
27 *    Saskatoon, Saskatchewan, CANADA
28 *    eric@skatter.usask.ca
29 *
30 *  COPYRIGHT (c) 1989-1998.
31 *  On-Line Applications Research Corporation (OAR).
32 *
33 *  Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca>
34 *  and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>
35 *  Copyright (c) 1999, National Research Council of Canada
36 *
37 *  The license and distribution terms for this file may be
38 *  found in the file LICENSE in this distribution or at
39 *  http://www.rtems.org/license/LICENSE.
40 */
41
42#include <stdlib.h>
43#include <unistd.h>
44#include <termios.h>
45#include <rtems.h>
46#include <rtems/libio.h>
47#include <rtems/bspIo.h>   /* for printk */
48#include <mpc5xx.h>
49#include <mpc5xx/console.h>
50#include <bsp/irq.h>
51
52
53/*
54 * SCI port descriptor table.
55 */
56typedef struct
57{
58  volatile m5xxSCIRegisters_t *regs;    /* hardware registers */
59  struct rtems_termios_tty *ttyp;       /* termios data for this port */
60} sci_desc;
61
62static sci_desc sci_descs[] = {
63  { &imb.qsmcm.sci1, 0 },               /* SCI 1 */
64  { &imb.qsmcm.sci2, 0 },               /* SCI 2 */
65};
66
67/*
68 * Number of SCI port initialization calls made so far.  Used to avoid
69 * installing the common interrupt handler more than once.
70 */
71int init_calls = 0;
72
73/*
74 * Default configuration.
75 */
76static struct termios default_termios = {
77  0,                                    /* input mode flags */
78  0,                                    /* output mode flags */
79  CS8 | CREAD | CLOCAL | B9600,         /* control mode flags */
80  0,                                    /* local mode flags */
81  0,                                    /* line discipline */
82  { 0 }                                 /* control characters */
83};
84
85
86extern uint32_t bsp_clock_speed;
87
88/*
89 * Termios callback functions
90 */
91
92int
93m5xx_uart_firstOpen(
94  int major,
95  int minor,
96  void *arg
97)
98{
99  rtems_libio_open_close_args_t *args = arg;
100  sci_desc* desc = &sci_descs[minor];
101  struct rtems_termios_tty *tty = args->iop->data1;
102
103  desc->ttyp = tty;                             /* connect tty */
104  if ( tty->device.outputUsesInterrupts == TERMIOS_IRQ_DRIVEN)
105    desc->regs->sccr1 |= QSMCM_SCI_RIE;         /* enable rx interrupt */
106
107  return RTEMS_SUCCESSFUL;
108}
109
110int
111m5xx_uart_lastClose(
112  int major,
113  int minor,
114  void* arg
115)
116{
117  sci_desc* desc = &sci_descs[minor];
118
119  desc->regs->sccr1 &= ~(QSMCM_SCI_RIE | QSMCM_SCI_TIE);  /* disable all */
120  desc->ttyp = NULL;                                      /* disconnect tty */
121
122  return RTEMS_SUCCESSFUL;
123}
124
125int
126m5xx_uart_pollRead(
127  int minor
128)
129{
130  volatile m5xxSCIRegisters_t *regs = sci_descs[minor].regs;
131  int c = -1;
132
133  if ( regs ) {
134    while ( (regs->scsr & QSMCM_SCI_RDRF) == 0 )
135      ;
136    c = regs->scdr;
137  }
138
139  return c;
140}
141
142ssize_t m5xx_uart_write(
143  int minor,
144  const char *buf,
145  size_t len
146)
147{
148  if (len > 0) {
149    volatile m5xxSCIRegisters_t *regs = sci_descs[minor].regs;
150
151    regs->scdr = *buf;                  /* start transmission */
152    regs->sccr1 |= QSMCM_SCI_TIE;               /* enable interrupt */
153  }
154
155  return 0;
156}
157
158ssize_t m5xx_uart_pollWrite(
159  int minor,
160  const char *buf,
161  size_t len
162)
163{
164  volatile m5xxSCIRegisters_t *regs = sci_descs[minor].regs;
165  size_t retval = len;
166
167  while ( len-- ) {
168    while ( (regs->scsr & QSMCM_SCI_TDRE) == 0 )
169      ;
170    regs->scdr = *buf++;
171  }
172
173  return retval;
174}
175
176int
177m5xx_uart_setAttributes(
178  int minor,
179  const struct termios *t
180)
181{
182  uint16_t sccr0 = sci_descs[minor].regs->sccr0;
183  uint16_t sccr1 = sci_descs[minor].regs->sccr1;
184  int baud;
185
186  /*
187   * Check that port number is valid
188   */
189  if ( (minor < SCI1_MINOR) || (minor > SCI2_MINOR) )
190    return RTEMS_INVALID_NUMBER;
191
192  /* Baud rate */
193  baud = rtems_termios_baud_to_number( t->c_ospeed );
194  if (baud > 0) {
195    sccr0 &= ~QSMCM_SCI_BAUD(-1);
196    sccr0 |= QSMCM_SCI_BAUD((bsp_clock_speed + (16 * baud)) / (32 * baud));
197  }
198
199  /* Number of data bits -- not available with MPC5xx SCI */
200  switch ( t->c_cflag & CSIZE ) {
201    case CS5:     break;
202    case CS6:     break;
203    case CS7:     break;
204    case CS8:     break;
205  }
206
207  /* Stop bits -- not easily available with MPC5xx SCI */
208  if ( t->c_cflag & CSTOPB ) {
209    /* Two stop bits */
210  } else {
211    /* One stop bit */
212  }
213
214  /* Parity */
215  if ( t->c_cflag & PARENB )
216    sccr1 |= QSMCM_SCI_PE;
217  else
218    sccr1 &= ~QSMCM_SCI_PE;
219
220  if ( t->c_cflag & PARODD )
221    sccr1 |= QSMCM_SCI_PT;
222  else
223    sccr1 &= ~QSMCM_SCI_PT;
224
225  /* Transmitter and receiver enable */
226  sccr1 |= QSMCM_SCI_TE;
227  if ( t->c_cflag & CREAD )
228    sccr1 |= QSMCM_SCI_RE;
229  else
230    sccr1 &= ~QSMCM_SCI_RE;
231
232  /* Write hardware registers */
233  sci_descs[minor].regs->sccr0 = sccr0;
234  sci_descs[minor].regs->sccr1 = sccr1;
235
236  return RTEMS_SUCCESSFUL;
237}
238
239
240/*
241 * Interrupt handling.
242 */
243static void
244m5xx_sci_interrupt_handler (rtems_irq_hdl_param unused)
245{
246  int minor;
247
248  for ( minor = 0; minor < NUM_PORTS; minor++ ) {
249    sci_desc *desc = &sci_descs[minor];
250    int sccr1 = desc->regs->sccr1;
251    int scsr = desc->regs->scsr;
252
253    /*
254     * Character received?
255     */
256    if ((sccr1 & QSMCM_SCI_RIE) && (scsr & QSMCM_SCI_RDRF)) {
257      char c = desc->regs->scdr;
258      rtems_termios_enqueue_raw_characters(desc->ttyp, &c, 1);
259    }
260    /*
261     * Transmitter empty?
262     */
263    if ((sccr1 & QSMCM_SCI_TIE) && (scsr & QSMCM_SCI_TDRE)) {
264      desc->regs->sccr1 &= ~QSMCM_SCI_TIE;
265      rtems_termios_dequeue_characters (desc->ttyp, 1);
266    }
267  }
268}
269
270static void m5xx_sci_nop(const rtems_irq_connect_data* ptr)
271{
272}
273
274static int m5xx_sci_isOn(const rtems_irq_connect_data* ptr)
275{
276  return 1;
277}
278
279/*
280 * Basic initialization.
281 */
282
283void
284m5xx_uart_initialize (int minor)
285{
286  /*
287   * Check that minor number is valid.
288   */
289  if ( (minor < SCI1_MINOR) || (minor > SCI2_MINOR) )
290    return;
291
292  /*
293   * Configure and enable receiver and transmitter.
294   */
295  m5xx_uart_setAttributes(minor, &default_termios);
296
297  /*
298   * Connect interrupt if not yet done.
299   */
300  if ( init_calls++ == 0 ) {
301    rtems_irq_connect_data irq_data;
302
303    irq_data.name = CPU_IRQ_SCI;
304    irq_data.hdl  = m5xx_sci_interrupt_handler;
305    irq_data.on   = m5xx_sci_nop;       /* can't enable both channels here */
306    irq_data.off  = m5xx_sci_nop;       /* can't disable both channels here */
307    irq_data.isOn = m5xx_sci_isOn;
308
309    if (!CPU_install_rtems_irq_handler (&irq_data)) {
310      printk("Unable to connect SCI Irq handler\n");
311      rtems_fatal_error_occurred(1);
312    }
313
314    imb.qsmcm.qdsci_il =                /* set interrupt level in port */
315      QSMCM_ILDSCI(CPU_irq_level_from_symbolic_name(CPU_IRQ_SCI));
316  }
317}
Note: See TracBrowser for help on using the repository browser.