source: rtems/bsps/m68k/mrm332/console/sci.c @ d7d66d7

5
Last change on this file since d7d66d7 was d7d66d7, checked in by Sebastian Huber <sebastian.huber@…>, on 04/19/18 at 04:28:01

bsps: Move console drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

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