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

4.104.114.84.95
Last change on this file since 73b5bd5d was 73b5bd5d, checked in by Ralf Corsepius <ralf.corsepius@…>, on Apr 15, 2004 at 1:33:58 PM

Remove stray white spaces.

  • Property mode set to 100644
File size: 13.7 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 "../ictrl/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  tmp = rtems_cpu_configuration_get_serial_per_sec() / baudrate;
213  tmp = ((tmp) >> 4) - 1;
214  port->BRDL = tmp & 0xff;
215  port->BRDH = tmp >> 8;
216
217}
218/*
219 * Hardware-dependent portion of tcsetattr().
220 */
221static int
222spiSetAttributes (int minor, const struct termios *t)
223{
224  int baud;
225
226  /* FIXME: check c_cflag & CRTSCTS for hardware flowcontrol */
227  /* FIXME: check and IMPLEMENT XON/XOFF                     */
228  switch (t->c_cflag & CBAUD) {
229  default:      baud = -1;      break;
230  case B50:     baud = 50;      break;
231  case B75:     baud = 75;      break;
232  case B110:    baud = 110;     break;
233  case B134:    baud = 134;     break;
234  case B150:    baud = 150;     break;
235  case B200:    baud = 200;     break;
236  case B300:    baud = 300;     break;
237  case B600:    baud = 600;     break;
238  case B1200:   baud = 1200;    break;
239  case B1800:   baud = 1800;    break;
240  case B2400:   baud = 2400;    break;
241  case B4800:   baud = 4800;    break;
242  case B9600:   baud = 9600;    break;
243  case B19200:  baud = 19200;   break;
244  case B38400:  baud = 38400;   break;
245  case B57600:  baud = 57600;   break;
246  case B115200: baud = 115200;  break;
247  case B230400: baud = 230400;  break;
248  case B460800: baud = 460800;  break;
249  }
250  if (baud > 0) {
251    spiBaudSet(baud);
252  }
253  return 0;
254}
255
256static int
257spiPollRead (int minor)
258{
259  unsigned char status;
260
261  while (0 == ((status = port->SPLS) & LSRDataReady)) {
262    /* Clean any dodgy status */
263    if ((status & (LSRFramingError | LSROverrunError | LSRParityError |
264                   LSRBreakInterrupt)) != 0) {
265      port->SPLS = (LSRFramingError | LSROverrunError | LSRParityError |
266                    LSRBreakInterrupt);
267    }
268  } 
269  return port->SPRB; 
270}
271
272static int
273spiInterruptWrite (int minor, const char *buf, int len)
274{
275  port->SPTB = *buf;           /* write char to send         */
276  port->SPTC |= TCRIntEnabled; /* always enable tx interrupt */
277  return 0;
278}
279
280static int 
281spiPollWrite(int minor,const char *buf,int len)
282{ 
283  unsigned char status;
284
285  while (len-- > 0) {
286    do {
287      if (port->SPHS) {
288        port->SPHS = (HSRDsr | HSRCts);
289      }
290      status = port->SPLS;
291    } while (0 == (status & LSRTxHoldEmpty));
292    port->SPTB = *buf++;
293  }
294  return 0;
295}
296
297/*
298 *
299 * deinit SPI
300 *
301 */
302void
303spiDeInit(void) 
304{
305  /*
306   * disable interrupts for serial port
307   * set it to state to work with polling boot monitor, if any...
308   */
309
310  /* set up baud rate to original state */
311  spiBaudSet(rtems_cpu_configuration_get_serial_rate());
312
313  /* clear any receive (error) status */
314  port->SPLS = (LSRDataReady   | LSRFramingError | LSROverrunError |
315                LSRParityError | LSRBreakInterrupt);
316
317  /* set up port control: DTR/RTS active,8 bit,1 stop,no parity */
318  port->SPCTL = (CRNormal | 
319                 CRDtr | CRRts | 
320                 CRWordLength8 | CRParityDisable | CRStopBitsOne);
321
322  /* clear handshake status bits */
323  port->SPHS = (HSRDsr | HSRCts);
324
325  /* enable receiver/transmitter, no interrupts */
326  port->SPRC = (RCREnable | RCRIntDisable);
327  port->SPTC = (TCREnable | TCRIntDisable);
328
329}
330
331/*
332 *
333 * init SPI
334 *
335 */
336rtems_status_code
337spiInitialize(void) 
338{
339  register unsigned tmp;
340  rtems_isr_entry previous_isr; /* this is a dummy */
341
342  /*
343   * Initialise the serial port
344   */
345
346  /*
347   * select RTS/CTS hardware handshake lines,
348   * select clock source
349   */
350  asm volatile ("mfdcr %0, 0xa0" : "=r" (tmp)); /* IOCR */
351
352  tmp &= ~3;
353  tmp |= (rtems_cpu_configuration_get_serial_external_clock() ? 2 : 0) | 1;
354
355  asm volatile ("mtdcr 0xa0, %0" : "=r" (tmp) : "0" (tmp)); /* IOCR */
356
357  /* clear any receive (error) status */
358  port->SPLS = (LSRDataReady   | LSRFramingError | LSROverrunError |
359                LSRParityError | LSRBreakInterrupt);
360
361  /* set up baud rate */
362  spiBaudSet(rtems_cpu_configuration_get_serial_rate());
363
364  /* set up port control: DTR/RTS active,8 bit,1 stop,no parity */
365  port->SPCTL = (CRNormal | 
366                 CRDtr | CRRts | 
367                 CRWordLength8 | CRParityDisable | CRStopBitsOne);
368
369  /* clear handshake status bits */
370  port->SPHS = (HSRDsr | HSRCts);
371
372  if (ppc403_spi_interrupt) {
373    /* add rx/tx isr to vector table */
374    ictrl_set_vector(spiRxInterruptHandler,
375                     PPC_IRQ_EXT_SPIR,
376                     &previous_isr);
377
378    ictrl_set_vector(spiTxInterruptHandler,
379                     PPC_IRQ_EXT_SPIT,
380                     &previous_isr);
381
382    port->SPRC = (RCREnable | RCRIntEnabled | RCRErrorInt);
383    port->SPTC = (TCREnable | TCRIntDisable); /* don't enable TxInt yet */
384  }
385  else {
386    /* enable receiver/transmitter, no interrupts */
387    port->SPRC = (RCREnable | RCRIntDisable);
388    port->SPTC = (TCREnable | TCRIntDisable);
389  }
390
391  atexit(spiDeInit);
392
393  return RTEMS_SUCCESSFUL;
394}
395
396/*
397 ***************
398 * BOILERPLATE *
399 ***************
400 */
401
402/*  console_initialize
403 *
404 *  This routine initializes the console IO driver.
405 *
406 *  Input parameters: NONE
407 *
408 *  Output parameters:  NONE
409 *
410 *  Return values:
411 */
412
413rtems_device_driver console_initialize(
414  rtems_device_major_number  major,
415  rtems_device_minor_number  minor,
416  void                      *arg
417)
418{
419  rtems_status_code status;
420
421  /*
422   * Set up TERMIOS
423   */
424  rtems_termios_initialize ();
425
426  /*
427   * Do device-specific initialization
428   */
429  spiInitialize ();
430
431  /*
432   * Register the device
433   */
434  status = rtems_io_register_name ("/dev/console", major, 0);
435  if (status != RTEMS_SUCCESSFUL)
436    rtems_fatal_error_occurred (status);
437  return RTEMS_SUCCESSFUL;
438}
439
440
441/*
442 *  Open entry point
443 */
444 
445rtems_device_driver console_open(
446  rtems_device_major_number major,
447  rtems_device_minor_number minor,
448  void                    * arg
449)
450{
451  rtems_status_code sc;
452  static const rtems_termios_callbacks intrCallbacks = {
453    NULL,               /* firstOpen */
454    NULL,               /* lastClose */
455    NULL,               /* pollRead */
456    spiInterruptWrite,  /* write */
457    spiSetAttributes,   /* setAttributes */
458    spiStopRemoteTx,    /* stopRemoteTx */
459    spiStartRemoteTx,   /* startRemoteTx */
460    1                   /* outputUsesInterrupts */
461  };
462
463  static const rtems_termios_callbacks pollCallbacks = {
464    NULL,               /* firstOpen */
465    NULL,               /* lastClose */
466    spiPollRead,        /* pollRead */
467    spiPollWrite,       /* write */
468    spiSetAttributes,   /* setAttributes */
469    spiStopRemoteTx,    /* stopRemoteTx */
470    spiStartRemoteTx,   /* startRemoteTx */
471    0                   /* outputUsesInterrupts */
472  };
473
474  if (ppc403_spi_interrupt) {
475    rtems_libio_open_close_args_t *args = arg;
476   
477    sc = rtems_termios_open (major, minor, arg, &intrCallbacks);
478    spittyp = args->iop->data1;
479  }
480  else {
481    sc = rtems_termios_open (major, minor, arg, &pollCallbacks);
482  }
483  return sc;
484}
485 
486/*
487 *  Close entry point
488 */
489 
490rtems_device_driver console_close(
491  rtems_device_major_number major,
492  rtems_device_minor_number minor,
493  void                    * arg
494)
495{
496  return rtems_termios_close (arg);
497}
498 
499/*
500 * read bytes from the serial port. We only have stdin.
501 */
502 
503rtems_device_driver console_read(
504  rtems_device_major_number major,
505  rtems_device_minor_number minor,
506  void                    * arg
507)
508{
509  return rtems_termios_read (arg);
510}
511 
512/*
513 * write bytes to the serial port. Stdout and stderr are the same.
514 */
515 
516rtems_device_driver console_write(
517  rtems_device_major_number major,
518  rtems_device_minor_number minor,
519  void                    * arg
520)
521{
522  return rtems_termios_write (arg);
523}
524 
525/*
526 *  IO Control entry point
527 */
528 
529rtems_device_driver console_control(
530  rtems_device_major_number major,
531  rtems_device_minor_number minor,
532  void                    * arg
533)
534{
535  return rtems_termios_ioctl (arg);
536}
Note: See TracBrowser for help on using the repository browser.