source: rtems/c/src/lib/libbsp/m68k/mrm332/console/sci.c @ 4377b904

4.104.114.95
Last change on this file since 4377b904 was 4377b904, checked in by Ralf Corsepius <ralf.corsepius@…>, on 08/19/08 at 10:23:15

2008-08-19 Ralf Corsépius <ralf.corsepius@…>

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