source: rtems/c/src/lib/libbsp/m68k/mrm332/console/sci.c @ 55068fa5

4.104.114.84.95
Last change on this file since 55068fa5 was 55068fa5, checked in by Ralf Corsepius <ralf.corsepius@…>, on 01/05/05 at 18:12:35

2005-01-05 Ralf Corsepius <ralf.corsepius@…>

  • console/sci.c: Remove CVS Log.
  • Property mode set to 100644
File size: 51.5 KB
Line 
1/*****************************************************************************
2* File:     sci.c
3*
4* Desc:     This file contains the console IO routines for the SCI port.
5*           There are two interfaces in this module. One is for the rtems
6*           termios/console code and the other is a device driver interface.
7*           This module works together with the termio module which is
8*           sometimes referred to as the "line disciplines" which implements
9*           terminal i/o processing like tabs, backspaces, and newlines.
10*           The rtems printf uses interrupt io and the rtems printk routine
11*           uses polled io which is better for debugging.
12*
13* Index:    Documentation
14*           Section A  - Include Files
15*           Section B  - Manifest Constants
16*           Section C  - External Data
17*           Section D  - External Functions
18*           Section E  - Local Functions
19*           Section F  - Local Variables
20*           Section G  - A circular data buffer for rcv chars
21*           Section H  - RTEMS termios callbacks for the interrupt api
22*           Section I  - RTEMS termios callbacks for the polled api
23
24*           Section 0  - Miscellaneous routines
25*           Section 1  - Routines to manipulate the circular buffer
26*           Section 2  - Interrupt based entry points for the termios module
27*           Section 3  - Polling based entry points for the termios module
28*           Section 4  - Device driver public api entry points
29*           Section 5  - Hardware level routines
30*           Section 6  - Testing and debugging code
31*
32* Refer:    Motorola QSM Reference Manual - Chapter 5 - SCI sub-module
33*
34* Note:     See bsp.h,confdefs.h,system.h for installing drivers into RTEMS.
35*
36* $Id$
37*
38*****************************************************************************/
39
40
41/*****************************************************************************
42  Compiler Options for the incurably curious
43*****************************************************************************/
44
45/*
46/opt/rtems/bin/m68k-rtems-gcc
47    --pipe                                      # use pipes, not tmp files
48    -B../../../../../../../../opti/lib/         # where the library is
49    -specs bsp_specs                            # ???
50    -qrtems                                     # ???
51    -g                                          # add debugging info
52    -Wall                                       # issue all warnings
53    -fasm                                       # allow inline asm???
54    -DCONSOLE_SCI                               # for opti-r box/rev b proto
55    -mcpu32                                     # machine = motorola cpu 32
56    -c                                          # compile, don't link
57    -O4                                         # max optimization
58    -fomit-frame-pointer                        # stack frames are optional
59    -o o-optimize/sci.o                         # the object file
60    ../../../../../../../../../rtems/c/src/lib/libbsp/m68k/opti/console/sci.c
61*/
62
63
64/*****************************************************************************
65  Overview of serial port console terminal input/output
66*****************************************************************************/
67
68/*
69   +-----------+                               +---------+
70   |    app    |                               |   app   |
71   +-----------+                               +---------+
72         |                                          |
73         | (printf,scanf,etc.)                      |
74         v                                          |
75   +-----------+                                    |
76   |    libc   |                                    |
77   +-----------+                                    |
78         |                                          |
79         |                                          |
80         |     (open,close,read,write,ioctl)        |
81   ======|==========================================|========================
82         | /dev/console                             | /dev/sci
83         | (stdin,stdout,stderr)                    |
84   ======|==========================================|========================
85         |                                          |
86         |                                          |
87         v                                          v
88   +-----------+         +-----------+         +---------+
89   |  console  |  <--->  |  termios  |  <--->  |   sci   |
90   |  driver   |         |  module   |         |  driver |
91   +-----------+         +-----------+         +---------+
92                                                    |
93                                                    |
94                                                    v
95                                               +---------+
96                                               |         |
97                                               |  uart   |
98                                               |         |
99                                               +---------+
100*/
101
102
103/*****************************************************************************
104  Section A - Include Files
105*****************************************************************************/
106
107#include <rtems.h>
108#include <bsp.h>
109#include <rtems/bspIo.h>
110#include <stdio.h>
111#include <rtems/libio.h>
112#include <libchip/serial.h>
113#include <libchip/sersupp.h>
114#include "sci.h"
115//#include "../misc/include/cpu332.h"
116
117
118/*****************************************************************************
119  Section B - Manifest Constants
120*****************************************************************************/
121
122#define SCI_MINOR       0                   // minor device number
123
124// IMPORTANT - if the device driver api is opened, it means the sci is being
125// used for direct hardware access, so other users (like termios) get ignored
126
127#define DRIVER_CLOSED   0                   // the device driver api is closed
128#define DRIVER_OPENED   1                   // the device driver api is opened
129
130// system clock definitions, i dont have documentation on this...
131
132#if 0 // Not needed, this is provided in mrm332.h
133#define XTAL            32768.0                 // crystal frequency in Hz
134#define NUMB_W          0                               // system clock parameters
135#define NUMB_X          1
136//efine NUMB_Y          0x38                    // for 14.942 Mhz
137#define NUMB_Y          0x3F                        // for 16.777 Mhz
138
139#define SYS_CLOCK       (XTAL * 4.0 * (NUMB_Y+1) * (1 << (2 * NUMB_W + NUMB_X)))
140
141#endif
142
143
144/*****************************************************************************
145  Section C - External Data
146*****************************************************************************/
147
148
149
150/*****************************************************************************
151  Section D - External Functions
152*****************************************************************************/
153
154
155
156/*****************************************************************************
157  Section E - Local Functions
158*****************************************************************************/
159
160void SCI_output_char(char c);
161
162rtems_isr SciIsr( rtems_vector_number vector );         // interrupt handler
163
164const rtems_termios_callbacks * SciGetTermiosHandlers( int32_t   polled );
165
166rtems_device_driver SciInitialize ();                   // device driver api
167rtems_device_driver SciOpen ();                         // device driver api
168rtems_device_driver SciClose ();                        // device driver api
169rtems_device_driver SciRead ();                         // device driver api
170rtems_device_driver SciWrite ();                        // device driver api
171rtems_device_driver SciControl ();                      // device driver api
172
173int32_t   SciInterruptOpen();                            // termios api
174int32_t   SciInterruptClose();                           // termios api
175int32_t   SciInterruptWrite();                           // termios api
176
177int32_t   SciSetAttributes();                            // termios api
178
179int32_t   SciPolledOpen();                               // termios api
180int32_t   SciPolledClose();                              // termios api
181int32_t   SciPolledRead();                               // termios api
182int32_t   SciPolledWrite();                              // termios api
183
184static void SciSetBaud(uint32_t   rate);                // hardware routine
185static void SciSetDataBits(uint16_t   bits);            // hardware routine
186static void SciSetParity(uint16_t   parity);            // hardware routine
187
188static void inline SciDisableAllInterrupts( void );     // hardware routine
189static void inline SciDisableTransmitInterrupts( void );// hardware routine
190static void inline SciDisableReceiveInterrupts( void ); // hardware routine
191
192static void inline SciEnableTransmitInterrupts( void ); // hardware routine
193static void inline SciEnableReceiveInterrupts( void );  // hardware routine
194
195static void inline SciDisableReceiver( void );          // hardware routine
196static void inline SciDisableTransmitter( void );       // hardware routine
197
198static void inline SciEnableReceiver( void );           // hardware routine
199static void inline SciEnableTransmitter( void );        // hardware routine
200
201void SciWriteCharWait  ( uint8_t);                   // hardware routine
202void SciWriteCharNoWait( uint8_t);                   // hardware routine
203
204uint8_t   inline SciCharAvailable( void );              // hardware routine
205
206uint8_t   inline SciReadCharWait( void );               // hardware routine
207uint8_t   inline SciReadCharNoWait( void );             // hardware routine
208
209void SciSendBreak( void );                              // test routine
210
211static int8_t   SciRcvBufGetChar();                      // circular rcv buf
212static void    SciRcvBufPutChar( uint8_t);           // circular rcv buf
213//atic void    SciRcvBufFlush( void );                  // circular rcv buf
214
215void SciUnitTest();                                     // test routine
216void SciPrintStats();                                   // test routine
217
218
219/*****************************************************************************
220  Section F - Local Variables
221*****************************************************************************/
222
223static struct rtems_termios_tty *SciTermioTty;
224
225static uint8_t   SciInited = 0;             // has the driver been inited
226
227static uint8_t   SciOpened;                 // has the driver been opened
228
229static uint8_t   SciMajor;                  // major device number
230
231static uint16_t   SciBaud;                  // current value in baud register
232
233static uint32_t   SciBytesIn  = 0;          // bytes received
234static uint32_t   SciBytesOut = 0;          // bytes transmitted
235
236static uint32_t   SciErrorsParity  = 0;     // error counter
237static uint32_t   SciErrorsNoise   = 0;     // error counter
238static uint32_t   SciErrorsFraming = 0;     // error counter
239static uint32_t   SciErrorsOverrun = 0;     // error counter
240
241#if defined(CONSOLE_SCI)
242
243// this is what rtems printk uses to do polling based output
244
245BSP_output_char_function_type      BSP_output_char = SCI_output_char;
246BSP_polling_getchar_function_type  BSP_poll_char   = NULL;
247
248#endif
249
250// cvs id string so you can use the unix ident command on the object
251
252#ifdef ID_STRINGS
253static const char SciIdent[]="$Id$";
254#endif
255
256
257/*****************************************************************************
258  Section G - A circular buffer for rcv chars when the driver interface is used.
259*****************************************************************************/
260
261// it is trivial to wrap your buffer pointers when size is a power of two
262
263#define SCI_RCV_BUF_SIZE        256         // must be a power of 2 !!!
264
265// if someone opens the sci device using the device driver interface,
266// then the receive data interrupt handler will put characters in this buffer
267// instead of sending them up to the termios module for the console
268
269static uint8_t   SciRcvBuffer[SCI_RCV_BUF_SIZE];
270
271static uint8_t   SciRcvBufPutIndex = 0;     // array index to put in next char
272
273static uint8_t   SciRcvBufGetIndex = 0;     // array index to take out next char
274
275static uint16_t  SciRcvBufCount = 0;        // how many bytes are in the buffer
276
277
278
279/*****************************************************************************
280  Section H - RTEMS termios callbacks for the interrupt version of the driver
281*****************************************************************************/
282
283static const rtems_termios_callbacks SciInterruptCallbacks =
284{
285    SciInterruptOpen,                       // first open
286    SciInterruptClose,                      // last close
287    NULL,                                   // polled read (not required)
288    SciInterruptWrite,                      // write
289    SciSetAttributes,                       // set attributes
290    NULL,                                   // stop remote xmit
291    NULL,                                   // start remote xmit
292    TRUE                                    // output uses interrupts
293};
294
295/*****************************************************************************
296  Section I - RTEMS termios callbacks for the polled version of the driver
297*****************************************************************************/
298
299static const rtems_termios_callbacks SciPolledCallbacks =
300{
301    SciPolledOpen,                          // first open
302    SciPolledClose,                         // last close
303    SciPolledRead,                          // polled read
304    SciPolledWrite,                         // write
305    SciSetAttributes,                       // set attributes
306    NULL,                                   // stop remote xmit
307    NULL,                                   // start remote xmit
308    FALSE                                   // output uses interrupts
309};
310
311
312/////////////////////////////////////////////////////////////////////////////
313//
314//                              SECTION 0
315//                        MISCELLANEOUS ROUTINES
316//
317/////////////////////////////////////////////////////////////////////////////
318
319/****************************************************************************
320* Func:     SCI_output_char
321* Desc:     used by rtems printk function to send a char to the uart
322* Inputs:   the character to transmit
323* Outputs:  none
324* Errors:   none
325* Scope:    public
326****************************************************************************/
327
328void SCI_output_char(char c)
329{
330//  ( minor device number, pointer to the character, length )
331
332    SciPolledWrite( SCI_MINOR, &c, 1);
333
334    return;
335}
336
337
338/****************************************************************************
339* Func:     SciGetTermiosHandlers
340* Desc:     returns a pointer to the table of serial io functions
341*           this is called from console_open with polled set to false
342* Inputs:   flag indicating whether we want polled or interrupt driven io
343* Outputs:  pointer to function table
344* Errors:   none
345* Scope:    public
346****************************************************************************/
347
348const rtems_termios_callbacks * SciGetTermiosHandlers( int32_t   polled )
349{
350    if ( polled )
351    {
352        return &SciPolledCallbacks;             // polling based
353    }
354    else
355    {
356        return &SciInterruptCallbacks;          // interrupt driven
357    }
358}
359
360
361/****************************************************************************
362* Func:     SciIsr
363* Desc:     interrupt handler for serial communications interface
364* Inputs:   vector number - unused
365* Outputs:  none
366* Errors:   none
367* Scope:    public API
368****************************************************************************/
369
370rtems_isr SciIsr( rtems_vector_number vector )
371{
372    uint8_t   ch;
373
374    if ( (*SCSR) & SCI_ERROR_PARITY  )   SciErrorsParity  ++;
375    if ( (*SCSR) & SCI_ERROR_FRAMING )   SciErrorsFraming ++;
376    if ( (*SCSR) & SCI_ERROR_NOISE   )   SciErrorsNoise   ++;
377    if ( (*SCSR) & SCI_ERROR_OVERRUN )   SciErrorsOverrun ++;
378
379    // see if it was a transmit interrupt
380
381    if ( (*SCSR) & SCI_XMTR_AVAILABLE )         // data reg empty, xmt complete
382    {
383        SciDisableTransmitInterrupts();
384
385        // tell termios module that the charcter was sent
386        // he will call us later to transmit more if there are any
387
388        if (rtems_termios_dequeue_characters( SciTermioTty, 1 ))
389        {
390            // there are more bytes to transmit so enable TX interrupt
391
392            SciEnableTransmitInterrupts();
393        }
394    }
395
396    // see if it was a receive interrupt
397    // on the sci uart we just get one character per interrupt
398
399    while (  SciCharAvailable() )               // char in data register?
400    {
401        ch = SciReadCharNoWait();               // get the char from the uart
402
403        // IMPORTANT!!!
404        // either send it to the termios module or keep it locally
405
406        if ( SciOpened == DRIVER_OPENED )       // the driver is open
407        {
408            SciRcvBufPutChar(ch);               // keep it locally
409        }
410        else                                    // put in termios buffer
411        {
412            rtems_termios_enqueue_raw_characters( SciTermioTty, &ch, 1 );
413        }
414
415        *SCSR &= SCI_CLEAR_RX_INT;              // clear the interrupt
416    }
417}
418
419
420/////////////////////////////////////////////////////////////////////////////
421//
422//                              SECTION 1
423//                ROUTINES TO MANIPULATE THE CIRCULAR BUFFER
424//
425/////////////////////////////////////////////////////////////////////////////
426
427/****************************************************************************
428* Func:     SciRcvBufGetChar
429* Desc:     read a character from the circular buffer
430*           make sure there is data before you call this!
431* Inputs:   none
432* Outputs:  the character or -1
433* Errors:   none
434* Scope:    private
435****************************************************************************/
436
437static int8_t   SciRcvBufGetChar()
438{
439    rtems_interrupt_level level;
440    uint8_t   ch;
441
442    if ( SciRcvBufCount == 0 )
443    {
444        rtems_fatal_error_occurred(0xDEAD);     // check the count first!
445    }
446
447    rtems_interrupt_disable( level );           // disable interrupts
448
449    ch = SciRcvBuffer[SciRcvBufGetIndex];       // get next byte
450
451    SciRcvBufGetIndex++;                        // bump the index
452
453    SciRcvBufGetIndex &= SCI_RCV_BUF_SIZE - 1;  // and wrap it
454
455    SciRcvBufCount--;                           // decrement counter
456
457    rtems_interrupt_enable( level );            // restore interrupts
458
459    return ch;                                  // return the char
460}
461
462
463/****************************************************************************
464* Func:     SciRcvBufPutChar
465* Desc:     put a character into the rcv data circular buffer
466* Inputs:   the character
467* Outputs:  none
468* Errors:   none
469* Scope:    private
470****************************************************************************/
471
472static void SciRcvBufPutChar( uint8_t   ch )
473{
474    rtems_interrupt_level level;
475
476    if ( SciRcvBufCount == SCI_RCV_BUF_SIZE )   // is there room?
477    {
478        return;                                 // no, throw it away
479    }
480
481    rtems_interrupt_disable( level );           // disable interrupts
482
483    SciRcvBuffer[SciRcvBufPutIndex] = ch;       // put it in the buf
484
485    SciRcvBufPutIndex++;                        // bump the index
486
487    SciRcvBufPutIndex &= SCI_RCV_BUF_SIZE - 1;  // and wrap it
488
489    SciRcvBufCount++;                           // increment counter
490
491    rtems_interrupt_enable( level );            // restore interrupts
492
493    return;                                     // return
494}
495
496
497/****************************************************************************
498* Func:     SciRcvBufFlush
499* Desc:     completely reset and clear the rcv buffer
500* Inputs:   none
501* Outputs:  none
502* Errors:   none
503* Scope:    private
504****************************************************************************/
505
506#if 0                                           // prevents compiler warning
507static void SciRcvBufFlush( void )
508{
509    rtems_interrupt_level level;
510
511    rtems_interrupt_disable( level );           // disable interrupts
512
513    memset( SciRcvBuffer, 0, sizeof(SciRcvBuffer) );
514
515    SciRcvBufPutIndex = 0;                      // clear
516
517    SciRcvBufGetIndex = 0;                      // clear
518
519    SciRcvBufCount = 0;                         // clear
520
521    rtems_interrupt_enable( level );            // restore interrupts
522
523    return;                                     // return
524}
525#endif
526
527
528/////////////////////////////////////////////////////////////////////////////
529//
530//                              SECTION 2
531//            INTERRUPT BASED ENTRY POINTS FOR THE TERMIOS MODULE
532//
533/////////////////////////////////////////////////////////////////////////////
534
535/****************************************************************************
536* Func:     SciInterruptOpen
537* Desc:     open routine for the interrupt based device driver
538*           Default state is 9600 baud, 8 bits, No parity, and 1 stop bit. ??
539**CHANGED** Default baud rate is now 19200, 8N1
540*           called from rtems_termios_open which is called from console_open
541* Inputs:   major - device number
542*           minor - device number
543*           args - points to terminal info
544* Outputs:  success/fail
545* Errors:   none
546* Scope:    public API
547****************************************************************************/
548
549int32_t   SciInterruptOpen(
550    int32_t    major,
551    int32_t    minor,
552    void     *arg
553)
554{
555    rtems_libio_open_close_args_t * args = arg;
556    rtems_isr_entry old_vector;
557
558    if ( minor != SCI_MINOR )                   // check minor device num
559    {
560        return -1;
561    }
562
563    if ( !args )                                // must have args
564    {
565        return -1;
566    }
567
568    SciTermioTty = args->iop->data1;            // save address of struct
569
570    SciDisableAllInterrupts();                  // turn off sci interrupts
571
572    // THIS IS ACTUALLY A BAD THING - SETTING LINE PARAMETERS HERE
573    // IT SHOULD BE DONE THROUGH TCSETATTR() WHEN THE CONSOLE IS OPENED!!!
574
575//  SciSetBaud(115200);                         // set the baud rate
576//  SciSetBaud( 57600);                         // set the baud rate
577//  SciSetBaud( 38400);                         // set the baud rate
578SciSetBaud( 19200);                         // set the baud rate
579//    SciSetBaud(  9600);                         // set the baud rate
580
581    SciSetParity(SCI_PARITY_NONE);              // set parity to none
582
583    SciSetDataBits(SCI_8_DATA_BITS);            // set data bits to 8
584
585    // Install our interrupt handler into RTEMS, where does 66 come from?
586
587    rtems_interrupt_catch( SciIsr, 66, &old_vector );
588
589    *QIVR  = 66;
590    *QIVR &= 0xf8;
591    *QILR |= 0x06 & 0x07;
592
593    SciEnableTransmitter();                     // enable the transmitter
594
595    SciEnableReceiver();                        // enable the receiver
596
597    SciEnableReceiveInterrupts();               // enable rcv interrupts
598
599    return RTEMS_SUCCESSFUL;
600}
601
602
603/****************************************************************************
604* Func:     SciInterruptClose
605* Desc:     close routine called by the termios module
606* Inputs:   major - device number
607*           minor - device number
608*           args - unused
609* Outputs:  success/fail
610* Errors:   none
611* Scope:    public - termio entry point
612****************************************************************************/
613
614int32_t   SciInterruptClose(
615    int32_t    major,
616    int32_t    minor,
617    void     *arg
618)
619{
620    SciDisableAllInterrupts();
621
622    return RTEMS_SUCCESSFUL;
623}
624
625
626/****************************************************************************
627* Func:     SciInterruptWrite
628* Desc:     writes data to the uart using transmit interrupts
629* Inputs:   minor - device number
630*           buf - points to the data
631*           len - number of bytes to send
632* Outputs:  success/fail
633* Errors:   none
634* Scope:    public API
635****************************************************************************/
636
637int32_t   SciInterruptWrite(
638    int32_t      minor,
639    const char *buf,
640    int32_t      len
641)
642{
643    // We are using interrupt driven output so termios only sends us
644    // one character at a time. The sci does not have a fifo.
645
646    if ( !len )                                 // no data?
647    {
648        return 0;                               // return error
649    }
650
651    if ( minor != SCI_MINOR )                   // check the minor dev num
652    {
653        return 0;                               // return error
654    }
655
656    if ( SciOpened == DRIVER_OPENED )           // is the driver api open?
657    {
658        return 1;                               // yep, throw this away
659    }
660
661    SciWriteCharNoWait(*buf);                   // try to send a char
662
663    *SCSR &= SCI_CLEAR_TDRE;                    // clear tx data reg empty flag
664
665    SciEnableTransmitInterrupts();              // enable the tx interrupt
666
667    return 1;                                   // return success
668}
669
670
671/****************************************************************************
672* Func:     SciSetAttributes
673* Desc:     setup the uart based on the termios modules requests
674* Inputs:   minor - device number
675*           t - pointer to the termios info struct
676* Outputs:  none
677* Errors:   none
678* Scope:    public API
679****************************************************************************/
680
681int32_t   SciSetAttributes(
682    int32_t   minor,
683    const struct termios *t
684)
685{
686    uint32_t    baud_requested;
687    uint32_t    sci_rate = 0;
688    uint16_t    sci_parity = 0;
689    uint16_t    sci_databits = 0;
690
691    if ( minor != SCI_MINOR )                   // check the minor dev num
692    {
693        return -1;                              // return error
694    }
695
696    // if you look closely you will see this is the only thing we use
697    // set the baud rate
698
699    baud_requested = t->c_cflag & CBAUD;        // baud rate
700
701    if (!baud_requested)
702    {
703//        baud_requested = B9600;                 // default to 9600 baud
704        baud_requested = B19200;                 // default to 19200 baud
705    }
706
707    sci_rate = termios_baud_to_number( baud_requested );
708
709    // parity error detection
710
711    if (t->c_cflag & PARENB)                    // enable parity detection?
712    {
713        if (t->c_cflag & PARODD)
714        {
715            sci_parity = SCI_PARITY_ODD;        // select odd parity
716        }
717        else
718        {
719            sci_parity = SCI_PARITY_EVEN;       // select even parity
720        }
721    }
722    else
723    {
724        sci_parity = SCI_PARITY_NONE;           // no parity, most common
725    }
726
727    //  set the number of data bits, 8 is most common
728
729    if (t->c_cflag & CSIZE)                     // was it specified?
730    {
731        switch (t->c_cflag & CSIZE)
732        {
733            case CS8:   sci_databits = SCI_8_DATA_BITS;   break;
734            default :   sci_databits = SCI_9_DATA_BITS;   break;
735        }
736    }
737    else
738    {
739        sci_databits = SCI_8_DATA_BITS;         // default to 8 data bits
740    }
741
742    //  the number of stop bits; always 1 for SCI
743
744    if (t->c_cflag & CSTOPB)
745    {
746        // do nothing
747    }
748
749    // setup the hardware with these serial port parameters
750
751    SciSetBaud(sci_rate);                       // set the baud rate
752
753    SciSetParity(sci_parity);                   // set the parity type
754
755    SciSetDataBits(sci_databits);               // set the data bits
756
757    return RTEMS_SUCCESSFUL;
758}
759
760
761/////////////////////////////////////////////////////////////////////////////
762//
763//                              SECTION 3
764//            POLLING BASED ENTRY POINTS FOR THE TERMIOS MODULE
765//
766/////////////////////////////////////////////////////////////////////////////
767
768/****************************************************************************
769* Func:     SciPolledOpen
770* Desc:     open routine for the polled i/o version of the driver
771*           called from rtems_termios_open which is called from console_open
772* Inputs:   major - device number
773*           minor - device number
774*           args - points to terminal info struct
775* Outputs:  success/fail
776* Errors:   none
777* Scope:    public - termios entry point
778****************************************************************************/
779
780int32_t   SciPolledOpen(
781    int32_t   major,
782    int32_t   minor,
783    void    *arg
784)
785{
786    rtems_libio_open_close_args_t * args = arg;
787
788    if ( minor != SCI_MINOR )                   // check minor device num
789    {
790        return -1;
791    }
792
793    if ( !args )                                // must have args
794    {
795        return -1;
796    }
797
798    SciTermioTty = args->iop->data1;            // Store tty pointer
799
800    SciDisableAllInterrupts();                  // don't generate interrupts
801
802    // THIS IS ACTUALLY A BAD THING - SETTING LINE PARAMETERS HERE
803    // IT SHOULD BE DONE THROUGH TCSETATTR() WHEN THE CONSOLE IS OPENED!!!
804
805//  SciSetBaud(115200);                         // set the baud rate
806//  SciSetBaud( 57600);                         // set the baud rate
807//  SciSetBaud( 38400);                         // set the baud rate
808  SciSetBaud( 19200);                         // set the baud rate
809//  SciSetBaud(  9600);                         // set the baud rate
810
811    SciSetParity(SCI_PARITY_NONE);              // set no parity
812
813    SciSetDataBits(SCI_8_DATA_BITS);            // set 8 data bits
814
815    SciEnableTransmitter();                     // enable the xmitter
816
817    SciEnableReceiver();                        // enable the rcvr
818
819    return RTEMS_SUCCESSFUL;
820}
821
822
823/****************************************************************************
824* Func:     SciPolledClose
825* Desc:     close routine for the device driver, same for both
826* Inputs:   major - device number
827*           minor - device number
828*           args - unused
829* Outputs:  success/fail
830* Errors:   none
831* Scope:    public termios API
832****************************************************************************/
833
834int32_t   SciPolledClose(
835    int32_t    major,
836    int32_t    minor,
837    void     *arg
838)
839{
840    SciDisableAllInterrupts();
841
842    return RTEMS_SUCCESSFUL;
843}
844
845
846/****************************************************************************
847* Func:     SciPolledRead
848* Desc:     polling based read routine for the uart
849* Inputs:   minor - device number
850* Outputs:  error or the character read
851* Errors:   none
852* Scope:    public API
853****************************************************************************/
854
855int32_t   SciPolledRead(
856    int32_t   minor
857)
858{
859    if ( minor != SCI_MINOR )               // check the minor dev num
860    {
861        return -1;                          // return error
862    }
863
864    if ( SciCharAvailable() )               // if a char is available
865    {
866        return SciReadCharNoWait();         // read the rx data register
867    }
868
869    return -1;                              // return error
870}
871
872
873/****************************************************************************
874* Func:     SciPolledWrite
875* Desc:     writes out characters in polled mode, waiting for the uart
876*           check in console_open, but we only seem to use interrupt mode
877* Inputs:   minor - device number
878*           buf - points to the data
879*           len - how many bytes
880* Outputs:  error or number of bytes written
881* Errors:   none
882* Scope:    public termios API
883****************************************************************************/
884
885int32_t   SciPolledWrite(
886    int32_t        minor,
887    const char   *buf,
888    int32_t        len
889)
890{
891    int32_t   written = 0;
892
893    if ( minor != SCI_MINOR )                   // check minor device num
894    {
895        return -1;
896    }
897
898    if ( SciOpened == DRIVER_OPENED )           // is the driver api open?
899    {
900        return -1;                              // toss the data
901    }
902
903    // send each byte in the string out the port
904
905    while ( written < len )
906    {
907        SciWriteCharWait(*buf++);               // send a byte
908
909        written++;                              // increment counter
910    }
911
912    return written;                             // return count
913}
914
915
916/////////////////////////////////////////////////////////////////////////////
917//
918//                              SECTION 4
919//                 DEVICE DRIVER PUBLIC API ENTRY POINTS
920//
921/////////////////////////////////////////////////////////////////////////////
922
923/****************************************************************************
924* Func:     SciInit
925* Desc:     Initialize the lasers device driver and hardware
926* Inputs:   major - the major device number which is assigned by rtems
927*           minor - the minor device number which is undefined at this point
928*           arg - ?????
929* Outputs:  RTEMS_SUCCESSFUL
930* Errors:   None.
931* Scope:    public API
932****************************************************************************/
933
934rtems_device_driver SciInitialize (
935    rtems_device_major_number major,
936    rtems_device_minor_number minor,
937    void * arg
938)
939{
940//     rtems_status_code status;
941
942//printk("%s\r\n", __FUNCTION__);
943
944    // register the SCI device name for termios console i/o
945    // this is done over in console.c which doesn't seem exactly right
946    // but there were problems doing it here...
947
948//  status = rtems_io_register_name( "/dev/sci", major, 0 );
949
950//  if (status != RTEMS_SUCCESSFUL)
951//      rtems_fatal_error_occurred(status);
952
953    SciMajor = major;                           // save the rtems major number
954
955    SciOpened = DRIVER_CLOSED;                  // initial state is closed
956
957    // if you have an interrupt handler, install it here
958
959    SciInited = 1;                              // set the inited flag
960
961    return RTEMS_SUCCESSFUL;
962}
963
964
965/****************************************************************************
966* Func:     SciOpen
967* Desc:     device driver open routine
968*           you must open a device before you can anything else
969*           only one process can have the device opened at a time
970*           you could look at the task id to restrict access if you want
971* Inputs:   major - the major device number assigned by rtems
972*           minor - the minor device number assigned by us
973*           arg - ?????
974* Outputs:  see below
975* Errors:   none
976* Scope:    public API
977****************************************************************************/
978
979rtems_device_driver SciOpen (
980    rtems_device_major_number major,
981    rtems_device_minor_number minor,
982    void * arg
983)
984{
985//printk("%s major=%d minor=%d\r\n", __FUNCTION__,major,minor);
986
987    if (SciInited == 0)                         // must be initialized first!
988    {
989        return RTEMS_NOT_CONFIGURED;
990    }
991
992    if (minor != SCI_MINOR)
993    {
994        return RTEMS_INVALID_NAME;              // verify minor number
995    }
996
997    if (SciOpened == DRIVER_OPENED)
998    {
999        return RTEMS_RESOURCE_IN_USE;           // already opened!
1000    }
1001
1002    SciOpened = DRIVER_OPENED;                  // set the opened flag
1003
1004    return RTEMS_SUCCESSFUL;
1005}
1006
1007
1008/****************************************************************************
1009* Func:     SciClose
1010* Desc:     device driver close routine
1011*           the device must be opened before you can close it
1012*           the device must be closed before someone (else) can open it
1013* Inputs:   major - the major device number
1014*           minor - the minor device number
1015*           arg - ?????
1016* Outputs:  see below
1017* Errors:   none
1018* Scope:    public API
1019****************************************************************************/
1020
1021rtems_device_driver SciClose (
1022    rtems_device_major_number major,
1023    rtems_device_minor_number minor,
1024    void * arg
1025)
1026{
1027//printk("%s major=%d minor=%d\r\n", __FUNCTION__,major,minor);
1028
1029    if (minor != SCI_MINOR)
1030    {
1031        return RTEMS_INVALID_NAME;              // check the minor number
1032    }
1033
1034    if (SciOpened != DRIVER_OPENED)
1035    {
1036        return RTEMS_INCORRECT_STATE;           // must be opened first
1037    }
1038
1039    SciOpened = DRIVER_CLOSED;                  // set the flag
1040
1041    return RTEMS_SUCCESSFUL;
1042}
1043
1044
1045/****************************************************************************
1046* Func:     SciRead
1047* Desc:     device driver read routine
1048*           this function is not meaningful for the laser devices
1049* Inputs:   major - the major device number
1050*           minor - the minor device number
1051*           arg - read/write arguments
1052* Outputs:  see below
1053* Errors:   none
1054* Scope:    public API
1055****************************************************************************/
1056
1057rtems_device_driver SciRead (
1058    rtems_device_major_number major,
1059    rtems_device_minor_number minor,
1060    void *arg
1061)
1062{
1063    rtems_libio_rw_args_t *rw_args;             // ptr to argument struct
1064    uint8_t   *buffer;
1065    uint16_t   length;
1066
1067    rw_args = (rtems_libio_rw_args_t *) arg;    // arguments to read()
1068
1069    if (minor != SCI_MINOR)
1070    {
1071        return RTEMS_INVALID_NAME;              // check the minor number
1072    }
1073
1074    if (SciOpened == DRIVER_CLOSED)
1075    {
1076        return RTEMS_INCORRECT_STATE;           // must be opened first
1077    }
1078
1079    buffer = rw_args->buffer;                   // points to user's buffer
1080
1081    length = rw_args->count;                    // how many bytes they want
1082
1083//  *buffer = SciReadCharWait();                // wait for a character
1084
1085    // if there isn't a character available, wait until one shows up
1086    // or the timeout period expires, which ever happens first
1087
1088    if ( SciRcvBufCount == 0 )                  // no chars
1089    {
1090        // wait for someone to wake me up...
1091        //rtems_task_wake_after(SciReadTimeout);
1092    }
1093
1094    if ( SciRcvBufCount )                       // any characters locally?
1095    {
1096        *buffer = SciRcvBufGetChar();           // get the character
1097
1098        rw_args->bytes_moved = 1;               // how many we actually read
1099    }
1100
1101    return RTEMS_SUCCESSFUL;
1102}
1103
1104
1105/****************************************************************************
1106* Func:     SciWrite
1107* Desc:     device driver write routine
1108*           this function is not meaningful for the laser devices
1109* Inputs:   major - the major device number
1110*           minor - the minor device number
1111*           arg - read/write arguments
1112* Outputs:  see below
1113* Errors:   non3
1114* Scope:    public API
1115****************************************************************************/
1116
1117rtems_device_driver SciWrite (
1118    rtems_device_major_number major,
1119    rtems_device_minor_number minor,
1120    void * arg
1121)
1122{
1123    rtems_libio_rw_args_t *rw_args;             // ptr to argument struct
1124    uint8_t   *buffer;
1125    uint16_t   length;
1126
1127    rw_args = (rtems_libio_rw_args_t *) arg;
1128
1129    if (minor != SCI_MINOR)
1130    {
1131        return RTEMS_INVALID_NAME;              // check the minor number
1132    }
1133
1134    if (SciOpened == DRIVER_CLOSED)
1135    {
1136        return RTEMS_INCORRECT_STATE;           // must be opened first
1137    }
1138
1139    buffer = (uint8_t*)rw_args->buffer;       // points to data
1140
1141    length = rw_args->count;                    // how many bytes
1142
1143    while (length--)
1144    {
1145        SciWriteCharWait(*buffer++);            // send the bytes out
1146    }
1147
1148    rw_args->bytes_moved = rw_args->count;      // how many we wrote
1149
1150    return RTEMS_SUCCESSFUL;
1151}
1152
1153
1154/****************************************************************************
1155* Func:     SciControl
1156* Desc:     device driver control routine
1157*           see below for an example of how to use the ioctl interface
1158* Inputs:   major - the major device number
1159*           minor - the minor device number
1160*           arg - io control args
1161* Outputs:  see below
1162* Errors:   none
1163* Scope:    public API
1164****************************************************************************/
1165
1166rtems_device_driver SciControl (
1167    rtems_device_major_number major,
1168    rtems_device_minor_number minor,
1169    void * arg
1170)
1171{
1172    rtems_libio_ioctl_args_t *args = arg;       // rtems arg struct
1173    uint16_t   command;                         // the cmd to execute
1174    uint16_t   unused;                          // maybe later
1175    uint16_t   *ptr;                            // ptr to user data
1176
1177//printk("%s major=%d minor=%d\r\n", __FUNCTION__,major,minor);
1178
1179    // do some sanity checking
1180
1181    if (minor != SCI_MINOR)
1182    {
1183        return RTEMS_INVALID_NAME;              // check the minor number
1184    }
1185
1186    if (SciOpened == DRIVER_CLOSED)
1187    {
1188        return RTEMS_INCORRECT_STATE;           // must be open first
1189    }
1190
1191    if (args == 0)
1192    {
1193        return RTEMS_INVALID_ADDRESS;           // must have args
1194    }
1195
1196    args->ioctl_return = -1;                    // assume an error
1197
1198    command = args->command;                    // get the command
1199    ptr     = args->buffer;                     // this is an address
1200    unused  = *ptr;                             // brightness
1201
1202    if (command == SCI_SEND_BREAK)              // process the command
1203    {
1204        SciSendBreak();                         // send break char
1205    }
1206
1207    args->ioctl_return = 0;                     // return status
1208
1209    return RTEMS_SUCCESSFUL;
1210}
1211
1212
1213/////////////////////////////////////////////////////////////////////////////
1214//
1215//                              SECTION 5
1216//                       HARDWARE LEVEL ROUTINES
1217//
1218/////////////////////////////////////////////////////////////////////////////
1219
1220/****************************************************************************
1221* Func:     SciSetBaud
1222* Desc:     setup the uart based on the termios modules requests
1223* Inputs:   baud rate
1224* Outputs:  none
1225* Errors:   none
1226* Scope:    private
1227****************************************************************************/
1228
1229static void SciSetBaud(uint32_t   rate)
1230{
1231    uint16_t   value;
1232    uint16_t   save_sccr1;
1233
1234// when you open the console you need to set the termio struct baud rate
1235// it has a default value of 9600, when someone calls tcsetattr it reverts!
1236
1237    SciBaud = rate;                             // save the rate
1238
1239    // calculate the register value as a float and convert to an int
1240    // set baud rate - you must define the system clock constant
1241    // see mrm332.h for an example
1242
1243    value = ( (uint16_t) ( SYS_CLOCK / rate / 32.0 + 0.5 ) & 0x1fff );
1244
1245    save_sccr1 = *SCCR1;                        // save register
1246
1247    // also turns off the xmtr and rcvr
1248
1249    *SCCR1 &= SCI_DISABLE_INT_ALL;              // disable interrupts
1250
1251    *SCCR0 = value;                             // write the register
1252
1253    *SCCR1 = save_sccr1;                        // restore register
1254
1255    return;
1256}
1257
1258
1259/****************************************************************************
1260* Func:     SciSetParity
1261* Desc:     setup the uart based on the termios modules requests
1262* Inputs:   parity
1263* Outputs:  none
1264* Errors:   none
1265* Scope:    private
1266****************************************************************************/
1267
1268static void SciSetParity(uint16_t   parity)
1269{
1270    uint16_t   value;
1271
1272    value = *SCCR1;                             // get the register
1273
1274    if (parity == SCI_PARITY_ODD)
1275    {
1276        value |= SCI_PARITY_ENABLE;             // parity enabled
1277        value |= SCI_PARITY_ODD;                // parity odd
1278    }
1279
1280    else if (parity == SCI_PARITY_EVEN)
1281    {
1282        value |= SCI_PARITY_ENABLE;             // parity enabled
1283        value &= ~SCI_PARITY_ODD;               // parity even
1284    }
1285
1286    else if (parity == SCI_PARITY_NONE)
1287    {
1288        value &= ~SCI_PARITY_ENABLE;            // disabled, most common
1289    }
1290
1291    /* else no changes */
1292
1293    *SCCR1 = value;                             // write the register
1294
1295    return;
1296}
1297
1298
1299/****************************************************************************
1300* Func:     SciSetDataBits
1301* Desc:     setup the uart based on the termios modules requests
1302* Inputs:   data bits
1303* Outputs:  none
1304* Errors:   none
1305* Scope:    private
1306****************************************************************************/
1307
1308static void SciSetDataBits(uint16_t   bits)
1309{
1310    uint16_t   value;
1311
1312    value = *SCCR1;                             // get the register
1313
1314    /* note - the parity setting affects the number of data bits */
1315
1316    if (bits == SCI_9_DATA_BITS)
1317    {
1318        value |= SCI_9_DATA_BITS;               // 9 data bits
1319    }
1320
1321    else if (bits == SCI_8_DATA_BITS)
1322    {
1323        value &= SCI_8_DATA_BITS;               // 8 data bits
1324    }
1325
1326    /* else no changes */
1327
1328    *SCCR1 = value;                             // write the register
1329
1330    return;
1331}
1332
1333
1334/****************************************************************************
1335* Func:     SciDisableAllInterrupts
1336* Func:     SciEnableTransmitInterrupts
1337* Func:     SciEnableReceiveInterrupts
1338* Desc:     handles generation of interrupts by the sci module
1339* Inputs:   none
1340* Outputs:  none
1341* Errors:   none
1342* Scope:    private
1343****************************************************************************/
1344
1345static void inline SciDisableAllInterrupts( void )
1346{
1347    // this also turns off the xmtr and rcvr
1348
1349    *SCCR1 &= SCI_DISABLE_INT_ALL;
1350}
1351
1352static void inline SciEnableReceiveInterrupts( void )
1353{
1354    *SCCR1 |= SCI_ENABLE_INT_RX;
1355}
1356
1357static void inline SciDisableReceiveInterrupts( void )
1358{
1359    *SCCR1 &= SCI_DISABLE_INT_RX;
1360}
1361
1362static void inline SciEnableTransmitInterrupts( void )
1363{
1364    *SCCR1 |= SCI_ENABLE_INT_TX;
1365}
1366
1367static void inline SciDisableTransmitInterrupts( void )
1368{
1369    *SCCR1 &= SCI_DISABLE_INT_TX;
1370}
1371
1372
1373/****************************************************************************
1374* Func:     SciEnableTransmitter, SciDisableTransmitter
1375* Func:     SciEnableReceiver,    SciDisableReceiver
1376* Desc:     turns the transmitter and receiver on and off
1377* Inputs:   none
1378* Outputs:  none
1379* Errors:   none
1380* Scope:    private
1381****************************************************************************/
1382
1383static void inline SciEnableTransmitter( void )
1384{
1385    *SCCR1 |= SCI_ENABLE_XMTR;
1386}
1387
1388static void inline SciDisableTransmitter( void )
1389{
1390    *SCCR1 &= SCI_DISABLE_XMTR;
1391}
1392
1393static void inline SciEnableReceiver( void )
1394{
1395    *SCCR1 |= SCI_ENABLE_RCVR;
1396}
1397
1398static void inline SciDisableReceiver( void )
1399{
1400    *SCCR1 &= SCI_DISABLE_RCVR;
1401}
1402
1403
1404/****************************************************************************
1405* Func:     SciWriteCharWait
1406* Desc:     wait for room in the fifo and then put a char in
1407* Inputs:   a byte to send
1408* Outputs:  none
1409* Errors:   none
1410* Scope:    public
1411****************************************************************************/
1412
1413void SciWriteCharWait(uint8_t   c)
1414{
1415    // poll the fifo, waiting for room for another character
1416
1417    while ( ( *SCSR & SCI_XMTR_AVAILABLE ) == 0 )
1418    {
1419        /* Either we are writing to the fifo faster than
1420         * the uart can clock bytes out onto the cable,
1421         * or we are in flow control (actually no, we
1422         * are ignoring flow control from the other end).
1423         * In the first case, higher baud rates will help.
1424         */
1425      /* relinquish processor while waiting */
1426      rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
1427    }
1428
1429    *SCDR = c;                                  // send the charcter
1430
1431    SciBytesOut++;                              // increment the counter
1432
1433    return;
1434}
1435
1436/****************************************************************************
1437* Func:     SciWriteCharNoWait
1438* Desc:     if no room in the fifo throw the char on the floor
1439* Inputs:   a byte to send
1440* Outputs:  none
1441* Errors:   none
1442* Scope:    public
1443****************************************************************************/
1444
1445void SciWriteCharNoWait(uint8_t   c)
1446{
1447    if ( ( *SCSR & SCI_XMTR_AVAILABLE ) == 0 )
1448    {
1449        return;                                 // no room, throw it away
1450    }
1451
1452    *SCDR = c;                                  // put the char in the fifo
1453
1454    SciBytesOut++;                              // increment the counter
1455
1456    return;
1457}
1458
1459
1460/****************************************************************************
1461* Func:     SciReadCharWait
1462* Desc:     read a character, waiting for one to show up, if need be
1463* Inputs:   none
1464* Outputs:  a character
1465* Errors:   none
1466* Scope:    public
1467****************************************************************************/
1468
1469uint8_t   inline SciReadCharWait( void )
1470{
1471    uint8_t   ch;
1472
1473    while ( SciCharAvailable() == 0 )           // anything there?
1474    {
1475      /* relinquish processor while waiting */
1476      rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
1477    }
1478
1479    // if you have rcv ints enabled, then the isr will probably
1480    // get the character before you will unless you turn off ints
1481    // ie polling and ints don't mix that well
1482
1483    ch = *SCDR;                                 // get the charcter
1484
1485    SciBytesIn++;                               // increment the counter
1486
1487    return ch;                                  // return the char
1488}
1489
1490/****************************************************************************
1491* Func:     SciReadCharNoWait
1492* Desc:     try to get a char but dont wait for one
1493* Inputs:   none
1494* Outputs:  a character or -1 if none
1495* Errors:   none
1496* Scope:    public
1497****************************************************************************/
1498
1499uint8_t   inline SciReadCharNoWait( void )
1500{
1501    uint8_t   ch;
1502
1503    if ( SciCharAvailable() == 0 )              // anything there?
1504        return -1;
1505
1506    ch = *SCDR;                                 // get the character
1507
1508    SciBytesIn++;                               // increment the count
1509
1510    return ch;                                  // return the char
1511}
1512
1513
1514/****************************************************************************
1515* Func:     SciCharAvailable
1516* Desc:     is there a receive character in the data register
1517* Inputs:   none
1518* Outputs:  false if no char available, else true
1519* Errors:   none
1520* Scope:    public
1521****************************************************************************/
1522
1523uint8_t   inline SciCharAvailable( void )
1524{
1525    return ( *SCSR & SCI_RCVR_READY );          // char in data register?
1526}
1527
1528
1529/****************************************************************************
1530* Func:     SciSendBreak
1531* Desc:     send 1 or tow breaks (all zero bits)
1532* Inputs:   none
1533* Outputs:  none
1534* Errors:   none
1535* Scope:    public
1536****************************************************************************/
1537
1538void SciSendBreak( void )
1539{
1540    // From the Motorola QSM reference manual -
1541
1542    // "if SBK is toggled by writing it first to a one and then immediately
1543    // to a zero (in less than one serial frame interval), the transmitter
1544    // sends only one or two break frames before reverting to mark (idle)
1545    // or before commencing to send more data"
1546
1547    *SCCR1 |=  SCI_SEND_BREAK;                  // set the bit
1548
1549    *SCCR1 &= ~SCI_SEND_BREAK;                  // clear the bit
1550
1551    return;
1552}
1553
1554
1555/////////////////////////////////////////////////////////////////////////////
1556//
1557//                             SECTION 6
1558//                             TEST CODE
1559//
1560/////////////////////////////////////////////////////////////////////////////
1561
1562/****************************************************************************
1563* Func:     SciUnitTest
1564* Desc:     test the device driver
1565* Inputs:   nothing
1566* Outputs:  nothing
1567* Scope:    public
1568****************************************************************************/
1569
1570#if 0
1571#define O_RDWR LIBIO_FLAGS_READ_WRITE           // dont like this but...
1572
1573void SciUnitTest()
1574{
1575    uint8_t   byte;                             // a character
1576    uint16_t   fd;                              // file descriptor for device
1577    uint16_t   result;                          // result of ioctl
1578
1579    fd = open("/dev/sci",O_RDWR);               // open the device
1580
1581printk("SCI open fd=%d\r\n",fd);
1582
1583    result = write(fd, "abcd\r\n", 6);          // send a string
1584
1585printk("SCI write result=%d\r\n",result);
1586
1587    result = read(fd, &byte, 1);                // read a byte
1588
1589printk("SCI read result=%d,byte=%x\r\n",result,byte);
1590
1591    return;
1592}
1593#endif
1594
1595
1596/****************************************************************************
1597* Func:     SciPrintStats
1598* Desc:     print out some driver information
1599* Inputs:   nothing
1600* Outputs:  nothing
1601* Scope:    public
1602****************************************************************************/
1603
1604void SciPrintStats ( void )
1605{
1606    printk("\r\n");
1607
1608    printk( "SYS_CLOCK is %2.6f Mhz\r\n\n", SYS_CLOCK / 1000000.0 );
1609
1610    printk( "Current baud rate is %d bps or %d cps\r\n\n", SciBaud, SciBaud / 10 );
1611
1612    printk( "SCI Uart chars in       %8d\r\n", SciBytesIn       );
1613    printk( "SCI Uart chars out      %8d\r\n", SciBytesOut      );
1614    printk( "SCI Uart framing errors %8d\r\n", SciErrorsFraming );
1615    printk( "SCI Uart parity  errors %8d\r\n", SciErrorsParity  );
1616    printk( "SCI Uart overrun errors %8d\r\n", SciErrorsOverrun );
1617    printk( "SCI Uart noise   errors %8d\r\n", SciErrorsNoise   );
1618
1619    return;
1620}
Note: See TracBrowser for help on using the repository browser.