Commit b2a5160c9f11cc5fe64230a6ec8f95e3aecfeacf
1 parent
e41c0f26
Add serial loopback mode (patch from Hervé Poussineau).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3973 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
39 additions
and
8 deletions
hw/serial.c
| ... | ... | @@ -93,6 +93,8 @@ struct SerialState { |
| 93 | 93 | int it_shift; |
| 94 | 94 | }; |
| 95 | 95 | |
| 96 | +static void serial_receive_byte(SerialState *s, int ch); | |
| 97 | + | |
| 96 | 98 | static void serial_update_irq(SerialState *s) |
| 97 | 99 | { |
| 98 | 100 | if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) { |
| ... | ... | @@ -161,11 +163,18 @@ static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) |
| 161 | 163 | s->lsr &= ~UART_LSR_THRE; |
| 162 | 164 | serial_update_irq(s); |
| 163 | 165 | ch = val; |
| 164 | - qemu_chr_write(s->chr, &ch, 1); | |
| 166 | + if (!(s->mcr & UART_MCR_LOOP)) { | |
| 167 | + /* when not in loopback mode, send the char */ | |
| 168 | + qemu_chr_write(s->chr, &ch, 1); | |
| 169 | + } | |
| 165 | 170 | s->thr_ipending = 1; |
| 166 | 171 | s->lsr |= UART_LSR_THRE; |
| 167 | 172 | s->lsr |= UART_LSR_TEMT; |
| 168 | 173 | serial_update_irq(s); |
| 174 | + if (s->mcr & UART_MCR_LOOP) { | |
| 175 | + /* in loopback mode, say that we just received a char */ | |
| 176 | + serial_receive_byte(s, ch); | |
| 177 | + } | |
| 169 | 178 | } |
| 170 | 179 | break; |
| 171 | 180 | case 1: |
| ... | ... | @@ -223,7 +232,10 @@ static uint32_t serial_ioport_read(void *opaque, uint32_t addr) |
| 223 | 232 | ret = s->rbr; |
| 224 | 233 | s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); |
| 225 | 234 | serial_update_irq(s); |
| 226 | - qemu_chr_accept_input(s->chr); | |
| 235 | + if (!(s->mcr & UART_MCR_LOOP)) { | |
| 236 | + /* in loopback mode, don't receive any data */ | |
| 237 | + qemu_chr_accept_input(s->chr); | |
| 238 | + } | |
| 227 | 239 | } |
| 228 | 240 | break; |
| 229 | 241 | case 1: |
| ... | ... | @@ -346,6 +358,25 @@ static int serial_load(QEMUFile *f, void *opaque, int version_id) |
| 346 | 358 | return 0; |
| 347 | 359 | } |
| 348 | 360 | |
| 361 | +static void serial_reset(void *opaque) | |
| 362 | +{ | |
| 363 | + SerialState *s = opaque; | |
| 364 | + | |
| 365 | + s->divider = 0; | |
| 366 | + s->rbr = 0; | |
| 367 | + s->ier = 0; | |
| 368 | + s->iir = UART_IIR_NO_INT; | |
| 369 | + s->lcr = 0; | |
| 370 | + s->mcr = 0; | |
| 371 | + s->lsr = UART_LSR_TEMT | UART_LSR_THRE; | |
| 372 | + s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS; | |
| 373 | + s->scr = 0; | |
| 374 | + | |
| 375 | + s->thr_ipending = 0; | |
| 376 | + s->last_break_enable = 0; | |
| 377 | + qemu_irq_lower(s->irq); | |
| 378 | +} | |
| 379 | + | |
| 349 | 380 | /* If fd is zero, it means that the serial device uses the console */ |
| 350 | 381 | SerialState *serial_init(int base, qemu_irq irq, CharDriverState *chr) |
| 351 | 382 | { |
| ... | ... | @@ -355,9 +386,9 @@ SerialState *serial_init(int base, qemu_irq irq, CharDriverState *chr) |
| 355 | 386 | if (!s) |
| 356 | 387 | return NULL; |
| 357 | 388 | s->irq = irq; |
| 358 | - s->lsr = UART_LSR_TEMT | UART_LSR_THRE; | |
| 359 | - s->iir = UART_IIR_NO_INT; | |
| 360 | - s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS; | |
| 389 | + | |
| 390 | + qemu_register_reset(serial_reset, s); | |
| 391 | + serial_reset(s); | |
| 361 | 392 | |
| 362 | 393 | register_savevm("serial", base, 2, serial_save, serial_load, s); |
| 363 | 394 | |
| ... | ... | @@ -452,12 +483,12 @@ SerialState *serial_mm_init (target_phys_addr_t base, int it_shift, |
| 452 | 483 | if (!s) |
| 453 | 484 | return NULL; |
| 454 | 485 | s->irq = irq; |
| 455 | - s->lsr = UART_LSR_TEMT | UART_LSR_THRE; | |
| 456 | - s->iir = UART_IIR_NO_INT; | |
| 457 | - s->msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS; | |
| 458 | 486 | s->base = base; |
| 459 | 487 | s->it_shift = it_shift; |
| 460 | 488 | |
| 489 | + qemu_register_reset(serial_reset, s); | |
| 490 | + serial_reset(s); | |
| 491 | + | |
| 461 | 492 | register_savevm("serial", base, 2, serial_save, serial_load, s); |
| 462 | 493 | |
| 463 | 494 | if (ioregister) { | ... | ... |