Commit b2a5160c9f11cc5fe64230a6ec8f95e3aecfeacf

Authored by balrog
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) {
... ...