source: rtems/c/src/lib/libcpu/powerpc/mpc8260/console-generic/console-generic.c @ 80bbfb9a

4.104.114.84.95
Last change on this file since 80bbfb9a was 5c76213, checked in by Joel Sherrill <joel.sherrill@…>, on 01/04/02 at 18:16:26

2002-01-03 Ralf Corsepius <corsepiu@…>

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