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 Tue Jan 13 11:56:28 2009 +0000 (11 years ago)
permissions -rw-r--r--
last change Merge lxdream-mem branch back to trunk
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 }
.