--- a/src/sh4/scif.c Tue Jan 01 05:08:38 2008 +0000 +++ b/src/sh4/scif.c Wed Jul 30 03:00:40 2008 +0000 @@ -58,7 +58,7 @@ void serial_attach_device( serial_device_t dev ) { if( serial_device != NULL ) - serial_detach_device(); + serial_detach_device(); serial_device = dev; } @@ -74,19 +74,19 @@ */ void serial_transmit_data( char *data, int length ) { if( length == 0 ) - return; + return; serial_data_block_t block = - g_malloc( sizeof( struct serial_data_block ) + length ); + g_malloc( sizeof( struct serial_data_block ) + length ); block->length = length; block->offset = 0; block->next = NULL; memcpy( block->data, data, length ); - + if( serial_recvq_head == NULL ) { - serial_recvq_head = serial_recvq_tail = block; + serial_recvq_head = serial_recvq_tail = block; } else { - serial_recvq_tail->next = block; - serial_recvq_tail = block; + serial_recvq_tail->next = block; + serial_recvq_tail = block; } } @@ -95,15 +95,15 @@ */ static int serial_transmit_dequeue( ) { if( serial_recvq_head != NULL ) { - uint8_t val = serial_recvq_head->data[serial_recvq_head->offset++]; - if( serial_recvq_head->offset >= serial_recvq_head->length ) { - serial_data_block_t next = serial_recvq_head->next; - g_free( serial_recvq_head ); - serial_recvq_head = next; - if( next == NULL ) - serial_recvq_tail = NULL; - } - return (int)(unsigned int)val; + uint8_t val = serial_recvq_head->data[serial_recvq_head->offset++]; + if( serial_recvq_head->offset >= serial_recvq_head->length ) { + serial_data_block_t next = serial_recvq_head->next; + g_free( serial_recvq_head ); + serial_recvq_head = next; + if( next == NULL ) + serial_recvq_tail = NULL; + } + return (int)(unsigned int)val; } return -1; @@ -195,7 +195,7 @@ { int val = SCIF_recvq.tail - SCIF_recvq.head; if( val < 0 ) { - val = FIFO_ARR_LENGTH - SCIF_recvq.head + SCIF_recvq.tail; + val = FIFO_ARR_LENGTH - SCIF_recvq.head + SCIF_recvq.tail; } return val; } @@ -205,10 +205,10 @@ uint8_t result; uint32_t tmp, length; if( SCIF_recvq.head == SCIF_recvq.tail ) - return -1; /* No data */ + return -1; /* No data */ result = SCIF_recvq.data[SCIF_recvq.head++]; if( SCIF_recvq.head > FIFO_LENGTH ) - SCIF_recvq.head = 0; + SCIF_recvq.head = 0; /* Update data count register */ tmp = MMIO_READ( SCIF, SCFDR2 ) & 0xF0; @@ -217,16 +217,16 @@ /* Clear flags (if requested ) */ if( clearFlags && length < SCIF_recvq.trigger ) { - tmp = SCFSR2_RDF; - if( length == 0 ) - tmp |= SCFSR2_DR; - tmp = MMIO_READ( SCIF, SCFSR2 ) & (~tmp); - MMIO_WRITE( SCIF, SCFSR2, tmp ); - /* If both flags are cleared, clear the interrupt as well */ - if( (tmp & (SCFSR2_DR|SCFSR2_RDF)) == 0 && IS_RECEIVE_IRQ_ENABLED() ) - intc_clear_interrupt( INT_SCIF_RXI ); + tmp = SCFSR2_RDF; + if( length == 0 ) + tmp |= SCFSR2_DR; + tmp = MMIO_READ( SCIF, SCFSR2 ) & (~tmp); + MMIO_WRITE( SCIF, SCFSR2, tmp ); + /* If both flags are cleared, clear the interrupt as well */ + if( (tmp & (SCFSR2_DR|SCFSR2_RDF)) == 0 && IS_RECEIVE_IRQ_ENABLED() ) + intc_clear_interrupt( INT_SCIF_RXI ); } - + return (int)(unsigned int)result; } @@ -235,13 +235,13 @@ uint32_t tmp, length; int newpos = SCIF_recvq.tail + 1; if( newpos > FIFO_LENGTH ) - newpos = 0; + newpos = 0; if( newpos == SCIF_recvq.head ) { - /* FIFO full - set ORER and discard the value */ - MMIO_WRITE( SCIF, SCLSR2, SCLSR2_ORER ); - if( IS_RECEIVE_ERROR_IRQ_ENABLED() ) - intc_raise_interrupt( INT_SCIF_ERI ); - return FALSE; + /* FIFO full - set ORER and discard the value */ + MMIO_WRITE( SCIF, SCLSR2, SCLSR2_ORER ); + if( IS_RECEIVE_ERROR_IRQ_ENABLED() ) + intc_raise_interrupt( INT_SCIF_ERI ); + return FALSE; } SCIF_recvq.data[SCIF_recvq.tail] = value; @@ -253,9 +253,9 @@ /* Update status register */ tmp = MMIO_READ( SCIF, SCFSR2 ); if( length >= SCIF_recvq.trigger ) { - tmp |= SCFSR2_RDF; - if( IS_RECEIVE_IRQ_ENABLED() ) - intc_raise_interrupt( INT_SCIF_RXI ); + tmp |= SCFSR2_RDF; + if( IS_RECEIVE_IRQ_ENABLED() ) + intc_raise_interrupt( INT_SCIF_RXI ); DMAC_trigger( DMAC_SCIF_RDF ); } MMIO_WRITE( SCIF, SCFSR2, tmp ); @@ -274,14 +274,14 @@ MMIO_WRITE( SCIF, SCFDR2, MMIO_READ( SCIF, SCFDR2 ) & 0xF0 ); MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) & ~(SCFSR2_DR|SCFSR2_RDF) ); if( IS_RECEIVE_IRQ_ENABLED() ) - intc_clear_interrupt( INT_SCIF_RXI ); + intc_clear_interrupt( INT_SCIF_RXI ); } static inline uint8_t SCIF_sendq_size( ) { int val = SCIF_sendq.tail - SCIF_sendq.head; if( val < 0 ) { - val = FIFO_ARR_LENGTH - SCIF_sendq.head + SCIF_sendq.tail; + val = FIFO_ARR_LENGTH - SCIF_sendq.head + SCIF_sendq.tail; } return val; } @@ -296,27 +296,27 @@ uint8_t result; uint32_t tmp, length; if( SCIF_sendq.head == SCIF_sendq.tail ) - return -1; /* No data */ + return -1; /* No data */ /* Update queue head pointer */ result = SCIF_sendq.data[SCIF_sendq.head++]; if( SCIF_sendq.head > FIFO_LENGTH ) - SCIF_sendq.head = 0; + SCIF_sendq.head = 0; /* Update data count register */ tmp = MMIO_READ( SCIF, SCFDR2 ) & 0x0F; length = SCIF_sendq_size(); MMIO_WRITE( SCIF, SCFDR2, tmp | (length << 8) ); - + /* Update status register */ if( length <= SCIF_sendq.trigger ) { - tmp = MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_TDFE; - if( length == 0 ) - tmp |= SCFSR2_TEND; /* Transmission ended - no data waiting */ - if( IS_TRANSMIT_IRQ_ENABLED() ) - intc_raise_interrupt( INT_SCIF_TXI ); + tmp = MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_TDFE; + if( length == 0 ) + tmp |= SCFSR2_TEND; /* Transmission ended - no data waiting */ + if( IS_TRANSMIT_IRQ_ENABLED() ) + intc_raise_interrupt( INT_SCIF_TXI ); DMAC_trigger( DMAC_SCIF_TDE ); - MMIO_WRITE( SCIF, SCFSR2, tmp ); + MMIO_WRITE( SCIF, SCFSR2, tmp ); } return (int)(unsigned int)result; } @@ -337,10 +337,10 @@ uint32_t tmp, length; int newpos = SCIF_sendq.tail + 1; if( newpos > FIFO_LENGTH ) - newpos = 0; + newpos = 0; if( newpos == SCIF_sendq.head ) { - /* FIFO full - discard */ - return FALSE; + /* FIFO full - discard */ + return FALSE; } SCIF_sendq.data[SCIF_sendq.tail] = value; SCIF_sendq.tail = newpos; @@ -349,17 +349,17 @@ tmp = MMIO_READ( SCIF, SCFDR2 ) & 0x0F; length = SCIF_sendq_size(); MMIO_WRITE( SCIF, SCFDR2, tmp | (length << 8) ); - + /* Update flags if requested */ if( clearFlags ) { - tmp = SCFSR2_TEND; - if( length > SCIF_sendq.trigger ) { - tmp |= SCFSR2_TDFE; - if( IS_TRANSMIT_IRQ_ENABLED() ) - intc_clear_interrupt( INT_SCIF_TXI ); - } - tmp = MMIO_READ( SCIF, SCFSR2 ) & (~tmp); - MMIO_WRITE( SCIF, SCFSR2, tmp ); + tmp = SCFSR2_TEND; + if( length > SCIF_sendq.trigger ) { + tmp |= SCFSR2_TDFE; + if( IS_TRANSMIT_IRQ_ENABLED() ) + intc_clear_interrupt( INT_SCIF_TXI ); + } + tmp = MMIO_READ( SCIF, SCFSR2 ) & (~tmp); + MMIO_WRITE( SCIF, SCFSR2, tmp ); } return TRUE; } @@ -370,7 +370,7 @@ MMIO_WRITE( SCIF, SCFDR2, MMIO_READ( SCIF, SCFDR2 ) & 0x0F ); MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_TEND | SCFSR2_TDFE ); if( IS_TRANSMIT_IRQ_ENABLED() ) { - intc_raise_interrupt( INT_SCIF_TXI ); + intc_raise_interrupt( INT_SCIF_TXI ); DMAC_trigger( DMAC_SCIF_TDE ); } } @@ -389,27 +389,27 @@ uint32_t recvq_size = SCIF_recvq_size(); if( sendq_size != 0 ) - result |= SCFSR2_TEND; + result |= SCFSR2_TEND; if( sendq_size <= SCIF_sendq.trigger ) - result |= SCFSR2_TDFE; + result |= SCFSR2_TDFE; else if( (result & SCFSR2_TDFE) == 0 && IS_TRANSMIT_IRQ_ENABLED() ) - intc_clear_interrupt( INT_SCIF_TXI ); + intc_clear_interrupt( INT_SCIF_TXI ); if( recvq_size >= SCIF_recvq.trigger ) - result |= SCFSR2_RDF; + result |= SCFSR2_RDF; if( (value & SCFSR2_DR) != 0 && (result & SCFSR2_DR) == 0 && - recvq_size != 0 ) - result |= SCFSR2_DR; + recvq_size != 0 ) + result |= SCFSR2_DR; if( (result & (SCFSR2_DR|SCFSR2_RDF)) == 0 && IS_RECEIVE_IRQ_ENABLED() ) - intc_clear_interrupt( INT_SCIF_RXI ); + intc_clear_interrupt( INT_SCIF_RXI ); if( IS_RECEIVE_ERROR_IRQ_ENABLED() ) { - if( (result & SCFSR2_BRK) == 0 ) - intc_clear_interrupt( INT_SCIF_BRI ); - if( (result & SCFSR2_ER) == 0 && - (MMIO_READ( SCIF, SCLSR2 ) & SCLSR2_ORER) == 0 ) - intc_clear_interrupt( INT_SCIF_ERI ); + if( (result & SCFSR2_BRK) == 0 ) + intc_clear_interrupt( INT_SCIF_BRI ); + if( (result & SCFSR2_ER) == 0 && + (MMIO_READ( SCIF, SCLSR2 ) & SCLSR2_ORER) == 0 ) + intc_clear_interrupt( INT_SCIF_ERI ); } } @@ -420,7 +420,7 @@ { MMIO_WRITE( SCIF, SCFSR2, MMIO_READ( SCIF, SCFSR2 ) | SCFSR2_BRK ); if( IS_RECEIVE_ERROR_IRQ_ENABLED() ) - intc_raise_interrupt( INT_SCIF_BRI ); + intc_raise_interrupt( INT_SCIF_BRI ); } const static int SCIF_CLOCK_MULTIPLIER[4] = {1, 4, 16, 64}; @@ -436,22 +436,22 @@ } else { - /* Otherwise, SH4 peripheral clock divided by n */ - int mult = SCIF_CLOCK_MULTIPLIER[MMIO_READ( SCIF, SCSMR2 ) & 0x03]; - - /* Then process the bitrate register */ - int bbr = MMIO_READ( SCIF, SCBRR2 ) & 0xFF; + /* Otherwise, SH4 peripheral clock divided by n */ + int mult = SCIF_CLOCK_MULTIPLIER[MMIO_READ( SCIF, SCSMR2 ) & 0x03]; - int baudrate = sh4_peripheral_freq / (32 * mult * (bbr+1) ); - - if( serial_device != NULL && serial_device->set_line_speed != NULL ) - serial_device->set_line_speed( baudrate ); + /* Then process the bitrate register */ + int bbr = MMIO_READ( SCIF, SCBRR2 ) & 0xFF; - SCIF_tick_period = sh4_peripheral_period * (32 * mult * (bbr+1)); + int baudrate = sh4_peripheral_freq / (32 * mult * (bbr+1) ); - /* + if( serial_device != NULL && serial_device->set_line_speed != NULL ) + serial_device->set_line_speed( baudrate ); + + SCIF_tick_period = sh4_peripheral_period * (32 * mult * (bbr+1)); + + /* clock_set_tick_rate( CLOCK_SCIF, baudrate / 10 ); - */ + */ } } @@ -459,9 +459,9 @@ { switch( reg ) { case SCFRDR2: /* Receive data */ - return SCIF_recvq_dequeue(FALSE); + return SCIF_recvq_dequeue(FALSE); default: - return MMIO_READ( SCIF, reg ); + return MMIO_READ( SCIF, reg ); } } @@ -470,95 +470,95 @@ uint32_t tmp; switch( reg ) { case SCSMR2: /* Serial mode register */ - /* Bit 6 => 0 = 8-bit, 1 = 7-bit - * Bit 5 => 0 = Parity disabled, 1 = parity enabled - * Bit 4 => 0 = Even parity, 1 = Odd parity - * Bit 3 => 0 = 1 stop bit, 1 = 2 stop bits - * Bits 0-1 => Clock select 00 = P, 01 = P/4, 10 = P/16, 11 = P/64 - */ - val &= 0x007B; - if( serial_device != NULL ) { - serial_device->set_line_params( val ); - } - tmp = MMIO_READ( SCIF, SCSMR2 ); - if( (tmp & 0x03) != (val & 0x03) ) { - /* Clock change */ - SCIF_update_line_speed( ); - } - /* Save for later read-back */ - MMIO_WRITE( SCIF, SCSMR2, val ); - break; + /* Bit 6 => 0 = 8-bit, 1 = 7-bit + * Bit 5 => 0 = Parity disabled, 1 = parity enabled + * Bit 4 => 0 = Even parity, 1 = Odd parity + * Bit 3 => 0 = 1 stop bit, 1 = 2 stop bits + * Bits 0-1 => Clock select 00 = P, 01 = P/4, 10 = P/16, 11 = P/64 + */ + val &= 0x007B; + if( serial_device != NULL ) { + serial_device->set_line_params( val ); + } + tmp = MMIO_READ( SCIF, SCSMR2 ); + if( (tmp & 0x03) != (val & 0x03) ) { + /* Clock change */ + SCIF_update_line_speed( ); + } + /* Save for later read-back */ + MMIO_WRITE( SCIF, SCSMR2, val ); + break; case SCBRR2: /* Bit rate register */ - MMIO_WRITE( SCIF, SCBRR2, val ); - SCIF_update_line_speed( ); - break; + MMIO_WRITE( SCIF, SCBRR2, val ); + SCIF_update_line_speed( ); + break; case SCSCR2: /* Serial control register */ - /* Bit 7 => Transmit-FIFO-data-empty interrupt enabled - * Bit 6 => Receive-data-full interrupt enabled - * Bit 5 => Transmit enable - * Bit 4 => Receive enable - * Bit 3 => Receive-error/break interrupt enabled - * Bit 1 => Clock enable - */ - val &= 0x00FA; - /* Clear any interrupts that just became disabled */ - if( (val & SCSCR2_TIE) == 0 ) - intc_clear_interrupt( INT_SCIF_TXI ); - if( (val & SCSCR2_RIE) == 0 ) - intc_clear_interrupt( INT_SCIF_RXI ); - if( (val & (SCSCR2_RIE|SCSCR2_REIE)) == 0 ) { - intc_clear_interrupt( INT_SCIF_ERI ); - intc_clear_interrupt( INT_SCIF_BRI ); - } - - MMIO_WRITE( SCIF, reg, val ); - break; + /* Bit 7 => Transmit-FIFO-data-empty interrupt enabled + * Bit 6 => Receive-data-full interrupt enabled + * Bit 5 => Transmit enable + * Bit 4 => Receive enable + * Bit 3 => Receive-error/break interrupt enabled + * Bit 1 => Clock enable + */ + val &= 0x00FA; + /* Clear any interrupts that just became disabled */ + if( (val & SCSCR2_TIE) == 0 ) + intc_clear_interrupt( INT_SCIF_TXI ); + if( (val & SCSCR2_RIE) == 0 ) + intc_clear_interrupt( INT_SCIF_RXI ); + if( (val & (SCSCR2_RIE|SCSCR2_REIE)) == 0 ) { + intc_clear_interrupt( INT_SCIF_ERI ); + intc_clear_interrupt( INT_SCIF_BRI ); + } + + MMIO_WRITE( SCIF, reg, val ); + break; case SCFTDR2: /* Transmit FIFO data register */ - SCIF_sendq_enqueue( val, FALSE ); - break; + SCIF_sendq_enqueue( val, FALSE ); + break; case SCFSR2: /* Serial status register */ - /* Bits 12-15 Parity error count - * Bits 8-11 Framing erro count - * Bit 7 - Receive error - * Bit 6 - Transmit end - * Bit 5 - Transmit FIFO data empty - * Bit 4 - Break detect - * Bit 3 - Framing error - * Bit 2 - Parity error - * Bit 1 - Receive FIFO data full - * Bit 0 - Receive data ready - */ - /* Clear off any flags/interrupts that are being set to 0 */ - SCIF_update_status( val ); - break; + /* Bits 12-15 Parity error count + * Bits 8-11 Framing erro count + * Bit 7 - Receive error + * Bit 6 - Transmit end + * Bit 5 - Transmit FIFO data empty + * Bit 4 - Break detect + * Bit 3 - Framing error + * Bit 2 - Parity error + * Bit 1 - Receive FIFO data full + * Bit 0 - Receive data ready + */ + /* Clear off any flags/interrupts that are being set to 0 */ + SCIF_update_status( val ); + break; case SCFCR2: /* FIFO control register */ - val &= 0x0F; - SCIF_recvq.trigger = SCIF_recvq_triggers[val >> 6]; - SCIF_sendq.trigger = SCIF_sendq_triggers[(val >> 4) & 0x03]; - if( val & SCFCR2_TFRST ) { - SCIF_sendq_clear(); - } - if( val & SCFCR2_RFRST ) { - SCIF_recvq_clear(); - } + val &= 0x0F; + SCIF_recvq.trigger = SCIF_recvq_triggers[val >> 6]; + SCIF_sendq.trigger = SCIF_sendq_triggers[(val >> 4) & 0x03]; + if( val & SCFCR2_TFRST ) { + SCIF_sendq_clear(); + } + if( val & SCFCR2_RFRST ) { + SCIF_recvq_clear(); + } - MMIO_WRITE( SCIF, reg, val ); - break; + MMIO_WRITE( SCIF, reg, val ); + break; case SCSPTR2: /* Serial Port Register */ - MMIO_WRITE( SCIF, reg, val ); - /* NOT IMPLEMENTED */ - WARN( "SCSPTR2 not implemented: Write %08X", val ); - break; + MMIO_WRITE( SCIF, reg, val ); + /* NOT IMPLEMENTED */ + WARN( "SCSPTR2 not implemented: Write %08X", val ); + break; case SCLSR2: - val = val & SCLSR2_ORER; - if( val == 0 ) { - MMIO_WRITE( SCIF, SCLSR2, val ); - if( (MMIO_READ( SCIF, SCFSR2 ) & SCFSR2_ER) == 0 && - IS_RECEIVE_ERROR_IRQ_ENABLED() ) - intc_clear_interrupt( INT_SCIF_ERI ); - } - - break; + val = val & SCLSR2_ORER; + if( val == 0 ) { + MMIO_WRITE( SCIF, SCLSR2, val ); + if( (MMIO_READ( SCIF, SCFSR2 ) & SCFSR2_ER) == 0 && + IS_RECEIVE_ERROR_IRQ_ENABLED() ) + intc_clear_interrupt( INT_SCIF_ERI ); + } + + break; } } @@ -579,42 +579,42 @@ gboolean rcvd = FALSE; if( IS_LOOPBACK_ENABLED() ) { - if( IS_TRANSMIT_ENABLED() ) { - int val = SCIF_sendq_dequeue(); - if( val != -1 && IS_RECEIVE_ENABLED() ) { - SCIF_recvq_enqueue( val ); - rcvd = TRUE; - } - } + if( IS_TRANSMIT_ENABLED() ) { + int val = SCIF_sendq_dequeue(); + if( val != -1 && IS_RECEIVE_ENABLED() ) { + SCIF_recvq_enqueue( val ); + rcvd = TRUE; + } + } } else { - if( IS_TRANSMIT_ENABLED() ) { - int val = SCIF_sendq_dequeue(); - if( val != -1 && serial_device != NULL && - serial_device->receive_data != NULL ) { - serial_device->receive_data( val ); - } - } - - if( IS_RECEIVE_ENABLED() ) { - int val = serial_transmit_dequeue(); - if( val != -1 ) { - SCIF_recvq_enqueue( val ); - rcvd = TRUE; - } - } + if( IS_TRANSMIT_ENABLED() ) { + int val = SCIF_sendq_dequeue(); + if( val != -1 && serial_device != NULL && + serial_device->receive_data != NULL ) { + serial_device->receive_data( val ); + } + } + + if( IS_RECEIVE_ENABLED() ) { + int val = serial_transmit_dequeue(); + if( val != -1 ) { + SCIF_recvq_enqueue( val ); + rcvd = TRUE; + } + } } /* Check if we need to set the DR flag */ if( !rcvd && !SCIF_rcvd_last_tick && - SCIF_recvq.head != SCIF_recvq.tail && - SCIF_recvq_size() < SCIF_recvq.trigger ) { - uint32_t tmp = MMIO_READ( SCIF, SCFSR2 ); - if( (tmp & SCFSR2_DR) == 0 ) { - MMIO_WRITE( SCIF, SCFSR2, tmp | SCFSR2_DR ); - if( IS_RECEIVE_IRQ_ENABLED() ) - intc_raise_interrupt( INT_SCIF_RXI ); - DMAC_trigger( DMAC_SCIF_RDF ); - } + SCIF_recvq.head != SCIF_recvq.tail && + SCIF_recvq_size() < SCIF_recvq.trigger ) { + uint32_t tmp = MMIO_READ( SCIF, SCFSR2 ); + if( (tmp & SCFSR2_DR) == 0 ) { + MMIO_WRITE( SCIF, SCFSR2, tmp | SCFSR2_DR ); + if( IS_RECEIVE_IRQ_ENABLED() ) + intc_raise_interrupt( INT_SCIF_RXI ); + DMAC_trigger( DMAC_SCIF_RDF ); + } } SCIF_rcvd_last_tick = rcvd; } @@ -630,7 +630,7 @@ { SCIF_tick_remainder += nanosecs; while( SCIF_tick_remainder >= SCIF_tick_period ) { - SCIF_tick_remainder -= SCIF_tick_period; - SCIF_clock_tick(); + SCIF_tick_remainder -= SCIF_tick_period; + SCIF_clock_tick(); } }