Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:47

0001 /*****************************************************************************
0002 * File:     sci.c
0003 *
0004 * Desc:     This file contains the console IO routines for the SCI port.
0005 *           There are two interfaces in this module. One is for the rtems
0006 *           termios/console code and the other is a device driver interface.
0007 *           This module works together with the termio module which is
0008 *           sometimes referred to as the "line disciplines" which implements
0009 *           terminal i/o processing like tabs, backspaces, and newlines.
0010 *           The rtems printf uses interrupt io and the rtems printk routine
0011 *           uses polled io which is better for debugging.
0012 *
0013 * Index:    Documentation
0014 *           Section A  - Include Files
0015 *           Section B  - Manifest Constants
0016 *           Section C  - External Data
0017 *           Section D  - External Functions
0018 *           Section E  - Local Functions
0019 *           Section F  - Local Variables
0020 *           Section G  - A circular data buffer for rcv chars
0021 *           Section H  - RTEMS termios callbacks for the interrupt api
0022 *           Section I  - RTEMS termios callbacks for the polled api
0023 
0024 *           Section 0  - Miscellaneous routines
0025 *           Section 1  - Routines to manipulate the circular buffer
0026 *           Section 2  - Interrupt based entry points for the termios module
0027 *           Section 3  - Polling based entry points for the termios module
0028 *           Section 4  - Device driver public api entry points
0029 *           Section 5  - Hardware level routines
0030 *           Section 6  - Testing and debugging code
0031 *
0032 * Refer:    Motorola QSM Reference Manual - Chapter 5 - SCI sub-module
0033 *
0034 * Note:     See bsp.h,confdefs.h,system.h for installing drivers into RTEMS.
0035 *
0036 *****************************************************************************/
0037 
0038 /*****************************************************************************
0039   Overview of serial port console terminal input/output
0040 *****************************************************************************/
0041 
0042 /*
0043    +-----------+                               +---------+
0044    |    app    |                               |   app   |
0045    +-----------+                               +---------+
0046          |                                          |
0047          | (printf,scanf,etc.)                      |
0048          v                                          |
0049    +-----------+                                    |
0050    |    libc   |                                    |
0051    +-----------+                                    |
0052          |                                          |
0053          |                                          |
0054          |     (open,close,read,write,ioctl)        |
0055    ======|==========================================|========================
0056          | /dev/console                             | /dev/sci
0057          | (stdin,stdout,stderr)                    |
0058    ======|==========================================|========================
0059          |                                          |
0060          |                                          |
0061          v                                          v
0062    +-----------+         +-----------+         +---------+
0063    |  console  |  <--->  |  termios  |  <--->  |   sci   |
0064    |  driver   |         |  module   |         |  driver |
0065    +-----------+         +-----------+         +---------+
0066                                                     |
0067                                                     |
0068                                                     v
0069                                                +---------+
0070                                                |         |
0071                                                |  uart   |
0072                                                |         |
0073                                                +---------+
0074 */
0075 
0076 
0077 /*****************************************************************************
0078   Section A - Include Files
0079 *****************************************************************************/
0080 
0081 #include <rtems.h>
0082 #include <bsp.h>
0083 #include <rtems/bspIo.h>
0084 #include <stdio.h>
0085 #include <rtems/libio.h>
0086 #include <libchip/serial.h>
0087 #include <libchip/sersupp.h>
0088 #include "sci.h"
0089 #include <rtems/m68k/qsm.h>
0090 #include <inttypes.h>
0091 /*#include "../misc/include/cpu332.h" */
0092 
0093 /*****************************************************************************
0094   Section B - Manifest Constants
0095 *****************************************************************************/
0096 
0097 #define SCI_MINOR       0                   /* minor device number */
0098 
0099 /* IMPORTANT - if the device driver api is opened, it means the sci is being
0100  * used for direct hardware access, so other users (like termios) get ignored
0101  */
0102 #define DRIVER_CLOSED   0                   /* the device driver api is closed */
0103 #define DRIVER_OPENED   1                   /* the device driver api is opened */
0104 
0105 /* system clock definitions, i dont have documentation on this... */
0106 
0107 #if 0 /* Not needed, this is provided in mrm332.h */
0108 #define XTAL            32768.0    /* crystal frequency in Hz */
0109 #define NUMB_W          0          /* system clock parameters */
0110 #define NUMB_X          1
0111 #define NUMB_Y          0x38       /* for 14.942 Mhz */
0112 #define NUMB_Y          0x3F       /* for 16.777 Mhz */
0113 
0114 #define SYS_CLOCK       (XTAL * 4.0 * (NUMB_Y+1) * (1 << (2 * NUMB_W + NUMB_X)))
0115 
0116 #endif
0117 
0118 
0119 /*****************************************************************************
0120   Section C - External Data
0121 *****************************************************************************/
0122 
0123 
0124 
0125 /*****************************************************************************
0126   Section D - External Functions
0127 *****************************************************************************/
0128 
0129 
0130 
0131 /*****************************************************************************
0132   Section E - Local Functions
0133 *****************************************************************************/
0134 
0135 void SCI_output_char(char c);
0136 
0137 /*rtems_isr SciIsr( rtems_vector_number vector );   interrupt handler */
0138 
0139 const rtems_termios_callbacks * SciGetTermiosHandlers( int32_t   polled );
0140 
0141 rtems_device_driver SciInitialize(                     /* device driver api */
0142     rtems_device_major_number, rtems_device_minor_number, void *);
0143 rtems_device_driver SciOpen(                           /* device driver api */
0144     rtems_device_major_number, rtems_device_minor_number, void *);
0145 rtems_device_driver SciClose(                          /* device driver api */
0146     rtems_device_major_number, rtems_device_minor_number, void *);
0147 rtems_device_driver SciRead(                           /* device driver api */
0148     rtems_device_major_number, rtems_device_minor_number, void *);
0149 rtems_device_driver SciWrite(                          /* device driver api */
0150     rtems_device_major_number, rtems_device_minor_number, void *);
0151 rtems_device_driver SciControl(                        /* device driver api */
0152     rtems_device_major_number, rtems_device_minor_number, void *);
0153 rtems_device_driver SciRead (
0154     rtems_device_major_number, rtems_device_minor_number, void *);
0155 
0156 rtems_isr SciIsr( rtems_vector_number vector );
0157 
0158 int     SciInterruptOpen(int, int, void *);               /* termios api */
0159 int     SciInterruptClose(int, int, void *);              /* termios api */
0160 ssize_t SciInterruptWrite(int, const char *, size_t);     /* termios api */
0161 
0162 int     SciSetAttributes(int, const struct termios*);     /* termios api */
0163 int     SciPolledOpen(int, int, void *);                  /* termios api */
0164 int     SciPolledClose(int, int, void *);                 /* termios api */
0165 int     SciPolledRead(int);                               /* termios api */
0166 ssize_t SciPolledWrite(int, const char *, size_t);        /* termios api */
0167 
0168 static void SciSetBaud(uint32_t   rate);                /* hardware routine */
0169 static void SciSetDataBits(uint16_t   bits);            /* hardware routine */
0170 static void SciSetParity(uint16_t   parity);            /* hardware routine */
0171 
0172 static void inline SciDisableAllInterrupts( void );     /* hardware routine */
0173 static void inline SciDisableTransmitInterrupts( void );/* hardware routine */
0174 static void inline SciDisableReceiveInterrupts( void ); /* hardware routine */
0175 
0176 static void inline SciEnableTransmitInterrupts( void ); /* hardware routine */
0177 static void inline SciEnableReceiveInterrupts( void );  /* hardware routine */
0178 
0179 static void inline SciDisableReceiver( void );          /* hardware routine */
0180 static void inline SciDisableTransmitter( void );       /* hardware routine */
0181 
0182 static void inline SciEnableReceiver( void );           /* hardware routine */
0183 static void inline SciEnableTransmitter( void );        /* hardware routine */
0184 
0185 void SciWriteCharWait  ( uint8_t );                     /* hardware routine */
0186 void SciWriteCharNoWait( uint8_t );                     /* hardware routine */
0187 
0188 uint8_t   inline SciCharAvailable( void );              /* hardware routine */
0189 
0190 static uint8_t   inline SciReadCharWait( void );        /* hardware routine */
0191 static uint8_t   inline SciReadCharNoWait( void );      /* hardware routine */
0192 
0193 void SciSendBreak( void );                              /* test routine */
0194 
0195 static int8_t   SciRcvBufGetChar(void);                 /* circular rcv buf */
0196 static void    SciRcvBufPutChar( uint8_t);              /* circular rcv buf */
0197 #if 0
0198 static void    SciRcvBufFlush( void );                  /* unused routine */
0199 #endif
0200 
0201 void SciUnitTest(void);                                 /* test routine */
0202 void SciPrintStats(void);                               /* test routine */
0203 
0204 
0205 /*****************************************************************************
0206   Section F - Local Variables
0207 *****************************************************************************/
0208 
0209 static struct rtems_termios_tty *SciTermioTty;
0210 
0211 static uint8_t   SciInited = 0;             /* has the driver been inited */
0212 
0213 static uint8_t   SciOpened;                 /* has the driver been opened */
0214 
0215 static uint8_t   SciMajor;                  /* major device number */
0216 
0217 static uint16_t   SciBaud;                  /* current value in baud register */
0218 
0219 static uint32_t   SciBytesIn  = 0;          /* bytes received */
0220 static uint32_t   SciBytesOut = 0;          /* bytes transmitted */
0221 
0222 static uint32_t   SciErrorsParity  = 0;     /* error counter */
0223 static uint32_t   SciErrorsNoise   = 0;     /* error counter */
0224 static uint32_t   SciErrorsFraming = 0;     /* error counter */
0225 static uint32_t   SciErrorsOverrun = 0;     /* error counter */
0226 
0227 #if defined(CONSOLE_SCI)
0228 
0229 /* this is what rtems printk uses to do polling based output */
0230 
0231 BSP_output_char_function_type      BSP_output_char = SCI_output_char;
0232 BSP_polling_getchar_function_type  BSP_poll_char   = NULL;
0233 
0234 #endif
0235 
0236 /*****************************************************************************
0237   Section G - A circular buffer for rcv chars when the driver interface is used.
0238 *****************************************************************************/
0239 
0240 /* it is trivial to wrap your buffer pointers when size is a power of two */
0241 
0242 #define SCI_RCV_BUF_SIZE        256         /* must be a power of 2 !!! */
0243 
0244 /* if someone opens the sci device using the device driver interface,
0245  * then the receive data interrupt handler will put characters in this buffer
0246  * instead of sending them up to the termios module for the console
0247  */
0248 static uint8_t   SciRcvBuffer[SCI_RCV_BUF_SIZE];
0249 
0250 static uint8_t   SciRcvBufPutIndex = 0; /* array index to put in next char */
0251 
0252 static uint8_t   SciRcvBufGetIndex = 0; /* array index to take out next char */
0253 
0254 static uint16_t  SciRcvBufCount = 0;   /* how many bytes are in the buffer */
0255 
0256 
0257 
0258 /*****************************************************************************
0259   Section H - RTEMS termios callbacks for the interrupt version of the driver
0260 *****************************************************************************/
0261 
0262 static const rtems_termios_callbacks SciInterruptCallbacks =
0263 {
0264     SciInterruptOpen,                       /* first open */
0265     SciInterruptClose,                      /* last close */
0266     NULL,                                   /* polled read (not required) */
0267     SciInterruptWrite,                      /* write */
0268     SciSetAttributes,                       /* set attributes */
0269     NULL,                                   /* stop remote xmit */
0270     NULL,                                   /* start remote xmit */
0271     TERMIOS_IRQ_DRIVEN                      /* output uses interrupts */
0272 };
0273 
0274 /*****************************************************************************
0275   Section I - RTEMS termios callbacks for the polled version of the driver
0276 *****************************************************************************/
0277 
0278 static const rtems_termios_callbacks SciPolledCallbacks =
0279 {
0280     SciPolledOpen,                          /* first open */
0281     SciPolledClose,                         /* last close */
0282     SciPolledRead,                          /* polled read */
0283     SciPolledWrite,                         /* write */
0284     SciSetAttributes,                       /* set attributes */
0285     NULL,                                   /* stop remote xmit */
0286     NULL,                                   /* start remote xmit */
0287     TERMIOS_POLLED                          /* output uses interrupts */
0288 };
0289 
0290 
0291 /*
0292  *                              SECTION 0
0293  *                        MISCELLANEOUS ROUTINES
0294  */
0295 
0296 /****************************************************************************
0297  * Func:     SCI_output_char
0298  * Desc:     used by rtems printk function to send a char to the uart
0299  * Inputs:   the character to transmit
0300  * Outputs:  none
0301  * Errors:   none
0302  * Scope:    public
0303  ****************************************************************************/
0304 
0305 void SCI_output_char(char c)
0306 {
0307 /*  ( minor device number, pointer to the character, length ) */
0308 
0309     SciPolledWrite( SCI_MINOR, &c, 1);
0310 
0311     return;
0312 }
0313 
0314 
0315 /****************************************************************************
0316 * Func:     SciGetTermiosHandlers
0317 * Desc:     returns a pointer to the table of serial io functions
0318 *           this is called from console_open with polled set to false
0319 * Inputs:   flag indicating whether we want polled or interrupt driven io
0320 * Outputs:  pointer to function table
0321 * Errors:   none
0322 * Scope:    public
0323 ****************************************************************************/
0324 
0325 const rtems_termios_callbacks * SciGetTermiosHandlers( int32_t   polled )
0326 {
0327     if ( polled )
0328     {
0329         return &SciPolledCallbacks;             /* polling based */
0330     }
0331     else
0332     {
0333         return &SciInterruptCallbacks;          /* interrupt driven */
0334     }
0335 }
0336 
0337 
0338 /****************************************************************************
0339 * Func:     SciIsr
0340 * Desc:     interrupt handler for serial communications interface
0341 * Inputs:   vector number - unused
0342 * Outputs:  none
0343 * Errors:   none
0344 * Scope:    public API
0345 ****************************************************************************/
0346 
0347 rtems_isr SciIsr( rtems_vector_number vector )
0348 {
0349     uint8_t   ch;
0350 
0351     if ( (*SCSR) & SCI_ERROR_PARITY  )   SciErrorsParity  ++;
0352     if ( (*SCSR) & SCI_ERROR_FRAMING )   SciErrorsFraming ++;
0353     if ( (*SCSR) & SCI_ERROR_NOISE   )   SciErrorsNoise   ++;
0354     if ( (*SCSR) & SCI_ERROR_OVERRUN )   SciErrorsOverrun ++;
0355 
0356     /* see if it was a transmit interrupt */
0357     /* data reg empty, xmt complete */
0358     if ( ( *SCCR1 & SCI_ENABLE_INT_TX ) && ( (*SCSR) & SCI_XMTR_AVAILABLE ) )
0359     {
0360         SciDisableTransmitInterrupts();
0361 
0362         /* tell termios module that the charcter was sent */
0363         /* he will call us later to transmit more if there are any */
0364 
0365         if (rtems_termios_dequeue_characters( SciTermioTty, 1 ))
0366         {
0367             /* there are more bytes to transmit so enable TX interrupt */
0368 
0369             SciEnableTransmitInterrupts();
0370         }
0371     }
0372 
0373     /* see if it was a receive interrupt */
0374     /* on the sci uart we just get one character per interrupt */
0375 
0376     while (  SciCharAvailable() )               /* char in data register? */
0377     {
0378         ch = SciReadCharNoWait();               /* get the char from the uart */
0379 
0380         /* IMPORTANT!!! */
0381         /* either send it to the termios module or keep it locally */
0382 
0383         if ( SciOpened == DRIVER_OPENED )       /* the driver is open */
0384         {
0385             SciRcvBufPutChar(ch);               /* keep it locally */
0386         }
0387         else                                    /* put in termios buffer */
0388         {
0389             char c = (char) ch;
0390             rtems_termios_enqueue_raw_characters( SciTermioTty, &c, 1 );
0391         }
0392 
0393         *SCSR &= SCI_CLEAR_RX_INT;              /* clear the interrupt */
0394     }
0395 }
0396 
0397 
0398 /*
0399  *                              SECTION 1
0400  *                ROUTINES TO MANIPULATE THE CIRCULAR BUFFER
0401  */
0402 
0403 /****************************************************************************
0404 * Func:     SciRcvBufGetChar
0405 * Desc:     read a character from the circular buffer
0406 *           make sure there is data before you call this!
0407 * Inputs:   none
0408 * Outputs:  the character or -1
0409 * Errors:   none
0410 * Scope:    private
0411 ****************************************************************************/
0412 
0413 static int8_t   SciRcvBufGetChar(void)
0414 {
0415     rtems_interrupt_level level;
0416     uint8_t   ch;
0417 
0418     if ( SciRcvBufCount == 0 )
0419     {
0420         rtems_fatal_error_occurred(0xDEAD);     /* check the count first! */
0421     }
0422 
0423     rtems_interrupt_disable( level );           /* disable interrupts */
0424 
0425     ch = SciRcvBuffer[SciRcvBufGetIndex];       /* get next byte */
0426 
0427     SciRcvBufGetIndex++;                        /* bump the index */
0428 
0429     SciRcvBufGetIndex &= SCI_RCV_BUF_SIZE - 1;  /* and wrap it */
0430 
0431     SciRcvBufCount--;                           /* decrement counter */
0432 
0433     rtems_interrupt_enable( level );            /* restore interrupts */
0434 
0435     return ch;                                  /* return the char */
0436 }
0437 
0438 
0439 /****************************************************************************
0440 * Func:     SciRcvBufPutChar
0441 * Desc:     put a character into the rcv data circular buffer
0442 * Inputs:   the character
0443 * Outputs:  none
0444 * Errors:   none
0445 * Scope:    private
0446 ****************************************************************************/
0447 
0448 static void SciRcvBufPutChar( uint8_t   ch )
0449 {
0450     rtems_interrupt_level level;
0451 
0452     if ( SciRcvBufCount == SCI_RCV_BUF_SIZE )   /* is there room? */
0453     {
0454         return;                                 /* no, throw it away */
0455     }
0456 
0457     rtems_interrupt_disable( level );           /* disable interrupts */
0458 
0459     SciRcvBuffer[SciRcvBufPutIndex] = ch;       /* put it in the buf */
0460 
0461     SciRcvBufPutIndex++;                        /* bump the index */
0462 
0463     SciRcvBufPutIndex &= SCI_RCV_BUF_SIZE - 1;  /* and wrap it */
0464 
0465     SciRcvBufCount++;                           /* increment counter */
0466 
0467     rtems_interrupt_enable( level );            /* restore interrupts */
0468 
0469     return;                                     /* return */
0470 }
0471 
0472 
0473 /****************************************************************************
0474 * Func:     SciRcvBufFlush
0475 * Desc:     completely reset and clear the rcv buffer
0476 * Inputs:   none
0477 * Outputs:  none
0478 * Errors:   none
0479 * Scope:    private
0480 ****************************************************************************/
0481 
0482 #if 0                                           /* prevents compiler warning */
0483 static void SciRcvBufFlush( void )
0484 {
0485     rtems_interrupt_level level;
0486 
0487     rtems_interrupt_disable( level );           /* disable interrupts */
0488 
0489     memset( SciRcvBuffer, 0, sizeof(SciRcvBuffer) );
0490 
0491     SciRcvBufPutIndex = 0;                      /* clear */
0492 
0493     SciRcvBufGetIndex = 0;                      /* clear */
0494 
0495     SciRcvBufCount = 0;                         /* clear */
0496 
0497     rtems_interrupt_enable( level );            /* restore interrupts */
0498 
0499     return;                                     /* return */
0500 }
0501 #endif
0502 
0503 
0504 /*
0505  *
0506  *                              SECTION 2
0507  *            INTERRUPT BASED ENTRY POINTS FOR THE TERMIOS MODULE
0508  */
0509 
0510 /****************************************************************************
0511 * Func:     SciInterruptOpen
0512 * Desc:     open routine for the interrupt based device driver
0513 *           Default state is 9600 baud, 8 bits, No parity, and 1 stop bit. ??
0514 **CHANGED** Default baud rate is now 19200, 8N1
0515 *           called from rtems_termios_open which is called from console_open
0516 * Inputs:   major - device number
0517 *           minor - device number
0518 *           args - points to terminal info
0519 * Outputs:  success/fail
0520 * Errors:   none
0521 * Scope:    public API
0522 ****************************************************************************/
0523 
0524 int   SciInterruptOpen(
0525     int    major,
0526     int    minor,
0527     void  *arg
0528 )
0529 {
0530     rtems_libio_open_close_args_t * args = arg;
0531     rtems_isr_entry old_vector;
0532 
0533     if ( minor != SCI_MINOR )                   /* check minor device num */
0534     {
0535         return -1;
0536     }
0537 
0538     if ( !args )                                /* must have args */
0539     {
0540         return -1;
0541     }
0542 
0543     SciTermioTty = args->iop->data1;            /* save address of struct */
0544 
0545     SciDisableAllInterrupts();                  /* turn off sci interrupts */
0546 
0547     /* THIS IS ACTUALLY A BAD THING - SETTING LINE PARAMETERS HERE */
0548     /* IT SHOULD BE DONE THROUGH TCSETATTR() WHEN THE CONSOLE IS OPENED!!! */
0549 
0550 /*  SciSetBaud(115200);                         set the baud rate */
0551 /*  SciSetBaud( 57600);                         set the baud rate */
0552 /*  SciSetBaud( 38400);                         set the baud rate */
0553 /*  SciSetBaud( 19200);                         set the baud rate */
0554     SciSetBaud(  9600);                      /* set the baud rate */
0555 
0556     SciSetParity(SCI_PARITY_NONE);              /* set parity to none */
0557 
0558     SciSetDataBits(SCI_8_DATA_BITS);            /* set data bits to 8 */
0559 
0560     /* Install our interrupt handler into RTEMS. */
0561     /* 68 is an unused user-defined vector.  Note that the vector must be */
0562     /* even - it sets the low bit for SPI interrupts, and clears it for */
0563     /* SCI interrupts.  Also note that vector 66 is used by CPU32bug on */
0564     /* the mrm332. */
0565 
0566     rtems_interrupt_catch( SciIsr, 68, &old_vector );
0567 
0568     *QSMCR = (*QSMCR & ~IARB) | 1; // Is 1 a good value for qsm iarb?
0569     *QIVR  = 68;
0570     *QILR &= 0xf8;
0571     *QILR |= 0x06 & 0x07;
0572 
0573     SciEnableTransmitter();                     /* enable the transmitter */
0574 
0575     SciEnableReceiver();                        /* enable the receiver */
0576 
0577     SciEnableReceiveInterrupts();               /* enable rcv interrupts */
0578 
0579     return RTEMS_SUCCESSFUL;
0580 }
0581 
0582 
0583 /****************************************************************************
0584 * Func:     SciInterruptClose
0585 * Desc:     close routine called by the termios module
0586 * Inputs:   major - device number
0587 *           minor - device number
0588 *           args - unused
0589 * Outputs:  success/fail
0590 * Errors:   none
0591 * Scope:    public - termio entry point
0592 ****************************************************************************/
0593 
0594 int   SciInterruptClose(
0595     int    major,
0596     int    minor,
0597     void  *arg
0598 )
0599 {
0600     SciDisableAllInterrupts();
0601 
0602     return RTEMS_SUCCESSFUL;
0603 }
0604 
0605 
0606 /****************************************************************************
0607 * Func:     SciInterruptWrite
0608 * Desc:     writes data to the uart using transmit interrupts
0609 * Inputs:   minor - device number
0610 *           buf - points to the data
0611 *           len - number of bytes to send
0612 * Outputs:  success/fail
0613 * Errors:   none
0614 * Scope:    public API
0615 ****************************************************************************/
0616 
0617 ssize_t   SciInterruptWrite(
0618     int         minor,
0619     const char *buf,
0620     size_t      len
0621 )
0622 {
0623     /* We are using interrupt driven output so termios only sends us */
0624     /* one character at a time. The sci does not have a fifo. */
0625 
0626     if ( !len )                                 /* no data? */
0627     {
0628         return -1;                              /* return error */
0629     }
0630 
0631     if ( minor != SCI_MINOR )                   /* check the minor dev num */
0632     {
0633         return -1;                              /* return error */
0634     }
0635 
0636     if ( SciOpened == DRIVER_OPENED )           /* is the driver api open? */
0637     {
0638         return -1;                              /* yep, throw this away */
0639     }
0640 
0641     SciWriteCharNoWait(*buf);                   /* try to send a char */
0642 
0643     *SCSR &= SCI_CLEAR_TDRE;                    /* clear tx data reg empty flag */
0644 
0645     SciEnableTransmitInterrupts();              /* enable the tx interrupt */
0646 
0647     return 0;                                   /* return success */
0648 }
0649 
0650 
0651 /****************************************************************************
0652 * Func:     SciSetAttributes
0653 * Desc:     setup the uart based on the termios modules requests
0654 * Inputs:   minor - device number
0655 *           t - pointer to the termios info struct
0656 * Outputs:  none
0657 * Errors:   none
0658 * Scope:    public API
0659 ****************************************************************************/
0660 
0661 int   SciSetAttributes(
0662     int                   minor,
0663     const struct termios *t
0664 )
0665 {
0666     uint32_t    baud_requested;
0667     uint32_t    sci_rate = 0;
0668     uint16_t    sci_parity = 0;
0669     uint16_t    sci_databits = 0;
0670 
0671     if ( minor != SCI_MINOR )                   /* check the minor dev num */
0672     {
0673         return -1;                              /* return error */
0674     }
0675 
0676     /* if you look closely you will see this is the only thing we use */
0677     /* set the baud rate */
0678 
0679     baud_requested = t->c_ospeed;               /* baud rate */
0680 
0681     if (!baud_requested)
0682     {
0683         baud_requested = B9600;                /* default to 9600 baud */
0684        /* baud_requested = B19200;                default to 19200 baud */
0685     }
0686 
0687     sci_rate = rtems_termios_baud_to_number( baud_requested );
0688 
0689     /* parity error detection */
0690 
0691     if (t->c_cflag & PARENB)                    /* enable parity detection? */
0692     {
0693         if (t->c_cflag & PARODD)
0694         {
0695             sci_parity = SCI_PARITY_ODD;        /* select odd parity */
0696         }
0697         else
0698         {
0699             sci_parity = SCI_PARITY_EVEN;       /* select even parity */
0700         }
0701     }
0702     else
0703     {
0704         sci_parity = SCI_PARITY_NONE;           /* no parity, most common */
0705     }
0706 
0707     /*  set the number of data bits, 8 is most common */
0708 
0709     if (t->c_cflag & CSIZE)                     /* was it specified? */
0710     {
0711         switch (t->c_cflag & CSIZE)
0712         {
0713             case CS8:   sci_databits = SCI_8_DATA_BITS;   break;
0714             default :   sci_databits = SCI_9_DATA_BITS;   break;
0715         }
0716     }
0717     else
0718     {
0719         sci_databits = SCI_8_DATA_BITS;         /* default to 8 data bits */
0720     }
0721 
0722     /*  the number of stop bits; always 1 for SCI */
0723 
0724     if (t->c_cflag & CSTOPB)
0725     {
0726         /* do nothing */
0727     }
0728 
0729     /* setup the hardware with these serial port parameters */
0730 
0731     SciSetBaud(sci_rate);                       /* set the baud rate */
0732     SciSetParity(sci_parity);                   /* set the parity type */
0733     SciSetDataBits(sci_databits);               /* set the data bits */
0734 
0735     return RTEMS_SUCCESSFUL;
0736 }
0737 
0738 
0739 /*
0740  *
0741  *                              SECTION 3
0742  *            POLLING BASED ENTRY POINTS FOR THE TERMIOS MODULE
0743  */
0744 
0745 /****************************************************************************
0746 * Func:     SciPolledOpen
0747 * Desc:     open routine for the polled i/o version of the driver
0748 *           called from rtems_termios_open which is called from console_open
0749 * Inputs:   major - device number
0750 *           minor - device number
0751 *           args - points to terminal info struct
0752 * Outputs:  success/fail
0753 * Errors:   none
0754 * Scope:    public - termios entry point
0755 ****************************************************************************/
0756 
0757 int   SciPolledOpen(
0758     int   major,
0759     int   minor,
0760     void *arg
0761 )
0762 {
0763     rtems_libio_open_close_args_t * args = arg;
0764 
0765     if ( minor != SCI_MINOR )                   /* check minor device num */
0766     {
0767         return -1;
0768     }
0769 
0770     if ( !args )                                /* must have args */
0771     {
0772         return -1;
0773     }
0774 
0775     SciTermioTty = args->iop->data1;            /* Store tty pointer */
0776 
0777     SciDisableAllInterrupts();                  /* don't generate interrupts */
0778 
0779     /* THIS IS ACTUALLY A BAD THING - SETTING LINE PARAMETERS HERE */
0780     /* IT SHOULD BE DONE THROUGH TCSETATTR() WHEN THE CONSOLE IS OPENED!!! */
0781 
0782 /*  SciSetBaud(115200);                            set the baud rate */
0783 /*  SciSetBaud( 57600);                            set the baud rate */
0784 /*  SciSetBaud( 38400);                            set the baud rate */
0785 /*  SciSetBaud( 19200);                          * set the baud rate */
0786     SciSetBaud(  9600);                         /* set the baud rate */
0787 
0788     SciSetParity(SCI_PARITY_NONE);              /* set no parity */
0789 
0790     SciSetDataBits(SCI_8_DATA_BITS);            /* set 8 data bits */
0791 
0792     SciEnableTransmitter();                     /* enable the xmitter */
0793 
0794     SciEnableReceiver();                        /* enable the rcvr */
0795 
0796     return RTEMS_SUCCESSFUL;
0797 }
0798 
0799 
0800 /****************************************************************************
0801 * Func:     SciPolledClose
0802 * Desc:     close routine for the device driver, same for both
0803 * Inputs:   major - device number
0804 *           minor - device number
0805 *           args - unused
0806 * Outputs:  success/fail
0807 * Errors:   none
0808 * Scope:    public termios API
0809 ****************************************************************************/
0810 
0811 int   SciPolledClose(
0812     int    major,
0813     int    minor,
0814     void  *arg
0815 )
0816 {
0817     SciDisableAllInterrupts();
0818 
0819     return RTEMS_SUCCESSFUL;
0820 }
0821 
0822 
0823 /****************************************************************************
0824 * Func:     SciPolledRead
0825 * Desc:     polling based read routine for the uart
0826 * Inputs:   minor - device number
0827 * Outputs:  error or the character read
0828 * Errors:   none
0829 * Scope:    public API
0830 ****************************************************************************/
0831 
0832 int   SciPolledRead(
0833     int   minor
0834 )
0835 {
0836     if ( minor != SCI_MINOR )               /* check the type-punned dev num */
0837     {
0838         return -1;                          /* return error */
0839     }
0840 
0841     if ( SciCharAvailable() )               /* if a char is available */
0842     {
0843         return SciReadCharNoWait();         /* read the rx data register */
0844     }
0845 
0846     return -1;                              /* return error */
0847 }
0848 
0849 
0850 /****************************************************************************
0851 * Func:     SciPolledWrite
0852 * Desc:     writes out characters in polled mode, waiting for the uart
0853 *           check in console_open, but we only seem to use interrupt mode
0854 * Inputs:   minor - device number
0855 *           buf - points to the data
0856 *           len - how many bytes
0857 * Outputs:  error or number of bytes written
0858 * Errors:   none
0859 * Scope:    public termios API
0860 ****************************************************************************/
0861 
0862 ssize_t SciPolledWrite(
0863     int         minor,
0864     const char *buf,
0865     size_t      len
0866 )
0867 {
0868     ssize_t written = 0;
0869 
0870     if ( minor != SCI_MINOR )                   /* check minor device num */
0871     {
0872         return -1;
0873     }
0874 
0875     if ( SciOpened == DRIVER_OPENED )           /* is the driver api open? */
0876     {
0877         return -1;                              /* toss the data */
0878     }
0879 
0880     /* send each byte in the string out the port */
0881 
0882     while ( written < len )
0883     {
0884         SciWriteCharWait(*buf++);               /* send a byte */
0885 
0886         written++;                              /* increment counter */
0887     }
0888 
0889     return written;                             /* return count */
0890 }
0891 
0892 
0893 /*
0894  *
0895  *                              SECTION 4
0896  *                 DEVICE DRIVER PUBLIC API ENTRY POINTS
0897  */
0898 
0899 /****************************************************************************
0900 * Func:     SciInit
0901 * Desc:     Initialize the lasers device driver and hardware
0902 * Inputs:   major - the major device number which is assigned by rtems
0903 *           minor - the minor device number which is undefined at this point
0904 *           arg - ?????
0905 * Outputs:  RTEMS_SUCCESSFUL
0906 * Errors:   None.
0907 * Scope:    public API
0908 ****************************************************************************/
0909 
0910 rtems_device_driver SciInitialize (
0911     rtems_device_major_number major,
0912     rtems_device_minor_number minor,
0913     void * arg
0914 )
0915 {
0916 /*     rtems_status_code status; */
0917 
0918 /*printk("%s\r\n", __FUNCTION__); */
0919 
0920     /* register the SCI device name for termios console i/o
0921      * this is done over in console.c which doesn't seem exactly right
0922      * but there were problems doing it here...
0923      */
0924 
0925 /*  status = rtems_io_register_name( "/dev/sci", major, 0 ); */
0926 
0927 /*  if (status != RTEMS_SUCCESSFUL) */
0928 /*      rtems_fatal_error_occurred(status); */
0929 
0930     SciMajor = major;                           /* save the rtems major number */
0931 
0932     SciOpened = DRIVER_CLOSED;                  /* initial state is closed */
0933 
0934     /* if you have an interrupt handler, install it here */
0935 
0936     SciInited = 1;                              /* set the inited flag */
0937 
0938     return RTEMS_SUCCESSFUL;
0939 }
0940 
0941 
0942 /****************************************************************************
0943 * Func:     SciOpen
0944 * Desc:     device driver open routine
0945 *           you must open a device before you can anything else
0946 *           only one process can have the device opened at a time
0947 *           you could look at the task id to restrict access if you want
0948 * Inputs:   major - the major device number assigned by rtems
0949 *           minor - the minor device number assigned by us
0950 *           arg - ?????
0951 * Outputs:  see below
0952 * Errors:   none
0953 * Scope:    public API
0954 ****************************************************************************/
0955 
0956 rtems_device_driver SciOpen (
0957     rtems_device_major_number major,
0958     rtems_device_minor_number minor,
0959     void * arg
0960 )
0961 {
0962 /*printk("%s major=%d minor=%d\r\n", __FUNCTION__,major,minor); */
0963 
0964     if (SciInited == 0)                         /* must be initialized first! */
0965     {
0966         return RTEMS_NOT_CONFIGURED;
0967     }
0968 
0969     if (minor != SCI_MINOR)
0970     {
0971         return RTEMS_INVALID_NAME;              /* verify minor number */
0972     }
0973 
0974     if (SciOpened == DRIVER_OPENED)
0975     {
0976         return RTEMS_RESOURCE_IN_USE;           /* already opened! */
0977     }
0978 
0979     SciOpened = DRIVER_OPENED;                  /* set the opened flag */
0980 
0981     return RTEMS_SUCCESSFUL;
0982 }
0983 
0984 
0985 /****************************************************************************
0986 * Func:     SciClose
0987 * Desc:     device driver close routine
0988 *           the device must be opened before you can close it
0989 *           the device must be closed before someone (else) can open it
0990 * Inputs:   major - the major device number
0991 *           minor - the minor device number
0992 *           arg - ?????
0993 * Outputs:  see below
0994 * Errors:   none
0995 * Scope:    public API
0996 ****************************************************************************/
0997 
0998 rtems_device_driver SciClose (
0999     rtems_device_major_number major,
1000     rtems_device_minor_number minor,
1001     void * arg
1002 )
1003 {
1004 /*printk("%s major=%d minor=%d\r\n", __FUNCTION__,major,minor); */
1005 
1006     if (minor != SCI_MINOR)
1007     {
1008         return RTEMS_INVALID_NAME;              /* check the minor number */
1009     }
1010 
1011     if (SciOpened != DRIVER_OPENED)
1012     {
1013         return RTEMS_INCORRECT_STATE;           /* must be opened first */
1014     }
1015 
1016     SciOpened = DRIVER_CLOSED;                  /* set the flag */
1017 
1018     return RTEMS_SUCCESSFUL;
1019 }
1020 
1021 
1022 /****************************************************************************
1023 * Func:     SciRead
1024 * Desc:     device driver read routine
1025 *           this function is not meaningful for the laser devices
1026 * Inputs:   major - the major device number
1027 *           minor - the minor device number
1028 *           arg - read/write arguments
1029 * Outputs:  see below
1030 * Errors:   none
1031 * Scope:    public API
1032 ****************************************************************************/
1033 
1034 rtems_device_driver SciRead (
1035     rtems_device_major_number major,
1036     rtems_device_minor_number minor,
1037     void *arg
1038 )
1039 {
1040     rtems_libio_rw_args_t *rw_args;             /* ptr to argument struct */
1041     char      *buffer;
1042 
1043     rw_args = (rtems_libio_rw_args_t *) arg;    /* arguments to read() */
1044 
1045     if (minor != SCI_MINOR)
1046     {
1047         return RTEMS_INVALID_NAME;              /* check the minor number */
1048     }
1049 
1050     if (SciOpened == DRIVER_CLOSED)
1051     {
1052         return RTEMS_INCORRECT_STATE;           /* must be opened first */
1053     }
1054 
1055     buffer = rw_args->buffer;                   /* points to user's buffer */
1056 
1057 /*  *buffer = SciReadCharWait();                   wait for a character */
1058 
1059     /* if there isn't a character available, wait until one shows up */
1060     /* or the timeout period expires, which ever happens first */
1061 
1062     if ( SciRcvBufCount == 0 )                  /* no chars */
1063     {
1064         /* wait for someone to wake me up... */
1065         /*rtems_task_wake_after(SciReadTimeout); */
1066     }
1067 
1068     if ( SciRcvBufCount )                       /* any characters locally? */
1069     {
1070         *buffer = SciRcvBufGetChar();           /* get the character */
1071 
1072         rw_args->bytes_moved = 1;               /* how many we actually read */
1073     }
1074 
1075     return RTEMS_SUCCESSFUL;
1076 }
1077 
1078 
1079 /****************************************************************************
1080 * Func:     SciWrite
1081 * Desc:     device driver write routine
1082 *           this function is not meaningful for the laser devices
1083 * Inputs:   major - the major device number
1084 *           minor - the minor device number
1085 *           arg - read/write arguments
1086 * Outputs:  see below
1087 * Errors:   non3
1088 * Scope:    public API
1089 ****************************************************************************/
1090 
1091 rtems_device_driver SciWrite (
1092     rtems_device_major_number major,
1093     rtems_device_minor_number minor,
1094     void * arg
1095 )
1096 {
1097     rtems_libio_rw_args_t *rw_args;             /* ptr to argument struct */
1098     uint8_t   *buffer;
1099     size_t     length;
1100 
1101     rw_args = (rtems_libio_rw_args_t *) arg;
1102 
1103     if (minor != SCI_MINOR)
1104     {
1105         return RTEMS_INVALID_NAME;              /* check the minor number */
1106     }
1107 
1108     if (SciOpened == DRIVER_CLOSED)
1109     {
1110         return RTEMS_INCORRECT_STATE;           /* must be opened first */
1111     }
1112 
1113     buffer = (uint8_t*)rw_args->buffer;       /* points to data */
1114 
1115     length = rw_args->count;                    /* how many bytes */
1116 
1117     while (length--)
1118     {
1119         SciWriteCharWait(*buffer++);            /* send the bytes out */
1120     }
1121 
1122     rw_args->bytes_moved = rw_args->count;      /* how many we wrote */
1123 
1124     return RTEMS_SUCCESSFUL;
1125 }
1126 
1127 
1128 /****************************************************************************
1129 * Func:     SciControl
1130 * Desc:     device driver control routine
1131 *           see below for an example of how to use the ioctl interface
1132 * Inputs:   major - the major device number
1133 *           minor - the minor device number
1134 *           arg - io control args
1135 * Outputs:  see below
1136 * Errors:   none
1137 * Scope:    public API
1138 ****************************************************************************/
1139 
1140 rtems_device_driver SciControl (
1141     rtems_device_major_number major,
1142     rtems_device_minor_number minor,
1143     void * arg
1144 )
1145 {
1146     rtems_libio_ioctl_args_t *args = arg;       /* rtems arg struct */
1147     uint16_t   command;                         /* the cmd to execute */
1148 
1149 /*printk("%s major=%d minor=%d\r\n", __FUNCTION__,major,minor); */
1150 
1151     /* do some sanity checking */
1152 
1153     if (minor != SCI_MINOR)
1154     {
1155         return RTEMS_INVALID_NAME;              /* check the minor number */
1156     }
1157 
1158     if (SciOpened == DRIVER_CLOSED)
1159     {
1160         return RTEMS_INCORRECT_STATE;           /* must be open first */
1161     }
1162 
1163     if (args == 0)
1164     {
1165         return RTEMS_INVALID_ADDRESS;           /* must have args */
1166     }
1167 
1168     args->ioctl_return = -1;                    /* assume an error */
1169 
1170     command = args->command;                    /* get the command */
1171 
1172     if (command == SCI_SEND_BREAK)              /* process the command */
1173     {
1174         SciSendBreak();                         /* send break char */
1175     }
1176 
1177     args->ioctl_return = 0;                     /* return status */
1178 
1179     return RTEMS_SUCCESSFUL;
1180 }
1181 
1182 
1183 /*
1184  *
1185  *                              SECTION 5
1186  *                       HARDWARE LEVEL ROUTINES
1187  */
1188 
1189 /****************************************************************************
1190 * Func:     SciSetBaud
1191 * Desc:     setup the uart based on the termios modules requests
1192 * Inputs:   baud rate
1193 * Outputs:  none
1194 * Errors:   none
1195 * Scope:    private
1196 ****************************************************************************/
1197 
1198 static void SciSetBaud(uint32_t   rate)
1199 {
1200     uint16_t   value;
1201     uint16_t   save_sccr1;
1202 
1203 /* when you open the console you need to set the termio struct baud rate */
1204 /* it has a default value of 9600, when someone calls tcsetattr it reverts! */
1205 
1206     SciBaud = rate;                             /* save the rate */
1207 
1208     /* calculate the register value as a float and convert to an int */
1209     /* set baud rate - you must define the system clock constant */
1210     /* see mrm332.h for an example */
1211 
1212     value = ( (uint16_t) ( SYS_CLOCK / rate / 32.0 + 0.5 ) & 0x1fff );
1213 
1214     save_sccr1 = *SCCR1;                        /* save register */
1215 
1216     /* also turns off the xmtr and rcvr */
1217 
1218     *SCCR1 &= SCI_DISABLE_INT_ALL;              /* disable interrupts */
1219 
1220     *SCCR0 = value;                             /* write the register */
1221 
1222     *SCCR1 = save_sccr1;                        /* restore register */
1223 
1224     return;
1225 }
1226 
1227 
1228 /****************************************************************************
1229 * Func:     SciSetParity
1230 * Desc:     setup the uart based on the termios modules requests
1231 * Inputs:   parity
1232 * Outputs:  none
1233 * Errors:   none
1234 * Scope:    private
1235 ****************************************************************************/
1236 
1237 static void SciSetParity(uint16_t   parity)
1238 {
1239     uint16_t   value;
1240 
1241     value = *SCCR1;                             /* get the register */
1242 
1243     if (parity == SCI_PARITY_ODD)
1244     {
1245         value |= SCI_PARITY_ENABLE;             /* parity enabled */
1246         value |= SCI_PARITY_ODD;                /* parity odd */
1247     }
1248 
1249     else if (parity == SCI_PARITY_EVEN)
1250     {
1251         value |= SCI_PARITY_ENABLE;             /* parity enabled */
1252         value &= ~SCI_PARITY_ODD;               /* parity even */
1253     }
1254 
1255     else if (parity == SCI_PARITY_NONE)
1256     {
1257         value &= ~SCI_PARITY_ENABLE;            /* disabled, most common */
1258     }
1259 
1260     /* else no changes */
1261 
1262     *SCCR1 = value;                             /* write the register */
1263 
1264     return;
1265 }
1266 
1267 
1268 /****************************************************************************
1269 * Func:     SciSetDataBits
1270 * Desc:     setup the uart based on the termios modules requests
1271 * Inputs:   data bits
1272 * Outputs:  none
1273 * Errors:   none
1274 * Scope:    private
1275 ****************************************************************************/
1276 
1277 static void SciSetDataBits(uint16_t   bits)
1278 {
1279     uint16_t   value;
1280 
1281     value = *SCCR1;                             /* get the register */
1282 
1283     /* note - the parity setting affects the number of data bits */
1284 
1285     if (bits == SCI_9_DATA_BITS)
1286     {
1287         value |= SCI_9_DATA_BITS;               /* 9 data bits */
1288     }
1289 
1290     else if (bits == SCI_8_DATA_BITS)
1291     {
1292         value &= SCI_8_DATA_BITS;               /* 8 data bits */
1293     }
1294 
1295     /* else no changes */
1296 
1297     *SCCR1 = value;                             /* write the register */
1298 
1299     return;
1300 }
1301 
1302 
1303 /****************************************************************************
1304 * Func:     SciDisableAllInterrupts
1305 * Func:     SciEnableTransmitInterrupts
1306 * Func:     SciEnableReceiveInterrupts
1307 * Desc:     handles generation of interrupts by the sci module
1308 * Inputs:   none
1309 * Outputs:  none
1310 * Errors:   none
1311 * Scope:    private
1312 ****************************************************************************/
1313 
1314 static void inline SciDisableAllInterrupts( void )
1315 {
1316     /* this also turns off the xmtr and rcvr */
1317 
1318     *SCCR1 &= SCI_DISABLE_INT_ALL;
1319 }
1320 
1321 static void inline SciEnableReceiveInterrupts( void )
1322 {
1323     *SCCR1 |= SCI_ENABLE_INT_RX;
1324 }
1325 
1326 static void inline SciDisableReceiveInterrupts( void )
1327 {
1328     *SCCR1 &= SCI_DISABLE_INT_RX;
1329 }
1330 
1331 static void inline SciEnableTransmitInterrupts( void )
1332 {
1333     *SCCR1 |= SCI_ENABLE_INT_TX;
1334 }
1335 
1336 static void inline SciDisableTransmitInterrupts( void )
1337 {
1338     *SCCR1 &= SCI_DISABLE_INT_TX;
1339 }
1340 
1341 
1342 /****************************************************************************
1343 * Func:     SciEnableTransmitter, SciDisableTransmitter
1344 * Func:     SciEnableReceiver,    SciDisableReceiver
1345 * Desc:     turns the transmitter and receiver on and off
1346 * Inputs:   none
1347 * Outputs:  none
1348 * Errors:   none
1349 * Scope:    private
1350 ****************************************************************************/
1351 
1352 static void inline SciEnableTransmitter( void )
1353 {
1354     *SCCR1 |= SCI_ENABLE_XMTR;
1355 }
1356 
1357 static void inline SciDisableTransmitter( void )
1358 {
1359     *SCCR1 &= SCI_DISABLE_XMTR;
1360 }
1361 
1362 static void inline SciEnableReceiver( void )
1363 {
1364     *SCCR1 |= SCI_ENABLE_RCVR;
1365 }
1366 
1367 static void inline SciDisableReceiver( void )
1368 {
1369     *SCCR1 &= SCI_DISABLE_RCVR;
1370 }
1371 
1372 
1373 /****************************************************************************
1374 * Func:     SciWriteCharWait
1375 * Desc:     wait for room in the fifo and then put a char in
1376 * Inputs:   a byte to send
1377 * Outputs:  none
1378 * Errors:   none
1379 * Scope:    public
1380 ****************************************************************************/
1381 
1382 void SciWriteCharWait(uint8_t   c)
1383 {
1384     /* poll the fifo, waiting for room for another character */
1385 
1386     while ( ( *SCSR & SCI_XMTR_AVAILABLE ) != SCI_XMTR_AVAILABLE )
1387     {
1388         /* Either we are writing to the fifo faster than
1389          * the uart can clock bytes out onto the cable,
1390          * or we are in flow control (actually no, we
1391          * are ignoring flow control from the other end).
1392          * In the first case, higher baud rates will help.
1393          */
1394       /* relinquish processor while waiting */
1395       rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
1396     }
1397 
1398     *SCDR = c;                                  /* send the charcter */
1399 
1400     SciBytesOut++;                              /* increment the counter */
1401 
1402     return;
1403 }
1404 
1405 /****************************************************************************
1406 * Func:     SciWriteCharNoWait
1407 * Desc:     if no room in the fifo throw the char on the floor
1408 * Inputs:   a byte to send
1409 * Outputs:  none
1410 * Errors:   none
1411 * Scope:    public
1412 ****************************************************************************/
1413 
1414 void SciWriteCharNoWait(uint8_t   c)
1415 {
1416     if ( ( *SCSR & SCI_XMTR_AVAILABLE ) == 0 )
1417     {
1418         return;                                 /* no room, throw it away */
1419     }
1420 
1421     *SCDR = c;                                  /* put the char in the fifo */
1422 
1423     SciBytesOut++;                              /* increment the counter */
1424 
1425     return;
1426 }
1427 
1428 
1429 /****************************************************************************
1430 * Func:     SciReadCharWait
1431 * Desc:     read a character, waiting for one to show up, if need be
1432 * Inputs:   none
1433 * Outputs:  a character
1434 * Errors:   none
1435 * Scope:    public
1436 ****************************************************************************/
1437 
1438 static uint8_t   inline SciReadCharWait( void )
1439 {
1440     uint8_t   ch;
1441 
1442     while ( SciCharAvailable() == 0 )           /* anything there? */
1443     {
1444       /* relinquish processor while waiting */
1445       rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
1446     }
1447 
1448     /* if you have rcv ints enabled, then the isr will probably */
1449     /* get the character before you will unless you turn off ints */
1450     /* ie polling and ints don't mix that well */
1451 
1452     ch = *SCDR;                                 /* get the charcter */
1453 
1454     SciBytesIn++;                               /* increment the counter */
1455 
1456     return ch;                                  /* return the char */
1457 }
1458 
1459 /****************************************************************************
1460 * Func:     SciReadCharNoWait
1461 * Desc:     try to get a char but dont wait for one
1462 * Inputs:   none
1463 * Outputs:  a character or -1 if none
1464 * Errors:   none
1465 * Scope:    public
1466 ****************************************************************************/
1467 
1468 static uint8_t   inline SciReadCharNoWait( void )
1469 {
1470     uint8_t   ch;
1471 
1472     if ( SciCharAvailable() == 0 )              /* anything there? */
1473         return -1;
1474 
1475     ch = *SCDR;                                 /* get the character */
1476 
1477     SciBytesIn++;                               /* increment the count */
1478 
1479     return ch;                                  /* return the char */
1480 }
1481 
1482 
1483 /****************************************************************************
1484 * Func:     SciCharAvailable
1485 * Desc:     is there a receive character in the data register
1486 * Inputs:   none
1487 * Outputs:  false if no char available, else true
1488 * Errors:   none
1489 * Scope:    public
1490 ****************************************************************************/
1491 
1492 uint8_t   inline SciCharAvailable( void )
1493 {
1494     return ( *SCSR & SCI_RCVR_READY );          /* char in data register? */
1495 }
1496 
1497 
1498 /****************************************************************************
1499 * Func:     SciSendBreak
1500 * Desc:     send 1 or tow breaks (all zero bits)
1501 * Inputs:   none
1502 * Outputs:  none
1503 * Errors:   none
1504 * Scope:    public
1505 ****************************************************************************/
1506 
1507 void SciSendBreak( void )
1508 {
1509     /* From the Motorola QSM reference manual - */
1510 
1511     /* "if SBK is toggled by writing it first to a one and then immediately */
1512     /* to a zero (in less than one serial frame interval), the transmitter */
1513     /* sends only one or two break frames before reverting to mark (idle) */
1514     /* or before commencing to send more data" */
1515 
1516     *SCCR1 |=  SCI_SEND_BREAK;                  /* set the bit */
1517 
1518     *SCCR1 &= ~SCI_SEND_BREAK;                  /* clear the bit */
1519 
1520     return;
1521 }
1522 
1523 
1524 /*
1525  *
1526  *                             SECTION 6
1527  *                             TEST CODE
1528  */
1529 
1530 /****************************************************************************
1531 * Func:     SciUnitTest
1532 * Desc:     test the device driver
1533 * Inputs:   nothing
1534 * Outputs:  nothing
1535 * Scope:    public
1536 ****************************************************************************/
1537 
1538 #if 0
1539 void SciUnitTest()
1540 {
1541     uint8_t   byte;                             /* a character */
1542     uint16_t   fd;                              /* file descriptor for device */
1543     uint16_t   result;                          /* result of ioctl */
1544 
1545     fd = open("/dev/sci",O_RDWR);               /* open the device */
1546 
1547 printk("SCI open fd=%d\r\n",fd);
1548 
1549     result = write(fd, "abcd\r\n", 6);          /* send a string */
1550 
1551 printk("SCI write result=%d\r\n",result);
1552 
1553     result = read(fd, &byte, 1);                /* read a byte */
1554 
1555 printk("SCI read result=%d,byte=%x\r\n",result,byte);
1556 
1557     return;
1558 }
1559 #endif
1560 
1561 
1562 /****************************************************************************
1563 * Func:     SciPrintStats
1564 * Desc:     print out some driver information
1565 * Inputs:   nothing
1566 * Outputs:  nothing
1567 * Scope:    public
1568 ****************************************************************************/
1569 
1570 void SciPrintStats ( void )
1571 {
1572     printk("\r\n");
1573 
1574     printk( "SYS_CLOCK is %2.6f Mhz\r\n\n", SYS_CLOCK / 1000000.0 );
1575 
1576     printk( "Current baud rate is %d bps or %d cps\r\n\n", SciBaud, SciBaud / 10 );
1577 
1578     printk( "SCI Uart chars in       %8" PRIu32 "\r\n", SciBytesIn       );
1579     printk( "SCI Uart chars out      %8" PRIu32 "\r\n", SciBytesOut      );
1580     printk( "SCI Uart framing errors %8" PRIu32 "\r\n", SciErrorsFraming );
1581     printk( "SCI Uart parity  errors %8" PRIu32 "\r\n", SciErrorsParity  );
1582     printk( "SCI Uart overrun errors %8" PRIu32 "\r\n", SciErrorsOverrun );
1583     printk( "SCI Uart noise   errors %8" PRIu32 "\r\n", SciErrorsNoise   );
1584 
1585     return;
1586 }