source: rtems/c/src/lib/libcpu/powerpc/mpc8260/console-generic/console-generic.c @ 1c6926c1

5
Last change on this file since 1c6926c1 was 1c6926c1, checked in by Kevin Kirspel <kevin-kirspel@…>, on 03/21/17 at 19:39:48

termios: Synchronize with latest FreeBSD headers

Adding modified FreeBSD headers to synchronize RTEMS termios with
FreeBSD. Modify termios to support dedicated input and output baud for
termios structure. Updated BSPs to use dedicated input and output baud
in termios structure. Updated tools to use dedicated input and output
baud in termios structure. Updated termios testsuites to use dedicated
input and output baud in termios structure.

Close #2897.

  • Property mode set to 100644
File size: 30.7 KB
Line 
1/*
2 *  General Serial I/O functions.
3 *
4 *  This file contains the functions for performing serial I/O.
5 *  The actual system calls (console_*) should be in the BSP part
6 *  of the source tree. That way different BSPs can use whichever
7 *  SMCs and SCCs they want. Originally, all the stuff was in
8 *  this file, and it caused problems with one BSP using SCC2
9 *  as /dev/console, others using SMC1 for /dev/console, etc.
10 *
11 *  On-chip resources used:
12 *   resource   minor                note
13 *    SMC1       0
14 *    SMC2       1
15 *    SCC1       2
16 *    SCC2       3
17 *    SCC3       4
18 *    SCC4       5
19 *    BRG1
20 *    BRG2
21 *    BRG3
22 *    BRG4
23 */
24
25/*
26 *  Author: Jay Monkman (jmonkman@frasca.com)
27 *  Copyright (C) 1998 by Frasca International, Inc.
28 *
29 *  Derived from c/src/lib/libbsp/m68k/gen360/console/console.c written by:
30 *    W. Eric Norum
31 *    Saskatchewan Accelerator Laboratory
32 *    University of Saskatchewan
33 *    Saskatoon, Saskatchewan, CANADA
34 *    eric@skatter.usask.ca
35 *
36 *  COPYRIGHT (c) 1989-1998.
37 *  On-Line Applications Research Corporation (OAR).
38 *
39 *  Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca>
40 *  and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>
41 *  Copyright (c) 1999, National Research Council of Canada
42 *
43 *  Copyright (c) 2001, Surrey Satellite Technology Ltd
44 *    SCC1 and SSC2 are used on MPC8260ADS board
45 *    SMCs are unused
46 *
47 *  The license and distribution terms for this file may be
48 *  found in the file LICENSE in this distribution or at
49 *  http://www.rtems.org/license/LICENSE.
50 */
51
52#include <bsp.h>
53#include <rtems/libio.h>
54#include <mpc8260.h>
55#include <mpc8260/console.h>
56#include <mpc8260/cpm.h>
57#include <stdlib.h>
58#include <unistd.h>
59#include <termios.h>
60#include <bsp/irq.h>
61#include <rtems/bspIo.h>   /* for printk */
62
63/*
64 * Interrupt-driven input buffer
65 */
66#define RXBUFSIZE       16
67
68/*
69 *  I/O buffers and pointers to buffer descriptors.
70 *  Currently, single buffered input is done. This will work only
71 *  if the Rx interrupts are serviced quickly.
72 *
73 *  TODO: Add a least double buffering for safety.
74 */
75static volatile char rxBuf[NUM_PORTS][RXBUFSIZE];
76static volatile char txBuf[NUM_PORTS];
77
78/* SCC/SMC buffer descriptors */
79static volatile m8260BufferDescriptor_t *RxBd[NUM_PORTS], *TxBd[NUM_PORTS];
80
81/* Used to track termios private data for callbacks */
82struct rtems_termios_tty *ttyp[NUM_PORTS];
83
84#if 0
85/* Used to record previous ISR */
86static rtems_isr_entry old_handler[NUM_PORTS];
87#endif
88
89/*
90 * Device-specific routines
91 */
92static int m8xx_smc_set_attributes(int, const struct termios*);
93static int m8xx_scc_set_attributes(int, const struct termios*);
94static rtems_isr m8xx_smc1_interrupt_handler(rtems_irq_hdl_param unused);
95static rtems_isr m8xx_smc2_interrupt_handler(rtems_irq_hdl_param unused);
96static rtems_isr m8xx_scc1_interrupt_handler(rtems_irq_hdl_param unused);
97static rtems_isr m8xx_scc2_interrupt_handler(rtems_irq_hdl_param unused);
98static rtems_isr m8xx_scc3_interrupt_handler(rtems_irq_hdl_param unused);
99static rtems_isr m8xx_scc4_interrupt_handler(rtems_irq_hdl_param unused);
100
101/*
102 * Hardware-dependent portion of tcsetattr().
103 */
104static int
105m8xx_smc_set_attributes (int minor, const struct termios *t)
106{
107  int baud, brg=0, csize=0, ssize, psize;
108  uint16_t   clen=0, cstopb, parenb, parodd, cread;
109
110  /* Baud rate */
111  switch (t->c_ospeed) {
112  default:      baud = -1;      break;
113  case B50:     baud = 50;      break;
114  case B75:     baud = 75;      break;
115  case B110:    baud = 110;     break;
116  case B134:    baud = 134;     break;
117  case B150:    baud = 150;     break;
118  case B200:    baud = 200;     break;
119  case B300:    baud = 300;     break;
120  case B600:    baud = 600;     break;
121  case B1200:   baud = 1200;    break;
122  case B1800:   baud = 1800;    break;
123  case B2400:   baud = 2400;    break;
124  case B4800:   baud = 4800;    break;
125  case B9600:   baud = 9600;    break;
126  case B19200:  baud = 19200;   break;
127  case B38400:  baud = 38400;   break;
128  case B57600:  baud = 57600;   break;
129  case B115200: baud = 115200;  break;
130  case B230400: baud = 230400;  break;
131  case B460800: baud = 460800;  break;
132  }
133  if (baud > 0) {
134   switch( minor ) {
135      case SMC1_MINOR:
136        /* SMC1 can only choose between BRG1 and 7 */
137        brg = m8xx_get_brg( M8260_SMC1_BRGS, baud*16 ) + 1;
138        m8260.cmxsmr &= ~0x30;
139        m8260.cmxsmr |= (brg==1? 0x00: 0x10 );
140        break;
141      case SMC2_MINOR:
142        /* SMC2 can only choose between BRG2 and 8 */
143        brg = m8xx_get_brg(  M8260_SMC2_BRGS, baud*16 ) + 1;
144        m8260.cmxsmr &= ~0x30;
145        m8260.cmxsmr |= (brg==2? 0x00: 0x01 );
146        break;
147    }
148  }
149
150  /* Number of data bits */
151  switch ( t->c_cflag & CSIZE ) {
152    case CS5:     csize = 5;       break;
153    case CS6:     csize = 6;       break;
154    case CS7:     csize = 7;       break;
155    case CS8:     csize = 8;       break;
156  }
157
158  /* Stop bits */
159  if ( t->c_cflag & CSTOPB ) {
160    cstopb = 0x0400;              /* Two stop bits */
161    ssize  = 2;
162  } else {
163    cstopb = 0x0000;              /* One stop bit */
164    ssize  = 1;
165  }
166
167  /* Parity */
168  if ( t->c_cflag & PARENB ) {
169    parenb = 0x0200;              /* Parity enabled on Tx and Rx */
170    psize  = 1;
171  } else {
172    parenb = 0x0000;              /* No parity on Tx and Rx */
173    psize  = 0;
174  }
175
176  if ( t->c_cflag & PARODD )
177    parodd = 0x0000;              /* Odd parity */
178  else
179    parodd = 0x0100;
180
181  /*
182   * Character Length = start + data + parity + stop - 1
183   */
184  switch ( 1 + csize + psize + ssize - 1 ) {
185    case 6:     clen = 0x3000;       break;
186    case 7:     clen = 0x3800;       break;
187    case 8:     clen = 0x4000;       break;
188    case 9:     clen = 0x4800;       break;
189    case 10:    clen = 0x5000;       break;
190    case 11:    clen = 0x5800;       break;
191  }
192
193  if ( t->c_cflag & CREAD )
194    cread = 0x0023;             /* UART normal operation, enable Rx and Tx */
195  else
196    cread = 0x0021;             /* UART normal operation, enable Tx */
197
198  /* Write the SIMODE/SMCMR registers */
199  switch (minor) {
200    case SMC1_MINOR:
201/*
202      m8xx.simode = ( (m8xx.simode & 0xffff8fff) | (brg << 12) );
203*/
204      m8260.smc1.smcmr = clen | cstopb | parenb | parodd | cread;
205      break;
206    case SMC2_MINOR:
207      /* CHECK THIS */
208/*
209      m8xx.simode = ( (m8xx.simode & 0x8fffffff) | (brg << 28) );
210*/
211      m8260.smc2.smcmr = clen | cstopb | parenb | parodd | cread;
212      break;
213  }
214  return 0;
215}
216
217static int
218m8xx_scc_set_attributes (int minor, const struct termios *t)
219{
220  int baud, brg=0;
221  uint16_t   csize=0, cstopb, parenb, parodd;
222
223  /* Baud rate */
224  switch (t->c_ospeed) {
225  default:      baud = -1;      break;
226  case B50:     baud = 50;      break;
227  case B75:     baud = 75;      break;
228  case B110:    baud = 110;     break;
229  case B134:    baud = 134;     break;
230  case B150:    baud = 150;     break;
231  case B200:    baud = 200;     break;
232  case B300:    baud = 300;     break;
233  case B600:    baud = 600;     break;
234  case B1200:   baud = 1200;    break;
235  case B1800:   baud = 1800;    break;
236  case B2400:   baud = 2400;    break;
237  case B4800:   baud = 4800;    break;
238  case B9600:   baud = 9600;    break;
239  case B19200:  baud = 19200;   break;
240  case B38400:  baud = 38400;   break;
241  case B57600:  baud = 57600;   break;
242  case B115200: baud = 115200;  break;
243  case B230400: baud = 230400;  break;
244  case B460800: baud = 460800;  break;
245  }
246  if (baud > 0) {
247    brg = m8xx_get_brg( M8260_SCC_BRGS, baud*16 );
248    m8260.cmxscr &= ~(0xFF000000 >> (8*(minor-SCC1_MINOR)) );
249    m8260.cmxscr |= ((brg<<(3+8*(3-(minor-SCC1_MINOR)))) &
250                     (brg<<(8*(3-(minor-SCC1_MINOR)))));
251  }
252  /* Number of data bits */
253  switch ( t->c_cflag & CSIZE ) {
254    case CS5:     csize = 0x0000;       break;
255    case CS6:     csize = 0x1000;       break;
256    case CS7:     csize = 0x2000;       break;
257    case CS8:     csize = 0x3000;       break;
258  }
259
260  /* Stop bits */
261  if ( t->c_cflag & CSTOPB )
262    cstopb = 0x4000;              /* Two stop bits */
263  else
264    cstopb = 0x0000;              /* One stop bit */
265
266  /* Parity */
267  if ( t->c_cflag & PARENB )
268    parenb = 0x0010;              /* Parity enabled on Tx and Rx */
269  else
270    parenb = 0x0000;              /* No parity on Tx and Rx */
271
272  if ( t->c_cflag & PARODD )
273    parodd = 0x0000;              /* Odd parity */
274  else
275    parodd = 0x000a;
276
277  /* Write the SICR/PSMR Registers */
278  switch (minor) {
279    case SCC1_MINOR:
280/*
281      m8xx.sicr = ( (m8xx.sicr & 0xffffc0ff) | (brg << 11) | (brg << 8) );
282*/
283      m8260.scc1.psmr = ( (cstopb | csize | parenb | parodd) | (m8260.scc1.psmr & 0x8fe0) );
284      break;
285    case SCC2_MINOR:
286/*
287      m8xx.sicr = ( (m8xx.sicr & 0xffffc0ff) | (brg << 11) | (brg << 8) );
288*/
289      m8260.scc2.psmr = ( (cstopb | csize | parenb | parodd) | (m8260.scc2.psmr & 0x8fe0) );
290      break;
291    case SCC3_MINOR:
292/*
293      m8xx.sicr = ( (m8xx.sicr & 0xffc0ffff) | (brg << 19) | (brg << 16) );
294*/
295      m8260.scc3.psmr = ( (cstopb | csize | parenb | parodd) | (m8260.scc3.psmr & 0x8fe0) );
296      break;
297    case SCC4_MINOR:
298/*
299      m8xx.sicr = ( (m8xx.sicr & 0xc0ffffff) | (brg << 27) | (brg << 24) );
300*/
301      m8260.scc4.psmr = ( (cstopb | csize | parenb | parodd) | (m8260.scc4.psmr & 0x8fe0) );
302      break;
303  }
304
305  return 0;
306}
307
308int
309m8xx_uart_setAttributes(
310  int minor,
311  const struct termios *t
312)
313{
314  /*
315   * Check that port number is valid
316   */
317  if ( (minor < SMC1_MINOR) || (minor > NUM_PORTS-1) )
318    return 0;
319
320  switch (minor) {
321    case SMC1_MINOR:
322    case SMC2_MINOR:
323      return m8xx_smc_set_attributes( minor, t );
324
325    case SCC1_MINOR:
326    case SCC2_MINOR:
327    case SCC3_MINOR:
328    case SCC4_MINOR:
329      return m8xx_scc_set_attributes( minor, t );
330  }
331  return 0;
332}
333
334/*
335 * Interrupt handlers
336 */
337static void
338m8xx_scc1_interrupt_handler (rtems_irq_hdl_param unused)
339{
340  /*
341   * Buffer received?
342   */
343  if ((m8260.scc1.sccm & M8260_SCCE_RX) && (m8260.scc1.scce & M8260_SCCE_RX)) {
344    m8260.scc1.scce = M8260_SCCE_RX;    /* Clear the event */
345
346
347    /* Check that the buffer is ours */
348    if ((RxBd[SCC1_MINOR]->status & M8260_BD_EMPTY) == 0) {
349      rtems_cache_invalidate_multiple_data_lines(
350        (const void *) RxBd[SCC1_MINOR]->buffer,
351        RxBd[SCC1_MINOR]->length );
352      rtems_termios_enqueue_raw_characters(
353        (void *)ttyp[SCC1_MINOR],
354        (char *)RxBd[SCC1_MINOR]->buffer,
355        (int)RxBd[SCC1_MINOR]->length );
356      RxBd[SCC1_MINOR]->status = M8260_BD_EMPTY | M8260_BD_WRAP |
357                                 M8260_BD_INTERRUPT;
358    }
359  }
360
361  /*
362   * Buffer transmitted?
363   */
364  if (m8260.scc1.scce & M8260_SCCE_TX) {
365    m8260.scc1.scce = M8260_SCCE_TX;  /* Clear the event */
366
367    /* Check that the buffer is ours */
368    if ((TxBd[SCC1_MINOR]->status & M8260_BD_READY) == 0)
369      rtems_termios_dequeue_characters (
370        (void *)ttyp[SCC1_MINOR],
371        (int)TxBd[SCC1_MINOR]->length);
372  }
373
374#if 0
375  m8260.sipnr_l |= M8260_SIMASK_SCC1;      /* Clear pending register */
376#endif
377}
378
379static void
380m8xx_scc2_interrupt_handler (rtems_irq_hdl_param unused)
381{
382  /*
383   * Buffer received?
384   */
385  if ((m8260.scc2.sccm & M8260_SCCE_RX) && (m8260.scc2.scce & M8260_SCCE_RX)) {
386    m8260.scc2.scce = M8260_SCCE_RX;    /* Clear the event */
387
388
389    /* Check that the buffer is ours */
390    if ((RxBd[SCC2_MINOR]->status & M8260_BD_EMPTY) == 0) {
391      rtems_cache_invalidate_multiple_data_lines(
392        (const void *) RxBd[SCC2_MINOR]->buffer,
393        RxBd[SCC2_MINOR]->length );
394      rtems_termios_enqueue_raw_characters(
395        (void *)ttyp[SCC2_MINOR],
396        (char *)RxBd[SCC2_MINOR]->buffer,
397        (int)RxBd[SCC2_MINOR]->length );
398      RxBd[SCC2_MINOR]->status = M8260_BD_EMPTY | M8260_BD_WRAP |
399                                 M8260_BD_INTERRUPT;
400    }
401  }
402
403  /*
404   * Buffer transmitted?
405   */
406  if (m8260.scc2.scce & M8260_SCCE_TX) {
407    m8260.scc2.scce = M8260_SCCE_TX;  /* Clear the event */
408
409    /* Check that the buffer is ours */
410    if ((TxBd[SCC2_MINOR]->status & M8260_BD_READY) == 0)
411      rtems_termios_dequeue_characters (
412        (void *)ttyp[SCC2_MINOR],
413        (int)TxBd[SCC2_MINOR]->length);
414  }
415
416#if 0
417  m8260.sipnr_l |= M8260_SIMASK_SCC2;      /* Clear pending register */
418#endif
419}
420
421static void
422m8xx_scc3_interrupt_handler (rtems_irq_hdl_param unused)
423{
424  /*
425   * Buffer received?
426   */
427  if ((m8260.scc3.sccm & M8260_SCCE_RX) && (m8260.scc3.scce & M8260_SCCE_RX)) {
428    m8260.scc3.scce = M8260_SCCE_RX;  /* Clear the event */
429
430
431    /* Check that the buffer is ours */
432    if ((RxBd[SCC3_MINOR]->status & M8260_BD_EMPTY) == 0) {
433      rtems_cache_invalidate_multiple_data_lines(
434        (const void *) RxBd[SCC3_MINOR]->buffer,
435        RxBd[SCC3_MINOR]->length );
436      rtems_termios_enqueue_raw_characters(
437        (void *)ttyp[SCC3_MINOR],
438        (char *)RxBd[SCC3_MINOR]->buffer,
439        (int)RxBd[SCC3_MINOR]->length );
440      RxBd[SCC3_MINOR]->status = M8260_BD_EMPTY | M8260_BD_WRAP |
441                                 M8260_BD_INTERRUPT;
442    }
443  }
444
445  /*
446   * Buffer transmitted?
447   */
448  if (m8260.scc3.scce & M8260_SCCE_TX) {
449    m8260.scc3.scce = M8260_SCCE_TX;    /* Clear the event */
450
451    /* Check that the buffer is ours */
452    if ((TxBd[SCC3_MINOR]->status & M8260_BD_READY) == 0)
453      rtems_termios_dequeue_characters (
454        (void *)ttyp[SCC3_MINOR],
455        (int)TxBd[SCC3_MINOR]->length);
456  }
457
458
459#if 0
460  m8260.sipnr_l |= M8260_SIMASK_SCC3;      /* Clear pending register */
461#endif
462}
463
464static void
465m8xx_scc4_interrupt_handler (rtems_irq_hdl_param unused)
466{
467  /*
468   * Buffer received?
469   */
470  if ((m8260.scc4.sccm & M8260_SCCE_RX) && (m8260.scc4.scce & M8260_SCCE_RX)) {
471    m8260.scc4.scce = M8260_SCCE_RX;  /* Clear the event */
472
473
474    /* Check that the buffer is ours */
475    if ((RxBd[SCC4_MINOR]->status & M8260_BD_EMPTY) == 0) {
476      rtems_cache_invalidate_multiple_data_lines(
477        (const void *) RxBd[SCC4_MINOR]->buffer,
478        RxBd[SCC4_MINOR]->length );
479      rtems_termios_enqueue_raw_characters(
480        (void *)ttyp[SCC4_MINOR],
481        (char *)RxBd[SCC4_MINOR]->buffer,
482        (int)RxBd[SCC4_MINOR]->length );
483      RxBd[SCC4_MINOR]->status = M8260_BD_EMPTY | M8260_BD_WRAP |
484                                 M8260_BD_INTERRUPT;
485    }
486  }
487
488  /*
489   * Buffer transmitted?
490   */
491  if (m8260.scc4.scce & M8260_SCCE_TX) {
492    m8260.scc4.scce = M8260_SCCE_TX;    /* Clear the event */
493
494    /* Check that the buffer is ours */
495    if ((TxBd[SCC4_MINOR]->status & M8260_BD_READY) == 0)
496      rtems_termios_dequeue_characters (
497        (void *)ttyp[SCC4_MINOR],
498        (int)TxBd[SCC4_MINOR]->length);
499  }
500
501#if 0
502  m8260.sipnr_l |= M8260_SIMASK_SCC4;      /* Clear pending register */
503#endif
504}
505
506static void
507m8xx_smc1_interrupt_handler (rtems_irq_hdl_param unused)
508{
509  /*
510   * Buffer received?
511   */
512  if (m8260.smc1.smce & M8260_SMCE_RX) {
513    m8260.smc1.smce = M8260_SMCE_RX;  /* Clear the event */
514
515
516    /* Check that the buffer is ours */
517    if ((RxBd[SMC1_MINOR]->status & M8260_BD_EMPTY) == 0) {
518      rtems_cache_invalidate_multiple_data_lines(
519        (const void *) RxBd[SMC1_MINOR]->buffer,
520        RxBd[SMC1_MINOR]->length );
521      rtems_termios_enqueue_raw_characters(
522        (void *)ttyp[SMC1_MINOR],
523        (char *)RxBd[SMC1_MINOR]->buffer,
524        (int)RxBd[SMC1_MINOR]->length );
525      RxBd[SMC1_MINOR]->status = M8260_BD_EMPTY | M8260_BD_WRAP |
526                                 M8260_BD_INTERRUPT;
527    }
528  }
529
530  /*
531   * Buffer transmitted?
532   */
533  if (m8260.smc1.smce & M8260_SMCE_TX) {
534    m8260.smc1.smce = M8260_SMCE_TX;    /* Clear the event */
535
536    /* Check that the buffer is ours */
537    if ((TxBd[SMC1_MINOR]->status & M8260_BD_READY) == 0)
538      rtems_termios_dequeue_characters (
539        (void *)ttyp[SMC1_MINOR],
540        (int)TxBd[SMC1_MINOR]->length);
541  }
542
543#if 0
544  m8260.sipnr_l = 0x00001000; /* Clear SMC1 interrupt-in-service bit */
545#endif
546}
547
548static void
549m8xx_smc2_interrupt_handler (rtems_irq_hdl_param unused)
550{
551  /*
552   * Buffer received?
553   */
554  if (m8260.smc2.smce & M8260_SMCE_RX) {
555    m8260.smc2.smce = M8260_SMCE_RX;  /* Clear the event */
556
557
558    /* Check that the buffer is ours */
559    if ((RxBd[SMC2_MINOR]->status & M8260_BD_EMPTY) == 0) {
560      rtems_cache_invalidate_multiple_data_lines(
561        (const void *) RxBd[SMC2_MINOR]->buffer,
562        RxBd[SMC2_MINOR]->length );
563      rtems_termios_enqueue_raw_characters(
564        (void *)ttyp[SMC2_MINOR],
565        (char *)RxBd[SMC2_MINOR]->buffer,
566        (int)RxBd[SMC2_MINOR]->length );
567      RxBd[SMC2_MINOR]->status = M8260_BD_EMPTY | M8260_BD_WRAP |
568                                 M8260_BD_INTERRUPT;
569    }
570  }
571
572  /*
573   * Buffer transmitted?
574   */
575  if (m8260.smc2.smce & M8260_SMCE_TX) {
576    m8260.smc2.smce = M8260_SMCE_TX;    /* Clear the event */
577
578    /* Check that the buffer is ours */
579    if ((TxBd[SMC2_MINOR]->status & M8260_BD_READY) == 0)
580      rtems_termios_dequeue_characters (
581        (void *)ttyp[SMC2_MINOR],
582        (int)TxBd[SMC2_MINOR]->length);
583  }
584
585#if 0
586  m8260.sipnr_l = 0x00000800; /* Clear SMC2 interrupt-in-service bit */
587#endif
588}
589
590static void m8xx_scc_enable(const rtems_irq_connect_data* ptr)
591{
592  volatile m8260SCCRegisters_t *sccregs = 0;
593  switch (ptr->name) {
594  case BSP_CPM_IRQ_SCC4 :
595    m8260.sipnr_l |= M8260_SIMASK_SCC4;
596    sccregs = &m8260.scc4;
597    break;
598  case BSP_CPM_IRQ_SCC3 :
599    m8260.sipnr_l |= M8260_SIMASK_SCC3;
600    sccregs = &m8260.scc3;
601    break;
602  case BSP_CPM_IRQ_SCC2 :
603    m8260.sipnr_l |= M8260_SIMASK_SCC2;
604    sccregs = &m8260.scc2;
605    break;
606  case BSP_CPM_IRQ_SCC1 :
607    m8260.sipnr_l |= M8260_SIMASK_SCC1;
608    sccregs = &m8260.scc1;
609    break;
610  default:
611    break;
612  }
613  sccregs->sccm = 3;
614}
615
616static void m8xx_scc_disable(const rtems_irq_connect_data* ptr)
617{
618  volatile m8260SCCRegisters_t *sccregs = 0;
619  switch (ptr->name) {
620  case BSP_CPM_IRQ_SCC4 :
621    sccregs = &m8260.scc4;
622    break;
623  case BSP_CPM_IRQ_SCC3 :
624    sccregs = &m8260.scc3;
625    break;
626  case BSP_CPM_IRQ_SCC2 :
627    sccregs = &m8260.scc2;
628    break;
629  case BSP_CPM_IRQ_SCC1 :
630    sccregs = &m8260.scc1;
631    break;
632  default:
633    break;
634  }
635  sccregs->sccm &= (~3);
636}
637
638static int m8xx_scc_isOn(const rtems_irq_connect_data* ptr)
639{
640 return BSP_irq_enabled_at_cpm (ptr->name);
641}
642
643static rtems_irq_connect_data consoleIrqData =
644{
645  BSP_CPM_IRQ_SCC1,
646  (rtems_irq_hdl)m8xx_scc1_interrupt_handler,
647  NULL,
648  (rtems_irq_enable) m8xx_scc_enable,
649  (rtems_irq_disable) m8xx_scc_disable,
650  (rtems_irq_is_enabled) m8xx_scc_isOn
651};
652
653void
654m8xx_uart_scc_initialize (int minor)
655{
656  unsigned char brg;
657  volatile m8260SCCparms_t *sccparms = 0;
658  volatile m8260SCCRegisters_t *sccregs = 0;
659
660  /*
661   * Check that minor number is valid
662   */
663  if ( (minor < SCC1_MINOR) || (minor > NUM_PORTS-1) )
664    return;
665
666  /* Get the sicr clock source bit values for 9600 bps */
667  brg = m8xx_get_brg(M8260_SCC_BRGS, 9600*16);
668
669  m8260.cmxscr &= ~(0xFF000000 >> (8*(minor-SCC1_MINOR)) );
670  m8260.cmxscr |= (brg<<(3+8*(3-(minor-SCC1_MINOR))));
671  m8260.cmxscr |= (brg<<(8*(3-(minor-SCC1_MINOR))));
672
673  /*
674   * Allocate buffer descriptors
675   */
676  RxBd[minor] = m8xx_bd_allocate(1);
677  TxBd[minor] = m8xx_bd_allocate(1);
678
679  /*
680   * Configure ports to enable TXDx and RXDx pins
681   */
682
683  m8260.ppard |=  (0x07 << ((minor-SCC1_MINOR)*3));
684  m8260.psord &= ~(0x07 << ((minor-SCC1_MINOR)*3));
685  if( minor == SCC1_MINOR )
686    m8260.psord |= 0x02;
687  m8260.pdird |=  (0x06 << ((minor-SCC1_MINOR)*3));
688  m8260.pdird &= ~(0x01 << ((minor-SCC1_MINOR)*3));
689
690
691  /*
692   * Set up SMC1 parameter RAM common to all protocols
693   */
694  if( minor == SCC1_MINOR ) {
695    sccparms = (m8260SCCparms_t*)&m8260.scc1p;
696    sccregs  = (m8260SCCRegisters_t*)&m8260.scc1;
697  }
698  else if( minor == SCC2_MINOR ) {
699    sccparms = (m8260SCCparms_t*)&m8260.scc2p;
700    sccregs  = (m8260SCCRegisters_t*)&m8260.scc2;
701  }
702  else if( minor == SCC3_MINOR ) {
703    sccparms = (m8260SCCparms_t*)&m8260.scc3p;
704    sccregs  = (m8260SCCRegisters_t*)&m8260.scc3;
705  }
706  else {
707    sccparms = (m8260SCCparms_t*)&m8260.scc4p;
708    sccregs  = (m8260SCCRegisters_t*)&m8260.scc4;
709  }
710
711  sccparms->rbase = (char *)RxBd[minor] - (char *)&m8260;
712  sccparms->tbase = (char *)TxBd[minor] - (char *)&m8260;
713
714  sccparms->rfcr = M8260_RFCR_MOT | M8260_RFCR_60X_BUS;
715  sccparms->tfcr = M8260_TFCR_MOT | M8260_TFCR_60X_BUS;
716  if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 )
717    sccparms->mrblr = RXBUFSIZE;    /* Maximum Rx buffer size */
718  else
719    sccparms->mrblr = 1;            /* Maximum Rx buffer size */
720  sccparms->un.uart.max_idl = 10;   /* Set nb of idle chars to close buffer */
721  sccparms->un.uart.brkcr = 0;      /* Set nb of breaks to send for STOP Tx */
722
723  sccparms->un.uart.parec = 0;      /* Clear parity error counter */
724  sccparms->un.uart.frmec = 0;      /* Clear framing error counter */
725  sccparms->un.uart.nosec = 0;      /* Clear noise counter */
726  sccparms->un.uart.brkec = 0;      /* Clear break counter */
727
728  sccparms->un.uart.uaddr[0] = 0;   /* Not in multidrop mode, so clear */
729  sccparms->un.uart.uaddr[1] = 0;   /* Not in multidrop mode, so clear */
730  sccparms->un.uart.toseq  = 0;     /* Tx Out-Of-SEQuence--no XON/XOFF now */
731
732  sccparms->un.uart.character[0] = 0x8000; /* Entry is invalid */
733  sccparms->un.uart.character[1] = 0x8000; /* Entry is invalid */
734  sccparms->un.uart.character[2] = 0x8000; /* Entry is invalid */
735  sccparms->un.uart.character[3] = 0x8000; /* Entry is invalid */
736  sccparms->un.uart.character[4] = 0x8000; /* Entry is invalid */
737  sccparms->un.uart.character[5] = 0x8000; /* Entry is invalid */
738  sccparms->un.uart.character[6] = 0x8000; /* Entry is invalid */
739  sccparms->un.uart.character[7] = 0x8000; /* Entry is invalid */
740
741  sccparms->un.uart.rccm = 0xc0ff;  /* No masking */
742
743  /*
744   * Set up the Receive Buffer Descriptor
745   */
746  RxBd[minor]->status = M8260_BD_EMPTY | M8260_BD_WRAP | M8260_BD_INTERRUPT;
747  RxBd[minor]->length = 0;
748  RxBd[minor]->buffer = rxBuf[minor];
749
750  /*
751   * Setup the Transmit Buffer Descriptor
752   */
753  TxBd[minor]->status = M8260_BD_WRAP;
754
755 /*
756   * Set up SCCx general and protocol-specific mode registers
757   */
758  sccregs->gsmr_h = 0x00000020;     /* RFW=low latency operation */
759  sccregs->gsmr_l = 0x00028004;     /* TDCR=RDCR=16x clock mode, MODE=uart*/
760  sccregs->scce = ~0;               /* Clear any pending event */
761  sccregs->sccm = 0;                /* Mask all interrupt/event sources */
762  sccregs->psmr = 0x3000;           /* Normal operation & mode, 1 stop bit,
763                                       8 data bits, no parity */
764  sccregs->dsr = 0x7E7E;            /* No fractional stop bits */
765  sccregs->gsmr_l = 0x00028034;     /* ENT=enable Tx, ENR=enable Rx */
766
767  /*
768   *  Initialize the Rx and Tx with the new parameters.
769   */
770  switch (minor) {
771    case SCC1_MINOR:
772      m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC1);
773      break;
774    case SCC2_MINOR:
775      m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC2);
776      break;
777    case SCC3_MINOR:
778      m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC3);
779      break;
780    case SCC4_MINOR:
781      m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC4);
782      break;
783  }
784
785  if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 ) {
786    switch (minor) {
787      case SCC1_MINOR:
788        consoleIrqData.name = BSP_CPM_IRQ_SCC1;
789        consoleIrqData.hdl = m8xx_scc1_interrupt_handler;
790        break;
791      case SCC2_MINOR:
792        consoleIrqData.name = BSP_CPM_IRQ_SCC2;
793        consoleIrqData.hdl = m8xx_scc2_interrupt_handler;
794        break;
795      case SCC3_MINOR:
796        consoleIrqData.name = BSP_CPM_IRQ_SCC3;
797        consoleIrqData.hdl = m8xx_scc3_interrupt_handler;
798        break;
799      case SCC4_MINOR:
800        consoleIrqData.name = BSP_CPM_IRQ_SCC4;
801        consoleIrqData.hdl = m8xx_scc4_interrupt_handler;
802        break;
803
804    }
805    if (!BSP_install_rtems_irq_handler (&consoleIrqData)) {
806      printk("Unable to connect SCC Irq handler\n");
807      rtems_fatal_error_occurred(1);
808    }
809  }
810}
811
812static void m8xx_smc_enable(const rtems_irq_connect_data* ptr)
813{
814  volatile m8260SMCRegisters_t *smcregs = 0;
815  switch (ptr->name) {
816  case BSP_CPM_IRQ_SMC1 :
817    smcregs = &m8260.smc1;
818    break;
819  case BSP_CPM_IRQ_SMC2 :
820    smcregs = &m8260.smc2;
821    break;
822  default:
823    break;
824  }
825  smcregs->smcm = 3;
826}
827
828static void m8xx_smc_disable(const rtems_irq_connect_data* ptr)
829{
830  volatile m8260SMCRegisters_t *smcregs = 0;
831  switch (ptr->name) {
832  case BSP_CPM_IRQ_SMC1 :
833    smcregs = &m8260.smc1;
834    break;
835  case BSP_CPM_IRQ_SMC2 :
836    smcregs = &m8260.smc2;
837    break;
838  default:
839    break;
840  }
841  smcregs->smcm &= (~3);
842}
843
844static int m8xx_smc_isOn(const rtems_irq_connect_data* ptr)
845{
846 return BSP_irq_enabled_at_cpm (ptr->name);
847}
848
849void
850m8xx_uart_smc_initialize (int minor)
851{
852  unsigned char brg;
853  volatile m8260SMCparms_t *smcparms = 0;
854  volatile m8260SMCRegisters_t *smcregs = 0;
855
856  /*
857   * Check that minor number is valid
858   */
859  if ( (minor < SMC1_MINOR) || (minor > SMC2_MINOR) )
860    return;
861
862  /* Get the simode clock source bit values for 9600 bps */
863  if( minor == SMC1_MINOR )
864    brg = m8xx_get_brg(M8260_SMC1_BRGS, 9600*16);
865  else
866    brg = m8xx_get_brg(M8260_SMC2_BRGS, 9600*16);
867  (void) brg; /* avoid set but not used warning */
868
869  /*
870   * Allocate buffer descriptors
871   */
872  RxBd[minor] = m8xx_bd_allocate (1);
873  TxBd[minor] = m8xx_bd_allocate (1);
874
875  /*
876   *  Get the address of the parameter RAM for the specified port,
877   *  configure I/O port B and put SMC in NMSI mode, connect the
878   *  SMC to the appropriate BRG.
879   *
880   *  SMC2 RxD is shared with port B bit 20
881   *  SMC2 TxD is shared with port B bit 21
882   *  SMC1 RxD is shared with port B bit 24
883   *  SMC1 TxD is shared with port B bit 25
884   */
885  switch (minor) {
886    case SMC1_MINOR:
887      smcparms = &m8260.smc1p;
888      smcregs  = &m8260.smc1;
889
890#if 0
891      m8260.pbpar |=  0x000000C0;    /* PB24 & PB25 are dedicated peripheral pins */
892      m8260.pbdir &= ~0x000000C0;    /* PB24 & PB25 must not drive UART lines */
893      m8260.pbodr &= ~0x000000C0;    /* PB24 & PB25 are not open drain */
894
895      m8260.simode &= 0xFFFF0FFF;    /* Clear SMC1CS & SMC1 for NMSI mode */
896      m8260.simode |= brg << 12;     /* SMC1CS = brg */
897#endif
898      break;
899
900    case SMC2_MINOR:
901      smcparms = &m8260.smc2p;
902      smcregs = &m8260.smc2;
903#if 0
904      m8260.pbpar |=  0x00000C00;    /* PB20 & PB21 are dedicated peripheral pins */
905      m8260.pbdir &= ~0x00000C00;    /* PB20 & PB21 must not drive the UART lines */
906      m8260.pbodr &= ~0x00000C00;    /* PB20 & PB21 are not open drain */
907
908      m8260.simode &= 0x0FFFFFFF;    /* Clear SMC2CS & SMC2 for NMSI mode */
909      m8260.simode |= brg << 28;     /* SMC2CS = brg */
910#endif
911      break;
912  }
913
914  /*
915   * Set up SMC parameter RAM common to all protocols
916   */
917  smcparms->rbase = (char *)RxBd[minor] - (char *)&m8260;
918  smcparms->tbase = (char *)TxBd[minor] - (char *)&m8260;
919  smcparms->rfcr = M8260_RFCR_MOT | M8260_RFCR_60X_BUS;
920  smcparms->tfcr = M8260_TFCR_MOT | M8260_TFCR_60X_BUS;
921  if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 )
922    smcparms->mrblr = RXBUFSIZE;    /* Maximum Rx buffer size */
923  else
924    smcparms->mrblr = 1;            /* Maximum Rx buffer size */
925
926  /*
927   * Set up SMC1 parameter RAM UART-specific parameters
928   */
929  smcparms->un.uart.max_idl = 10;   /* Set nb of idle chars to close buffer */
930  smcparms->un.uart.brkcr = 0;      /* Set nb of breaks to send for STOP Tx */
931  smcparms->un.uart.brkec = 0;      /* Clear break counter */
932
933  /*
934   * Set up the Receive Buffer Descriptor
935   */
936  RxBd[minor]->status = M8260_BD_EMPTY | M8260_BD_WRAP | M8260_BD_INTERRUPT;
937  RxBd[minor]->length = 0;
938  RxBd[minor]->buffer = rxBuf[minor];
939
940  /*
941   * Setup the Transmit Buffer Descriptor
942   */
943  TxBd[minor]->status = M8260_BD_WRAP;
944
945  /*
946   * Set up SMCx general and protocol-specific mode registers
947   */
948  smcregs->smce = ~0;               /* Clear any pending events */
949  smcregs->smcm = 0;                /* Enable SMC Rx & Tx interrupts */
950  smcregs->smcmr = M8260_SMCMR_CLEN(9) | M8260_SMCMR_SM_UART;
951
952  /*
953   * Send "Init parameters" command
954   */
955  switch (minor) {
956    case SMC1_MINOR:
957      m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SMC1);
958      break;
959
960    case SMC2_MINOR:
961      m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SMC2);
962      break;
963  }
964
965  /*
966   * Enable receiver and transmitter
967   */
968  smcregs->smcmr |= M8260_SMCMR_TEN | M8260_SMCMR_REN;
969  if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 ) {
970    consoleIrqData.on = m8xx_smc_enable;
971    consoleIrqData.off = m8xx_smc_disable;
972    consoleIrqData.isOn = m8xx_smc_isOn;
973    switch (minor) {
974      case SMC1_MINOR:
975        consoleIrqData.name = BSP_CPM_IRQ_SMC1;
976        consoleIrqData.hdl  = m8xx_smc1_interrupt_handler;
977        break;
978
979      case SMC2_MINOR:
980        consoleIrqData.name = BSP_CPM_IRQ_SMC2;
981        consoleIrqData.hdl  = m8xx_smc2_interrupt_handler;
982        break;
983#if 0
984      case SMC1_MINOR:
985        rtems_interrupt_catch (m8xx_smc1_interrupt_handler,
986                                    PPC_IRQ_CPM_SMC1,
987                                    &old_handler[minor]);
988
989        smcregs->smcm = 3;            /* Enable SMC1 Rx & Tx interrupts */
990        m8260.sipnr_l |= M8260_SIMASK_SMC1;      /* Clear pending register */
991        m8260.simr_l  |= M8260_SIMASK_SMC1;      /* Enable SMC1 interrupts */
992        break;
993
994      case SMC2_MINOR:
995        rtems_interrupt_catch (m8xx_smc2_interrupt_handler,
996                                    PPC_IRQ_CPM_SMC2,
997                                    &old_handler[minor]);
998
999        smcregs->smcm = 3;            /* Enable SMC2 Rx & Tx interrupts */
1000        m8260.sipnr_l |= M8260_SIMASK_SMC2;      /* Clear pending register */
1001        m8260.simr_l  |= M8260_SIMASK_SMC2;      /* Enable SMC2 interrupts */
1002        break;
1003#endif
1004    }
1005    if (!BSP_install_rtems_irq_handler (&consoleIrqData)) {
1006      printk("Unable to connect SMC Irq handler\n");
1007      rtems_fatal_error_occurred(1);
1008    }
1009  }
1010}
1011
1012void
1013m8xx_uart_initialize(void)
1014{
1015}
1016
1017void
1018m8xx_uart_interrupts_initialize(void)
1019{
1020#ifdef mpc8260
1021  /* CHECK THIS */
1022
1023#else
1024
1025#if defined(mpc860)
1026  m8xx.cicr = 0x00E43F80;           /* SCaP=SCC1, SCbP=SCC2, SCcP=SCC3,
1027                                       SCdP=SCC4, IRL=1, HP=PC15, IEN=1 */
1028#else
1029  m8xx.cicr = 0x00043F80;           /* SCaP=SCC1, SCbP=SCC2, IRL=1, HP=PC15, IEN=1 */
1030#endif
1031  m8xx.simask |= M8xx_SIMASK_LVM1;  /* Enable level interrupts */
1032#endif
1033}
1034
1035int
1036m8xx_uart_pollRead(
1037  int minor
1038)
1039{
1040  unsigned char c;
1041
1042  if (RxBd[minor]->status & M8260_BD_EMPTY) {
1043    return -1;
1044  }
1045  rtems_cache_invalidate_multiple_data_lines(
1046    (const void *) RxBd[minor]->buffer,
1047    RxBd[minor]->length
1048  );
1049  c = ((char *)RxBd[minor]->buffer)[0];
1050  RxBd[minor]->status = M8260_BD_EMPTY | M8260_BD_WRAP;
1051  return c;
1052}
1053
1054/*
1055 *  TODO: Get a free buffer and set it up.
1056 */
1057ssize_t
1058m8xx_uart_write(
1059  int minor,
1060  const char *buf,
1061  size_t len
1062)
1063{
1064  if (len > 0) {
1065    while( (TxBd[minor]->status) & M8260_BD_READY );
1066
1067    rtems_cache_flush_multiple_data_lines( buf, len );
1068    TxBd[minor]->buffer = (char *) buf;
1069    TxBd[minor]->length = len;
1070    TxBd[minor]->status = M8260_BD_READY | M8260_BD_WRAP | M8260_BD_INTERRUPT;
1071  }
1072
1073  return 0;
1074}
1075
1076ssize_t
1077m8xx_uart_pollWrite(
1078  int minor,
1079  const char *buf,
1080  size_t len
1081)
1082{
1083  size_t retval = len;
1084
1085  while (len--) {
1086    while (TxBd[minor]->status & M8260_BD_READY)
1087      continue;
1088    txBuf[minor] = *buf++;
1089    rtems_cache_flush_multiple_data_lines( (void *)&txBuf[minor], 1 );
1090    TxBd[minor]->buffer = &txBuf[minor];
1091    TxBd[minor]->length = 1;
1092    TxBd[minor]->status = M8260_BD_READY | M8260_BD_WRAP;
1093  }
1094
1095  return retval;
1096}
Note: See TracBrowser for help on using the repository browser.