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

4.104.114.84.95
Last change on this file since f817b02 was f817b02, checked in by Joel Sherrill <joel.sherrill@…>, on 11/04/99 at 18:05:09

The files in libcpu should not be directly dependent on any BSP. In
particular, using bsp.h, or getting information from the BSP which
should properly be obtained from RTEMS is forbidden. This is
necessary to strengthen the division between the BSP independent
parts of RTEMS and the BSPs themselves. This started after
comments and analysis by Ralf Corsepius <corsepiu@…>.
The changes primarily eliminated the need to include bsp.h and
peeking at BSP_Configuration. The use of Cpu_table in each
BSP needs to be eliminated.

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