filename | src/sh4/scif.c |
changeset | 929:fd8cb0c82f5f |
prev | 828:b42865f00fb5 |
next | 975:007bf7eb944f |
author | nkeynes |
date | Sat Dec 27 02:59:35 2008 +0000 (15 years ago) |
branch | lxdream-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 }
.