source: rtems/c/src/lib/libcpu/powerpc/ppc403/console/console.c @ e9ae97fb

4.104.114.84.95
Last change on this file since e9ae97fb was e9ae97fb, checked in by Joel Sherrill <joel.sherrill@…>, on 11/09/01 at 00:04:57

2001-11-08 Dennis Ehlin (ECS) <Dennis.Ehlin@…>

This modification is part of the submitted modifications necessary to
support the IBM PPC405 family. This submission was reviewed by
Thomas Doerfler <Thomas.Doerfler@…> who ensured it did
not negatively impact the ppc403 BSPs. The submission and tracking
process was captured as PR50.

  • ppc403/console/console405.c ppc403/tty_drv/.cvsignore, ppc403/tty_drv/Makefile.am, ppc403/tty_drv/tty_drv.c, ppc403/tty_drv/tty_drv.h: New files.
  • Makefile.am, README, configure.ac, old_exception_processing/cpu.c, old_exception_processing/cpu.h, ppc403/Makefile.am, ppc403/clock/clock.c, ppc403/console/Makefile.am, ppc403/console/console.c, ppc403/ictrl/ictrl.c, ppc403/ictrl/ictrl.h, ppc403/timer/timer.c: Modified.
  • Property mode set to 100644
File size: 14.1 KB
RevLine 
[3235ad9]1/*
2 *  This file contains the PowerPC 403GA console IO package.
3 *
[aecfa2b]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 *
[e57b0e2]16 *  Author:     Andrew Bray <andy@i-cubed.co.uk>
[3235ad9]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 *
[aecfa2b]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 *
[3235ad9]44 *  Derived from c/src/lib/libbsp/no_cpu/no_bsp/console/console.c:
45 *
[aecfa2b]46 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
[3235ad9]47 *  On-Line Applications Research Corporation (OAR).
[aecfa2b]48 *  All rights assigned to U.S. Government, 1994.
[3235ad9]49 *
[aecfa2b]50 *  This material may be reproduced by or for the U.S. Government pursuant
51 *  to the copyright license under the clause at DFARS 252.227-7013.  This
52 *  notice must appear in all copies of this file and its derivatives.
[3235ad9]53 *
[aecfa2b]54 *  console.c,v 1.4 1995/12/05 19:23:02 joel Exp
[3235ad9]55 */
56
57#define NO_BSP_INIT
58
[f817b02]59#include <rtems.h>
[3a4ae6c]60#include <rtems/libio.h>
[aecfa2b]61#include "../ictrl/ictrl.h"
62#include <stdlib.h>                                     /* for atexit() */
[3235ad9]63
64struct async {
[aecfa2b]65/*---------------------------------------------------------------------------+
[3235ad9]66| Line Status Register.
[aecfa2b]67+---------------------------------------------------------------------------*/
68  unsigned char SPLS;
69  unsigned char SPLSset;
[3235ad9]70#define LSRDataReady             0x80
71#define LSRFramingError          0x40
72#define LSROverrunError          0x20
73#define LSRParityError           0x10
74#define LSRBreakInterrupt        0x08
75#define LSRTxHoldEmpty           0x04
76#define LSRTxShiftEmpty          0x02
77
[aecfa2b]78/*---------------------------------------------------------------------------+
[3235ad9]79| Handshake Status Register.
[aecfa2b]80+---------------------------------------------------------------------------*/
81  unsigned char SPHS;
82  unsigned char SPHSset;
[3235ad9]83#define HSRDsr                   0x80
84#define HSRCts                   0x40
85
[aecfa2b]86/*---------------------------------------------------------------------------+
[3235ad9]87| Baud rate divisor registers
[aecfa2b]88+---------------------------------------------------------------------------*/
89  unsigned char BRDH;
90  unsigned char BRDL;
[3235ad9]91
[aecfa2b]92/*---------------------------------------------------------------------------+
[3235ad9]93| Control Register.
[aecfa2b]94+---------------------------------------------------------------------------*/
95  unsigned char SPCTL;
96#define CRNormal                 0x00
97#define CRLoopback               0x40
98#define CRAutoEcho               0x80
[3235ad9]99#define CRDtr                    0x20
100#define CRRts                    0x10
101#define CRWordLength7            0x00
102#define CRWordLength8            0x08
103#define CRParityDisable          0x00
104#define CRParityEnable           0x04
105#define CREvenParity             0x00
[aecfa2b]106#define CROddParity              0x02
[3235ad9]107#define CRStopBitsOne            0x00
108#define CRStopBitsTwo            0x01
[aecfa2b]109#define CRDisableDtrRts          0x00
[3235ad9]110
[aecfa2b]111/*--------------------------------------------------------------------------+
[3235ad9]112| Receiver Command Register.
[aecfa2b]113+--------------------------------------------------------------------------*/
114  unsigned char SPRC;
115#define RCRDisable               0x00
116#define RCREnable                0x80
117#define RCRIntDisable            0x00
118#define RCRIntEnabled            0x20
119#define RCRDMACh2                0x40
120#define RCRDMACh3                0x60
121#define RCRErrorInt              0x10
122#define RCRPauseEnable           0x08
123
124/*--------------------------------------------------------------------------+
[3235ad9]125| Transmitter Command Register.
[aecfa2b]126+--------------------------------------------------------------------------*/
[3235ad9]127    unsigned char SPTC;
[aecfa2b]128#define TCRDisable               0x00
129#define TCREnable                0x80
130#define TCRIntDisable            0x00
131#define TCRIntEnabled            0x20
132#define TCRDMACh2                0x40
133#define TCRDMACh3                0x60
134#define TCRTxEmpty               0x10
135#define TCRErrorInt              0x08
136#define TCRStopPause             0x04
137#define TCRBreakGen              0x02
138
139/*--------------------------------------------------------------------------+
[3235ad9]140| Miscellanies defines.
[aecfa2b]141+--------------------------------------------------------------------------*/
142  unsigned char SPTB;
[3235ad9]143#define SPRB    SPTB
144};
145
146typedef volatile struct async *pasync;
147static const pasync port = (pasync)0x40000000;
148
[aecfa2b]149static void *spittyp;         /* handle for termios */
[e9ae97fb]150int ppc403_spi_interrupt = 1; /* use interrupts... */
[aecfa2b]151
152/*
153 * Rx Interrupt handler
[3235ad9]154 */
[aecfa2b]155static rtems_isr
156spiRxInterruptHandler (rtems_vector_number v)
157{
158  char ch;
159
160  /* clear any receive errors (errors are ignored now) */
161  port->SPLS = (LSRFramingError | LSROverrunError |
162                LSRParityError  | LSRBreakInterrupt);
163  /*
164   * Buffer received?
165   */
166  if (port->SPLS & LSRDataReady) {
167    ch = port->SPRB; /* read receive buffer */
168    rtems_termios_enqueue_raw_characters (spittyp,&ch,1);
169  }
170}
[3235ad9]171
[aecfa2b]172/*
173 * Tx Interrupt handler
174 */
175static rtems_isr
176spiTxInterruptHandler (rtems_vector_number v)
[3235ad9]177{
[aecfa2b]178  /*
179   * char transmitted?
180   */
181  if (0 != (port->SPLS & LSRTxHoldEmpty)) { /* must always be true!! */
182    port->SPTC &= ~TCRIntEnabled;           /* stop irqs for now...  */
183                                            /* and call termios...   */
184    rtems_termios_dequeue_characters (spittyp,1);
185  }
186}
[3235ad9]187
[aecfa2b]188/*
189 * enable/disable RTS line to start/stop remote transmitter
190 */
191static int
192spiStartRemoteTx (int minor)
193{
194  rtems_interrupt_level level;
[3235ad9]195
[aecfa2b]196  rtems_interrupt_disable (level);
197  port->SPCTL |= CRRts;           /* activate RTS  */
198  rtems_interrupt_enable (level);
199  return 0;
[3235ad9]200}
201
[aecfa2b]202static int
203spiStopRemoteTx (int minor)
204{
205  rtems_interrupt_level level;
[3235ad9]206
[aecfa2b]207  rtems_interrupt_disable (level);
208  port->SPCTL &= ~CRRts;           /* deactivate RTS  */
209  rtems_interrupt_enable (level);
210  return 0;
211}
212
213void
214spiBaudSet(unsigned32 baudrate)
215{
216  unsigned32 tmp;
[458bd34]217  tmp = rtems_cpu_configuration_get_serial_per_sec() / baudrate;
[aecfa2b]218  tmp = ((tmp) >> 4) - 1;
219  port->BRDL = tmp & 0xff;
220  port->BRDH = tmp >> 8;
221
222}
223/*
224 * Hardware-dependent portion of tcsetattr().
[3235ad9]225 */
[aecfa2b]226static int
227spiSetAttributes (int minor, const struct termios *t)
228{
229  int baud;
230
231  /* FIXME: check c_cflag & CRTSCTS for hardware flowcontrol */
232  /* FIXME: check and IMPLEMENT XON/XOFF                     */
233  switch (t->c_cflag & CBAUD) {
234  default:      baud = -1;      break;
235  case B50:     baud = 50;      break;
236  case B75:     baud = 75;      break;
237  case B110:    baud = 110;     break;
238  case B134:    baud = 134;     break;
239  case B150:    baud = 150;     break;
240  case B200:    baud = 200;     break;
241  case B300:    baud = 300;     break;
242  case B600:    baud = 600;     break;
243  case B1200:   baud = 1200;    break;
244  case B1800:   baud = 1800;    break;
245  case B2400:   baud = 2400;    break;
246  case B4800:   baud = 4800;    break;
247  case B9600:   baud = 9600;    break;
248  case B19200:  baud = 19200;   break;
249  case B38400:  baud = 38400;   break;
250  case B57600:  baud = 57600;   break;
251  case B115200: baud = 115200;  break;
252  case B230400: baud = 230400;  break;
253  case B460800: baud = 460800;  break;
254  }
255  if (baud > 0) {
256    spiBaudSet(baud);
257  }
258  return 0;
259}
[3235ad9]260
[aecfa2b]261static int
262spiPollRead (int minor)
[3235ad9]263{
264  unsigned char status;
265
[aecfa2b]266  while (0 == ((status = port->SPLS) & LSRDataReady)) {
267    /* Clean any dodgy status */
268    if ((status & (LSRFramingError | LSROverrunError | LSRParityError |
269                   LSRBreakInterrupt)) != 0) {
[3235ad9]270      port->SPLS = (LSRFramingError | LSROverrunError | LSRParityError |
[aecfa2b]271                    LSRBreakInterrupt);
[3235ad9]272    }
[aecfa2b]273  }
274  return port->SPRB; 
275}
276
277static int
278spiInterruptWrite (int minor, const char *buf, int len)
279{
280  port->SPTB = *buf;           /* write char to send         */
281  port->SPTC |= TCRIntEnabled; /* always enable tx interrupt */
282  return 0;
283}
284
285static int
286spiPollWrite(int minor,const char *buf,int len)
287
288  unsigned char status;
[3235ad9]289
[aecfa2b]290  while (len-- > 0) {
291    do {
292      if (port->SPHS) {
293        port->SPHS = (HSRDsr | HSRCts);
294      }
295      status = port->SPLS;
296    } while (0 == (status & LSRTxHoldEmpty));
297    port->SPTB = *buf++;
298  }
299  return 0;
[3235ad9]300}
301
[aecfa2b]302/*
[3235ad9]303 *
[aecfa2b]304 * deinit SPI
[3235ad9]305 *
[aecfa2b]306 */
307void
308spiDeInit(void)
309{
310  /*
311   * disable interrupts for serial port
312   * set it to state to work with polling boot monitor, if any...
313   */
314
315  /* set up baud rate to original state */
[458bd34]316  spiBaudSet(rtems_cpu_configuration_get_serial_rate());
[aecfa2b]317
318  /* clear any receive (error) status */
319  port->SPLS = (LSRDataReady   | LSRFramingError | LSROverrunError |
320                LSRParityError | LSRBreakInterrupt);
321
322  /* set up port control: DTR/RTS active,8 bit,1 stop,no parity */
323  port->SPCTL = (CRNormal |
324                 CRDtr | CRRts |
325                 CRWordLength8 | CRParityDisable | CRStopBitsOne);
326
327  /* clear handshake status bits */
328  port->SPHS = (HSRDsr | HSRCts);
329
330  /* enable receiver/transmitter, no interrupts */
331  port->SPRC = (RCREnable | RCRIntDisable);
332  port->SPTC = (TCREnable | TCRIntDisable);
333
334}
335
336/*
[3235ad9]337 *
[aecfa2b]338 * init SPI
[3235ad9]339 *
340 */
[aecfa2b]341rtems_status_code
342spiInitialize(void)
[3235ad9]343{
[aecfa2b]344  register unsigned tmp;
345  rtems_isr_entry previous_isr; /* this is a dummy */
[3235ad9]346
[aecfa2b]347  /*
348   * Initialise the serial port
349   */
[3235ad9]350
[aecfa2b]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;
[458bd34]358  tmp |= (rtems_cpu_configuration_get_serial_external_clock() ? 2 : 0) | 1;
[aecfa2b]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 */
[458bd34]367  spiBaudSet(rtems_cpu_configuration_get_serial_rate());
[aecfa2b]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
[3235ad9]408 *
[aecfa2b]409 *  This routine initializes the console IO driver.
[3235ad9]410 *
[aecfa2b]411 *  Input parameters: NONE
[3235ad9]412 *
413 *  Output parameters:  NONE
[aecfa2b]414 *
415 *  Return values:
[3235ad9]416 */
417
[aecfa2b]418rtems_device_driver console_initialize(
419  rtems_device_major_number  major,
420  rtems_device_minor_number  minor,
421  void                      *arg
[3235ad9]422)
423{
[aecfa2b]424  rtems_status_code status;
[3235ad9]425
[aecfa2b]426  /*
427   * Set up TERMIOS
428   */
429  rtems_termios_initialize ();
[3235ad9]430
[aecfa2b]431  /*
432   * Do device-specific initialization
433   */
434  spiInitialize ();
[3235ad9]435
[aecfa2b]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;
[3235ad9]443}
444
[aecfa2b]445
[3235ad9]446/*
[3a4ae6c]447 *  Open entry point
[3235ad9]448 */
[3a4ae6c]449 
450rtems_device_driver console_open(
451  rtems_device_major_number major,
452  rtems_device_minor_number minor,
453  void                    * arg
[3235ad9]454)
455{
[aecfa2b]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;
[3a4ae6c]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{
[aecfa2b]501  return rtems_termios_close (arg);
[3a4ae6c]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{
[aecfa2b]514  return rtems_termios_read (arg);
[3235ad9]515}
[3a4ae6c]516 
[3235ad9]517/*
[3a4ae6c]518 * write bytes to the serial port. Stdout and stderr are the same.
[3235ad9]519 */
[3a4ae6c]520 
521rtems_device_driver console_write(
522  rtems_device_major_number major,
523  rtems_device_minor_number minor,
524  void                    * arg
[3235ad9]525)
526{
[aecfa2b]527  return rtems_termios_write (arg);
[3a4ae6c]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{
[aecfa2b]540  return rtems_termios_ioctl (arg);
[3235ad9]541}
[3a4ae6c]542
Note: See TracBrowser for help on using the repository browser.