Search
lxdream.org :: lxdream/src/sh4/scif.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/scif.c
changeset 35:21a4be098304
prev32:bf0bc2c524b8
next54:d8b73031289c
author nkeynes
date Mon Dec 26 03:54:55 2005 +0000 (15 years ago)
permissions -rw-r--r--
last change Remove modules.h - move definitions into dream.h
Add source string to output list (taken from module name)
ARM Work in progress
view annotate diff log raw
     1 /**
     2  * $Id: scif.c,v 1.7 2005-12-26 03:54:55 nkeynes Exp $
     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 "sh4core.h"
    24 #include "sh4mmio.h"
    25 #include "intc.h"
    26 #include "clock.h"
    27 #include "serial.h"
    29 void SCIF_set_break(void);
    31 /************************* External serial interface ************************/
    33 /**
    34  * Note: serial_* operations are called from outside the SH4, and as such are
    35  * named relative to the external serial device. SCIF_* operations are only
    36  * called internally to the SH4 and so are named relative to the CPU.
    37  */
    39 /**
    40  * Storage space for inbound/outbound data blocks. It's a little more
    41  * convenient for serial consumers to be able to deal with block-sized pieces
    42  * rather than a byte at a time, even if it makes all this look rather
    43  * complicated.
    44  *
    45  * Currently there's no limit on the number of blocks that can be queued up.
    46  */
    47 typedef struct serial_data_block {
    48     uint32_t length;
    49     uint32_t offset;
    50     struct serial_data_block *next;
    51     char data[];
    52 } *serial_data_block_t;
    54 serial_data_block_t serial_recvq_head = NULL, serial_recvq_tail = NULL;
    55 serial_device_t serial_device = NULL;
    57 void serial_attach_device( serial_device_t dev ) 
    58 {
    59     if( serial_device != NULL )
    60 	serial_detach_device();
    61     serial_device = dev;
    62 }
    65 void serial_detach_device( void )
    66 {
    67     serial_device = NULL;
    68 }
    70 /**
    71  * Add a block of data to the serial receive queue. The data will be received
    72  * by the CPU at the appropriate baud rate.
    73  */
    74 void serial_transmit_data( char *data, int length ) {
    75     if( length == 0 )
    76 	return;
    77     serial_data_block_t block = 
    78 	g_malloc( sizeof( struct serial_data_block ) + length );
    79     block->length = length;
    80     block->offset = 0;
    81     block->next = NULL;
    82     memcpy( block->data, data, length );
    84     if( serial_recvq_head == NULL ) {
    85 	serial_recvq_head = serial_recvq_tail = block;
    86     } else {
    87 	serial_recvq_tail->next = block;
    88 	serial_recvq_tail = block;
    89     }
    90 }
    92 /**
    93  * Dequeue a byte from the serial input queue
    94  */
    95 static int serial_transmit_dequeue( ) {
    96     if( serial_recvq_head != NULL ) {
    97 	uint8_t val = serial_recvq_head->data[serial_recvq_head->offset++];
    98 	if( serial_recvq_head->offset >= serial_recvq_head->length ) {
    99 	    serial_data_block_t next = serial_recvq_head->next;
   100 	    g_free( serial_recvq_head );
   101 	    serial_recvq_head = next;
   102 	    if( next == NULL )
   103 		serial_recvq_tail = NULL;
   104 	}
   105 	return (int)(unsigned int)val;
   106     }
   107     return -1;
   109 }
   111 void serial_transmit_break() {
   112     SCIF_set_break();
   113 }
   115 /********************************* SCIF *************************************/
   117 #define FIFO_LENGTH 16
   118 #define FIFO_ARR_LENGTH (FIFO_LENGTH+1)
   120 /* Serial control register flags */
   121 #define SCSCR2_TIE  0x80
   122 #define SCSCR2_RIE  0x40
   123 #define SCSCR2_TE   0x20
   124 #define SCSCR2_RE   0x10
   125 #define SCSCR2_REIE 0x08
   126 #define SCSCR2_CKE 0x02
   128 #define IS_TRANSMIT_IRQ_ENABLED() (MMIO_READ(SCIF,SCSCR2) & SCSCR2_TIE)
   129 #define IS_RECEIVE_IRQ_ENABLED() (MMIO_READ(SCIF,SCSCR2) & SCSCR2_RIE)
   130 #define IS_RECEIVE_ERROR_IRQ_ENABLED() (MMIO_READ(SCIF,SCSCR2) & (SCSCR2_RIE|SCSCR2_REIE))
   131 /* Receive is enabled if the RE bit is set in SCSCR2, and the ORER bit is cleared in SCLSR2 */
   132 #define IS_RECEIVE_ENABLED() ( (MMIO_READ(SCIF,SCSCR2) & SCSCR2_RE) && (MMIO_READ(SCIF,SCLSR2) & SCLSR2_ORER == 0) )
   133 /* Transmit is enabled if the TE bit is set in SCSCR2 */
   134 #define IS_TRANSMIT_ENABLED() (MMIO_READ(SCIF,SCSCR2) & SCSCR2_TE)
   135 #define IS_LOOPBACK_ENABLED() (MMIO_READ(SCIF,SCFCR2) & SCFCR2_LOOP)
   137 /* Serial status register flags */
   138 #define SCFSR2_ER   0x80
   139 #define SCFSR2_TEND 0x40
   140 #define SCFSR2_TDFE 0x20
   141 #define SCFSR2_BRK  0x10
   142 #define SCFSR2_RDF  0x02
   143 #define SCFSR2_DR   0x01
   145 /* FIFO control register flags */
   146 #define SCFCR2_MCE   0x08
   147 #define SCFCR2_TFRST 0x04
   148 #define SCFCR2_RFRST 0x02
   149 #define SCFCR2_LOOP  0x01
   151 /* Line Status Register */
   152 #define SCLSR2_ORER 0x01
   154 struct SCIF_fifo {
   155     int head;
   156     int tail;
   157     int trigger;
   158     uint8_t data[FIFO_ARR_LENGTH];
   159 };
   161 int SCIF_recvq_triggers[4] = {1, 4, 8, 14};
   162 struct SCIF_fifo SCIF_recvq = {0,0,1};
   164 int SCIF_sendq_triggers[4] = {8, 4, 2, 1};
   165 struct SCIF_fifo SCIF_sendq = {0,0,8};
   167 /**
   168  * Flag to indicate if data was received (ie added to the receive queue)
   169  * during the last SCIF clock tick. Used to determine when to set the DR
   170  * flag.
   171  */
   172 gboolean SCIF_rcvd_last_tick = FALSE;
   174 uint32_t SCIF_tick_period = 0;
   175 uint32_t SCIF_tick_remainder = 0;
   177 void SCIF_save_state( FILE *f ) 
   178 {
   179     fwrite( &SCIF_recvq, sizeof(SCIF_recvq), 1, f );
   180     fwrite( &SCIF_sendq, sizeof(SCIF_sendq), 1, f );
   181     fwrite( &SCIF_rcvd_last_tick, sizeof(gboolean), 1, f );
   183 }
   185 int SCIF_load_state( FILE *f ) 
   186 {
   187     fread( &SCIF_recvq, sizeof(SCIF_recvq), 1, f );
   188     fread( &SCIF_sendq, sizeof(SCIF_sendq), 1, f );
   189     fread( &SCIF_rcvd_last_tick, sizeof(gboolean), 1, f );
   190     return 0;
   191 }
   193 static inline uint8_t SCIF_recvq_size( ) 
   194 {
   195     int val = SCIF_recvq.tail - SCIF_recvq.head;
   196     if( val < 0 ) {
   197 	val = FIFO_ARR_LENGTH - SCIF_recvq.head + SCIF_recvq.tail;
   198     }
   199     return val;
   200 }
   202 int SCIF_recvq_dequeue( gboolean clearFlags )
   203 {
   204     uint8_t result;
   205     uint32_t tmp, length;
   206     if( SCIF_recvq.head == SCIF_recvq.tail )
   207 	return -1; /* No data */
   208     result = SCIF_recvq.data[SCIF_recvq.head++];
   209     if( SCIF_recvq.head > FIFO_LENGTH )
   210 	SCIF_recvq.head = 0;
   212     /* Update data count register */
   213     tmp = MMIO_READ( SCIF, SCFDR2 ) & 0xF0;
   214     length = SCIF_recvq_size();
   215     MMIO_WRITE( SCIF, SCFDR2, tmp | length );
   217     /* Clear flags (if requested ) */
   218     if( clearFlags && length < SCIF_recvq.trigger ) {
   219 	tmp = SCFSR2_RDF;
   220 	if( length == 0 )
   221 	    tmp |= SCFSR2_DR;
   222 	tmp = MMIO_READ( SCIF, SCFSR2 ) & (~tmp);
   223 	MMIO_WRITE( SCIF, SCFSR2, tmp );
   224 	/* If both flags are cleared, clear the interrupt as well */
   225 	if( (tmp & (SCFSR2_DR|SCFSR2_RDF)) == 0 && IS_RECEIVE_IRQ_ENABLED() )
   226 	    intc_clear_interrupt( INT_SCIF_RXI );
   227     }
   229     return (int)(unsigned int)result;
   230 }
   232 gboolean SCIF_recvq_enqueue( uint8_t value )
   233 {
   234     uint32_t tmp, length;
   235     int newpos = SCIF_recvq.tail + 1;
   236     if( newpos > FIFO_LENGTH )
   237 	newpos = 0;
   238     if( newpos == SCIF_recvq.head ) {
   239 	/* FIFO full - set ORER and discard the value */
   240 	MMIO_WRITE( SCIF, SCLSR2, SCLSR2_ORER );
   241 	if( IS_RECEIVE_ERROR_IRQ_ENABLED() )
   242 	    intc_raise_interrupt( INT_SCIF_ERI );
   243 	return FALSE;
   244     }
   245     SCIF_recvq.data[SCIF_recvq.tail] = value;
   247     /* Update data count register */
   248     tmp = MMIO_READ( SCIF, SCFDR2 ) & 0xF0;
   249     length = SCIF_recvq_size();
   250     MMIO_WRITE( SCIF, SCFDR2, tmp | length );
   252     /* Update status register */
   253     tmp = MMIO_READ( SCIF, SCFSR2 );
   254     if( length >= SCIF_recvq.trigger ) {
   255 	tmp |= SCFSR2_RDF;
   256 	if( IS_RECEIVE_IRQ_ENABLED() ) 
   257 	    intc_raise_interrupt( INT_SCIF_RXI );
   258     }
   259     MMIO_WRITE( SCIF, SCFSR2, tmp );
   260     return TRUE;
   261 }
   264 /**
   265  * Reset the receive FIFO to its initial state. Manual is unclear as to
   266  * whether this also clears flags/interrupts, but we're assuming here that
   267  * it does until proven otherwise.
   268  */
   269 void SCIF_recvq_clear( void ) 
   270 {
   271     SCIF_recvq.head = SCIF_recvq.tail = 0;
   272     MMIO_WRITE( SCIF, SCFDR2, MMIO_READ( SCIF, SCFDR2 ) & 0xF0 );
   273     MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) & ~(SCFSR2_DR|SCFSR2_RDF) );
   274     if( IS_RECEIVE_IRQ_ENABLED() )
   275 	intc_clear_interrupt( INT_SCIF_RXI );
   276 }
   278 static inline uint8_t SCIF_sendq_size( ) 
   279 {
   280     int val = SCIF_sendq.tail - SCIF_sendq.head;
   281     if( val < 0 ) {
   282 	val = FIFO_ARR_LENGTH - SCIF_sendq.head + SCIF_sendq.tail;
   283     }
   284     return val;
   285 }
   287 /**
   288  * Dequeue one byte from the SCIF transmit queue (ie transmit the byte),
   289  * updating all status flags as required.
   290  * @return The byte dequeued, or -1 if the queue is empty.
   291  */
   292 int SCIF_sendq_dequeue( )
   293 {
   294     uint8_t result;
   295     uint32_t tmp, length;
   296     if( SCIF_sendq.head == SCIF_sendq.tail )
   297 	return -1; /* No data */
   299     /* Update queue head pointer */
   300     result = SCIF_sendq.data[SCIF_sendq.head++];
   301     if( SCIF_sendq.head > FIFO_LENGTH )
   302 	SCIF_sendq.head = 0;
   304     /* Update data count register */
   305     tmp = MMIO_READ( SCIF, SCFDR2 ) & 0x0F;
   306     length = SCIF_sendq_size();
   307     MMIO_WRITE( SCIF, SCFDR2, tmp | (length << 8) );
   309     /* Update status register */
   310     if( length <= SCIF_sendq.trigger ) {
   311 	tmp = MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_TDFE;
   312 	if( length == 0 )
   313 	    tmp |= SCFSR2_TEND; /* Transmission ended - no data waiting */
   314 	if( IS_TRANSMIT_IRQ_ENABLED() ) 
   315 	    intc_raise_interrupt( INT_SCIF_TXI );
   316 	MMIO_WRITE( SCIF, SCFSR2, tmp );
   317     }
   318     return (int)(unsigned int)result;
   319 }
   321 /**
   322  * Enqueue a single byte in the SCIF transmit queue. If the queue is full,
   323  * the value will be discarded.
   324  * @param value to be queued.
   325  * @param clearFlags TRUE if the TEND/TDFE flags should be cleared
   326  *   if the queue exceeds the trigger level. (According to the manual,
   327  *   DMAC writes will clear the flag, whereas regular SH4 writes do NOT
   328  *   automatically clear it. Go figure).
   329  * @return gboolean TRUE if the value was queued, FALSE if the queue was
   330  *   full.
   331  */
   332 gboolean SCIF_sendq_enqueue( uint8_t value, gboolean clearFlags )
   333 {
   334     uint32_t tmp, length;
   335     int newpos = SCIF_sendq.tail + 1;
   336     if( newpos > FIFO_LENGTH )
   337 	newpos = 0;
   338     if( newpos == SCIF_sendq.head ) {
   339 	/* FIFO full - discard */
   340 	return FALSE;
   341     }
   342     SCIF_sendq.data[SCIF_sendq.tail] = value;
   343     SCIF_sendq.tail = newpos;
   345     /* Update data count register */
   346     tmp = MMIO_READ( SCIF, SCFDR2 ) & 0x0F;
   347     length = SCIF_sendq_size();
   348     MMIO_WRITE( SCIF, SCFDR2, tmp | (length << 8) );
   350     /* Update flags if requested */
   351     if( clearFlags ) {
   352 	tmp = SCFSR2_TEND;
   353 	if( length > SCIF_sendq.trigger ) {
   354 	    tmp |= SCFSR2_TDFE;
   355 	    if( IS_TRANSMIT_IRQ_ENABLED() )
   356 		intc_clear_interrupt( INT_SCIF_TXI );
   357 	}
   358 	tmp = MMIO_READ( SCIF, SCFSR2 ) & (~tmp);
   359 	MMIO_WRITE( SCIF, SCFSR2, tmp );
   360     }
   361     return TRUE;
   362 }
   364 void SCIF_sendq_clear( void ) 
   365 {
   366     SCIF_sendq.head = SCIF_sendq.tail = 0;
   367     MMIO_WRITE( SCIF, SCFDR2, MMIO_READ( SCIF, SCFDR2 ) & 0x0F );
   368     MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_TEND | SCFSR2_TDFE );
   369     if( IS_TRANSMIT_IRQ_ENABLED() ) {
   370 	intc_raise_interrupt( INT_SCIF_TXI );
   371     }
   372 }
   374 /**
   375  * Update the SCFSR2 status register with the given mask (ie clear any values
   376  * that are set to 0 in the mask. According to a strict reading of the doco
   377  * though, the bits will only actually clear if the flag state is no longer
   378  * true, so we need to recheck everything...
   379  */
   380 void SCIF_update_status( uint32_t mask )
   381 {
   382     uint32_t value = MMIO_READ( SCIF, SCFSR2 );
   383     uint32_t result = value & mask;
   384     uint32_t sendq_size = SCIF_sendq_size();
   385     uint32_t recvq_size = SCIF_recvq_size();
   387     if( sendq_size != 0 )
   388 	result |= SCFSR2_TEND;
   390     if( sendq_size <= SCIF_sendq.trigger )
   391 	result |= SCFSR2_TDFE;
   392     else if( result & SCFSR2_TDFE == 0 && IS_TRANSMIT_IRQ_ENABLED() )
   393 	intc_clear_interrupt( INT_SCIF_TXI );
   395     if( recvq_size >= SCIF_recvq.trigger )
   396 	result |= SCFSR2_RDF;
   397     if( (value & SCFSR2_DR) != 0 && (result & SCFSR2_DR) == 0 &&
   398 	recvq_size != 0 )
   399 	result |= SCFSR2_DR;
   400     if( (result & (SCFSR2_DR|SCFSR2_RDF)) == 0 && IS_RECEIVE_IRQ_ENABLED() )
   401 	intc_clear_interrupt( INT_SCIF_RXI );
   403     if( IS_RECEIVE_ERROR_IRQ_ENABLED() ) {
   404 	if( (result & SCFSR2_BRK) == 0 )
   405 	    intc_clear_interrupt( INT_SCIF_BRI );
   406 	if( (result & SCFSR2_ER) == 0 && 
   407 	    (MMIO_READ( SCIF, SCLSR2 ) & SCLSR2_ORER) == 0 )
   408 	    intc_clear_interrupt( INT_SCIF_ERI );
   409     }
   410 }
   412 /**
   413  * Set the break detected flag
   414  */
   415 void SCIF_set_break( void ) 
   416 {
   417     MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_BRK );
   418     if( IS_RECEIVE_ERROR_IRQ_ENABLED() )
   419 	intc_raise_interrupt( INT_SCIF_BRI );
   420 }
   422 const static int SCIF_CLOCK_MULTIPLIER[4] = {1, 4, 16, 64};
   424 /**
   425  * Calculate the current line speed.
   426  */
   427 void SCIF_update_line_speed( void )
   428 {
   429     /* If CKE1 is set, use the external clock as a base */
   430     if( MMIO_READ( SCIF, SCSCR2 ) & SCSCR2_CKE ) {
   433     } else {
   435 	/* Otherwise, SH4 peripheral clock divided by n */
   436 	int mult = SCIF_CLOCK_MULTIPLIER[MMIO_READ( SCIF, SCSMR2 ) & 0x03];
   438 	/* Then process the bitrate register */
   439 	int bbr = MMIO_READ( SCIF, SCBRR2 ) & 0xFF;
   441 	int baudrate = sh4_peripheral_freq / (32 * mult * (bbr+1) );
   443 	if( serial_device != NULL && serial_device->set_line_speed != NULL )
   444 	    serial_device->set_line_speed( baudrate );
   446 	SCIF_tick_period = sh4_peripheral_period * (32 * mult * (bbr+1));
   448 	/*
   449 	  clock_set_tick_rate( CLOCK_SCIF, baudrate / 10 );
   450 	*/
   451     }
   452 }
   454 int32_t mmio_region_SCIF_read( uint32_t reg )
   455 {
   456     switch( reg ) {
   457     case SCFRDR2: /* Receive data */
   458 	return SCIF_recvq_dequeue(FALSE);
   459     default:
   460 	return MMIO_READ( SCIF, reg );
   461     }
   462 }
   464 void mmio_region_SCIF_write( uint32_t reg, uint32_t val ) 
   465 {
   466     uint32_t tmp;
   467     switch( reg ) {
   468     case SCSMR2: /* Serial mode register */
   469 	/* Bit 6 => 0 = 8-bit, 1 = 7-bit
   470 	 * Bit 5 => 0 = Parity disabled, 1 = parity enabled
   471 	 * Bit 4 => 0 = Even parity, 1 = Odd parity
   472 	 * Bit 3 => 0 = 1 stop bit, 1 = 2 stop bits
   473 	 * Bits 0-1 => Clock select 00 = P, 01 = P/4, 10 = P/16, 11 = P/64
   474 	 */
   475 	val &= 0x007B;
   476 	if( serial_device != NULL ) {
   477 	    serial_device->set_line_params( val );
   478 	}
   479 	tmp = MMIO_READ( SCIF, SCSMR2 );
   480 	if( tmp & 0x03 != val & 0x03 ) {
   481 	    /* Clock change */
   482 	    SCIF_update_line_speed( );
   483 	}
   484 	/* Save for later read-back */
   485 	MMIO_WRITE( SCIF, SCSMR2, val );
   486 	break;
   487     case SCBRR2: /* Bit rate register */
   488 	MMIO_WRITE( SCIF, SCBRR2, val );
   489 	SCIF_update_line_speed( );
   490 	break;
   491     case SCSCR2: /* Serial control register */
   492 	/* Bit 7 => Transmit-FIFO-data-empty interrupt enabled 
   493 	 * Bit 6 => Receive-data-full interrupt enabled 
   494 	 * Bit 5 => Transmit enable 
   495 	 * Bit 4 => Receive enable 
   496 	 * Bit 3 => Receive-error/break interrupt enabled
   497 	 * Bit 1 => Clock enable
   498 	 */
   499 	val &= 0x00FA;
   500 	/* Clear any interrupts that just became disabled */
   501 	if( val & SCSCR2_TIE == 0 )
   502 	    intc_clear_interrupt( INT_SCIF_TXI );
   503 	if( val & SCSCR2_RIE == 0 )
   504 	    intc_clear_interrupt( INT_SCIF_RXI );
   505 	if( val & (SCSCR2_RIE|SCSCR2_REIE) == 0 ) {
   506 	    intc_clear_interrupt( INT_SCIF_ERI );
   507 	    intc_clear_interrupt( INT_SCIF_BRI );
   508 	}
   510 	MMIO_WRITE( SCIF, reg, val );
   511 	break;
   512     case SCFTDR2: /* Transmit FIFO data register */
   513 	SCIF_sendq_enqueue( val, FALSE );
   514 	break;
   515     case SCFSR2: /* Serial status register */
   516 	/* Bits 12-15 Parity error count
   517 	 * Bits 8-11 Framing erro count 
   518 	 * Bit 7 - Receive error
   519 	 * Bit 6 - Transmit end
   520 	 * Bit 5 - Transmit FIFO data empty
   521 	 * Bit 4 - Break detect
   522 	 * Bit 3 - Framing error
   523 	 * Bit 2 - Parity error
   524 	 * Bit 1 - Receive FIFO data full
   525 	 * Bit 0 - Receive data ready
   526 	 */
   527 	/* Clear off any flags/interrupts that are being set to 0 */
   528 	SCIF_update_status( val );
   529 	break;
   530     case SCFCR2: /* FIFO control register */
   531 	val &= 0x0F;
   532 	SCIF_recvq.trigger = SCIF_recvq_triggers[val >> 6];
   533 	SCIF_sendq.trigger = SCIF_sendq_triggers[(val >> 4) & 0x03];
   534 	if( val & SCFCR2_TFRST ) {
   535 	    SCIF_sendq_clear();
   536 	}
   537 	if( val & SCFCR2_RFRST ) {
   538 	    SCIF_recvq_clear();
   539 	}
   541 	MMIO_WRITE( SCIF, reg, val );
   542 	break;
   543     case SCSPTR2: /* Serial Port Register */
   544 	MMIO_WRITE( SCIF, reg, val );
   545 	/* NOT IMPLEMENTED */
   546 	WARN( "SCSPTR2 not implemented: Write %08X", val );
   547 	break;
   548     case SCLSR2:
   549 	val = val & SCLSR2_ORER;
   550 	if( val == 0 ) {
   551 	    MMIO_WRITE( SCIF, SCLSR2, val );
   552 	    if( (MMIO_READ( SCIF, SCFSR2 ) & SCFSR2_ER) == 0 &&
   553 		IS_RECEIVE_ERROR_IRQ_ENABLED() ) 
   554 		intc_clear_interrupt( INT_SCIF_ERI );
   555 	}
   557 	break;
   558     }
   559 }
   561 /**
   562  * Actions for a single tick of the serial clock, defined as the transmission
   563  * time of a single frame.
   564  *
   565  * If transmit queue is non-empty:
   566  *    Transmit one byte and remove from queue
   567  * If input receive source is non-empty:
   568  *    Transfer one byte to the receive queue (if queue is full, byte is lost)
   569  * If recvq is non-empty, less than the trigger level, and no data has been
   570  *    received in the last 2 ticks (including this one), set the DR flag and
   571  *    IRQ if appropriate.
   572  */
   573 void SCIF_clock_tick( void ) 
   574 {
   575     gboolean rcvd = FALSE;
   577     if( IS_LOOPBACK_ENABLED() ) {
   578 	if( IS_TRANSMIT_ENABLED() ) {
   579 	    int val = SCIF_sendq_dequeue();
   580 	    if( val != -1 && IS_RECEIVE_ENABLED() ) {
   581 		SCIF_recvq_enqueue( val );
   582 		rcvd = TRUE;
   583 	    }
   584 	}
   585     } else {
   586 	if( IS_TRANSMIT_ENABLED() ) {
   587 	    int val = SCIF_sendq_dequeue();
   588 	    if( val != -1 && serial_device != NULL && 
   589 		serial_device->receive_data != NULL ) {
   590 		serial_device->receive_data( val );
   591 	    }
   592 	}
   594 	if( IS_RECEIVE_ENABLED() ) {
   595 	    int val = serial_transmit_dequeue();
   596 	    if( val != -1 ) {
   597 		SCIF_recvq_enqueue( val );
   598 		rcvd = TRUE;
   599 	    }
   600 	}
   601     }
   603     /* Check if we need to set the DR flag */
   604     if( !rcvd && !SCIF_rcvd_last_tick &&
   605 	SCIF_recvq.head != SCIF_recvq.tail &&
   606 	SCIF_recvq_size() < SCIF_recvq.trigger ) {
   607 	uint32_t tmp = MMIO_READ( SCIF, SCFSR2 );
   608 	if( tmp & SCFSR2_DR == 0 ) {
   609 	    MMIO_WRITE( SCIF, SCFSR2, tmp | SCFSR2_DR );
   610 	    if( IS_RECEIVE_IRQ_ENABLED() )
   611 		intc_raise_interrupt( INT_SCIF_RXI );
   612 	}
   613     }
   614     SCIF_rcvd_last_tick = rcvd;
   615 }
   617 void SCIF_reset( void )
   618 {
   619     SCIF_recvq_clear();
   620     SCIF_sendq_clear();
   621     SCIF_update_line_speed();
   622 }
   624 void SCIF_run_slice( uint32_t nanosecs ) 
   625 {
   626     SCIF_tick_remainder += nanosecs;
   627     while( SCIF_tick_remainder >= SCIF_tick_period ) {
   628 	SCIF_tick_remainder -= SCIF_tick_period;
   629 	SCIF_clock_tick();
   630     }
   631 }
.