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

4.104.114.95
Last change on this file since 39d08d55 was 39d08d55, checked in by Ralf Corsepius <ralf.corsepius@…>, on 09/06/08 at 17:36:55

Convert to "bool".

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