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

4.104.114.84.95
Last change on this file since 5e77d129 was df49c60, checked in by Joel Sherrill <joel.sherrill@…>, on Jun 12, 2000 at 3:00:15 PM

Merged from 4.5.0-beta3a

  • Property mode set to 100644
File size: 14.1 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() */
63
64struct async {
65/*---------------------------------------------------------------------------+
66| Line Status Register.
67+---------------------------------------------------------------------------*/
68  unsigned char SPLS;
69  unsigned char SPLSset;
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
78/*---------------------------------------------------------------------------+
79| Handshake Status Register.
80+---------------------------------------------------------------------------*/
81  unsigned char SPHS;
82  unsigned char SPHSset;
83#define HSRDsr                   0x80
84#define HSRCts                   0x40
85
86/*---------------------------------------------------------------------------+
87| Baud rate divisor registers
88+---------------------------------------------------------------------------*/
89  unsigned char BRDH;
90  unsigned char BRDL;
91
92/*---------------------------------------------------------------------------+
93| Control Register.
94+---------------------------------------------------------------------------*/
95  unsigned char SPCTL;
96#define CRNormal                 0x00
97#define CRLoopback               0x40
98#define CRAutoEcho               0x80
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
106#define CROddParity              0x02
107#define CRStopBitsOne            0x00
108#define CRStopBitsTwo            0x01
109#define CRDisableDtrRts          0x00
110
111/*--------------------------------------------------------------------------+
112| Receiver Command Register.
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/*--------------------------------------------------------------------------+
125| Transmitter Command Register.
126+--------------------------------------------------------------------------*/
127    unsigned char SPTC;
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/*--------------------------------------------------------------------------+
140| Miscellanies defines.
141+--------------------------------------------------------------------------*/
142  unsigned char SPTB;
143#define SPRB    SPTB
144};
145
146typedef volatile struct async *pasync;
147static const pasync port = (pasync)0x40000000;
148
149static void *spittyp;         /* handle for termios */
150int ppc403_spi_interrupt = 1; /* do not use interrupts... */
151
152/*
153 * Rx Interrupt handler
154 */
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}
171
172/*
173 * Tx Interrupt handler
174 */
175static rtems_isr
176spiTxInterruptHandler (rtems_vector_number v)
177{
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}
187
188/*
189 * enable/disable RTS line to start/stop remote transmitter
190 */
191static int
192spiStartRemoteTx (int minor)
193{
194  rtems_interrupt_level level;
195
196  rtems_interrupt_disable (level);
197  port->SPCTL |= CRRts;           /* activate RTS  */
198  rtems_interrupt_enable (level);
199  return 0;
200}
201
202static int
203spiStopRemoteTx (int minor)
204{
205  rtems_interrupt_level level;
206
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;
217  tmp = rtems_cpu_configuration_get_serial_per_sec() / baudrate;
218  tmp = ((tmp) >> 4) - 1;
219  port->BRDL = tmp & 0xff;
220  port->BRDH = tmp >> 8;
221
222}
223/*
224 * Hardware-dependent portion of tcsetattr().
225 */
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}
260
261static int
262spiPollRead (int minor)
263{
264  unsigned char status;
265
266  while (0 == ((status = port->SPLS) & LSRDataReady)) {
267    /* Clean any dodgy status */
268    if ((status & (LSRFramingError | LSROverrunError | LSRParityError |
269                   LSRBreakInterrupt)) != 0) {
270      port->SPLS = (LSRFramingError | LSROverrunError | LSRParityError |
271                    LSRBreakInterrupt);
272    }
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;
289
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;
300}
301
302/*
303 *
304 * deinit SPI
305 *
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 */
316  spiBaudSet(rtems_cpu_configuration_get_serial_rate());
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/*
337 *
338 * init SPI
339 *
340 */
341rtems_status_code
342spiInitialize(void) 
343{
344  register unsigned tmp;
345  rtems_isr_entry previous_isr; /* this is a dummy */
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 |= (rtems_cpu_configuration_get_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(rtems_cpu_configuration_get_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}
542
Note: See TracBrowser for help on using the repository browser.