Search
lxdream.org :: lxdream/src/sh4/scif.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/scif.c
changeset 929:fd8cb0c82f5f
prev828:b42865f00fb5
next975:007bf7eb944f
author nkeynes
date Sat Dec 27 02:59:35 2008 +0000 (15 years ago)
branchlxdream-mem
permissions -rw-r--r--
last change Replace fpscr_mask/fpscr flags in xlat_cache_block with a single xlat_sh4_mode,
which tracks the field of the same name in sh4r - actually a little faster this way.
Now depends on SR.MD, FPSCR.PR and FPSCR.SZ (although it doesn't benefit from the SR
flag yet).

Also fixed the failure to check the flags in the common case (code address returned
by previous block) which took away the performance benefits, but oh well.
view annotate diff log raw
     1 /**
     2  * $Id$
     3  * SCIF (Serial Communication Interface with FIFO) implementation - part of the 
     4  * SH4 standard on-chip peripheral set. The SCIF is hooked up to the DCs
     5  * external serial port
     6  *
     7  * Copyright (c) 2005 Nathan Keynes.
     8  *
     9  * This program is free software; you can redistribute it and/or modify
    10  * it under the terms of the GNU General Public License as published by
    11  * the Free Software Foundation; either version 2 of the License, or
    12  * (at your option) any later version.
    13  *
    14  * This program is distributed in the hope that it will be useful,
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    17  * GNU General Public License for more details.
    18  */
    20 #include <glib.h>
    21 #include "dream.h"
    22 #include "mem.h"
    23 #include "sh4/sh4core.h"
    24 #include "sh4/sh4mmio.h"
    25 #include "sh4/intc.h"
    26 #include "sh4/dmac.h"
    27 #include "clock.h"
    28 #include "serial.h"
    30 void SCIF_set_break(void);
    32 /************************* External serial interface ************************/
    34 /**
    35  * Note: serial_* operations are called from outside the SH4, and as such are
    36  * named relative to the external serial device. SCIF_* operations are only
    37  * called internally to the SH4 and so are named relative to the CPU.
    38  */
    40 /**
    41  * Storage space for inbound/outbound data blocks. It's a little more
    42  * convenient for serial consumers to be able to deal with block-sized pieces
    43  * rather than a byte at a time, even if it makes all this look rather
    44  * complicated.
    45  *
    46  * Currently there's no limit on the number of blocks that can be queued up.
    47  */
    48 typedef struct serial_data_block {
    49     uint32_t length;
    50     uint32_t offset;
    51     struct serial_data_block *next;
    52     char data[];
    53 } *serial_data_block_t;
    55 serial_data_block_t serial_recvq_head = NULL, serial_recvq_tail = NULL;
    56 serial_device_t serial_device = NULL;
    58 void serial_attach_device( serial_device_t dev ) 
    59 {
    60     if( serial_device != NULL )
    61         serial_detach_device();
    62     serial_device = dev;
    63 }
    66 void serial_detach_device( void )
    67 {
    68     serial_device = NULL;
    69 }
    71 /**
    72  * Add a block of data to the serial receive queue. The data will be received
    73  * by the CPU at the appropriate baud rate.
    74  */
    75 void serial_transmit_data( char *data, int length ) {
    76     if( length == 0 )
    77         return;
    78     serial_data_block_t block = 
    79         g_malloc( sizeof( struct serial_data_block ) + length );
    80     block->length = length;
    81     block->offset = 0;
    82     block->next = NULL;
    83     memcpy( block->data, data, length );
    85     if( serial_recvq_head == NULL ) {
    86         serial_recvq_head = serial_recvq_tail = block;
    87     } else {
    88         serial_recvq_tail->next = block;
    89         serial_recvq_tail = block;
    90     }
    91 }
    93 /**
    94  * Dequeue a byte from the serial input queue
    95  */
    96 static int serial_transmit_dequeue( ) {
    97     if( serial_recvq_head != NULL ) {
    98         uint8_t val = serial_recvq_head->data[serial_recvq_head->offset++];
    99         if( serial_recvq_head->offset >= serial_recvq_head->length ) {
   100             serial_data_block_t next = serial_recvq_head->next;
   101             g_free( serial_recvq_head );
   102             serial_recvq_head = next;
   103             if( next == NULL )
   104                 serial_recvq_tail = NULL;
   105         }
   106         return (int)(unsigned int)val;
   107     }
   108     return -1;
   110 }
   112 void serial_transmit_break() {
   113     SCIF_set_break();
   114 }
   116 /********************************* SCIF *************************************/
   118 #define FIFO_LENGTH 16
   119 #define FIFO_ARR_LENGTH (FIFO_LENGTH+1)
   121 /* Serial control register flags */
   122 #define SCSCR2_TIE  0x80
   123 #define SCSCR2_RIE  0x40
   124 #define SCSCR2_TE   0x20
   125 #define SCSCR2_RE   0x10
   126 #define SCSCR2_REIE 0x08
   127 #define SCSCR2_CKE 0x02
   129 #define IS_TRANSMIT_IRQ_ENABLED() (MMIO_READ(SCIF,SCSCR2) & SCSCR2_TIE)
   130 #define IS_RECEIVE_IRQ_ENABLED() (MMIO_READ(SCIF,SCSCR2) & SCSCR2_RIE)
   131 #define IS_RECEIVE_ERROR_IRQ_ENABLED() (MMIO_READ(SCIF,SCSCR2) & (SCSCR2_RIE|SCSCR2_REIE))
   132 /* Receive is enabled if the RE bit is set in SCSCR2, and the ORER bit is cleared in SCLSR2 */
   133 #define IS_RECEIVE_ENABLED() ( (MMIO_READ(SCIF,SCSCR2) & SCSCR2_RE) && ((MMIO_READ(SCIF,SCLSR2) & SCLSR2_ORER) == 0) )
   134 /* Transmit is enabled if the TE bit is set in SCSCR2 */
   135 #define IS_TRANSMIT_ENABLED() (MMIO_READ(SCIF,SCSCR2) & SCSCR2_TE)
   136 #define IS_LOOPBACK_ENABLED() (MMIO_READ(SCIF,SCFCR2) & SCFCR2_LOOP)
   138 /* Serial status register flags */
   139 #define SCFSR2_ER   0x80
   140 #define SCFSR2_TEND 0x40
   141 #define SCFSR2_TDFE 0x20
   142 #define SCFSR2_BRK  0x10
   143 #define SCFSR2_RDF  0x02
   144 #define SCFSR2_DR   0x01
   146 /* FIFO control register flags */
   147 #define SCFCR2_MCE   0x08
   148 #define SCFCR2_TFRST 0x04
   149 #define SCFCR2_RFRST 0x02
   150 #define SCFCR2_LOOP  0x01
   152 /* Line Status Register */
   153 #define SCLSR2_ORER 0x01
   155 struct SCIF_fifo {
   156     int head;
   157     int tail;
   158     int trigger;
   159     uint8_t data[FIFO_ARR_LENGTH];
   160 };
   162 int SCIF_recvq_triggers[4] = {1, 4, 8, 14};
   163 struct SCIF_fifo SCIF_recvq = {0,0,1};
   165 int SCIF_sendq_triggers[4] = {8, 4, 2, 1};
   166 struct SCIF_fifo SCIF_sendq = {0,0,8};
   168 /**
   169  * Flag to indicate if data was received (ie added to the receive queue)
   170  * during the last SCIF clock tick. Used to determine when to set the DR
   171  * flag.
   172  */
   173 gboolean SCIF_rcvd_last_tick = FALSE;
   175 uint32_t SCIF_tick_period = 0;
   176 uint32_t SCIF_tick_remainder = 0;
   178 void SCIF_save_state( FILE *f ) 
   179 {
   180     fwrite( &SCIF_recvq, sizeof(SCIF_recvq), 1, f );
   181     fwrite( &SCIF_sendq, sizeof(SCIF_sendq), 1, f );
   182     fwrite( &SCIF_rcvd_last_tick, sizeof(gboolean), 1, f );
   184 }
   186 int SCIF_load_state( FILE *f ) 
   187 {
   188     fread( &SCIF_recvq, sizeof(SCIF_recvq), 1, f );
   189     fread( &SCIF_sendq, sizeof(SCIF_sendq), 1, f );
   190     fread( &SCIF_rcvd_last_tick, sizeof(gboolean), 1, f );
   191     return 0;
   192 }
   194 static inline uint8_t SCIF_recvq_size( ) 
   195 {
   196     int val = SCIF_recvq.tail - SCIF_recvq.head;
   197     if( val < 0 ) {
   198         val = FIFO_ARR_LENGTH - SCIF_recvq.head + SCIF_recvq.tail;
   199     }
   200     return val;
   201 }
   203 int SCIF_recvq_dequeue( gboolean clearFlags )
   204 {
   205     uint8_t result;
   206     uint32_t tmp, length;
   207     if( SCIF_recvq.head == SCIF_recvq.tail )
   208         return -1; /* No data */
   209     result = SCIF_recvq.data[SCIF_recvq.head++];
   210     if( SCIF_recvq.head > FIFO_LENGTH )
   211         SCIF_recvq.head = 0;
   213     /* Update data count register */
   214     tmp = MMIO_READ( SCIF, SCFDR2 ) & 0xF0;
   215     length = SCIF_recvq_size();
   216     MMIO_WRITE( SCIF, SCFDR2, tmp | length );
   218     /* Clear flags (if requested ) */
   219     if( clearFlags && length < SCIF_recvq.trigger ) {
   220         tmp = SCFSR2_RDF;
   221         if( length == 0 )
   222             tmp |= SCFSR2_DR;
   223         tmp = MMIO_READ( SCIF, SCFSR2 ) & (~tmp);
   224         MMIO_WRITE( SCIF, SCFSR2, tmp );
   225         /* If both flags are cleared, clear the interrupt as well */
   226         if( (tmp & (SCFSR2_DR|SCFSR2_RDF)) == 0 && IS_RECEIVE_IRQ_ENABLED() )
   227             intc_clear_interrupt( INT_SCIF_RXI );
   228     }
   230     return (int)(unsigned int)result;
   231 }
   233 gboolean SCIF_recvq_enqueue( uint8_t value )
   234 {
   235     uint32_t tmp, length;
   236     int newpos = SCIF_recvq.tail + 1;
   237     if( newpos > FIFO_LENGTH )
   238         newpos = 0;
   239     if( newpos == SCIF_recvq.head ) {
   240         /* FIFO full - set ORER and discard the value */
   241         MMIO_WRITE( SCIF, SCLSR2, SCLSR2_ORER );
   242         if( IS_RECEIVE_ERROR_IRQ_ENABLED() )
   243             intc_raise_interrupt( INT_SCIF_ERI );
   244         return FALSE;
   245     }
   246     SCIF_recvq.data[SCIF_recvq.tail] = value;
   248     /* Update data count register */
   249     tmp = MMIO_READ( SCIF, SCFDR2 ) & 0xF0;
   250     length = SCIF_recvq_size();
   251     MMIO_WRITE( SCIF, SCFDR2, tmp | length );
   253     /* Update status register */
   254     tmp = MMIO_READ( SCIF, SCFSR2 );
   255     if( length >= SCIF_recvq.trigger ) {
   256         tmp |= SCFSR2_RDF;
   257         if( IS_RECEIVE_IRQ_ENABLED() ) 
   258             intc_raise_interrupt( INT_SCIF_RXI );
   259         DMAC_trigger( DMAC_SCIF_RDF );
   260     }
   261     MMIO_WRITE( SCIF, SCFSR2, tmp );
   262     return TRUE;
   263 }
   266 /**
   267  * Reset the receive FIFO to its initial state. Manual is unclear as to
   268  * whether this also clears flags/interrupts, but we're assuming here that
   269  * it does until proven otherwise.
   270  */
   271 void SCIF_recvq_clear( void ) 
   272 {
   273     SCIF_recvq.head = SCIF_recvq.tail = 0;
   274     MMIO_WRITE( SCIF, SCFDR2, MMIO_READ( SCIF, SCFDR2 ) & 0xF0 );
   275     MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) & ~(SCFSR2_DR|SCFSR2_RDF) );
   276     if( IS_RECEIVE_IRQ_ENABLED() )
   277         intc_clear_interrupt( INT_SCIF_RXI );
   278 }
   280 static inline uint8_t SCIF_sendq_size( ) 
   281 {
   282     int val = SCIF_sendq.tail - SCIF_sendq.head;
   283     if( val < 0 ) {
   284         val = FIFO_ARR_LENGTH - SCIF_sendq.head + SCIF_sendq.tail;
   285     }
   286     return val;
   287 }
   289 /**
   290  * Dequeue one byte from the SCIF transmit queue (ie transmit the byte),
   291  * updating all status flags as required.
   292  * @return The byte dequeued, or -1 if the queue is empty.
   293  */
   294 int SCIF_sendq_dequeue( )
   295 {
   296     uint8_t result;
   297     uint32_t tmp, length;
   298     if( SCIF_sendq.head == SCIF_sendq.tail )
   299         return -1; /* No data */
   301     /* Update queue head pointer */
   302     result = SCIF_sendq.data[SCIF_sendq.head++];
   303     if( SCIF_sendq.head > FIFO_LENGTH )
   304         SCIF_sendq.head = 0;
   306     /* Update data count register */
   307     tmp = MMIO_READ( SCIF, SCFDR2 ) & 0x0F;
   308     length = SCIF_sendq_size();
   309     MMIO_WRITE( SCIF, SCFDR2, tmp | (length << 8) );
   311     /* Update status register */
   312     if( length <= SCIF_sendq.trigger ) {
   313         tmp = MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_TDFE;
   314         if( length == 0 )
   315             tmp |= SCFSR2_TEND; /* Transmission ended - no data waiting */
   316         if( IS_TRANSMIT_IRQ_ENABLED() ) 
   317             intc_raise_interrupt( INT_SCIF_TXI );
   318         DMAC_trigger( DMAC_SCIF_TDE );
   319         MMIO_WRITE( SCIF, SCFSR2, tmp );
   320     }
   321     return (int)(unsigned int)result;
   322 }
   324 /**
   325  * Enqueue a single byte in the SCIF transmit queue. If the queue is full,
   326  * the value will be discarded.
   327  * @param value to be queued.
   328  * @param clearFlags TRUE if the TEND/TDFE flags should be cleared
   329  *   if the queue exceeds the trigger level. (According to the manual,
   330  *   DMAC writes will clear the flag, whereas regular SH4 writes do NOT
   331  *   automatically clear it. Go figure).
   332  * @return gboolean TRUE if the value was queued, FALSE if the queue was
   333  *   full.
   334  */
   335 gboolean SCIF_sendq_enqueue( uint8_t value, gboolean clearFlags )
   336 {
   337     uint32_t tmp, length;
   338     int newpos = SCIF_sendq.tail + 1;
   339     if( newpos > FIFO_LENGTH )
   340         newpos = 0;
   341     if( newpos == SCIF_sendq.head ) {
   342         /* FIFO full - discard */
   343         return FALSE;
   344     }
   345     SCIF_sendq.data[SCIF_sendq.tail] = value;
   346     SCIF_sendq.tail = newpos;
   348     /* Update data count register */
   349     tmp = MMIO_READ( SCIF, SCFDR2 ) & 0x0F;
   350     length = SCIF_sendq_size();
   351     MMIO_WRITE( SCIF, SCFDR2, tmp | (length << 8) );
   353     /* Update flags if requested */
   354     if( clearFlags ) {
   355         tmp = SCFSR2_TEND;
   356         if( length > SCIF_sendq.trigger ) {
   357             tmp |= SCFSR2_TDFE;
   358             if( IS_TRANSMIT_IRQ_ENABLED() )
   359                 intc_clear_interrupt( INT_SCIF_TXI );
   360         }
   361         tmp = MMIO_READ( SCIF, SCFSR2 ) & (~tmp);
   362         MMIO_WRITE( SCIF, SCFSR2, tmp );
   363     }
   364     return TRUE;
   365 }
   367 void SCIF_sendq_clear( void ) 
   368 {
   369     SCIF_sendq.head = SCIF_sendq.tail = 0;
   370     MMIO_WRITE( SCIF, SCFDR2, MMIO_READ( SCIF, SCFDR2 ) & 0x0F );
   371     MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_TEND | SCFSR2_TDFE );
   372     if( IS_TRANSMIT_IRQ_ENABLED() ) {
   373         intc_raise_interrupt( INT_SCIF_TXI );
   374         DMAC_trigger( DMAC_SCIF_TDE );
   375     }
   376 }
   378 /**
   379  * Update the SCFSR2 status register with the given mask (ie clear any values
   380  * that are set to 0 in the mask. According to a strict reading of the doco
   381  * though, the bits will only actually clear if the flag state is no longer
   382  * true, so we need to recheck everything...
   383  */
   384 void SCIF_update_status( uint32_t mask )
   385 {
   386     uint32_t value = MMIO_READ( SCIF, SCFSR2 );
   387     uint32_t result = value & mask;
   388     uint32_t sendq_size = SCIF_sendq_size();
   389     uint32_t recvq_size = SCIF_recvq_size();
   391     if( sendq_size != 0 )
   392         result |= SCFSR2_TEND;
   394     if( sendq_size <= SCIF_sendq.trigger )
   395         result |= SCFSR2_TDFE;
   396     else if( (result & SCFSR2_TDFE) == 0 && IS_TRANSMIT_IRQ_ENABLED() )
   397         intc_clear_interrupt( INT_SCIF_TXI );
   399     if( recvq_size >= SCIF_recvq.trigger )
   400         result |= SCFSR2_RDF;
   401     if( (value & SCFSR2_DR) != 0 && (result & SCFSR2_DR) == 0 &&
   402             recvq_size != 0 )
   403         result |= SCFSR2_DR;
   404     if( (result & (SCFSR2_DR|SCFSR2_RDF)) == 0 && IS_RECEIVE_IRQ_ENABLED() )
   405         intc_clear_interrupt( INT_SCIF_RXI );
   407     if( IS_RECEIVE_ERROR_IRQ_ENABLED() ) {
   408         if( (result & SCFSR2_BRK) == 0 )
   409             intc_clear_interrupt( INT_SCIF_BRI );
   410         if( (result & SCFSR2_ER) == 0 && 
   411                 (MMIO_READ( SCIF, SCLSR2 ) & SCLSR2_ORER) == 0 )
   412             intc_clear_interrupt( INT_SCIF_ERI );
   413     }
   414 }
   416 /**
   417  * Set the break detected flag
   418  */
   419 void SCIF_set_break( void ) 
   420 {
   421     MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_BRK );
   422     if( IS_RECEIVE_ERROR_IRQ_ENABLED() )
   423         intc_raise_interrupt( INT_SCIF_BRI );
   424 }
   426 const static int SCIF_CLOCK_MULTIPLIER[4] = {1, 4, 16, 64};
   428 /**
   429  * Calculate the current line speed.
   430  */
   431 void SCIF_update_line_speed( void )
   432 {
   433     /* If CKE1 is set, use the external clock as a base */
   434     if( MMIO_READ( SCIF, SCSCR2 ) & SCSCR2_CKE ) {
   437     } else {
   439         /* Otherwise, SH4 peripheral clock divided by n */
   440         int mult = SCIF_CLOCK_MULTIPLIER[MMIO_READ( SCIF, SCSMR2 ) & 0x03];
   442         /* Then process the bitrate register */
   443         int bbr = MMIO_READ( SCIF, SCBRR2 ) & 0xFF;
   445         int baudrate = sh4_peripheral_freq / (32 * mult * (bbr+1) );
   447         if( serial_device != NULL && serial_device->set_line_speed != NULL )
   448             serial_device->set_line_speed( baudrate );
   450         SCIF_tick_period = sh4_peripheral_period * (32 * mult * (bbr+1));
   452         /*
   453 	  clock_set_tick_rate( CLOCK_SCIF, baudrate / 10 );
   454          */
   455     }
   456 }
   458 MMIO_REGION_READ_FN( SCIF, reg )
   459 {
   460     reg &= 0xFFF;
   461     switch( reg ) {
   462     case SCFRDR2: /* Receive data */
   463         return SCIF_recvq_dequeue(FALSE);
   464     default:
   465         return MMIO_READ( SCIF, reg );
   466     }
   467 }
   469 MMIO_REGION_WRITE_FN( SCIF, reg, val )
   470 {
   471     uint32_t tmp;
   472     reg &= 0xFFF;
   473     switch( reg ) {
   474     case SCSMR2: /* Serial mode register */
   475         /* Bit 6 => 0 = 8-bit, 1 = 7-bit
   476          * Bit 5 => 0 = Parity disabled, 1 = parity enabled
   477          * Bit 4 => 0 = Even parity, 1 = Odd parity
   478          * Bit 3 => 0 = 1 stop bit, 1 = 2 stop bits
   479          * Bits 0-1 => Clock select 00 = P, 01 = P/4, 10 = P/16, 11 = P/64
   480          */
   481         val &= 0x007B;
   482         if( serial_device != NULL ) {
   483             serial_device->set_line_params( val );
   484         }
   485         tmp = MMIO_READ( SCIF, SCSMR2 );
   486         if( (tmp & 0x03) != (val & 0x03) ) {
   487             /* Clock change */
   488             SCIF_update_line_speed( );
   489         }
   490         /* Save for later read-back */
   491         MMIO_WRITE( SCIF, SCSMR2, val );
   492         break;
   493     case SCBRR2: /* Bit rate register */
   494         MMIO_WRITE( SCIF, SCBRR2, val );
   495         SCIF_update_line_speed( );
   496         break;
   497     case SCSCR2: /* Serial control register */
   498         /* Bit 7 => Transmit-FIFO-data-empty interrupt enabled 
   499          * Bit 6 => Receive-data-full interrupt enabled 
   500          * Bit 5 => Transmit enable 
   501          * Bit 4 => Receive enable 
   502          * Bit 3 => Receive-error/break interrupt enabled
   503          * Bit 1 => Clock enable
   504          */
   505         val &= 0x00FA;
   506         /* Clear any interrupts that just became disabled */
   507         if( (val & SCSCR2_TIE) == 0 )
   508             intc_clear_interrupt( INT_SCIF_TXI );
   509         if( (val & SCSCR2_RIE) == 0 )
   510             intc_clear_interrupt( INT_SCIF_RXI );
   511         if( (val & (SCSCR2_RIE|SCSCR2_REIE)) == 0 ) {
   512             intc_clear_interrupt( INT_SCIF_ERI );
   513             intc_clear_interrupt( INT_SCIF_BRI );
   514         }
   516         MMIO_WRITE( SCIF, reg, val );
   517         break;
   518     case SCFTDR2: /* Transmit FIFO data register */
   519         SCIF_sendq_enqueue( val, FALSE );
   520         break;
   521     case SCFSR2: /* Serial status register */
   522         /* Bits 12-15 Parity error count
   523          * Bits 8-11 Framing erro count 
   524          * Bit 7 - Receive error
   525          * Bit 6 - Transmit end
   526          * Bit 5 - Transmit FIFO data empty
   527          * Bit 4 - Break detect
   528          * Bit 3 - Framing error
   529          * Bit 2 - Parity error
   530          * Bit 1 - Receive FIFO data full
   531          * Bit 0 - Receive data ready
   532          */
   533         /* Clear off any flags/interrupts that are being set to 0 */
   534         SCIF_update_status( val );
   535         break;
   536     case SCFCR2: /* FIFO control register */
   537         val &= 0x0F;
   538         SCIF_recvq.trigger = SCIF_recvq_triggers[val >> 6];
   539         SCIF_sendq.trigger = SCIF_sendq_triggers[(val >> 4) & 0x03];
   540         if( val & SCFCR2_TFRST ) {
   541             SCIF_sendq_clear();
   542         }
   543         if( val & SCFCR2_RFRST ) {
   544             SCIF_recvq_clear();
   545         }
   547         MMIO_WRITE( SCIF, reg, val );
   548         break;
   549     case SCSPTR2: /* Serial Port Register */
   550         MMIO_WRITE( SCIF, reg, val );
   551         /* NOT IMPLEMENTED - 'direct' serial I/O */
   552         if( val != 0 ) {
   553             WARN( "SCSPTR2 not implemented: Write %08X", val );
   554         }
   555         break;
   556     case SCLSR2:
   557         val = val & SCLSR2_ORER;
   558         if( val == 0 ) {
   559             MMIO_WRITE( SCIF, SCLSR2, val );
   560             if( (MMIO_READ( SCIF, SCFSR2 ) & SCFSR2_ER) == 0 &&
   561                     IS_RECEIVE_ERROR_IRQ_ENABLED() ) 
   562                 intc_clear_interrupt( INT_SCIF_ERI );
   563         }
   565         break;
   566     }
   567 }
   569 /**
   570  * Actions for a single tick of the serial clock, defined as the transmission
   571  * time of a single frame.
   572  *
   573  * If transmit queue is non-empty:
   574  *    Transmit one byte and remove from queue
   575  * If input receive source is non-empty:
   576  *    Transfer one byte to the receive queue (if queue is full, byte is lost)
   577  * If recvq is non-empty, less than the trigger level, and no data has been
   578  *    received in the last 2 ticks (including this one), set the DR flag and
   579  *    IRQ if appropriate.
   580  */
   581 void SCIF_clock_tick( void ) 
   582 {
   583     gboolean rcvd = FALSE;
   585     if( IS_LOOPBACK_ENABLED() ) {
   586         if( IS_TRANSMIT_ENABLED() ) {
   587             int val = SCIF_sendq_dequeue();
   588             if( val != -1 && IS_RECEIVE_ENABLED() ) {
   589                 SCIF_recvq_enqueue( val );
   590                 rcvd = TRUE;
   591             }
   592         }
   593     } else {
   594         if( IS_TRANSMIT_ENABLED() ) {
   595             int val = SCIF_sendq_dequeue();
   596             if( val != -1 && serial_device != NULL && 
   597                     serial_device->receive_data != NULL ) {
   598                 serial_device->receive_data( val );
   599             }
   600         }
   602         if( IS_RECEIVE_ENABLED() ) {
   603             int val = serial_transmit_dequeue();
   604             if( val != -1 ) {
   605                 SCIF_recvq_enqueue( val );
   606                 rcvd = TRUE;
   607             }
   608         }
   609     }
   611     /* Check if we need to set the DR flag */
   612     if( !rcvd && !SCIF_rcvd_last_tick &&
   613             SCIF_recvq.head != SCIF_recvq.tail &&
   614             SCIF_recvq_size() < SCIF_recvq.trigger ) {
   615         uint32_t tmp = MMIO_READ( SCIF, SCFSR2 );
   616         if( (tmp & SCFSR2_DR) == 0 ) {
   617             MMIO_WRITE( SCIF, SCFSR2, tmp | SCFSR2_DR );
   618             if( IS_RECEIVE_IRQ_ENABLED() )
   619                 intc_raise_interrupt( INT_SCIF_RXI );
   620             DMAC_trigger( DMAC_SCIF_RDF );
   621         }
   622     }
   623     SCIF_rcvd_last_tick = rcvd;
   624 }
   626 void SCIF_reset( void )
   627 {
   628     SCIF_recvq_clear();
   629     SCIF_sendq_clear();
   630     SCIF_update_line_speed();
   631 }
   633 void SCIF_run_slice( uint32_t nanosecs ) 
   634 {
   635     SCIF_tick_remainder += nanosecs;
   636     while( SCIF_tick_remainder >= SCIF_tick_period ) {
   637         SCIF_tick_remainder -= SCIF_tick_period;
   638         SCIF_clock_tick();
   639     }
   640 }
.