Search
lxdream.org :: lxdream/src/sh4/scif.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/sh4/scif.c
changeset 1078:d8f1cf224e7e
prev1077:136fc24d17ef
author nkeynes
date Fri May 29 18:47:05 2015 +1000 (5 years ago)
permissions -rw-r--r--
last change Fix test case
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);
    31 void SCIF_run_to(uint32_t nanosecs);
    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 serial_device_t serial_get_device( )
    59 {
    60     return serial_device;
    61 }
    63 serial_device_t serial_attach_device( serial_device_t dev ) 
    64 {
    65     serial_device_t olddev = serial_device;
    66     if( serial_device != NULL )
    67         serial_detach_device();
    68     serial_device = dev;
    69     if( serial_device != NULL && serial_device->attach != NULL )
    70         serial_device->attach(serial_device);
    71     return olddev;
    72 }
    75 serial_device_t serial_detach_device( void )
    76 {
    77     serial_device_t dev = serial_device;
    78     if( serial_device != NULL && serial_device->detach != NULL ) {
    79         serial_device->detach(serial_device);
    80     }
    81     serial_device = NULL;
    82     return dev;
    83 }
    85 void serial_destroy_device( serial_device_t dev )
    86 {
    87     if( dev != NULL ) {
    88         if( serial_device == dev )
    89             serial_detach_device();
    90         if( dev->destroy )
    91             dev->destroy(dev);
    92     }
    93 }
    95 /**
    96  * Add a block of data to the serial receive queue. The data will be received
    97  * by the CPU at the appropriate baud rate.
    98  */
    99 void serial_transmit_data( char *data, int length ) {
   100     if( length == 0 )
   101         return;
   102     serial_data_block_t block = 
   103         g_malloc( sizeof( struct serial_data_block ) + length );
   104     block->length = length;
   105     block->offset = 0;
   106     block->next = NULL;
   107     memcpy( block->data, data, length );
   109     if( serial_recvq_head == NULL ) {
   110         serial_recvq_head = serial_recvq_tail = block;
   111     } else {
   112         serial_recvq_tail->next = block;
   113         serial_recvq_tail = block;
   114     }
   115 }
   117 /**
   118  * Dequeue a byte from the serial input queue
   119  */
   120 static int serial_transmit_dequeue( ) {
   121     if( serial_recvq_head != NULL ) {
   122         uint8_t val = serial_recvq_head->data[serial_recvq_head->offset++];
   123         if( serial_recvq_head->offset >= serial_recvq_head->length ) {
   124             serial_data_block_t next = serial_recvq_head->next;
   125             g_free( serial_recvq_head );
   126             serial_recvq_head = next;
   127             if( next == NULL )
   128                 serial_recvq_tail = NULL;
   129         }
   130         return (int)(unsigned int)val;
   131     }
   132     return -1;
   134 }
   136 void serial_transmit_break() {
   137     SCIF_set_break();
   138 }
   140 /********************************* SCIF *************************************/
   142 #define FIFO_LENGTH 16
   143 #define FIFO_ARR_LENGTH (FIFO_LENGTH+1)
   145 /* Serial control register flags */
   146 #define SCSCR2_TIE  0x80
   147 #define SCSCR2_RIE  0x40
   148 #define SCSCR2_TE   0x20
   149 #define SCSCR2_RE   0x10
   150 #define SCSCR2_REIE 0x08
   151 #define SCSCR2_CKE 0x02
   153 #define IS_TRANSMIT_IRQ_ENABLED() (MMIO_READ(SCIF,SCSCR2) & SCSCR2_TIE)
   154 #define IS_RECEIVE_IRQ_ENABLED() (MMIO_READ(SCIF,SCSCR2) & SCSCR2_RIE)
   155 #define IS_RECEIVE_ERROR_IRQ_ENABLED() (MMIO_READ(SCIF,SCSCR2) & (SCSCR2_RIE|SCSCR2_REIE))
   156 /* Receive is enabled if the RE bit is set in SCSCR2, and the ORER bit is cleared in SCLSR2 */
   157 #define IS_RECEIVE_ENABLED() ( (MMIO_READ(SCIF,SCSCR2) & SCSCR2_RE) && ((MMIO_READ(SCIF,SCLSR2) & SCLSR2_ORER) == 0) )
   158 /* Transmit is enabled if the TE bit is set in SCSCR2 */
   159 #define IS_TRANSMIT_ENABLED() (MMIO_READ(SCIF,SCSCR2) & SCSCR2_TE)
   160 #define IS_LOOPBACK_ENABLED() (MMIO_READ(SCIF,SCFCR2) & SCFCR2_LOOP)
   162 /* Serial status register flags */
   163 #define SCFSR2_ER   0x80
   164 #define SCFSR2_TEND 0x40
   165 #define SCFSR2_TDFE 0x20
   166 #define SCFSR2_BRK  0x10
   167 #define SCFSR2_RDF  0x02
   168 #define SCFSR2_DR   0x01
   170 /* FIFO control register flags */
   171 #define SCFCR2_MCE   0x08
   172 #define SCFCR2_TFRST 0x04
   173 #define SCFCR2_RFRST 0x02
   174 #define SCFCR2_LOOP  0x01
   176 /* Line Status Register */
   177 #define SCLSR2_ORER 0x01
   179 struct SCIF_fifo {
   180     int head;
   181     int tail;
   182     int trigger;
   183     uint8_t data[FIFO_ARR_LENGTH];
   184 };
   186 int SCIF_recvq_triggers[4] = {1, 4, 8, 14};
   187 struct SCIF_fifo SCIF_recvq = {0,0,1};
   189 int SCIF_sendq_triggers[4] = {8, 4, 2, 1};
   190 struct SCIF_fifo SCIF_sendq = {0,0,8};
   192 /**
   193  * Flag to indicate if data was received (ie added to the receive queue)
   194  * during the last SCIF clock tick. Used to determine when to set the DR
   195  * flag.
   196  */
   197 gboolean SCIF_rcvd_last_tick = FALSE;
   199 uint32_t SCIF_tick_period = 0;
   200 uint32_t SCIF_tick_remainder = 0;
   201 uint32_t SCIF_slice_cycle = 0;
   203 void SCIF_save_state( FILE *f ) 
   204 {
   205     fwrite( &SCIF_recvq, sizeof(SCIF_recvq), 1, f );
   206     fwrite( &SCIF_sendq, sizeof(SCIF_sendq), 1, f );
   207     fwrite( &SCIF_rcvd_last_tick, sizeof(gboolean), 1, f );
   209 }
   211 int SCIF_load_state( FILE *f ) 
   212 {
   213     fread( &SCIF_recvq, sizeof(SCIF_recvq), 1, f );
   214     fread( &SCIF_sendq, sizeof(SCIF_sendq), 1, f );
   215     fread( &SCIF_rcvd_last_tick, sizeof(gboolean), 1, f );
   216     return 0;
   217 }
   219 static inline uint8_t SCIF_recvq_size( ) 
   220 {
   221     int val = SCIF_recvq.tail - SCIF_recvq.head;
   222     if( val < 0 ) {
   223         val = FIFO_ARR_LENGTH - SCIF_recvq.head + SCIF_recvq.tail;
   224     }
   225     return val;
   226 }
   228 int SCIF_recvq_dequeue( gboolean clearFlags )
   229 {
   230     uint8_t result;
   231     uint32_t tmp, length;
   232     if( SCIF_recvq.head == SCIF_recvq.tail )
   233         return -1; /* No data */
   234     result = SCIF_recvq.data[SCIF_recvq.head++];
   235     if( SCIF_recvq.head > FIFO_LENGTH )
   236         SCIF_recvq.head = 0;
   238     /* Update data count register */
   239     tmp = MMIO_READ( SCIF, SCFDR2 ) & 0xF0;
   240     length = SCIF_recvq_size();
   241     MMIO_WRITE( SCIF, SCFDR2, tmp | length );
   243     /* Clear flags (if requested ) */
   244     if( clearFlags && length < SCIF_recvq.trigger ) {
   245         tmp = SCFSR2_RDF;
   246         if( length == 0 )
   247             tmp |= SCFSR2_DR;
   248         tmp = MMIO_READ( SCIF, SCFSR2 ) & (~tmp);
   249         MMIO_WRITE( SCIF, SCFSR2, tmp );
   250         /* If both flags are cleared, clear the interrupt as well */
   251         if( (tmp & (SCFSR2_DR|SCFSR2_RDF)) == 0 && IS_RECEIVE_IRQ_ENABLED() )
   252             intc_clear_interrupt( INT_SCIF_RXI );
   253     }
   255     return (int)(unsigned int)result;
   256 }
   258 gboolean SCIF_recvq_enqueue( uint8_t value )
   259 {
   260     uint32_t tmp, length;
   261     int newpos = SCIF_recvq.tail + 1;
   262     if( newpos > FIFO_LENGTH )
   263         newpos = 0;
   264     if( newpos == SCIF_recvq.head ) {
   265         /* FIFO full - set ORER and discard the value */
   266         MMIO_WRITE( SCIF, SCLSR2, SCLSR2_ORER );
   267         if( IS_RECEIVE_ERROR_IRQ_ENABLED() )
   268             intc_raise_interrupt( INT_SCIF_ERI );
   269         return FALSE;
   270     }
   271     SCIF_recvq.data[SCIF_recvq.tail] = value;
   273     /* Update data count register */
   274     tmp = MMIO_READ( SCIF, SCFDR2 ) & 0xF0;
   275     length = SCIF_recvq_size();
   276     MMIO_WRITE( SCIF, SCFDR2, tmp | length );
   278     /* Update status register */
   279     tmp = MMIO_READ( SCIF, SCFSR2 );
   280     if( length >= SCIF_recvq.trigger ) {
   281         tmp |= SCFSR2_RDF;
   282         if( IS_RECEIVE_IRQ_ENABLED() ) 
   283             intc_raise_interrupt( INT_SCIF_RXI );
   284         DMAC_trigger( DMAC_SCIF_RDF );
   285     }
   286     MMIO_WRITE( SCIF, SCFSR2, tmp );
   287     return TRUE;
   288 }
   291 /**
   292  * Reset the receive FIFO to its initial state. Manual is unclear as to
   293  * whether this also clears flags/interrupts, but we're assuming here that
   294  * it does until proven otherwise.
   295  */
   296 void SCIF_recvq_clear( void ) 
   297 {
   298     SCIF_recvq.head = SCIF_recvq.tail = 0;
   299     MMIO_WRITE( SCIF, SCFDR2, MMIO_READ( SCIF, SCFDR2 ) & 0xF0 );
   300     MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) & ~(SCFSR2_DR|SCFSR2_RDF) );
   301     if( IS_RECEIVE_IRQ_ENABLED() )
   302         intc_clear_interrupt( INT_SCIF_RXI );
   303 }
   305 static inline uint8_t SCIF_sendq_size( ) 
   306 {
   307     int val = SCIF_sendq.tail - SCIF_sendq.head;
   308     if( val < 0 ) {
   309         val = FIFO_ARR_LENGTH - SCIF_sendq.head + SCIF_sendq.tail;
   310     }
   311     return val;
   312 }
   314 /**
   315  * Dequeue one byte from the SCIF transmit queue (ie transmit the byte),
   316  * updating all status flags as required.
   317  * @return The byte dequeued, or -1 if the queue is empty.
   318  */
   319 int SCIF_sendq_dequeue( )
   320 {
   321     uint8_t result;
   322     uint32_t tmp, length;
   323     if( SCIF_sendq.head == SCIF_sendq.tail )
   324         return -1; /* No data */
   326     /* Update queue head pointer */
   327     result = SCIF_sendq.data[SCIF_sendq.head++];
   328     if( SCIF_sendq.head > FIFO_LENGTH )
   329         SCIF_sendq.head = 0;
   331     /* Update data count register */
   332     tmp = MMIO_READ( SCIF, SCFDR2 ) & 0x0F;
   333     length = SCIF_sendq_size();
   334     MMIO_WRITE( SCIF, SCFDR2, tmp | (length << 8) );
   336     /* Update status register */
   337     if( length <= SCIF_sendq.trigger ) {
   338         tmp = MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_TDFE;
   339         if( length == 0 )
   340             tmp |= SCFSR2_TEND; /* Transmission ended - no data waiting */
   341         if( IS_TRANSMIT_IRQ_ENABLED() ) 
   342             intc_raise_interrupt( INT_SCIF_TXI );
   343         DMAC_trigger( DMAC_SCIF_TDE );
   344         MMIO_WRITE( SCIF, SCFSR2, tmp );
   345     }
   346     return (int)(unsigned int)result;
   347 }
   349 /**
   350  * Enqueue a single byte in the SCIF transmit queue. If the queue is full,
   351  * the value will be discarded.
   352  * @param value to be queued.
   353  * @param clearFlags TRUE if the TEND/TDFE flags should be cleared
   354  *   if the queue exceeds the trigger level. (According to the manual,
   355  *   DMAC writes will clear the flag, whereas regular SH4 writes do NOT
   356  *   automatically clear it. Go figure).
   357  * @return gboolean TRUE if the value was queued, FALSE if the queue was
   358  *   full.
   359  */
   360 gboolean SCIF_sendq_enqueue( uint8_t value, gboolean clearFlags )
   361 {
   362     uint32_t tmp, length;
   363     int newpos = SCIF_sendq.tail + 1;
   364     if( newpos > FIFO_LENGTH )
   365         newpos = 0;
   366     if( newpos == SCIF_sendq.head ) {
   367         /* FIFO full - discard */
   368         return FALSE;
   369     }
   370     SCIF_sendq.data[SCIF_sendq.tail] = value;
   371     SCIF_sendq.tail = newpos;
   373     /* Update data count register */
   374     tmp = MMIO_READ( SCIF, SCFDR2 ) & 0x0F;
   375     length = SCIF_sendq_size();
   376     MMIO_WRITE( SCIF, SCFDR2, tmp | (length << 8) );
   378     /* Update flags if requested */
   379     if( clearFlags ) {
   380         tmp = SCFSR2_TEND;
   381         if( length > SCIF_sendq.trigger ) {
   382             tmp |= SCFSR2_TDFE;
   383             if( IS_TRANSMIT_IRQ_ENABLED() )
   384                 intc_clear_interrupt( INT_SCIF_TXI );
   385         }
   386         tmp = MMIO_READ( SCIF, SCFSR2 ) & (~tmp);
   387         MMIO_WRITE( SCIF, SCFSR2, tmp );
   388     }
   389     return TRUE;
   390 }
   392 void SCIF_sendq_clear( void ) 
   393 {
   394     SCIF_sendq.head = SCIF_sendq.tail = 0;
   395     MMIO_WRITE( SCIF, SCFDR2, MMIO_READ( SCIF, SCFDR2 ) & 0x0F );
   396     MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_TEND | SCFSR2_TDFE );
   397     if( IS_TRANSMIT_IRQ_ENABLED() ) {
   398         intc_raise_interrupt( INT_SCIF_TXI );
   399         DMAC_trigger( DMAC_SCIF_TDE );
   400     }
   401 }
   403 /**
   404  * Update the SCFSR2 status register with the given mask (ie clear any values
   405  * that are set to 0 in the mask. According to a strict reading of the doco
   406  * though, the bits will only actually clear if the flag state is no longer
   407  * true, so we need to recheck everything...
   408  */
   409 void SCIF_update_status( uint32_t mask )
   410 {
   411     uint32_t value = MMIO_READ( SCIF, SCFSR2 );
   412     uint32_t result = value & mask;
   413     uint32_t sendq_size = SCIF_sendq_size();
   414     uint32_t recvq_size = SCIF_recvq_size();
   416     if( sendq_size != 0 )
   417         result |= SCFSR2_TEND;
   419     if( sendq_size <= SCIF_sendq.trigger )
   420         result |= SCFSR2_TDFE;
   421     else if( (result & SCFSR2_TDFE) == 0 && IS_TRANSMIT_IRQ_ENABLED() )
   422         intc_clear_interrupt( INT_SCIF_TXI );
   424     if( recvq_size >= SCIF_recvq.trigger )
   425         result |= SCFSR2_RDF;
   426     if( (value & SCFSR2_DR) != 0 && (result & SCFSR2_DR) == 0 &&
   427             recvq_size != 0 )
   428         result |= SCFSR2_DR;
   429     if( (result & (SCFSR2_DR|SCFSR2_RDF)) == 0 && IS_RECEIVE_IRQ_ENABLED() )
   430         intc_clear_interrupt( INT_SCIF_RXI );
   432     if( IS_RECEIVE_ERROR_IRQ_ENABLED() ) {
   433         if( (result & SCFSR2_BRK) == 0 )
   434             intc_clear_interrupt( INT_SCIF_BRI );
   435         if( (result & SCFSR2_ER) == 0 && 
   436                 (MMIO_READ( SCIF, SCLSR2 ) & SCLSR2_ORER) == 0 )
   437             intc_clear_interrupt( INT_SCIF_ERI );
   438     }
   439     MMIO_WRITE( SCIF, SCFSR2, result );
   440 }
   442 /**
   443  * Set the break detected flag
   444  */
   445 void SCIF_set_break( void ) 
   446 {
   447     MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_BRK );
   448     if( IS_RECEIVE_ERROR_IRQ_ENABLED() )
   449         intc_raise_interrupt( INT_SCIF_BRI );
   450 }
   452 const static int SCIF_CLOCK_MULTIPLIER[4] = {1, 4, 16, 64};
   454 /**
   455  * Calculate the current line speed.
   456  */
   457 void SCIF_update_line_speed( void )
   458 {
   459     /* If CKE1 is set, use the external clock as a base */
   460     if( MMIO_READ( SCIF, SCSCR2 ) & SCSCR2_CKE ) {
   463     } else {
   465         /* Otherwise, SH4 peripheral clock divided by n */
   466         int mult = SCIF_CLOCK_MULTIPLIER[MMIO_READ( SCIF, SCSMR2 ) & 0x03];
   468         /* Then process the bitrate register */
   469         int bbr = MMIO_READ( SCIF, SCBRR2 ) & 0xFF;
   471         SCIF_tick_period = sh4_peripheral_period * (32 * mult * (bbr+1));
   472         int baudrate = 1000000000 / SCIF_tick_period;
   474         if( serial_device != NULL && serial_device->set_line_speed != NULL )
   475             serial_device->set_line_speed( serial_device, baudrate );
   478         /*
   479 	  clock_set_tick_rate( CLOCK_SCIF, baudrate / 10 );
   480          */
   481     }
   482 }
   484 MMIO_REGION_READ_FN( SCIF, reg )
   485 {
   486     SCIF_run_to(sh4r.slice_cycle);
   487     reg &= 0xFFF;
   488     switch( reg ) {
   489     case SCFRDR2: /* Receive data */
   490         return SCIF_recvq_dequeue(FALSE);
   491     default:
   492         return MMIO_READ( SCIF, reg );
   493     }
   494 }
   495 MMIO_REGION_READ_DEFSUBFNS(SCIF)
   498 MMIO_REGION_WRITE_FN( SCIF, reg, val )
   499 {
   500     SCIF_run_to(sh4r.slice_cycle);
   501     uint32_t tmp;
   502     reg &= 0xFFF;
   503     switch( reg ) {
   504     case SCSMR2: /* Serial mode register */
   505         /* Bit 6 => 0 = 8-bit, 1 = 7-bit
   506          * Bit 5 => 0 = Parity disabled, 1 = parity enabled
   507          * Bit 4 => 0 = Even parity, 1 = Odd parity
   508          * Bit 3 => 0 = 1 stop bit, 1 = 2 stop bits
   509          * Bits 0-1 => Clock select 00 = P, 01 = P/4, 10 = P/16, 11 = P/64
   510          */
   511         val &= 0x007B;
   512         if( serial_device != NULL ) {
   513             serial_device->set_line_params( serial_device, val );
   514         }
   515         tmp = MMIO_READ( SCIF, SCSMR2 );
   516         if( (tmp & 0x03) != (val & 0x03) ) {
   517             /* Clock change */
   518             SCIF_update_line_speed( );
   519         }
   520         /* Save for later read-back */
   521         MMIO_WRITE( SCIF, SCSMR2, val );
   522         break;
   523     case SCBRR2: /* Bit rate register */
   524         MMIO_WRITE( SCIF, SCBRR2, val );
   525         SCIF_update_line_speed( );
   526         break;
   527     case SCSCR2: /* Serial control register */
   528         /* Bit 7 => Transmit-FIFO-data-empty interrupt enabled 
   529          * Bit 6 => Receive-data-full interrupt enabled 
   530          * Bit 5 => Transmit enable 
   531          * Bit 4 => Receive enable 
   532          * Bit 3 => Receive-error/break interrupt enabled
   533          * Bit 1 => Clock enable
   534          */
   535         val &= 0x00FA;
   536         /* Clear any interrupts that just became disabled */
   537         if( (val & SCSCR2_TIE) == 0 )
   538             intc_clear_interrupt( INT_SCIF_TXI );
   539         if( (val & SCSCR2_RIE) == 0 )
   540             intc_clear_interrupt( INT_SCIF_RXI );
   541         if( (val & (SCSCR2_RIE|SCSCR2_REIE)) == 0 ) {
   542             intc_clear_interrupt( INT_SCIF_ERI );
   543             intc_clear_interrupt( INT_SCIF_BRI );
   544         }
   546         MMIO_WRITE( SCIF, reg, val );
   547         break;
   548     case SCFTDR2: /* Transmit FIFO data register */
   549         SCIF_sendq_enqueue( val, FALSE );
   550         break;
   551     case SCFSR2: /* Serial status register */
   552         /* Bits 12-15 Parity error count
   553          * Bits 8-11 Framing erro count 
   554          * Bit 7 - Receive error
   555          * Bit 6 - Transmit end
   556          * Bit 5 - Transmit FIFO data empty
   557          * Bit 4 - Break detect
   558          * Bit 3 - Framing error
   559          * Bit 2 - Parity error
   560          * Bit 1 - Receive FIFO data full
   561          * Bit 0 - Receive data ready
   562          */
   563         /* Clear off any flags/interrupts that are being set to 0 */
   564         SCIF_update_status( val );
   565         break;
   566     case SCFCR2: /* FIFO control register */
   567         val &= 0x0F;
   568         SCIF_recvq.trigger = SCIF_recvq_triggers[val >> 6];
   569         SCIF_sendq.trigger = SCIF_sendq_triggers[(val >> 4) & 0x03];
   570         if( val & SCFCR2_TFRST ) {
   571             SCIF_sendq_clear();
   572         }
   573         if( val & SCFCR2_RFRST ) {
   574             SCIF_recvq_clear();
   575         }
   577         MMIO_WRITE( SCIF, reg, val );
   578         break;
   579     case SCSPTR2: /* Serial Port Register */
   580         MMIO_WRITE( SCIF, reg, val );
   581         /* NOT IMPLEMENTED - 'direct' serial I/O */
   582         if( val != 0 ) {
   583             WARN( "SCSPTR2 not implemented: Write %08X", val );
   584         }
   585         break;
   586     case SCLSR2:
   587         val = val & SCLSR2_ORER;
   588         if( val == 0 ) {
   589             MMIO_WRITE( SCIF, SCLSR2, val );
   590             if( (MMIO_READ( SCIF, SCFSR2 ) & SCFSR2_ER) == 0 &&
   591                     IS_RECEIVE_ERROR_IRQ_ENABLED() ) 
   592                 intc_clear_interrupt( INT_SCIF_ERI );
   593         }
   595         break;
   596     }
   597 }
   599 /**
   600  * Actions for a single tick of the serial clock, defined as the transmission
   601  * time of a single frame.
   602  *
   603  * If transmit queue is non-empty:
   604  *    Transmit one byte and remove from queue
   605  * If input receive source is non-empty:
   606  *    Transfer one byte to the receive queue (if queue is full, byte is lost)
   607  * If recvq is non-empty, less than the trigger level, and no data has been
   608  *    received in the last 2 ticks (including this one), set the DR flag and
   609  *    IRQ if appropriate.
   610  */
   611 void SCIF_clock_tick( void ) 
   612 {
   613     gboolean rcvd = FALSE;
   615     if( IS_LOOPBACK_ENABLED() ) {
   616         if( IS_TRANSMIT_ENABLED() ) {
   617             int val = SCIF_sendq_dequeue();
   618             if( val != -1 && IS_RECEIVE_ENABLED() ) {
   619                 SCIF_recvq_enqueue( val );
   620                 rcvd = TRUE;
   621             }
   622         }
   623     } else {
   624         if( IS_TRANSMIT_ENABLED() ) {
   625             int val = SCIF_sendq_dequeue();
   626             if( val != -1 && serial_device != NULL && 
   627                     serial_device->receive_data != NULL ) {
   628                 serial_device->receive_data( serial_device, val );
   629             }
   630         }
   632         if( IS_RECEIVE_ENABLED() ) {
   633             int val = serial_transmit_dequeue();
   634             if( val != -1 ) {
   635                 SCIF_recvq_enqueue( val );
   636                 rcvd = TRUE;
   637             }
   638         }
   639     }
   641     /* Check if we need to set the DR flag */
   642     if( !rcvd && !SCIF_rcvd_last_tick &&
   643             SCIF_recvq.head != SCIF_recvq.tail &&
   644             SCIF_recvq_size() < SCIF_recvq.trigger ) {
   645         uint32_t tmp = MMIO_READ( SCIF, SCFSR2 );
   646         if( (tmp & SCFSR2_DR) == 0 ) {
   647             MMIO_WRITE( SCIF, SCFSR2, tmp | SCFSR2_DR );
   648             if( IS_RECEIVE_IRQ_ENABLED() )
   649                 intc_raise_interrupt( INT_SCIF_RXI );
   650             DMAC_trigger( DMAC_SCIF_RDF );
   651         }
   652     }
   653     SCIF_rcvd_last_tick = rcvd;
   654 }
   656 void SCIF_reset( void )
   657 {
   658     SCIF_recvq_clear();
   659     SCIF_sendq_clear();
   660     SCIF_update_line_speed();
   661 }
   663 void SCIF_run_to( uint32_t nanosecs )
   664 {
   665     SCIF_tick_remainder += nanosecs - SCIF_slice_cycle;
   666     while( SCIF_tick_remainder >= SCIF_tick_period ) {
   667         SCIF_tick_remainder -= SCIF_tick_period;
   668         SCIF_clock_tick();
   669     }
   670     SCIF_slice_cycle = nanosecs;
   671 }
   673 void SCIF_run_slice( uint32_t nanosecs )
   674 {
   675     SCIF_run_to(nanosecs);
   676     SCIF_slice_cycle = 0;
   677 }
.