25a26 > 41a43,46 > #define UART_IIR_CTI 0x0C /* Character Timeout Indication */ > > #define UART_IIR_FENF 0x80 /* Fifo enabled, but not functionning */ > #define UART_IIR_FE 0xC0 /* Fifo enabled */ 72a78,190 > /* > * These are the definitions for the Fifo Control Register > */ > > #define UART_FCR_ITL_MASQ 0xC0 /* Masq for Interrupt Trigger Level */ > > #define UART_FCR_ITL_1 0x00 /* 1 byte Interrupt Trigger Level */ > #define UART_FCR_ITL_4 0x40 /* 4 bytes Interrupt Trigger Level */ > #define UART_FCR_ITL_8 0x80 /* 8 bytes Interrupt Trigger Level */ > #define UART_FCR_ITL_14 0xC0 /* 14 bytes Interrupt Trigger Level */ > > #define UART_FCR_DMS 0x08 /* DMA Mode Select */ > #define UART_FCR_XFR 0x04 /* XMIT Fifo Reset */ > #define UART_FCR_RFR 0x02 /* RCVR Fifo Reset */ > #define UART_FCR_FE 0x01 /* FIFO Enable */ > > #define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */ > > struct SerialFifo { > char *data; /* bytes contained by the fifo */ > unsigned int count; /* number of byte in the fifo */ > unsigned int length; /* length of the fifo */ > unsigned int trigger; /* trigger level of the fifo */ > } typedef SerialFifo; > > /* initialize a FIFO */ > SerialFifo * fifo_init(unsigned int length, unsigned int trigger) { > SerialFifo *f; > if(!length) > return NULL; > if(trigger>length) > return NULL; > f = qemu_mallocz(sizeof(SerialFifo)); > if(f == NULL) > return NULL; > f->data = qemu_mallocz(length); > if(f->data == NULL) { > qemu_free(f); > return NULL; > } > f->length = length; > f->count = 0; > f->trigger = trigger; > return f; > } > > /* set the trigger level of a FIFO */ > int fifo_set_trigger(SerialFifo *f, unsigned int trigger) { > f->trigger = trigger; > return 1; > } > > /* clear a FIFO */ > int fifo_clear(SerialFifo *f) { > f->count = 0; > return 1; > } > > > /* free the memory of the FIFO - unused */ > int fifo_free(SerialFifo *f) { > if(f->data != NULL) > qemu_free(f->data); > qemu_free(f); > return 1; > } > > /* put a character in the FIFO */ > int fifo_put(SerialFifo *f, uint8_t *buf, int size) { > if(f->count >= f->length) > return 0; > /* Do the fifo moving */ > memmove(f->data+f->count, buf, size); > f->count += size; > return 1; > } > > /* get the FIFO triggering level */ > unsigned int fifo_get_trigger(SerialFifo *f) { > return f->trigger; > } > > > /* get the first char of the FIFO */ > char fifo_get(SerialFifo *f) { > char c; > if(f->count == 0) > return (char) 0; > f->count -= 1; > c = f->data[0]; > memmove(f->data, f->data+1, f->count); > return c; > } > > unsigned int fifo_count(SerialFifo *f) { > return f->count; > } > > unsigned int fifo_is_full(SerialFifo *f) { > if(f->count >= f->length) > return 1; > else > return 0; > } > > /* Used to test if the FIFO trigger level is reached */ > unsigned int fifo_is_triggered(SerialFifo *f) { > if(f->count >= f->trigger) > return 1; > else > return 0; > } > 82a201 > uint8_t fcr; 92a212,218 > int output_fifo_count; /* number of byte in the simulated XMIT FIFO */ > int64_t output_start_time; /* Time when the first byte has been put in the XMIT FIFO */ > SerialFifo *input_fifo; > float char_transmit_time; /* time to transmit a char */ > struct QEMUTimer *fifo_timeout_timer; > int timeout_ipending; /* timeout interrupt pending state */ > struct QEMUTimer *fifo_transmit_timer; 94a221,222 > > 97,98c225,232 < if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) { < s->iir = UART_IIR_RDI; --- > if ((s->lsr & UART_LSR_OE) && (s->ier & UART_IER_RLSI)) { > s->iir = (s->iir& UART_IIR_FE) | UART_IIR_RLSI; > } else if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI) && (s->fcr & UART_FCR_FE) && fifo_is_triggered(s->input_fifo) ) { > s->iir = (s->iir& UART_IIR_FE) | UART_IIR_RDI; > } else if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI) && !((s->fcr & UART_FCR_FE) != 0) ) { > s->iir = (s->iir& UART_IIR_FE) | UART_IIR_RDI; > } else if (s->timeout_ipending) { > s->iir = (s->iir& UART_IIR_FE) | UART_IIR_CTI; 100c234 < s->iir = UART_IIR_THRI; --- > s->iir = (s->iir& UART_IIR_FE) | UART_IIR_THRI; 102c236 < s->iir = UART_IIR_NO_INT; --- > s->iir = (s->iir& UART_IIR_FE) | UART_IIR_NO_INT; 104c238 < if (s->iir != UART_IIR_NO_INT) { --- > if ( ! (s->iir & UART_IIR_NO_INT) ) { 113c247 < int speed, parity, data_bits, stop_bits; --- > int speed, parity, data_bits, stop_bits, bit_count; 115a250,251 > bit_count = 1; > 116a253 > bit_count += 1; 128a266,267 > > 136a276,277 > bit_count += stop_bits + data_bits; > s->char_transmit_time = ( (float) bit_count * 1000) / speed; 159,161d299 < s->thr_ipending = 0; < s->lsr &= ~UART_LSR_THRE; < serial_update_irq(s); 163,166c301,323 < qemu_chr_write(s->chr, &ch, 1); < s->thr_ipending = 1; < s->lsr |= UART_LSR_THRE; < s->lsr |= UART_LSR_TEMT; --- > if(s->fcr & UART_FCR_FE) { > s->thr_ipending = 0; > s->lsr &= ~UART_LSR_TEMT; > s->lsr &= ~UART_LSR_THRE; > qemu_chr_write(s->chr, &ch, 1); > /* get the vm time when the first byte is put in the output FIFO */ > if(s->output_fifo_count == 0) { > s->output_start_time = qemu_get_clock (vm_clock); > } > int64_t ticks; > /* call the XMIT ending FIFO emit when all byte are suposed to be send by the output fifo */ > ticks = (int64_t) ((ticks_per_sec * s->char_transmit_time * s->output_fifo_count )/1000); > qemu_mod_timer(s->fifo_transmit_timer , s->output_start_time + ticks); > s->output_fifo_count += 1; > } else { > s->thr_ipending = 0; > s->lsr &= ~UART_LSR_THRE; > serial_update_irq(s); > qemu_chr_write(s->chr, &ch, 1); > s->thr_ipending = 1; > s->lsr |= UART_LSR_THRE; > s->lsr |= UART_LSR_TEMT; > } 182a340,390 > { > /* FIFO Control Register - ignores the DMA bit */ > unsigned int trigger; > int fifo_enable_changed; > > trigger = 0; > fifo_enable_changed = 0; > > > /* Compute RCVR FIFO trigger Level */ > ch = val & UART_FCR_ITL_MASQ; > if(ch == (unsigned char) UART_FCR_ITL_1) > trigger = 1; > if(ch == (unsigned char) UART_FCR_ITL_4) > trigger = 4; > if(ch == (unsigned char) UART_FCR_ITL_8) > trigger = 8; > if(ch == (unsigned char) UART_FCR_ITL_14) > trigger = 14; > > ch = val; > /* Detect FIFO mode changes */ > if(ch & UART_FCR_FE) { > if( !(s->fcr & UART_FCR_FE) ) > fifo_enable_changed = 1; > s->iir |= UART_IIR_FE; > } else { > if(s->fcr & UART_FCR_FE) > fifo_enable_changed = 1; > s->iir &= ~(unsigned char) UART_IIR_FE; > } > > s->fcr = val; > > /* Clear FIFOs if FIFO mode has been changed */ > if(fifo_enable_changed) { > fifo_clear(s->input_fifo); > } > > /* If FIFO mode is enabled config RCVR FIFO trigger level */ > if(s->fcr & UART_FCR_FE) { > fifo_set_trigger(s->input_fifo, trigger); > } > > /* Manage Fifo Control Register clearing bits*/ > if(s->fcr & UART_FCR_FE) { > if(s->fcr & UART_FCR_RFR) > fifo_clear(s->input_fifo); > } > > } 223,224c431,446 < ret = s->rbr; < s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); --- > if(s->fcr & UART_FCR_FE) { > int64_t ticks; > ticks = (int64_t) ( (ticks_per_sec * s->char_transmit_time * 4) / 1000 ); > ret = fifo_get(s->input_fifo); > if(fifo_count(s->input_fifo) == 0) > s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); > else > /* call the RCVR FIFO timeout routine in 4 char transmit time */ > qemu_mod_timer(s->fifo_timeout_timer , qemu_get_clock (vm_clock) + ticks); > s->timeout_ipending = 0; > /* break interrupt */ > > } else { > ret = s->rbr; > s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); > } 271a494,517 > /* callback used to trigger the Transmit Holding Register Empty interrupt when all byte are transmited from the simulated XMIT buffer */ > static void output_bytes_transmited_cb (void *opaque) { > SerialState *s = opaque; > s->output_fifo_count = 0; > s->thr_ipending = 1; > s->lsr |= UART_LSR_THRE; > s->lsr |= UART_LSR_TEMT; > serial_update_irq(s); > } > > /* callback called when no new char has been received for 4 char transmit times */ > static void timeout_timer_cb (void *opaque) { > SerialState *s = opaque; > > if(fifo_count(s->input_fifo) > 0) { > s->timeout_ipending = 1; > } else { > s->timeout_ipending = 0; > } > serial_update_irq(s); > } > > > 274c520,527 < return !(s->lsr & UART_LSR_DR); --- > if(s->fcr & UART_FCR_FE) { > if(fifo_count(s->input_fifo) < UART_FIFO_LENGTH) > return UART_FIFO_LENGTH - fifo_count(s->input_fifo); > else > return 0; > } else { > return !(s->lsr & UART_LSR_DR); > } 277,280c530,545 < static void serial_receive_byte(SerialState *s, int ch) < { < s->rbr = ch; < s->lsr |= UART_LSR_DR; --- > static void serial_receive_bytes(SerialState *s, uint8_t *buf, int size) { > if(s->fcr & UART_FCR_FE) { > if( fifo_is_full(s->input_fifo) ) { > s->lsr |= UART_LSR_OE; > } else { > /* call the timeout receive callback in 4 char transmit time */ > int64_t ticks; > ticks = (int64_t) ((ticks_per_sec * s->char_transmit_time * 4) / 1000 ); > fifo_put(s->input_fifo, buf, size); > s->lsr |= UART_LSR_DR; > qemu_mod_timer(s->fifo_timeout_timer , qemu_get_clock (vm_clock) + ticks); > } > } else { > s->rbr = buf[0]; > s->lsr |= UART_LSR_DR; > } 283a549,550 > > 300c567 < serial_receive_byte(s, buf[0]); --- > serial_receive_bytes(s, buf, size); 322a590 > qemu_put_8s(f,&s->fcr); 340a609 > qemu_get_8s(f,&s->fcr); 359a629,636 > /* Init fifo structures */ > s->input_fifo = fifo_init(UART_FIFO_LENGTH , 0); > s->fifo_timeout_timer = qemu_new_timer(vm_clock, timeout_timer_cb, s); > s->fifo_transmit_timer = qemu_new_timer(vm_clock, output_bytes_transmited_cb, s); > > s->output_fifo_count = 0; > s->output_start_time = 0; > 445a723,730 > /* Init fifo structures */ > s->input_fifo = fifo_init(UART_FIFO_LENGTH , 0); > s->fifo_timeout_timer = qemu_new_timer(vm_clock, timeout_timer_cb, s); > s->fifo_transmit_timer = qemu_new_timer(vm_clock, output_bytes_transmited_cb, s); > s->output_fifo_count = 0; > s->output_start_time = 0; > >