debuggers.hg
changeset 16576:f0ac46de680c
[QEMU-DM] Upgrade emulated UART to 16550A.
This patch adds 16550 emulation to qemu-dm. I still consider it a work
in progress, but from my testing, it consistently performs better than
the old code already, sometimes considerably so (on my laptop, dumping
out data over serial from a HVM DomU -> pty in Dom0 was up to 5.3
times faster than with the old 16450 code). I can consistenly reach
full 115200 baud speeds over physical serial lines when the virtual
device is backed by a phys port, which I never could with the old code.
There are still some things to be done. I want to add proper error
handling, so that overflow/framing & parity errors on the physical
port get detected and reported by the virtual port. Also, now that
FIFOs are in place, I believe performance could be improved
significantly by putting some code into the hypervisor so that reads &
writes from the FIFOs don't have to exit into qemu-dm at all. I'm also
reading up on the specs for newer uarts with deeper FIFOs.
Signed-off-by: Trolle Selander <trolle.selander@gmail.com>
This patch adds 16550 emulation to qemu-dm. I still consider it a work
in progress, but from my testing, it consistently performs better than
the old code already, sometimes considerably so (on my laptop, dumping
out data over serial from a HVM DomU -> pty in Dom0 was up to 5.3
times faster than with the old 16450 code). I can consistenly reach
full 115200 baud speeds over physical serial lines when the virtual
device is backed by a phys port, which I never could with the old code.
There are still some things to be done. I want to add proper error
handling, so that overflow/framing & parity errors on the physical
port get detected and reported by the virtual port. Also, now that
FIFOs are in place, I believe performance could be improved
significantly by putting some code into the hypervisor so that reads &
writes from the FIFOs don't have to exit into qemu-dm at all. I'm also
reading up on the specs for newer uarts with deeper FIFOs.
Signed-off-by: Trolle Selander <trolle.selander@gmail.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Wed Dec 05 14:21:00 2007 +0000 (2007-12-05) |
parents | bf21e00155b7 |
children | 46af6ec3ae4e |
files | tools/ioemu/hw/serial.c |
line diff
1.1 --- a/tools/ioemu/hw/serial.c Wed Dec 05 14:18:34 2007 +0000 1.2 +++ b/tools/ioemu/hw/serial.c Wed Dec 05 14:21:00 2007 +0000 1.3 @@ -1,5 +1,5 @@ 1.4 /* 1.5 - * QEMU 16450 UART emulation 1.6 + * QEMU 16550A UART emulation 1.7 * 1.8 * Copyright (c) 2003-2004 Fabrice Bellard 1.9 * 1.10 @@ -21,6 +21,7 @@ 1.11 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 1.12 * THE SOFTWARE. 1.13 */ 1.14 + 1.15 #include "vl.h" 1.16 #include <sys/time.h> 1.17 #include <time.h> 1.18 @@ -43,6 +44,10 @@ 1.19 #define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ 1.20 #define UART_IIR_RDI 0x04 /* Receiver data interrupt */ 1.21 #define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ 1.22 +#define UART_IIR_CTI 0x0C /* Character Timeout Indication */ 1.23 + 1.24 +#define UART_IIR_FENF 0x80 /* Fifo enabled, but not functionning */ 1.25 +#define UART_IIR_FE 0xC0 /* Fifo enabled */ 1.26 1.27 /* 1.28 * These are the definitions for the Modem Control Register 1.29 @@ -75,14 +80,36 @@ 1.30 #define UART_LSR_DR 0x01 /* Receiver data ready */ 1.31 #define UART_LSR_INT_ANY 0x1E /* Any of the lsr-interrupt-triggering status bits */ 1.32 1.33 -/* Maximum retries for a single byte transmit. */ 1.34 -#define WRITE_MAX_SINGLE_RETRIES 3 1.35 -/* Maximum retries for a sequence of back-to-back unsuccessful transmits. */ 1.36 -#define WRITE_MAX_TOTAL_RETRIES 10 1.37 +/* Interrupt trigger levels. The byte-counts are for 16550A - in newer UARTs the byte-count for each ITL is higher. */ 1.38 + 1.39 +#define UART_FCR_ITL_1 0x00 /* 1 byte ITL */ 1.40 +#define UART_FCR_ITL_2 0x40 /* 4 bytes ITL */ 1.41 +#define UART_FCR_ITL_3 0x80 /* 8 bytes ITL */ 1.42 +#define UART_FCR_ITL_4 0xC0 /* 14 bytes ITL */ 1.43 + 1.44 +#define UART_FCR_DMS 0x08 /* DMA Mode Select */ 1.45 +#define UART_FCR_XFR 0x04 /* XMIT Fifo Reset */ 1.46 +#define UART_FCR_RFR 0x02 /* RCVR Fifo Reset */ 1.47 +#define UART_FCR_FE 0x01 /* FIFO Enable */ 1.48 + 1.49 +#define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */ 1.50 + 1.51 +#define XMIT_FIFO 0 1.52 +#define RECV_FIFO 1 1.53 + 1.54 +struct SerialFIFO { 1.55 + uint8_t data[UART_FIFO_LENGTH]; 1.56 + uint8_t count; 1.57 + uint8_t itl; /* Interrupt Trigger Level */ 1.58 + uint8_t tail; 1.59 + uint8_t head; 1.60 +} typedef SerialFIFO; 1.61 1.62 struct SerialState { 1.63 uint16_t divider; 1.64 uint8_t rbr; /* receive register */ 1.65 + uint8_t thr; /* transmit holding register */ 1.66 + uint8_t tsr; /* transmit shift register */ 1.67 uint8_t ier; 1.68 uint8_t iir; /* read only */ 1.69 uint8_t lcr; 1.70 @@ -90,6 +117,7 @@ struct SerialState { 1.71 uint8_t lsr; /* read only */ 1.72 uint8_t msr; /* read only */ 1.73 uint8_t scr; 1.74 + uint8_t fcr; 1.75 /* NOTE: this hidden state is necessary for tx irq generation as 1.76 it can be reset while reading iir */ 1.77 int thr_ipending; 1.78 @@ -100,24 +128,73 @@ struct SerialState { 1.79 int last_break_enable; 1.80 target_ulong base; 1.81 int it_shift; 1.82 + int tsr_retry; 1.83 + 1.84 + uint64_t last_xmit_ts; /* Time when the last byte was successfully sent out of the tsr */ 1.85 + SerialFIFO recv_fifo; 1.86 + SerialFIFO xmit_fifo; 1.87 + 1.88 + struct QEMUTimer *fifo_timeout_timer; 1.89 + int timeout_ipending; /* timeout interrupt pending state */ 1.90 + struct QEMUTimer *fifo_transmit_timer; 1.91 + 1.92 + 1.93 uint64_t char_transmit_time; /* time to transmit a char in ticks*/ 1.94 int poll_msl; 1.95 1.96 - /* 1.97 - * If a character transmitted via UART cannot be written to its 1.98 - * destination immediately we remember it here and retry a few times via 1.99 - * a polling timer. 1.100 - * - write_single_retries: Number of write retries for current byte. 1.101 - * - write_total_retries: Number of write retries for back-to-back 1.102 - * unsuccessful transmits. 1.103 - */ 1.104 - int write_single_retries; 1.105 - int write_total_retries; 1.106 - char write_chr; 1.107 - QEMUTimer *write_retry_timer; 1.108 - QEMUTimer *modem_status_poll; 1.109 + struct QEMUTimer *modem_status_poll; 1.110 }; 1.111 1.112 +/* Rate limit serial requests so that e.g. grub on a serial console 1.113 + doesn't kill dom0. Simple token bucket. If we get some actual 1.114 + data from the user, instantly refil the bucket. */ 1.115 + 1.116 +/* How long it takes to generate a token, in microseconds. */ 1.117 +#define TOKEN_PERIOD 1000 1.118 +/* Maximum and initial size of token bucket */ 1.119 +#define TOKENS_MAX 100000 1.120 + 1.121 +static int tokens_avail; 1.122 + 1.123 +static void fifo_clear(SerialState *s, int fifo) { 1.124 + SerialFIFO *f = ( fifo ) ? &s->recv_fifo : &s->xmit_fifo; 1.125 + memset(f->data, 0, UART_FIFO_LENGTH); 1.126 + f->count = 0; 1.127 + f->head = 0; 1.128 + f->tail = 0; 1.129 +} 1.130 + 1.131 +static int fifo_put(SerialState *s, int fifo, uint8_t chr) { 1.132 + SerialFIFO *f = ( fifo ) ? &s->recv_fifo : &s->xmit_fifo; 1.133 + 1.134 + f->data[f->head++] = chr; 1.135 + 1.136 + if (f->head == UART_FIFO_LENGTH) 1.137 + f->head = 0; 1.138 + f->count++; 1.139 + 1.140 + tokens_avail = TOKENS_MAX; 1.141 + 1.142 + return 1; 1.143 +} 1.144 + 1.145 +uint8_t fifo_get(SerialState *s, int fifo) { 1.146 + SerialFIFO *f = ( fifo ) ? &s->recv_fifo : &s->xmit_fifo; 1.147 + uint8_t c; 1.148 + 1.149 + if( f->count == 0 ) 1.150 + return 0; 1.151 + 1.152 + c = f->data[f->tail++]; 1.153 + if (f->tail == UART_FIFO_LENGTH) 1.154 + f->tail = 0; 1.155 + f->count--; 1.156 + 1.157 + tokens_avail = TOKENS_MAX; 1.158 + 1.159 + return c; 1.160 +} 1.161 + 1.162 static void serial_update_irq(SerialState *s) 1.163 { 1.164 uint8_t tmp_iir = UART_IIR_NO_INT; 1.165 @@ -127,13 +204,19 @@ static void serial_update_irq(SerialStat 1.166 return; 1.167 } 1.168 1.169 - if ( ( s->ier & UART_IER_RLSI ) && ( s->lsr & UART_LSR_INT_ANY ) ) { 1.170 + if ( ( s->ier & UART_IER_RLSI ) && (s->lsr & UART_LSR_INT_ANY ) ) { 1.171 tmp_iir = UART_IIR_RLSI; 1.172 - } else if ( ( s->ier & UART_IER_RDI ) && ( s->lsr & UART_LSR_DR ) ) { 1.173 - tmp_iir = UART_IIR_RDI; 1.174 - } else if ( ( s->ier & UART_IER_THRI ) && s->thr_ipending ) { 1.175 - tmp_iir = UART_IIR_THRI; 1.176 - } else if ( ( s->ier & UART_IER_MSI ) && ( s->msr & UART_MSR_ANY_DELTA ) ) { 1.177 + } else if ( s->timeout_ipending ) { 1.178 + tmp_iir = UART_IIR_CTI; 1.179 + } else if ( ( s->ier & UART_IER_RDI ) && (s->lsr & UART_LSR_DR ) ) { 1.180 + if ( !(s->iir & UART_FCR_FE) ) { 1.181 + tmp_iir = UART_IIR_RDI; 1.182 + } else if ( s->recv_fifo.count >= s->recv_fifo.itl ) { 1.183 + tmp_iir = UART_IIR_RDI; 1.184 + } 1.185 + } else if ( (s->ier & UART_IER_THRI) && s->thr_ipending ) { 1.186 + tmp_iir = UART_IIR_THRI; 1.187 + } else if ( (s->ier & UART_IER_MSI) && (s->msr & UART_MSR_ANY_DELTA) ) { 1.188 tmp_iir = UART_IIR_MSI; 1.189 } 1.190 1.191 @@ -185,17 +268,6 @@ static void serial_update_parameters(Ser 1.192 #endif 1.193 } 1.194 1.195 -/* Rate limit serial requests so that e.g. grub on a serial console 1.196 - doesn't kill dom0. Simple token bucket. If we get some actual 1.197 - data from the user, instantly refil the bucket. */ 1.198 - 1.199 -/* How long it takes to generate a token, in microseconds. */ 1.200 -#define TOKEN_PERIOD 1000 1.201 -/* Maximum and initial size of token bucket */ 1.202 -#define TOKENS_MAX 100000 1.203 - 1.204 -static int tokens_avail; 1.205 - 1.206 static void serial_get_token(void) 1.207 { 1.208 static struct timeval last_refil_time; 1.209 @@ -246,34 +318,6 @@ static void serial_get_token(void) 1.210 tokens_avail--; 1.211 } 1.212 1.213 -static void serial_chr_write(void *opaque) 1.214 -{ 1.215 - SerialState *s = opaque; 1.216 - 1.217 - /* Cancel any outstanding retry if this is a new byte. */ 1.218 - qemu_del_timer(s->write_retry_timer); 1.219 - 1.220 - /* Retry every 100ms for 300ms total. */ 1.221 - if (qemu_chr_write(s->chr, &s->write_chr, 1) == -1) { 1.222 - s->write_total_retries++; 1.223 - if (s->write_single_retries++ >= WRITE_MAX_SINGLE_RETRIES) 1.224 - fprintf(stderr, "serial: write error\n"); 1.225 - else if (s->write_total_retries <= WRITE_MAX_TOTAL_RETRIES) { 1.226 - qemu_mod_timer(s->write_retry_timer, 1.227 - qemu_get_clock(vm_clock) + ticks_per_sec / 10); 1.228 - return; 1.229 - } 1.230 - } else { 1.231 - s->write_total_retries = 0; /* if successful then reset counter */ 1.232 - } 1.233 - 1.234 - /* Success: Notify guest that THR is empty. */ 1.235 - s->thr_ipending = 1; 1.236 - s->lsr |= UART_LSR_THRE; 1.237 - s->lsr |= UART_LSR_TEMT; 1.238 - serial_update_irq(s); 1.239 -} 1.240 - 1.241 static void serial_update_msl( SerialState *s ) 1.242 { 1.243 uint8_t omsr; 1.244 @@ -285,7 +329,7 @@ static void serial_update_msl( SerialSta 1.245 s->poll_msl = -1; 1.246 return; 1.247 } 1.248 - 1.249 + 1.250 omsr = s->msr; 1.251 1.252 s->msr = ( flags & TIOCM_CTS ) ? s->msr | UART_MSR_CTS : s->msr & ~UART_MSR_CTS; 1.253 @@ -297,7 +341,7 @@ static void serial_update_msl( SerialSta 1.254 /* Set delta bits */ 1.255 s->msr = s->msr | ( ( s->msr >> 4 ) ^ ( omsr >> 4 ) ); 1.256 /* UART_MSR_TERI only if change was from 1 -> 0 */ 1.257 - if ( (s->msr & UART_MSR_TERI) && !(omsr & UART_MSR_RI)) 1.258 + if ( ( s->msr & UART_MSR_TERI ) && !( omsr & UART_MSR_RI ) ) 1.259 s->msr &= ~UART_MSR_TERI; 1.260 serial_update_irq(s); 1.261 } 1.262 @@ -305,10 +349,45 @@ static void serial_update_msl( SerialSta 1.263 /* The real 16550A apparently has a 250ns response latency to line status changes. 1.264 We'll be lazy and poll only every 10ms, and only poll it at all if MSI interrupts are turned on */ 1.265 1.266 - if (s->poll_msl) 1.267 + if ( s->poll_msl ) 1.268 qemu_mod_timer(s->modem_status_poll, qemu_get_clock(vm_clock) + ticks_per_sec / 100); 1.269 } 1.270 1.271 +static void serial_xmit(void *opaque) { 1.272 + SerialState *s = opaque; 1.273 + uint64_t new_xmit_ts = qemu_get_clock(vm_clock); 1.274 + 1.275 + if ( s->tsr_retry == 0 ) { 1.276 + if (s->fcr & UART_FCR_FE) { 1.277 + s->tsr = fifo_get(s,XMIT_FIFO); 1.278 + if ( !s->xmit_fifo.count ) 1.279 + s->lsr |= UART_LSR_THRE; 1.280 + } else { 1.281 + s->tsr = s->thr; 1.282 + s->lsr |= UART_LSR_THRE; 1.283 + } 1.284 + } 1.285 + 1.286 + if ( qemu_chr_write(s->chr, &s->tsr, 1) != 1 ) { 1.287 + s->tsr_retry++; 1.288 + qemu_mod_timer(s->fifo_transmit_timer, new_xmit_ts + s->char_transmit_time ); 1.289 + return; 1.290 + } 1.291 + 1.292 + s->tsr_retry = 0; 1.293 + s->last_xmit_ts = qemu_get_clock(vm_clock); 1.294 + 1.295 + if ( s->xmit_fifo.count > 0 ) 1.296 + qemu_mod_timer(s->fifo_transmit_timer, s->last_xmit_ts + s->char_transmit_time ); 1.297 + 1.298 + if ( s->lsr & UART_LSR_THRE ) { 1.299 + s->lsr |= UART_LSR_TEMT; 1.300 + s->thr_ipending = 1; 1.301 + serial_update_irq(s); 1.302 + } 1.303 +} 1.304 + 1.305 + 1.306 static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) 1.307 { 1.308 SerialState *s = opaque; 1.309 @@ -324,12 +403,19 @@ static void serial_ioport_write(void *op 1.310 s->divider = (s->divider & 0xff00) | val; 1.311 serial_update_parameters(s); 1.312 } else { 1.313 - s->thr_ipending = 0; 1.314 - s->lsr &= ~UART_LSR_THRE; 1.315 - serial_update_irq(s); 1.316 - s->write_chr = val; 1.317 - s->write_single_retries = 0; 1.318 - serial_chr_write(s); 1.319 + s->thr = (uint8_t) val; 1.320 + if(s->fcr & UART_FCR_FE) { 1.321 + fifo_put(s, XMIT_FIFO, s->thr); 1.322 + s->thr_ipending = 0; 1.323 + s->lsr &= ~UART_LSR_TEMT; 1.324 + s->lsr &= ~UART_LSR_THRE; 1.325 + serial_update_irq(s); 1.326 + } else { 1.327 + s->thr_ipending = 0; 1.328 + s->lsr &= ~UART_LSR_THRE; 1.329 + serial_update_irq(s); 1.330 + } 1.331 + serial_xmit(s); 1.332 } 1.333 break; 1.334 case 1: 1.335 @@ -338,7 +424,8 @@ static void serial_ioport_write(void *op 1.336 serial_update_parameters(s); 1.337 } else { 1.338 s->ier = val & 0x0f; 1.339 - /* Turn on polling of modem status lines if guest has IER_MSI turned on */ 1.340 + /* If the backend device is a real serial port, turn polling of the modem 1.341 + status lines on physical port on or off depending on UART_IER_MSI state */ 1.342 if ( s->poll_msl >= 0 ) { 1.343 if ( s->ier & UART_IER_MSI ) { 1.344 s->poll_msl = 1; 1.345 @@ -348,14 +435,57 @@ static void serial_ioport_write(void *op 1.346 s->poll_msl = 0; 1.347 } 1.348 } 1.349 - 1.350 if (s->lsr & UART_LSR_THRE) { 1.351 s->thr_ipending = 1; 1.352 + serial_update_irq(s); 1.353 } 1.354 - serial_update_irq(s); 1.355 } 1.356 break; 1.357 case 2: 1.358 + val = val & 0xFF; 1.359 + 1.360 + if ( s->fcr == val) 1.361 + break; 1.362 + 1.363 + /* Did the enable/disable flag change? If so, make sure FIFOs get flushed */ 1.364 + if ( (val ^ s->fcr) & UART_FCR_FE ) 1.365 + val |= UART_FCR_XFR | UART_FCR_RFR; 1.366 + 1.367 + /* FIFO clear */ 1.368 + 1.369 + if ( val & UART_FCR_RFR ) { 1.370 + qemu_del_timer(s->fifo_timeout_timer); 1.371 + s->timeout_ipending=0; 1.372 + fifo_clear(s,RECV_FIFO); 1.373 + } 1.374 + 1.375 + if ( val & UART_FCR_XFR ) { 1.376 + fifo_clear(s,XMIT_FIFO); 1.377 + } 1.378 + 1.379 + if ( val & UART_FCR_FE ) { 1.380 + s->iir |= UART_IIR_FE; 1.381 + /* Set RECV_FIFO trigger Level */ 1.382 + switch ( val & 0xC0 ) { 1.383 + case UART_FCR_ITL_1: 1.384 + s->recv_fifo.itl = 1; 1.385 + break; 1.386 + case UART_FCR_ITL_2: 1.387 + s->recv_fifo.itl = 4; 1.388 + break; 1.389 + case UART_FCR_ITL_3: 1.390 + s->recv_fifo.itl = 8; 1.391 + break; 1.392 + case UART_FCR_ITL_4: 1.393 + s->recv_fifo.itl = 14; 1.394 + break; 1.395 + } 1.396 + } else 1.397 + s->iir &= ~UART_IIR_FE; 1.398 + 1.399 + /* Set fcr - or at least the bits in it that are supposed to "stick" */ 1.400 + s->fcr = val & 0xC9; 1.401 + serial_update_irq(s); 1.402 break; 1.403 case 3: 1.404 { 1.405 @@ -378,7 +508,7 @@ static void serial_ioport_write(void *op 1.406 if ( val & UART_MCR_LOOP ) 1.407 break; 1.408 1.409 - if ( ( s->poll_msl >= 0 ) && ( old_mcr != s->mcr ) ) { 1.410 + if ( s->poll_msl >= 0 && old_mcr != s->mcr ) { 1.411 1.412 qemu_chr_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags); 1.413 1.414 @@ -390,8 +520,8 @@ static void serial_ioport_write(void *op 1.415 flags |= TIOCM_DTR; 1.416 1.417 qemu_chr_ioctl(s->chr,CHR_IOCTL_SERIAL_SET_TIOCM, &flags); 1.418 - 1.419 - /* Update the modem status after a one-character-send wait-time. The dev */ 1.420 + /* Update the modem status after a one-character-send wait-time, since there may be a response 1.421 + from the device/computer at the other end of the serial line */ 1.422 qemu_mod_timer(s->modem_status_poll, qemu_get_clock(vm_clock) + s->char_transmit_time ); 1.423 } 1.424 } 1.425 @@ -418,9 +548,18 @@ static uint32_t serial_ioport_read(void 1.426 if (s->lcr & UART_LCR_DLAB) { 1.427 ret = s->divider & 0xff; 1.428 } else { 1.429 - ret = s->rbr; 1.430 - s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); 1.431 - serial_update_irq(s); 1.432 + if(s->fcr & UART_FCR_FE) { 1.433 + ret = fifo_get(s,RECV_FIFO); 1.434 + if ( s->recv_fifo.count == 0 ) 1.435 + s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); 1.436 + else 1.437 + qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock (vm_clock) + s->char_transmit_time * 4 ); 1.438 + s->timeout_ipending = 0; 1.439 + } else { 1.440 + ret = s->rbr; 1.441 + s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); 1.442 + } 1.443 + serial_update_irq(s); 1.444 } 1.445 break; 1.446 case 1: 1.447 @@ -432,9 +571,7 @@ static uint32_t serial_ioport_read(void 1.448 break; 1.449 case 2: 1.450 ret = s->iir; 1.451 - /* reset THR pending bit */ 1.452 - if ((ret & 0x7) == UART_IIR_THRI) 1.453 - s->thr_ipending = 0; 1.454 + s->thr_ipending = 0; 1.455 serial_update_irq(s); 1.456 break; 1.457 case 3: 1.458 @@ -446,6 +583,11 @@ static uint32_t serial_ioport_read(void 1.459 case 5: 1.460 serial_get_token(); 1.461 ret = s->lsr; 1.462 + /* Clear break interrupt */ 1.463 + if ( s->lsr & UART_LSR_BI ) { 1.464 + s->lsr &= ~UART_LSR_BI; 1.465 + serial_update_irq(s); 1.466 + } 1.467 break; 1.468 case 6: 1.469 serial_get_token(); 1.470 @@ -456,12 +598,14 @@ static uint32_t serial_ioport_read(void 1.471 ret |= (s->mcr & 0x02) << 3; 1.472 ret |= (s->mcr & 0x01) << 5; 1.473 } else { 1.474 - ret = 0; 1.475 if ( s->poll_msl >= 0 ) 1.476 serial_update_msl(s); 1.477 ret = s->msr; 1.478 - s->msr &= 0xF0; /* Clear delta bits after read */ 1.479 - serial_update_irq(s); 1.480 + /* Clear delta bits & msr int after read, if they were set */ 1.481 + if ( s->msr & UART_MSR_ANY_DELTA ) { 1.482 + s->msr &= 0xF0; 1.483 + serial_update_irq(s); 1.484 + } 1.485 } 1.486 break; 1.487 case 7: 1.488 @@ -476,14 +620,17 @@ static uint32_t serial_ioport_read(void 1.489 1.490 static int serial_can_receive(SerialState *s) 1.491 { 1.492 - return !(s->lsr & UART_LSR_DR); 1.493 -} 1.494 - 1.495 -static void serial_receive_byte(SerialState *s, int ch) 1.496 -{ 1.497 - s->rbr = ch; 1.498 - s->lsr |= UART_LSR_DR; 1.499 - serial_update_irq(s); 1.500 + if(s->fcr & UART_FCR_FE) { 1.501 + if(s->recv_fifo.count < UART_FIFO_LENGTH) 1.502 + /* Advertise (fifo.itl - fifo.count) bytes when count < ITL, and 1 if above. If UART_FIFO_LENGTH - fifo.count is 1.503 + advertised the effect will be to almost always fill the fifo completely before the guest has a chance to respond, 1.504 + effectively overriding the ITL that the guest has set. */ 1.505 + return ( s->recv_fifo.count <= s->recv_fifo.itl ) ? s->recv_fifo.itl - s->recv_fifo.count : 1; 1.506 + else 1.507 + return 0; 1.508 + } else { 1.509 + return !(s->lsr & UART_LSR_DR); 1.510 + } 1.511 } 1.512 1.513 static void serial_receive_break(SerialState *s) 1.514 @@ -492,6 +639,15 @@ static void serial_receive_break(SerialS 1.515 s->lsr |= UART_LSR_BI | UART_LSR_DR; 1.516 serial_update_irq(s); 1.517 } 1.518 + 1.519 +/* There's data in recv_fifo and s->rbr has not been read for 4 char transmit times */ 1.520 +static void fifo_timeout_int (void *opaque) { 1.521 + SerialState *s = opaque; 1.522 + if ( s->recv_fifo.count ) { 1.523 + s->timeout_ipending = 1; 1.524 + serial_update_irq(s); 1.525 + } 1.526 +} 1.527 1.528 static int serial_can_receive1(void *opaque) 1.529 { 1.530 @@ -503,7 +659,19 @@ static void serial_receive1(void *opaque 1.531 { 1.532 SerialState *s = opaque; 1.533 tokens_avail = TOKENS_MAX; 1.534 - serial_receive_byte(s, buf[0]); 1.535 + if(s->fcr & UART_FCR_FE) { 1.536 + int i; 1.537 + for (i = 0; i < size; i++) { 1.538 + fifo_put(s, RECV_FIFO, buf[i]); 1.539 + } 1.540 + s->lsr |= UART_LSR_DR; 1.541 + /* call the timeout receive callback in 4 char transmit time */ 1.542 + qemu_mod_timer(s->fifo_timeout_timer, qemu_get_clock (vm_clock) + s->char_transmit_time * 4); 1.543 + } else { 1.544 + s->rbr = buf[0]; 1.545 + s->lsr |= UART_LSR_DR; 1.546 + } 1.547 + serial_update_irq(s); 1.548 } 1.549 1.550 static void serial_event(void *opaque, int event) 1.551 @@ -527,6 +695,7 @@ static void serial_save(QEMUFile *f, voi 1.552 qemu_put_8s(f,&s->lsr); 1.553 qemu_put_8s(f,&s->msr); 1.554 qemu_put_8s(f,&s->scr); 1.555 + qemu_get_8s(f,&s->fcr); 1.556 } 1.557 1.558 static int serial_load(QEMUFile *f, void *opaque, int version_id) 1.559 @@ -548,6 +717,7 @@ static int serial_load(QEMUFile *f, void 1.560 qemu_get_8s(f,&s->lsr); 1.561 qemu_get_8s(f,&s->msr); 1.562 qemu_get_8s(f,&s->scr); 1.563 + qemu_get_8s(f,&s->fcr); 1.564 1.565 return 0; 1.566 } 1.567 @@ -571,119 +741,26 @@ SerialState *serial_init(SetIRQFunc *set 1.568 s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS; 1.569 /* Default to 9600 baud, no parity, one stop bit */ 1.570 s->divider = 0x0C; 1.571 - s->char_transmit_time = ticks_per_sec * ( 9 / 9600 ); 1.572 + s->tsr_retry = 0; 1.573 + s->char_transmit_time = ( ticks_per_sec / 9600 ) * 9; 1.574 1.575 - s->write_retry_timer = qemu_new_timer(vm_clock, serial_chr_write, s); 1.576 - s->modem_status_poll = qemu_new_timer(vm_clock, serial_update_msl, s); 1.577 + s->modem_status_poll = qemu_new_timer(vm_clock, ( QEMUTimerCB *) serial_update_msl, s); 1.578 1.579 s->poll_msl = 0; 1.580 1.581 + fifo_clear(s,RECV_FIFO); 1.582 + fifo_clear(s,XMIT_FIFO); 1.583 + s->last_xmit_ts = qemu_get_clock(vm_clock); 1.584 + s->fifo_timeout_timer = qemu_new_timer(vm_clock, ( QEMUTimerCB *) fifo_timeout_int, s); 1.585 + s->fifo_transmit_timer = qemu_new_timer(vm_clock, ( QEMUTimerCB *) serial_xmit, s); 1.586 + 1.587 register_savevm("serial", base, 2, serial_save, serial_load, s); 1.588 1.589 register_ioport_write(base, 8, 1, serial_ioport_write, s); 1.590 register_ioport_read(base, 8, 1, serial_ioport_read, s); 1.591 s->chr = chr; 1.592 - qemu_chr_add_handlers(chr, serial_can_receive1, serial_receive1, 1.593 + qemu_chr_add_handlers(chr, serial_can_receive1, serial_receive1, 1.594 serial_event, s); 1.595 serial_update_msl(s); 1.596 - 1.597 return s; 1.598 } 1.599 - 1.600 -/* Memory mapped interface */ 1.601 -static uint32_t serial_mm_readb (void *opaque, target_phys_addr_t addr) 1.602 -{ 1.603 - SerialState *s = opaque; 1.604 - 1.605 - return serial_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFF; 1.606 -} 1.607 - 1.608 -static void serial_mm_writeb (void *opaque, 1.609 - target_phys_addr_t addr, uint32_t value) 1.610 -{ 1.611 - SerialState *s = opaque; 1.612 - 1.613 - serial_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFF); 1.614 -} 1.615 - 1.616 -static uint32_t serial_mm_readw (void *opaque, target_phys_addr_t addr) 1.617 -{ 1.618 - SerialState *s = opaque; 1.619 - 1.620 - return serial_ioport_read(s, (addr - s->base) >> s->it_shift) & 0xFFFF; 1.621 -} 1.622 - 1.623 -static void serial_mm_writew (void *opaque, 1.624 - target_phys_addr_t addr, uint32_t value) 1.625 -{ 1.626 - SerialState *s = opaque; 1.627 - 1.628 - serial_ioport_write(s, (addr - s->base) >> s->it_shift, value & 0xFFFF); 1.629 -} 1.630 - 1.631 -static uint32_t serial_mm_readl (void *opaque, target_phys_addr_t addr) 1.632 -{ 1.633 - SerialState *s = opaque; 1.634 - 1.635 - return serial_ioport_read(s, (addr - s->base) >> s->it_shift); 1.636 -} 1.637 - 1.638 -static void serial_mm_writel (void *opaque, 1.639 - target_phys_addr_t addr, uint32_t value) 1.640 -{ 1.641 - SerialState *s = opaque; 1.642 - 1.643 - serial_ioport_write(s, (addr - s->base) >> s->it_shift, value); 1.644 -} 1.645 - 1.646 -static CPUReadMemoryFunc *serial_mm_read[] = { 1.647 - &serial_mm_readb, 1.648 - &serial_mm_readw, 1.649 - &serial_mm_readl, 1.650 -}; 1.651 - 1.652 -static CPUWriteMemoryFunc *serial_mm_write[] = { 1.653 - &serial_mm_writeb, 1.654 - &serial_mm_writew, 1.655 - &serial_mm_writel, 1.656 -}; 1.657 - 1.658 -SerialState *serial_mm_init (SetIRQFunc *set_irq, void *opaque, 1.659 - target_ulong base, int it_shift, 1.660 - int irq, CharDriverState *chr) 1.661 -{ 1.662 - SerialState *s; 1.663 - int s_io_memory; 1.664 - 1.665 - s = qemu_mallocz(sizeof(SerialState)); 1.666 - if (!s) 1.667 - return NULL; 1.668 - s->set_irq = set_irq; 1.669 - s->irq_opaque = opaque; 1.670 - s->irq = irq; 1.671 - s->ier = 0; 1.672 - s->lsr = UART_LSR_TEMT | UART_LSR_THRE; 1.673 - s->iir = UART_IIR_NO_INT; 1.674 - s->mcr = UART_MCR_OUT2; 1.675 - s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS; 1.676 - /* Default to 9600 baud, no parity, one stop bit */ 1.677 - s->divider = 0x0C; 1.678 - s->char_transmit_time = ticks_per_sec * ( 9 / 9600 ); 1.679 - 1.680 - s->base = base; 1.681 - s->it_shift = it_shift; 1.682 - 1.683 - s->write_retry_timer = qemu_new_timer(vm_clock, serial_chr_write, s); 1.684 - s->modem_status_poll = qemu_new_timer(vm_clock, serial_update_msl, s); 1.685 - s->poll_msl = 0; 1.686 - 1.687 - register_savevm("serial", base, 2, serial_save, serial_load, s); 1.688 - 1.689 - s_io_memory = cpu_register_io_memory(0, serial_mm_read, 1.690 - serial_mm_write, s); 1.691 - cpu_register_physical_memory(base, 8 << it_shift, s_io_memory); 1.692 - s->chr = chr; 1.693 - qemu_chr_add_handlers(chr, serial_can_receive1, serial_receive1, 1.694 - serial_event, s); 1.695 - return s; 1.696 -}