source: rtems/c/src/lib/libbsp/m68k/mrm332/console/sci.c @ 1c6926c1

Last change on this file since 1c6926c1 was 1c6926c1, checked in by Kevin Kirspel <kevin-kirspel@…>, on Mar 21, 2017 at 7:39:48 PM

termios: Synchronize with latest FreeBSD headers

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

Close #2897.

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