source: rtems/c/src/lib/libcpu/powerpc/ppc403/console/console.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: 13.8 KB
Line 
1/*
2 *  This file contains the PowerPC 403GA console IO package.
3 *
4 *  Author:     Thomas Doerfler <td@imd.m.isar.de>
5 *              IMD Ingenieurbuero fuer Microcomputertechnik
6 *
7 *  COPYRIGHT (c) 1998 by IMD
8 *
9 *  Changes from IMD are covered by the original distributions terms.
10 *  changes include interrupt support and termios support
11 *  for backward compatibility, the original polled driver has been
12 *  renamed to console.c.polled
13 *
14 *  This file has been initially created (polled version) by
15 *
16 *  Author:     Andrew Bray <andy@i-cubed.co.uk>
17 *
18 *  COPYRIGHT (c) 1995 by i-cubed ltd.
19 *
20 *  To anyone who acknowledges that this file is provided "AS IS"
21 *  without any express or implied warranty:
22 *      permission to use, copy, modify, and distribute this file
23 *      for any purpose is hereby granted without fee, provided that
24 *      the above copyright notice and this notice appears in all
25 *      copies, and that the name of i-cubed limited not be used in
26 *      advertising or publicity pertaining to distribution of the
27 *      software without specific, written prior permission.
28 *      i-cubed limited makes no representations about the suitability
29 *      of this software for any purpose.
30 *
31 *  Modifications for spooling (interrupt driven) console driver
32 *            by Thomas Doerfler <td@imd.m.isar.de>
33 *  for these modifications:
34 *  COPYRIGHT (c) 1997 by IMD, Puchheim, Germany.
35 *
36 *  To anyone who acknowledges that this file is provided "AS IS"
37 *  without any express or implied warranty:
38 *      permission to use, copy, modify, and distribute this file
39 *      for any purpose is hereby granted without fee, provided that
40 *      the above copyright notice and this notice appears in all
41 *      copies. IMD makes no representations about the suitability
42 *      of this software for any purpose.
43 *
44 *  Derived from c/src/lib/libbsp/no_cpu/no_bsp/console/console.c:
45 *
46 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
47 *  On-Line Applications Research Corporation (OAR).
48 */
49
50#define NO_BSP_INIT
51
52#include <rtems.h>
53#include <rtems/libio.h>
54#include "../irq/ictrl.h"
55#include <stdlib.h>                                     /* for atexit() */
56
57struct async {
58/*---------------------------------------------------------------------------+
59| Line Status Register.
60+---------------------------------------------------------------------------*/
61  unsigned char SPLS;
62  unsigned char SPLSset;
63#define LSRDataReady             0x80
64#define LSRFramingError          0x40
65#define LSROverrunError          0x20
66#define LSRParityError           0x10
67#define LSRBreakInterrupt        0x08
68#define LSRTxHoldEmpty           0x04
69#define LSRTxShiftEmpty          0x02
70
71/*---------------------------------------------------------------------------+
72| Handshake Status Register.
73+---------------------------------------------------------------------------*/
74  unsigned char SPHS;
75  unsigned char SPHSset;
76#define HSRDsr                   0x80
77#define HSRCts                   0x40
78
79/*---------------------------------------------------------------------------+
80| Baud rate divisor registers
81+---------------------------------------------------------------------------*/
82  unsigned char BRDH;
83  unsigned char BRDL;
84
85/*---------------------------------------------------------------------------+
86| Control Register.
87+---------------------------------------------------------------------------*/
88  unsigned char SPCTL;
89#define CRNormal                 0x00
90#define CRLoopback               0x40
91#define CRAutoEcho               0x80
92#define CRDtr                    0x20
93#define CRRts                    0x10
94#define CRWordLength7            0x00
95#define CRWordLength8            0x08
96#define CRParityDisable          0x00
97#define CRParityEnable           0x04
98#define CREvenParity             0x00
99#define CROddParity              0x02
100#define CRStopBitsOne            0x00
101#define CRStopBitsTwo            0x01
102#define CRDisableDtrRts          0x00
103
104/*--------------------------------------------------------------------------+
105| Receiver Command Register.
106+--------------------------------------------------------------------------*/
107  unsigned char SPRC;
108#define RCRDisable               0x00
109#define RCREnable                0x80
110#define RCRIntDisable            0x00
111#define RCRIntEnabled            0x20
112#define RCRDMACh2                0x40
113#define RCRDMACh3                0x60
114#define RCRErrorInt              0x10
115#define RCRPauseEnable           0x08
116
117/*--------------------------------------------------------------------------+
118| Transmitter Command Register.
119+--------------------------------------------------------------------------*/
120    unsigned char SPTC;
121#define TCRDisable               0x00
122#define TCREnable                0x80
123#define TCRIntDisable            0x00
124#define TCRIntEnabled            0x20
125#define TCRDMACh2                0x40
126#define TCRDMACh3                0x60
127#define TCRTxEmpty               0x10
128#define TCRErrorInt              0x08
129#define TCRStopPause             0x04
130#define TCRBreakGen              0x02
131
132/*--------------------------------------------------------------------------+
133| Miscellanies defines.
134+--------------------------------------------------------------------------*/
135  unsigned char SPTB;
136#define SPRB    SPTB
137};
138
139typedef volatile struct async *pasync;
140static const pasync port = (pasync)0x40000000;
141
142static void *spittyp;         /* handle for termios */
143int ppc403_spi_interrupt = 1; /* use interrupts... */
144
145/*
146 * Rx Interrupt handler
147 */
148static rtems_isr
149spiRxInterruptHandler (rtems_vector_number v)
150{
151  char ch;
152
153  /* clear any receive errors (errors are ignored now) */
154  port->SPLS = (LSRFramingError | LSROverrunError |
155                LSRParityError  | LSRBreakInterrupt);
156  /*
157   * Buffer received?
158   */
159  if (port->SPLS & LSRDataReady) {
160    ch = port->SPRB; /* read receive buffer */
161    rtems_termios_enqueue_raw_characters (spittyp,&ch,1);
162  }
163}
164
165/*
166 * Tx Interrupt handler
167 */
168static rtems_isr
169spiTxInterruptHandler (rtems_vector_number v)
170{
171  /*
172   * char transmitted?
173   */
174  if (0 != (port->SPLS & LSRTxHoldEmpty)) { /* must always be true!! */
175    port->SPTC &= ~TCRIntEnabled;           /* stop irqs for now...  */
176                                            /* and call termios...   */
177    rtems_termios_dequeue_characters (spittyp,1);
178  }
179}
180
181/*
182 * enable/disable RTS line to start/stop remote transmitter
183 */
184static int
185spiStartRemoteTx (int minor)
186{
187  rtems_interrupt_level level;
188
189  rtems_interrupt_disable (level);
190  port->SPCTL |= CRRts;           /* activate RTS  */
191  rtems_interrupt_enable (level);
192  return 0;
193}
194
195static int
196spiStopRemoteTx (int minor)
197{
198  rtems_interrupt_level level;
199
200  rtems_interrupt_disable (level);
201  port->SPCTL &= ~CRRts;           /* deactivate RTS  */
202  rtems_interrupt_enable (level);
203  return 0;
204}
205
206void
207spiBaudSet(uint32_t   baudrate)
208{
209  uint32_t   tmp;
210  extern uint32_t bsp_serial_per_sec;
211  tmp = bsp_serial_per_sec / baudrate;
212  tmp = ((tmp) >> 4) - 1;
213  port->BRDL = tmp & 0xff;
214  port->BRDH = tmp >> 8;
215
216}
217/*
218 * Hardware-dependent portion of tcsetattr().
219 */
220static int
221spiSetAttributes (int minor, const struct termios *t)
222{
223  int baud;
224
225  /* FIXME: check c_cflag & CRTSCTS for hardware flowcontrol */
226  /* FIXME: check and IMPLEMENT XON/XOFF                     */
227  switch (t->c_ospeed) {
228  default:      baud = -1;      break;
229  case B50:     baud = 50;      break;
230  case B75:     baud = 75;      break;
231  case B110:    baud = 110;     break;
232  case B134:    baud = 134;     break;
233  case B150:    baud = 150;     break;
234  case B200:    baud = 200;     break;
235  case B300:    baud = 300;     break;
236  case B600:    baud = 600;     break;
237  case B1200:   baud = 1200;    break;
238  case B1800:   baud = 1800;    break;
239  case B2400:   baud = 2400;    break;
240  case B4800:   baud = 4800;    break;
241  case B9600:   baud = 9600;    break;
242  case B19200:  baud = 19200;   break;
243  case B38400:  baud = 38400;   break;
244  case B57600:  baud = 57600;   break;
245  case B115200: baud = 115200;  break;
246  case B230400: baud = 230400;  break;
247  case B460800: baud = 460800;  break;
248  }
249  if (baud > 0) {
250    spiBaudSet(baud);
251  }
252  return 0;
253}
254
255static int
256spiPollRead (int minor)
257{
258  unsigned char status;
259
260  while (0 == ((status = port->SPLS) & LSRDataReady)) {
261    /* Clean any dodgy status */
262    if ((status & (LSRFramingError | LSROverrunError | LSRParityError |
263                   LSRBreakInterrupt)) != 0) {
264      port->SPLS = (LSRFramingError | LSROverrunError | LSRParityError |
265                    LSRBreakInterrupt);
266    }
267  }
268  return port->SPRB;
269}
270
271static int
272spiInterruptWrite (int minor, const char *buf, int len)
273{
274  if (len > 0) {
275    port->SPTB = *buf;           /* write char to send         */
276    port->SPTC |= TCRIntEnabled; /* always enable tx interrupt */
277  }
278
279  return 0;
280}
281
282static int
283spiPollWrite(int minor,const char *buf,int len)
284{
285  unsigned char status;
286
287  while (len-- > 0) {
288    do {
289      if (port->SPHS) {
290        port->SPHS = (HSRDsr | HSRCts);
291      }
292      status = port->SPLS;
293    } while (0 == (status & LSRTxHoldEmpty));
294    port->SPTB = *buf++;
295  }
296  return 0;
297}
298
299/*
300 *
301 * deinit SPI
302 *
303 */
304void
305spiDeInit(void)
306{
307  extern uint32_t bsp_serial_rate;
308  /*
309   * disable interrupts for serial port
310   * set it to state to work with polling boot monitor, if any...
311   */
312
313  /* set up baud rate to original state */
314  spiBaudSet(bsp_serial_rate);
315
316  /* clear any receive (error) status */
317  port->SPLS = (LSRDataReady   | LSRFramingError | LSROverrunError |
318                LSRParityError | LSRBreakInterrupt);
319
320  /* set up port control: DTR/RTS active,8 bit,1 stop,no parity */
321  port->SPCTL = (CRNormal |
322                 CRDtr | CRRts |
323                 CRWordLength8 | CRParityDisable | CRStopBitsOne);
324
325  /* clear handshake status bits */
326  port->SPHS = (HSRDsr | HSRCts);
327
328  /* enable receiver/transmitter, no interrupts */
329  port->SPRC = (RCREnable | RCRIntDisable);
330  port->SPTC = (TCREnable | TCRIntDisable);
331
332}
333
334/*
335 *
336 * init SPI
337 *
338 */
339rtems_status_code
340spiInitialize(void)
341{
342  register unsigned tmp;
343  rtems_isr_entry previous_isr; /* this is a dummy */
344  extern bool bsp_serial_external_clock;
345  extern uint32_t bsp_serial_rate;
346
347  /*
348   * Initialise the serial port
349   */
350
351  /*
352   * select RTS/CTS hardware handshake lines,
353   * select clock source
354   */
355  __asm__ volatile ("mfdcr %0, 0xa0" : "=r" (tmp)); /* IOCR */
356
357  tmp &= ~3;
358  tmp |= (bsp_serial_external_clock ? 2 : 0) | 1;
359
360  __asm__ volatile ("mtdcr 0xa0, %0" : "=r" (tmp) : "0" (tmp)); /* IOCR */
361
362  /* clear any receive (error) status */
363  port->SPLS = (LSRDataReady   | LSRFramingError | LSROverrunError |
364                LSRParityError | LSRBreakInterrupt);
365
366  /* set up baud rate */
367  spiBaudSet(bsp_serial_rate);
368
369  /* set up port control: DTR/RTS active,8 bit,1 stop,no parity */
370  port->SPCTL = (CRNormal |
371                 CRDtr | CRRts |
372                 CRWordLength8 | CRParityDisable | CRStopBitsOne);
373
374  /* clear handshake status bits */
375  port->SPHS = (HSRDsr | HSRCts);
376
377  if (ppc403_spi_interrupt) {
378    /* add rx/tx isr to vector table */
379    ictrl_set_vector(spiRxInterruptHandler,
380                     PPC_IRQ_EXT_SPIR,
381                     &previous_isr);
382
383    ictrl_set_vector(spiTxInterruptHandler,
384                     PPC_IRQ_EXT_SPIT,
385                     &previous_isr);
386
387    port->SPRC = (RCREnable | RCRIntEnabled | RCRErrorInt);
388    port->SPTC = (TCREnable | TCRIntDisable); /* don't enable TxInt yet */
389  }
390  else {
391    /* enable receiver/transmitter, no interrupts */
392    port->SPRC = (RCREnable | RCRIntDisable);
393    port->SPTC = (TCREnable | TCRIntDisable);
394  }
395
396  atexit(spiDeInit);
397
398  return RTEMS_SUCCESSFUL;
399}
400
401/*
402 ***************
403 * BOILERPLATE *
404 ***************
405 */
406
407/*  console_initialize
408 *
409 *  This routine initializes the console IO driver.
410 *
411 *  Input parameters: NONE
412 *
413 *  Output parameters:  NONE
414 *
415 *  Return values:
416 */
417
418rtems_device_driver console_initialize(
419  rtems_device_major_number  major,
420  rtems_device_minor_number  minor,
421  void                      *arg
422)
423{
424  rtems_status_code status;
425
426  /*
427   * Set up TERMIOS
428   */
429  rtems_termios_initialize ();
430
431  /*
432   * Do device-specific initialization
433   */
434  spiInitialize ();
435
436  /*
437   * Register the device
438   */
439  status = rtems_io_register_name ("/dev/console", major, 0);
440  if (status != RTEMS_SUCCESSFUL)
441    rtems_fatal_error_occurred (status);
442  return RTEMS_SUCCESSFUL;
443}
444
445
446/*
447 *  Open entry point
448 */
449
450rtems_device_driver console_open(
451  rtems_device_major_number major,
452  rtems_device_minor_number minor,
453  void                    * arg
454)
455{
456  rtems_status_code sc;
457  static const rtems_termios_callbacks intrCallbacks = {
458    NULL,               /* firstOpen */
459    NULL,               /* lastClose */
460    NULL,               /* pollRead */
461    spiInterruptWrite,  /* write */
462    spiSetAttributes,   /* setAttributes */
463    spiStopRemoteTx,    /* stopRemoteTx */
464    spiStartRemoteTx,   /* startRemoteTx */
465    1                   /* outputUsesInterrupts */
466  };
467
468  static const rtems_termios_callbacks pollCallbacks = {
469    NULL,               /* firstOpen */
470    NULL,               /* lastClose */
471    spiPollRead,        /* pollRead */
472    spiPollWrite,       /* write */
473    spiSetAttributes,   /* setAttributes */
474    spiStopRemoteTx,    /* stopRemoteTx */
475    spiStartRemoteTx,   /* startRemoteTx */
476    0                   /* outputUsesInterrupts */
477  };
478
479  if (ppc403_spi_interrupt) {
480    rtems_libio_open_close_args_t *args = arg;
481
482    sc = rtems_termios_open (major, minor, arg, &intrCallbacks);
483    spittyp = args->iop->data1;
484  }
485  else {
486    sc = rtems_termios_open (major, minor, arg, &pollCallbacks);
487  }
488  return sc;
489}
490
491/*
492 *  Close entry point
493 */
494
495rtems_device_driver console_close(
496  rtems_device_major_number major,
497  rtems_device_minor_number minor,
498  void                    * arg
499)
500{
501  return rtems_termios_close (arg);
502}
503
504/*
505 * read bytes from the serial port. We only have stdin.
506 */
507
508rtems_device_driver console_read(
509  rtems_device_major_number major,
510  rtems_device_minor_number minor,
511  void                    * arg
512)
513{
514  return rtems_termios_read (arg);
515}
516
517/*
518 * write bytes to the serial port. Stdout and stderr are the same.
519 */
520
521rtems_device_driver console_write(
522  rtems_device_major_number major,
523  rtems_device_minor_number minor,
524  void                    * arg
525)
526{
527  return rtems_termios_write (arg);
528}
529
530/*
531 *  IO Control entry point
532 */
533
534rtems_device_driver console_control(
535  rtems_device_major_number major,
536  rtems_device_minor_number minor,
537  void                    * arg
538)
539{
540  return rtems_termios_ioctl (arg);
541}
Note: See TracBrowser for help on using the repository browser.